Skip to content

Releases: Eden-Kramer-Lab/spectral_connectivity

v2.0.0

27 Oct 14:39

Choose a tag to compare

[2.0.0] - 2025-10-27

BREAKING CHANGES

3D Input Requirement for Multitaper Class

BREAKING CHANGE: Multitaper now requires 3D input arrays with explicit (n_time_samples, n_trials, n_signals) shape. Previously ambiguous 2D arrays now raise informative ValueError.

  • Migration Required: Use the new prepare_time_series() helper function to convert 1D/2D arrays to 3D format

  • Why: Eliminates dangerous ambiguity where (n_time, n) could mean either:

    • (n_time, 1 trial, n signals) OR
    • (n_time, n trials, 1 signal)

    Silent misinterpretation produces scientifically incorrect results.

Migration Example:

# Before (ambiguous)
mt = Multitaper(eeg_data, sampling_frequency=1000)

# After (explicit)
from spectral_connectivity.transforms import prepare_time_series
eeg_3d = prepare_time_series(eeg_data, axis='signals')  # or axis='trials'
mt = Multitaper(eeg_3d, sampling_frequency=1000)

Nyquist Frequency Now Included for Even-Length FFTs

BREAKING CHANGE: Corrected frequency bin indexing to include Nyquist frequency for even-length FFTs

  • Impact on results:
    • Even-length FFTs (N=1024): Now return 513 frequencies instead of 512 (adds Nyquist bin)
    • Odd-length FFTs (N=1023): No change (still return 512 frequencies)
  • Affected functions: All connectivity measures using @_non_negative_frequencies decorator
  • Scientific justification: The Nyquist frequency (sampling_rate/2) represents valid spectral information that should not be discarded
  • See CHANGELOG "Unreleased" section for complete details and migration guidance

Development Tooling Changes

  • BREAKING: Migrated from black to ruff format for code formatting
  • BREAKING: Migrated from flake8/pydocstyle to ruff for linting
  • Development workflows now use ruff format and ruff check commands
  • All formatting/linting configurations moved to pyproject.toml under [tool.ruff]
  • Developers must update their tooling: pip install ruff (100x faster than previous tools)

Added

  • prepare_time_series() helper function for safe dimension handling:
    • Converts 1D/2D arrays to required 3D format
    • Explicit axis parameter to clarify dimension meaning
    • Prevents ambiguous dimension interpretation
    • Required for migration to v2.0.0
  • Comprehensive notebook snapshot testing with Syrupy:
    • 27 snapshot tests covering all tutorial notebook examples
    • Tests validate output shapes, data types, and numerical properties
    • Ensures tutorial examples remain accurate across releases
    • Automatically catches breaking changes in example code
    • Uses Syrupy's snapshot testing for efficient test maintenance
  • Test infrastructure (tests/conftest.py):
    • Added pytest fixture to reset numpy random state before each test
    • Ensures consistent test reproducibility with fixed seed (42)
    • Helps prevent test ordering issues from shared random state
    • Auto-runs before every test without explicit fixture declaration
  • Physical constants with scientific rationale (spectral_connectivity/transforms.py):
    • MIN_EIGENVALUE_THRESHOLD = 0.9: Minimum eigenvalue for low-bias tapers
      • Documents that 90% of taper energy must be in main lobe to reduce spectral leakage
      • Reference: Thomson (1982), "Spectrum estimation and harmonic analysis"
    • TAPER_MULTIPLIER = 2.0: Multiplier for calculating number of tapers
      • Documents the theoretical basis: ~2*NW orthogonal Slepian sequences are well-concentrated
      • Reference: Slepian (1978), "Prolate spheroidal wave functions"
    • All magic numbers replaced with named constants throughout codebase
    • Docstrings updated to reference constants while preserving readability
  • Comprehensive test suite for advanced connectivity measures (tests/test_advanced_connectivity.py):
    • 18 test methods covering canonical_coherence(), global_coherence(), and group_delay()
    • Tests validate output shapes, value ranges, and mathematical properties (symmetry, antisymmetry)
    • Integration tests for complete Multitaper → Connectivity → advanced measures workflow
    • Tests handle edge cases: different group sizes, single signals, non-contiguous labels
    • Graceful handling of group_delay edge case when no frequencies are significant
  • Parameter helper functions for guided multitaper analysis:
    • estimate_frequency_resolution(): Calculate frequency resolution from parameters
    • estimate_n_tapers(): Calculate number of tapers from time-halfbandwidth product
    • suggest_parameters(): Get parameter recommendations for your data
    • MultitaperParameters TypedDict for type-safe parameter handling
  • summarize_parameters() method to Multitaper class:
    • Human-readable summary of all analysis parameters
    • Shows computed values (n_tapers, frequency_resolution, n_windows)
    • Displays overlap percentage for windowing
    • Formatted for terminal/notebook output
  • Enhanced time_halfbandwidth_product docstring with formulas and practical guidance:
    • Mathematical relationship to frequency resolution and n_tapers
    • Typical values (NW=2,3,4,5+) with trade-off explanations
    • Examples for achieving target resolutions (1 Hz, 5 Hz, 10 Hz)
    • Cross-references to helper functions
  • Comprehensive test suite for parameter helpers (test_parameter_helpers.py):
    • 22 tests covering all helper functions
    • Domain-specific tests (EEG, LFP typical parameters)
    • Edge cases (conflicting parameters, impossible resolutions)
    • Consistency checks with actual Multitaper behavior

Changed

  • Complete type hint coverage (spectral_connectivity/transforms.py, spectral_connectivity/connectivity.py):
    • Added type hints to ALL 28 previously untyped functions:
      • transforms._make_tapers(): Added parameter and return types
      • connectivity.py: 27 functions including all connectivity measures and helper functions
    • Used TYPE_CHECKING block to avoid circular imports for Multitaper type
    • Added Literal types for multiple_comparisons_method parameter
    • Fixed Optional/None handling in _get_independent_frequency_step() and _bandpass()
    • Fixed phase_lag_index return type (extract real part from complex result)
    • Enabled disallow_untyped_defs = true for transforms and connectivity modules
    • All 9 modules now have strict type checking enabled
    • 100% of public API is now fully type-annotated
  • Test coverage improvements:
    • Overall coverage increased from 85% to 88%
    • connectivity.py coverage improved from 71% to 93%
    • Fixed snapshot tests after Nyquist frequency bin correction
    • Updated test assertions to use correct frequency bin calculation: N//2 + 1 instead of (N+1)//2
  • Improved method discovery in multitaper_connectivity() wrapper:
    • Replaced dir() with inspect.getmembers(predicate=inspect.isfunction) for type-safe method filtering
    • Automatically excludes properties and classmethods (more robust)
    • Renamed bad_methods to excluded_methods with clear categorization
    • Changed from list to set for O(1) membership testing
    • Added test test_method_discovery_with_inspect() to verify behavior
  • Documented design decision for adjust_for_multiple_comparisons():
    • Replaced TODO comment with clear explanation of current behavior
    • Explained why axis parameter is not implemented (standard approach treats all p-values as single family)
    • Left open for future enhancement if needed

Removed

  • All TODO comments from codebase (2 resolved)

Changed

  • Development tooling modernization:
    • Migrated from black to ruff format for code formatting (100x faster)
    • Migrated from flake8/pydocstyle to ruff check for linting
    • Updated GitHub Actions CI to use ruff format --check and ruff check
    • Updated CLAUDE.md with new ruff commands
    • All formatting and linting now unified under single fast tool
  • Code quality improvements:
    • Applied ruff format to all source files (10 files reformatted)
    • Fixed 19 auto-fixable ruff linting issues
    • All source code and tests now pass ruff check with zero warnings
    • Type hints improved with better union handling for detrend() function
  • Updated tutorial notebooks to use prepare_time_series() for 3D input
  • Improved random number generation in tests for better isolation

Fixed

  • MyPy type annotation error in detrend() function (transforms.py:1867-1876):
    • Fixed union type handling for bp parameter (now int | list[int] | NDArray[np.integer])
    • Added support for list input in addition to int and ndarray
    • Eliminated unreachable code warnings from MyPy
    • All 9 source files now pass strict mypy type checking

Nyquist Frequency Fix (from earlier release)

  • Critical bug fix: Corrected frequency bin indexing to include Nyquist frequency for even-length FFTs
    • Affected code: Changed frequency indexing from (N+1)//2 to N//2 + 1 in three locations:
      • _non_negative_frequencies decorator (line 107)
      • canonical_coherence method (line 638)
      • _estimate_spectral_granger_prediction function (line 2108)
    • Impact on results:
      • Even-length FFTs (N=1024): Now return 513 frequencies instead of 512 (adds Nyquist bin)
      • Odd-length FFTs (N=1023): No change (still return 512 frequencies)
    • Affected functions: All connectivity measures using @_non_negative_frequencies decorator:
      • coherency(), coherence_magnitude(), coherence_phase(), imaginary_coherence()
      • phase_lag_index(), weighted_phase_lag_index(), debiased_squared_phase_lag_index()
      • debiased_squared_weighted_phase_lag_index(), phase_locking_value(), pairwise_phase_consistency()
      • power(), all Granger causality measures (DTF, PDC, etc.)
    • Scientific justification: The Nyquist frequency (sampling_rate/2) represents the highest frequency
      that can be unambiguously represented in sampled data....
Read more

1.1.2

19 Oct 18:52

Choose a tag to compare

Minor fixes.

v1.1.0

09 Dec 00:59

Choose a tag to compare

  • Archival release for JOSS

v1.0.3

15 Sep 00:43

Choose a tag to compare

  • Add paper for JOSS
  • Blockwise computations for efficiency.

v1.0.2

10 Jun 15:20

Choose a tag to compare

  • Update citations

v1.0.1

10 Jun 14:34

Choose a tag to compare

  • add power spectrum confidence intervals

v1.0.0

22 May 19:40

Choose a tag to compare

  • Added GPU support

v0.2.6.dev0

14 Oct 13:35

Choose a tag to compare

  • Added global coherence
  • Added ability to take expectation over time windows

v0.2.5.dev0

14 Oct 20:48

Choose a tag to compare

v0.2.5.dev0 Pre-release
Pre-release

Add xarray wrapper from @mmyros.

v0.2.3.dev0

11 Oct 04:43

Choose a tag to compare

v0.2.3.dev0 Pre-release
Pre-release
  • Fix keys
  • use lru_cache