Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The ability to modify single cell properties during the simulation run #205

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion neurodamus/core/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class _SimConfig(object):
reports = None
configures = None
modifications = None
modification_times = []

# Hoc objects used
_config_parser = None
Expand Down Expand Up @@ -272,7 +273,7 @@ def init(cls, config_file, cli_options):
cls.injects = compat.Map(cls._config_parser.parsedInjects)
cls.reports = compat.Map(cls._config_parser.parsedReports)
cls.configures = compat.Map(cls._config_parser.parsedConfigures or {})
cls.modifications = compat.Map(cls._config_parser.parsedModifications or {})
cls.modifications = cls._config_parser.parsedModifications or {}
cls.cli_options = CliOptions(**(cli_options or {}))
cls.dry_run = cls.cli_options.dry_run
cls.crash_test_mode = cls.cli_options.crash_test
Expand Down Expand Up @@ -516,9 +517,12 @@ def _stimulus_params(config: _SimConfig, run_conf):

@SimConfig.validator
def _modification_params(config: _SimConfig, run_conf):
times = set()
required_fields = ("Target", "Type",)
for name, mod_block in config.modifications.items():
_check_params("Modification " + name, compat.Map(mod_block), required_fields, ())
times.add(mod_block["Delay"])
config.modification_times = sorted(times)


def _make_circuit_config(config_dict, req_morphology=True):
Expand Down
5 changes: 3 additions & 2 deletions neurodamus/core/coreneuron_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ._utils import run_only_rank0
from . import NeurodamusCore as Nd
from ..report import get_section_index
from ..utils.logging import log_verbose


class CompartmentMapping:
Expand Down Expand Up @@ -171,7 +172,7 @@ def write_spike_filename(self, filename):
fp.write(filename)
fp.write("\n")

def psolve_core(self, save_path=None, restore_path=None, coreneuron_direct_mode=False):
def psolve_core(self, save_path=None, restore_path=None, coreneuron_direct_mode=False, tstop=None):
from neuron import coreneuron
from . import NeurodamusCore as Nd

Expand All @@ -186,7 +187,7 @@ def psolve_core(self, save_path=None, restore_path=None, coreneuron_direct_mode=
# Model is already written to disk by calling pc.nrncore_write()
coreneuron.skip_write_model_to_disk = True
coreneuron.model_path = f"{self.datadir}"
Nd.pc.psolve(Nd.tstop)
Nd.pc.psolve(tstop or Nd.tstop)


# Singleton
Expand Down
70 changes: 47 additions & 23 deletions neurodamus/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ def _enable_replay(self, source, target, stim_conf, tshift=.0, delay=.0,
# -
@mpi_no_errors
@timeit(name="Enable Modifications")
def enable_modifications(self):
def enable_modifications(self, time=0.0):
"""Iterate over any Modification blocks read from the config file and apply them to the
network. The steps needed are more complex than NeuronConfigures, so the user should not be
expected to write the hoc directly, but rather access a library of already available mods.
Expand All @@ -798,11 +798,12 @@ def enable_modifications(self):
log_stage("Enabling modifications...")

mod_manager = ModificationManager(self._target_manager)
for name, mod in SimConfig.modifications.items():
mod_info = compat.Map(mod)
target_spec = TargetSpec(mod_info["Target"])
logging.info(" * [MOD] %s: %s -> %s", name, mod_info["Type"], target_spec)
mod_manager.interpret(target_spec, mod_info)
for name, mod in SimConfig.modifications.copy().items():
if mod["Delay"] == time:
target_spec = TargetSpec(mod["Target"])
logging.info(" * [MOD] %s: %s -> %s", name, mod["Type"], target_spec)
mod_manager.interpret(target_spec, mod)
del SimConfig.modifications[name]

# Reporting
ReportParams = namedtuple("ReportParams", "name, rep_type, report_on, unit, format, dt, "
Expand Down Expand Up @@ -846,8 +847,11 @@ def enable_reports(self):
if SimConfig.restore_coreneuron:
continue # we dont even need to initialize reports

has_gids = len(self._circuits.global_manager.get_final_gids()) > 0
report = Report(*rep_params, SimConfig.use_coreneuron) if has_gids else None
# In coreneuron direct (in-memory) mode, i_membrane data is copied
# between neuron and coreneuron
if SimConfig.coreneuron_direct_mode and "i_membrane" in rep_params.report_on:
Nd.cvode.use_fast_imem(1)


# With coreneuron direct mode, enable fast membrane current calculation for i_membrane
if SimConfig.coreneuron_direct_mode and \
Expand All @@ -856,18 +860,21 @@ def enable_reports(self):

if not SimConfig.use_coreneuron or rep_params.rep_type == "Synapse":
try:
has_gids = len(self._circuits.global_manager.get_final_gids()) > 0
report = Report(*rep_params, SimConfig.use_coreneuron) if has_gids else None
self._report_setup(report, rep_conf, target, rep_params.rep_type)
except Exception as e:
logging.error("Error setting up report '%s': %s", rep_name, e)
n_errors += 1
continue

# Custom reporting. TODO: Move `_report_setup` to cellManager.enable_report
target_population = target_spec.population or self._target_spec.population
cell_manager = self._circuits.get_node_manager(target_population)
cell_manager.enable_report(report, target, SimConfig.use_coreneuron)
# target_population = target_spec.population or self._target_spec.population
# cell_manager = self._circuits.get_node_manager(target_population)
# cell_manager.enable_report(report, target, SimConfig.use_coreneuron)

self._report_list.append(report)
if report:
self._report_list.append(report)

if n_errors > 0:
raise Exception("%d reporting errors detected. Terminating" % (n_errors,))
Expand Down Expand Up @@ -1313,33 +1320,47 @@ def run_all(self):
self.sim_init()

timings = None
if SimConfig.use_neuron:
timings = self._run_neuron()

for t in SimConfig.modification_times:
if t >= Nd.tstop:
continue
timings = self._run_interval(t)
Nd.t = t
self.enable_modifications(t)

timings = self._run_interval()
if SimConfig.use_neuron or SimConfig.coreneuron_direct_mode:
self.sonata_spikes()

return timings

def _run_interval(self, tstop=None):
timings = None
if SimConfig.use_neuron:
timings = self._run_neuron(tstop)
if SimConfig.use_coreneuron:
print_mem_usage()
if not SimConfig.coreneuron_direct_mode:
self.clear_model(avoid_clearing_queues=False)
self._run_coreneuron()
if SimConfig.coreneuron_direct_mode:
self.sonata_spikes()
self._run_coreneuron(tstop)
return timings

# -
@return_neuron_timings
def _run_neuron(self):
def _run_neuron(self, tstop=None):
if MPI.rank == 0:
_ = SimulationProgress()
self.solve()
self.solve(tstop)
logging.info("Simulation finished.")

# -
def _run_coreneuron(self):
def _run_coreneuron(self, tstop=None):
logging.info("Launching simulation with CoreNEURON")
CoreConfig.psolve_core(
getattr(SimConfig, "save", None),
getattr(SimConfig, "restore", None),
SimConfig.coreneuron_direct_mode
SimConfig.coreneuron_direct_mode,
tstop
)

#
Expand Down Expand Up @@ -1541,7 +1562,8 @@ def cleanup(self):
print_mem_usage()

# Coreneuron runs clear the model before starting
if not SimConfig.use_coreneuron or SimConfig.simulate_model is False:
if not SimConfig.use_coreneuron or SimConfig.coreneuron_direct_mode \
or SimConfig.simulate_model is False:
self.clear_model(avoid_creating_objs=True)

if SimConfig.delete_corenrn_data and not SimConfig.dry_run:
Expand Down Expand Up @@ -1660,7 +1682,9 @@ def init(self):

self.enable_stimulus()
print_mem_usage()
self.enable_modifications()
if SimConfig.modification_times[0] == 0:
self.enable_modifications(time=0)
SimConfig.modification_times.remove(0)

if self._run_conf["EnableReports"]:
self.enable_reports()
Expand Down
Loading