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.
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/PKG-INFO +1 -1
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/entrainment.py +1 -81
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/spikes.py +55 -6
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/connections.py +255 -153
- bmtool-0.7.2.1/bmtool/bmplot/entrainment.py +865 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/spikes.py +118 -5
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/synapses.py +3 -3
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/util.py +3 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/PKG-INFO +1 -1
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/setup.py +1 -1
- bmtool-0.7.1.7/bmtool/bmplot/entrainment.py +0 -368
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/LICENSE +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/README.md +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/SLURM.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/__init__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/__main__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/__init__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/lfp.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/analysis/netcon_reports.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/__init__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/lfp.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/bmplot/netcon_reports.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/connectors.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/debug/__init__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/debug/commands.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/debug/debug.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/graphs.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/manage.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/plot_commands.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/singlecell.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/__init__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/commands.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/neuron/__init__.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool/util/neuron/celltuner.py +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/SOURCES.txt +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/dependency_links.txt +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/entry_points.txt +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/requires.txt +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/bmtool.egg-info/top_level.txt +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/pyproject.toml +0 -0
- {bmtool-0.7.1.7 → bmtool-0.7.2.1}/setup.cfg +0 -0
@@ -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,
|
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
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|