bmtool 0.6.8.2__py3-none-any.whl → 0.6.8.3__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/lfp.py CHANGED
@@ -406,56 +406,70 @@ def calculate_plv_over_time(x1: np.ndarray, x2: np.ndarray, fs: float,
406
406
  return np.array(plv_over_time), np.array(times)
407
407
 
408
408
 
409
- def calculate_ppc1(spike_times, lfp_signal, fs, freq_range, window_size=0.5):
409
+ def calculate_ppc1(spike_times: np.ndarray = None, lfp_signal: np.ndarray = None, spike_fs : float = None,
410
+ lfp_fs: float = None, method: str = 'hilbert', freq_of_interest: float = None,
411
+ lowcut: float = None, highcut: float = None,
412
+ bandwidth: float = 2.0) -> tuple:
410
413
  """
411
- Calculate PPC1 metric between spike times and LFP signal using the vector dot product method.
414
+ Calculate Phase-Phase Coupling (PPC1) between spike times and LFP signal. Based on https://www.sciencedirect.com/science/article/pii/S1053811910000959
412
415
 
413
416
  Parameters:
414
- -----------
415
- spike_times : array_like
416
- Array of spike times in seconds
417
- lfp_signal : array_like
418
- Local field potential time series
419
- fs : float
420
- Sampling frequency of the LFP signal in Hz
421
- freq_range : tuple
422
- Frequency range (low, high) to filter the LFP signal in Hz
423
- window_size : float, optional
424
- Size of the window around each spike in seconds, default is 0.5s
417
+ - spike_times: Array of spike times
418
+ - lfp_signal: Local field potential time series
419
+ - spike_fs: Sampling frequency in Hz of the spike times only needed if spikes times and lfp has different fs
420
+ - lfp_fs : Sampling frequency in Hz of the LFP
421
+ - method: 'wavelet' or 'hilbert' to choose the phase extraction method
422
+ - freq_of_interest: Desired frequency for wavelet phase extraction
423
+ - lowcut, highcut: Cutoff frequencies for bandpass filtering (Hilbert method)
424
+ - bandwidth: Bandwidth parameter for the wavelet
425
425
 
426
426
  Returns:
427
- --------
428
- ppc1 : float
429
- PPC1 value
430
- phases : array
431
- Phases at spike times
427
+ - ppc1: Phase-Phase Coupling value
428
+ - spike_phases: Phases at spike times
432
429
  """
433
- # Convert spike times to sample indices
434
- spike_indices = np.round(spike_times * fs).astype(int)
435
430
 
436
- # Filter LFP in the frequency band of interest
437
- nyquist = fs / 2
438
- b, a = signal.butter(3, [freq_range[0] / nyquist, freq_range[1] / nyquist], btype='band')
439
- filtered_lfp = signal.filtfilt(b, a, lfp_signal)
431
+ if spike_fs == None:
432
+ spike_fs = lfp_fs
433
+ # Convert spike times to sample indices
434
+ spike_times_seconds = spike_times / spike_fs
435
+
436
+ # Then convert from seconds to samples at the new sampling rate
437
+ spike_indices = np.round(spike_times_seconds * lfp_fs).astype(int)
440
438
 
441
- # Get analytic signal through Hilbert transform
442
- analytic_signal = signal.hilbert(filtered_lfp)
439
+ # Filter indices to ensure they're within bounds of the LFP signal
440
+ valid_indices = [idx for idx in spike_indices if 0 <= idx < len(lfp_signal)]
441
+ if len(valid_indices) <= 1:
442
+ return 0, np.array([])
443
443
 
444
- # Extract instantaneous phase
445
- instantaneous_phase = np.angle(analytic_signal)
444
+ # Extract phase using the specified method
445
+ if method == 'wavelet':
446
+ if freq_of_interest is None:
447
+ raise ValueError("freq_of_interest must be provided for the wavelet method.")
448
+
449
+ # Apply CWT to extract phase at the frequency of interest
450
+ lfp_complex = wavelet_filter(x=lfp_signal, freq=freq_of_interest, fs=lfp_fs, bandwidth=bandwidth)
451
+ instantaneous_phase = np.angle(lfp_complex)
452
+
453
+ elif method == 'hilbert':
454
+ if lowcut is None or highcut is None:
455
+ print("Lowcut and/or highcut were not defined, signal will not be filtered and will just take Hilbert transform for PPC1 calculation")
456
+ filtered_lfp = lfp_signal
457
+ else:
458
+ # Bandpass filter the signal
459
+ filtered_lfp = butter_bandpass_filter(lfp_signal, lowcut, highcut, lfp_fs)
460
+
461
+ # Get phase using the Hilbert transform
462
+ analytic_signal = signal.hilbert(filtered_lfp)
463
+ instantaneous_phase = np.angle(analytic_signal)
464
+
465
+ else:
466
+ raise ValueError("Invalid method. Choose 'wavelet' or 'hilbert'.")
446
467
 
447
468
  # Get phases at spike times
448
- spike_phases = []
449
- for spike_idx in spike_indices:
450
- if 0 <= spike_idx < len(instantaneous_phase):
451
- spike_phases.append(instantaneous_phase[spike_idx])
452
-
453
- spike_phases = np.array(spike_phases)
469
+ spike_phases = instantaneous_phase[valid_indices]
454
470
 
455
471
  # Calculate PPC1
456
472
  n = len(spike_phases)
457
- if n <= 1:
458
- return 0, spike_phases
459
473
 
460
474
  # Convert phases to unit vectors in the complex plane
461
475
  unit_vectors = np.exp(1j * spike_phases)
bmtool/bmplot.py CHANGED
@@ -1012,6 +1012,8 @@ def plot_firing_rate_distribution(individual_stats: pd.DataFrame, groupby: Union
1012
1012
 
1013
1013
  return ax
1014
1014
 
1015
+ def plot_entrainment():
1016
+ pass
1015
1017
 
1016
1018
  def plot_3d_positions(config=None, populations_list=None, group_by=None, title=None, save_file=None, subset=None):
1017
1019
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bmtool
3
- Version: 0.6.8.2
3
+ Version: 0.6.8.3
4
4
  Summary: BMTool
5
5
  Home-page: https://github.com/cyneuro/bmtool
6
6
  Download-URL:
@@ -1,7 +1,7 @@
1
1
  bmtool/SLURM.py,sha256=umHYGUX2HDlZr6Zo89wQekGrK9mZdAi0rBdCA7a--hE,19904
2
2
  bmtool/__init__.py,sha256=ZStTNkAJHJxG7Pwiy5UgCzC4KlhMS5pUNPtUJZVwL_Y,136
3
3
  bmtool/__main__.py,sha256=TmFkmDxjZ6250nYD4cgGhn-tbJeEm0u-EMz2ajAN9vE,650
4
- bmtool/bmplot.py,sha256=YoI7StM9qeZqyRfFX4M7oUGFz50tXTDOMIUqjYozj9s,54066
4
+ bmtool/bmplot.py,sha256=ymyrNBctZoglsNA28733mXzM_l4b_3JIchXkQa2V2XE,54099
5
5
  bmtool/connectors.py,sha256=hWkUUcJ4tmas8NDOFPPjQT-TgTlPcpjuZsYyAW2WkPA,72242
6
6
  bmtool/graphs.py,sha256=K8BiughRUeXFVvAgo8UzrwpSClIVg7UfmIcvtEsEsk0,6020
7
7
  bmtool/manage.py,sha256=_lCU0qBQZ4jSxjzAJUd09JEetb--cud7KZgxQFbLGSY,657
@@ -9,7 +9,7 @@ bmtool/plot_commands.py,sha256=Tqujyf0c0u8olhiHOMwgUSJXIIE1hgjv6otb25G9cA0,12298
9
9
  bmtool/singlecell.py,sha256=XZAT_2n44EhwqVLnk3qur9aO7oJ-10axJZfwPBslM88,27219
10
10
  bmtool/synapses.py,sha256=gIkfLhKDG2dHHCVJJoKuQrFn_Qut843bfk_-s97wu6c,54553
11
11
  bmtool/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- bmtool/analysis/lfp.py,sha256=DXZvxYMVjFiCJS_IySQIUrpBQjdNuHVL8A7rxrHB7xo,16900
12
+ bmtool/analysis/lfp.py,sha256=bCpxqhdH6r71yXyqAv_M7BMq4x75lO7bctyyQi6pqdU,18186
13
13
  bmtool/analysis/spikes.py,sha256=qqJ4zD8xfvSwltlWm_Bhicdngzl6uBqH6Kn5wOMKRc8,11507
14
14
  bmtool/debug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  bmtool/debug/commands.py,sha256=AwtcR7BUUheM0NxvU1Nu234zCdpobhJv5noX8x5K2vY,583
@@ -19,9 +19,9 @@ bmtool/util/commands.py,sha256=zJF-fiLk0b8LyzHDfvewUyS7iumOxVnj33IkJDzux4M,64396
19
19
  bmtool/util/util.py,sha256=00vOAwTVIifCqouBoFoT0lBashl4fCalrk8fhg_Uq4c,56654
20
20
  bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  bmtool/util/neuron/celltuner.py,sha256=xSRpRN6DhPFz4q5buq_W8UmsD7BbUrkzYBEbKVloYss,87194
22
- bmtool-0.6.8.2.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
23
- bmtool-0.6.8.2.dist-info/METADATA,sha256=pE_Li9uoVYndKge-Gcm7gawxW71VbGfFhEL1lT0-kB8,20431
24
- bmtool-0.6.8.2.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
25
- bmtool-0.6.8.2.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
26
- bmtool-0.6.8.2.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
27
- bmtool-0.6.8.2.dist-info/RECORD,,
22
+ bmtool-0.6.8.3.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
23
+ bmtool-0.6.8.3.dist-info/METADATA,sha256=jT598Nn_w-_OrCzo7L0cW1wtrv-OKW2aIDhxAqXA2-Q,20431
24
+ bmtool-0.6.8.3.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
25
+ bmtool-0.6.8.3.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
26
+ bmtool-0.6.8.3.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
27
+ bmtool-0.6.8.3.dist-info/RECORD,,