Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Commit 1e56736

Browse files
authored
Merge branch 'master' into lfpy
2 parents 2ab0c58 + 519b2fc commit 1e56736

File tree

7 files changed

+99
-23
lines changed

7 files changed

+99
-23
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ on:
77

88
jobs:
99
test:
10-
runs-on: ubuntu-latest
10+
name: Test for python ${{ matrix.python-version }} on ${{ matrix.os }}
11+
runs-on: ${{ matrix.os }}
1112
strategy:
1213
matrix:
14+
os: [ubuntu-latest, macos-latest]
1315
python-version: ["3.7", "3.8", "3.9", "3.10"]
1416

1517
steps:

bluepyopt/deapext/optimisations.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,10 @@ def setup_deap(self):
199199

200200
# Register the evaluation function for the individuals
201201
# import deap_efel_eval1
202-
self.toolbox.register("evaluate", self.evaluator.evaluate_with_lists)
202+
self.toolbox.register(
203+
"evaluate",
204+
self.evaluator.set_neuron_variables_and_evaluate_with_lists
205+
)
203206

204207
# Register the mate operator
205208
self.toolbox.register(

bluepyopt/deapext/optimisationsCMA.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,10 @@ def setup_deap(self):
211211
)
212212

213213
# Register the evaluation function for the individuals
214-
self.toolbox.register("evaluate", self.evaluator.evaluate_with_lists)
214+
self.toolbox.register(
215+
"evaluate",
216+
self.evaluator.set_neuron_variables_and_evaluate_with_lists
217+
)
215218

216219
import copyreg
217220
import types

bluepyopt/ephys/evaluators.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,17 @@ def evaluate_with_lists(self, param_list=None, target='scores'):
216216

217217
return self.objective_list(obj_dict)
218218

219+
def set_neuron_variables_and_evaluate_with_lists(
220+
self, param_list=None, target='scores'
221+
):
222+
"""Set NEURON variables and run evaluation with lists.
223+
224+
Setting the NEURON variables is necessary when using ipyparallel,
225+
since the new subprocesses have pristine NEURON.
226+
"""
227+
self.sim.set_neuron_variables()
228+
return self.evaluate_with_lists(param_list=param_list, target=target)
229+
219230
def evaluate(self, param_list=None, target='scores'):
220231
"""Run evaluation with lists as input and outputs"""
221232

bluepyopt/ephys/protocols.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,12 +258,20 @@ def _reduce_method(meth):
258258
copyreg.pickle(types.MethodType, _reduce_method)
259259
import pebble
260260
from concurrent.futures import TimeoutError
261+
import multiprocessing
262+
263+
# Default context for python>=3.8 on macos is spawn.
264+
# Spwan context would reset NEURON properties, such as dt.
265+
multiprocessing_context = multiprocessing.get_context('fork')
261266

262267
if timeout is not None:
263268
if timeout < 0:
264269
raise ValueError("timeout should be > 0")
265-
266-
with pebble.ProcessPool(max_workers=1, max_tasks=1) as pool:
270+
with pebble.ProcessPool(
271+
max_workers=1,
272+
max_tasks=1,
273+
context=multiprocessing_context
274+
) as pool:
267275
tasks = pool.schedule(self._run_func, kwargs={
268276
'cell_model': cell_model,
269277
'param_values': param_values,

bluepyopt/ephys/simulators.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ def __init__(self, dt=None, cvode_active=True, cvode_minstep=None,
2121
"""Constructor
2222
2323
Args:
24-
dt (float): the integration time step used by neuron.
25-
cvode_active (bool): should neuron use the variable time step
24+
dt (float): the integration time step used by Neuron.
25+
cvode_active (bool): should Neuron use the variable time step
2626
integration method
2727
cvode_minstep (float): the minimum time step allowed for a cvode
2828
step. Default is 0.0.
@@ -34,27 +34,21 @@ def __init__(self, dt=None, cvode_active=True, cvode_minstep=None,
3434
"./data/".
3535
"""
3636

37-
if platform.system() == 'Windows':
38-
# hoc.so does not exist on NEURON Windows
39-
# although \\hoc.pyd can work here, it gives an error for
40-
# nrn_nobanner_ line
41-
self.disable_banner = False
42-
self.banner_disabled = False
43-
else:
44-
self.disable_banner = True
45-
self.banner_disabled = False
46-
37+
# hoc.so does not exist on NEURON Windows or MacOS
38+
# although \\hoc.pyd can work here, it gives an error for
39+
# nrn_nobanner_ line
40+
self.disable_banner = platform.system() not in ['Windows', 'Darwin']
41+
self.banner_disabled = False
4742
self.mechanisms_directory = mechanisms_directory
48-
self.neuron.h.load_file('stdrun.hoc')
4943

5044
self.dt = dt if dt is not None else self.neuron.h.dt
51-
self.neuron.h.dt = self.dt
5245

53-
self.neuron.h.cvode_active(1 if cvode_active else 0)
5446
self.cvode_minstep_value = cvode_minstep
5547

5648
self.cvode_active = cvode_active
5749

50+
self.set_neuron_variables()
51+
5852
self.random123_globalindex = random123_globalindex
5953

6054
@property
@@ -93,11 +87,9 @@ def _nrn_disable_banner():
9387
ctypes.c_int.in_dll(nrndll, 'nrn_nobanner_').value = 1
9488

9589
# pylint: disable=R0201
96-
# TODO function below should probably a class property or something in that
97-
# sense
9890
@property
9991
def neuron(self):
100-
"""Return neuron module"""
92+
"""Return Neuron module"""
10193

10294
if self.disable_banner and not self.banner_disabled:
10395
NrnSimulator._nrn_disable_banner()
@@ -112,6 +104,12 @@ def neuron(self):
112104

113105
return neuron
114106

107+
def set_neuron_variables(self):
108+
"""Set Neuron variables"""
109+
self.neuron.h.load_file('stdrun.hoc')
110+
self.neuron.h.dt = self.dt
111+
self.neuron.h.cvode_active(1 if self.cvode_active else 0)
112+
115113
def run(
116114
self,
117115
tstop=None,

bluepyopt/tests/test_ephys/test_protocols.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,57 @@ def test_sweepprotocol_run_unisolated():
365365
dummy_cell.destroy(sim=nrn_sim)
366366

367367

368+
@pytest.mark.unit
369+
def test_sweepprotocol_run_isolated():
370+
"""ephys.protocols: Test SweepProtocol isolated run"""
371+
372+
nrn_sim = ephys.simulators.NrnSimulator(dt=0.1)
373+
dummy_cell = dummycells.DummyCellModel1()
374+
soma_loc = ephys.locations.NrnSeclistCompLocation(
375+
name='soma_loc',
376+
seclist_name='somatic',
377+
sec_index=0,
378+
comp_x=.5)
379+
unknown_loc = ephys.locations.NrnSomaDistanceCompLocation(
380+
name='unknown_loc',
381+
seclist_name='somatic',
382+
soma_distance=100)
383+
384+
rec_soma = ephys.recordings.CompRecording(
385+
name='soma.v',
386+
location=soma_loc,
387+
variable='v')
388+
rec_unknown = ephys.recordings.CompRecording(
389+
name='unknown.v',
390+
location=unknown_loc,
391+
variable='v')
392+
393+
stim = ephys.stimuli.NrnSquarePulse(
394+
step_amplitude=0.0,
395+
step_delay=0.0,
396+
step_duration=50,
397+
total_duration=50,
398+
location=soma_loc)
399+
400+
protocol = ephys.protocols.SweepProtocol(
401+
name='prot',
402+
stimuli=[stim],
403+
recordings=[rec_soma, rec_unknown])
404+
405+
responses = protocol.run(
406+
cell_model=dummy_cell,
407+
param_values={},
408+
sim=nrn_sim,
409+
isolate=True)
410+
411+
assert 'soma.v' in responses
412+
assert 'unknown.v' in responses
413+
assert responses['unknown.v'] is None
414+
415+
protocol.destroy(sim=nrn_sim)
416+
dummy_cell.destroy(sim=nrn_sim)
417+
418+
368419
@pytest.mark.unit
369420
def test_nrnsimulator_exception():
370421
"""ephys.protocols: test if protocol raise nrn sim exception"""

0 commit comments

Comments
 (0)