SleePyPhases 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/PKG-INFO +1 -1
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/PSGEventManager.py +1 -2
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/Plugin.py +4 -5
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/RecordFeatureExtraction.py +5 -70
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/ExtractFeatures.py +6 -3
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/Setup.py +4 -4
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/Training.py +4 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases.egg-info/PKG-INFO +1 -1
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases.egg-info/SOURCES.txt +0 -1
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/setup.py +1 -1
- sleepyphases-0.3.0/SleePyPhases/FeatureExtraction copy.py +0 -116
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/LICENSE +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/README.md +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/DataManipulation.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/EventScorer.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/FeatureExtraction.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/MultiScorer.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/Plot.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/PreManipulation.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/Reporter.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/SignalPreprocessing.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/SleepMetaData.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/__init__.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/BuildDataset.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/DataAnalysis.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/DataReport.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/Eval.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/EvalPlotExamples.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/EvalReport.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/ExportMetadataToMeticalDB.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/Extract.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/ExtractEvents.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/ExtractRecordFeatures.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/GatherMetadata.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/TestRun.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/ThresholdOptimisation.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/Validation.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/VisualizeConfig.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases/phases/__init__.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases.egg-info/dependency_links.txt +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases.egg-info/requires.txt +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/SleePyPhases.egg-info/top_level.txt +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/pyproject.toml +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/setup.cfg +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/__init__.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/conftest.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/__init__.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_BuildDataset.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_BuildDatasetFolded.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_BuildDatasetSegments.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_DataManipulation.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_Eval.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_EventScorer.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_Extract.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_PreManipulation.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_RecordFeatureExtraction.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_RecordProcessor.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_Setup.py +0 -0
- {sleepyphases-0.3.0 → sleepyphases-0.4.0}/tests/unit/test_SignalPreprocessing.py +0 -0
|
@@ -74,7 +74,7 @@ class PSGEventManager(EventManager):
|
|
|
74
74
|
"SlowEyeMovement",
|
|
75
75
|
"Spindle-eeg",
|
|
76
76
|
],
|
|
77
|
-
"fail": [ # maximal
|
|
77
|
+
"fail": [ # maximal 31 for 32bit integer
|
|
78
78
|
"workingSignal",
|
|
79
79
|
"fail-channel0",
|
|
80
80
|
"fail-channel1",
|
|
@@ -106,7 +106,6 @@ class PSGEventManager(EventManager):
|
|
|
106
106
|
"fail-channel27",
|
|
107
107
|
"fail-channel28",
|
|
108
108
|
"fail-channel29",
|
|
109
|
-
"fail-channel30",
|
|
110
109
|
],
|
|
111
110
|
"limb": ["noneLegmovement", "LegMovement-Left", "LegMovement-Right", "LegMovement"],
|
|
112
111
|
"spo2": [
|
|
@@ -3,6 +3,7 @@ from pyPhasesRecordloader import RecordLoader
|
|
|
3
3
|
|
|
4
4
|
from SleepHarmonizer.recordwriter.RecordWriter import RecordWriter
|
|
5
5
|
|
|
6
|
+
from SleePyPhases.phases.ExtractFeatures import ExtractFeatures
|
|
6
7
|
from SleePyPhases.phases.Extract import Extract
|
|
7
8
|
from SleePyPhases.phases.Setup import Setup
|
|
8
9
|
from SleePyPhases.phases.BuildDataset import BuildDataset
|
|
@@ -12,6 +13,7 @@ from SleePyPhases.phases.Eval import Eval
|
|
|
12
13
|
from SleePyPhases.phases.EvalReport import EvalReport
|
|
13
14
|
from SleePyPhases.phases.ThresholdOptimisation import ThresholdOptimisation
|
|
14
15
|
from SleePyPhases.phases.TestRun import TestRun
|
|
16
|
+
from SleePyPhases.phases.ExtractFeatures import ExtractFeatures
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
from pyPhases.exporter.PickleExporter import PickleExporter
|
|
@@ -33,8 +35,8 @@ class Plugin(PluginAdapter):
|
|
|
33
35
|
"ThresholdOptimisation": (ThresholdOptimisation, ["threshold", "validationResult"]),
|
|
34
36
|
"Eval": (Eval, ["evalResults", "eventResults"]),
|
|
35
37
|
"EvalReport": (EvalReport, []),
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
+
"ExtractFeatures": (ExtractFeatures, ["features"]),
|
|
39
|
+
"TestRun": (TestRun, []),
|
|
38
40
|
}
|
|
39
41
|
dataMap = {
|
|
40
42
|
"features": ["metadata"],
|
|
@@ -69,8 +71,5 @@ class Plugin(PluginAdapter):
|
|
|
69
71
|
project.registerExporter(ModelExporter({"basePath": dataPath}))
|
|
70
72
|
project.registerExporter(MemmapRecordExporter({"basePath": dataPath}))
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
def initPlugin(self):
|
|
74
|
-
RecordLoader.registerRecordLoader("RecordLoaderTSM", "SleePyPhases.recordloaders")
|
|
75
74
|
|
|
76
75
|
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import pandas as pd
|
|
2
1
|
from typing import List
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
5
|
from pandas import DataFrame
|
|
6
|
+
from pyPhases import Swappable
|
|
6
7
|
from pyPhasesML import FeatureExtraction as pyPhasesFeatureExtraction
|
|
7
|
-
from pyPhasesRecordloader import
|
|
8
|
+
from pyPhasesRecordloader import ChannelsNotPresent, Event, RecordSignal, Signal
|
|
8
9
|
|
|
9
10
|
from SleePyPhases.PSGEventManager import PSGEventManager
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
segmentSignal: Recordsignal of the segment with 18 EEG channels
|
|
14
|
-
"""
|
|
12
|
+
|
|
13
|
+
class RecordFeatureExtraction(pyPhasesFeatureExtraction, Swappable):
|
|
15
14
|
|
|
16
15
|
def step(self, stepname: str, recordSignal: RecordSignal, eventlist: List[Event], channel=None, **options) -> Signal:
|
|
17
16
|
if hasattr(self, stepname):
|
|
@@ -272,67 +271,3 @@ class RecordFeatureExtraction(pyPhasesFeatureExtraction):
|
|
|
272
271
|
|
|
273
272
|
return ret
|
|
274
273
|
|
|
275
|
-
def spindles(self, segmentSignal: RecordSignal, eventlist: List[Event], channel: str):
|
|
276
|
-
from .external.sumo.sumo.scripts.a7.butter_filter import butter_bandpass_filter, downsample
|
|
277
|
-
# from .external.sumo.a7.detect_spindles import detect_spindle
|
|
278
|
-
from .external.sumo.sumo.scripts.predict_plain_data import SimpleDataset
|
|
279
|
-
# from .external.sumo.sumo.predict_plain_data import A7
|
|
280
|
-
import pytorch_lightning as pl
|
|
281
|
-
from torch.utils.data import Dataset, DataLoader
|
|
282
|
-
import torch
|
|
283
|
-
from .external.sumo.sumo.model.sumo import SUMO
|
|
284
|
-
from .external.sumo.sumo.config.config import Config
|
|
285
|
-
# from .external.sumo.model.data import spindle_vect_to_indices
|
|
286
|
-
|
|
287
|
-
config = Config('predict', create_dirs=False)
|
|
288
|
-
|
|
289
|
-
def get_model(p):
|
|
290
|
-
# p = Path(p)
|
|
291
|
-
|
|
292
|
-
model_checkpoint = torch.load(p)
|
|
293
|
-
|
|
294
|
-
model = SUMO(config)
|
|
295
|
-
model.load_state_dict(model_checkpoint['state_dict'])
|
|
296
|
-
|
|
297
|
-
return model
|
|
298
|
-
|
|
299
|
-
eegSignal = segmentSignal.getSignalByName(channel)
|
|
300
|
-
resample_rate = 100
|
|
301
|
-
model_path = "SleePyPhases/external/sumo/sumo/output/final.ckpt"
|
|
302
|
-
|
|
303
|
-
if len(eegSignal.signal) == 0:
|
|
304
|
-
return None
|
|
305
|
-
|
|
306
|
-
eegs = []
|
|
307
|
-
eegSignal = downsample(butter_bandpass_filter(eegSignal.signal, 0.3, 30.0, eegSignal.frequency, 10), eegSignal.frequency, resample_rate)
|
|
308
|
-
eegs.append(eegSignal)
|
|
309
|
-
|
|
310
|
-
dataset = SimpleDataset(eegs)
|
|
311
|
-
dataloader = DataLoader(dataset)
|
|
312
|
-
model = get_model(model_path)
|
|
313
|
-
trainer = pl.Trainer(num_sanity_val_steps=0, logger=False)
|
|
314
|
-
predictions = trainer.predict(model, dataloader)
|
|
315
|
-
pred = predictions[0]
|
|
316
|
-
|
|
317
|
-
# spindles_a7 = A7(x, resample_rate)
|
|
318
|
-
spindle_vect = pred[0].numpy()
|
|
319
|
-
|
|
320
|
-
diff = np.diff(np.r_[0, spindle_vect, 0]) # be able to detect spindles at the start and end of vector
|
|
321
|
-
spindles = np.c_[np.argwhere(diff == 1), np.argwhere(diff == -1)] / resample_rate
|
|
322
|
-
# spindles = spindle_vect_to_indices(spindle_vect) / resample_rate
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
# frequencies, psd = signal.welch(eegs[0][s.start:s.end()],
|
|
326
|
-
# fs=100,
|
|
327
|
-
# nperseg=min(256, s.duration),
|
|
328
|
-
# scaling='spectrum')
|
|
329
|
-
# dominant_freq = frequencies[np.argmax(psd)]
|
|
330
|
-
|
|
331
|
-
spindles = [Event("spindle", s[0], s[1] - s[0]) for s in spindles]
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return {
|
|
335
|
-
"spindles-count": len(spindles),
|
|
336
|
-
"spindles-mean-druation": np.array([s.duration for s in spindles]).mean()
|
|
337
|
-
}
|
|
338
|
-
|
|
@@ -76,7 +76,7 @@ class ExtractFeatures(Phase):
|
|
|
76
76
|
try:
|
|
77
77
|
recordSignal = recordLoader.getHarmonizedSignal(recordId)
|
|
78
78
|
|
|
79
|
-
events: List[Event] = RecordFeatureExtraction(
|
|
79
|
+
events: List[Event] = RecordFeatureExtraction.getInstance().step(name, recordSignal, *options)
|
|
80
80
|
|
|
81
81
|
if channelType is not None:
|
|
82
82
|
channelType = [s.name for s in recordSignal.signals if s.typeStr == channelType]
|
|
@@ -192,7 +192,7 @@ class ExtractFeatures(Phase):
|
|
|
192
192
|
try:
|
|
193
193
|
idx = (recordId, c)
|
|
194
194
|
featureStep = featureConfig["type"]
|
|
195
|
-
RecordFeatureExtraction(
|
|
195
|
+
RecordFeatureExtraction.getInstance().updateMetadataByStep(featureStep, recordSignal, eventlist, metadata=self.features, channel=c)
|
|
196
196
|
except ChannelsNotPresent as e:
|
|
197
197
|
self.logError(f"channels not present: {e.channels}")
|
|
198
198
|
|
|
@@ -209,10 +209,13 @@ class ExtractFeatures(Phase):
|
|
|
209
209
|
self.features = None
|
|
210
210
|
metadata = self.project.getData("metadata", pd.DataFrame)
|
|
211
211
|
recordIds = metadata["recordId"]
|
|
212
|
-
forceCalculation = self.getConfig("featureExtraction.
|
|
212
|
+
forceCalculation = self.getConfig("featureExtraction.force", False)
|
|
213
213
|
|
|
214
214
|
reqFeatures = {f["name"]: True for f in self.getConfig("featureExtraction.features", [])}
|
|
215
215
|
|
|
216
|
+
recordId = self.getConfig("recordId", False)
|
|
217
|
+
recordIds = [recordId] if recordId else recordIds.iloc
|
|
218
|
+
|
|
216
219
|
for recordId in tqdm(recordIds.iloc):
|
|
217
220
|
if forceCalculation:
|
|
218
221
|
# the parameter forced has no meaning, it is just known to be not in the metadata, so the record will always be recalculated
|
|
@@ -8,16 +8,16 @@ from pyPhasesRecordloader import RecordLoader
|
|
|
8
8
|
|
|
9
9
|
class Setup(Phase):
|
|
10
10
|
def prepareConfig(self):
|
|
11
|
-
numLabels = len(self.getConfig("classification.labelNames"))
|
|
11
|
+
numLabels = len(self.getConfig("classification.labelNames", []))
|
|
12
12
|
self.setConfig("numLabels", numLabels)
|
|
13
13
|
|
|
14
|
-
numClasses = [len(c) for c in self.getConfig("classification.classNames")]
|
|
14
|
+
numClasses = [len(c) for c in self.getConfig("classification.classNames", [])]
|
|
15
15
|
self.setConfig("numClasses", numClasses)
|
|
16
16
|
|
|
17
|
-
defaultValidationbatchManipulation = self.getConfig("segmentManipulationEval", self.getConfig("segmentManipulation"))
|
|
17
|
+
defaultValidationbatchManipulation = self.getConfig("segmentManipulationEval", self.getConfig("segmentManipulation", []))
|
|
18
18
|
self.setConfig("segmentManipulationEval", defaultValidationbatchManipulation)
|
|
19
19
|
|
|
20
|
-
preprocessingConfig = self.getConfig("preprocessing")
|
|
20
|
+
preprocessingConfig = self.getConfig("preprocessing", {})
|
|
21
21
|
if "combineChannels" in preprocessingConfig:
|
|
22
22
|
RecordLoader.get().addCombinedChannels(preprocessingConfig["combineChannels"])
|
|
23
23
|
|
|
@@ -77,6 +77,8 @@ class Training(Phase):
|
|
|
77
77
|
|
|
78
78
|
gridOutputs = []
|
|
79
79
|
for fold in range(startfold, endfold):
|
|
80
|
+
# save model state (random initialisation or pretrained)
|
|
81
|
+
startState = ModelManager.getModel().model.state_dict()
|
|
80
82
|
self.setConfig("fold", fold)
|
|
81
83
|
# only train if it doesnt allready exist
|
|
82
84
|
self.getData("modelState", Model)
|
|
@@ -85,6 +87,8 @@ class Training(Phase):
|
|
|
85
87
|
self.project.unregister("modelState")
|
|
86
88
|
self.project.unregister("modelStateConfig")
|
|
87
89
|
gridOutputs.append(self.gridOutput)
|
|
90
|
+
# reset model state
|
|
91
|
+
ModelManager.getModel().model.load_state_dict(startState)
|
|
88
92
|
|
|
89
93
|
self.project.gridOutput = {
|
|
90
94
|
"epochs": str(np.mean([m["epochs"] for m in gridOutputs])),
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="SleePyPhases",
|
|
8
|
-
version="v0.
|
|
8
|
+
version="v0.4.0"[1:],
|
|
9
9
|
author="Franz Ehrlich",
|
|
10
10
|
author_email="fehrlichd@gmail.com",
|
|
11
11
|
description="A framwork for creating deep learning pipelines for sleep data",
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from pyPhasesML import FeatureExtraction as pyPhasesFeatureExtraction
|
|
5
|
-
from pyPhasesML import ModelManager
|
|
6
|
-
from pyPhasesRecordloader import RecordSignal, Event
|
|
7
|
-
|
|
8
|
-
from .DataAugmentation import DataAugmentation
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class FeatureExtraction(pyPhasesFeatureExtraction):
|
|
12
|
-
"""augmentation for the physionet challenge 2023
|
|
13
|
-
segmentSignal: Recordsignal of the segment with 18 EEG channels
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def __init__(self, project) -> None:
|
|
17
|
-
super().__init__()
|
|
18
|
-
self.project = project
|
|
19
|
-
|
|
20
|
-
def time(self, segmentSignal: RecordSignal):
|
|
21
|
-
segmentLength = segmentSignal.getShape()[1]
|
|
22
|
-
# segmentLengthInHOurs = segmentLength / segmentSignal.targetFrequency / 3600
|
|
23
|
-
# hour, minutes = segmentSignal.start.split(":")
|
|
24
|
-
# startTimeInHours = int(hour) + int(minutes) / 60
|
|
25
|
-
# endTimeInHours = startTimeInHours + segmentLengthInHOurs
|
|
26
|
-
hour = segmentSignal.start
|
|
27
|
-
endTimeInHours = hour + 1
|
|
28
|
-
return np.linspace(hour, endTimeInHours, segmentLength)
|
|
29
|
-
|
|
30
|
-
def featureModel(self, segmentSignal: RecordSignal, featureName: str, xChannels: List[str]):
|
|
31
|
-
import torch
|
|
32
|
-
useGPU = torch.cuda.is_available() and False
|
|
33
|
-
with self.project:
|
|
34
|
-
config = self.project.config["featureConfigs", featureName]
|
|
35
|
-
self.project.config.update(config)
|
|
36
|
-
self.project.addConfig(config)
|
|
37
|
-
|
|
38
|
-
self.project.trigger("configChanged", None)
|
|
39
|
-
self.project.setConfig("trainingParameter.batchSize", 1)
|
|
40
|
-
self.project.setConfig("recordWise", True)
|
|
41
|
-
|
|
42
|
-
modelPath = self.project.getConfig("featureModel", torch)
|
|
43
|
-
|
|
44
|
-
# this is needed for mutlithreading
|
|
45
|
-
ModelManager.loadModel(self.project)
|
|
46
|
-
# get feature model
|
|
47
|
-
model = ModelManager.getModel(True)
|
|
48
|
-
model.useGPU = useGPU
|
|
49
|
-
state = model.load(modelPath)
|
|
50
|
-
model.loadState(state)
|
|
51
|
-
featureModel = model.model.eval()
|
|
52
|
-
|
|
53
|
-
featureModel = featureModel.cuda() if useGPU else featureModel.cpu()
|
|
54
|
-
|
|
55
|
-
# we assum that the segment is already preprocessed for the model
|
|
56
|
-
array = segmentSignal.getSignalArray(xChannels, transpose=True)
|
|
57
|
-
|
|
58
|
-
da = DataAugmentation(self.project.config, self.project.getConfig("datasetSplit"), recordAnnotations={})
|
|
59
|
-
array, _ = da.augmentSegment(array, None)
|
|
60
|
-
array = array.transpose(2, 1, 0)
|
|
61
|
-
|
|
62
|
-
features = model.predict(array, get_likelihood=True)
|
|
63
|
-
_, features = da.restoreLength(None, features, length=segmentSignal.getShape()[1])
|
|
64
|
-
features = features[:, :, 1]
|
|
65
|
-
|
|
66
|
-
return features
|
|
67
|
-
|
|
68
|
-
def spindles(self, segmentSignal: RecordSignal): #xChannels: List[str]
|
|
69
|
-
from .external.sumo.a7.butter_filter import butter_bandpass_filter, downsample
|
|
70
|
-
# from .external.sumo.a7.detect_spindles import detect_spindle
|
|
71
|
-
from .external.sumo.predict_plain_data import SimpleDataset
|
|
72
|
-
from .external.sumo.predict_plain_data import A7
|
|
73
|
-
import pytorch_lightning as pl
|
|
74
|
-
from torch.utils.data import Dataset, DataLoader
|
|
75
|
-
import torch
|
|
76
|
-
from .external.sumo.model.sumo import SUMO
|
|
77
|
-
from .external.sumo.model.config import Config
|
|
78
|
-
# from .external.sumo.model.data import spindle_vect_to_indices
|
|
79
|
-
|
|
80
|
-
config = Config('predict', create_dirs=False)
|
|
81
|
-
|
|
82
|
-
def get_model(p):
|
|
83
|
-
# p = Path(p)
|
|
84
|
-
|
|
85
|
-
model_checkpoint = torch.load(p)
|
|
86
|
-
|
|
87
|
-
model = SUMO(config)
|
|
88
|
-
model.load_state_dict(model_checkpoint['state_dict'])
|
|
89
|
-
|
|
90
|
-
return model
|
|
91
|
-
|
|
92
|
-
eegSignals = [s for s in segmentSignal.signals if s.typeStr == "eeg"]
|
|
93
|
-
resample_rate = 100
|
|
94
|
-
model_path = "SleePyPhases/external/sumo/model/final.ckpt"
|
|
95
|
-
|
|
96
|
-
eegs = []
|
|
97
|
-
for eegSignal in eegSignals:
|
|
98
|
-
eegSignal = downsample(butter_bandpass_filter(eegSignal.signal, 0.3, 30.0, eegSignal.frequency, 10), eegSignal.frequency, resample_rate)
|
|
99
|
-
eegs.append(eegSignal)
|
|
100
|
-
|
|
101
|
-
dataset = SimpleDataset(eegs)
|
|
102
|
-
dataloader = DataLoader(dataset)
|
|
103
|
-
model = get_model(model_path)
|
|
104
|
-
trainer = pl.Trainer(num_sanity_val_steps=0, logger=False)
|
|
105
|
-
predictions = trainer.predict(model, dataloader)
|
|
106
|
-
|
|
107
|
-
for x, pred in zip(eegs, predictions):
|
|
108
|
-
# spindles_a7 = A7(x, resample_rate)
|
|
109
|
-
spindle_vect = pred[0].numpy()
|
|
110
|
-
|
|
111
|
-
diff = np.diff(np.r_[0, spindle_vect, 0]) # be able to detect spindles at the start and end of vector
|
|
112
|
-
spindles = np.c_[np.argwhere(diff == 1), np.argwhere(diff == -1)] / resample_rate
|
|
113
|
-
# spindles = spindle_vect_to_indices(spindle_vect) / resample_rate
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return [Event("spindle-slow", 500, 10)]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|