Skip to content

Commit

Permalink
Fix CoreNEURON reports restore
Browse files Browse the repository at this point in the history
 - Update 'save' report.conf with new tstop instead of creating a new one
  • Loading branch information
jorblancoa committed Nov 25, 2024
1 parent 6abadd7 commit f17c5e3
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 30 deletions.
42 changes: 42 additions & 0 deletions neurodamus/core/coreneuron_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pathlib import Path
from ._utils import run_only_rank0
from . import NeurodamusCore as Nd
from .configuration import ConfigurationError
from ..report import get_section_index


Expand Down Expand Up @@ -85,6 +86,47 @@ class _CoreNEURONConfig(object):
def instantiate_artificial_cell(self):
self.artificial_cell_object = Nd.CoreNEURONArtificialCell()

@run_only_rank0
def update_tstop(self, report_name, nodeset_name, tstop):
# Try current directory first
report_conf = Path(self.output_root) / self.report_config_file
if not report_conf.exists():
# Try one level up from output_root
parent_report_conf = Path(self.output_root) / ".." / self.report_config_file
if parent_report_conf.exists():
# Copy the file to current location
report_conf.write_bytes(parent_report_conf.read_bytes())
else:
raise ConfigurationError(f"Report config file not found in {report_conf} "
f"or {parent_report_conf}")

# Read all content
with report_conf.open('rb') as f:
lines = f.readlines()

# Find and update the matching line
found = False
for i, line in enumerate(lines):
try:
parts = line.decode().split()
# Report name and target name must match in order to update the tstop
if parts[0:2] == [report_name, nodeset_name]:
parts[9] = f"{tstop:.6f}"
lines[i] = (' '.join(parts) + '\n').encode()
found = True
break
except (UnicodeDecodeError, IndexError):
# Ignore lines that cannot be decoded (binary data)
continue

if not found:
raise ConfigurationError(f"Report '{report_name}' with target '{nodeset_name}' "
"not matching any report in the 'save' execution")

# Write back
with report_conf.open('wb') as f:
f.writelines(lines)

@run_only_rank0
def write_report_config(
self, report_name, target_name, report_type, report_variable,
Expand Down
65 changes: 35 additions & 30 deletions neurodamus/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ def enable_reports(self):
pop_offsets_alias = self._circuits.get_population_offsets()
else:
pop_offsets_alias = CircuitManager.read_population_offsets()
if SimConfig.use_coreneuron:
if SimConfig.use_coreneuron and not SimConfig.restore_coreneuron:
CoreConfig.write_report_count(len(reports_conf))

for rep_name, rep_conf in reports_conf.items():
Expand All @@ -839,7 +839,7 @@ def enable_reports(self):
continue

if SimConfig.use_coreneuron and MPI.rank == 0:
if not self._report_write_coreneuron_config(rep_name, rep_conf, target, rep_params):
if not self._report_write_coreneuron_config(rep_conf, target, rep_params):
n_errors += 1
continue

Expand Down Expand Up @@ -940,35 +940,38 @@ def _report_build_params(self, rep_name, rep_conf, target, pop_offsets_alias_pop
)

#
def _report_write_coreneuron_config(self, rep_name, rep_conf, target, rep_params):
def _report_write_coreneuron_config(self, rep_conf, target, rep_params):
target_spec = TargetSpec(rep_conf["Target"])

# for sonata config, compute target_type from user inputs
if "Sections" in rep_conf and "Compartments" in rep_conf:
def _compute_corenrn_target_type(section_type, compartment_type):
sections = ["all", "soma", "axon", "dend", "apic"]
compartments = ["center", "all"]
if section_type not in sections:
raise ConfigurationError(f"Report: invalid section type '{section_type}'")
if compartment_type not in compartments:
raise ConfigurationError(f"Report: invalid compartment type {compartment_type}")
if section_type == "all": # for "all sections", support only target_type=0
return 0
# 0=Compartment, Section { 2=Soma, 3=Axon, 4=Dendrite, 5=Apical, 6=SomaAll ... }
return sections.index(section_type)+1+4*compartments.index(compartment_type)

section_type = rep_conf.get("Sections")
compartment_type = rep_conf.get("Compartments")
target_type = _compute_corenrn_target_type(section_type, compartment_type)

reporton_comma_separated = ",".join(rep_params.report_on.split())
core_report_params = (
(os.path.basename(rep_conf.get("FileName", rep_name)),
target_spec.name, rep_params.rep_type, reporton_comma_separated)
+ rep_params[3:5] + (target_type,) + rep_params[5:8]
+ (target.get_gids(), SimConfig.corenrn_buff_size)
)
CoreConfig.write_report_config(*core_report_params)
if SimConfig.restore_coreneuron:
CoreConfig.update_tstop(rep_params.name, target_spec.name, rep_params.end)
else:
# for sonata config, compute target_type from user inputs
if "Sections" in rep_conf and "Compartments" in rep_conf:
def _compute_corenrn_target_type(section_type, compartment_type):
sections = ["all", "soma", "axon", "dend", "apic"]
compartments = ["center", "all"]
if section_type not in sections:
raise ConfigurationError(f"Report: invalid section type '{section_type}'")
if compartment_type not in compartments:
raise ConfigurationError(f"Report: invalid compartment type "
f"{compartment_type}")
if section_type == "all": # for "all sections", support only target_type=0
return 0
# 0=Compartment, Section { 2=Soma, 3=Axon, 4=Dendrite, 5=Apical, 6=SomaAll ... }
return sections.index(section_type)+1+4*compartments.index(compartment_type)

section_type = rep_conf.get("Sections")
compartment_type = rep_conf.get("Compartments")
target_type = _compute_corenrn_target_type(section_type, compartment_type)

reporton_comma_separated = ",".join(rep_params.report_on.split())
core_report_params = (
(rep_params.name, target_spec.name, rep_params.rep_type, reporton_comma_separated)
+ rep_params[3:5] + (target_type,) + rep_params[5:8]
+ (target.get_gids(), SimConfig.corenrn_buff_size)
)
CoreConfig.write_report_config(*core_report_params)
return True

def _report_setup(self, report, rep_conf, target, rep_type):
Expand Down Expand Up @@ -1008,8 +1011,10 @@ def _report_setup(self, report, rep_conf, target, rep_type):
report.add_synapse_report(cell, point, spgid, pop_name, pop_offset)

def _reports_init(self, pop_offsets_alias):
pop_offsets = pop_offsets_alias[0]
if SimConfig.restore_coreneuron:
return

pop_offsets = pop_offsets_alias[0]
if SimConfig.use_coreneuron:
# write spike populations
if hasattr(CoreConfig, "write_population_count"):
Expand Down

0 comments on commit f17c5e3

Please sign in to comment.