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

Commit aa66fe2

Browse files
author
Jaquier Aurélien Tristan
committed
Merge branch 'master' of https://github.com/BlueBrain/BluePyOpt into neuroml-test
Conflicts: setup.py tox.ini
2 parents 69c0b40 + 3440402 commit aa66fe2

37 files changed

+4643
-62
lines changed

bluepyopt/ephys/efeatures.py

Lines changed: 420 additions & 0 deletions
Large diffs are not rendered by default.

bluepyopt/ephys/extra_features_utils.py

Lines changed: 500 additions & 0 deletions
Large diffs are not rendered by default.

bluepyopt/ephys/models.py

Lines changed: 314 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ def create_empty_template(
200200
''' % dict(template_name=template_name, objref_str=objref_str,
201201
newseclist_str=newseclist_str,
202202
create_str=create_str)
203-
204203
return template
205204

206205
@staticmethod
@@ -246,7 +245,8 @@ def instantiate(self, sim=None):
246245

247246
if self.params is not None:
248247
for param in self.params.values():
249-
param.instantiate(sim=sim, icell=self.icell)
248+
param.instantiate(sim=sim, icell=self.icell,
249+
params=self.params)
250250

251251
def destroy(self, sim=None): # pylint: disable=W0613
252252
"""Destroy instantiated model in simulator"""
@@ -479,3 +479,315 @@ def load_hoc_template(sim, hoc_string):
479479
'NEURON does not have template: ' + template_name
480480

481481
return template_name
482+
483+
484+
class LFPyCellModel(Model):
485+
486+
"""LFPy.Cell model class"""
487+
488+
def __init__(
489+
self,
490+
name,
491+
electrode=None,
492+
morph=None,
493+
mechs=None,
494+
params=None,
495+
dt=0.025,
496+
v_init=-65.0,
497+
gid=0,
498+
seclist_names=None,
499+
secarray_names=None,
500+
):
501+
"""Constructor
502+
503+
Args:
504+
name (str): name of this object
505+
should be alphanumeric string, underscores are allowed,
506+
first char should be a letter
507+
morph (Morphology):
508+
underlying Morphology of the cell
509+
mechs (list of Mechanisms):
510+
Mechanisms associated with the cell
511+
params (list of Parameters):
512+
Parameters of the cell model
513+
seclist_names (list of strings):
514+
Names of the lists of sections
515+
secarray_names (list of strings):
516+
Names of the sections
517+
"""
518+
super(LFPyCellModel, self).__init__(name)
519+
self.check_name()
520+
self.morphology = morph
521+
self.mechanisms = mechs
522+
self.params = collections.OrderedDict()
523+
if params is not None:
524+
for param in params:
525+
self.params[param.name] = param
526+
527+
# Cell instantiation in simulator
528+
self.icell = None
529+
self.lfpy_cell = None
530+
self.electrode = electrode
531+
self.lfpy_electrode = None
532+
533+
self.dt = dt
534+
self.v_init = v_init
535+
536+
self.param_values = None
537+
self.gid = gid
538+
539+
if seclist_names is None:
540+
self.seclist_names = [
541+
"all",
542+
"somatic",
543+
"basal",
544+
"apical",
545+
"axonal",
546+
"myelinated",
547+
]
548+
else:
549+
self.seclist_names = seclist_names
550+
551+
if secarray_names is None:
552+
self.secarray_names = ["soma", "dend", "apic", "axon", "myelin"]
553+
else:
554+
self.secarray_names = secarray_names
555+
556+
def check_name(self):
557+
"""Check if name complies with requirements"""
558+
559+
allowed_chars = string.ascii_letters + string.digits + "_"
560+
561+
if sys.version_info[0] < 3:
562+
translate_args = [None, allowed_chars]
563+
else:
564+
translate_args = [str.maketrans("", "", allowed_chars)]
565+
566+
if (
567+
self.name == ""
568+
or self.name[0] not in string.ascii_letters
569+
or not str(self.name).translate(*translate_args) == ""
570+
):
571+
raise TypeError(
572+
'CellModel: name "%s" provided to constructor does not comply '
573+
"with the rules for Neuron template name: name should be "
574+
"alphanumeric "
575+
"non-empty string, underscores are allowed, "
576+
"first char should be letter" % self.name
577+
)
578+
579+
def params_by_names(self, param_names):
580+
"""Get parameter objects by name"""
581+
582+
return [self.params[param_name] for param_name in param_names]
583+
584+
def freeze(self, param_dict):
585+
"""Set params"""
586+
587+
for param_name, param_value in param_dict.items():
588+
self.params[param_name].freeze(param_dict[param_name])
589+
590+
def unfreeze(self, param_names):
591+
"""Unset params"""
592+
593+
for param_name in param_names:
594+
self.params[param_name].unfreeze()
595+
596+
@staticmethod
597+
def create_empty_template(
598+
template_name, seclist_names=None, secarray_names=None
599+
):
600+
"""create an hoc template named template_name for an empty cell"""
601+
602+
objref_str = "objref this, CellRef"
603+
newseclist_str = ""
604+
605+
if seclist_names:
606+
for seclist_name in seclist_names:
607+
objref_str += ", %s" % seclist_name
608+
newseclist_str += (
609+
" %s = new SectionList()\n" % seclist_name
610+
)
611+
612+
create_str = ""
613+
if secarray_names:
614+
create_str = "create "
615+
create_str += ", ".join(
616+
"%s[1]" % secarray_name for secarray_name in secarray_names
617+
)
618+
create_str += "\n"
619+
620+
template = """\
621+
begintemplate %(template_name)s
622+
%(objref_str)s
623+
proc init() {\n%(newseclist_str)s
624+
forall delete_section()
625+
CellRef = this
626+
}
627+
628+
gid = 0
629+
630+
proc destroy() {localobj nil
631+
CellRef = nil
632+
}
633+
634+
%(create_str)s
635+
endtemplate %(template_name)s
636+
""" % dict(
637+
template_name=template_name,
638+
objref_str=objref_str,
639+
newseclist_str=newseclist_str,
640+
create_str=create_str,
641+
)
642+
643+
return template
644+
645+
@staticmethod
646+
def create_empty_cell(name, sim, seclist_names=None, secarray_names=None):
647+
"""Create an empty cell in Neuron"""
648+
649+
# TODO minize hardcoded definition
650+
# E.g. sectionlist can be procedurally generated
651+
hoc_template = CellModel.create_empty_template(
652+
name, seclist_names, secarray_names
653+
)
654+
sim.neuron.h(hoc_template)
655+
656+
template_function = getattr(sim.neuron.h, name)
657+
658+
return template_function()
659+
660+
def instantiate(self, sim=None):
661+
"""Instantiate model in simulator"""
662+
from LFPy import Cell
663+
from lfpykit import RecExtElectrode
664+
665+
# TODO replace this with the real template name
666+
if not hasattr(sim.neuron.h, self.name):
667+
self.icell = self.create_empty_cell(
668+
self.name,
669+
sim=sim,
670+
seclist_names=self.seclist_names,
671+
secarray_names=self.secarray_names,
672+
)
673+
else:
674+
self.icell = getattr(sim.neuron.h, self.name)()
675+
676+
self.icell.gid = self.gid
677+
678+
self.morphology.instantiate(sim=sim, icell=self.icell)
679+
680+
self.lfpy_cell = Cell(
681+
morphology=sim.neuron.h.allsec(),
682+
dt=self.dt,
683+
v_init=self.v_init,
684+
pt3d=True,
685+
delete_sections=False,
686+
nsegs_method=None,
687+
)
688+
689+
self.lfpy_electrode = RecExtElectrode(
690+
self.lfpy_cell, probe=self.electrode
691+
)
692+
693+
if self.mechanisms is not None:
694+
for mechanism in self.mechanisms:
695+
mechanism.instantiate(sim=sim, icell=self.icell)
696+
697+
if self.params is not None:
698+
for param in self.params.values():
699+
param.instantiate(sim=sim, icell=self.icell,
700+
params=self.params)
701+
702+
def destroy(self, sim=None): # pylint: disable=W0613
703+
"""Destroy instantiated model in simulator"""
704+
705+
# Make sure the icell's destroy() method is called
706+
# without it a circular reference exists between CellRef and the object
707+
# this prevents the icells from being garbage collected, and
708+
# cell objects pile up in the simulator
709+
self.icell.destroy()
710+
711+
# The line below is some M. Hines magic
712+
# DON'T remove it, because it will make sure garbage collection
713+
# is called on the icell object
714+
sim.neuron.h.Vector().size()
715+
716+
self.icell = None
717+
718+
self.morphology.destroy(sim=sim)
719+
for mechanism in self.mechanisms:
720+
mechanism.destroy(sim=sim)
721+
for param in self.params.values():
722+
param.destroy(sim=sim)
723+
724+
def check_nonfrozen_params(self, param_names): # pylint: disable=W0613
725+
"""Check if all nonfrozen params are set"""
726+
727+
for param_name, param in self.params.items():
728+
if not param.frozen:
729+
raise Exception(
730+
"CellModel: Nonfrozen param %s needs to be "
731+
"set before simulation" % param_name
732+
)
733+
734+
def create_hoc(
735+
self,
736+
param_values,
737+
ignored_globals=(),
738+
template="cell_template.jinja2",
739+
disable_banner=False,
740+
template_dir=None,
741+
):
742+
"""Create hoc code for this model"""
743+
744+
to_unfreeze = []
745+
for param in self.params.values():
746+
if not param.frozen:
747+
param.freeze(param_values[param.name])
748+
to_unfreeze.append(param.name)
749+
750+
template_name = self.name
751+
morphology = os.path.basename(self.morphology.morphology_path)
752+
if self.morphology.do_replace_axon:
753+
replace_axon = self.morphology.replace_axon_hoc
754+
else:
755+
replace_axon = None
756+
757+
ret = create_hoc.create_hoc(
758+
mechs=self.mechanisms,
759+
parameters=self.params.values(),
760+
morphology=morphology,
761+
ignored_globals=ignored_globals,
762+
replace_axon=replace_axon,
763+
template_name=template_name,
764+
template_filename=template,
765+
template_dir=template_dir,
766+
disable_banner=disable_banner,
767+
)
768+
769+
self.unfreeze(to_unfreeze)
770+
771+
return ret
772+
773+
def __str__(self):
774+
"""Return string representation"""
775+
776+
content = "%s:\n" % self.name
777+
778+
content += " morphology:\n"
779+
780+
if self.morphology is not None:
781+
content += " %s\n" % str(self.morphology)
782+
783+
content += " mechanisms:\n"
784+
if self.mechanisms is not None:
785+
for mechanism in self.mechanisms:
786+
content += " %s\n" % mechanism
787+
788+
content += " params:\n"
789+
if self.params is not None:
790+
for param in self.params.values():
791+
content += " %s\n" % param
792+
793+
return content

bluepyopt/ephys/morphologies.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ class NrnFileMorphology(Morphology, DictMixin):
4242

4343
"""Morphology loaded from a file"""
4444
SERIALIZED_FIELDS = ('morphology_path', 'do_replace_axon', 'do_set_nseg',
45-
'replace_axon_hoc', )
45+
'replace_axon_hoc', 'nseg_frequency',
46+
'morph_modifiers', 'morph_modifiers_hoc',
47+
'morph_modifiers_kwargs')
4648

4749
def __init__(
4850
self,
@@ -53,7 +55,8 @@ def __init__(
5355
replace_axon_hoc=None,
5456
nseg_frequency=40,
5557
morph_modifiers=None,
56-
morph_modifiers_hoc=None):
58+
morph_modifiers_hoc=None,
59+
morph_modifiers_kwargs=None):
5760
"""Constructor
5861
5962
Args:
@@ -73,6 +76,7 @@ def __init__(
7376
with (sim, icell) as arguments
7477
morph_modifiers_hoc (list): list of hoc strings corresponding
7578
to morph_modifiers
79+
morph_modifiers_kwargs (dict): kwargs for morph_modifiers functions
7680
"""
7781
name = os.path.basename(morphology_path)
7882
super(NrnFileMorphology, self).__init__(name=name, comment=comment)
@@ -84,6 +88,9 @@ def __init__(
8488
self.nseg_frequency = nseg_frequency
8589
self.morph_modifiers = morph_modifiers
8690
self.morph_modifiers_hoc = morph_modifiers_hoc
91+
self.morph_modifiers_kwargs = morph_modifiers_kwargs
92+
if self.morph_modifiers_kwargs is None:
93+
self.morph_modifiers_kwargs = {}
8794

8895
if replace_axon_hoc is None:
8996
self.replace_axon_hoc = self.default_replace_axon_hoc
@@ -146,7 +153,8 @@ def instantiate(self, sim=None, icell=None):
146153

147154
if self.morph_modifiers is not None:
148155
for morph_modifier in self.morph_modifiers:
149-
morph_modifier(sim=sim, icell=icell)
156+
morph_modifier(sim=sim, icell=icell,
157+
**self.morph_modifiers_kwargs)
150158

151159
def destroy(self, sim=None):
152160
"""Destroy morphology instantiation"""

0 commit comments

Comments
 (0)