bmtool 0.7.1.7__py3-none-any.whl → 0.7.2.1__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.
- bmtool/analysis/entrainment.py +1 -81
- bmtool/analysis/spikes.py +55 -6
- bmtool/bmplot/connections.py +255 -153
- bmtool/bmplot/entrainment.py +525 -28
- bmtool/bmplot/spikes.py +118 -5
- bmtool/synapses.py +3 -3
- bmtool/util/util.py +3 -0
- {bmtool-0.7.1.7.dist-info → bmtool-0.7.2.1.dist-info}/METADATA +1 -1
- {bmtool-0.7.1.7.dist-info → bmtool-0.7.2.1.dist-info}/RECORD +13 -13
- {bmtool-0.7.1.7.dist-info → bmtool-0.7.2.1.dist-info}/WHEEL +1 -1
- {bmtool-0.7.1.7.dist-info → bmtool-0.7.2.1.dist-info}/entry_points.txt +0 -0
- {bmtool-0.7.1.7.dist-info → bmtool-0.7.2.1.dist-info}/licenses/LICENSE +0 -0
- {bmtool-0.7.1.7.dist-info → bmtool-0.7.2.1.dist-info}/top_level.txt +0 -0
bmtool/bmplot/spikes.py
CHANGED
@@ -20,6 +20,7 @@ def raster(
|
|
20
20
|
tstart: Optional[float] = None,
|
21
21
|
tstop: Optional[float] = None,
|
22
22
|
color_map: Optional[Dict[str, str]] = None,
|
23
|
+
dot_size: Optional[float] = 0.3,
|
23
24
|
) -> Axes:
|
24
25
|
"""
|
25
26
|
Plots a raster plot of neural spikes, with different colors for each population.
|
@@ -40,6 +41,8 @@ def raster(
|
|
40
41
|
Stop time for filtering spikes; only spikes with timestamps less than `tstop` will be plotted.
|
41
42
|
color_map : dict, optional
|
42
43
|
Dictionary specifying colors for each population. Keys should be population names, and values should be color values.
|
44
|
+
dot_size: float, optional
|
45
|
+
Size of the dot to display on the scatterplot
|
43
46
|
|
44
47
|
Returns:
|
45
48
|
-------
|
@@ -53,6 +56,7 @@ def raster(
|
|
53
56
|
- If `color_map` is provided, it should contain colors for all unique `pop_name` values in `spikes_df`.
|
54
57
|
"""
|
55
58
|
# Initialize axes if none provided
|
59
|
+
sns.set_style("whitegrid")
|
56
60
|
if ax is None:
|
57
61
|
_, ax = plt.subplots(1, 1)
|
58
62
|
|
@@ -102,15 +106,17 @@ def raster(
|
|
102
106
|
raise ValueError(f"color_map is missing colors for populations: {missing_colors}")
|
103
107
|
|
104
108
|
# Plot each population with its specified or generated color
|
109
|
+
legend_handles = []
|
105
110
|
for pop_name, group in spikes_df.groupby(groupby):
|
106
|
-
ax.scatter(
|
107
|
-
|
108
|
-
)
|
111
|
+
ax.scatter(group["timestamps"], group["node_ids"], color=color_map[pop_name], s=dot_size)
|
112
|
+
# Dummy scatter for consistent legend appearance
|
113
|
+
handle = ax.scatter([], [], color=color_map[pop_name], label=pop_name, s=20)
|
114
|
+
legend_handles.append(handle)
|
109
115
|
|
110
116
|
# Label axes
|
111
117
|
ax.set_xlabel("Time")
|
112
118
|
ax.set_ylabel("Node ID")
|
113
|
-
ax.legend(title="Population", loc="upper right", framealpha=0.9
|
119
|
+
ax.legend(handles=legend_handles, title="Population", loc="upper right", framealpha=0.9)
|
114
120
|
|
115
121
|
return ax
|
116
122
|
|
@@ -142,6 +148,7 @@ def plot_firing_rate_pop_stats(
|
|
142
148
|
Axes with the bar plot.
|
143
149
|
"""
|
144
150
|
# Ensure groupby is a list for consistent handling
|
151
|
+
sns.set_style("whitegrid")
|
145
152
|
if isinstance(groupby, str):
|
146
153
|
groupby = [groupby]
|
147
154
|
|
@@ -234,6 +241,7 @@ def plot_firing_rate_distribution(
|
|
234
241
|
matplotlib.axes.Axes
|
235
242
|
Axes with the selected plot type(s) overlayed.
|
236
243
|
"""
|
244
|
+
sns.set_style("whitegrid")
|
237
245
|
# Ensure groupby is a list for consistent handling
|
238
246
|
if isinstance(groupby, str):
|
239
247
|
groupby = [groupby]
|
@@ -287,8 +295,9 @@ def plot_firing_rate_distribution(
|
|
287
295
|
y="firing_rate",
|
288
296
|
ax=ax,
|
289
297
|
palette=color_map,
|
290
|
-
inner="
|
298
|
+
inner="box",
|
291
299
|
alpha=0.4,
|
300
|
+
cut=0, # This prevents the KDE from extending beyond the data range
|
292
301
|
)
|
293
302
|
elif pt == "swarm":
|
294
303
|
sns.swarmplot(
|
@@ -308,3 +317,107 @@ def plot_firing_rate_distribution(
|
|
308
317
|
ax.grid(axis="y", linestyle="--", alpha=0.7)
|
309
318
|
|
310
319
|
return ax
|
320
|
+
|
321
|
+
|
322
|
+
def plot_firing_rate_vs_node_attribute(
|
323
|
+
individual_stats: Optional[pd.DataFrame] = None,
|
324
|
+
config: Optional[str] = None,
|
325
|
+
nodes: Optional[pd.DataFrame] = None,
|
326
|
+
groupby: Optional[str] = None,
|
327
|
+
network_name: Optional[str] = None,
|
328
|
+
attribute: Optional[str] = None,
|
329
|
+
figsize=(12, 8),
|
330
|
+
dot_size: float = 3,
|
331
|
+
) -> plt.Figure:
|
332
|
+
"""
|
333
|
+
Plot firing rate vs node attribute for each group in separate subplots.
|
334
|
+
|
335
|
+
Parameters
|
336
|
+
----------
|
337
|
+
individual_stats : pd.DataFrame, optional
|
338
|
+
DataFrame containing individual cell firing rates from compute_firing_rate_stats
|
339
|
+
config : str, optional
|
340
|
+
Path to configuration file for loading node data
|
341
|
+
nodes : pd.DataFrame, optional
|
342
|
+
Pre-loaded node data as alternative to loading from config
|
343
|
+
groupby : str, optional
|
344
|
+
Column name in individual_stats to group plots by
|
345
|
+
network_name : str, optional
|
346
|
+
Name of network to load from config file
|
347
|
+
attribute : str, optional
|
348
|
+
Node attribute column name to plot against firing rate
|
349
|
+
figsize : tuple[int, int], optional
|
350
|
+
Figure dimensions (width, height) in inches
|
351
|
+
dot_size : float, optional
|
352
|
+
Size of scatter plot points
|
353
|
+
|
354
|
+
Returns
|
355
|
+
-------
|
356
|
+
matplotlib.figure.Figure
|
357
|
+
Figure containing the subplots
|
358
|
+
|
359
|
+
Raises
|
360
|
+
------
|
361
|
+
ValueError
|
362
|
+
If neither config nor nodes is provided
|
363
|
+
If network_name is missing when using config
|
364
|
+
If attribute is not found in nodes DataFrame
|
365
|
+
If node_ids column is missing
|
366
|
+
If nodes index is not unique
|
367
|
+
"""
|
368
|
+
# Input validation
|
369
|
+
if config is None and nodes is None:
|
370
|
+
raise ValueError("Must provide either config or nodes")
|
371
|
+
if config is not None and nodes is None:
|
372
|
+
if network_name is None:
|
373
|
+
raise ValueError("network_name required when using config")
|
374
|
+
nodes = load_nodes_from_config(config)
|
375
|
+
if attribute not in nodes.columns:
|
376
|
+
raise ValueError(f"Attribute '{attribute}' not found in nodes DataFrame")
|
377
|
+
|
378
|
+
# Extract node attribute data
|
379
|
+
node_attribute = nodes[attribute]
|
380
|
+
|
381
|
+
# Validate data structure
|
382
|
+
if "node_ids" not in individual_stats.columns:
|
383
|
+
raise ValueError("individual_stats missing required 'node_ids' column")
|
384
|
+
if not nodes.index.is_unique:
|
385
|
+
raise ValueError("nodes DataFrame must have unique index for merging")
|
386
|
+
|
387
|
+
# Merge firing rate data with node attributes
|
388
|
+
merged_df = individual_stats.merge(
|
389
|
+
node_attribute, left_on="node_ids", right_index=True, how="left"
|
390
|
+
)
|
391
|
+
|
392
|
+
# Setup subplot layout
|
393
|
+
max_groups = 15 # Maximum number of subplots to avoid overcrowding
|
394
|
+
unique_groups = merged_df[groupby].unique()
|
395
|
+
n_groups = min(len(unique_groups), max_groups)
|
396
|
+
|
397
|
+
if len(unique_groups) > max_groups:
|
398
|
+
print(f"Warning: Limiting display to {max_groups} groups out of {len(unique_groups)}")
|
399
|
+
unique_groups = unique_groups[:max_groups]
|
400
|
+
|
401
|
+
n_cols = min(3, n_groups)
|
402
|
+
n_rows = (n_groups + n_cols - 1) // n_cols
|
403
|
+
|
404
|
+
# Create subplots
|
405
|
+
fig, axes = plt.subplots(n_rows, n_cols, figsize=figsize)
|
406
|
+
if n_groups == 1:
|
407
|
+
axes = np.array([axes])
|
408
|
+
axes = axes.flatten()
|
409
|
+
|
410
|
+
# Plot each group
|
411
|
+
for i, group in enumerate(unique_groups):
|
412
|
+
group_df = merged_df[merged_df[groupby] == group]
|
413
|
+
axes[i].scatter(group_df["firing_rate"], group_df[attribute], s=dot_size)
|
414
|
+
axes[i].set_xlabel("Firing Rate (Hz)")
|
415
|
+
axes[i].set_ylabel(attribute)
|
416
|
+
axes[i].set_title(f"{groupby}: {group}")
|
417
|
+
|
418
|
+
# Hide unused subplots
|
419
|
+
for j in range(i + 1, len(axes)):
|
420
|
+
axes[j].set_visible(False)
|
421
|
+
|
422
|
+
plt.tight_layout()
|
423
|
+
plt.show()
|
bmtool/synapses.py
CHANGED
@@ -18,7 +18,7 @@ from scipy.optimize import curve_fit, minimize, minimize_scalar
|
|
18
18
|
from scipy.signal import find_peaks
|
19
19
|
from tqdm.notebook import tqdm
|
20
20
|
|
21
|
-
from bmtool.util.util import
|
21
|
+
from bmtool.util.util import load_templates_from_config
|
22
22
|
|
23
23
|
|
24
24
|
class SynapseTuner:
|
@@ -69,7 +69,7 @@ class SynapseTuner:
|
|
69
69
|
neuron.load_mechanisms(mechanisms_dir)
|
70
70
|
h.load_file(templates_dir)
|
71
71
|
else:
|
72
|
-
|
72
|
+
# loads both mech and templates
|
73
73
|
load_templates_from_config(config)
|
74
74
|
|
75
75
|
self.conn_type_settings = conn_type_settings
|
@@ -983,7 +983,7 @@ class GapJunctionTuner:
|
|
983
983
|
neuron.load_mechanisms(mechanisms_dir)
|
984
984
|
h.load_file(templates_dir)
|
985
985
|
else:
|
986
|
-
|
986
|
+
# this will load both mechs and templates
|
987
987
|
load_templates_from_config(config)
|
988
988
|
|
989
989
|
self.general_settings = general_settings
|
bmtool/util/util.py
CHANGED
@@ -447,6 +447,9 @@ def load_mechanisms_from_config(config=None):
|
|
447
447
|
|
448
448
|
|
449
449
|
def load_templates_from_config(config=None):
|
450
|
+
"""
|
451
|
+
loads the neuron mechanisms and templates provided from BMTK config
|
452
|
+
"""
|
450
453
|
if config is None:
|
451
454
|
config = "simulation_config.json"
|
452
455
|
config = load_config(config)
|
@@ -6,29 +6,29 @@ bmtool/graphs.py,sha256=gBTzI6c2BBK49dWGcfWh9c56TAooyn-KaiEy0Im1HcI,6717
|
|
6
6
|
bmtool/manage.py,sha256=lsgRejp02P-x6QpA7SXcyXdalPhRmypoviIA2uAitQs,608
|
7
7
|
bmtool/plot_commands.py,sha256=Dxm_RaT4CtHnfsltTtUopJ4KVbfhxtktEB_b7bFEXII,12716
|
8
8
|
bmtool/singlecell.py,sha256=I2yolbAnNC8qpnRkNdnDCLidNW7CktmBuRrcowMZJ3A,45041
|
9
|
-
bmtool/synapses.py,sha256=
|
9
|
+
bmtool/synapses.py,sha256=y8UJAqO1jpZY-mY9gVVMN8Dj1r9jD2fI1nAaNQeQfz4,66148
|
10
10
|
bmtool/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
bmtool/analysis/entrainment.py,sha256=
|
11
|
+
bmtool/analysis/entrainment.py,sha256=NQloQtVpEWjDzmkZwMWVcm3hSjErHBZfQl1mrBVoIE8,25321
|
12
12
|
bmtool/analysis/lfp.py,sha256=S2JvxkjcK3-EH93wCrhqNSFY6cX7fOq74pz64ibHKrc,26556
|
13
13
|
bmtool/analysis/netcon_reports.py,sha256=VnPZNKPaQA7oh1q9cIatsqQudm4cOtzNtbGPXoiDCD0,2909
|
14
|
-
bmtool/analysis/spikes.py,sha256=
|
14
|
+
bmtool/analysis/spikes.py,sha256=3n-xmyEZ7w6CKEND7-aKOAvdDg0lwDuPI5sMdOuPwa0,24637
|
15
15
|
bmtool/bmplot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
-
bmtool/bmplot/connections.py,sha256=
|
17
|
-
bmtool/bmplot/entrainment.py,sha256=
|
16
|
+
bmtool/bmplot/connections.py,sha256=L0UGOOsD4Iqxv492uSChpsFHIC_Ntz8X51ZfE_AJcP8,58216
|
17
|
+
bmtool/bmplot/entrainment.py,sha256=BrBMerqyiG2YWAO_OEFv7OJf3yeFz3l9jUt4NamluLc,32837
|
18
18
|
bmtool/bmplot/lfp.py,sha256=SNpbWGOUnYEgnkeBw5S--aPN5mIGD22Gw2Pwus0_lvY,2034
|
19
19
|
bmtool/bmplot/netcon_reports.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
bmtool/bmplot/spikes.py,sha256=
|
20
|
+
bmtool/bmplot/spikes.py,sha256=odzCSMbFRHp9qthSGQ0WzMWUwNQ7R1Z6gLT6VPF_o5Q,15326
|
21
21
|
bmtool/debug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
bmtool/debug/commands.py,sha256=VV00f6q5gzZI503vUPeG40ABLLen0bw_k4-EX-H5WZE,580
|
23
23
|
bmtool/debug/debug.py,sha256=9yUFvA4_Bl-x9s29quIEG3pY-S8hNJF3RKBfRBHCl28,208
|
24
24
|
bmtool/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
25
|
bmtool/util/commands.py,sha256=Nn-R-4e9g8ZhSPZvTkr38xeKRPfEMANB9Lugppj82UI,68564
|
26
|
-
bmtool/util/util.py,sha256=
|
26
|
+
bmtool/util/util.py,sha256=S8sAXwDiISGAqnSXRIgFqxqCRzL5YcxAqP1UGxGA5Z4,62906
|
27
27
|
bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
28
|
bmtool/util/neuron/celltuner.py,sha256=lokRLUM1rsdSYBYrNbLBBo39j14mm8TBNVNRnSlhHCk,94868
|
29
|
-
bmtool-0.7.1.
|
30
|
-
bmtool-0.7.1.
|
31
|
-
bmtool-0.7.1.
|
32
|
-
bmtool-0.7.1.
|
33
|
-
bmtool-0.7.1.
|
34
|
-
bmtool-0.7.1.
|
29
|
+
bmtool-0.7.2.1.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
|
30
|
+
bmtool-0.7.2.1.dist-info/METADATA,sha256=rEXYmlS4RZxoXEK_2fV57B1c0CSNA38Eh4JmzQ1YGQ8,3577
|
31
|
+
bmtool-0.7.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
32
|
+
bmtool-0.7.2.1.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
|
33
|
+
bmtool-0.7.2.1.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
|
34
|
+
bmtool-0.7.2.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|