bluecellulab 2.6.67__py3-none-any.whl → 2.6.68__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bluecellulab might be problematic. Click here for more details.

bluecellulab/cell/core.py CHANGED
@@ -47,6 +47,7 @@ from bluecellulab.stimulus.circuit_stimulus_definitions import SynapseReplay
47
47
  from bluecellulab.synapse import SynapseFactory, Synapse
48
48
  from bluecellulab.synapse.synapse_types import SynapseID
49
49
  from bluecellulab.type_aliases import HocObjectType, NeuronSection, SectionMapping
50
+ from bluecellulab.cell.section_tools import currents_vars, section_to_variable_recording_str
50
51
 
51
52
  logger = logging.getLogger(__name__)
52
53
 
@@ -250,6 +251,10 @@ class Cell(InjectableMixin, PlottableMixin):
250
251
  else:
251
252
  self._default_disable_ttx()
252
253
 
254
+ @property
255
+ def ttx_enabled(self):
256
+ return getattr(self, "_ttx_enabled", False)
257
+
253
258
  def _default_enable_ttx(self) -> None:
254
259
  """Default enable_ttx implementation."""
255
260
  for section in self.sections.values():
@@ -782,7 +787,7 @@ class Cell(InjectableMixin, PlottableMixin):
782
787
  if section is None:
783
788
  section = self.soma
784
789
 
785
- # Optional: validate before constructing the string
790
+ # validate before constructing the string
786
791
  seg = section(segx)
787
792
  if "." in variable:
788
793
  mech, var = variable.split(".", 1)
@@ -895,23 +900,41 @@ class Cell(InjectableMixin, PlottableMixin):
895
900
  def __del__(self):
896
901
  self.delete()
897
902
 
898
-
899
- def section_to_variable_recording_str(section, segx: float, variable: str) -> str:
900
- """Build an evaluable NEURON pointer string for `add_recording`.
901
-
902
- Accepts:
903
- - top-level vars: "v", "ina", "ik", ...
904
- - mechanism-scoped vars: "kca.gkca", "na3.m", "na3.h", ...
905
-
906
- Returns examples:
907
- neuron.h.soma[0](0.5)._ref_v
908
- neuron.h.soma[0](0.5)._ref_ina
909
- neuron.h.soma[0](0.5).kca._ref_gkca
910
- neuron.h.dend[3](0.7).na3._ref_m
911
- """
912
- sec_name = section.name()
913
- if "." in variable:
914
- mech, var = variable.split(".", 1)
915
- return f"neuron.h.{sec_name}({segx}).{mech}._ref_{var}"
916
- else:
917
- return f"neuron.h.{sec_name}({segx})._ref_{variable}"
903
+ def add_currents_recordings(
904
+ self,
905
+ section,
906
+ segx: float = 0.5,
907
+ *,
908
+ include_nonspecific: bool = True,
909
+ include_point_processes: bool = False,
910
+ dt: float | None = None,
911
+ ) -> list[str]:
912
+ """Record all available currents (ionic + optionally nonspecific) at
913
+ (section, segx)."""
914
+
915
+ # discover what’s available at this site
916
+ available = currents_vars(section)
917
+ chosen: list[str] = []
918
+
919
+ for name, meta in available.items():
920
+ kind = meta.get("kind")
921
+
922
+ if kind == "ionic_current":
923
+ self.add_variable_recording(name, section=section, segx=segx, dt=dt)
924
+ chosen.append(name)
925
+
926
+ elif kind == "nonspecific_current":
927
+ if not include_nonspecific:
928
+ continue
929
+ # density-mech nonspecific currents
930
+ self.add_variable_recording(name, section=section, segx=segx, dt=dt)
931
+ chosen.append(name)
932
+
933
+ elif kind == "point_process_current":
934
+ if not include_point_processes:
935
+ continue
936
+ # point process nonspecific currents
937
+ self.add_variable_recording(name, section=section, segx=segx, dt=dt)
938
+ chosen.append(name)
939
+
940
+ return chosen
@@ -0,0 +1,96 @@
1
+ # Copyright 2025 Open Brain Institute
2
+
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """NEURON section helpers for BlueCelluLab."""
15
+
16
+
17
+ def currents_vars(section) -> dict:
18
+ """Return recordable currents (with units) at a given section.
19
+
20
+ - Ionic currents from the ions block (e.g. ``ina``, ``ik``, ``ica``), in mA/cm².
21
+ - Mechanism currents for variables ``i`` or ``ihcn``, reported as ``<var>_<mech>``
22
+ (e.g. ``i_pas``, ``ihcn_Ih``), in mA/cm².
23
+
24
+ Args:
25
+ section: NEURON Section object.
26
+
27
+ Returns:
28
+ dict mapping variable names to {"units": str, "kind": str}.
29
+ """
30
+ psec = section.psection()
31
+ out = {}
32
+
33
+ ions = psec.get("ions", {}) or {}
34
+ for ion, vars_dict in ions.items():
35
+ if ion == "ttx":
36
+ continue
37
+ name = f"i{ion}"
38
+ if name in vars_dict:
39
+ out[name] = {"units": "mA/cm²", "kind": "ionic_current"}
40
+
41
+ special_currents = {
42
+ ("pas", "i"): "i_pas",
43
+ ("Ih", "ihcn"): "ihcn_Ih",
44
+ ("hd", "i"): "i_hd",
45
+ }
46
+
47
+ for (mech, var), out_name in special_currents.items():
48
+ if var in (psec.get("density_mechs") or {}).get(mech, {}):
49
+ out[out_name] = {"units": "mA/cm²", "kind": "nonspecific_current"}
50
+
51
+ return dict(sorted(out.items()))
52
+
53
+
54
+ def mechs_vars(section, include_point_mechs: bool = False) -> dict:
55
+ """Return mechanism-scoped variables at a given section.
56
+
57
+ Args:
58
+ section: NEURON Section object.
59
+ include_point_mechs: Whether to include point processes.
60
+ """
61
+ psec = section.psection()
62
+ dens = psec.get("density_mechs", {}) or {}
63
+ points = psec.get("point_mechs", {}) or {}
64
+ mech_map = {
65
+ mech: sorted(vars_dict.keys())
66
+ for mech, vars_dict in dens.items() if vars_dict
67
+ }
68
+ entry = {"mech": mech_map}
69
+ if include_point_mechs:
70
+ point_map = {
71
+ pp: sorted(vars_dict.keys())
72
+ for pp, vars_dict in points.items() if vars_dict
73
+ }
74
+ entry["point"] = point_map
75
+ return entry
76
+
77
+
78
+ def section_to_variable_recording_str(section, segx: float, variable: str) -> str:
79
+ """Build an evaluable NEURON pointer string for `add_recording`.
80
+
81
+ Accepts:
82
+ - top-level vars: "v", "ina", "ik", ...
83
+ - mechanism-scoped vars: "kca.gkca", "na3.m", "na3.h", ...
84
+
85
+ Returns examples:
86
+ neuron.h.soma[0](0.5)._ref_v
87
+ neuron.h.soma[0](0.5)._ref_ina
88
+ neuron.h.soma[0](0.5).kca._ref_gkca
89
+ neuron.h.dend[3](0.7).na3._ref_m
90
+ """
91
+ sec_name = section.name()
92
+ if "." in variable:
93
+ mech, var = variable.split(".", 1)
94
+ return f"neuron.h.{sec_name}({segx}).{mech}._ref_{var}"
95
+ else:
96
+ return f"neuron.h.{sec_name}({segx})._ref_{variable}"
bluecellulab/tools.py CHANGED
@@ -632,108 +632,3 @@ def compute_memodel_properties(
632
632
  )
633
633
 
634
634
  return {"holding_current": holding_current, "rheobase": rheobase, "rin": rin}
635
-
636
-
637
- def list_segment_ion_variables(cell, xs=(0.5,)):
638
- """Enumerate top-level ionic variables (e.g. v, ina, ik, gna) available for
639
- each section at specified segment locations.
640
-
641
- Includes:
642
- - Membrane potential (v)
643
- - Standard ionic currents (ina, ik, ica, icl)
644
- - Reversal potentials (ena, ek, eca, ecl)
645
- - Conductances if exposed (gna, gk, gca, gcl)
646
- """
647
- out = {}
648
- for sec in cell.sections.values():
649
- xmap = {}
650
- for x in xs:
651
- seg = sec(x)
652
-
653
- vars_ = []
654
- # voltage always there
655
- if hasattr(seg, "_ref_v"):
656
- vars_.append("v")
657
-
658
- # ionic currents (present if mechanisms with ions are inserted)
659
- for ion in ("na", "k", "ca", "cl"):
660
- if hasattr(seg, f"_ref_i{ion}"):
661
- vars_.append(f"i{ion}")
662
- if hasattr(seg, f"_ref_e{ion}"):
663
- vars_.append(f"e{ion}")
664
- if hasattr(seg, f"_ref_g{ion}"):
665
- vars_.append(f"g{ion}")
666
-
667
- xmap[float(x)] = sorted(set(vars_))
668
-
669
- out[sec.name()] = xmap
670
- return out
671
-
672
-
673
- def list_segment_mechanism_variables(cell, xs=(0.5,), include_point_mechs=False):
674
- """Enumerate mechanism-scoped recordables per section/segment.
675
-
676
- Returns:
677
- dict: A nested dictionary of the form::
678
-
679
- {
680
- "<secname>": {
681
- x: {
682
- "mech": {
683
- "<density_mech>": [<vars>],
684
- ...
685
- },
686
- "point": {
687
- "<point_mech>": [<vars>],
688
- ...
689
- } # present only if include_point_mechs
690
- },
691
- ...
692
- },
693
- ...
694
- }
695
- """
696
- out = {}
697
- for sec in cell.sections.values():
698
- dens = sec.psection().get("density_mechs", {}) or {}
699
- points = sec.psection().get("point_mechs", {}) or {}
700
- xmap = {}
701
-
702
- for x in xs:
703
- seg = sec(x)
704
-
705
- # Density mechanisms
706
- mech_map = {}
707
- for mech, vardict in dens.items():
708
- mobj = getattr(seg, mech, None)
709
- if mobj is None:
710
- continue
711
- # take var names advertised by psection(), keep those that are actually _ref_-exposed
712
- vars_found = sorted(
713
- v for v in vardict.keys()
714
- if hasattr(mobj, f"_ref_{v}")
715
- )
716
- if vars_found:
717
- mech_map[mech] = vars_found
718
-
719
- entry = {"mech": mech_map}
720
-
721
- # Point processes
722
- if include_point_mechs:
723
- pp_map = {}
724
- for pp, vardict in points.items():
725
- pobj = getattr(seg, pp, None)
726
- if pobj is None:
727
- continue
728
- vars_found = sorted(
729
- v for v in vardict.keys()
730
- if hasattr(pobj, f"_ref_{v}")
731
- )
732
- if vars_found:
733
- pp_map[pp] = vars_found
734
- entry["point"] = pp_map
735
-
736
- xmap[float(x)] = entry
737
-
738
- out[sec.name()] = xmap
739
- return out
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluecellulab
3
- Version: 2.6.67
3
+ Version: 2.6.68
4
4
  Summary: Biologically detailed neural network simulations and analysis.
5
5
  Author: Blue Brain Project, EPFL
6
6
  License: Apache2.0
@@ -10,7 +10,7 @@ bluecellulab/plotwindow.py,sha256=ePU-EegZ1Sqk0SoYYiQ6k24ZO4s3Hgfpx10uePiJ5xM,27
10
10
  bluecellulab/psection.py,sha256=FSOwRNuOTyB469BM-jPEf9l1J59FamXmzrQgBI6cnP4,6174
11
11
  bluecellulab/psegment.py,sha256=PTgoGLqM4oFIdF_8QHFQCU59j-8TQmtq6PakiGUQhIo,3138
12
12
  bluecellulab/rngsettings.py,sha256=2Ykb4Ylk3XTs58x1UIxjg8XJqjSpnCgKRZ8avXCDpxk,4237
13
- bluecellulab/tools.py,sha256=1v3y4klNywl_6JRJzsdtuAn7w-pY5ysVaREcj0WwLWw,25253
13
+ bluecellulab/tools.py,sha256=XvfWGSbNevAEUa8TYlAJtRurKOvbARY0wLa6qHkm93g,21925
14
14
  bluecellulab/type_aliases.py,sha256=DvgjERv2Ztdw_sW63JrZTQGpJ0x5uMTFB5hcBHDb0WA,441
15
15
  bluecellulab/utils.py,sha256=0NhwlzyLnSi8kziSfDsQf7pokO4qDkMJVAO33kSX4O0,2227
16
16
  bluecellulab/verbosity.py,sha256=T0IgX7DrRo19faxrT4Xzb27gqxzoILQ8FzYKxvUeaPM,1342
@@ -21,12 +21,13 @@ bluecellulab/analysis/plotting.py,sha256=PqRoaZz33ULMw8A9YnZXXrxcUd84M_dwlYMTFhG
21
21
  bluecellulab/analysis/utils.py,sha256=eMirP557D11BuedgSqjripDxOq1haIldNbnYNetV1bg,121
22
22
  bluecellulab/cell/__init__.py,sha256=Sbc0QOsJ8E7tSwf3q7fsXuE_SevBN6ZmoCVyyU5zfII,208
23
23
  bluecellulab/cell/cell_dict.py,sha256=VE7pi-NsMVRSmo-PSdbiLYmolDOu0Gc6JxFBkuQpFdk,1346
24
- bluecellulab/cell/core.py,sha256=YtF9sh8deBD2VdIJdki4ox-x-8UjRNpF1VSCIi_bNIc,37054
24
+ bluecellulab/cell/core.py,sha256=PKus_O8iREcU5-SDBjM7XbRUwromPz-K9imGo2Q11-4,37875
25
25
  bluecellulab/cell/injector.py,sha256=GB0pmyZMOHNV-lzd_t4cLoDE87S58IMbe7-qU1zBWvE,19033
26
26
  bluecellulab/cell/plotting.py,sha256=t2qDUabFtsBb-nJMkDh5UfsgW-wvQ2wfDwAVZ8-hWPo,4032
27
27
  bluecellulab/cell/random.py,sha256=pemekc11geRBKD8Ghb82tvKOZLfFWkUz1IKLc_NWg-A,1773
28
28
  bluecellulab/cell/recording.py,sha256=dekJspPb_5yrS6WR3aXtvZ6KWwMNbyhe5aIOVtNDHpY,342
29
29
  bluecellulab/cell/section_distance.py,sha256=QrNJ_avRSm-PFZfSg-FrcCqu-BNZNwcbECwMN9fY2ho,3908
30
+ bluecellulab/cell/section_tools.py,sha256=abIxZLyy0RFl7KVC3eR6gTxssK-y0nx0_qoj6eOVArU,3201
30
31
  bluecellulab/cell/serialized_sections.py,sha256=5JfLNgrUKdyYe4mKFIH2zMnT5QohNB9JYXbe475goEg,1543
31
32
  bluecellulab/cell/sonata_proxy.py,sha256=1FsMDosS7fbffgY_shaBKVIXjkmxL5aiPLlxcgeAUsc,1529
32
33
  bluecellulab/cell/stimuli_generator.py,sha256=DwWX8Keed1KgKExwlD4u-h4WUhEXcsG7XPjJTxqfZaQ,7129
@@ -75,9 +76,9 @@ bluecellulab/synapse/__init__.py,sha256=RW8XoAMXOvK7OG1nHl_q8jSEKLj9ZN4oWf2nY9HA
75
76
  bluecellulab/synapse/synapse_factory.py,sha256=NHwRMYMrnRVm_sHmyKTJ1bdoNmWZNU4UPOGu7FCi-PE,6987
76
77
  bluecellulab/synapse/synapse_types.py,sha256=zs_yBvGTH4QrbQF3nEViidyq1WM_ZcTSFdjUxB3khW0,16871
77
78
  bluecellulab/validation/validation.py,sha256=D35LE_131CtIzeeePAPz1OFzncGjAcvF02lSIvGvL2E,21331
78
- bluecellulab-2.6.67.dist-info/licenses/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
79
- bluecellulab-2.6.67.dist-info/licenses/LICENSE,sha256=dAMAR2Sud4Nead1wGFleKiwTZfkTNZbzmuGfcTKb3kg,11335
80
- bluecellulab-2.6.67.dist-info/METADATA,sha256=tj0QBiJYmRKvwjLntgoUR29HxbPgp4K2lvkX0W1vQdE,8331
81
- bluecellulab-2.6.67.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
82
- bluecellulab-2.6.67.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
83
- bluecellulab-2.6.67.dist-info/RECORD,,
79
+ bluecellulab-2.6.68.dist-info/licenses/AUTHORS.txt,sha256=EDs3H-2HXBojbma10psixk3C2rFiOCTIREi2ZAbXYNQ,179
80
+ bluecellulab-2.6.68.dist-info/licenses/LICENSE,sha256=dAMAR2Sud4Nead1wGFleKiwTZfkTNZbzmuGfcTKb3kg,11335
81
+ bluecellulab-2.6.68.dist-info/METADATA,sha256=D7ekc9VkRUId673jW-Gl8zfSp9VbBfcEvGqc4ANfWN0,8331
82
+ bluecellulab-2.6.68.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
83
+ bluecellulab-2.6.68.dist-info/top_level.txt,sha256=VSyEP8w9l3pXdRkyP_goeMwiNA8KWwitfAqUkveJkdQ,13
84
+ bluecellulab-2.6.68.dist-info/RECORD,,