py-neuromodulation 0.0.2__py3-none-any.whl → 0.0.4__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 (51) hide show
  1. py_neuromodulation/ConnectivityDecoding/Automated Anatomical Labeling 3 (Rolls 2020).nii +0 -0
  2. py_neuromodulation/ConnectivityDecoding/_get_grid_hull.m +34 -0
  3. py_neuromodulation/ConnectivityDecoding/_get_grid_whole_brain.py +106 -0
  4. py_neuromodulation/ConnectivityDecoding/_helper_write_connectome.py +119 -0
  5. py_neuromodulation/ConnectivityDecoding/mni_coords_cortical_surface.mat +0 -0
  6. py_neuromodulation/ConnectivityDecoding/mni_coords_whole_brain.mat +0 -0
  7. py_neuromodulation/ConnectivityDecoding/rmap_func_all.nii +0 -0
  8. py_neuromodulation/ConnectivityDecoding/rmap_struc.nii +0 -0
  9. py_neuromodulation/{helper.py → _write_example_dataset_helper.py} +1 -1
  10. py_neuromodulation/nm_EpochStream.py +2 -3
  11. py_neuromodulation/nm_IO.py +43 -70
  12. py_neuromodulation/nm_RMAP.py +308 -11
  13. py_neuromodulation/nm_analysis.py +1 -1
  14. py_neuromodulation/nm_artifacts.py +25 -0
  15. py_neuromodulation/nm_bispectra.py +64 -29
  16. py_neuromodulation/nm_bursts.py +44 -30
  17. py_neuromodulation/nm_coherence.py +2 -1
  18. py_neuromodulation/nm_features.py +4 -2
  19. py_neuromodulation/nm_filter.py +63 -32
  20. py_neuromodulation/nm_filter_preprocessing.py +91 -0
  21. py_neuromodulation/nm_fooof.py +47 -29
  22. py_neuromodulation/nm_mne_connectivity.py +1 -1
  23. py_neuromodulation/nm_normalization.py +50 -74
  24. py_neuromodulation/nm_oscillatory.py +151 -31
  25. py_neuromodulation/nm_plots.py +13 -10
  26. py_neuromodulation/nm_rereference.py +10 -8
  27. py_neuromodulation/nm_run_analysis.py +28 -13
  28. py_neuromodulation/nm_settings.json +51 -3
  29. py_neuromodulation/nm_sharpwaves.py +103 -136
  30. py_neuromodulation/nm_stats.py +44 -30
  31. py_neuromodulation/nm_stream_abc.py +18 -10
  32. py_neuromodulation/nm_stream_offline.py +188 -46
  33. py_neuromodulation/utils/_logging.py +24 -0
  34. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.4.dist-info}/METADATA +72 -32
  35. py_neuromodulation-0.0.4.dist-info/RECORD +72 -0
  36. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.4.dist-info}/WHEEL +1 -1
  37. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/MOV_aligned_features_ch_ECOG_RIGHT_0_all.png +0 -0
  38. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/all_feature_plt.pdf +0 -0
  39. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_FEATURES.csv +0 -182
  40. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_LM_ML_RES.p +0 -0
  41. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SETTINGS.json +0 -273
  42. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_SIDECAR.json +0 -6
  43. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_decoding_performance.png +0 -0
  44. py_neuromodulation/data/derivatives/sub-testsub_ses-EphysMedOff_task-gripforce_run-0/sub-testsub_ses-EphysMedOff_task-gripforce_run-0_nm_channels.csv +0 -11
  45. py_neuromodulation/py_neuromodulation.egg-info/PKG-INFO +0 -104
  46. py_neuromodulation/py_neuromodulation.egg-info/dependency_links.txt +0 -1
  47. py_neuromodulation/py_neuromodulation.egg-info/requires.txt +0 -26
  48. py_neuromodulation/py_neuromodulation.egg-info/top_level.txt +0 -1
  49. py_neuromodulation-0.0.2.dist-info/RECORD +0 -73
  50. /py_neuromodulation/{py_neuromodulation.egg-info/SOURCES.txt → utils/__init__.py} +0 -0
  51. {py_neuromodulation-0.0.2.dist-info → py_neuromodulation-0.0.4.dist-info/licenses}/LICENSE +0 -0
@@ -1,14 +1,304 @@
1
- import enum
2
- import nibabel as nib
3
1
  import numpy as np
4
2
  import os
5
- #from numba import jit
3
+ import wget
4
+
5
+
6
+ # from numba import jit
6
7
  from scipy import stats
8
+ import scipy.io as sio
7
9
  import pandas as pd
10
+ from typing import Union, Tuple, List
11
+ import nibabel as nib
12
+ from matplotlib import pyplot as plt
13
+
14
+ import py_neuromodulation
8
15
 
9
16
  from py_neuromodulation import nm_plots
10
17
 
11
- class RMAPChannelSelector:
18
+ LIST_STRUC_UNCONNECTED_GRIDPOINTS_HULL = [256, 385, 417, 447, 819, 914]
19
+ LIST_STRUC_UNCONNECTED_GRIDPOINTS_WHOLEBRAIN = [
20
+ 1,
21
+ 8,
22
+ 16,
23
+ 33,
24
+ 34,
25
+ 35,
26
+ 36,
27
+ 37,
28
+ 51,
29
+ 75,
30
+ 77,
31
+ 78,
32
+ 99,
33
+ 109,
34
+ 115,
35
+ 136,
36
+ 155,
37
+ 170,
38
+ 210,
39
+ 215,
40
+ 243,
41
+ 352,
42
+ 359,
43
+ 361,
44
+ 415,
45
+ 416,
46
+ 422,
47
+ 529,
48
+ 567,
49
+ 569,
50
+ 622,
51
+ 623,
52
+ 625,
53
+ 627,
54
+ 632,
55
+ 633,
56
+ 634,
57
+ 635,
58
+ 639,
59
+ 640,
60
+ 641,
61
+ 643,
62
+ 644,
63
+ 650,
64
+ 661,
65
+ 663,
66
+ 667,
67
+ 683,
68
+ 684,
69
+ 685,
70
+ 704,
71
+ 708,
72
+ 722,
73
+ 839,
74
+ 840,
75
+ 905,
76
+ 993,
77
+ 1011,
78
+ ]
79
+
80
+
81
+ class ConnectivityChannelSelector:
82
+
83
+ def __init__(
84
+ self,
85
+ whole_brain_connectome: bool = True,
86
+ func_connectivity: bool = True,
87
+ ) -> None:
88
+ """ConnectivityChannelSelector
89
+
90
+ Parameters
91
+ ----------
92
+ whole_brain_connectome : bool, optional
93
+ if True a 1236 whole-brain point grid is chosen,
94
+ if False, a 1025 point grid of the cortical hull is loaded,
95
+ by default True
96
+ func_connectivity : bool, optional
97
+ if true, functional connectivity fMRI is loaded,
98
+ if false structural dMRIby, default True
99
+ """
100
+
101
+ self.connectome_name = self._get_connectome_name(
102
+ whole_brain_connectome, func_connectivity
103
+ )
104
+
105
+ self.whole_brain_connectome = whole_brain_connectome
106
+ self.func_connectivity = func_connectivity
107
+
108
+ self.PATH_CONN_DECODING = os.path.join(
109
+ py_neuromodulation.__path__[0],
110
+ "ConnectivityDecoding",
111
+ )
112
+
113
+ if whole_brain_connectome:
114
+ self.PATH_GRID = os.path.join(
115
+ self.PATH_CONN_DECODING,
116
+ "mni_coords_whole_brain.mat",
117
+ )
118
+ self.grid = sio.loadmat(self.PATH_GRID)["downsample_ctx"]
119
+ if func_connectivity is False:
120
+ # reduce the grid to only valid points that are not in LIST_STRUC_UNCONNECTED_GRIDPOINTS_WHOLEBRAIN
121
+ self.grid = np.delete(
122
+ self.grid,
123
+ LIST_STRUC_UNCONNECTED_GRIDPOINTS_WHOLEBRAIN,
124
+ axis=0,
125
+ )
126
+ else:
127
+ self.PATH_GRID = os.path.join(
128
+ self.PATH_CONN_DECODING,
129
+ "mni_coords_cortical_surface.mat",
130
+ )
131
+ self.grid = sio.loadmat(self.PATH_GRID)["downsample_ctx"]
132
+ if func_connectivity is False:
133
+ # reduce the grid to only valid points that are not in LIST_STRUC_UNCONNECTED_GRIDPOINTS_HULL
134
+ self.grid = np.delete(
135
+ self.grid, LIST_STRUC_UNCONNECTED_GRIDPOINTS_HULL, axis=0
136
+ )
137
+
138
+ if func_connectivity:
139
+ self.RMAP_arr = nib.load(
140
+ os.path.join(self.PATH_CONN_DECODING, "RMAP_func_all.nii")
141
+ ).get_fdata()
142
+ else:
143
+ self.RMAP_arr = nib.load(
144
+ os.path.join(self.PATH_CONN_DECODING, "RMAP_struc.nii")
145
+ ).get_fdata()
146
+
147
+ def _get_connectome_name(
148
+ self, whole_brain_connectome: str, func_connectivity: str
149
+ ):
150
+
151
+ connectome_name = "connectome_"
152
+ if whole_brain_connectome:
153
+ connectome_name += "whole_brain_"
154
+ else:
155
+ connectome_name += "hull_"
156
+ if func_connectivity:
157
+ connectome_name += "func"
158
+ else:
159
+ connectome_name += "struc"
160
+ return connectome_name
161
+
162
+ def get_available_connectomes(self) -> list:
163
+ """Return list of saved connectomes in the
164
+ package folder/ConnectivityDecoding/connectome_folder/ folder.
165
+
166
+ Returns
167
+ -------
168
+ list_connectomes: list
169
+ """
170
+ return os.listdir(
171
+ os.path.join(
172
+ self.PATH_CONN_DECODING,
173
+ "connectome_folder",
174
+ )
175
+ )
176
+
177
+ def plot_grid(self) -> None:
178
+ """Plot the loaded template grid that passed coordinates are matched to."""
179
+
180
+ fig = plt.figure()
181
+ ax = fig.add_subplot(111, projection="3d")
182
+ ax.scatter(
183
+ self.grid[:, 0], self.grid[:, 1], self.grid[:, 2], s=50, alpha=0.2
184
+ )
185
+ plt.show()
186
+
187
+ def get_closest_node(
188
+ self, coord: Union[List, np.array]
189
+ ) -> Tuple[List, List]:
190
+ """Given a list or np.array of coordinates, return the closest nodes in the
191
+ grid and their indices.
192
+
193
+ Parameters
194
+ ----------
195
+ coord : np.array
196
+ MNI coordinates with shape (num_channels, 3)
197
+
198
+ Returns
199
+ -------
200
+ Tuple[List, List]
201
+ Grid coordinates, grid indices
202
+ """
203
+
204
+ idx_ = []
205
+ for c in coord:
206
+ dist = np.linalg.norm(self.grid - c, axis=1)
207
+ idx_.append(np.argmin(dist))
208
+
209
+ return [self.grid[idx] for idx in idx_], idx_
210
+
211
+ def get_rmap_correlations(
212
+ self, fps: Union[list, np.array], RMAP_use: np.array = None
213
+ ) -> List:
214
+ """Calculate correlations of passed fingerprints with the RMAP
215
+
216
+ Parameters
217
+ ----------
218
+ fps : Union[list, np.array]
219
+ List of fingerprints
220
+ RMAP_use : np.array, optional
221
+ Passed RMAP, by default None
222
+
223
+ Returns
224
+ -------
225
+ List
226
+ correlation values
227
+ """
228
+
229
+ RMAP_ = self.RMAP_arr if RMAP_use is None else RMAP_use
230
+ RMAP_ = RMAP_.flatten()
231
+ corrs = []
232
+ for fp in fps:
233
+ corrs.append(np.corrcoef(RMAP_, fp.flatten())[0][1])
234
+ return corrs
235
+
236
+ def load_connectome(
237
+ self,
238
+ whole_brain_connectome: bool = None,
239
+ func_connectivity: bool = None,
240
+ ) -> None:
241
+ """Load connectome, if not available download connectome from
242
+ Zenodo.
243
+
244
+ Parameters
245
+ ----------
246
+ whole_brain_connectome : bool, optional
247
+ if true whole brain connectome
248
+ if false cortical hull grid connectome, by default None
249
+ func_connectivity : bool, optional
250
+ if true fMRI if false dMRI, by default None
251
+ """
252
+
253
+ if whole_brain_connectome is not None:
254
+ self.whole_brain_connectome = whole_brain_connectome
255
+ if func_connectivity is not None:
256
+ self.func_connectivity = func_connectivity
257
+
258
+ self.connectome_name = self._get_connectome_name(
259
+ self.whole_brain_connectome, self.func_connectivity
260
+ )
261
+
262
+ PATH_CONNECTOME = os.path.join(
263
+ self.PATH_CONN_DECODING,
264
+ "connectome_folder",
265
+ self.connectome_name + ".mat",
266
+ )
267
+
268
+ if os.path.exists(PATH_CONNECTOME) is False:
269
+ user_input = input(
270
+ "Do you want to download the connectome? (yes/no): "
271
+ ).lower()
272
+ if user_input == "yes":
273
+ self._download_connectome()
274
+ elif user_input == "no":
275
+ print("Connectome missing, has to be downloaded")
276
+
277
+ self.connectome = sio.loadmat(PATH_CONNECTOME)
278
+
279
+ def get_grid_fingerprints(self, grid_idx: Union[list, np.array]) -> list:
280
+ return [self.connectome[str(grid_idx)] for grid_idx in grid_idx]
281
+
282
+ def download_connectome(
283
+ self,
284
+ ):
285
+ # download the connectome from the Zenodo API
286
+ print("Downloading the connectome...")
287
+
288
+ record_id = "10804702"
289
+ file_name = self.connectome_name
290
+
291
+ wget.download(
292
+ f"https://zenodo.org/api/records/{record_id}/files/{file_name}/content",
293
+ out=os.path.join(
294
+ self.PATH_CONN_DECODING,
295
+ "connectome_folder",
296
+ f"{self.connectome_name}.mat",
297
+ ),
298
+ )
299
+
300
+
301
+ class RMAPCross_Val_ChannelSelector:
12
302
 
13
303
  def __init__(self) -> None:
14
304
  pass
@@ -90,7 +380,7 @@ class RMAPChannelSelector:
90
380
  return r
91
381
 
92
382
  @staticmethod
93
- #@jit(nopython=True)
383
+ # @jit(nopython=True)
94
384
  def calculate_RMap_numba(fp, performances):
95
385
  # The RMap also needs performances; for every fingerprint / channel
96
386
  # Save the corresponding performance
@@ -112,7 +402,7 @@ class RMAPChannelSelector:
112
402
  return RMAP
113
403
 
114
404
  @staticmethod
115
- #@jit(nopython=True)
405
+ # @jit(nopython=True)
116
406
  def get_corr_numba(fp, fp_test):
117
407
  val = np.corrcoef(fp_test, fp)[0][1]
118
408
  return val
@@ -126,7 +416,7 @@ class RMAPChannelSelector:
126
416
  per_predict = []
127
417
 
128
418
  for idx_left_out, f_left_out in enumerate(l_fps_names):
129
- print(idx_left_out)
419
+ # print(idx_left_out)
130
420
  l_cv = l_fps_dat.copy()
131
421
  per_cv = l_per.copy()
132
422
 
@@ -160,7 +450,7 @@ class RMAPChannelSelector:
160
450
  per_left_out = []
161
451
 
162
452
  for subject_test in sub_list:
163
- print(subject_test)
453
+ # print(subject_test)
164
454
  idx_test = [
165
455
  idx for idx, f in enumerate(l_fps_names) if subject_test in f
166
456
  ]
@@ -224,11 +514,18 @@ class RMAPChannelSelector:
224
514
  idx_max = np.argmax(np.array(fp_pairs)[:, 3])
225
515
  return fp_pairs[idx_max][0:3]
226
516
 
227
- def plot_performance_prediction_correlation(per_left_out, per_predict, out_path_save: str = None):
517
+ def plot_performance_prediction_correlation(
518
+ per_left_out, per_predict, out_path_save: str = None
519
+ ):
228
520
  df_plt_corr = pd.DataFrame()
229
521
  df_plt_corr["test_performance"] = per_left_out
230
- df_plt_corr["struct_conn_predict"] = per_predict # change "struct" with "funct" for functional connectivity
522
+ df_plt_corr["struct_conn_predict"] = (
523
+ per_predict # change "struct" with "funct" for functional connectivity
524
+ )
231
525
 
232
526
  nm_plots.reg_plot(
233
- x_col="test_performance", y_col="struct_conn_predict", data=df_plt_corr, out_path_save=out_path_save
527
+ x_col="test_performance",
528
+ y_col="struct_conn_predict",
529
+ data=df_plt_corr,
530
+ out_path_save=out_path_save,
234
531
  )
@@ -221,7 +221,7 @@ class Feature_Reader:
221
221
  pd.DataFrame: z-scored feature_arr
222
222
  """
223
223
  cols_norm = [c for c in self.feature_arr.columns if "time" not in c]
224
- feature_arr_norm = stats.zscore(self.feature_arr[cols_norm])
224
+ feature_arr_norm = stats.zscore(self.feature_arr[cols_norm], nan_policy="omit")
225
225
  feature_arr_norm["time"] = self.feature_arr["time"]
226
226
  return feature_arr_norm
227
227
 
@@ -0,0 +1,25 @@
1
+ from pyparrm import PARRM
2
+
3
+
4
+ class PARRMArtifactRejection:
5
+ def __init__(self, data, sampling_freq, artefact_freq, verbose=False):
6
+ self.data = data
7
+ self.sampling_freq = sampling_freq
8
+ self.artefact_freq = artefact_freq
9
+ self.verbose = verbose
10
+
11
+ self.parrm = PARRM(
12
+ data=data,
13
+ sampling_freq=sampling_freq,
14
+ artefact_freq=artefact_freq,
15
+ verbose=False,
16
+ )
17
+
18
+ def filter_data(self):
19
+ self.parrm.find_period()
20
+ self.parrm.create_filter(
21
+ filter_direction="both",
22
+ )
23
+ filtered_data = self.parrm.filter_data()
24
+
25
+ return filtered_data
@@ -4,9 +4,11 @@ from pybispectra import compute_fft, get_example_data_paths, WaveShape
4
4
 
5
5
  from py_neuromodulation import nm_features_abc
6
6
 
7
- class Bispectra(nm_features_abc.Feature):
8
7
 
9
- def __init__(self, settings: dict, ch_names: Iterable[str], sfreq: int | float) -> None:
8
+ class Bispectra(nm_features_abc.Feature):
9
+ def __init__(
10
+ self, settings: dict, ch_names: Iterable[str], sfreq: int | float
11
+ ) -> None:
10
12
  super().__init__(settings, ch_names, sfreq)
11
13
  self.sfreq = sfreq
12
14
  self.ch_names = ch_names
@@ -40,18 +42,14 @@ class Bispectra(nm_features_abc.Feature):
40
42
  )
41
43
 
42
44
  test_range("f1s", s["bispectrum"]["f1s"])
43
- test_range("f2s", s["bispectrum"]["f2s"])
45
+ test_range("f2s", s["bispectrum"]["f2s"])
44
46
 
45
- for feature_name, val in s["bispectrum"][
46
- "components"
47
- ].items():
47
+ for feature_name, val in s["bispectrum"]["components"].items():
48
48
  assert isinstance(
49
49
  val, bool
50
50
  ), f"bispectrum component {feature_name} has to be of type bool, got {val}"
51
-
52
- for feature_name, val in s["bispectrum"][
53
- "bispectrum_features"
54
- ].items():
51
+
52
+ for feature_name, val in s["bispectrum"]["bispectrum_features"].items():
55
53
  assert isinstance(
56
54
  val, bool
57
55
  ), f"bispectrum feature {feature_name} has to be of type bool, got {val}"
@@ -66,10 +64,15 @@ class Bispectra(nm_features_abc.Feature):
66
64
  f"specified frequency_ranges_hz: {s['frequency_ranges_hz']}"
67
65
  )
68
66
 
69
- def compute_bs_features(self, spectrum_ch: np.array, features_compute: dict, ch_name: str, component: str, f_band: str) -> dict:
70
-
67
+ def compute_bs_features(
68
+ self,
69
+ spectrum_ch: np.array,
70
+ features_compute: dict,
71
+ ch_name: str,
72
+ component: str,
73
+ f_band: str,
74
+ ) -> dict:
71
75
  for bispectrum_feature in self.s["bispectrum"]["bispectrum_features"]:
72
-
73
76
  if bispectrum_feature == "mean":
74
77
  func = np.nanmean
75
78
  if bispectrum_feature == "sum":
@@ -78,9 +81,25 @@ class Bispectra(nm_features_abc.Feature):
78
81
  func = np.nanvar
79
82
 
80
83
  if f_band is not None:
81
- str_feature = "_".join([ch_name, "Bispectrum", component, bispectrum_feature, f_band])
84
+ str_feature = "_".join(
85
+ [
86
+ ch_name,
87
+ "Bispectrum",
88
+ component,
89
+ bispectrum_feature,
90
+ f_band,
91
+ ]
92
+ )
82
93
  else:
83
- str_feature = "_".join([ch_name, "Bispectrum", component, bispectrum_feature, "whole_fband_range"])
94
+ str_feature = "_".join(
95
+ [
96
+ ch_name,
97
+ "Bispectrum",
98
+ component,
99
+ bispectrum_feature,
100
+ "whole_fband_range",
101
+ ]
102
+ )
84
103
 
85
104
  features_compute[str_feature] = func(spectrum_ch)
86
105
 
@@ -89,22 +108,29 @@ class Bispectra(nm_features_abc.Feature):
89
108
  def calc_feature(self, data: np.array, features_compute: dict) -> dict:
90
109
  for ch_idx, ch_name in enumerate(self.ch_names):
91
110
  fft_coeffs, freqs = compute_fft(
92
- data=np.expand_dims(data[ch_idx, :], axis=(0,1)),
111
+ data=np.expand_dims(data[ch_idx, :], axis=(0, 1)),
93
112
  sampling_freq=self.sfreq,
94
113
  n_points=data.shape[1],
95
- verbose=False,
114
+ verbose=False,
96
115
  )
97
116
 
98
- f_spectrum_range = freqs[np.logical_and(freqs >= np.min([self.f1s, self.f2s]), freqs <= np.max([self.f1s, self.f2s]))]
117
+ f_spectrum_range = freqs[
118
+ np.logical_and(
119
+ freqs >= np.min([self.f1s, self.f2s]),
120
+ freqs <= np.max([self.f1s, self.f2s]),
121
+ )
122
+ ]
99
123
 
100
124
  waveshape = WaveShape(
101
125
  data=fft_coeffs,
102
- freqs=freqs.astype(int),
126
+ freqs=freqs,
103
127
  sampling_freq=self.sfreq,
104
128
  verbose=False,
105
129
  )
106
130
 
107
- waveshape.compute(f1s=tuple(self.f1s), f2s=tuple(self.f2s))
131
+ waveshape.compute(
132
+ f1s=(self.f1s[0], self.f1s[-1]), f2s=(self.f2s[0], self.f2s[-1])
133
+ )
108
134
 
109
135
  bispectrum = np.squeeze(waveshape.results._data)
110
136
 
@@ -120,14 +146,23 @@ class Bispectra(nm_features_abc.Feature):
120
146
  spectrum_ch = np.angle(bispectrum)
121
147
 
122
148
  for fb in self.s["bispectrum"]["frequency_bands"]:
123
- range_ = (f_spectrum_range >= self.s["frequency_ranges_hz"][fb][0]) \
124
- & (f_spectrum_range <= self.s["frequency_ranges_hz"][fb][1])
125
- #waveshape.results.plot()
126
- data_bs = spectrum_ch[range_, range_]
127
-
128
- features_compute = self.compute_bs_features(data_bs, features_compute, ch_name, component, fb)
129
-
130
- if self.s["bispectrum"]["compute_features_for_whole_fband_range"]:
131
- features_compute = self.compute_bs_features(spectrum_ch, features_compute, ch_name, component, None)
149
+ range_ = (
150
+ f_spectrum_range >= self.s["frequency_ranges_hz"][fb][0]
151
+ ) & (
152
+ f_spectrum_range <= self.s["frequency_ranges_hz"][fb][1]
153
+ )
154
+ # waveshape.results.plot()
155
+ data_bs = spectrum_ch[range_, range_]
156
+
157
+ features_compute = self.compute_bs_features(
158
+ data_bs, features_compute, ch_name, component, fb
159
+ )
160
+
161
+ if self.s["bispectrum"][
162
+ "compute_features_for_whole_fband_range"
163
+ ]:
164
+ features_compute = self.compute_bs_features(
165
+ spectrum_ch, features_compute, ch_name, component, None
166
+ )
132
167
 
133
168
  return features_compute