diff --git a/src/miv_simulator/config.py b/src/miv_simulator/config.py index 9f4204f..7c81074 100644 --- a/src/miv_simulator/config.py +++ b/src/miv_simulator/config.py @@ -245,6 +245,7 @@ class ParametricSurface(BaseModel): class CellType(BaseModel): template: str + mechanism: Union[str, Dict, None] synapses: Dict[ Literal["density"], Dict[ diff --git a/src/miv_simulator/interface/connections.py b/src/miv_simulator/interface/connections.py index a2c4e43..7e411b8 100644 --- a/src/miv_simulator/interface/connections.py +++ b/src/miv_simulator/interface/connections.py @@ -19,7 +19,6 @@ class Config(BaseModel): axon_extents: config.AxonExtents = Field("???") synapses: config.Synapses = Field("???") include_forest_populations: Optional[list] = None - template_path: str = "./templates" connectivity_namespace: str = "Connections" coordinates_namespace: str = "Coordinates" synapses_namespace: str = "Synapse Attributes" @@ -47,7 +46,6 @@ def __call__(self): include_forest_populations=self.config.include_forest_populations, synapses=self.config.synapses, axon_extents=self.config.axon_extents, - template_path=self.config.template_path, output_filepath=self.output_filepath, connectivity_namespace=self.config.connectivity_namespace, coordinates_namespace=self.config.coordinates_namespace, diff --git a/src/miv_simulator/interface/synapses.py b/src/miv_simulator/interface/synapses.py index 6ba0812..16d1969 100644 --- a/src/miv_simulator/interface/synapses.py +++ b/src/miv_simulator/interface/synapses.py @@ -3,10 +3,11 @@ from machinable import Component from miv_simulator import config from miv_simulator import simulator -from pydantic import BaseModel, Field, ConfigDict +from pydantic import BaseModel, Field, ConfigDict, field_validator from typing import Optional, Dict from miv_simulator.utils import from_yaml from mpi4py import MPI +from miv_simulator import mechanisms class Synapses(Component): @@ -17,7 +18,7 @@ class Config(BaseModel): cell_types: config.CellTypes = Field("???") population: str = Field("???") distribution: str = "uniform" - mechanisms_path: str = "./mechanisms" + mechanisms_path: str = "./mechanisms/compiled" template_path: str = "./templates" io_size: int = -1 write_size: int = 1 @@ -25,6 +26,17 @@ class Config(BaseModel): value_chunk_size: int = 1000 ranks: int = 8 + @field_validator("cell_types") + @classmethod + def template_must_not_be_reduced(cls, v): + for population, d in v.items(): + if d["template"].lower() in ["brk_nrn", "pr_nrn", "sc_nrn"]: + raise ValueError( + f"Reduced template {d['template']} for population {population}. A non-reduced template is required for synapse generation." + ) + + return v + def config_from_file(self, filename: str) -> Dict: return from_yaml(filename) @@ -34,12 +46,12 @@ def output_filepath(self) -> str: def __call__(self): logging.basicConfig(level=logging.INFO) + mechanisms.load(self.config.mechanisms_path) simulator.distribute_synapses( forest_filepath=self.config.forest_filepath, cell_types=self.config.cell_types, populations=(self.config.population,), distribution=self.config.distribution, - mechanisms_path=self.config.mechanisms_path, template_path=self.config.template_path, output_filepath=self.output_filepath, io_size=self.config.io_size, diff --git a/src/miv_simulator/simulator/distribute_synapses.py b/src/miv_simulator/simulator/distribute_synapses.py index 2e11472..38074ac 100644 --- a/src/miv_simulator/simulator/distribute_synapses.py +++ b/src/miv_simulator/simulator/distribute_synapses.py @@ -213,6 +213,7 @@ def distribute_synapse_locations( configure_hoc( template_directory=template_path, use_coreneuron=env.use_coreneuron, + mechanisms_directory=mechanisms_path, dt=env.dt, tstop=env.tstop, celsius=env.globals.get("celsius", None), @@ -223,7 +224,6 @@ def distribute_synapse_locations( cell_types=env.celltypes, populations=populations, distribution=distribution, - mechanisms_path=mechanisms_path, template_path=template_path, io_size=io_size, output_filepath=output_path, @@ -240,7 +240,6 @@ def distribute_synapses( cell_types: config.CellTypes, populations: Tuple[str, ...], distribution: Literal["uniform", "poisson"], - mechanisms_path: str, template_path: str, output_filepath: Optional[str], io_size: int, @@ -258,7 +257,7 @@ def distribute_synapses( if rank == 0: logger.info(f"{comm.size} ranks have been allocated") - configure_hoc(mechanisms_directory=mechanisms_path) + configure_hoc() if io_size == -1: io_size = comm.size diff --git a/src/miv_simulator/simulator/execution_environment.py b/src/miv_simulator/simulator/execution_environment.py index dbf7e15..addc3ef 100644 --- a/src/miv_simulator/simulator/execution_environment.py +++ b/src/miv_simulator/simulator/execution_environment.py @@ -1,10 +1,11 @@ from typing import Optional from miv_simulator.utils import AbstractEnv from mpi4py import MPI -from collections import defaultdict, namedtuple +from collections import defaultdict from neuron import h import logging from miv_simulator.network import make_cells, connect_gjs, connect_cells +from miv_simulator.utils import from_yaml, ExprClosure import time import random from miv_simulator import config @@ -113,7 +114,6 @@ def load_cells( population_names = self.comm.bcast(population_names, root=0) cell_attribute_info = self.comm.bcast(cell_attribute_info, root=0) - # TODO: refactor from declarative to imperative celltypes = dict(cell_types) typenames = sorted(celltypes.keys()) for k in typenames: @@ -121,23 +121,16 @@ def load_cells( if population_range is not None: celltypes[k]["start"] = population_ranges[k][0] celltypes[k]["num"] = population_ranges[k][1] - if "mechanism file" in celltypes[k]: - if isinstance(celltypes[k]["mechanism file"], str): - celltypes[k]["mech_file_path"] = celltypes[k][ - "mechanism file" - ] - mech_dict = None + + if "mechanism" in celltypes[k]: + mech_dict = celltypes[k]["mechanism"] + if isinstance(mech_dict, str): if rank == 0: - mech_file_path = celltypes[k]["mech_file_path"] - if self.config_prefix is not None: - mech_file_path = os.path.join( - self.config_prefix, mech_file_path - ) - mech_dict = read_from_yaml(mech_file_path) - else: - mech_dict = celltypes[k]["mechanism file"] - mech_dict = self.comm.bcast(mech_dict, root=0) + mech_dict = from_yaml(mech_dict) + mech_dict = self.comm.bcast(mech_dict, root=0) celltypes[k]["mech_dict"] = mech_dict + celltypes[k]["mech_file_path"] = "$mechanism" + if "synapses" in celltypes[k]: synapses_dict = celltypes[k]["synapses"] if "weights" in synapses_dict: @@ -198,7 +191,7 @@ class _binding: "dataset_prefix": "", "template_dict": self.template_dict, "cell_attribute_info": cell_attribute_info, - "celltypes": cell_types, + "celltypes": celltypes, "model_config": { "Random Seeds": { "Intracellular Recording Sample": self.seed diff --git a/src/miv_simulator/simulator/generate_connections.py b/src/miv_simulator/simulator/generate_connections.py index 7605795..c3bd8a1 100644 --- a/src/miv_simulator/simulator/generate_connections.py +++ b/src/miv_simulator/simulator/generate_connections.py @@ -85,7 +85,6 @@ def generate_distance_connections( include_forest_populations=include, synapses=env.connection_config, axon_extents=env.connection_extents, - template_path=env.template_path, use_coreneuron=env.use_coreneuron, dt=env.dt, tstop=env.tstop, @@ -111,7 +110,6 @@ def generate_connections( include_forest_populations: Optional[list], synapses: config.Synapses, axon_extents: config.AxonExtents, - template_path: str, output_filepath: Optional[str], connectivity_namespace: str, coordinates_namespace: str,