py-neuromodulation 0.0.5__py3-none-any.whl → 0.0.7__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.
- py_neuromodulation/__init__.py +16 -10
- py_neuromodulation/{nm_RMAP.py → analysis/RMAP.py} +2 -2
- py_neuromodulation/analysis/__init__.py +4 -0
- py_neuromodulation/{nm_decode.py → analysis/decode.py} +4 -4
- py_neuromodulation/{nm_analysis.py → analysis/feature_reader.py} +21 -20
- py_neuromodulation/{nm_plots.py → analysis/plots.py} +54 -12
- py_neuromodulation/{nm_stats.py → analysis/stats.py} +2 -8
- py_neuromodulation/{nm_settings.yaml → default_settings.yaml} +7 -9
- py_neuromodulation/features/__init__.py +31 -0
- py_neuromodulation/features/bandpower.py +165 -0
- py_neuromodulation/{nm_bispectra.py → features/bispectra.py} +11 -12
- py_neuromodulation/{nm_bursts.py → features/bursts.py} +14 -9
- py_neuromodulation/{nm_coherence.py → features/coherence.py} +28 -19
- py_neuromodulation/{nm_features.py → features/feature_processor.py} +30 -53
- py_neuromodulation/{nm_fooof.py → features/fooof.py} +11 -8
- py_neuromodulation/{nm_hjorth_raw.py → features/hjorth_raw.py} +10 -5
- py_neuromodulation/{nm_linelength.py → features/linelength.py} +1 -1
- py_neuromodulation/{nm_mne_connectivity.py → features/mne_connectivity.py} +5 -6
- py_neuromodulation/{nm_nolds.py → features/nolds.py} +5 -7
- py_neuromodulation/{nm_oscillatory.py → features/oscillatory.py} +7 -181
- py_neuromodulation/{nm_sharpwaves.py → features/sharpwaves.py} +13 -4
- py_neuromodulation/filter/__init__.py +3 -0
- py_neuromodulation/{nm_kalmanfilter.py → filter/kalman_filter.py} +67 -71
- py_neuromodulation/filter/kalman_filter_external.py +1890 -0
- py_neuromodulation/{nm_filter.py → filter/mne_filter.py} +128 -219
- py_neuromodulation/filter/notch_filter.py +93 -0
- py_neuromodulation/processing/__init__.py +10 -0
- py_neuromodulation/{nm_artifacts.py → processing/artifacts.py} +2 -3
- py_neuromodulation/{nm_preprocessing.py → processing/data_preprocessor.py} +19 -25
- py_neuromodulation/{nm_filter_preprocessing.py → processing/filter_preprocessing.py} +3 -4
- py_neuromodulation/{nm_normalization.py → processing/normalization.py} +9 -7
- py_neuromodulation/{nm_projection.py → processing/projection.py} +14 -14
- py_neuromodulation/{nm_rereference.py → processing/rereference.py} +13 -13
- py_neuromodulation/{nm_resample.py → processing/resample.py} +1 -4
- py_neuromodulation/stream/__init__.py +3 -0
- py_neuromodulation/{nm_run_analysis.py → stream/data_processor.py} +42 -42
- py_neuromodulation/stream/generator.py +53 -0
- py_neuromodulation/{nm_mnelsl_generator.py → stream/mnelsl_player.py} +10 -6
- py_neuromodulation/{nm_mnelsl_stream.py → stream/mnelsl_stream.py} +13 -9
- py_neuromodulation/{nm_settings.py → stream/settings.py} +27 -24
- py_neuromodulation/{nm_stream.py → stream/stream.py} +217 -188
- py_neuromodulation/utils/__init__.py +2 -0
- py_neuromodulation/{nm_define_nmchannels.py → utils/channels.py} +14 -9
- py_neuromodulation/{nm_database.py → utils/database.py} +2 -2
- py_neuromodulation/{nm_IO.py → utils/io.py} +42 -77
- py_neuromodulation/utils/keyboard.py +52 -0
- py_neuromodulation/{nm_logger.py → utils/logging.py} +3 -3
- py_neuromodulation/{nm_types.py → utils/types.py} +72 -14
- {py_neuromodulation-0.0.5.dist-info → py_neuromodulation-0.0.7.dist-info}/METADATA +12 -29
- py_neuromodulation-0.0.7.dist-info/RECORD +89 -0
- py_neuromodulation/FieldTrip.py +0 -589
- py_neuromodulation/_write_example_dataset_helper.py +0 -83
- py_neuromodulation/nm_generator.py +0 -45
- py_neuromodulation/nm_stream_abc.py +0 -166
- py_neuromodulation-0.0.5.dist-info/RECORD +0 -83
- {py_neuromodulation-0.0.5.dist-info → py_neuromodulation-0.0.7.dist-info}/WHEEL +0 -0
- {py_neuromodulation-0.0.5.dist-info → py_neuromodulation-0.0.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
from collections.abc import
|
|
1
|
+
from collections.abc import Sequence
|
|
2
2
|
import numpy as np
|
|
3
3
|
from itertools import product
|
|
4
4
|
|
|
5
|
-
from py_neuromodulation.
|
|
6
|
-
from pydantic import field_validator
|
|
5
|
+
from py_neuromodulation.utils.types import NMBaseModel, BoolSelector, NMFeature
|
|
7
6
|
from typing import TYPE_CHECKING
|
|
8
7
|
|
|
9
|
-
from py_neuromodulation.nm_features import NMFeature
|
|
10
|
-
from py_neuromodulation.nm_types import BoolSelector
|
|
11
|
-
|
|
12
8
|
if TYPE_CHECKING:
|
|
13
|
-
from py_neuromodulation.
|
|
14
|
-
from py_neuromodulation.nm_kalmanfilter import KalmanSettings
|
|
9
|
+
from py_neuromodulation.stream.settings import NMSettings
|
|
15
10
|
|
|
16
11
|
|
|
17
12
|
class OscillatoryFeatures(BoolSelector):
|
|
@@ -40,7 +35,7 @@ ESTIMATOR_DICT = {
|
|
|
40
35
|
|
|
41
36
|
class OscillatoryFeature(NMFeature):
|
|
42
37
|
def __init__(
|
|
43
|
-
self, settings: "NMSettings", ch_names:
|
|
38
|
+
self, settings: "NMSettings", ch_names: Sequence[str], sfreq: int
|
|
44
39
|
) -> None:
|
|
45
40
|
settings.validate()
|
|
46
41
|
self.settings: OscillatorySettings # Assignment in subclass __init__
|
|
@@ -63,7 +58,7 @@ class FFT(OscillatoryFeature):
|
|
|
63
58
|
def __init__(
|
|
64
59
|
self,
|
|
65
60
|
settings: "NMSettings",
|
|
66
|
-
ch_names:
|
|
61
|
+
ch_names: Sequence[str],
|
|
67
62
|
sfreq: int,
|
|
68
63
|
) -> None:
|
|
69
64
|
from scipy.fft import rfftfreq
|
|
@@ -127,7 +122,7 @@ class Welch(OscillatoryFeature):
|
|
|
127
122
|
def __init__(
|
|
128
123
|
self,
|
|
129
124
|
settings: "NMSettings",
|
|
130
|
-
ch_names:
|
|
125
|
+
ch_names: Sequence[str],
|
|
131
126
|
sfreq: int,
|
|
132
127
|
) -> None:
|
|
133
128
|
from scipy.fft import rfftfreq
|
|
@@ -190,7 +185,7 @@ class STFT(OscillatoryFeature):
|
|
|
190
185
|
def __init__(
|
|
191
186
|
self,
|
|
192
187
|
settings: "NMSettings",
|
|
193
|
-
ch_names:
|
|
188
|
+
ch_names: Sequence[str],
|
|
194
189
|
sfreq: int,
|
|
195
190
|
) -> None:
|
|
196
191
|
from scipy.fft import rfftfreq
|
|
@@ -252,172 +247,3 @@ class STFT(OscillatoryFeature):
|
|
|
252
247
|
)[idx]
|
|
253
248
|
|
|
254
249
|
return feature_results
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
class BandpowerFeatures(BoolSelector):
|
|
258
|
-
activity: bool = True
|
|
259
|
-
mobility: bool = False
|
|
260
|
-
complexity: bool = False
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
###################################
|
|
264
|
-
######## BANDPOWER FEATURE ########
|
|
265
|
-
###################################
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
class BandpassSettings(NMBaseModel):
|
|
269
|
-
segment_lengths_ms: dict[str, int] = {
|
|
270
|
-
"theta": 1000,
|
|
271
|
-
"alpha": 500,
|
|
272
|
-
"low_beta": 333,
|
|
273
|
-
"high_beta": 333,
|
|
274
|
-
"low_gamma": 100,
|
|
275
|
-
"high_gamma": 100,
|
|
276
|
-
"HFA": 100,
|
|
277
|
-
}
|
|
278
|
-
bandpower_features: BandpowerFeatures = BandpowerFeatures()
|
|
279
|
-
log_transform: bool = True
|
|
280
|
-
kalman_filter: bool = False
|
|
281
|
-
|
|
282
|
-
@field_validator("segment_lengths_ms")
|
|
283
|
-
@classmethod
|
|
284
|
-
# Replace spaces with underscores in frequency band names
|
|
285
|
-
def fbands_spaces_to_underscores(cls, segment_lengths_ms: dict[str, int]):
|
|
286
|
-
return {k.replace(" ", "_"): v for k, v in segment_lengths_ms.items()}
|
|
287
|
-
|
|
288
|
-
@field_validator("bandpower_features")
|
|
289
|
-
@classmethod
|
|
290
|
-
def bandpower_features_validator(cls, bandpower_features: BandpowerFeatures):
|
|
291
|
-
assert (
|
|
292
|
-
len(bandpower_features.get_enabled()) > 0
|
|
293
|
-
), "Set at least one bandpower_feature to True."
|
|
294
|
-
|
|
295
|
-
return bandpower_features
|
|
296
|
-
|
|
297
|
-
def validate_fbands(self, settings: "NMSettings") -> None:
|
|
298
|
-
# Ensure that each freq-band is defined in the global settings
|
|
299
|
-
for fband_name in settings.frequency_ranges_hz.keys():
|
|
300
|
-
assert fband_name in self.segment_lengths_ms, (
|
|
301
|
-
f"frequency range {fband_name} "
|
|
302
|
-
"needs to be defined in settings.bandpass_filter_settings.segment_lengths_ms]"
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
# Ensure that segment length for each freq-band is smaller than the feature segment length setting
|
|
306
|
-
for fband_name, seg_length_fband in self.segment_lengths_ms.items():
|
|
307
|
-
assert seg_length_fband <= settings.segment_length_features_ms, (
|
|
308
|
-
f"segment length {seg_length_fband} needs to be smaller than "
|
|
309
|
-
f" settings['segment_length_features_ms'] = {settings.segment_length_features_ms}"
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
class BandPower(NMFeature):
|
|
314
|
-
def __init__(
|
|
315
|
-
self,
|
|
316
|
-
settings: "NMSettings",
|
|
317
|
-
ch_names: Iterable[str],
|
|
318
|
-
sfreq: float,
|
|
319
|
-
use_kf: bool | None = None,
|
|
320
|
-
) -> None:
|
|
321
|
-
settings.validate()
|
|
322
|
-
|
|
323
|
-
self.bp_settings: BandpassSettings = settings.bandpass_filter_settings
|
|
324
|
-
self.kalman_filter_settings: KalmanSettings = settings.kalman_filter_settings
|
|
325
|
-
self.sfreq = sfreq
|
|
326
|
-
self.ch_names = ch_names
|
|
327
|
-
self.KF_dict: dict = {}
|
|
328
|
-
|
|
329
|
-
from py_neuromodulation.nm_filter import MNEFilter
|
|
330
|
-
|
|
331
|
-
self.bandpass_filter = MNEFilter(
|
|
332
|
-
f_ranges=[
|
|
333
|
-
tuple(frange) for frange in settings.frequency_ranges_hz.values()
|
|
334
|
-
],
|
|
335
|
-
sfreq=self.sfreq,
|
|
336
|
-
filter_length=self.sfreq - 1,
|
|
337
|
-
verbose=False,
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
if use_kf or (use_kf is None and self.bp_settings.kalman_filter):
|
|
341
|
-
self.init_KF("bandpass_activity")
|
|
342
|
-
|
|
343
|
-
seglengths = self.bp_settings.segment_lengths_ms
|
|
344
|
-
|
|
345
|
-
self.feature_params = []
|
|
346
|
-
for ch_idx, ch_name in enumerate(self.ch_names):
|
|
347
|
-
for f_band_idx, f_band in enumerate(settings.frequency_ranges_hz.keys()):
|
|
348
|
-
seglength_ms = seglengths[f_band]
|
|
349
|
-
seglen = int(np.floor(self.sfreq / 1000 * seglength_ms))
|
|
350
|
-
for bp_feature in self.bp_settings.bandpower_features.get_enabled():
|
|
351
|
-
feature_name = "_".join([ch_name, "bandpass", bp_feature, f_band])
|
|
352
|
-
self.feature_params.append(
|
|
353
|
-
(
|
|
354
|
-
ch_idx,
|
|
355
|
-
f_band_idx,
|
|
356
|
-
seglen,
|
|
357
|
-
bp_feature,
|
|
358
|
-
feature_name,
|
|
359
|
-
)
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
def init_KF(self, feature: str) -> None:
|
|
363
|
-
from py_neuromodulation.nm_kalmanfilter import define_KF
|
|
364
|
-
|
|
365
|
-
for f_band in self.kalman_filter_settings.frequency_bands:
|
|
366
|
-
for channel in self.ch_names:
|
|
367
|
-
self.KF_dict["_".join([channel, feature, f_band])] = define_KF(
|
|
368
|
-
self.kalman_filter_settings.Tp,
|
|
369
|
-
self.kalman_filter_settings.sigma_w,
|
|
370
|
-
self.kalman_filter_settings.sigma_v,
|
|
371
|
-
)
|
|
372
|
-
|
|
373
|
-
def update_KF(self, feature_calc: np.floating, KF_name: str) -> np.floating:
|
|
374
|
-
if KF_name in self.KF_dict:
|
|
375
|
-
self.KF_dict[KF_name].predict()
|
|
376
|
-
self.KF_dict[KF_name].update(feature_calc)
|
|
377
|
-
feature_calc = self.KF_dict[KF_name].x[0]
|
|
378
|
-
return feature_calc
|
|
379
|
-
|
|
380
|
-
def calc_feature(self, data: np.ndarray) -> dict:
|
|
381
|
-
data = self.bandpass_filter.filter_data(data)
|
|
382
|
-
|
|
383
|
-
feature_results = {}
|
|
384
|
-
|
|
385
|
-
for (
|
|
386
|
-
ch_idx,
|
|
387
|
-
f_band_idx,
|
|
388
|
-
seglen,
|
|
389
|
-
bp_feature,
|
|
390
|
-
feature_name,
|
|
391
|
-
) in self.feature_params:
|
|
392
|
-
feature_results[feature_name] = self.calc_bp_feature(
|
|
393
|
-
bp_feature, feature_name, data[ch_idx, f_band_idx, -seglen:]
|
|
394
|
-
)
|
|
395
|
-
|
|
396
|
-
return feature_results
|
|
397
|
-
|
|
398
|
-
def calc_bp_feature(self, bp_feature, feature_name, data):
|
|
399
|
-
match bp_feature:
|
|
400
|
-
case "activity":
|
|
401
|
-
feature_calc = np.var(data)
|
|
402
|
-
if self.bp_settings.log_transform:
|
|
403
|
-
feature_calc = np.log10(feature_calc)
|
|
404
|
-
if self.KF_dict:
|
|
405
|
-
feature_calc = self.update_KF(feature_calc, feature_name)
|
|
406
|
-
case "mobility":
|
|
407
|
-
feature_calc = np.sqrt(np.var(np.diff(data)) / np.var(data))
|
|
408
|
-
case "complexity":
|
|
409
|
-
feature_calc = self.calc_complexity(data)
|
|
410
|
-
case _:
|
|
411
|
-
raise ValueError(f"Unknown bandpower feature: {bp_feature}")
|
|
412
|
-
|
|
413
|
-
return np.nan_to_num(feature_calc)
|
|
414
|
-
|
|
415
|
-
@staticmethod
|
|
416
|
-
def calc_complexity(data: np.ndarray) -> float:
|
|
417
|
-
dat_deriv = np.diff(data)
|
|
418
|
-
deriv_variance = np.var(dat_deriv)
|
|
419
|
-
mobility = np.sqrt(deriv_variance / np.var(data))
|
|
420
|
-
dat_deriv_2_var = np.var(np.diff(dat_deriv))
|
|
421
|
-
deriv_mobility = np.sqrt(dat_deriv_2_var / deriv_variance)
|
|
422
|
-
|
|
423
|
-
return deriv_mobility / mobility
|
|
@@ -2,7 +2,6 @@ from collections.abc import Sequence
|
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
from itertools import product
|
|
4
4
|
|
|
5
|
-
from py_neuromodulation.nm_types import NMBaseModel
|
|
6
5
|
from pydantic import model_validator
|
|
7
6
|
from typing import TYPE_CHECKING, Any, Callable
|
|
8
7
|
|
|
@@ -13,11 +12,15 @@ if np.__version__ >= "2.0.0":
|
|
|
13
12
|
else:
|
|
14
13
|
from numpy.core._methods import _mean as np_mean
|
|
15
14
|
|
|
16
|
-
from py_neuromodulation.
|
|
17
|
-
|
|
15
|
+
from py_neuromodulation.utils.types import (
|
|
16
|
+
NMFeature,
|
|
17
|
+
NMBaseModel,
|
|
18
|
+
BoolSelector,
|
|
19
|
+
FrequencyRange,
|
|
20
|
+
)
|
|
18
21
|
|
|
19
22
|
if TYPE_CHECKING:
|
|
20
|
-
from py_neuromodulation
|
|
23
|
+
from py_neuromodulation import NMSettings
|
|
21
24
|
|
|
22
25
|
# Using low-level numpy mean function for performance, could do the same for the other estimators
|
|
23
26
|
ESTIMATOR_DICT = {
|
|
@@ -38,6 +41,7 @@ class PeakDetectionSettings(NMBaseModel):
|
|
|
38
41
|
class SharpwaveFeatures(BoolSelector):
|
|
39
42
|
peak_left: bool = False
|
|
40
43
|
peak_right: bool = False
|
|
44
|
+
num_peaks: bool = False
|
|
41
45
|
trough: bool = False
|
|
42
46
|
width: bool = False
|
|
43
47
|
prominence: bool = True
|
|
@@ -368,6 +372,11 @@ class SharpwaveAnalyzer(NMFeature):
|
|
|
368
372
|
# results["sharpness"] = ((trough_height - left_height) + (trough_height - right_height)) / 2
|
|
369
373
|
results["sharpness"] = trough_height - 0.5 * (left_height + right_height)
|
|
370
374
|
|
|
375
|
+
if self.sw_settings.sharpwave_features.num_peaks:
|
|
376
|
+
results["num_peaks"] = [
|
|
377
|
+
trough_idx.shape[0]
|
|
378
|
+
] # keep list to the estimator can be applied
|
|
379
|
+
|
|
371
380
|
if self.need_steepness:
|
|
372
381
|
# steepness is calculated as the first derivative
|
|
373
382
|
steepness: np.ndarray = np.concatenate((np.zeros(1), np.diff(data)))
|
|
@@ -1,71 +1,67 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from py_neuromodulation.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class KalmanSettings(NMBaseModel):
|
|
12
|
-
Tp: float = 0.1
|
|
13
|
-
sigma_w: float = 0.7
|
|
14
|
-
sigma_v: float = 1.0
|
|
15
|
-
frequency_bands: list[str] = [
|
|
16
|
-
"theta",
|
|
17
|
-
"alpha",
|
|
18
|
-
"low_beta",
|
|
19
|
-
"high_beta",
|
|
20
|
-
"low_gamma",
|
|
21
|
-
"high_gamma",
|
|
22
|
-
"HFA",
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
f =
|
|
60
|
-
f.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
]
|
|
69
|
-
)
|
|
70
|
-
f.P = cov([[1, 0], [0, 1]])
|
|
71
|
-
return f
|
|
1
|
+
import numpy as np
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
from py_neuromodulation.utils.types import NMBaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from py_neuromodulation.stream.settings import NMSettings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class KalmanSettings(NMBaseModel):
|
|
12
|
+
Tp: float = 0.1
|
|
13
|
+
sigma_w: float = 0.7
|
|
14
|
+
sigma_v: float = 1.0
|
|
15
|
+
frequency_bands: list[str] = [
|
|
16
|
+
"theta",
|
|
17
|
+
"alpha",
|
|
18
|
+
"low_beta",
|
|
19
|
+
"high_beta",
|
|
20
|
+
"low_gamma",
|
|
21
|
+
"high_gamma",
|
|
22
|
+
"HFA",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
def validate_fbands(self, settings: "NMSettings") -> None:
|
|
26
|
+
assert all(
|
|
27
|
+
(item in settings.frequency_ranges_hz for item in self.frequency_bands)
|
|
28
|
+
), (
|
|
29
|
+
"Frequency bands for Kalman filter must also be specified in "
|
|
30
|
+
"bandpass_filter_settings."
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def define_KF(Tp, sigma_w, sigma_v):
|
|
35
|
+
"""Define Kalman filter according to white noise acceleration model.
|
|
36
|
+
See DOI: 10.1109/TBME.2009.2038990 for explanation
|
|
37
|
+
See https://filterpy.readthedocs.io/en/latest/kalman/KalmanFilter.html#r64ca38088676-2 for implementation details
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
Tp : float
|
|
42
|
+
prediction interval
|
|
43
|
+
sigma_w : float
|
|
44
|
+
process noise
|
|
45
|
+
sigma_v : float
|
|
46
|
+
measurement noise
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
filterpy.KalmanFilter
|
|
51
|
+
initialized KalmanFilter object
|
|
52
|
+
"""
|
|
53
|
+
from .kalman_filter_external import KalmanFilter
|
|
54
|
+
|
|
55
|
+
f = KalmanFilter(dim_x=2, dim_z=1)
|
|
56
|
+
f.x = np.array([0, 1]) # x here sensor signal and it's first derivative
|
|
57
|
+
f.F = np.array([[1, Tp], [0, 1]])
|
|
58
|
+
f.H = np.array([[1, 0]])
|
|
59
|
+
f.R = sigma_v
|
|
60
|
+
f.Q = np.array(
|
|
61
|
+
[
|
|
62
|
+
[(sigma_w**2) * (Tp**3) / 3, (sigma_w**2) * (Tp**2) / 2],
|
|
63
|
+
[(sigma_w**2) * (Tp**2) / 2, (sigma_w**2) * Tp],
|
|
64
|
+
]
|
|
65
|
+
)
|
|
66
|
+
f.P = np.cov([[1, 0], [0, 1]])
|
|
67
|
+
return f
|