dendrotweaks 0.3.1__py3-none-any.whl → 0.4.0__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.
- dendrotweaks/__init__.py +2 -2
- dendrotweaks/analysis/ephys_analysis.py +12 -8
- dendrotweaks/biophys/__init__.py +7 -0
- dendrotweaks/{membrane → biophys}/default_templates/NEURON_template.py +5 -3
- dendrotweaks/{membrane → biophys}/default_templates/default.py +2 -1
- dendrotweaks/{membrane → biophys}/default_templates/standard_channel.mod +5 -1
- dendrotweaks/{membrane → biophys}/groups.py +2 -2
- dendrotweaks/biophys/io/__init__.py +11 -0
- dendrotweaks/{membrane → biophys}/io/ast.py +6 -0
- dendrotweaks/{membrane → biophys}/io/code_generators.py +7 -1
- dendrotweaks/{membrane → biophys}/io/converter.py +3 -3
- dendrotweaks/{membrane → biophys}/io/factories.py +8 -6
- dendrotweaks/biophys/io/loader.py +190 -0
- dendrotweaks/{membrane → biophys}/io/parser.py +8 -8
- dendrotweaks/{membrane → biophys}/mechanisms.py +14 -10
- dendrotweaks/model.py +65 -32
- dendrotweaks/morphology/sec_trees.py +1 -1
- dendrotweaks/path_manager.py +9 -11
- dendrotweaks/simulators.py +82 -48
- dendrotweaks/stimuli/populations.py +11 -0
- {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/METADATA +2 -2
- dendrotweaks-0.4.0.dist-info/RECORD +56 -0
- {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/WHEEL +1 -1
- dendrotweaks/membrane/__init__.py +0 -6
- dendrotweaks/membrane/io/__init__.py +0 -11
- dendrotweaks/membrane/io/loader.py +0 -90
- dendrotweaks-0.3.1.dist-info/RECORD +0 -56
- /dendrotweaks/{membrane → biophys}/default_mod/AMPA.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_mod/AMPA_NMDA.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_mod/CaDyn.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_mod/GABAa.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_mod/Leak.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_mod/NMDA.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_mod/vecstim.mod +0 -0
- /dendrotweaks/{membrane → biophys}/default_templates/template_jaxley.py +0 -0
- /dendrotweaks/{membrane → biophys}/default_templates/template_jaxley_new.py +0 -0
- /dendrotweaks/{membrane → biophys}/distributions.py +0 -0
- /dendrotweaks/{membrane → biophys}/io/grammar.py +0 -0
- /dendrotweaks/{membrane → biophys}/io/reader.py +0 -0
- {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {dendrotweaks-0.3.1.dist-info → dendrotweaks-0.4.0.dist-info}/top_level.txt +0 -0
dendrotweaks/model.py
CHANGED
@@ -9,13 +9,13 @@ from dendrotweaks.morphology.point_trees import PointTree
|
|
9
9
|
from dendrotweaks.morphology.sec_trees import Section, SectionTree, Domain
|
10
10
|
from dendrotweaks.morphology.seg_trees import Segment, SegmentTree
|
11
11
|
from dendrotweaks.simulators import NEURONSimulator
|
12
|
-
from dendrotweaks.
|
13
|
-
from dendrotweaks.
|
14
|
-
from dendrotweaks.
|
15
|
-
from dendrotweaks.
|
12
|
+
from dendrotweaks.biophys.groups import SegmentGroup
|
13
|
+
from dendrotweaks.biophys.mechanisms import Mechanism, LeakChannel, CaDynamics
|
14
|
+
from dendrotweaks.biophys.io import create_channel, standardize_channel, create_standard_channel
|
15
|
+
from dendrotweaks.biophys.io import MODFileLoader
|
16
16
|
from dendrotweaks.morphology.io import create_point_tree, create_section_tree, create_segment_tree
|
17
17
|
from dendrotweaks.stimuli.iclamps import IClamp
|
18
|
-
from dendrotweaks.
|
18
|
+
from dendrotweaks.biophys.distributions import Distribution
|
19
19
|
from dendrotweaks.stimuli.populations import Population
|
20
20
|
from dendrotweaks.utils import calculate_lambda_f, dynamic_import
|
21
21
|
from dendrotweaks.utils import get_domain_color, timeit
|
@@ -343,11 +343,11 @@ class Model():
|
|
343
343
|
"""
|
344
344
|
return self.path_manager.list_files('morphology', extension=extension)
|
345
345
|
|
346
|
-
def
|
346
|
+
def list_biophys(self, extension='json'):
|
347
347
|
"""
|
348
|
-
List the
|
348
|
+
List the biophysical configurations available for the model.
|
349
349
|
"""
|
350
|
-
return self.path_manager.list_files('
|
350
|
+
return self.path_manager.list_files('biophys', extension=extension)
|
351
351
|
|
352
352
|
def list_mechanisms(self, extension='mod'):
|
353
353
|
"""
|
@@ -355,7 +355,7 @@ class Model():
|
|
355
355
|
"""
|
356
356
|
return self.path_manager.list_files('mod', extension=extension)
|
357
357
|
|
358
|
-
def
|
358
|
+
def list_stimuli(self, extension='json'):
|
359
359
|
"""
|
360
360
|
List the stimuli configurations available for the model.
|
361
361
|
"""
|
@@ -1287,7 +1287,7 @@ class Model():
|
|
1287
1287
|
print(f'Recording added to sec {sec} at loc {loc}.')
|
1288
1288
|
|
1289
1289
|
|
1290
|
-
def remove_recording(self, sec, loc):
|
1290
|
+
def remove_recording(self, sec, loc, var='v'):
|
1291
1291
|
"""
|
1292
1292
|
Remove a recording from the model.
|
1293
1293
|
|
@@ -1298,14 +1298,14 @@ class Model():
|
|
1298
1298
|
loc : float
|
1299
1299
|
The location along the normalized section length to remove the recording from.
|
1300
1300
|
"""
|
1301
|
-
self.simulator.remove_recording(sec, loc)
|
1301
|
+
self.simulator.remove_recording(sec, loc, var)
|
1302
1302
|
|
1303
1303
|
|
1304
|
-
def remove_all_recordings(self):
|
1304
|
+
def remove_all_recordings(self, var=None):
|
1305
1305
|
"""
|
1306
1306
|
Remove all recordings from the model.
|
1307
1307
|
"""
|
1308
|
-
self.simulator.remove_all_recordings()
|
1308
|
+
self.simulator.remove_all_recordings(var=var)
|
1309
1309
|
|
1310
1310
|
|
1311
1311
|
def run(self, duration=300):
|
@@ -1598,7 +1598,7 @@ class Model():
|
|
1598
1598
|
'name': self.name,
|
1599
1599
|
},
|
1600
1600
|
'd_lambda': self.d_lambda,
|
1601
|
-
'domains': {domain: list(mechs) for domain, mechs in self.domains_to_mechs.items()},
|
1601
|
+
'domains': {domain: sorted(list(mechs)) for domain, mechs in self.domains_to_mechs.items()},
|
1602
1602
|
'groups': [
|
1603
1603
|
group.to_dict() for group in self._groups
|
1604
1604
|
],
|
@@ -1657,9 +1657,9 @@ class Model():
|
|
1657
1657
|
|
1658
1658
|
|
1659
1659
|
|
1660
|
-
def
|
1660
|
+
def export_biophys(self, file_name, **kwargs):
|
1661
1661
|
"""
|
1662
|
-
Export the
|
1662
|
+
Export the biophysical properties of the model to a JSON file.
|
1663
1663
|
|
1664
1664
|
Parameters
|
1665
1665
|
----------
|
@@ -1669,16 +1669,18 @@ class Model():
|
|
1669
1669
|
Additional keyword arguments to pass to `json.dump`.
|
1670
1670
|
"""
|
1671
1671
|
|
1672
|
-
path_to_json = self.path_manager.get_file_path('
|
1672
|
+
path_to_json = self.path_manager.get_file_path('biophys', file_name, extension='json')
|
1673
|
+
if not kwargs.get('indent'):
|
1674
|
+
kwargs['indent'] = 4
|
1673
1675
|
|
1674
1676
|
data = self.to_dict()
|
1675
1677
|
with open(path_to_json, 'w') as f:
|
1676
1678
|
json.dump(data, f, **kwargs)
|
1677
1679
|
|
1678
1680
|
|
1679
|
-
def
|
1681
|
+
def load_biophys(self, file_name, recompile=True):
|
1680
1682
|
"""
|
1681
|
-
Load the
|
1683
|
+
Load the biophysical properties of the model from a JSON file.
|
1682
1684
|
|
1683
1685
|
Parameters
|
1684
1686
|
----------
|
@@ -1688,13 +1690,18 @@ class Model():
|
|
1688
1690
|
Whether to recompile the mechanisms after loading. Default is True.
|
1689
1691
|
"""
|
1690
1692
|
self.add_default_mechanisms()
|
1691
|
-
|
1693
|
+
|
1692
1694
|
|
1693
|
-
path_to_json = self.path_manager.get_file_path('
|
1695
|
+
path_to_json = self.path_manager.get_file_path('biophys', file_name, extension='json')
|
1694
1696
|
|
1695
1697
|
with open(path_to_json, 'r') as f:
|
1696
1698
|
data = json.load(f)
|
1697
1699
|
|
1700
|
+
for mech_name in {mech for mechs in data['domains'].values() for mech in mechs}:
|
1701
|
+
if mech_name in ['Leak', 'CaDyn', 'Independent']:
|
1702
|
+
continue
|
1703
|
+
self.add_mechanism(mech_name, dir_name='mod', recompile=recompile)
|
1704
|
+
|
1698
1705
|
self.from_dict(data)
|
1699
1706
|
|
1700
1707
|
|
@@ -1715,6 +1722,14 @@ class Model():
|
|
1715
1722
|
**self.simulator.to_dict(),
|
1716
1723
|
},
|
1717
1724
|
'stimuli': {
|
1725
|
+
'recordings': [
|
1726
|
+
{
|
1727
|
+
'name': f'rec_{i}',
|
1728
|
+
'var': var
|
1729
|
+
}
|
1730
|
+
for var, recs in self.simulator.recordings.items()
|
1731
|
+
for i, _ in enumerate(recs)
|
1732
|
+
],
|
1718
1733
|
'iclamps': [
|
1719
1734
|
{
|
1720
1735
|
'name': f'iclamp_{i}',
|
@@ -1743,11 +1758,16 @@ class Model():
|
|
1743
1758
|
"""
|
1744
1759
|
|
1745
1760
|
rec_data = {
|
1746
|
-
'type': [
|
1747
|
-
'idx': [
|
1748
|
-
'sec_idx': [
|
1749
|
-
'loc': [
|
1761
|
+
'type': [],
|
1762
|
+
'idx': [],
|
1763
|
+
'sec_idx': [],
|
1764
|
+
'loc': [],
|
1750
1765
|
}
|
1766
|
+
for var, recs in self.simulator.recordings.items():
|
1767
|
+
rec_data['type'].extend(['rec'] * len(recs))
|
1768
|
+
rec_data['idx'].extend([i for i in range(len(recs))])
|
1769
|
+
rec_data['sec_idx'].extend([seg._section.idx for seg in recs])
|
1770
|
+
rec_data['loc'].extend([seg.x for seg in recs])
|
1751
1771
|
|
1752
1772
|
iclamp_data = {
|
1753
1773
|
'type': ['iclamp'] * len(self.iclamps),
|
@@ -1776,6 +1796,7 @@ class Model():
|
|
1776
1796
|
pd.DataFrame(iclamp_data),
|
1777
1797
|
pd.DataFrame(synapses_data)
|
1778
1798
|
], ignore_index=True)
|
1799
|
+
df['idx'] = df['idx'].astype(int)
|
1779
1800
|
df['sec_idx'] = df['sec_idx'].astype(int)
|
1780
1801
|
if path_to_csv: df.to_csv(path_to_csv, index=False)
|
1781
1802
|
|
@@ -1797,6 +1818,8 @@ class Model():
|
|
1797
1818
|
|
1798
1819
|
data = self.stimuli_to_dict()
|
1799
1820
|
|
1821
|
+
if not kwargs.get('indent'):
|
1822
|
+
kwargs['indent'] = 4
|
1800
1823
|
with open(path_to_json, 'w') as f:
|
1801
1824
|
json.dump(data, f, **kwargs)
|
1802
1825
|
|
@@ -1827,13 +1850,9 @@ class Model():
|
|
1827
1850
|
|
1828
1851
|
self.simulator.from_dict(data['simulation'])
|
1829
1852
|
|
1830
|
-
#
|
1831
|
-
|
1832
|
-
|
1833
|
-
for i, row in df_recs.iterrows():
|
1834
|
-
self.add_recording(
|
1835
|
-
self.sec_tree.sections[row['sec_idx']], row['loc']
|
1836
|
-
)
|
1853
|
+
# Clear all stimuli and recordings
|
1854
|
+
self.remove_all_stimuli()
|
1855
|
+
self.remove_all_recordings()
|
1837
1856
|
|
1838
1857
|
# IClamps -----------------------------------------------------------
|
1839
1858
|
|
@@ -1875,6 +1894,20 @@ class Model():
|
|
1875
1894
|
pop.update_input_params(**pop_data['input_params'])
|
1876
1895
|
self._add_population(pop)
|
1877
1896
|
|
1897
|
+
# Recordings ---------------------------------------------------------
|
1898
|
+
|
1899
|
+
df_recs = df_stimuli[df_stimuli['type'] == 'rec'].reset_index(drop=True, inplace=False)
|
1900
|
+
for i, row in df_recs.iterrows():
|
1901
|
+
# TODO: This conditional statement is to account for a recent change
|
1902
|
+
# in the JSON structure. It should be removed in the future.
|
1903
|
+
if data['stimuli'].get('recordings'):
|
1904
|
+
var = data['stimuli']['recordings'][i]['var']
|
1905
|
+
else:
|
1906
|
+
var = 'v'
|
1907
|
+
self.add_recording(
|
1908
|
+
self.sec_tree.sections[row['sec_idx']], row['loc'], var
|
1909
|
+
)
|
1910
|
+
|
1878
1911
|
|
1879
1912
|
def export_to_NEURON(self, file_name, include_kinetic_params=True):
|
1880
1913
|
"""
|
@@ -770,7 +770,7 @@ class SectionTree(Tree):
|
|
770
770
|
"""
|
771
771
|
|
772
772
|
unique_domain_names = set([sec.domain for sec in self.sections])
|
773
|
-
self.domains = {name: Domain(name) for name in unique_domain_names}
|
773
|
+
self.domains = {name: Domain(name) for name in sorted(unique_domain_names)}
|
774
774
|
|
775
775
|
for sec in self.sections:
|
776
776
|
self.domains[sec.domain].add_section(sec)
|
dendrotweaks/path_manager.py
CHANGED
@@ -26,9 +26,9 @@ class PathManager:
|
|
26
26
|
'default_mod': os.path.join(self.path_to_data, 'Default'),
|
27
27
|
'templates': os.path.join(self.path_to_data, 'Templates'),
|
28
28
|
'morphology': os.path.join(self.path_to_model, 'morphology'),
|
29
|
-
'
|
30
|
-
'mod': os.path.join(self.path_to_model, '
|
31
|
-
'python': os.path.join(self.path_to_model, '
|
29
|
+
'biophys': os.path.join(self.path_to_model, 'biophys'),
|
30
|
+
'mod': os.path.join(self.path_to_model, 'biophys', 'mod'),
|
31
|
+
'python': os.path.join(self.path_to_model, 'biophys', 'python'),
|
32
32
|
'stimuli': os.path.join(self.path_to_model, 'stimuli'),
|
33
33
|
}
|
34
34
|
self._ensure_paths_exist()
|
@@ -61,8 +61,7 @@ class PathManager:
|
|
61
61
|
"""
|
62
62
|
Copy default mod files to the data directory.
|
63
63
|
"""
|
64
|
-
|
65
|
-
DEFAULT_MOD_DIR = os.path.join(os.path.dirname(__file__), 'membrane', 'default_mod')
|
64
|
+
DEFAULT_MOD_DIR = os.path.join(os.path.dirname(__file__), 'biophys', 'default_mod')
|
66
65
|
for file_name in os.listdir(DEFAULT_MOD_DIR):
|
67
66
|
source = os.path.join(DEFAULT_MOD_DIR, file_name)
|
68
67
|
destination = os.path.join(self.paths['default_mod'], file_name)
|
@@ -72,8 +71,7 @@ class PathManager:
|
|
72
71
|
"""
|
73
72
|
Copy template files to the data directory.
|
74
73
|
"""
|
75
|
-
|
76
|
-
TEMPLATES_DIR = os.path.join(os.path.dirname(__file__), 'membrane', 'default_templates')
|
74
|
+
TEMPLATES_DIR = os.path.join(os.path.dirname(__file__), 'biophys', 'default_templates')
|
77
75
|
for file_name in os.listdir(TEMPLATES_DIR):
|
78
76
|
source = os.path.join(TEMPLATES_DIR, file_name)
|
79
77
|
destination = os.path.join(self.paths['templates'], file_name)
|
@@ -169,16 +167,16 @@ class PathManager:
|
|
169
167
|
return self.list_files('stimuli', extension=extension)
|
170
168
|
|
171
169
|
|
172
|
-
def
|
170
|
+
def list_biophys(self):
|
173
171
|
"""
|
174
|
-
List all
|
172
|
+
List all biophysics files.
|
175
173
|
|
176
174
|
Returns
|
177
175
|
-------
|
178
176
|
List[str]
|
179
|
-
A list of
|
177
|
+
A list of biophysics file names.
|
180
178
|
"""
|
181
|
-
return self.list_files('
|
179
|
+
return self.list_files('biophys', extension='.json')
|
182
180
|
|
183
181
|
|
184
182
|
def print_directory_tree(self, subfolder=None) -> None:
|
dendrotweaks/simulators.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from collections import defaultdict
|
2
2
|
import warnings
|
3
|
+
from functools import cached_property
|
3
4
|
|
4
5
|
import matplotlib.pyplot as plt
|
5
6
|
import neuron
|
@@ -35,26 +36,47 @@ class Simulator:
|
|
35
36
|
A generic simulator class.
|
36
37
|
"""
|
37
38
|
def __init__(self):
|
38
|
-
self.
|
39
|
-
self.t = None
|
39
|
+
self._t = None
|
40
40
|
self.dt = None
|
41
|
-
self.
|
41
|
+
self._recordings = {'v': {}}
|
42
42
|
|
43
|
-
def
|
43
|
+
def plot_var(self, var='v', ax=None, segments=None, **kwargs):
|
44
|
+
if self._t is None:
|
45
|
+
raise ValueError('Simulation has not been run yet.')
|
46
|
+
if var not in self.recordings:
|
47
|
+
raise ValueError(f'Variable {var} not recorded.')
|
44
48
|
if ax is None:
|
45
49
|
fig, ax = plt.subplots()
|
46
50
|
if segments is None:
|
47
|
-
segments = self.recordings.keys()
|
48
|
-
for seg,
|
51
|
+
segments = self.recordings[var].keys()
|
52
|
+
for seg, x in self.recordings[var].items():
|
49
53
|
if segments and seg not in segments:
|
50
54
|
continue
|
51
|
-
ax.plot(self.t,
|
52
|
-
|
55
|
+
ax.plot(self.t, x, label=f'{var} {seg.domain} {seg.idx}', **kwargs)
|
53
56
|
if len(segments) < 10:
|
54
57
|
ax.legend()
|
55
|
-
# ax.set_ylim(-100, 60)
|
56
58
|
ax.set_xlabel('Time (ms)')
|
57
|
-
|
59
|
+
if var == 'v':
|
60
|
+
ax.set_ylabel('Voltage (mV)')
|
61
|
+
elif var.startswith('i_'):
|
62
|
+
ax.set_ylabel('Current (nA)')
|
63
|
+
return ax
|
64
|
+
|
65
|
+
def plot_voltage(self, **kwargs):
|
66
|
+
"""
|
67
|
+
Plot the recorded voltages.
|
68
|
+
"""
|
69
|
+
self.plot_var('v', **kwargs)
|
70
|
+
|
71
|
+
def plot_currents(self, **kwargs):
|
72
|
+
"""
|
73
|
+
Plot the recorded currents.
|
74
|
+
"""
|
75
|
+
ax = kwargs.pop('ax', None)
|
76
|
+
for var in self.recordings:
|
77
|
+
if var.startswith('i_'):
|
78
|
+
ax = self.plot_var(var, ax=ax, **kwargs)
|
79
|
+
|
58
80
|
|
59
81
|
|
60
82
|
class NEURONSimulator(Simulator):
|
@@ -88,10 +110,33 @@ class NEURONSimulator(Simulator):
|
|
88
110
|
self.temperature = temperature
|
89
111
|
self.v_init = v_init * mV
|
90
112
|
self._duration = 300
|
113
|
+
|
91
114
|
|
92
115
|
self.dt = dt
|
93
116
|
self._cvode = cvode
|
94
117
|
|
118
|
+
@cached_property
|
119
|
+
def recordings(self):
|
120
|
+
return {
|
121
|
+
var:{ seg: vec.to_python() for seg, vec in recs.items() }
|
122
|
+
for var, recs in self._recordings.items()
|
123
|
+
}
|
124
|
+
|
125
|
+
@cached_property
|
126
|
+
def t(self):
|
127
|
+
return self._t.to_python()
|
128
|
+
|
129
|
+
def _clean_cache(self):
|
130
|
+
"""
|
131
|
+
Clean the cache of the simulator.
|
132
|
+
"""
|
133
|
+
try:
|
134
|
+
del self.recordings
|
135
|
+
del self.t
|
136
|
+
except AttributeError:
|
137
|
+
# Property hasn't been accessed yet, so no need to delete
|
138
|
+
pass
|
139
|
+
|
95
140
|
|
96
141
|
def add_recording(self, sec, loc, var='v'):
|
97
142
|
"""
|
@@ -107,11 +152,16 @@ class NEURONSimulator(Simulator):
|
|
107
152
|
The variable to record. Default is 'v' (voltage).
|
108
153
|
"""
|
109
154
|
seg = sec(loc)
|
110
|
-
if
|
111
|
-
|
112
|
-
self.
|
113
|
-
|
114
|
-
|
155
|
+
if not hasattr(seg._ref, f'_ref_{var}'):
|
156
|
+
raise ValueError(f'Segment {seg} does not have variable {var}.')
|
157
|
+
if self._recordings.get(var, {}).get(seg):
|
158
|
+
self.remove_recording(sec, loc, var)
|
159
|
+
if var not in self._recordings:
|
160
|
+
self._recordings[var] = {}
|
161
|
+
self._recordings[var][seg] = h.Vector().record(getattr(seg._ref, f'_ref_{var}'))
|
162
|
+
self._clean_cache()
|
163
|
+
|
164
|
+
def remove_recording(self, sec, loc, var='v'):
|
115
165
|
"""
|
116
166
|
Remove a recording from the simulator.
|
117
167
|
|
@@ -123,20 +173,23 @@ class NEURONSimulator(Simulator):
|
|
123
173
|
The location along the normalized section length to remove the recording from.
|
124
174
|
"""
|
125
175
|
seg = sec(loc)
|
126
|
-
if self.
|
127
|
-
self.
|
128
|
-
self.
|
129
|
-
|
130
|
-
|
176
|
+
if self._recordings[var].get(seg):
|
177
|
+
self._recordings[var][seg] = None
|
178
|
+
self._recordings[var].pop(seg)
|
179
|
+
if not self._recordings[var]:
|
180
|
+
self._recordings.pop(var)
|
181
|
+
self._clean_cache()
|
182
|
+
|
183
|
+
def remove_all_recordings(self, var=None):
|
131
184
|
"""
|
132
185
|
Remove all recordings from the simulator.
|
133
186
|
"""
|
134
|
-
|
135
|
-
|
136
|
-
self.
|
137
|
-
|
138
|
-
|
139
|
-
|
187
|
+
variables = [var] if var else list(self._recordings.keys())
|
188
|
+
for variable in variables:
|
189
|
+
for seg in list(self._recordings.get(variable, {}).keys()):
|
190
|
+
self.remove_recording(seg._section, seg.x, variable)
|
191
|
+
if self._recordings.get(variable):
|
192
|
+
warnings.warn(f'Not all recordings were removed for variable {variable}: {self._recordings}')
|
140
193
|
|
141
194
|
|
142
195
|
def _init_simulation(self):
|
@@ -161,35 +214,16 @@ class NEURONSimulator(Simulator):
|
|
161
214
|
duration : float
|
162
215
|
The duration of the simulation in milliseconds.
|
163
216
|
"""
|
164
|
-
self._duration = duration
|
165
|
-
|
166
|
-
|
167
|
-
# vs = list(self.recordings.values())
|
168
|
-
Is = []
|
169
217
|
|
170
|
-
|
171
|
-
# # v = h.Vector().record(seg._ref_v)
|
172
|
-
# vs.append(v)
|
218
|
+
self._clean_cache()
|
173
219
|
|
174
|
-
|
220
|
+
self._duration = duration
|
175
221
|
|
176
|
-
|
177
|
-
# pass
|
178
|
-
# else:
|
179
|
-
# for seg in self.recordings.keys():
|
180
|
-
# if getattr(seg, f'_ref_i_{self.ch.suffix}', None) is None:
|
181
|
-
# logger.warning(
|
182
|
-
# f'No current recorded for {self.ch.suffix} at {seg}. Make i a RANGE variable in mod file.')
|
183
|
-
# continue
|
184
|
-
# I = h.Vector().record(getattr(seg, f'_ref_i_{self.ch.suffix}'))
|
185
|
-
# Is.append(I)
|
222
|
+
self._t = h.Vector().record(h._ref_t)
|
186
223
|
|
187
224
|
self._init_simulation()
|
188
225
|
|
189
226
|
h.continuerun(duration * ms)
|
190
|
-
|
191
|
-
self.t = t.to_python()
|
192
|
-
self.vs = {seg: v.to_python() for seg, v in self.recordings.items()}
|
193
227
|
|
194
228
|
|
195
229
|
def to_dict(self):
|
@@ -123,6 +123,17 @@ class Population():
|
|
123
123
|
spike_times[syn].extend(syn.spike_times)
|
124
124
|
return dict(spike_times)
|
125
125
|
|
126
|
+
@property
|
127
|
+
def n_per_seg(self):
|
128
|
+
"""
|
129
|
+
Return the number of synapses per segment.
|
130
|
+
"""
|
131
|
+
n_per_seg = {seg: 0 for seg in self.segments}
|
132
|
+
for (sec, loc), syns in self.synapses.items():
|
133
|
+
seg = sec(loc)
|
134
|
+
n_per_seg[seg] += len(syns)
|
135
|
+
return dict(n_per_seg)
|
136
|
+
|
126
137
|
|
127
138
|
def update_kinetic_params(self, **params):
|
128
139
|
"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: dendrotweaks
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Summary: A toolbox for exploring dendritic dynamics
|
5
5
|
Home-page: https://dendrotweaks.dendrites.gr
|
6
6
|
Author: Roman Makarov
|
@@ -15,7 +15,7 @@ Classifier: Operating System :: OS Independent
|
|
15
15
|
Requires-Python: >=3.9
|
16
16
|
Description-Content-Type: text/markdown
|
17
17
|
License-File: LICENSE
|
18
|
-
Requires-Dist: neuron>=8.2.6
|
18
|
+
Requires-Dist: neuron>=8.2.6; sys_platform == "linux" or sys_platform == "darwin"
|
19
19
|
Requires-Dist: neuron-reduce==0.0.7
|
20
20
|
Requires-Dist: numpy<2.0.0
|
21
21
|
Requires-Dist: pandas
|
@@ -0,0 +1,56 @@
|
|
1
|
+
dendrotweaks/__init__.py,sha256=qmlQDMHQGSD70naZme_cEMgale9T5OH6VqjdxhznouM,384
|
2
|
+
dendrotweaks/model.py,sha256=XX4WPaHPYUzm9CF4S6lUCDc_a1mORJaEbwtLexqEKCQ,68796
|
3
|
+
dendrotweaks/model_io.py,sha256=xwXKMcUle-Y0HoWFYVZu3G8v4pdQXmeaDfl2Xi65eHw,2137
|
4
|
+
dendrotweaks/path_manager.py,sha256=dai5o6UA0nk-ubwKWRu4LFdDBO77zW_SsMf6k0MLBiI,8703
|
5
|
+
dendrotweaks/simulators.py,sha256=ADiXPqcWZ7oLQfMMnhgQNpgCW-NE6lBb5hZCQACSIkM,7237
|
6
|
+
dendrotweaks/utils.py,sha256=jaUJNb39Bsevg3WJByP56bO7CLj1wzlh-uGZl-lxi1I,7131
|
7
|
+
dendrotweaks/analysis/__init__.py,sha256=SEYpoQ5iXiQXyHB20-IAdDHYI-7CR5GYFXIwr-O05Ug,858
|
8
|
+
dendrotweaks/analysis/ephys_analysis.py,sha256=Caiww27p9dnL5_27OmZ95AZ_OmefvImAPyItsJMSdmA,14320
|
9
|
+
dendrotweaks/analysis/morphometric_analysis.py,sha256=5zohjGssyx-wezI-yY3Q-kYM_wzAQLLFBJ9Xk950_JY,3571
|
10
|
+
dendrotweaks/biophys/__init__.py,sha256=k0o2xwyoaJUb1lfO9OHtqxheNP6R-Ya5o0g-bJOdCZg,360
|
11
|
+
dendrotweaks/biophys/distributions.py,sha256=ADPFPA-CN7AbRJj0Ry4TxFZJhdYXJm87iIGWZSDr5vI,10299
|
12
|
+
dendrotweaks/biophys/groups.py,sha256=Kze8ft8EYFXWW6zJhhbpWQUUt82L47g2IbB-5WpsWrY,3481
|
13
|
+
dendrotweaks/biophys/mechanisms.py,sha256=j9uygcwkK6Z_08hpTHax40Wn-eV4V_k_on_KyPDnO90,18520
|
14
|
+
dendrotweaks/biophys/default_mod/AMPA.mod,sha256=HY_pWzYvaSDV-w7qruenG2mnll8v79s40HFHjUCIi4U,980
|
15
|
+
dendrotweaks/biophys/default_mod/AMPA_NMDA.mod,sha256=ztv2ePUiEQZ93-23FTkGO2DC91rehQuqo0NUIbHZ368,2318
|
16
|
+
dendrotweaks/biophys/default_mod/CaDyn.mod,sha256=gwc69K_rxu2w_mV7CnOSOnVaCMc8Z-MfdBFf6lAj4kg,1298
|
17
|
+
dendrotweaks/biophys/default_mod/GABAa.mod,sha256=jdGRid-Wzw4y9kHvq74oSMogLhSiS-Ac2DDaLOrxVi8,983
|
18
|
+
dendrotweaks/biophys/default_mod/Leak.mod,sha256=u0lwMYGgl5kNZN5W4N6YHgRSeVxb-z2oM9fqou5rCV8,420
|
19
|
+
dendrotweaks/biophys/default_mod/NMDA.mod,sha256=tT4Q5UPoeztXcQ45uZc2PUO3-8OkDLCmrS7WDsn1yQQ,1185
|
20
|
+
dendrotweaks/biophys/default_mod/vecstim.mod,sha256=iSpJgR96O2Z3pLNUFIsZ7YJ529ncKUBaZqDJvA0_oV0,965
|
21
|
+
dendrotweaks/biophys/default_templates/NEURON_template.py,sha256=MWSv2fLKGJxdt2zfSO0b74peuBC8U9j_S6AwM5URXts,14945
|
22
|
+
dendrotweaks/biophys/default_templates/default.py,sha256=7HEbR2GJEOhgiox1QtZUEuHi5ihNAHDLsXQiQk980tI,2201
|
23
|
+
dendrotweaks/biophys/default_templates/standard_channel.mod,sha256=sw80c-JyqfXNA7c7v7pZGLY-0MgFUvd3bPvJcAGXNSk,2923
|
24
|
+
dendrotweaks/biophys/default_templates/template_jaxley.py,sha256=t-GsCSUyQ7rDoaLmyuWd9bIxB8W3bCqJdnikD59EVvI,3676
|
25
|
+
dendrotweaks/biophys/default_templates/template_jaxley_new.py,sha256=I62KhnOYNV1bT-nPsDTxjIISYmDcso2X8rnsos28nYs,3631
|
26
|
+
dendrotweaks/biophys/io/__init__.py,sha256=kkmQ4L0SatI3lWd3qE8KqOIKd7x3G2OnqAAW93sWWCU,575
|
27
|
+
dendrotweaks/biophys/io/ast.py,sha256=7x_Kxz1qoQHZeIjovUNyVuKgUo4vAFKm-bd4hn9n1CI,6078
|
28
|
+
dendrotweaks/biophys/io/code_generators.py,sha256=yg0Do1XLM_rIXk4i_FibJGfkWOt-GN0lq5dOCD4D3pk,11702
|
29
|
+
dendrotweaks/biophys/io/converter.py,sha256=5yrPJhyZbuwV7tTGoacnNOvmRdVgXPIyGfiR0PyOVzg,3371
|
30
|
+
dendrotweaks/biophys/io/factories.py,sha256=j1Hi2u-NTFFL8ElRYlgGVNHRcfKWH6o5GfKvraMTlwM,5020
|
31
|
+
dendrotweaks/biophys/io/grammar.py,sha256=TJLTDlr8Ajp3J9DJ4IvulOCcpUkYr7HnoI0TGnNuEPc,11677
|
32
|
+
dendrotweaks/biophys/io/loader.py,sha256=Wv9ZkEDyA3MkCdV0sMeRnBffg2WAI7yTV3r6C412GiY,6378
|
33
|
+
dendrotweaks/biophys/io/parser.py,sha256=boT27lFrn5LYrJnkZFs0SwrZZrkSkwO8efqGPJ4Qj0I,17914
|
34
|
+
dendrotweaks/biophys/io/reader.py,sha256=JWm5WM9illvSfDkhWEmWBcj8Y7PSi8zeZX9j1ARUHVU,6576
|
35
|
+
dendrotweaks/morphology/__init__.py,sha256=aqJTQOpRVOYcbWqZ2q4e-Oy735r9_ubW-uE_5cFZVtI,323
|
36
|
+
dendrotweaks/morphology/domains.py,sha256=Y4txcGdBdl2aK1DfbTRziNtDyd6bChczwpCWE7lTFzg,2391
|
37
|
+
dendrotweaks/morphology/point_trees.py,sha256=5dUPaQXYPdJbWoD3pFI2DV2XnuFRhB5d0wTBlfmmIeI,21600
|
38
|
+
dendrotweaks/morphology/sec_trees.py,sha256=4EU8YbYsi1Pr_n7vkFuKQtIIWbJwP-8Q_epmioEXAIw,36902
|
39
|
+
dendrotweaks/morphology/seg_trees.py,sha256=uwL1X9qeFNyJVHua1I3rhp0fLSRrS2TAVyb1Fnw4RwQ,3595
|
40
|
+
dendrotweaks/morphology/trees.py,sha256=NrNvPMR-U0clt63eqwVJqU0H8NJgY53QGA_BkdcwkQI,16033
|
41
|
+
dendrotweaks/morphology/io/__init__.py,sha256=gAZqZdf5VKPb6ksK8Lwt7MbTAq8TDP8uq3Vs_ebNFEY,324
|
42
|
+
dendrotweaks/morphology/io/factories.py,sha256=NngNINw73diGK7fud314JzWVhxv2aYLuA9wUuQA0Diw,6344
|
43
|
+
dendrotweaks/morphology/io/reader.py,sha256=hW3c541WtG1rNag_YreEhvrLzm8-OTtw0fQREeHDthM,1913
|
44
|
+
dendrotweaks/morphology/io/validation.py,sha256=lVkYw9y9yG5QpRh_N0YQ3FbZwuSUsQfSqJTMumMcDdc,7872
|
45
|
+
dendrotweaks/morphology/reduce/__init__.py,sha256=p6Mg3KDHxTt8S4DtI0m7L7MqV6dS2pdIYAwB7B-toVw,921
|
46
|
+
dendrotweaks/morphology/reduce/reduce.py,sha256=5czZDrG3xsvHn3c_tbYhUOlXgST989-RS-ntbhlvvA0,6361
|
47
|
+
dendrotweaks/morphology/reduce/reduced_cylinder.py,sha256=jGJ4J-amukRr-3DPirVR5pzNO-6H7_sZF1N_X57ZGdw,5132
|
48
|
+
dendrotweaks/stimuli/__init__.py,sha256=bFfSEZhCVpwOVEBgLe65iiY3SdpjKPhyLemC1z5OX9I,153
|
49
|
+
dendrotweaks/stimuli/iclamps.py,sha256=NjkhhwZKJR1f_g3N9BVxMVoO9ubBk5WkQ6h9Bnf9xgA,1681
|
50
|
+
dendrotweaks/stimuli/populations.py,sha256=y85v8smiMifINIqXm1O3mOINAlDTz-SPGLS78alhX5A,8325
|
51
|
+
dendrotweaks/stimuli/synapses.py,sha256=g4MgWTske2TZ2i9FIIOE8-KXNx_3dWa3zEhB2rcqYig,5470
|
52
|
+
dendrotweaks-0.4.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
53
|
+
dendrotweaks-0.4.0.dist-info/METADATA,sha256=9AAcxk2ZzIvqUOQg7hNf0Tw1an2EYJLl76gSI21WAKM,2740
|
54
|
+
dendrotweaks-0.4.0.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
|
55
|
+
dendrotweaks-0.4.0.dist-info/top_level.txt,sha256=OzT_2BSI5j5zxC447K6Y-0W-GHbued7iX-_hFGAKMxY,13
|
56
|
+
dendrotweaks-0.4.0.dist-info/RECORD,,
|
@@ -1,6 +0,0 @@
|
|
1
|
-
from dendrotweaks.membrane.mechanisms import Mechanism, IonChannel, CaDynamics, StandardIonChannel, LeakChannel
|
2
|
-
from dendrotweaks.membrane.mechanisms import LeakChannel
|
3
|
-
from dendrotweaks.membrane.groups import SegmentGroup
|
4
|
-
from dendrotweaks.membrane.distributions import Distribution
|
5
|
-
|
6
|
-
import dendrotweaks.membrane.io as io
|
@@ -1,11 +0,0 @@
|
|
1
|
-
from dendrotweaks.membrane.io.loader import MODFileLoader
|
2
|
-
from dendrotweaks.membrane.io.converter import MODFileConverter
|
3
|
-
|
4
|
-
from dendrotweaks.membrane.io.reader import MODFileReader
|
5
|
-
from dendrotweaks.membrane.io.parser import MODFileParser
|
6
|
-
from dendrotweaks.membrane.io.code_generators import PythonCodeGenerator
|
7
|
-
from dendrotweaks.membrane.io.code_generators import NMODLCodeGenerator
|
8
|
-
|
9
|
-
from dendrotweaks.membrane.io.factories import create_channel
|
10
|
-
from dendrotweaks.membrane.io.factories import create_standard_channel
|
11
|
-
from dendrotweaks.membrane.io.factories import standardize_channel
|