py-neuromodulation 0.0.4__py3-none-any.whl → 0.0.5__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.
Files changed (80) hide show
  1. py_neuromodulation/ConnectivityDecoding/_get_grid_hull.m +34 -34
  2. py_neuromodulation/ConnectivityDecoding/_get_grid_whole_brain.py +95 -106
  3. py_neuromodulation/ConnectivityDecoding/_helper_write_connectome.py +107 -119
  4. py_neuromodulation/FieldTrip.py +589 -589
  5. py_neuromodulation/__init__.py +74 -13
  6. py_neuromodulation/_write_example_dataset_helper.py +83 -65
  7. py_neuromodulation/data/README +6 -6
  8. py_neuromodulation/data/dataset_description.json +8 -8
  9. py_neuromodulation/data/participants.json +32 -32
  10. py_neuromodulation/data/participants.tsv +2 -2
  11. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_coordsystem.json +5 -5
  12. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_space-mni_electrodes.tsv +11 -11
  13. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_channels.tsv +11 -11
  14. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.json +18 -18
  15. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vhdr +35 -35
  16. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/ieeg/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_ieeg.vmrk +13 -13
  17. py_neuromodulation/data/sub-testsub/ses-EphysMedOff/sub-testsub_ses-EphysMedOff_scans.tsv +2 -2
  18. py_neuromodulation/grid_cortex.tsv +40 -40
  19. py_neuromodulation/liblsl/libpugixml.so.1.12 +0 -0
  20. py_neuromodulation/liblsl/linux/bionic_amd64/liblsl.1.16.2.so +0 -0
  21. py_neuromodulation/liblsl/linux/bookworm_amd64/liblsl.1.16.2.so +0 -0
  22. py_neuromodulation/liblsl/linux/focal_amd46/liblsl.1.16.2.so +0 -0
  23. py_neuromodulation/liblsl/linux/jammy_amd64/liblsl.1.16.2.so +0 -0
  24. py_neuromodulation/liblsl/linux/jammy_x86/liblsl.1.16.2.so +0 -0
  25. py_neuromodulation/liblsl/linux/noble_amd64/liblsl.1.16.2.so +0 -0
  26. py_neuromodulation/liblsl/macos/amd64/liblsl.1.16.2.dylib +0 -0
  27. py_neuromodulation/liblsl/macos/arm64/liblsl.1.16.0.dylib +0 -0
  28. py_neuromodulation/liblsl/windows/amd64/liblsl.1.16.2.dll +0 -0
  29. py_neuromodulation/liblsl/windows/x86/liblsl.1.16.2.dll +0 -0
  30. py_neuromodulation/nm_IO.py +413 -417
  31. py_neuromodulation/nm_RMAP.py +496 -531
  32. py_neuromodulation/nm_analysis.py +993 -1074
  33. py_neuromodulation/nm_artifacts.py +30 -25
  34. py_neuromodulation/nm_bispectra.py +154 -168
  35. py_neuromodulation/nm_bursts.py +292 -198
  36. py_neuromodulation/nm_coherence.py +251 -205
  37. py_neuromodulation/nm_database.py +149 -0
  38. py_neuromodulation/nm_decode.py +918 -992
  39. py_neuromodulation/nm_define_nmchannels.py +300 -302
  40. py_neuromodulation/nm_features.py +144 -116
  41. py_neuromodulation/nm_filter.py +219 -219
  42. py_neuromodulation/nm_filter_preprocessing.py +79 -91
  43. py_neuromodulation/nm_fooof.py +139 -159
  44. py_neuromodulation/nm_generator.py +45 -37
  45. py_neuromodulation/nm_hjorth_raw.py +52 -73
  46. py_neuromodulation/nm_kalmanfilter.py +71 -58
  47. py_neuromodulation/nm_linelength.py +21 -33
  48. py_neuromodulation/nm_logger.py +66 -0
  49. py_neuromodulation/nm_mne_connectivity.py +149 -112
  50. py_neuromodulation/nm_mnelsl_generator.py +90 -0
  51. py_neuromodulation/nm_mnelsl_stream.py +116 -0
  52. py_neuromodulation/nm_nolds.py +96 -93
  53. py_neuromodulation/nm_normalization.py +173 -214
  54. py_neuromodulation/nm_oscillatory.py +423 -448
  55. py_neuromodulation/nm_plots.py +585 -612
  56. py_neuromodulation/nm_preprocessing.py +83 -0
  57. py_neuromodulation/nm_projection.py +370 -394
  58. py_neuromodulation/nm_rereference.py +97 -95
  59. py_neuromodulation/nm_resample.py +59 -50
  60. py_neuromodulation/nm_run_analysis.py +325 -435
  61. py_neuromodulation/nm_settings.py +289 -68
  62. py_neuromodulation/nm_settings.yaml +244 -0
  63. py_neuromodulation/nm_sharpwaves.py +423 -401
  64. py_neuromodulation/nm_stats.py +464 -480
  65. py_neuromodulation/nm_stream.py +398 -0
  66. py_neuromodulation/nm_stream_abc.py +166 -218
  67. py_neuromodulation/nm_types.py +193 -0
  68. {py_neuromodulation-0.0.4.dist-info → py_neuromodulation-0.0.5.dist-info}/METADATA +29 -26
  69. py_neuromodulation-0.0.5.dist-info/RECORD +83 -0
  70. {py_neuromodulation-0.0.4.dist-info → py_neuromodulation-0.0.5.dist-info}/WHEEL +1 -1
  71. {py_neuromodulation-0.0.4.dist-info → py_neuromodulation-0.0.5.dist-info}/licenses/LICENSE +21 -21
  72. py_neuromodulation/nm_EpochStream.py +0 -92
  73. py_neuromodulation/nm_across_patient_decoding.py +0 -927
  74. py_neuromodulation/nm_cohortwrapper.py +0 -435
  75. py_neuromodulation/nm_eval_timing.py +0 -239
  76. py_neuromodulation/nm_features_abc.py +0 -39
  77. py_neuromodulation/nm_settings.json +0 -338
  78. py_neuromodulation/nm_stream_offline.py +0 -359
  79. py_neuromodulation/utils/_logging.py +0 -24
  80. py_neuromodulation-0.0.4.dist-info/RECORD +0 -72
@@ -1,116 +1,144 @@
1
- import numpy as np
2
-
3
- from py_neuromodulation import (
4
- nm_hjorth_raw,
5
- nm_mne_connectivity,
6
- nm_sharpwaves,
7
- nm_coherence,
8
- nm_fooof,
9
- nm_nolds,
10
- nm_features_abc,
11
- nm_oscillatory,
12
- nm_bursts,
13
- nm_linelength,
14
- nm_bispectra,
15
- )
16
-
17
-
18
- class Features:
19
- """Class for calculating features."""
20
-
21
- features: list[nm_features_abc.Feature] = []
22
-
23
- def __init__(
24
- self, s: dict, ch_names: list[str], sfreq: int | float
25
- ) -> None:
26
- """_summary_
27
-
28
- Parameters
29
- ----------
30
- s : dict
31
- _description_
32
- ch_names : list[str]
33
- _description_
34
- sfreq : int | float
35
- _description_
36
-
37
- Raises
38
- ------
39
- ValueError
40
- _description_
41
- """
42
-
43
- self.features = []
44
-
45
- for feature in s["features"]:
46
- if s["features"][feature] is False:
47
- continue
48
- match feature:
49
- case "raw_hjorth":
50
- FeatureClass = nm_hjorth_raw.Hjorth
51
- case "return_raw":
52
- FeatureClass = nm_hjorth_raw.Raw
53
- case "bandpass_filter":
54
- FeatureClass = nm_oscillatory.BandPower
55
- case "stft":
56
- FeatureClass = nm_oscillatory.STFT
57
- case "fft":
58
- FeatureClass = nm_oscillatory.FFT
59
- case "welch":
60
- FeatureClass = nm_oscillatory.Welch
61
- case "sharpwave_analysis":
62
- FeatureClass = nm_sharpwaves.SharpwaveAnalyzer
63
- case "fooof":
64
- FeatureClass = nm_fooof.FooofAnalyzer
65
- case "nolds":
66
- FeatureClass = nm_nolds.Nolds
67
- case "coherence":
68
- FeatureClass = nm_coherence.NM_Coherence
69
- case "bursts":
70
- FeatureClass = nm_bursts.Burst
71
- case "linelength":
72
- FeatureClass = nm_linelength.LineLength
73
- case "mne_connectivity":
74
- FeatureClass = nm_mne_connectivity.MNEConnectivity
75
- case "bispectrum":
76
- FeatureClass = nm_bispectra.Bispectra
77
- case _:
78
- raise ValueError(f"Unknown feature found. Got: {feature}.")
79
-
80
- FeatureClass.test_settings(s, ch_names, sfreq)
81
- f_obj = FeatureClass(s, ch_names, sfreq)
82
- self.features.append(f_obj)
83
-
84
- def register_new_feature(self, feature: nm_features_abc.Feature) -> None:
85
- """Register new feature.
86
-
87
- Parameters
88
- ----------
89
- feature : nm_features_abc.Feature
90
- New feature to add to feature list
91
- """
92
- self.features.append(feature)
93
-
94
- def estimate_features(self, data: np.ndarray) -> dict:
95
- """Calculate features, as defined in settings.json
96
- Features are based on bandpower, raw Hjorth parameters and sharp wave
97
- characteristics.
98
-
99
- Parameters
100
- ----------
101
- data (np array) : (channels, time)
102
-
103
- Returns
104
- -------
105
- dat (dict): naming convention : channel_method_feature_(f_band)
106
- """
107
-
108
- features_compute = {}
109
-
110
- for feature in self.features:
111
- features_compute = feature.calc_feature(
112
- data,
113
- features_compute,
114
- )
115
-
116
- return features_compute
1
+ from typing import Protocol, Type, runtime_checkable, TYPE_CHECKING
2
+ from collections.abc import Sequence
3
+ import numpy as np
4
+
5
+ if TYPE_CHECKING:
6
+ from nm_settings import NMSettings
7
+
8
+ from py_neuromodulation.nm_types import ImportDetails, get_class, FeatureName
9
+
10
+
11
+ @runtime_checkable
12
+ class NMFeature(Protocol):
13
+ def __init__(
14
+ self, settings: "NMSettings", ch_names: Sequence[str], sfreq: int | float
15
+ ) -> None: ...
16
+
17
+ def calc_feature(self, data: np.ndarray) -> dict:
18
+ """
19
+ Feature calculation method. Each method needs to loop through all channels
20
+
21
+ Parameters
22
+ ----------
23
+ data : 'np.ndarray'
24
+ (channels, time)
25
+ feature_results : dict
26
+
27
+ Returns
28
+ -------
29
+ dict
30
+ """
31
+ ...
32
+
33
+
34
+ FEATURE_DICT: dict[FeatureName | str, ImportDetails] = {
35
+ "raw_hjorth": ImportDetails("nm_hjorth_raw", "Hjorth"),
36
+ "return_raw": ImportDetails("nm_hjorth_raw", "Raw"),
37
+ "bandpass_filter": ImportDetails("nm_oscillatory", "BandPower"),
38
+ "stft": ImportDetails("nm_oscillatory", "STFT"),
39
+ "fft": ImportDetails("nm_oscillatory", "FFT"),
40
+ "welch": ImportDetails("nm_oscillatory", "Welch"),
41
+ "sharpwave_analysis": ImportDetails("nm_sharpwaves", "SharpwaveAnalyzer"),
42
+ "fooof": ImportDetails("nm_fooof", "FooofAnalyzer"),
43
+ "nolds": ImportDetails("nm_nolds", "Nolds"),
44
+ "coherence": ImportDetails("nm_coherence", "NMCoherence"),
45
+ "bursts": ImportDetails("nm_bursts", "Burst"),
46
+ "linelength": ImportDetails("nm_linelength", "LineLength"),
47
+ "mne_connectivity": ImportDetails("nm_mne_connectivity", "MNEConnectivity"),
48
+ "bispectrum": ImportDetails("nm_bispectra", "Bispectra"),
49
+ }
50
+
51
+
52
+ class FeatureProcessors:
53
+ """Class for storing NMFeature objects and calculating features during processing"""
54
+
55
+ def __init__(
56
+ self, settings: "NMSettings", ch_names: list[str], sfreq: float
57
+ ) -> None:
58
+ """Initialize FeatureProcessors object with settings, channel names and sampling frequency.
59
+
60
+ Args:
61
+ settings (NMSettings): PyNM settings object
62
+ ch_names (list[str]): list of channel names
63
+ sfreq (float): sampling frequency in Hz
64
+ """
65
+ from py_neuromodulation import user_features
66
+
67
+ # Accept 'str' for custom features
68
+ self.features: dict[FeatureName | str, NMFeature] = {
69
+ feature_name: get_class(FEATURE_DICT[feature_name])(
70
+ settings, ch_names, sfreq
71
+ )
72
+ for feature_name in settings.features.get_enabled()
73
+ }
74
+
75
+ for feature_name, feature in user_features.items():
76
+ self.features[feature_name] = feature(settings, ch_names, sfreq)
77
+
78
+ def register_new_feature(self, feature_name: str, feature: NMFeature) -> None:
79
+ """Register new feature.
80
+
81
+ Parameters
82
+ ----------
83
+ feature : nm_features_abc.Feature
84
+ New feature to add to feature list
85
+ """
86
+ self.features[feature_name] = feature # type: ignore
87
+
88
+ def estimate_features(self, data: np.ndarray) -> dict:
89
+ """Calculate features, as defined in settings.json
90
+ Features are based on bandpower, raw Hjorth parameters and sharp wave
91
+ characteristics.
92
+
93
+ Parameters
94
+ ----------
95
+ data (np array) : (channels, time)
96
+
97
+ Returns
98
+ -------
99
+ dat (dict): naming convention : channel_method_feature_(f_band)
100
+ """
101
+
102
+ feature_results: dict = {}
103
+
104
+ for feature in self.features.values():
105
+ feature_results.update(feature.calc_feature(data))
106
+
107
+ return feature_results
108
+
109
+ def get_feature(self, fname: FeatureName) -> NMFeature:
110
+ return self.features[fname]
111
+
112
+
113
+ def add_custom_feature(feature_name: str, new_feature: Type[NMFeature]):
114
+ """Add a custom feature to the dictionary of user-defined features.
115
+ The feature will be automatically enabled in the settings,
116
+ and computed when the Stream.run() method is called.
117
+
118
+ Args:
119
+ feature_name (str): A name for the feature that will be used to
120
+ enable/disable the feature in settings and to store the feature
121
+ class instance in the DataProcessor
122
+
123
+ new_feature (NMFeature): Class that implements the user-defined
124
+ feature. It should implement the NMSettings protocol (defined
125
+ in this file).
126
+ """
127
+ from py_neuromodulation import user_features
128
+ from py_neuromodulation.nm_settings import NMSettings
129
+
130
+ user_features[feature_name] = new_feature
131
+ NMSettings._add_feature(feature_name)
132
+
133
+
134
+ def remove_custom_feature(feature_name: str):
135
+ """Remove a custom feature from the dictionary of user-defined features.
136
+
137
+ Args:
138
+ feature_name (str): Name of the feature to remove
139
+ """
140
+ from py_neuromodulation import user_features
141
+ from py_neuromodulation.nm_settings import NMSettings
142
+
143
+ user_features.pop(feature_name)
144
+ NMSettings._remove_feature(feature_name)