bmtool 0.6.9.23__tar.gz → 0.6.9.24__tar.gz

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.
Files changed (33) hide show
  1. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/PKG-INFO +1 -1
  2. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/analysis/spikes.py +53 -0
  3. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/bmplot.py +95 -1
  4. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/util/util.py +28 -0
  5. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool.egg-info/PKG-INFO +1 -1
  6. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/setup.py +1 -1
  7. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/LICENSE +0 -0
  8. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/README.md +0 -0
  9. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/SLURM.py +0 -0
  10. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/__init__.py +0 -0
  11. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/__main__.py +0 -0
  12. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/analysis/__init__.py +0 -0
  13. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/analysis/lfp.py +0 -0
  14. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/analysis/netcon_reports.py +0 -0
  15. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/connectors.py +0 -0
  16. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/debug/__init__.py +0 -0
  17. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/debug/commands.py +0 -0
  18. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/debug/debug.py +0 -0
  19. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/graphs.py +0 -0
  20. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/manage.py +0 -0
  21. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/plot_commands.py +0 -0
  22. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/singlecell.py +0 -0
  23. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/synapses.py +0 -0
  24. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/util/__init__.py +0 -0
  25. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/util/commands.py +0 -0
  26. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/util/neuron/__init__.py +0 -0
  27. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool/util/neuron/celltuner.py +0 -0
  28. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool.egg-info/SOURCES.txt +0 -0
  29. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool.egg-info/dependency_links.txt +0 -0
  30. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool.egg-info/entry_points.txt +0 -0
  31. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool.egg-info/requires.txt +0 -0
  32. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/bmtool.egg-info/top_level.txt +0 -0
  33. {bmtool-0.6.9.23 → bmtool-0.6.9.24}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bmtool
3
- Version: 0.6.9.23
3
+ Version: 0.6.9.24
4
4
  Summary: BMTool
5
5
  Home-page: https://github.com/cyneuro/bmtool
6
6
  Download-URL:
@@ -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
@@ -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.
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bmtool
3
- Version: 0.6.9.23
3
+ Version: 0.6.9.24
4
4
  Summary: BMTool
5
5
  Home-page: https://github.com/cyneuro/bmtool
6
6
  Download-URL:
@@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
6
6
 
7
7
  setup(
8
8
  name="bmtool",
9
- version='0.6.9.23',
9
+ version='0.6.9.24',
10
10
  author="Neural Engineering Laboratory at the University of Missouri",
11
11
  author_email="gregglickert@mail.missouri.edu",
12
12
  description="BMTool",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes