From e999d535902fbe74a8417efaf687e628bc0f82d3 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:11:30 +0200 Subject: [PATCH 01/25] Bump to Arbor v0.9.0. --- src/gui_state.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui_state.cpp b/src/gui_state.cpp index 02391a0..119c584 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -736,8 +736,11 @@ namespace { } } } - std::sort(state_vars.begin(), state_vars.end()); - std::unique(state_vars.begin(), state_vars.end()); + { + std::sort(state_vars.begin(), state_vars.end()); + auto last = std::unique(state_vars.begin(), state_vars.end()); + state_vars.erase(last, state_vars.end()); + } for (const auto& locset: state.locsets) { with_id id{locset}; From 7f3f20fd07cf01a7b93e8a33aa20603c60af6d0c Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:11:30 +0200 Subject: [PATCH 02/25] Bump completed --- src/gui_state.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui_state.cpp b/src/gui_state.cpp index 02391a0..119c584 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -736,8 +736,11 @@ namespace { } } } - std::sort(state_vars.begin(), state_vars.end()); - std::unique(state_vars.begin(), state_vars.end()); + { + std::sort(state_vars.begin(), state_vars.end()); + auto last = std::unique(state_vars.begin(), state_vars.end()); + state_vars.erase(last, state_vars.end()); + } for (const auto& locset: state.locsets) { with_id id{locset}; From f23d9f38c178997088dfa8651349f634dedfe34e Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Fri, 2 Aug 2024 13:50:36 +0200 Subject: [PATCH 03/25] Bump to Arbor v0.9.0. complete --- src/gui_state.cpp | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/gui_state.cpp b/src/gui_state.cpp index 119c584..8c318c6 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -1,7 +1,6 @@ #include "gui_state.hpp" #include -#include #include #include @@ -390,8 +389,8 @@ namespace { state.renderer.render(vs, {mouse.x - win_pos.x, size.y + win_pos.y - mouse.y}); ImGui::Image(reinterpret_cast(state.renderer.cell.tex), size, ImVec2(0, 1), ImVec2(1, 0)); if (ImGui::IsItemHovered()) { - auto shft = ImGui::IsKeyDown(GLFW_KEY_LEFT_SHIFT) || ImGui::IsKeyDown(GLFW_KEY_RIGHT_SHIFT); - auto ctrl = ImGui::IsKeyDown(GLFW_KEY_LEFT_CONTROL) || ImGui::IsKeyDown(GLFW_KEY_RIGHT_CONTROL); + auto shft = ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift); + auto ctrl = ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl); if (shft || ctrl) { auto what = shft ? ImGuizmo::ROTATE : ImGuizmo::TRANSLATE; glm::vec3 shift = {vs.offset.x/vs.size.x, vs.offset.y/vs.size.y, 0.0f}; @@ -1083,33 +1082,33 @@ void gui_state::deserialize(const std::filesystem::path& fn) { return id; } - void operator()(const arb::init_membrane_potential& t) { state->parameter_defs[region].Vm = t.value; } - void operator()(const arb::axial_resistivity& t) { state->parameter_defs[region].RL = t.value; } - void operator()(const arb::temperature_K& t) { state->parameter_defs[region].TK = t.value; } - void operator()(const arb::membrane_capacitance& t) { state->parameter_defs[region].Cm = t.value; } + void operator()(const arb::init_membrane_potential& t) { state->parameter_defs[region].Vm = t.value.get_scalar(); } + void operator()(const arb::axial_resistivity& t) { state->parameter_defs[region].RL = t.value.get_scalar(); } + void operator()(const arb::temperature_K& t) { state->parameter_defs[region].TK = t.value.get_scalar(); } + void operator()(const arb::membrane_capacitance& t) { state->parameter_defs[region].Cm = t.value.get_scalar(); } void operator()(const arb::init_int_concentration& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].Xi = t.value; + state->ion_par_defs[{region, *ion}].Xi = t.value.get_scalar(); } void operator()(const arb::init_ext_concentration& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].Xo = t.value; + state->ion_par_defs[{region, *ion}].Xo = t.value.get_scalar(); } void operator()(const arb::init_reversal_potential& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].Er = t.value; + state->ion_par_defs[{region, *ion}].Er = t.value.get_scalar(); } void operator()(const arb::ion_diffusivity& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].D = t.value; + state->ion_par_defs[{region, *ion}].D = t.value.get_scalar(); } void operator()(const arb::scaled_mechanism& s) { auto id = make_density(s.t_mech); @@ -1120,20 +1119,7 @@ void gui_state::deserialize(const std::filesystem::path& fn) { } } void operator()(const arb::density& d) { make_density(d); } - }; - - struct df_visitor { - gui_state* state; - void operator()(const arb::init_membrane_potential& t) { log_error("Cannot handle this"); } - void operator()(const arb::axial_resistivity& t) { log_error("Cannot handle this"); } - void operator()(const arb::temperature_K& t) { log_error("Cannot handle this"); } - void operator()(const arb::membrane_capacitance& t) { log_error("Cannot handle this"); } - void operator()(const arb::init_int_concentration& t) { log_error("Cannot handle this"); } - void operator()(const arb::init_ext_concentration& t) { log_error("Cannot handle this"); } - void operator()(const arb::init_reversal_potential& t) { log_error("Cannot handle this"); } - void operator()(const arb::ion_reversal_potential_method& t) { log_error("Cannot handle this"); } - void operator()(const arb::ion_diffusivity& t) { log_error("Cannot handle this"); } - void operator()(const arb::cv_policy& t) { log_error("Cannot handle this"); } + void operator()(const arb::voltage_process& d) { log_error("Cannot handle this"); } }; struct acc_visitor { @@ -1482,8 +1468,7 @@ void gui_state::run_simulation() { t.values.push_back(*value); } sim.traces[t.id] = t; - }, - arb::sampling_policy::exact); + }); try { sm.run(sim.until, sim.dt); } catch (...) { From 13c6e8f759511dafab2e4b6c9815418695383461 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:08:16 +0200 Subject: [PATCH 04/25] Update to arbor/master (0.10.0) --- 3rd-party/ImGuizmo | 2 +- 3rd-party/arbor | 2 +- 3rd-party/fmt | 2 +- 3rd-party/glbinding | 2 +- 3rd-party/glfw | 2 +- 3rd-party/icons | 2 +- 3rd-party/imgui | 2 +- 3rd-party/implot | 2 +- 3rd-party/json | 2 +- 3rd-party/spdlog | 2 +- CMakeLists.txt | 5 ++- src/gui_state.cpp | 105 +++++++++++++++++++++++++------------------- src/loader.cpp | 26 ++++++++--- src/loader.hpp | 1 - src/recipe.hpp | 2 +- src/simulation.hpp | 9 +++- 16 files changed, 101 insertions(+), 67 deletions(-) diff --git a/3rd-party/ImGuizmo b/3rd-party/ImGuizmo index 664cf2d..ba662b1 160000 --- a/3rd-party/ImGuizmo +++ b/3rd-party/ImGuizmo @@ -1 +1 @@ -Subproject commit 664cf2d73864a36b2a8b5091d33fc4578c885eca +Subproject commit ba662b119d64f9ab700bb2cd7b2781f9044f5565 diff --git a/3rd-party/arbor b/3rd-party/arbor index 8e82ec1..9ff54f8 160000 --- a/3rd-party/arbor +++ b/3rd-party/arbor @@ -1 +1 @@ -Subproject commit 8e82ec1947a3a6d84452969d1d628b2292654319 +Subproject commit 9ff54f8e7c989203960da64779f9900aeb56a08b diff --git a/3rd-party/fmt b/3rd-party/fmt index c4ee726..0c9fce2 160000 --- a/3rd-party/fmt +++ b/3rd-party/fmt @@ -1 +1 @@ -Subproject commit c4ee726532178e556d923372f29163bd206d7732 +Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592 diff --git a/3rd-party/glbinding b/3rd-party/glbinding index 21729a0..ff2ff7a 160000 --- a/3rd-party/glbinding +++ b/3rd-party/glbinding @@ -1 +1 @@ -Subproject commit 21729a0f5e6f64565d708f6221d436662c467325 +Subproject commit ff2ff7a7aad77b907a67bd5962d6e11a4f9c699e diff --git a/3rd-party/glfw b/3rd-party/glfw index 7482de6..7b6aead 160000 --- a/3rd-party/glfw +++ b/3rd-party/glfw @@ -1 +1 @@ -Subproject commit 7482de6071d21db77a7236155da44c172a7f6c9e +Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579 diff --git a/3rd-party/icons b/3rd-party/icons index 7d6ff1f..f30b1e7 160000 --- a/3rd-party/icons +++ b/3rd-party/icons @@ -1 +1 @@ -Subproject commit 7d6ff1f4ba51e7a2b142be39457768abece1549c +Subproject commit f30b1e73b2d71eb331d77619c3f1de34199afc38 diff --git a/3rd-party/imgui b/3rd-party/imgui index 8cbd391..139e99c 160000 --- a/3rd-party/imgui +++ b/3rd-party/imgui @@ -1 +1 @@ -Subproject commit 8cbd391f096b9314a08670052cc0025cbcadb249 +Subproject commit 139e99ca37a3e127c87690202faec005cd892d36 diff --git a/3rd-party/implot b/3rd-party/implot index b47c8ba..18c7243 160000 --- a/3rd-party/implot +++ b/3rd-party/implot @@ -1 +1 @@ -Subproject commit b47c8bacdbc78bc521691f70666f13924bb522ab +Subproject commit 18c72431f8265e2b0b5378a3a73d8a883b2175ff diff --git a/3rd-party/json b/3rd-party/json index 69d7448..9cca280 160000 --- a/3rd-party/json +++ b/3rd-party/json @@ -1 +1 @@ -Subproject commit 69d744867f8847c91a126fa25e9a6a3d67b3be41 +Subproject commit 9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03 diff --git a/3rd-party/spdlog b/3rd-party/spdlog index 76fb40d..27cb4c7 160000 --- a/3rd-party/spdlog +++ b/3rd-party/spdlog @@ -1 +1 @@ -Subproject commit 76fb40d95455f249bd70824ecfcae7a8f0930fa3 +Subproject commit 27cb4c76708608465c413f6d0e6b8d99a4d84302 diff --git a/CMakeLists.txt b/CMakeLists.txt index d238a21..41aa5b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,11 @@ cmake_minimum_required(VERSION 3.19) find_package(Git) project(the-arbor-gui - VERSION 0.8.1 + VERSION 0.10.1 LANGUAGES C CXX) +set(EXPORT_COMPILE_COMMANDS ON) + set(CMAKE_CXX_STANDARD 20) include(GNUInstallDirs) @@ -141,6 +143,7 @@ target_include_directories(imgui PRIVATE 3rd-party/imgui) target_include_directories(imgui PUBLIC 3rd-party/implot) target_include_directories(imgui PUBLIC 3rd-party/ImGuizmo/) target_link_libraries(imgui PRIVATE glfw) +target_compile_definitions(arbor-gui-deps INTERFACE SPDLOG_FMT_EXTERNAL) # Get commit hashes from git and inject into config execute_process(COMMAND ${GIT_EXECUTABLE} -C ${PROJECT_SOURCE_DIR} describe --always --dirty --abbrev=0 diff --git a/src/gui_state.cpp b/src/gui_state.cpp index 8c318c6..67b3630 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "gui.hpp" #include "utils.hpp" @@ -36,6 +37,7 @@ extern float delta_zoom; extern glm::vec2 mouse; using namespace std::literals; +namespace U = arb::units; namespace { inline void gui_read_morphology(gui_state& state, bool& open); @@ -852,20 +854,22 @@ namespace { i_clamp.frequency = item.frequency; i_clamp.phase = item.phase; std::sort(item.envelope.begin(), item.envelope.end()); - for (const auto& [t, i]: item.envelope) i_clamp.envelope.emplace_back(arb::i_clamp::envelope_point{t, i}); + for (const auto& [t, i]: item.envelope) { + i_clamp.envelope.emplace_back(arb::i_clamp::envelope_point{t * U::ms , i * U::nA }); + } decor.place(locset, i_clamp, item.tag); } for (const auto child: state.detectors.get_children(id)) { auto item = state.detectors[child]; - decor.place(locset, arb::threshold_detector{item.threshold}, item.tag); + decor.place(locset, arb::threshold_detector{item.threshold * U::mV}, item.tag); } } auto param = state.parameter_defaults; - if (param.RL) decor.set_default(arb::axial_resistivity{param.RL.value()}); - if (param.Cm) decor.set_default(arb::membrane_capacitance{param.Cm.value()}); - if (param.TK) decor.set_default(arb::temperature_K{param.TK.value()}); - if (param.Vm) decor.set_default(arb::init_membrane_potential{param.Vm.value()}); + if (param.RL) decor.set_default(arb::axial_resistivity{param.RL.value() * U::Ohm * U::cm}); + if (param.Cm) decor.set_default(arb::membrane_capacitance{param.Cm.value() * U::F / U::m2}); + if (param.TK) decor.set_default(arb::temperature{param.TK.value() * U::Kelvin }); + if (param.Vm) decor.set_default(arb::init_membrane_potential{param.Vm.value() * U::mV}); for (const auto& ion: state.ions) { const auto& data = state.ion_defaults[ion]; @@ -878,13 +882,13 @@ namespace { if (state.presets.ion_data.contains(name)) { auto p = state.presets.ion_data.at(name); - decor.set_default(arb::init_int_concentration{name, data.Xi.value_or(p.init_int_concentration.value())}); - decor.set_default(arb::init_ext_concentration{name, data.Xo.value_or(p.init_ext_concentration.value())}); - decor.set_default(arb::init_reversal_potential{name, data.Er.value_or(p.init_reversal_potential.value())}); + decor.set_default(arb::init_int_concentration{name, data.Xi.value_or(p.init_int_concentration.value()) * U::mM}); + decor.set_default(arb::init_ext_concentration{name, data.Xo.value_or(p.init_ext_concentration.value()) * U::mM}); + decor.set_default(arb::init_reversal_potential{name, data.Er.value_or(p.init_reversal_potential.value())* U::mV}); } else { - decor.set_default(arb::init_int_concentration{name, data.Xi.value()}); - decor.set_default(arb::init_ext_concentration{name, data.Xo.value()}); - decor.set_default(arb::init_reversal_potential{name, data.Er.value()}); + decor.set_default(arb::init_int_concentration{name, data.Xi.value() * U::mM}); + decor.set_default(arb::init_ext_concentration{name, data.Xo.value() * U::mM}); + decor.set_default(arb::init_reversal_potential{name, data.Er.value() * U::mV}); } } @@ -892,17 +896,17 @@ namespace { auto rg = state.region_defs[id]; if (!rg.data) continue; auto param = state.parameter_defs[id]; - if (param.RL) decor.paint(rg.data.value(), arb::axial_resistivity{param.RL.value()}); - if (param.Cm) decor.paint(rg.data.value(), arb::membrane_capacitance{param.Cm.value()}); - if (param.TK) decor.paint(rg.data.value(), arb::temperature_K{param.TK.value()}); - if (param.Vm) decor.paint(rg.data.value(), arb::init_membrane_potential{param.Vm.value()}); + if (param.RL) decor.paint(rg.data.value(), arb::axial_resistivity{param.RL.value() * U::Ohm * U::cm}); + if (param.Cm) decor.paint(rg.data.value(), arb::membrane_capacitance{param.Cm.value() * U::F / U::m2}); + if (param.TK) decor.paint(rg.data.value(), arb::temperature{param.TK.value() * U::Kelvin}); + if (param.Vm) decor.paint(rg.data.value(), arb::init_membrane_potential{param.Vm.value() * U::mV}); for (const auto& ion: state.ions) { const auto& data = state.ion_par_defs[{id, ion}]; const auto& name = state.ion_defs[ion].name; - if (data.Xi) decor.paint(rg.data.value(), arb::init_int_concentration{name, data.Xi.value()}); - if (data.Xo) decor.paint(rg.data.value(), arb::init_ext_concentration{name, data.Xo.value()}); - if (data.Er) decor.paint(rg.data.value(), arb::init_reversal_potential{name, data.Er.value()}); + if (data.Xi) decor.paint(rg.data.value(), arb::init_int_concentration{name, data.Xi.value() * U::mM}); + if (data.Xo) decor.paint(rg.data.value(), arb::init_ext_concentration{name, data.Xo.value() * U::mM}); + if (data.Er) decor.paint(rg.data.value(), arb::init_reversal_potential{name, data.Er.value() * U::mV}); } for (const auto child: state.mechanisms.get_children(id)) { @@ -940,7 +944,7 @@ namespace { if (ImGui::BeginChild("TracePlot", {-180.0f, 0.0f})) { if (to_plot) { auto probe = to_plot.value(); - auto trace = state.sim.traces.at(probe); + auto trace = state.sim.traces.at(probe.value); const auto& [lo, hi] = std::accumulate(trace.values.begin(), trace.values.end(), std::make_pair(std::numeric_limits::max(), std::numeric_limits::min()), @@ -1014,9 +1018,9 @@ void gui_state::deserialize(const std::filesystem::path& fn) { struct ls_visitor { gui_state* state; id_type locset; - std::string tag; + arb::hash_type tag; - ls_visitor(gui_state* s, const arb::locset& l, const std::string& t): state{s}, tag{t} { + ls_visitor(gui_state* s, const arb::locset& l, const arb::hash_type& t): state{s}, tag{t} { auto ls = to_string(l); auto res = std::find_if(state->locsets.begin(), state->locsets.end(), [&](const auto& id) { @@ -1082,33 +1086,33 @@ void gui_state::deserialize(const std::filesystem::path& fn) { return id; } - void operator()(const arb::init_membrane_potential& t) { state->parameter_defs[region].Vm = t.value.get_scalar(); } - void operator()(const arb::axial_resistivity& t) { state->parameter_defs[region].RL = t.value.get_scalar(); } - void operator()(const arb::temperature_K& t) { state->parameter_defs[region].TK = t.value.get_scalar(); } - void operator()(const arb::membrane_capacitance& t) { state->parameter_defs[region].Cm = t.value.get_scalar(); } + void operator()(const arb::init_membrane_potential& t) { state->parameter_defs[region].Vm = t.value; } + void operator()(const arb::axial_resistivity& t) { state->parameter_defs[region].RL = t.value; } + void operator()(const arb::temperature& t) { state->parameter_defs[region].TK = t.value; } + void operator()(const arb::membrane_capacitance& t) { state->parameter_defs[region].Cm = t.value; } void operator()(const arb::init_int_concentration& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].Xi = t.value.get_scalar(); + state->ion_par_defs[{region, *ion}].Xi = t.value; } void operator()(const arb::init_ext_concentration& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].Xo = t.value.get_scalar(); + state->ion_par_defs[{region, *ion}].Xo = t.value; } void operator()(const arb::init_reversal_potential& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].Er = t.value.get_scalar(); + state->ion_par_defs[{region, *ion}].Er = t.value; } void operator()(const arb::ion_diffusivity& t) { auto ion = std::find_if(state->ions.begin(), state->ions.end(), [&](const auto& id) { return state->ion_defs[id].name == t.ion; }); if (ion == state->ions.end()) log_error("Unknown ion"); - state->ion_par_defs[{region, *ion}].D = t.value.get_scalar(); + state->ion_par_defs[{region, *ion}].D = t.value; } void operator()(const arb::scaled_mechanism& s) { auto id = make_density(s.t_mech); @@ -1426,15 +1430,15 @@ void gui_state::run_simulation() { auto p = presets.ion_data.at(name); prop.add_ion(name, data.charge, - def.Xi.value_or(p.init_int_concentration.value()), - def.Xo.value_or(p.init_ext_concentration.value()), - def.Er.value_or(p.init_reversal_potential.value())); + def.Xi.value_or(p.init_int_concentration.value()) * U::mM, + def.Xo.value_or(p.init_ext_concentration.value()) * U::mM, + def.Er.value_or(p.init_reversal_potential.value())* U::mV); } else { prop.add_ion(name, data.charge, - def.Xi.value(), - def.Xo.value(), - def.Er.value()); + def.Xi.value() * U::mM, + def.Xo.value() * U::mM, + def.Er.value() * U::mV); } } auto rec = make_recipe(prop, cell); @@ -1444,33 +1448,42 @@ void gui_state::run_simulation() { const auto& where = locset_defs[ls]; if (!where.data) continue; auto loc = where.data.value(); + // TODO this is quite crude... + auto tag = std::to_string(pb.value); if (data.kind == "Voltage") { - rec.probes.emplace_back(arb::cable_probe_membrane_voltage{loc}, pb.value); + rec.probes.emplace_back(arb::cable_probe_membrane_voltage{loc}, tag); } else if (data.kind == "Axial Current") { - rec.probes.emplace_back(arb::cable_probe_axial_current{loc}, pb.value); + rec.probes.emplace_back(arb::cable_probe_axial_current{loc}, tag); } else if (data.kind == "Membrane Current") { - rec.probes.emplace_back(arb::cable_probe_total_ion_current_density{loc}, pb.value); + rec.probes.emplace_back(arb::cable_probe_total_ion_current_density{loc}, tag); } // TODO Finish } } // Make simulation - auto sm = arb::simulation(rec); + auto sm = arb::simulation(rec); sim.traces.clear(); + sim.tag_to_id.clear(); sm.add_sampler(arb::all_probes, - arb::regular_schedule(this->sim.dt), - [&](arb::probe_metadata pm, std::size_t n, const arb::sample_record* samples) { - auto loc = arb::util::any_cast(pm.meta); - trace t{(size_t)pm.tag, pm.index, loc->pos, loc->branch, {}, {}}; + arb::regular_schedule(this->sim.dt * U::ms), + [&](const arb::probe_metadata pm, std::size_t n, const arb::sample_record* samples) { + auto loc = arb::util::any_cast(pm.meta); + auto tag = pm.id.tag; + if (sim.tag_to_id.count(tag) == 0) { + id_type id = {sim.traces.size()}; + sim.tag_to_id[tag] = id; + sim.traces.emplace_back(tag, id, pm.index, loc->pos, loc->branch); + } + auto id = sim.tag_to_id[tag]; + auto& t = sim.traces.at(id.value); for (std::size_t i = 0; i(samples[i].data); t.times.push_back(samples[i].time); t.values.push_back(*value); } - sim.traces[t.id] = t; }); try { - sm.run(sim.until, sim.dt); + sm.run(sim.until * U::ms, sim.dt * U::ms); } catch (...) { ImGui::OpenPopup("Error"); } diff --git a/src/loader.cpp b/src/loader.cpp index d25a97f..06e6c31 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -14,6 +14,7 @@ namespace io { loaded_morphology load_swc(const std::filesystem::path &fn, std::function &)> swc_to_morph) { + return { swc_to_morph(arborio::parse_swc(slurp(fn)).records()), {{"soma", "(tag 1)"}, {"axon", "(tag 2)"}, @@ -22,8 +23,21 @@ loaded_morphology load_swc(const std::filesystem::path &fn, {}}; } -loaded_morphology load_neuron_swc(const std::filesystem::path &fn) { return load_swc(fn, arborio::load_swc_neuron); } -loaded_morphology load_arbor_swc(const std::filesystem::path &fn) { return load_swc(fn, arborio::load_swc_arbor); } +loaded_morphology load_neuron_swc(const std::filesystem::path &fn) { + auto loaded = arborio::load_swc_neuron(fn); + loaded_morphology res{.morph=loaded.morphology}; + for (const auto& [k, v]: loaded.labels.regions()) res.regions.emplace_back(k, to_string(v)); + for (const auto& [k, v]: loaded.labels.locsets()) res.locsets.emplace_back(k, to_string(v)); + return res; +} + +loaded_morphology load_arbor_swc(const std::filesystem::path &fn) { + auto loaded = arborio::load_swc_arbor(fn); + loaded_morphology res{.morph=loaded.morphology}; + for (const auto& [k, v]: loaded.labels.regions()) res.regions.emplace_back(k, to_string(v)); + for (const auto& [k, v]: loaded.labels.locsets()) res.locsets.emplace_back(k, to_string(v)); + return res; +} loaded_morphology load_neuroml_morph(const std::filesystem::path &fn) { arborio::neuroml nml(slurp(fn)); @@ -33,8 +47,8 @@ loaded_morphology load_neuroml_morph(const std::filesystem::path &fn) { if (!morph_data) log_error("Invalid morphology id {} in NML file."); auto morph = morph_data.value(); loaded_morphology result{.morph=morph.morphology}; - for (const auto& [k, v]: morph.groups.regions()) result.regions.emplace_back(k, to_string(v)); - for (const auto& [k, v]: morph.groups.locsets()) result.locsets.emplace_back(k, to_string(v)); + for (const auto& [k, v]: morph.labels.regions()) result.regions.emplace_back(k, to_string(v)); + for (const auto& [k, v]: morph.labels.locsets()) result.locsets.emplace_back(k, to_string(v)); return result; } @@ -46,8 +60,8 @@ loaded_morphology load_neuroml_cell(const std::filesystem::path &fn) { if (!morph_data) log_error("Invalid cell id {} in NML file."); auto morph = morph_data.value(); loaded_morphology result{.morph=morph.morphology}; - for (const auto& [k, v]: morph.groups.regions()) result.regions.emplace_back(k, to_string(v)); - for (const auto& [k, v]: morph.groups.locsets()) result.locsets.emplace_back(k, to_string(v)); + for (const auto& [k, v]: morph.labels.regions()) result.regions.emplace_back(k, to_string(v)); + for (const auto& [k, v]: morph.labels.locsets()) result.locsets.emplace_back(k, to_string(v)); return result; } diff --git a/src/loader.hpp b/src/loader.hpp index 2784cd8..3384804 100644 --- a/src/loader.hpp +++ b/src/loader.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/src/recipe.hpp b/src/recipe.hpp index b2455f2..6d8af70 100644 --- a/src/recipe.hpp +++ b/src/recipe.hpp @@ -22,7 +22,7 @@ struct recipe: arb::recipe { std::any get_global_properties(arb::cell_kind) const override { return properties; } }; - +inline recipe make_recipe(const arb::cable_cell_global_properties& properties, const arb::cable_cell& cell) { recipe result; diff --git a/src/simulation.hpp b/src/simulation.hpp index 9ce4330..718e2e5 100644 --- a/src/simulation.hpp +++ b/src/simulation.hpp @@ -5,9 +5,9 @@ #include #include "id.hpp" -#include "utils.hpp" struct trace { + std::string tag; id_type id; size_t index; double location; @@ -15,6 +15,10 @@ struct trace { bool show = true; std::vector times; std::vector values; + + trace(const std::string t, const id_type i, size_t x, const double l, const size_t b): + tag{std::move(t)}, id{i}, index{x}, location{l}, branch{b} + {} }; @@ -25,7 +29,8 @@ struct simulation { bool should_run = false; bool show_trace = false; - std::unordered_map traces; + std::unordered_map tag_to_id; + std::vector traces; }; void gui_sim(simulation&); From 6de3292c0c04a9670a49a3fc85554fc1751a3041 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:48:05 +0200 Subject: [PATCH 05/25] Wayland. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 26acc69..1de72c0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,7 +42,7 @@ jobs: - name: Update apt run: sudo apt update - name: Install missing packages - run: sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev + run: sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev libwayland-bin libwayland-dev libxkbcommon-dev xorg-dev - name: Check config run: | $CC --version From 60f5506e0d6156d5c367703c0b61672f6d24324a Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:57:14 +0200 Subject: [PATCH 06/25] Arch? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1de72c0..efb9af4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: $CC --version $CXX --version - name: Configure - run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=x86-64-v2 + run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=x86-64 - name: Build run: cmake --build $bld_dir -j 2 - name: Install From 2affca169c333a1d3aa35235a313abbcb12da83d Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:09:32 +0200 Subject: [PATCH 07/25] ? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index efb9af4..5e816a3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: $CC --version $CXX --version - name: Configure - run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=x86-64 + run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=k8 - name: Build run: cmake --build $bld_dir -j 2 - name: Install From d7e67d90158315bff1d01426a94596642c1bbf8a Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:21:12 +0200 Subject: [PATCH 08/25] Test? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5e816a3..1de72c0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: $CC --version $CXX --version - name: Configure - run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=k8 + run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=x86-64-v2 - name: Build run: cmake --build $bld_dir -j 2 - name: Install From fda2246889a5cc4f12078f197a3a0df6f632c720 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:04:00 +0200 Subject: [PATCH 09/25] Bump OS and compiler. --- .github/workflows/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1de72c0..dd89dbf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,15 +17,15 @@ jobs: config: - { name: "Ubuntu Low (AppImage)", - os: "ubuntu-20.04", - cc: "gcc-10", - cxx: "g++-10" + os: "ubuntu-22.04", + cc: "gcc-11", + cxx: "g++-11" } - { name: "Ubuntu High", - os: "ubuntu-22.04", - cc: "clang-14", - cxx: "clang++-14" + os: "ubuntu-24.04", + cc: "clang-18", + cxx: "clang++-18" } fail-fast: false env: From 84a66cfac3ebb8677f08aa9449bc9a6d124e8761 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:58:15 +0200 Subject: [PATCH 10/25] haswell? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dd89dbf..e55c2cd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: $CC --version $CXX --version - name: Configure - run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=x86-64-v2 + run: cmake -S . -B $bld_dir -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC --install-prefix $app_dir/usr -DARB_ARCH=haswell - name: Build run: cmake --build $bld_dir -j 2 - name: Install From 5badbbecf935d3665866db00c4895d27c88036a6 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:13:07 +0200 Subject: [PATCH 11/25] FUSE? --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e55c2cd..d37a31c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,7 +42,7 @@ jobs: - name: Update apt run: sudo apt update - name: Install missing packages - run: sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev libwayland-bin libwayland-dev libxkbcommon-dev xorg-dev + run: sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglu1-mesa-dev freeglut3-dev libfuse2 mesa-common-dev libwayland-bin libwayland-dev libxkbcommon-dev xorg-dev - name: Check config run: | $CC --version From 5d1dd22d48dd374bfe4e5838c99658873edb56d1 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:19:43 +0200 Subject: [PATCH 12/25] CVE. --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1a5ef47..3da403a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -97,7 +97,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "Get artifacts" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Move and rename appimage run: mv */*.AppImage arbor-gui.AppImage - name: Move and rename dmg @@ -122,4 +122,3 @@ jobs: generateReleaseNotes: true artifacts: '*.dmg,*.AppImage,*.tar.gz' token: ${{ secrets.GITHUB_TOKEN }} - \ No newline at end of file From 4281517a5151821cb4349e1f45a0feb3154ed2c8 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:21:05 +0100 Subject: [PATCH 13/25] Get ready for v0.11 --- 3rd-party/arbor | 2 +- 3rd-party/fmt | 2 +- 3rd-party/glfw | 2 +- 3rd-party/glm | 2 +- 3rd-party/imgui | 2 +- 3rd-party/spdlog | 2 +- CMakeLists.txt | 2 +- data/ball_and_stick.swc | 6 +- .../normal-soma-normal-dend.swc | 8 + .../single-soma-normal-dend.swc | 7 + .../single-soma-single-dend.swc | 6 + src/geometry.cpp | 3 + src/gui_state.cpp | 405 +++++++++--------- src/loader.cpp | 3 +- src/utils.cpp | 2 +- src/window.cpp | 8 +- 16 files changed, 244 insertions(+), 218 deletions(-) create mode 100644 data/swc-interpretation/normal-soma-normal-dend.swc create mode 100644 data/swc-interpretation/single-soma-normal-dend.swc create mode 100644 data/swc-interpretation/single-soma-single-dend.swc diff --git a/3rd-party/arbor b/3rd-party/arbor index 9ff54f8..c4ff08c 160000 --- a/3rd-party/arbor +++ b/3rd-party/arbor @@ -1 +1 @@ -Subproject commit 9ff54f8e7c989203960da64779f9900aeb56a08b +Subproject commit c4ff08ceef2760796538c4117a259fd2104442ed diff --git a/3rd-party/fmt b/3rd-party/fmt index 0c9fce2..1239137 160000 --- a/3rd-party/fmt +++ b/3rd-party/fmt @@ -1 +1 @@ -Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592 +Subproject commit 123913715afeb8a437e6388b4473fcc4753e1c9a diff --git a/3rd-party/glfw b/3rd-party/glfw index 7b6aead..e7ea71b 160000 --- a/3rd-party/glfw +++ b/3rd-party/glfw @@ -1 +1 @@ -Subproject commit 7b6aead9fb88b3623e3b3725ebb42670cbe4c579 +Subproject commit e7ea71be039836da3a98cea55ae5569cb5eb885c diff --git a/3rd-party/glm b/3rd-party/glm index bf71a83..0af55cc 160000 --- a/3rd-party/glm +++ b/3rd-party/glm @@ -1 +1 @@ -Subproject commit bf71a834948186f4097caa076cd2663c69a10e1e +Subproject commit 0af55ccecd98d4e5a8d1fad7de25ba429d60e863 diff --git a/3rd-party/imgui b/3rd-party/imgui index 139e99c..11b3a7c 160000 --- a/3rd-party/imgui +++ b/3rd-party/imgui @@ -1 +1 @@ -Subproject commit 139e99ca37a3e127c87690202faec005cd892d36 +Subproject commit 11b3a7c8ca23201294464c7f368614a9106af2a1 diff --git a/3rd-party/spdlog b/3rd-party/spdlog index 27cb4c7..f355b3d 160000 --- a/3rd-party/spdlog +++ b/3rd-party/spdlog @@ -1 +1 @@ -Subproject commit 27cb4c76708608465c413f6d0e6b8d99a4d84302 +Subproject commit f355b3d58f7067eee1706ff3c801c2361011f3d5 diff --git a/CMakeLists.txt b/CMakeLists.txt index 41aa5b2..6539ddc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.27) find_package(Git) diff --git a/data/ball_and_stick.swc b/data/ball_and_stick.swc index c223837..89c99da 100644 --- a/data/ball_and_stick.swc +++ b/data/ball_and_stick.swc @@ -1,2 +1,4 @@ -1 1 -3.0 0.0 0.0 3 -1 -2 1 3.0 0.0 0.0 3 1 +# SWC format: ID, Type, X, Y, Z, Radius, Parent +1 1 0.0 0.0 0.0 10.0 -1 # Soma +2 3 0.0 0.0 10.0 1.0 1 # Dendrite +3 3 0.0 0.0 20.0 1.0 2 # Dendrite diff --git a/data/swc-interpretation/normal-soma-normal-dend.swc b/data/swc-interpretation/normal-soma-normal-dend.swc new file mode 100644 index 0000000..7f4e908 --- /dev/null +++ b/data/swc-interpretation/normal-soma-normal-dend.swc @@ -0,0 +1,8 @@ +# id, tag, x, y, z, radius, parent +1 1 -3.0 0.0 0.0 3.0 -1 +2 1 -3.0 0.0 3.0 3.0 1 +3 3 -3.0 -6.0 0.0 3.0 1 +4 3 -3.0 -9.0 0.0 3.0 3 +5 2 -3.0 6.0 0.0 3.0 1 +6 2 -3.0 12.0 0.0 3.0 5 +7 2 -3.0 18.0 0.0 3.0 6 diff --git a/data/swc-interpretation/single-soma-normal-dend.swc b/data/swc-interpretation/single-soma-normal-dend.swc new file mode 100644 index 0000000..ce42adf --- /dev/null +++ b/data/swc-interpretation/single-soma-normal-dend.swc @@ -0,0 +1,7 @@ +# id, tag, x, y, z, radius, parent +1 1 -3.0 0.0 0.0 3.0 -1 +2 3 -3.0 -6.0 0.0 3.0 1 +3 3 -3.0 -9.0 0.0 3.0 2 +4 2 -3.0 6.0 0.0 3.0 1 +5 2 -3.0 12.0 0.0 3.0 4 +6 2 -3.0 18.0 0.0 3.0 5 diff --git a/data/swc-interpretation/single-soma-single-dend.swc b/data/swc-interpretation/single-soma-single-dend.swc new file mode 100644 index 0000000..e9f7b86 --- /dev/null +++ b/data/swc-interpretation/single-soma-single-dend.swc @@ -0,0 +1,6 @@ +# id, tag, x, y, z, radius, parent +1 1 -3.0 0.0 0.0 3.0 -1 +2 3 -3.0 -6.0 0.0 3.0 1 +3 2 -3.0 6.0 0.0 3.0 1 +4 2 -3.0 12.0 0.0 3.0 3 +5 2 -3.0 18.0 0.0 3.0 4 diff --git a/src/geometry.cpp b/src/geometry.cpp index 373c377..9424461 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -699,12 +699,14 @@ void geometry::load_geometry(const arb::morphology& morph, bool reset) { branch_to_ids[branch].emplace_back(lo, hi); } } + log_info("Loaded {} segments and {} branches", segments.size(), morph.num_branches()); log_info("Making geometry"); if (segments.empty()) { log_info("Empty geometry"); return; } + root = {(float) segments[0].prox.x, (float) segments[0].prox.y, (float) segments[0].prox.z}; log_debug("New root x={} y={} z={}", root.x, root.y, root.z); { @@ -724,6 +726,7 @@ void geometry::load_geometry(const arb::morphology& morph, bool reset) { } log_debug("Frustra generated: {} ({} points)", indices.size()/n_indices, vertices.size()); + { // Re-scale into [-1, 1]^3 box rescale = ax.scale; diff --git a/src/gui_state.cpp b/src/gui_state.cpp index 67b3630..0207c89 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -128,16 +128,14 @@ namespace { loader_error.clear(); ImGui::CloseCurrentPopup(); } - ImGui::EndPopup(); - } + } // load error if (ko) open = false; ImGui::EndPopup(); - } + } // Load } inline void gui_read_cat(gui_state& state, bool& open) { - with_id id{"loading cat"}; ImGui::OpenPopup("Load"); static std::vector suffixes{".so"}; @@ -250,7 +248,6 @@ namespace { } inline void gui_main(gui_state& state) { - static bool opt_fullscreen = true; static bool opt_padding = false; static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; @@ -297,7 +294,7 @@ namespace { ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); } gui_menu_bar(state); - ImGui::End(); + ImGui::End(); // dockspace } inline void gui_read_morphology(gui_state& state, bool& open_file) { @@ -376,174 +373,183 @@ namespace { inline bool gui_axes(axes& ax) { ImGui::Text("%s Axes", icon_axes); gui_right_margin(); - gui_toggle(icon_on, icon_off, ax.active); + gui_toggle(fmt::format("{}##{}", icon_on, "ax").c_str(), fmt::format("{}##{}", icon_off, "ax").c_str(), ax.active); auto mv = ImGui::InputFloat3("Position", &ax.origin[0]); auto sz = ImGui::InputFloat("Size", &ax.scale, 0, 0, "%f µm"); return mv || sz; } - inline void gui_cell(gui_state& state) { - if (ImGui::Begin("Cell")) { - ImGui::BeginChild("Cell Render"); - auto size = ImGui::GetWindowSize(), win_pos = ImGui::GetWindowPos(); - auto& vs = state.view; - vs.size = to_glmvec(size); - state.renderer.render(vs, {mouse.x - win_pos.x, size.y + win_pos.y - mouse.y}); - ImGui::Image(reinterpret_cast(state.renderer.cell.tex), size, ImVec2(0, 1), ImVec2(1, 0)); - if (ImGui::IsItemHovered()) { - auto shft = ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift); - auto ctrl = ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl); - if (shft || ctrl) { - auto what = shft ? ImGuizmo::ROTATE : ImGuizmo::TRANSLATE; - glm::vec3 shift = {vs.offset.x/vs.size.x, vs.offset.y/vs.size.y, 0.0f}; - glm::mat4 V = glm::lookAt(vs.camera, vs.target/state.renderer.rescale + shift, vs.up); - glm::mat4 P = glm::perspective(glm::radians(vs.zoom), vs.size.x/vs.size.y, 0.1f, 100.0f); - ImGuizmo::SetDrawlist(); - ImGuizmo::SetRect(win_pos.x, win_pos.y, size.x, size.y); - ImGuizmo::Manipulate(glm::value_ptr(V), glm::value_ptr(P), what, ImGuizmo::LOCAL, glm::value_ptr(vs.rotate)); - } else { - vs.zoom = std::clamp(vs.zoom + delta_zoom, 1.0f, 45.0f); - } - } - - static float t_last = 0.0; - float t_now = glfwGetTime(); - if (state.demo_mode) vs.rotate = glm::rotate(vs.rotate, state.auto_omega*(t_now - t_last), glm::vec3{0.0f, 1.0f, 0.0f}); - t_last = t_now; - - state.object = state.renderer.get_id(); - - if (ImGui::BeginPopupContextWindow()) { - ImGui::Text("%s Camera", icon_camera); + inline void gui_cell_context_menu(gui_state& state) { + if (ImGui::BeginPopupContextWindow()) { + ImGui::Text("%s Camera", icon_camera); + { + with_indent indent{}; + ImGui::SliderFloat("Auto-rotate", &state.auto_omega, 0.1f, 2.0f); + gui_right_margin(); + gui_toggle(icon_on, icon_off, state.demo_mode); + ImGui::InputFloat3("Target", &state.view.target[0]); + ImGui::ColorEdit3("Background",& (state.renderer.cell.clear_color.x), ImGuiColorEditFlags_NoInputs); { - with_indent indent{}; - ImGui::SliderFloat("Auto-rotate", &state.auto_omega, 0.1f, 2.0f); - gui_right_margin(); - gui_toggle(icon_on, icon_off, state.demo_mode); - ImGui::InputFloat3("Target", &state.view.target[0]); - ImGui::ColorEdit3("Background",& (state.renderer.cell.clear_color.x), ImGuiColorEditFlags_NoInputs); - { - ImGui::SameLine(); - if (ImGui::BeginCombo("Colormap", state.renderer.cmap.c_str())) { - with_item_width iw(80.0f); - for (const auto& [k, v]: state.renderer.cmaps) { - if (ImGui::Selectable(k.c_str(), k == state.renderer.cmap)) state.renderer.cmap = k; - } - ImGui::EndCombo(); + ImGui::SameLine(); + if (ImGui::BeginCombo("Colormap", state.renderer.cmap.c_str())) { + with_item_width iw(80.0f); + for (const auto& [k, v]: state.renderer.cmaps) { + if (ImGui::Selectable(k.c_str(), k == state.renderer.cmap)) state.renderer.cmap = k; } + ImGui::EndCombo(); } - if (ImGui::BeginMenu(fmt::format("{} Snap", icon_locset).c_str())) { - for (const auto& id: state.locsets) { - const auto& ls = state.locset_defs[id]; - if (ls.state != def_state::good) continue; - if (ImGui::BeginMenu(fmt::format("{} {}", icon_locset, ls.name).c_str())) { - auto points = state.builder.make_points(ls.data.value()); - for (const auto& point: points) { - const auto lbl = fmt::format("({: 7.3f} {: 7.3f} {: 7.3f})", point.x, point.y, point.z); - if (ImGui::MenuItem(lbl.c_str())) { - state.view.offset = {0.0, 0.0}; - state.view.target = point; - } + } + if (ImGui::BeginMenu(fmt::format("{} Snap", icon_locset).c_str())) { + for (const auto& id: state.locsets) { + const auto& ls = state.locset_defs[id]; + if (ls.state != def_state::good) continue; + if (ImGui::BeginMenu(fmt::format("{} {}", icon_locset, ls.name).c_str())) { + auto points = state.builder.make_points(ls.data.value()); + for (const auto& point: points) { + const auto lbl = fmt::format("({: 7.3f} {: 7.3f} {: 7.3f})", point.x, point.y, point.z); + if (ImGui::MenuItem(lbl.c_str())) { + state.view.offset = {0.0, 0.0}; + state.view.target = point; } - ImGui::EndMenu(); } + ImGui::EndMenu(); } - ImGui::EndMenu(); - } - if (gui_menu_item("Reset##camera", icon_refresh)) { - state.view.offset = {0.0f, 0.0f}; - state.view.rotate = glm::mat4(1.0f); - state.view.target = {0.0f, 0.0f, 0.0f}; - state.renderer.cell.clear_color = {214.0f/255, 214.0f/255, 214.0f/255}; } + ImGui::EndMenu(); } - ImGui::Separator(); - if(gui_axes(state.renderer.ax)) state.renderer.make_ruler(); - ImGui::Separator(); - ImGui::Text("%s Model", icon_cell); - { - with_indent indent{}; - int tmp = state.renderer.n_faces; - if (ImGui::DragInt("Frustrum Resolution", &tmp, 1.0f, 8, 64, "%d", ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_AlwaysClamp)) { - state.renderer.n_faces = tmp; - state.renderer.load_geometry(state.builder.morph); - for (const auto& rg: state.regions) state.update_region(rg); - for (const auto& ls: state.locsets) state.update_locset(ls); - } + if (gui_menu_item("Reset##camera", icon_refresh)) { + state.view.offset = {0.0f, 0.0f}; + state.view.rotate = glm::mat4(1.0f); + state.view.target = {0.0f, 0.0f, 0.0f}; + state.renderer.cell.clear_color = {214.0f/255, 214.0f/255, 214.0f/255}; } - ImGui::Separator(); - if (gui_menu_item("Snapshot", icon_paint)) state.store_snapshot(); - ImGui::InputText("Output",& state.snapshot_path); - ImGui::EndPopup(); } - ImGui::EndChild(); + ImGui::Separator(); + if(gui_axes(state.renderer.ax)) state.renderer.make_ruler(); + ImGui::Separator(); + ImGui::Text("%s Model", icon_cell); + { + with_indent indent{}; + int tmp = state.renderer.n_faces; + if (ImGui::DragInt("Frustrum Resolution", &tmp, 1.0f, 8, 64, "%d", ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_AlwaysClamp)) { + state.renderer.n_faces = tmp; + state.renderer.load_geometry(state.builder.morph); + for (const auto& rg: state.regions) state.update_region(rg); + for (const auto& ls: state.locsets) state.update_locset(ls); + } + } + ImGui::Separator(); + if (gui_menu_item("Snapshot", icon_paint)) state.store_snapshot(); + ImGui::InputText("Output",& state.snapshot_path); + ImGui::EndPopup(); } - ImGui::End(); } - inline void gui_cell_info(gui_state& state) { - if (ImGui::Begin(fmt::format("{} Morphology##info", icon_branch).c_str())) { - if (state.object) { - auto& object = state.object.value(); - ImGui::BulletText("Segment %u", object.data.id); - { - with_indent indent; - auto - px = object.data.prox.x, dx = object.data.dist.x, lx = dx - px, - py = object.data.prox.y, dy = object.data.dist.y, ly = dy - py, - pz = object.data.prox.z, dz = object.data.dist.z, lz = dz - pz; - ImGui::BulletText("Extent (%.1f, %.1f, %.1f) -- (%.1f, %.1f, %.1f)", px, py, pz, dx, dy, dz); - ImGui::BulletText("Radii %g µm %g µm", object.data.prox.radius, object.data.dist.radius); - ImGui::BulletText("Length %g µm", std::sqrt(lx*lx + ly*ly + lz*lz)); - } - ImGui::BulletText("Branch %zu", object.branch); - { - with_indent indent; - ImGui::BulletText("Segments"); - auto count = 0ul; - for (const auto& [lo, hi]: *object.segment_ids) { - ImGui::SameLine(); - if (lo == hi) { - ImGui::Text("%zu", lo); - } else { - ImGui::Text("%zu-%zu", lo, hi); - } - count += hi - lo + 1; + inline void gui_cell(gui_state& state) { + if (ImGui::Begin("Cell")) { + if (ImGui::BeginChild("Cell Render")) { + auto size = ImGui::GetWindowSize(), win_pos = ImGui::GetWindowPos(); + auto& vs = state.view; + vs.size = to_glmvec(size); + state.renderer.render(vs, {mouse.x - win_pos.x, size.y + win_pos.y - mouse.y}); + ImGui::Image(static_cast(state.renderer.cell.tex), size, ImVec2(0, 1), ImVec2(1, 0)); + if (ImGui::IsItemHovered()) { + auto shft = ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift); + auto ctrl = ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl); + if (shft || ctrl) { + auto what = shft ? ImGuizmo::ROTATE : ImGuizmo::TRANSLATE; + glm::vec3 shift = {vs.offset.x/vs.size.x, vs.offset.y/vs.size.y, 0.0f}; + glm::mat4 V = glm::lookAt(vs.camera, vs.target/state.renderer.rescale + shift, vs.up); + glm::mat4 P = glm::perspective(glm::radians(vs.zoom), vs.size.x/vs.size.y, 0.1f, 100.0f); + ImGuizmo::SetDrawlist(); + ImGuizmo::SetRect(win_pos.x, win_pos.y, size.x, size.y); + ImGuizmo::Manipulate(glm::value_ptr(V), glm::value_ptr(P), what, ImGuizmo::LOCAL, glm::value_ptr(vs.rotate)); + } + else { + vs.zoom = std::clamp(vs.zoom + delta_zoom, 1.0f, 45.0f); } - ImGui::BulletText("Count %zu", count); } - } - ImGui::End(); + + // + static float t_last = 0.0; + float t_now = glfwGetTime(); + if (state.demo_mode) vs.rotate = glm::rotate(vs.rotate, state.auto_omega*(t_now - t_last), glm::vec3{0.0f, 1.0f, 0.0f}); + t_last = t_now; + + state.object = state.renderer.get_id(); + } // cell render + ImGui::EndChild(); + } // cell + ImGui::End(); + } + + inline void gui_morph_info(gui_state& state) { + auto& object = state.object.value(); + ImGui::BulletText("Segment %u", object.data.id); + { + with_indent indent; + auto + px = object.data.prox.x, dx = object.data.dist.x, lx = dx - px, + py = object.data.prox.y, dy = object.data.dist.y, ly = dy - py, + pz = object.data.prox.z, dz = object.data.dist.z, lz = dz - pz; + ImGui::BulletText("Extent (%.1f, %.1f, %.1f) -- (%.1f, %.1f, %.1f)", px, py, pz, dx, dy, dz); + ImGui::BulletText("Radii %g µm %g µm", object.data.prox.radius, object.data.dist.radius); + ImGui::BulletText("Length %g µm", std::sqrt(lx*lx + ly*ly + lz*lz)); } - if (ImGui::Begin(fmt::format("{} Locations##info", icon_location).c_str())) { - if (state.object) { - auto& object = state.object.value(); - ImGui::BulletText("IExprs"); - { - with_indent indent; - for (const auto& iex: state.iexpr_defs.items) { - if (iex.state == def_state::good) { - auto& info = iex.info; - const auto& [pv, dv] = info.values.at(object.data.id); - ImGui::BulletText("%s: %f -- %f", iex.name.c_str(), pv, dv); - } - } + ImGui::BulletText("Branch %zu", object.branch); + { + with_indent indent; + ImGui::BulletText("Segments"); + auto count = 0ul; + for (const auto& [lo, hi]: *object.segment_ids) { + ImGui::SameLine(); + if (lo == hi) { + ImGui::Text("%zu", lo); + } else { + ImGui::Text("%zu-%zu", lo, hi); } - ImGui::BulletText("Regions"); - { - with_indent indent; - for (const auto& region: state.segment_to_regions[object.data.id]) { - ImGui::ColorButton("", to_imvec(state.renderer.regions[region].color)); - ImGui::SameLine(); - ImGui::AlignTextToFramePadding(); - ImGui::Text("%s", state.region_defs[region].name.c_str()); - } + count += hi - lo + 1; + } + ImGui::BulletText("Count %zu", count); + } + } + + inline void gui_loc_info(gui_state& state) { + auto& object = state.object.value(); + ImGui::BulletText("IExprs"); + { + with_indent indent; + for (const auto& iex: state.iexpr_defs.items) { + if (iex.state == def_state::good) { + auto& info = iex.info; + const auto& [pv, dv] = info.values.at(object.data.id); + ImGui::BulletText("%s: %f -- %f", iex.name.c_str(), pv, dv); } } - ImGui::End(); + } + ImGui::BulletText("Regions"); + { + with_indent indent; + for (const auto& region: state.segment_to_regions[object.data.id]) { + ImGui::ColorButton("", to_imvec(state.renderer.regions[region].color)); + ImGui::SameLine(); + ImGui::AlignTextToFramePadding(); + ImGui::Text("%s", state.region_defs[region].name.c_str()); + } } } + inline void gui_cell_info(gui_state& state) { + if (ImGui::Begin(fmt::format("{} Morphology##info", icon_branch).c_str())) { + if (state.object) gui_morph_info(state); + } + ImGui::End(); + if (ImGui::Begin(fmt::format("{} Locations##info", icon_location).c_str())) { + if (state.object) gui_loc_info(state); + } + ImGui::End(); + } + template inline void gui_locdefs(const std::string& name, entity& ids, @@ -551,7 +557,6 @@ namespace { component_unique& renderables, event_queue& events, bool show_color=true) { - with_id guard{name}; auto from = -1, to = -1; auto open = gui_tree_add(name, [&](){ events.emplace_back(evt_add_locdef{}); }); @@ -636,7 +641,7 @@ namespace { ImGui::Separator(); gui_locdefs(fmt::format("{} Inhomogeneous", icon_iexpr), state.iexprs, state.iexpr_defs, state.renderer.iexprs, state.events, false); } - ImGui::End(); + ImGui::End(); // locations } inline void gui_ion_settings(gui_state& state) { @@ -656,7 +661,6 @@ namespace { } inline void gui_ion_defaults(gui_state& state) { - with_id guard{"ion-defaults"}; auto open = gui_tree_add(fmt::format("{} Default", icon_default), [&]() { state.add_ion(); }); if (open) { @@ -686,7 +690,6 @@ namespace { } inline void gui_parameters(gui_state& state) { - with_id id{"parameters"}; if (ImGui::Begin(fmt::format("{} Parameters", icon_list).c_str())) { if (gui_tree(fmt::format("{} Cable Cell Properties", icon_sliders))) { @@ -716,7 +719,7 @@ namespace { } ImGui::Separator(); gui_mechanisms(state); - } + } // parameter ImGui::End(); } @@ -779,13 +782,11 @@ namespace { inline void gui_debug(bool& open) { ImGui::ShowMetricsWindow(&open); } inline void gui_style(bool& open) { - if (ImGui::Begin("Style", &open)) ImGui::ShowStyleEditor(); ImGui::End(); } inline void gui_about(bool& open) { - if (ImGui::Begin("About", &open)) { ImGui::Text("Version: %s", gui_git_commit); ImGui::Text("Webpage: %s", gui_web_page); @@ -794,15 +795,12 @@ namespace { ImGui::End(); } - inline void gui_demo(bool& open) { - if (ImGui::Begin("Demo", &open)) ImGui::ShowDemoWindow(); ImGui::End(); } inline void gui_stimuli(gui_state& state) { - std::vector values(state.sim.until/state.sim.dt, 0.0f); if (gui_tree(fmt::format("{} Stimuli", icon_stimulus))) { for (const auto& locset: state.locsets) { @@ -824,7 +822,6 @@ namespace { if (ImGui::Begin(fmt::format("{} Simulation", icon_sim).c_str())) { ImGui::Separator(); gui_sim(state.sim); - ImGui::Separator(); gui_cv_policy(state.cv_policy_def, state.renderer.cv_boundaries, state.events); ImGui::Separator(); @@ -938,53 +935,60 @@ namespace { return {state.builder.morph, decor, state.builder.labels}; } - void gui_traces(gui_state& state) { - static std::optional to_plot; - if (ImGui::Begin("Traces")) { - if (ImGui::BeginChild("TracePlot", {-180.0f, 0.0f})) { - if (to_plot) { - auto probe = to_plot.value(); - auto trace = state.sim.traces.at(probe.value); - const auto& [lo, hi] = std::accumulate(trace.values.begin(), - trace.values.end(), - std::make_pair(std::numeric_limits::max(), std::numeric_limits::min()), - [] (const auto& p, auto x) -> std::pair { return { std::min(x, p.first), std::max(x, p.second)};}); - auto probe_def = state.probes[probe]; - auto var = fmt::format("{} {}", probe_def.kind, probe_def.variable); - - if (ImPlot::BeginPlot(fmt::format("Probe {} @ branch {} ({})", probe.value, trace.branch, trace.location).c_str(), - ImVec2(-1, -20))) { - ImPlot::SetupAxes("Time (t/ms)", var.c_str()); - ImPlot::SetupAxesLimits(0, state.sim.until, lo, hi); - ImPlot::SetupFinish(); - ImPlot::PlotLine(var.c_str(), trace.times.data(), trace.values.data(), trace.values.size()); - ImPlot::EndPlot(); - } - } else { - if (ImPlot::BeginPlot("Please select a probe below")) { - ImPlot::EndPlot(); - } + inline void gui_plot(gui_state& state, std::optional to_plot) { + if (ImGui::BeginChild("TracePlot", {-180.0f, 0.0f})) { + if (to_plot) { + auto probe = to_plot.value(); + auto trace = state.sim.traces.at(probe.value); + const auto& [lo, hi] = std::accumulate(trace.values.begin(), + trace.values.end(), + std::make_pair(std::numeric_limits::max(), std::numeric_limits::min()), + [] (const auto& p, auto x) -> std::pair { return { std::min(x, p.first), std::max(x, p.second)};}); + auto probe_def = state.probes[probe]; + auto var = fmt::format("{} {}", probe_def.kind, probe_def.variable); + + if (ImPlot::BeginPlot(fmt::format("Probe {} @ branch {} ({})", probe.value, trace.branch, trace.location).c_str(), + ImVec2(-1, -20))) { + ImPlot::SetupAxes("Time (t/ms)", var.c_str()); + ImPlot::SetupAxesLimits(0, state.sim.until, lo, hi); + ImPlot::SetupFinish(); + ImPlot::PlotLine(var.c_str(), trace.times.data(), trace.values.data(), trace.values.size()); + ImPlot::EndPlot(); + } + } else { + if (ImPlot::BeginPlot("Please select a probe below")) { + ImPlot::EndPlot(); } } - ImGui::EndChild(); - ImGui::SameLine(); - if (ImGui::BeginChild("TraceSelect", {150.0f, 0.0f})) { - for (const auto& locset: state.locsets) { - with_id id{locset}; - auto locset_def = state.locset_defs[locset]; - if (gui_tree(fmt::format("{} {}", icon_locset, locset_def.name))) { - for (const auto& probe: state.probes.get_children(locset)) { - const auto& data = state.probes[probe]; - if(ImGui::RadioButton(fmt::format("{} {}: {} {}", icon_probe, probe.value, data.kind, data.variable).c_str(), - to_plot && (to_plot.value() == probe))) { - to_plot = probe; - } + } + ImGui::EndChild(); + } + + inline void gui_trace_select(gui_state& state, std::optional to_plot) { + if (ImGui::BeginChild("TraceSelect", {150.0f, 0.0f})) { + for (const auto& locset: state.locsets) { + with_id id{locset}; + auto locset_def = state.locset_defs[locset]; + if (gui_tree(fmt::format("{} {}", icon_locset, locset_def.name))) { + for (const auto& probe: state.probes.get_children(locset)) { + const auto& data = state.probes[probe]; + if(ImGui::RadioButton(fmt::format("{} {}: {} {}", icon_probe, probe.value, data.kind, data.variable).c_str(), + to_plot && (to_plot.value() == probe))) { + to_plot = probe; } - ImGui::TreePop(); } + ImGui::TreePop(); } } - ImGui::EndChild(); + } + ImGui::EndChild(); + } + + void gui_traces(gui_state& state) { + static std::optional to_plot; + if (ImGui::Begin("Traces")) { + gui_plot(state, to_plot); + ImGui::SameLine(); } ImGui::End(); } @@ -1418,7 +1422,7 @@ void gui_state::run_simulation() { if (parameter_defaults.Vm) prop.default_parameters.init_membrane_potential = parameter_defaults.Vm; auto cat = arb::mechanism_catalogue{}; - for (const auto& [k, v]: catalogues) cat.import(v, k + "::"); + for (const auto& [k, v]: catalogues) cat.extend(v, k + "::"); prop.catalogue = cat; for (const auto& ion: ions) { @@ -1490,5 +1494,6 @@ void gui_state::run_simulation() { if (ImGui::BeginPopupModal("Error")) { ImGui::Text("Arbor failed to run."); if (ImGui::Button("OK")) ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); } } diff --git a/src/loader.cpp b/src/loader.cpp index 06e6c31..fc38a62 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -28,6 +27,7 @@ loaded_morphology load_neuron_swc(const std::filesystem::path &fn) { loaded_morphology res{.morph=loaded.morphology}; for (const auto& [k, v]: loaded.labels.regions()) res.regions.emplace_back(k, to_string(v)); for (const auto& [k, v]: loaded.labels.locsets()) res.locsets.emplace_back(k, to_string(v)); + log_info("Loaded SWC (Neuron) {} branches {} ", loaded.segment_tree.size(), loaded.morphology.num_branches()); return res; } @@ -36,6 +36,7 @@ loaded_morphology load_arbor_swc(const std::filesystem::path &fn) { loaded_morphology res{.morph=loaded.morphology}; for (const auto& [k, v]: loaded.labels.regions()) res.regions.emplace_back(k, to_string(v)); for (const auto& [k, v]: loaded.labels.locsets()) res.locsets.emplace_back(k, to_string(v)); + log_info("Loaded SWC (Arbor) {} branches {} ", loaded.segment_tree.size(), loaded.morphology.num_branches()); return res; } diff --git a/src/utils.cpp b/src/utils.cpp index 634d138..8b6f3fc 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -29,7 +29,7 @@ std::filesystem::path get_resource_path(const std::filesystem::path& fn) { } void log_init() { - spdlog::set_level(spdlog::level::warn); + spdlog::set_level(spdlog::level::info); } diff --git a/src/window.cpp b/src/window.cpp index 797d818..0bc73a2 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -59,14 +59,8 @@ Window::Window() { ImPlot::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - // Enable keyboard navigation + // Enable keyboard navigation and docking io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - // Update key mapping - { - #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } - MAP_KEY(ImGuiNavInput_Activate, GLFW_KEY_SPACE); - #undef MAP_KEY - } io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; if (!(io.ConfigFlags & ImGuiConfigFlags_DockingEnable)) log_error("ImGui docking disabled"); From 297cd2e4b38c859259a6bf322d0d0afbea2e5a2a Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Mon, 10 Mar 2025 15:05:37 +0100 Subject: [PATCH 14/25] Fix ini, add last case to swc-inter --- CMakeLists.txt | 2 +- .../normal-soma-single-dend.swc | 7 +++ .../single-soma-single-dend.swc | 2 +- default.ini | 45 ++++++++++--------- src/gui_state.cpp | 2 +- 5 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 data/swc-interpretation/normal-soma-single-dend.swc diff --git a/CMakeLists.txt b/CMakeLists.txt index 6539ddc..22bade5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.27) find_package(Git) project(the-arbor-gui - VERSION 0.10.1 + VERSION 0.11.1 LANGUAGES C CXX) set(EXPORT_COMPILE_COMMANDS ON) diff --git a/data/swc-interpretation/normal-soma-single-dend.swc b/data/swc-interpretation/normal-soma-single-dend.swc new file mode 100644 index 0000000..5f03a98 --- /dev/null +++ b/data/swc-interpretation/normal-soma-single-dend.swc @@ -0,0 +1,7 @@ +# id, tag, x, y, z, radius, parent +1 1 -3.0 0.0 0.0 3.0 -1 +2 1 3.0 0.0 0.0 3.0 1 +3 3 -3.0 -6.0 0.0 3.0 1 +4 2 -3.0 6.0 0.0 3.0 1 +5 2 -3.0 12.0 0.0 3.0 4 +6 2 -3.0 18.0 0.0 3.0 5 diff --git a/data/swc-interpretation/single-soma-single-dend.swc b/data/swc-interpretation/single-soma-single-dend.swc index e9f7b86..e1c7835 100644 --- a/data/swc-interpretation/single-soma-single-dend.swc +++ b/data/swc-interpretation/single-soma-single-dend.swc @@ -1,5 +1,5 @@ # id, tag, x, y, z, radius, parent -1 1 -3.0 0.0 0.0 3.0 -1 +1 1 -3.0 0.0 0.0 3.0 -1 2 3 -3.0 -6.0 0.0 3.0 1 3 2 -3.0 6.0 0.0 3.0 1 4 2 -3.0 12.0 0.0 3.0 3 diff --git a/default.ini b/default.ini index 60f7193..e4bb40a 100644 --- a/default.ini +++ b/default.ini @@ -10,43 +10,43 @@ Collapsed=0 [Window][ Locations] Pos=0,24 -Size=339,696 +Size=338,696 Collapsed=0 DockId=0x00000001,0 [Window][Cell] -Pos=341,24 -Size=939,559 +Pos=340,24 +Size=940,559 Collapsed=0 -DockId=0x00000003,0 +DockId=0x00000002,0 [Window][Traces] -Pos=341,24 -Size=939,559 +Pos=340,24 +Size=940,559 Collapsed=0 -DockId=0x00000003,1 +DockId=0x00000002,1 [Window][ Morphology##info] -Pos=341,585 -Size=480,135 +Pos=340,585 +Size=603,135 Collapsed=0 -DockId=0x00000005,0 +DockId=0x00000004,0 [Window][ Locations##info] -Pos=823,585 -Size=457,135 +Pos=945,585 +Size=335,135 Collapsed=0 -DockId=0x00000006,0 +DockId=0x00000005,0 [Window][ Parameters] Pos=0,24 -Size=339,696 +Size=338,696 Collapsed=0 DockId=0x00000001,1 [Window][ Simulation] Pos=0,24 -Size=339,696 +Size=338,696 Collapsed=0 DockId=0x00000001,2 @@ -66,11 +66,12 @@ Size=758,446 Collapsed=0 [Docking][Data] -DockSpace ID=0x3BC79352 Window=0x4647B76E Pos=0,24 Size=1280,696 Split=X Selected=0xBF700C0A - DockNode ID=0x00000001 Parent=0x3BC79352 SizeRef=339,696 CentralNode=1 Selected=0xBF700C0A - DockNode ID=0x00000002 Parent=0x3BC79352 SizeRef=939,696 Split=Y Selected=0x90C8F40C - DockNode ID=0x00000003 Parent=0x00000002 SizeRef=939,559 Selected=0x65F68FF8 - DockNode ID=0x00000004 Parent=0x00000002 SizeRef=939,135 Split=X Selected=0xAB9526FD - DockNode ID=0x00000005 Parent=0x00000004 SizeRef=480,135 Selected=0x93CAA630 - DockNode ID=0x00000006 Parent=0x00000004 SizeRef=457,135 Selected=0xAB9526FD +DockSpace ID=0x3BC79352 Pos=0,24 Size=1280,696 CentralNode=1 Selected=0xBF700C0A +DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=0,24 Size=1280,696 Split=X Selected=0x9FA67BE9 + DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=338,696 Selected=0xBB245857 + DockNode ID=0x00000006 Parent=0xC0DFADC4 SizeRef=940,696 Split=Y + DockNode ID=0x00000002 Parent=0x00000006 SizeRef=1280,559 CentralNode=1 Selected=0x47506C1A + DockNode ID=0x00000003 Parent=0x00000006 SizeRef=1280,135 Split=X Selected=0x29E5A105 + DockNode ID=0x00000004 Parent=0x00000003 SizeRef=821,135 Selected=0x29E5A105 + DockNode ID=0x00000005 Parent=0x00000003 SizeRef=457,135 Selected=0x655FAFBA diff --git a/src/gui_state.cpp b/src/gui_state.cpp index 0207c89..ac92881 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -289,7 +289,7 @@ namespace { // DockSpace ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags& ImGuiConfigFlags_DockingEnable) { + if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); } From 763166acd242182a38c21bdcb186caa5eebac58b Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Mon, 10 Mar 2025 15:20:14 +0100 Subject: [PATCH 15/25] Bump CI --- .github/workflows/main.yml | 14 +++++++------- .github/workflows/release.yml | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d37a31c..afe290f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,9 +17,9 @@ jobs: config: - { name: "Ubuntu Low (AppImage)", - os: "ubuntu-22.04", - cc: "gcc-11", - cxx: "g++-11" + os: "ubuntu-24.04", + cc: "gcc-14", + cxx: "g++-14" } - { name: "Ubuntu High", @@ -35,7 +35,7 @@ jobs: bld_dir: build_dir steps: - name: "Clone w/ submodules" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: "recursive" @@ -66,7 +66,7 @@ jobs: - name: Delete Linuxdeploy if: ${{ startsWith(matrix.config.cc, 'gcc') }} run: rm -f ./linuxdeploy-x86_64.AppImage - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: ${{ startsWith(matrix.config.cc, 'gcc') }} with: name: linux appimage @@ -94,7 +94,7 @@ jobs: CXX: ${{ matrix.config.cxx }} steps: - name: "Clone w/ submodules" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: "recursive" @@ -108,7 +108,7 @@ jobs: run: cmake --build build -j 2 --target package - name: Upload .dmg if: ${{ matrix.config.os == 'macos-11' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: apple dmg path: build/*.dmg diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3da403a..d925a32 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,9 +14,9 @@ jobs: config: - { name: "Ubuntu", - os: "ubuntu-20.04", - cc: "gcc-10", - cxx: "g++-10" + os: "ubuntu-22.04", + cc: "gcc-12", + cxx: "g++-12" } fail-fast: false env: @@ -26,7 +26,7 @@ jobs: bld_dir: build_dir steps: - name: "Clone w/ submodules" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: "recursive" @@ -52,7 +52,7 @@ jobs: run: ./linuxdeploy-x86_64.AppImage --appdir="$app_dir" --output=appimage - name: Delete Linuxdeploy run: rm -f ./linuxdeploy-x86_64.AppImage - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: linux appimage path: './*.AppImage*' @@ -64,7 +64,7 @@ jobs: config: - { name: "MacOS", - os: "macos-11", + os: "macos-12", cc: "clang", cxx: "clang++" } @@ -73,7 +73,7 @@ jobs: CXX: ${{ matrix.config.cxx }} steps: - name: "Clone w/ submodules" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: "recursive" @@ -86,7 +86,7 @@ jobs: - name: Build run: cmake --build build -j 2 --target package - name: Upload .dmg - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: apple dmg path: build/*.dmg @@ -103,7 +103,7 @@ jobs: - name: Move and rename dmg run: mv */*.dmg arbor-gui.dmg - name: "Clone w/ submodules" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: "recursive" From a00efce80811d94217e70dc2decc665e905f39b4 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Wed, 12 Mar 2025 10:03:46 +0100 Subject: [PATCH 16/25] Bump clang --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index afe290f..3477cd9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,13 +16,13 @@ jobs: matrix: config: - { - name: "Ubuntu Low (AppImage)", + name: "Ubuntu GCC", os: "ubuntu-24.04", cc: "gcc-14", cxx: "g++-14" } - { - name: "Ubuntu High", + name: "Ubuntu Clang", os: "ubuntu-24.04", cc: "clang-18", cxx: "clang++-18" From ee2d55f043cea4ff00cf166be20f4f41f32ba790 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Wed, 12 Mar 2025 14:15:35 +0100 Subject: [PATCH 17/25] LTO? --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22bade5..adcd2e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project(the-arbor-gui LANGUAGES C CXX) set(EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF CACHE BOOL "" FORCE) set(CMAKE_CXX_STANDARD 20) include(GNUInstallDirs) From 2103e5b79a066ccb8111ecc6839edfda26f44ab1 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Thu, 24 Apr 2025 21:48:50 +0200 Subject: [PATCH 18/25] Bump dependencies --- 3rd-party/arbor | 2 +- 3rd-party/glbinding | 2 +- 3rd-party/json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/3rd-party/arbor b/3rd-party/arbor index c4ff08c..bf234aa 160000 --- a/3rd-party/arbor +++ b/3rd-party/arbor @@ -1 +1 @@ -Subproject commit c4ff08ceef2760796538c4117a259fd2104442ed +Subproject commit bf234aa82f497258d1f330ff9311d92463f1929a diff --git a/3rd-party/glbinding b/3rd-party/glbinding index ff2ff7a..c8a66c9 160000 --- a/3rd-party/glbinding +++ b/3rd-party/glbinding @@ -1 +1 @@ -Subproject commit ff2ff7a7aad77b907a67bd5962d6e11a4f9c699e +Subproject commit c8a66c92e8a81d82e384a4c80207913519c1f17e diff --git a/3rd-party/json b/3rd-party/json index 9cca280..55f9368 160000 --- a/3rd-party/json +++ b/3rd-party/json @@ -1 +1 @@ -Subproject commit 9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03 +Subproject commit 55f93686c01528224f448c19128836e7df245f72 From 2bd099f5f190a5943c927576b81ddc4d9ff196f8 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Thu, 24 Apr 2025 21:57:44 +0200 Subject: [PATCH 19/25] ditch old Macos --- .github/workflows/main.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3477cd9..5a11358 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -78,14 +78,20 @@ jobs: matrix: config: - { - name: "MacOS Low (DiskIm)", - os: "macos-11", + name: "MacOS XIII", + os: "macos-13", cc: "clang", cxx: "clang++" } - { - name: "MacOS High", - os: "macos-12", + name: "MacOS XIV", + os: "macos-14", + cc: "clang", + cxx: "clang++" + } + - { + name: "MacOS XV", + os: "macos-15", cc: "clang", cxx: "clang++" } @@ -106,9 +112,3 @@ jobs: run: cmake -S . -B build -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC -DARBORGUI_BUILD_BUNDLE=ON - name: Build run: cmake --build build -j 2 --target package - - name: Upload .dmg - if: ${{ matrix.config.os == 'macos-11' }} - uses: actions/upload-artifact@v4 - with: - name: apple dmg - path: build/*.dmg From cba92759da49e3f9fb67b9aad6ad45b2a01fd66a Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Thu, 24 Apr 2025 22:46:02 +0200 Subject: [PATCH 20/25] upload dmg --- .github/workflows/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5a11358..2bec887 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -112,3 +112,7 @@ jobs: run: cmake -S . -B build -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_COMPILER=$CC -DARBORGUI_BUILD_BUNDLE=ON - name: Build run: cmake --build build -j 2 --target package + - uses: actions/upload-artifact@v4 + with: + name: disk image + path: build/*.dmg From f04440ede397b21f14d2587072088cb1f024ab48 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Thu, 24 Apr 2025 22:56:39 +0200 Subject: [PATCH 21/25] avoid conflict --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2bec887..12aeaab 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -114,5 +114,5 @@ jobs: run: cmake --build build -j 2 --target package - uses: actions/upload-artifact@v4 with: - name: disk image + name: arbor-gui-${{ matrix.os }} path: build/*.dmg From 01580f248fbd385795467daeb3eb769ef9e1836a Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Fri, 25 Apr 2025 07:31:56 +0200 Subject: [PATCH 22/25] avoid conflict even harder --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 12aeaab..dd5dc4d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -114,5 +114,5 @@ jobs: run: cmake --build build -j 2 --target package - uses: actions/upload-artifact@v4 with: - name: arbor-gui-${{ matrix.os }} + name: arbor-gui-${{ matrix.config.os }} path: build/*.dmg From 4e8ae0f583992f1fb4985ad59fb6da7993b305ac Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Fri, 25 Apr 2025 07:51:04 +0200 Subject: [PATCH 23/25] Give up on MacOS 13 --- .github/workflows/main.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dd5dc4d..e0d5bf1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,12 +77,6 @@ jobs: strategy: matrix: config: - - { - name: "MacOS XIII", - os: "macos-13", - cc: "clang", - cxx: "clang++" - } - { name: "MacOS XIV", os: "macos-14", From d4d63af1ddf9a94eff9e62d3bfb210da75c9c70d Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Fri, 25 Apr 2025 21:32:41 +0200 Subject: [PATCH 24/25] Fix bugs in the MacOS bundle. --- CMakeLists.txt | 59 ++++++++++++++++++++++++++++++---------- default.ini => imgui.ini | 0 src/utils.cpp | 2 +- 3 files changed, 46 insertions(+), 15 deletions(-) rename default.ini => imgui.ini (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index adcd2e3..dfe8396 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.27) find_package(Git) project(the-arbor-gui - VERSION 0.11.1 + VERSION 0.11.2 LANGUAGES C CXX) set(EXPORT_COMPILE_COMMANDS ON) @@ -186,22 +186,53 @@ if(ARBORGUI_BUILD_BUNDLE) set(ARBORGUI_ICON arbor.icns) set(ARBORGUI_ICON_PATH ${CMAKE_SOURCE_DIR}/images/${ARBORGUI_ICON}) - set_source_files_properties(${ARBORGUI_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - add_executable(arbor-gui MACOSX_BUNDLE ${ARBORGUI_ICON_PATH} ${gui_srcs} $) - set_target_properties(arbor-gui PROPERTIES MACOSX_BUNDLE_ICONFILE ${ARBORGUI_ICON}) + set(arbgui_resources) + set_source_files_properties(${CMAKE_SOURCE_DIR}/imgui.ini + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + list(APPEND arbgui_resources ${CMAKE_SOURCE_DIR}/imgui.ini) + + file(GLOB_RECURSE shaders ${CMAKE_SOURCE_DIR}/glsl/*/*.glsl) + foreach(SHADER_FILE ${shaders}) + list(APPEND arbgui_resources ${SHADER_FILE}) + file(RELATIVE_PATH SHADER_REL ${CMAKE_SOURCE_DIR}/glsl ${SHADER_FILE}) + get_filename_component(SHADER_DIR ${SHADER_REL} DIRECTORY) + set_source_files_properties(${SHADER_FILE} + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources/glsl/${SHADER_DIR}) + endforeach() + + file(GLOB_RECURSE fonts ${CMAKE_SOURCE_DIR}/fonts/*/*.ttf) + foreach(FONT_FILE ${fonts}) + list(APPEND arbgui_resources ${FONT_FILE}) + file(RELATIVE_PATH FONT_REL ${CMAKE_SOURCE_DIR}/fonts ${FONT_FILE}) + get_filename_component(FONT_DIR ${FONT_REL} DIRECTORY) + set_source_files_properties(${FONT_FILE} + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources/fonts/${FONT_DIR}) + endforeach() + + set_source_files_properties(${CMAKE_SOURCE_DIR}/images/arbor.icns + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + + add_executable(arbor-gui MACOSX_BUNDLE ${gui_srcs} $ ${arbgui_resources} ${CMAKE_SOURCE_DIR}/images/arbor.icns) + set_target_properties(arbor-gui + PROPERTIES + BUNDLE True + MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME} + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_ICONFILE ${ARBORGUI_ICON} + MACOSX_BUNDLE_INFO_STRING "A GUI for Arbor" + RESOURCE ${arbgui_resources}) target_compile_definitions(arbor-gui PUBLIC FMT_HEADER_ONLY) target_include_directories(arbor-gui PRIVATE src ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(arbor-gui PRIVATE ${ARBORGUI_LIBS} arbor arborio glbinding glfw arbor-gui-deps) install(TARGETS arbor-gui - BUNDLE DESTINATION . COMPONENT Runtime - RUNTIME DESTINATION bin COMPONENT Runtime) - - install(FILES ${ARBORGUI_ICON_PATH} DESTINATION ${resource_path}) - install(FILES default.ini DESTINATION ${resource_path} RENAME imgui.ini) - install(DIRECTORY glsl DESTINATION ${resource_path}) - install(DIRECTORY fonts DESTINATION ${resource_path}) + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION bin COMPONENT Runtime) set(CPACK_BINARY_DRAGNDROP ON) set(CPACK_GENERATOR "DragNDrop") @@ -237,7 +268,7 @@ else() endif() # install resources - install(DIRECTORY glsl DESTINATION ${resource_path}) - install(DIRECTORY fonts DESTINATION ${resource_path}) - install(FILES default.ini DESTINATION ${resource_path} RENAME imgui.ini) + install(DIRECTORY glsl DESTINATION ${resource_path}) + install(DIRECTORY fonts DESTINATION ${resource_path}) + install(FILES imgui.ini DESTINATION ${resource_path}) endif() diff --git a/default.ini b/imgui.ini similarity index 100% rename from default.ini rename to imgui.ini diff --git a/src/utils.cpp b/src/utils.cpp index 8b6f3fc..87ebccb 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -21,7 +21,7 @@ std::filesystem::path get_resource_path(const std::filesystem::path& fn) { CFURLRef appUrlRef = CFBundleCopyBundleURL( CFBundleGetMainBundle() ); CFStringRef macPath = CFURLCopyFileSystemPath( appUrlRef, kCFURLPOSIXPathStyle ); CFStringEncoding encodingMethod = CFStringGetSystemEncoding(); - const char* path = CFStringGetCStringPtr(macPath, encodingMethod); + auto path = std::string(CFStringGetCStringPtr(macPath, encodingMethod)); CFRelease(appUrlRef); CFRelease(macPath); return std::filesystem::path{path} / "Contents/Resources" / fn; From e89474b54cae152671816819e4d544a916341315 Mon Sep 17 00:00:00 2001 From: Thorsten Hater <24411438+thorstenhater@users.noreply.github.com> Date: Tue, 23 Sep 2025 14:10:02 +0200 Subject: [PATCH 25/25] Update Readme, fix code for Ubuntu --- 3rd-party/arbor | 2 +- README.md | 25 +++++-------------------- src/gui_state.cpp | 4 ++-- src/main.cpp | 5 +++++ src/utils.cpp | 2 +- src/window.cpp | 2 ++ 6 files changed, 16 insertions(+), 24 deletions(-) diff --git a/3rd-party/arbor b/3rd-party/arbor index bf234aa..0ca5b20 160000 --- a/3rd-party/arbor +++ b/3rd-party/arbor @@ -1 +1 @@ -Subproject commit bf234aa82f497258d1f330ff9311d92463f1929a +Subproject commit 0ca5b20b7a525ea9cb902bdf1af9d85fdd578e33 diff --git a/README.md b/README.md index 33c23aa..857b42e 100644 --- a/README.md +++ b/README.md @@ -120,31 +120,16 @@ Next, follow the platform specific instructions. ``` bash sudo apt update sudo apt install build-essential libssl-dev \ - libxml2-dev libxrandr-dev libxinerama-dev \ + libxrandr-dev libxinerama-dev \ libxcursor-dev libxi-dev libglu1-mesa-dev \ - freeglut3-dev mesa-common-dev gcc-10 g++-10 + freeglut3-dev mesa-common-dev gcc g++ \ + libglfw3 cmake pkg-config xorg-dev libwayland-dev ``` - If your cmake version is less than 3.18, you will need to update it - as well - ``` bash - cmake --version - 3.16 # default on Ubunte 20.04 LTS - # if pip is present - pip install --update cmake - ``` -2. Add GCC10 as alternative to GCC and select it: - ``` bash - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10 - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10 - ``` - Use `gcc --version` to confirm it is now version 10. If not you will - need to run `sudo update-alternatives --config gcc` (and its analog for - `g++`) and manually select the right number. - 3. Install Arbor GUI ```bash cmake .. - sudo make install -j 4 + make + sudo make install ``` ## Windows (WSL2) diff --git a/src/gui_state.cpp b/src/gui_state.cpp index ac92881..9d85096 100644 --- a/src/gui_state.cpp +++ b/src/gui_state.cpp @@ -380,7 +380,7 @@ namespace { } inline void gui_cell_context_menu(gui_state& state) { - if (ImGui::BeginPopupContextWindow()) { + if (ImGui::BeginPopupContextWindow("cell-ctx-window", ImGuiPopupFlags_MouseButtonRight)) { ImGui::Text("%s Camera", icon_camera); { with_indent indent{}; @@ -469,7 +469,7 @@ namespace { vs.zoom = std::clamp(vs.zoom + delta_zoom, 1.0f, 45.0f); } } - + gui_cell_context_menu(state); // static float t_last = 0.0; float t_now = glfwGetTime(); diff --git a/src/main.cpp b/src/main.cpp index 78ff162..ba99540 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,11 @@ int main(int, char**) { Window window{}; gui_state state{}; + // show at least once. + window.begin_frame(); + state.gui(); + window.end_frame(); + for (;window.running() && !state.shutdown_requested;) { if (!window.visible()) { log_debug("Pausing for events."); diff --git a/src/utils.cpp b/src/utils.cpp index 87ebccb..1baeda3 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -29,7 +29,7 @@ std::filesystem::path get_resource_path(const std::filesystem::path& fn) { } void log_init() { - spdlog::set_level(spdlog::level::info); + spdlog::set_level(spdlog::level::debug); } diff --git a/src/window.cpp b/src/window.cpp index 0bc73a2..5b18258 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -41,6 +41,8 @@ Window::Window() { glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 1); + glfwWindowHint(GLFW_FOCUSED, 1); + glfwWindowHint(GLFW_VISIBLE, 1); glsl_version = "#version 410"; handle = glfwCreateWindow(1280, 720, "arbor-gui", NULL, NULL); if (handle == nullptr) log_fatal("Failed to obtain window");