Skip to content

Commit 6f730a6

Browse files
committed
Merge branch 'master' into slds-wt
2 parents 84cc3cb + 2ac5cc7 commit 6f730a6

23 files changed

Lines changed: 235 additions & 96 deletions

.github/workflows/coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
- name: Setup cmake
6767
uses: jwlawson/actions-setup-cmake@v2
6868
with:
69-
cmake-version : '3.19'
69+
cmake-version : '3.20'
7070

7171
- name: Setup Caliper profiler
7272
run: |

.github/workflows/neuron-ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ jobs:
3636
SDK_ROOT: $(xcrun --sdk macosx --show-sdk-path)
3737
SKIP_WHEELHOUSE_REPAIR: true
3838
BUILD_TYPE: Release
39-
DESIRED_CMAKE_VERSION: 3.19
40-
DYNAMIC_PYTHON_CMAKE_VERSION: 3.19
39+
DESIRED_CMAKE_VERSION: '3.20'
40+
DYNAMIC_PYTHON_CMAKE_VERSION: '3.20'
4141
PY_MIN_VERSION: ${{ matrix.config.python_min_version || '3.10' }}
4242
PY_MAX_VERSION: ${{ matrix.config.python_max_version || '3.14' }}
4343
MUSIC_INSTALL_DIR: /opt/MUSIC

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ jobs:
159159
- name: Setup cmake
160160
uses: jwlawson/actions-setup-cmake@v2
161161
with:
162-
cmake-version : '3.19'
162+
cmake-version : '3.20'
163163

164164
- name: Set up Python
165165
id: setup-python

CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
1+
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
22
# Note that this needs to happen **before** the call to project(...). This is because CMake reads
33
# the CRAYPE_LINK_TYPE environment variable inside the call to project(...) and sets various flags
44
# and properties based on its value. Because we are so early in the CMake processing, we have to
@@ -39,7 +39,7 @@ if(POLICY CMP0177)
3939
cmake_policy(SET CMP0177 NEW)
4040
endif()
4141

42-
# customizable install path to Python components. Mostly useful for Spack builds
42+
# customizable install path to Python components. Mostly useful for Spack & venv builds
4343
set(NRN_INSTALL_PYTHON_PREFIX
4444
"lib/python/neuron/"
4545
CACHE STRING
@@ -65,6 +65,11 @@ else()
6565
set(NRN_INSTALL_DATA_PREFIX)
6666
endif()
6767

68+
# Make python install path relative to CMAKE_INSTALL_PREFIX
69+
if(IS_ABSOLUTE "${NRN_INSTALL_PYTHON_PREFIX}")
70+
cmake_path(RELATIVE_PATH NRN_INSTALL_PYTHON_PREFIX BASE_DIRECTORY "${CMAKE_INSTALL_PREFIX}")
71+
endif()
72+
6873
# =============================================================================
6974
# CMake common project settings
7075
# =============================================================================

docs/capi.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,10 @@ Functions, objects, and the stack
905905
906906
// Create current clamp at soma
907907
Symbol* iclamp_sym = nrn_symbol("IClamp");
908-
nrn_object_push((Object*)soma); // Push soma as object
908+
nrn_section_push(soma); // specify the section separately
909909
nrn_double_push(0.0); // Push location (0.0)
910910
Object* iclamp = nrn_object_new(iclamp_sym, 2);
911+
nrn_section_pop();
911912
912913
**Python Equivalent:**
913914

@@ -1966,8 +1967,10 @@ Here we stimulate the cell with a :class:`IClamp` at time 1 ms.
19661967
nrn_mechanism_insert(soma, nrn_symbol("hh"));
19671968
19681969
// current clamp at soma(0.5)
1970+
nrn_section_push(soma); // specify the section separately
19691971
nrn_double_push(0.5);
19701972
Object* iclamp = nrn_object_new(nrn_symbol("IClamp"), 1);
1973+
nrn_section_pop();
19711974
for (const auto& [property, value] : {pair{"amp", 0.3}, pair{"del", 1.0}, pair{"dur", 0.1}}) {
19721975
nrn_property_set(iclamp, property, value);
19731976
}
@@ -2051,4 +2054,4 @@ This displays the following image:
20512054
.. image:: progref/images/hh_sim_cpp.png
20522055
:alt: Hodgkin-Huxley simulation driven by a current clamp at 1ms showing an action potential
20532056
:width: 75%
2054-
:align: center
2057+
:align: center

docs/cmake_doc/options.rst

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,30 @@ NRN_ENABLE_PYTHON:BOOL=ON
306306
Enable Python interpreter support
307307
(default python, fallback to python3, but see PYTHON_EXECUTABLE below)
308308

309+
NRN_INSTALL_PYTHON_PREFIX:STRING="lib/python/neuron/"
310+
-----------------------------------------------------
311+
Path where NEURON Python components will be installed, relative to CMAKE_INSTALL_PREFIX. Must end with a directory named "neuron"
312+
313+
Environment variable PYTHONPATH must contain the real path to NRN_INSTALL_PYTHON_PREFIX in order for python to find neuron.
314+
315+
This path must end with a directory named "neuron"
316+
317+
For venv's, configure cmake with:
318+
319+
.. code-block:: shell
320+
321+
-DCMAKE_INSTALL_PREFIX=$(python -c "import sysconfig; print(sysconfig.get_path('data', 'venv'))") \
322+
-DNRN_INSTALL_PYTHON_PREFIX=$(python -c "import sysconfig; print(sysconfig.get_path('platlib', 'venv') + '/neuron')")
323+
324+
To install to your home directory, configure cmake with:
325+
326+
.. code-block:: shell
327+
328+
-DCMAKE_INSTALL_PREFIX=$(python3 -m site --user-base) \
329+
-DNRN_INSTALL_PYTHON_PREFIX=$(python3 -m site --user-site)/neuron
330+
331+
This option is ignored when building a wheel, in which case the value is forced to "neuron/"
332+
309333
.. _cmake_nrn_enable_python_dynamic:
310334
NRN_ENABLE_PYTHON_DYNAMIC:BOOL=OFF
311335
----------------------------------
@@ -544,7 +568,7 @@ NRN_ENABLE_TESTS:BOOL=OFF
544568
python3 -m pytest test_currents.py
545569
546570
NRN_ENABLE_COVERAGE:BOOL=OFF
547-
---------------------------
571+
----------------------------
548572
Enable code coverage
549573

550574
Requires ``lcov`` (e.g. ``sudo apt install lcov``).
@@ -677,7 +701,7 @@ NRN_ENABLE_DIGEST:BOOL=OFF
677701
Requires libcrypto
678702

679703
NRN_ENABLE_ARCH_INDEP_EXP_POW:BOOL=OFF
680-
---------------------------------
704+
--------------------------------------
681705
Provides \ :func:`use_exp_pow_precision` function so that exp and pow produce
682706
same results on all platforms.
683707

src/coreneuron/apps/main1.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,11 @@ extern "C" int run_solve_core(int argc, char** argv) {
561561

562562
// register all reports with libsonata
563563
double min_report_dt = INT_MAX;
564+
size_t lfp_report_counter = 0;
564565
for (size_t i = 0; i < configs.size(); i++) {
566+
if (configs[i].type == ReportType::LFP) {
567+
configs[i].lfp_report_index = lfp_report_counter++;
568+
}
565569
std::unique_ptr<ReportHandler> report_handler = create_report_handler(configs[i],
566570
spikes_info);
567571
if (report_handler) {

src/coreneuron/io/nrn2core_direct.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extern void (*nrn2core_get_dat3_secmapping_)(int i_c,
106106
int& nsec,
107107
int& nseg,
108108
size_t& total_lfp_factors,
109-
int& n_electrodes,
109+
std::vector<size_t>& electrode_offsets,
110110
std::vector<int>& data_sec,
111111
std::vector<int>& data_seg,
112112
std::vector<double>& data_lfp);

src/coreneuron/io/nrn_filehandler.hpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <iostream>
1212
#include <fstream>
13+
#include <sstream>
1314
#include <vector>
1415
#include <cmath>
1516
#include <sys/stat.h>
@@ -118,18 +119,27 @@ class FileHandler {
118119
NrnThreadMappingInfo* ntmapping,
119120
std::shared_ptr<CellMapping> cmap,
120121
const NrnThread& nt) {
121-
int nsec, nseg, n_scan;
122-
size_t total_lfp_factors;
123-
int num_electrodes;
124-
char line_buf[max_line_length], name[max_line_length];
125-
126-
F.getline(line_buf, sizeof(line_buf));
127-
n_scan = sscanf(
128-
line_buf, "%s %d %d %zd %d", name, &nsec, &nseg, &total_lfp_factors, &num_electrodes);
129-
130-
nrn_assert(n_scan == 5);
122+
std::string line;
123+
std::getline(F, line);
124+
125+
std::istringstream iss(line);
126+
std::string name_str;
127+
int nsec = 0;
128+
int nseg = 0;
129+
size_t total_lfp_factors = 0;
130+
int offset_count = 0;
131+
iss >> name_str >> nsec >> nseg >> total_lfp_factors >> offset_count;
132+
nrn_assert(!iss.fail());
133+
134+
if (offset_count > 0) {
135+
cmap->electrode_offsets.resize(offset_count);
136+
for (int k = 0; k < offset_count; k++) {
137+
iss >> cmap->electrode_offsets[k];
138+
}
139+
nrn_assert(!iss.fail());
140+
}
131141

132-
mapinfo->type = section_type_from_string(name);
142+
mapinfo->type = section_type_from_string(name_str);
133143

134144
if (nseg) {
135145
auto sec = read_vector<int>(nseg);
@@ -144,20 +154,16 @@ class FileHandler {
144154
lfp_factors = read_vector<double>(total_lfp_factors);
145155
}
146156

147-
int factor_offset = 0;
148157
for (int i = 0; i < nseg; i++) {
149158
mapinfo->add_segment(sec[i], seg[i]);
150159
ntmapping->add_segment_id(seg[i]);
151-
int factor_offset = i * num_electrodes;
152160
if (total_lfp_factors > 0) {
153-
// Abort if the factors contains a NaN
161+
const auto num_electrodes = cmap->num_electrodes();
154162
nrn_assert(count_if(lfp_factors.begin(), lfp_factors.end(), [](double d) {
155163
return std::isnan(d);
156164
}) == 0);
157-
std::vector<double> segment_factors(lfp_factors.begin() + factor_offset,
158-
lfp_factors.begin() + factor_offset +
159-
num_electrodes);
160-
cmap->add_segment_lfp_factor(seg[i], segment_factors);
165+
auto begin = lfp_factors.begin() + i * num_electrodes;
166+
cmap->add_segment_lfp_factor(seg[i], begin, begin + num_electrodes);
161167
}
162168
}
163169
}

src/coreneuron/io/nrnsection_mapping.hpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <vector>
1919

2020
#include "coreneuron/io/reports/nrnreport.hpp"
21+
#include "coreneuron/utils/nrn_assert.h"
2122
#include "coreneuron/utils/utils.hpp"
2223

2324
namespace coreneuron {
@@ -73,8 +74,15 @@ struct CellMapping {
7374
/** list of section lists (like soma, axon, apic) */
7475
std::vector<std::shared_ptr<SecMapping>> sec_mappings;
7576

76-
/** map containing segment ids an its respective lfp factors */
77-
std::unordered_map<int, std::vector<double>> lfp_factors;
77+
/** segment ids for lfp factors (one per compartment with LFP data) */
78+
std::vector<int> lfp_segment_ids;
79+
80+
/** flat array of lfp factors: stride = num_electrodes, indexed as [i * stride + e] */
81+
std::vector<double> lfp_factors_flat;
82+
83+
/** Electrode offsets per LFP report (CSR-style, size = num_reports + 1).
84+
* offsets[i]..offsets[i+1] gives the electrode range for report i. */
85+
std::vector<size_t> electrode_offsets;
7886

7987
CellMapping(int g)
8088
: gid(g) {}
@@ -99,13 +107,9 @@ struct CellMapping {
99107
});
100108
}
101109

102-
/** @brief return the number of electrodes in the lfp_factors map **/
103-
int num_electrodes() const {
104-
int num_electrodes = 0;
105-
if (!lfp_factors.empty()) {
106-
num_electrodes = lfp_factors.begin()->second.size();
107-
}
108-
return num_electrodes;
110+
/** @brief return the total number of electrodes **/
111+
size_t num_electrodes() const {
112+
return electrode_offsets.empty() ? 0 : electrode_offsets.back();
109113
}
110114

111115
/** @brief number of section lists */
@@ -148,8 +152,18 @@ struct CellMapping {
148152
}
149153

150154
/** @brief add the lfp electrode factors of a segment_id */
151-
void add_segment_lfp_factor(const int segment_id, std::vector<double>& factors) {
152-
lfp_factors.insert({segment_id, factors});
155+
void add_segment_lfp_factor(const int segment_id,
156+
std::vector<double>::const_iterator begin,
157+
std::vector<double>::const_iterator end) {
158+
const size_t n = std::distance(begin, end);
159+
if (n == 0) {
160+
return;
161+
}
162+
const auto curr_n_electrodes = num_electrodes();
163+
// All segments must have the same number of electrode factors
164+
nrn_assert(curr_n_electrodes == 0 || n == curr_n_electrodes);
165+
lfp_segment_ids.push_back(segment_id);
166+
lfp_factors_flat.insert(lfp_factors_flat.end(), begin, end);
153167
}
154168
};
155169

0 commit comments

Comments
 (0)