bmtool 0.6.9.23__py3-none-any.whl → 0.6.9.24__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/spikes.py +53 -0
- bmtool/bmplot.py +95 -1
- bmtool/util/util.py +28 -0
- {bmtool-0.6.9.23.dist-info → bmtool-0.6.9.24.dist-info}/METADATA +1 -1
- {bmtool-0.6.9.23.dist-info → bmtool-0.6.9.24.dist-info}/RECORD +9 -9
- {bmtool-0.6.9.23.dist-info → bmtool-0.6.9.24.dist-info}/WHEEL +0 -0
- {bmtool-0.6.9.23.dist-info → bmtool-0.6.9.24.dist-info}/entry_points.txt +0 -0
- {bmtool-0.6.9.23.dist-info → bmtool-0.6.9.24.dist-info}/licenses/LICENSE +0 -0
- {bmtool-0.6.9.23.dist-info → bmtool-0.6.9.24.dist-info}/top_level.txt +0 -0
bmtool/analysis/spikes.py
CHANGED
@@ -7,6 +7,7 @@ import pandas as pd
|
|
7
7
|
from bmtool.util.util import load_nodes_from_config
|
8
8
|
from typing import Dict, Optional,Tuple, Union, List
|
9
9
|
import numpy as np
|
10
|
+
from scipy.stats import mannwhitneyu
|
10
11
|
import os
|
11
12
|
|
12
13
|
|
@@ -252,3 +253,55 @@ def get_population_spike_rate(spikes: pd.DataFrame, fs: float = 400.0, t_start:
|
|
252
253
|
|
253
254
|
return spike_rate
|
254
255
|
|
256
|
+
|
257
|
+
def compare_firing_over_times(spike_df,group_by, time_window_1, time_window_2):
|
258
|
+
"""
|
259
|
+
Compares the firing rates of a population during two different time windows
|
260
|
+
time_window_1 and time_window_2 should be a list of [start, stop] in milliseconds
|
261
|
+
Returns firing rates and results of a Mann-Whitney U test (non-parametric)
|
262
|
+
"""
|
263
|
+
# Filter spikes for the population of interest
|
264
|
+
for pop_name in spike_df[group_by].unique():
|
265
|
+
print(f"Population: {pop_name}")
|
266
|
+
pop_spikes = spike_df[spike_df[group_by] == pop_name]
|
267
|
+
|
268
|
+
# Filter by time windows
|
269
|
+
pop_spikes_1 = pop_spikes[(pop_spikes['timestamps'] >= time_window_1[0]) & (pop_spikes['timestamps'] <= time_window_1[1])]
|
270
|
+
pop_spikes_2 = pop_spikes[(pop_spikes['timestamps'] >= time_window_2[0]) & (pop_spikes['timestamps'] <= time_window_2[1])]
|
271
|
+
|
272
|
+
# Get unique neuron IDs
|
273
|
+
unique_neurons = pop_spikes['node_ids'].unique()
|
274
|
+
|
275
|
+
# Calculate firing rates per neuron for each time window in Hz
|
276
|
+
neuron_rates_1 = []
|
277
|
+
neuron_rates_2 = []
|
278
|
+
|
279
|
+
for neuron in unique_neurons:
|
280
|
+
# Count spikes for this neuron in each window
|
281
|
+
n_spikes_1 = len(pop_spikes_1[pop_spikes_1['node_ids'] == neuron])
|
282
|
+
n_spikes_2 = len(pop_spikes_2[pop_spikes_2['node_ids'] == neuron])
|
283
|
+
|
284
|
+
# Calculate firing rate in Hz (convert ms to seconds by dividing by 1000)
|
285
|
+
rate_1 = n_spikes_1 / ((time_window_1[1] - time_window_1[0]) / 1000)
|
286
|
+
rate_2 = n_spikes_2 / ((time_window_2[1] - time_window_2[0]) / 1000)
|
287
|
+
|
288
|
+
neuron_rates_1.append(rate_1)
|
289
|
+
neuron_rates_2.append(rate_2)
|
290
|
+
|
291
|
+
# Calculate average firing rates
|
292
|
+
avg_firing_rate_1 = np.mean(neuron_rates_1) if neuron_rates_1 else 0
|
293
|
+
avg_firing_rate_2 = np.mean(neuron_rates_2) if neuron_rates_2 else 0
|
294
|
+
|
295
|
+
# Perform Mann-Whitney U test
|
296
|
+
# Handle the case when one or both arrays are empty
|
297
|
+
if len(neuron_rates_1) > 0 and len(neuron_rates_2) > 0:
|
298
|
+
u_stat, p_val = mannwhitneyu(neuron_rates_1, neuron_rates_2, alternative='two-sided')
|
299
|
+
else:
|
300
|
+
u_stat, p_val = np.nan, np.nan
|
301
|
+
|
302
|
+
print(f" Average firing rate in window 1: {avg_firing_rate_1:.2f} Hz")
|
303
|
+
print(f" Average firing rate in window 2: {avg_firing_rate_2:.2f} Hz")
|
304
|
+
print(f" U-statistic: {u_stat:.2f}")
|
305
|
+
print(f" p-value: {p_val}")
|
306
|
+
print(f" Significant difference (p<0.05): {'Yes' if p_val < 0.05 else 'No'}")
|
307
|
+
return
|
bmtool/bmplot.py
CHANGED
@@ -23,8 +23,9 @@ import sys
|
|
23
23
|
import re
|
24
24
|
from typing import Optional, Dict, Union, List
|
25
25
|
|
26
|
-
from .util.util import CellVarsFile,load_nodes_from_config #, missing_units
|
26
|
+
from .util.util import CellVarsFile,load_nodes_from_config,load_templates_from_config #, missing_units
|
27
27
|
from bmtk.analyzer.utils import listify
|
28
|
+
from neuron import h
|
28
29
|
|
29
30
|
use_description = """
|
30
31
|
|
@@ -682,6 +683,99 @@ def edge_histogram_matrix(config=None,sources = None,targets=None,sids=None,tids
|
|
682
683
|
fig.text(0.04, 0.5, 'Source', va='center', rotation='vertical')
|
683
684
|
plt.draw()
|
684
685
|
|
686
|
+
def plot_synapse_location_histograms(config, target_model, source=None, target=None):
|
687
|
+
"""
|
688
|
+
generates a histogram of the positions of the synapses on a cell broken down by section
|
689
|
+
config: a BMTK config
|
690
|
+
target_model: the name of the model_template used when building the BMTK node
|
691
|
+
source: The source BMTK network
|
692
|
+
target: The target BMTK network
|
693
|
+
"""
|
694
|
+
# Load mechanisms and template
|
695
|
+
|
696
|
+
util.load_templates_from_config(config)
|
697
|
+
|
698
|
+
# Load node and edge data
|
699
|
+
nodes, edges = util.load_nodes_edges_from_config(config)
|
700
|
+
nodes = nodes[source]
|
701
|
+
edges = edges[f'{source}_to_{target}']
|
702
|
+
|
703
|
+
# Map target_node_id to model_template
|
704
|
+
edges['target_model_template'] = edges['target_node_id'].map(nodes['model_template'])
|
705
|
+
|
706
|
+
# Map source_node_id to pop_name
|
707
|
+
edges['source_pop_name'] = edges['source_node_id'].map(nodes['pop_name'])
|
708
|
+
|
709
|
+
edges = edges[edges['target_model_template'] == target_model]
|
710
|
+
|
711
|
+
# Create the cell model from target model
|
712
|
+
cell = getattr(h, target_model.split(':')[1])()
|
713
|
+
|
714
|
+
# Create a mapping from section index to section name
|
715
|
+
section_id_to_name = {}
|
716
|
+
for idx, sec in enumerate(cell.all):
|
717
|
+
section_id_to_name[idx] = sec.name()
|
718
|
+
|
719
|
+
# Add a new column with section names based on afferent_section_id
|
720
|
+
edges['afferent_section_name'] = edges['afferent_section_id'].map(section_id_to_name)
|
721
|
+
|
722
|
+
# Get unique sections and source populations
|
723
|
+
unique_pops = edges['source_pop_name'].unique()
|
724
|
+
|
725
|
+
# Filter to only include sections with data
|
726
|
+
section_counts = edges['afferent_section_name'].value_counts()
|
727
|
+
sections_with_data = section_counts[section_counts > 0].index.tolist()
|
728
|
+
|
729
|
+
|
730
|
+
# Create a figure with subplots for each section
|
731
|
+
plt.figure(figsize=(8,12))
|
732
|
+
|
733
|
+
# Color map for source populations
|
734
|
+
color_map = plt.cm.tab10(np.linspace(0, 1, len(unique_pops)))
|
735
|
+
pop_colors = {pop: color for pop, color in zip(unique_pops, color_map)}
|
736
|
+
|
737
|
+
# Create a histogram for each section
|
738
|
+
for i, section in enumerate(sections_with_data):
|
739
|
+
ax = plt.subplot(len(sections_with_data), 1, i+1)
|
740
|
+
|
741
|
+
# Get data for this section
|
742
|
+
section_data = edges[edges['afferent_section_name'] == section]
|
743
|
+
|
744
|
+
# Group by source population
|
745
|
+
for pop_name, pop_group in section_data.groupby('source_pop_name'):
|
746
|
+
if len(pop_group) > 0:
|
747
|
+
ax.hist(pop_group['afferent_section_pos'], bins=15, alpha=0.7,
|
748
|
+
label=pop_name, color=pop_colors[pop_name])
|
749
|
+
|
750
|
+
# Set title and labels
|
751
|
+
ax.set_title(f"{section}", fontsize=10)
|
752
|
+
ax.set_xlabel('Section Position', fontsize=8)
|
753
|
+
ax.set_ylabel('Frequency', fontsize=8)
|
754
|
+
ax.tick_params(labelsize=7)
|
755
|
+
ax.grid(True, alpha=0.3)
|
756
|
+
|
757
|
+
# Only add legend to the first plot
|
758
|
+
if i == 0:
|
759
|
+
ax.legend(fontsize=8)
|
760
|
+
|
761
|
+
plt.tight_layout()
|
762
|
+
plt.suptitle('Connection Distribution by Cell Section and Source Population', fontsize=16, y=1.02)
|
763
|
+
if is_notebook:
|
764
|
+
plt.show()
|
765
|
+
else:
|
766
|
+
pass
|
767
|
+
|
768
|
+
# Create a summary table
|
769
|
+
print("Summary of connections by section and source population:")
|
770
|
+
pivot_table = edges.pivot_table(
|
771
|
+
values='afferent_section_id',
|
772
|
+
index='afferent_section_name',
|
773
|
+
columns='source_pop_name',
|
774
|
+
aggfunc='count',
|
775
|
+
fill_value=0
|
776
|
+
)
|
777
|
+
print(pivot_table)
|
778
|
+
|
685
779
|
def plot_connection_info(text, num, source_labels, target_labels, title, syn_info='0', save_file=None, return_dict=None):
|
686
780
|
"""
|
687
781
|
Function to plot connection information as a heatmap, including handling missing source and target values.
|
bmtool/util/util.py
CHANGED
@@ -6,6 +6,8 @@ import numpy as np
|
|
6
6
|
from numpy import genfromtxt
|
7
7
|
import h5py
|
8
8
|
import pandas as pd
|
9
|
+
import neuron
|
10
|
+
from neuron import h
|
9
11
|
|
10
12
|
#from bmtk.utils.io.cell_vars import CellVarsFile
|
11
13
|
#from bmtk.analyzer.cell_vars import _get_cell_report
|
@@ -392,6 +394,32 @@ def load_edges_from_paths(edge_paths):#network_dir='network'):
|
|
392
394
|
|
393
395
|
return edges_dict
|
394
396
|
|
397
|
+
def load_mechanisms_from_config(config=None):
|
398
|
+
"""
|
399
|
+
loads neuron mechanisms from BMTK config
|
400
|
+
"""
|
401
|
+
if config is None:
|
402
|
+
config = 'simulation_config.json'
|
403
|
+
config = load_config(config)
|
404
|
+
return neuron.load_mechanisms(config['components']['mechanisms_dir'])
|
405
|
+
|
406
|
+
def load_templates_from_config(config=None):
|
407
|
+
if config is None:
|
408
|
+
config = 'simulation_config.json'
|
409
|
+
config = load_config(config)
|
410
|
+
load_mechanisms_from_config(config)
|
411
|
+
return load_templates_from_paths(config['components']['templates_dir'])
|
412
|
+
|
413
|
+
def load_templates_from_paths(template_paths):
|
414
|
+
# load all the files in the templates dir
|
415
|
+
for item in os.listdir(template_paths):
|
416
|
+
item_path = os.path.join(template_paths, item)
|
417
|
+
if os.path.isfile(item_path):
|
418
|
+
print(f"loading {item_path}")
|
419
|
+
h.load_file(item_path)
|
420
|
+
|
421
|
+
|
422
|
+
|
395
423
|
def cell_positions_by_id(config=None, nodes=None, populations=[], popids=[], prepend_pop=True):
|
396
424
|
"""
|
397
425
|
Returns a dictionary of arrays of arrays {"population_popid":[[1,2,3],[1,2,4]],...
|
@@ -1,7 +1,7 @@
|
|
1
1
|
bmtool/SLURM.py,sha256=PST_jOD5ZmwbJj15Tgq3UIvdq4FYN4EkPuDt66P8OXU,20136
|
2
2
|
bmtool/__init__.py,sha256=ZStTNkAJHJxG7Pwiy5UgCzC4KlhMS5pUNPtUJZVwL_Y,136
|
3
3
|
bmtool/__main__.py,sha256=TmFkmDxjZ6250nYD4cgGhn-tbJeEm0u-EMz2ajAN9vE,650
|
4
|
-
bmtool/bmplot.py,sha256=
|
4
|
+
bmtool/bmplot.py,sha256=9CYCwi2vAIH7OgxYZzieKcXxp_GEhv8VOjRfdhoCLAw,66142
|
5
5
|
bmtool/connectors.py,sha256=uLhZIjur0_jWOtSZ9w6-PHftB9Xj6FFXWL5tndEMDYY,73570
|
6
6
|
bmtool/graphs.py,sha256=ShBgJr1iZrM3ugU2wT6hbhmBAkc3mmf7yZQfPuPEqPM,6691
|
7
7
|
bmtool/manage.py,sha256=_lCU0qBQZ4jSxjzAJUd09JEetb--cud7KZgxQFbLGSY,657
|
@@ -11,18 +11,18 @@ bmtool/synapses.py,sha256=6h1V64b_KYHN589NFikHrt_Q3lXPvtEgIpwYFlInWb0,64551
|
|
11
11
|
bmtool/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
bmtool/analysis/lfp.py,sha256=KTDMzqhkpTI308sWqoJnbHeCMSFScaJCO4u50Kd4FzA,33570
|
13
13
|
bmtool/analysis/netcon_reports.py,sha256=WWh12H9gjEZXhI_q7RErgGQ9iSPoTvCUnUjwNGxRwsY,3071
|
14
|
-
bmtool/analysis/spikes.py,sha256=
|
14
|
+
bmtool/analysis/spikes.py,sha256=x24kd0RUhumJkiunfHNEE7mM6JUqdWy1gqabmkMM4cU,14129
|
15
15
|
bmtool/debug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
bmtool/debug/commands.py,sha256=AwtcR7BUUheM0NxvU1Nu234zCdpobhJv5noX8x5K2vY,583
|
17
17
|
bmtool/debug/debug.py,sha256=xqnkzLiH3s-tS26Y5lZZL62qR2evJdi46Gud-HzxEN4,207
|
18
18
|
bmtool/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
bmtool/util/commands.py,sha256=zJF-fiLk0b8LyzHDfvewUyS7iumOxVnj33IkJDzux4M,64396
|
20
|
-
bmtool/util/util.py,sha256=
|
20
|
+
bmtool/util/util.py,sha256=XR0qZnv_Q47jMBKQpFzCSkCuKe9u8L3YSGJAOpP2zT0,57630
|
21
21
|
bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
bmtool/util/neuron/celltuner.py,sha256=xSRpRN6DhPFz4q5buq_W8UmsD7BbUrkzYBEbKVloYss,87194
|
23
|
-
bmtool-0.6.9.
|
24
|
-
bmtool-0.6.9.
|
25
|
-
bmtool-0.6.9.
|
26
|
-
bmtool-0.6.9.
|
27
|
-
bmtool-0.6.9.
|
28
|
-
bmtool-0.6.9.
|
23
|
+
bmtool-0.6.9.24.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
|
24
|
+
bmtool-0.6.9.24.dist-info/METADATA,sha256=CWgLenXWZTL9S5SAjARfnej708SAl2z6HepAfR-HztM,2769
|
25
|
+
bmtool-0.6.9.24.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
26
|
+
bmtool-0.6.9.24.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
|
27
|
+
bmtool-0.6.9.24.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
|
28
|
+
bmtool-0.6.9.24.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|