bmtool 0.7.1.7__tar.gz → 0.7.2.1__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 (41) hide show
  1. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/PKG-INFO +1 -1
  2. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/entrainment.py +1 -81
  3. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/spikes.py +55 -6
  4. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/connections.py +255 -153
  5. bmtool-0.7.2.1/bmtool/bmplot/entrainment.py +865 -0
  6. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/spikes.py +118 -5
  7. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/synapses.py +3 -3
  8. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/util.py +3 -0
  9. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/PKG-INFO +1 -1
  10. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/setup.py +1 -1
  11. bmtool-0.7.1.7/bmtool/bmplot/entrainment.py +0 -368
  12. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/LICENSE +0 -0
  13. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/README.md +0 -0
  14. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/SLURM.py +0 -0
  15. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/__init__.py +0 -0
  16. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/__main__.py +0 -0
  17. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/__init__.py +0 -0
  18. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/lfp.py +0 -0
  19. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/netcon_reports.py +0 -0
  20. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/__init__.py +0 -0
  21. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/lfp.py +0 -0
  22. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/netcon_reports.py +0 -0
  23. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/connectors.py +0 -0
  24. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/debug/__init__.py +0 -0
  25. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/debug/commands.py +0 -0
  26. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/debug/debug.py +0 -0
  27. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/graphs.py +0 -0
  28. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/manage.py +0 -0
  29. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/plot_commands.py +0 -0
  30. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/singlecell.py +0 -0
  31. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/__init__.py +0 -0
  32. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/commands.py +0 -0
  33. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/neuron/__init__.py +0 -0
  34. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/neuron/celltuner.py +0 -0
  35. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/SOURCES.txt +0 -0
  36. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/dependency_links.txt +0 -0
  37. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/entry_points.txt +0 -0
  38. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/requires.txt +0 -0
  39. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/top_level.txt +0 -0
  40. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/pyproject.toml +0 -0
  41. {bmtool-0.7.1.7 → bmtool-0.7.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bmtool
3
- Version: 0.7.1.7
3
+ Version: 0.7.2.1
4
4
  Summary: BMTool
5
5
  Home-page: https://github.com/cyneuro/bmtool
6
6
  Download-URL:
@@ -7,13 +7,12 @@ from typing import Dict, List, Optional, Union
7
7
  import numba
8
8
  import numpy as np
9
9
  import pandas as pd
10
- import scipy.stats as stats
11
10
  import xarray as xr
12
11
  from numba import cuda
13
12
  from scipy import signal
14
13
  from tqdm.notebook import tqdm
15
14
 
16
- from .lfp import butter_bandpass_filter, get_lfp_phase, get_lfp_power, wavelet_filter
15
+ from .lfp import butter_bandpass_filter, get_lfp_phase, wavelet_filter
17
16
 
18
17
 
19
18
  def align_spike_times_with_lfp(lfp: xr.DataArray, timestamps: np.ndarray) -> np.ndarray:
@@ -635,85 +634,6 @@ def calculate_entrainment_per_cell(
635
634
  return entrainment_dict
636
635
 
637
636
 
638
- def calculate_spike_rate_power_correlation(
639
- spike_rate: xr.DataArray,
640
- lfp_data: np.ndarray,
641
- fs: float,
642
- pop_names: list,
643
- filter_method: str = "wavelet",
644
- bandwidth: float = 2.0,
645
- lowcut: float = None,
646
- highcut: float = None,
647
- freq_range: tuple = (10, 100),
648
- freq_step: float = 5,
649
- type_name: str = "raw", # 'raw' or 'smoothed'
650
- ):
651
- """
652
- Calculate correlation between population spike rates (xarray) and LFP power across frequencies.
653
-
654
- Parameters
655
- ----------
656
- spike_rate : xr.DataArray
657
- Population spike rates with dimensions (time, population[, type])
658
- lfp_data : np.ndarray
659
- LFP data
660
- fs : float
661
- Sampling frequency
662
- pop_names : list
663
- List of population names to analyze
664
- filter_method : str, optional
665
- Filtering method to use, either 'wavelet' or 'butter' (default: 'wavelet')
666
- bandwidth : float, optional
667
- Bandwidth parameter for wavelet filter when method='wavelet' (default: 2.0)
668
- lowcut : float, optional
669
- Lower frequency bound (Hz) for butterworth bandpass filter, required if filter_method='butter'
670
- highcut : float, optional
671
- Upper frequency bound (Hz) for butterworth bandpass filter, required if filter_method='butter'
672
- freq_range : tuple, optional
673
- Min and max frequency to analyze (default: (10, 100))
674
- freq_step : float, optional
675
- Step size for frequency analysis (default: 5)
676
- type_name : str, optional
677
- Which type of spike rate to use if 'type' dimension exists (default: 'raw')
678
-
679
- Returns
680
- -------
681
- correlation_results : dict
682
- Dictionary with correlation results for each population and frequency
683
- frequencies : array
684
- Array of frequencies analyzed
685
- """
686
- frequencies = np.arange(freq_range[0], freq_range[1] + 1, freq_step)
687
- correlation_results = {pop: {} for pop in pop_names}
688
-
689
- # Calculate power at each frequency band using specified filter
690
- power_by_freq = {}
691
- for freq in frequencies:
692
- power_by_freq[freq] = get_lfp_power(
693
- lfp_data, freq, fs, filter_method, lowcut=lowcut, highcut=highcut, bandwidth=bandwidth
694
- )
695
-
696
- # For each population, extract the correct spike rate
697
- for pop in pop_names:
698
- # If 'type' dimension exists, select the type
699
- if "type" in spike_rate.dims:
700
- pop_rate = spike_rate.sel(population=pop, type=type_name).values
701
- else:
702
- pop_rate = spike_rate.sel(population=pop).values
703
-
704
- # Calculate correlation with power at each frequency
705
- for freq in frequencies:
706
- lfp_power = power_by_freq[freq]
707
- # Ensure lengths match
708
- min_len = min(len(pop_rate), len(lfp_power))
709
- if len(pop_rate) != len(lfp_power):
710
- print(f"Warning: Length mismatch for {pop} at {freq} Hz, truncating to {min_len}")
711
- corr, p_val = stats.spearmanr(pop_rate[:min_len], lfp_power[:min_len])
712
- correlation_results[pop][freq] = {"correlation": corr, "p_value": p_val}
713
-
714
- return correlation_results, frequencies
715
-
716
-
717
637
  def get_spikes_in_cycle(
718
638
  spike_df,
719
639
  lfp_data,
@@ -281,12 +281,13 @@ def get_population_spike_rate(
281
281
  node_number = {}
282
282
 
283
283
  if config is None:
284
- print(
285
- "Note: Node number is obtained by counting unique node spikes in the network.\nIf the network did not run for a sufficient duration, or not all cells fired,\nthen this count will not include all nodes so the firing rate will not be of the whole population!"
286
- )
287
- print(
288
- "You can provide a config to calculate the correct amount of nodes! for a true population rate."
289
- )
284
+ pass
285
+ # print(
286
+ # "Note: Node number is obtained by counting unique node spikes in the network.\nIf the network did not run for a sufficient duration, or not all cells fired,\nthen this count will not include all nodes so the firing rate will not be of the whole population!"
287
+ # )
288
+ # print(
289
+ # "You can provide a config to calculate the correct amount of nodes! for a true population rate."
290
+ # )
290
291
 
291
292
  if config:
292
293
  if not network_name:
@@ -602,3 +603,51 @@ def find_bursting_cells(
602
603
  )
603
604
 
604
605
  return burst_cells
606
+
607
+
608
+ def find_highest_firing_cells(
609
+ df: pd.DataFrame, upper_quantile: float, groupby: str = "pop_name"
610
+ ) -> pd.DataFrame:
611
+ """
612
+ Identifies and returns spikes from cells with firing rates above a specified upper quantile,
613
+ grouped by a population label.
614
+
615
+ Parameters
616
+ ----------
617
+ df : pd.DataFrame
618
+ DataFrame containing spike data with at least the following columns:
619
+ - 'timestamps': Time of each spike event
620
+ - 'node_ids': Identifier for each neuron
621
+ - groupby (e.g., 'pop_name'): Population labels or grouping identifiers for neurons
622
+
623
+ upper_quantile : float
624
+ The upper quantile threshold (between 0 and 1).
625
+ Cells with firing rates in the top (1 - upper_quantile) fraction are selected.
626
+ For example, upper_quantile=0.8 selects the top 20% of high-firing cells.
627
+
628
+ groupby : str, optional
629
+ The column name used to group neurons by population. Default is 'pop_name'.
630
+
631
+ Returns
632
+ -------
633
+ pd.DataFrame
634
+ A DataFrame containing only the spikes from the high-firing cells across all groupbys.
635
+ """
636
+ if upper_quantile == 0:
637
+ return df
638
+ df_list = []
639
+ for pop in df[groupby].unique():
640
+ pop_df = df[df[groupby] == pop]
641
+ _, pop_fr = compute_firing_rate_stats(pop_df, groupby=groupby)
642
+
643
+ # Identify high firing cells
644
+ threshold = pop_fr["firing_rate"].quantile(upper_quantile)
645
+ high_firing_cells = pop_fr[pop_fr["firing_rate"] >= threshold]["node_ids"]
646
+
647
+ # Filter spikes for high firing cells
648
+ pop_spikes = pop_df[pop_df["node_ids"].isin(high_firing_cells)]
649
+ df_list.append(pop_spikes)
650
+
651
+ # Combine all high firing spikes into one DataFrame
652
+ result_df = pd.concat(df_list, ignore_index=True)
653
+ return result_df