paradigma 0.1.2__py3-none-any.whl → 0.2.0__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.
- paradigma/__init__.py +1 -3
- paradigma/constants.py +35 -0
- paradigma/feature_extraction.py +678 -0
- paradigma/gait_analysis.py +413 -0
- paradigma/gait_analysis_config.py +244 -0
- paradigma/heart_rate_analysis.py +127 -0
- paradigma/heart_rate_analysis_config.py +9 -0
- paradigma/heart_rate_util.py +173 -0
- paradigma/imu_preprocessing.py +229 -0
- paradigma/ppg/classifier/LR_PPG_quality.pkl +0 -0
- paradigma/ppg/classifier/LR_model.mat +0 -0
- paradigma/ppg/feat_extraction/acc_feature.m +20 -0
- paradigma/ppg/feat_extraction/peakdet.m +64 -0
- paradigma/ppg/feat_extraction/ppg_features.m +53 -0
- paradigma/ppg/glob_functions/extract_hr_segments.m +37 -0
- paradigma/ppg/glob_functions/extract_overlapping_segments.m +23 -0
- paradigma/ppg/glob_functions/jsonlab/AUTHORS.txt +41 -0
- paradigma/ppg/glob_functions/jsonlab/ChangeLog.txt +74 -0
- paradigma/ppg/glob_functions/jsonlab/LICENSE_BSD.txt +25 -0
- paradigma/ppg/glob_functions/jsonlab/LICENSE_GPLv3.txt +699 -0
- paradigma/ppg/glob_functions/jsonlab/README.txt +394 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/entries +368 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/demo_jsonlab_basic.m.svn-base +180 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/demo_ubjson_basic.m.svn-base +180 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/example1.json.svn-base +23 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/example2.json.svn-base +22 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/example3.json.svn-base +11 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/example4.json.svn-base +34 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/jsonlab_basictest.matlab.svn-base +662 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/jsonlab_selftest.m.svn-base +27 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/jsonlab_selftest.matlab.svn-base +144 -0
- paradigma/ppg/glob_functions/jsonlab/examples/.svn/text-base/jsonlab_speedtest.m.svn-base +21 -0
- paradigma/ppg/glob_functions/jsonlab/examples/demo_jsonlab_basic.m +180 -0
- paradigma/ppg/glob_functions/jsonlab/examples/demo_ubjson_basic.m +180 -0
- paradigma/ppg/glob_functions/jsonlab/examples/example1.json +23 -0
- paradigma/ppg/glob_functions/jsonlab/examples/example2.json +22 -0
- paradigma/ppg/glob_functions/jsonlab/examples/example3.json +11 -0
- paradigma/ppg/glob_functions/jsonlab/examples/example4.json +34 -0
- paradigma/ppg/glob_functions/jsonlab/examples/jsonlab_basictest.matlab +662 -0
- paradigma/ppg/glob_functions/jsonlab/examples/jsonlab_selftest.m +27 -0
- paradigma/ppg/glob_functions/jsonlab/examples/jsonlab_selftest.matlab +144 -0
- paradigma/ppg/glob_functions/jsonlab/examples/jsonlab_speedtest.m +21 -0
- paradigma/ppg/glob_functions/jsonlab/jsonopt.m +32 -0
- paradigma/ppg/glob_functions/jsonlab/loadjson.m +566 -0
- paradigma/ppg/glob_functions/jsonlab/loadubjson.m +528 -0
- paradigma/ppg/glob_functions/jsonlab/mergestruct.m +33 -0
- paradigma/ppg/glob_functions/jsonlab/savejson.m +475 -0
- paradigma/ppg/glob_functions/jsonlab/saveubjson.m +504 -0
- paradigma/ppg/glob_functions/jsonlab/varargin2struct.m +40 -0
- paradigma/ppg/glob_functions/sample_prob_final.m +49 -0
- paradigma/ppg/glob_functions/synchronization.m +76 -0
- paradigma/ppg/glob_functions/tsdf_scan_meta.m +22 -0
- paradigma/ppg/hr_functions/Long_TFD_JOT.m +37 -0
- paradigma/ppg/hr_functions/PPG_TFD_HR.m +59 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/.gitignore +4 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/CHANGELOG.md +23 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/LICENCE.md +27 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/README.md +251 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/README.pdf +0 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/common/gen_Doppler_kern.m +142 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/common/gen_Doppler_lag_kern.m +314 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/common/gen_lag_kern.m +123 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/dec_tfd.m +154 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/decimated_TFDs/dec_di_gdtfd.m +194 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/decimated_TFDs/dec_li_gdtfd.m +200 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/decimated_TFDs/dec_nonsep_gdtfd.m +229 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/decimated_TFDs/dec_sep_gdtfd.m +241 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/full_TFDs/di_gdtfd.m +157 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/full_TFDs/li_gdtfd.m +190 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/full_TFDs/nonsep_gdtfd.m +196 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/full_TFDs/sep_gdtfd.m +199 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/full_tfd.m +144 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/load_curdir.m +13 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/pics/decimated_TFDs_examples.png +0 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/pics/full_TFDs_examples.png +0 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/check_dec_params_seq.m +79 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/dispEE.m +9 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/dispVars.m +26 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/disp_bytes.m +25 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/fold_vector_full.m +40 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/fold_vector_half.m +34 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/gen_LFM.m +29 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/get_analytic_signal.m +76 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/get_window.m +176 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/isreal_fn.m +11 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/padWin.m +97 -0
- paradigma/ppg/hr_functions/TFD toolbox JOT/utils/vtfd.m +149 -0
- paradigma/ppg/preprocessing/preprocessing_imu.m +15 -0
- paradigma/ppg/preprocessing/preprocessing_ppg.m +13 -0
- paradigma/ppg_preprocessing.py +313 -0
- paradigma/preprocessing_config.py +64 -0
- paradigma/quantification.py +58 -0
- paradigma/tremor/TremorFeaturesAndClassification.m +345 -0
- paradigma/tremor/feat_extraction/DerivativesExtract.m +22 -0
- paradigma/tremor/feat_extraction/ExtractBandSignalsRMS.m +72 -0
- paradigma/tremor/feat_extraction/MFCCExtract.m +100 -0
- paradigma/tremor/feat_extraction/PSDBandPower.m +52 -0
- paradigma/tremor/feat_extraction/PSDEst.m +63 -0
- paradigma/tremor/feat_extraction/PSDExtrAxis.m +88 -0
- paradigma/tremor/feat_extraction/PSDExtrOpt.m +95 -0
- paradigma/tremor/preprocessing/InterpData.m +32 -0
- paradigma/tremor/weekly_aggregates/WeeklyAggregates.m +295 -0
- paradigma/util.py +50 -0
- paradigma/windowing.py +217 -0
- paradigma-0.2.0.dist-info/LICENSE +192 -0
- paradigma-0.2.0.dist-info/METADATA +58 -0
- paradigma-0.2.0.dist-info/RECORD +108 -0
- paradigma/dummy.py +0 -3
- paradigma-0.1.2.dist-info/LICENSE +0 -201
- paradigma-0.1.2.dist-info/METADATA +0 -18
- paradigma-0.1.2.dist-info/RECORD +0 -6
- {paradigma-0.1.2.dist-info → paradigma-0.2.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
function [PSDFeaturesOut] = PSDExtrAxis(Conf,Data,freq)
|
|
2
|
+
% #########################################################################
|
|
3
|
+
% Input
|
|
4
|
+
% Conf - Structure
|
|
5
|
+
% .freqrange - array - double - frequency Range for
|
|
6
|
+
% dominant power evaluation
|
|
7
|
+
% .SpectralIntervalPeak - scalar - double - number of samples around
|
|
8
|
+
% the peak to evaluate
|
|
9
|
+
% Fixed Dominant Power
|
|
10
|
+
% .StrAxis - string - signal axis (or Sum) specified to be
|
|
11
|
+
% considered for feature extraction
|
|
12
|
+
% .nfft - scalar - double - number of points for the
|
|
13
|
+
% FFT (number of samples)
|
|
14
|
+
% .Fs - scalar - double - sampling Rate
|
|
15
|
+
% .MinFreqOverallBand - scalar - double - minimum frequency for
|
|
16
|
+
% overall power evaluation
|
|
17
|
+
% .MaxFreqOverallBand - scalar - double - maximum frequency for
|
|
18
|
+
% overall power evaluation
|
|
19
|
+
%
|
|
20
|
+
% Data - PSD Matrix - matrix - double - N frequency values x
|
|
21
|
+
% (Nsignals + 1) - last column is the
|
|
22
|
+
% PSD sum (PSDx + PSDy + PSDz)
|
|
23
|
+
%
|
|
24
|
+
% freq - array - double - frequency vector associsted to the PSD;
|
|
25
|
+
% #########################################################################
|
|
26
|
+
% Output
|
|
27
|
+
% PSDFeaturesOut - matrix - double (1 x 2)
|
|
28
|
+
% (1) PowerAxis - power in the full range 0.5 - 25 Hz
|
|
29
|
+
% (2) DomPower - dominant power 1.25 Hz around the peak
|
|
30
|
+
% within the range: freqrange
|
|
31
|
+
% #########################################################################
|
|
32
|
+
|
|
33
|
+
% Get the estimation parameters
|
|
34
|
+
freqrange = Conf.freqrange;
|
|
35
|
+
SpectralIntervalPeak = Conf.SpectralIntervalPeak;
|
|
36
|
+
StrAxis = Conf.StrAxis;
|
|
37
|
+
nfft = Conf.nfft;
|
|
38
|
+
Fs = Conf.Fs;
|
|
39
|
+
MinFreqOverallBand = Conf.MinFreqOverallBand;
|
|
40
|
+
MaxFreqOverallBand = Conf.MaxFreqOverallBand;
|
|
41
|
+
|
|
42
|
+
% Getting the signal axis or sum according to what specified in the input
|
|
43
|
+
switch StrAxis
|
|
44
|
+
case 'X'
|
|
45
|
+
Pxx = Data(:,1);
|
|
46
|
+
case 'Y'
|
|
47
|
+
Pxx = Data(:,2);
|
|
48
|
+
case 'Z'
|
|
49
|
+
Pxx = Data(:,3);
|
|
50
|
+
case 'Sum'
|
|
51
|
+
Pxx = Data(:,4);
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
f0 = Fs/nfft; % Spectral Resolution
|
|
55
|
+
|
|
56
|
+
SpectrumInterval = SpectralIntervalPeak; % Number of samples taken around the spectral peak to compute dominant power
|
|
57
|
+
FreqLowerBound = freqrange(1); % lower frequency bound
|
|
58
|
+
FreqUpperBound = freqrange(2); % upper frequency bound
|
|
59
|
+
|
|
60
|
+
% Logical array specifying the specified frequency
|
|
61
|
+
BandFreq = (freq >= FreqLowerBound & freq <= FreqUpperBound);
|
|
62
|
+
|
|
63
|
+
% Total Power - area under PSD using an approximation by the left: 5
|
|
64
|
+
% frequency coefficients are considered for symmetry around the peak
|
|
65
|
+
% implying a frequency width of 1.25 Hz
|
|
66
|
+
|
|
67
|
+
InitialIndexFullBandPower = find(freq == MinFreqOverallBand); % Initial index for full-band power estimation - this is required to remove frequency components associated with gyroscope drift
|
|
68
|
+
FinalIndexFullBandPower = find(freq == (MaxFreqOverallBand-f0)); % Final index for full-band power estimation: area will be estimated using approximation by the left
|
|
69
|
+
|
|
70
|
+
TotalPower = f0*sum(Pxx(InitialIndexFullBandPower:FinalIndexFullBandPower)); % Total power up to 25 Hz
|
|
71
|
+
|
|
72
|
+
% Dominanting Frequency Characteristics
|
|
73
|
+
[max_power, ind_max_rel] = max(Pxx(BandFreq)); % Peak values and index within the specified band
|
|
74
|
+
indplus = find(BandFreq == 1); % Initial index of the band specified
|
|
75
|
+
ind_max = indplus(1) + ind_max_rel - 1; % index of the dominant frequency
|
|
76
|
+
|
|
77
|
+
FreqPeak = freq(ind_max); % Dominant frequency
|
|
78
|
+
|
|
79
|
+
LowerFixedPeakBound = max(1,ind_max - SpectrumInterval); % lower bound frequency index avoiding negative indexed for dominant frequency lower than 0.5 Hz
|
|
80
|
+
MaxFixedPeakBound = ind_max + SpectrumInterval; % upper bound frequency index
|
|
81
|
+
|
|
82
|
+
% Dominant power (area under PSD using approximation by the left)
|
|
83
|
+
FixedDomPower = f0*(sum(Pxx(LowerFixedPeakBound:MaxFixedPeakBound))); % this takes 5 PSD coefficients which implies a bandwidth of 1.25 Hz
|
|
84
|
+
|
|
85
|
+
% Concatening features:
|
|
86
|
+
PxxFeatures = [TotalPower FixedDomPower];
|
|
87
|
+
|
|
88
|
+
PSDFeaturesOut = PxxFeatures; % Defining the output
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
function [PSDFeaturesOut] = PSDExtrOpt(Conf,Data,freq)
|
|
2
|
+
% #########################################################################
|
|
3
|
+
% Input
|
|
4
|
+
% Conf - Structure
|
|
5
|
+
% .freqrange - array - double - Frequency Range for feature
|
|
6
|
+
% Extraction
|
|
7
|
+
% .SpectralIntervalPeak - scalar - double - number of samples around
|
|
8
|
+
% the peak to evaluate Fixed
|
|
9
|
+
% Dominant Power
|
|
10
|
+
% .StrAxis - string - signal axis (or Sum) specified to be
|
|
11
|
+
% considered for feature extraction
|
|
12
|
+
% .nfft - scalar - double - number of points for the
|
|
13
|
+
% FFT (number of samples)
|
|
14
|
+
% .Fs - scalar - double - sampling Rate
|
|
15
|
+
%
|
|
16
|
+
% Data - PSD Matrix - matrix - double - Frequency values x (NPSDsignals + 1)
|
|
17
|
+
% last column is the PSD sum
|
|
18
|
+
% (PSDx + PSDy + PSDz)
|
|
19
|
+
%
|
|
20
|
+
% freq - array - double - frequency vector associsted to the PSD;
|
|
21
|
+
% #########################################################################
|
|
22
|
+
% Output - Table with PSD features for the axis (or sum of the axis)
|
|
23
|
+
% selected
|
|
24
|
+
% PSDFeaturesOut - array - double (1 x 3)
|
|
25
|
+
% BandPower - power in the range
|
|
26
|
+
% FreqPeak - dominant frequency in the tremor range
|
|
27
|
+
% FixedDomPower - dominant power 1.25 Hz around the
|
|
28
|
+
% tremor peak
|
|
29
|
+
% #########################################################################
|
|
30
|
+
|
|
31
|
+
% Get the estimation parameters
|
|
32
|
+
freqrange = Conf.freqrange;
|
|
33
|
+
SpectralIntervalPeak = Conf.SpectralIntervalPeak;
|
|
34
|
+
StrAxis = Conf.StrAxis;
|
|
35
|
+
nfft = Conf.nfft;
|
|
36
|
+
Fs = Conf.Fs;
|
|
37
|
+
|
|
38
|
+
% Getting the signal axis or sum according to what specified in the input
|
|
39
|
+
switch StrAxis
|
|
40
|
+
case 'X'
|
|
41
|
+
Pxx = Data(:,1);
|
|
42
|
+
case 'Y'
|
|
43
|
+
Pxx = Data(:,2);
|
|
44
|
+
case 'Z'
|
|
45
|
+
Pxx = Data(:,3);
|
|
46
|
+
case 'Sum'
|
|
47
|
+
Pxx = Data(:,4);
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
f0 = Fs/nfft; % Spectral Resolution
|
|
51
|
+
|
|
52
|
+
SpectrumInterval = SpectralIntervalPeak; % Number of samples taken around
|
|
53
|
+
% the spectral peak to compute
|
|
54
|
+
% dominant power
|
|
55
|
+
|
|
56
|
+
FreqLowerBound = freqrange(1); % lower frequency bound
|
|
57
|
+
FreqUpperBound = freqrange(2); % upper frequency bound
|
|
58
|
+
|
|
59
|
+
% Logical array specifying the specified frequency
|
|
60
|
+
BandFreq = (freq >= FreqLowerBound & freq <= FreqUpperBound);
|
|
61
|
+
|
|
62
|
+
% Power - area under PSD using an approximation by the left
|
|
63
|
+
% Dominant Power: 5 frequency coefficients are considered around the peak
|
|
64
|
+
% (2 coefficients for each side) implying a frequency width of 1.25 Hz
|
|
65
|
+
|
|
66
|
+
% Initial index for bandpower estimation
|
|
67
|
+
InitialIndexBandForPower = find(freq == FreqLowerBound);
|
|
68
|
+
|
|
69
|
+
% Final index for bandpower estimation: area will be estimated using
|
|
70
|
+
% approximation by the left
|
|
71
|
+
FinalIndexBandForPower = find(freq == (FreqUpperBound-f0));
|
|
72
|
+
|
|
73
|
+
% Bandpower evaluation
|
|
74
|
+
BandPower = f0*sum(Pxx(InitialIndexBandForPower:FinalIndexBandForPower));
|
|
75
|
+
|
|
76
|
+
% Dominanting Frequency Characteristics
|
|
77
|
+
[max_power, ind_max_rel] = max(Pxx(BandFreq)); % Peak values and index within the specified band
|
|
78
|
+
indplus = find(BandFreq == 1); % Initial index of the band specified
|
|
79
|
+
ind_max = indplus(1) + ind_max_rel - 1; % index of the dominant frequency
|
|
80
|
+
|
|
81
|
+
FreqPeak = freq(ind_max); % Dominant frequency
|
|
82
|
+
|
|
83
|
+
LowerFixedPeakBound = max(1,ind_max - SpectrumInterval); % lower bound frequency index avoiding negative indexed for dominant frequency lower than 0.5 Hz
|
|
84
|
+
MaxFixedPeakBound = ind_max + SpectrumInterval; % upper bound frequency index
|
|
85
|
+
|
|
86
|
+
% Dominant power (area under PSD using approximation by the left)
|
|
87
|
+
FixedDomPower = f0*(sum(Pxx(LowerFixedPeakBound:MaxFixedPeakBound))); % this takes 5 PSD coefficients which implies a bandwidth of 1.25 Hz
|
|
88
|
+
|
|
89
|
+
% Dominant power normalized by the band power
|
|
90
|
+
% FixedDomPowerRatio = FixedDomPower/BandPower;
|
|
91
|
+
|
|
92
|
+
% Concatening features:
|
|
93
|
+
PxxFeatures = [BandPower FreqPeak FixedDomPower];
|
|
94
|
+
|
|
95
|
+
PSDFeaturesOut = PxxFeatures; % Defining the output
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
% Interpolate Data
|
|
2
|
+
% Diogo C. Soriano
|
|
3
|
+
% 15/08/2022
|
|
4
|
+
|
|
5
|
+
% #########################################################################
|
|
6
|
+
% Input:
|
|
7
|
+
% tr - array - double - running time in (s) after transformation from Unix time;
|
|
8
|
+
% y_curr_gyro - matrix - double - gyroscope matrix Nsamples x 3: columns [x,y,z]
|
|
9
|
+
% Fs - scalar - double - sampling rate (Hz);
|
|
10
|
+
% unix_ticks_ms - scalar - double - Unix ticks / ms
|
|
11
|
+
% ts - scalar - double - Unix time start
|
|
12
|
+
|
|
13
|
+
% Output:
|
|
14
|
+
% t_imu_proc{n} - cell - (double) - Unix time corrected (interpolated);
|
|
15
|
+
% v_imu_proc{n} - cell - (double) - Nsamples x Nchannels - Gyroscope
|
|
16
|
+
% signals interpolated. Columns: [x y z]
|
|
17
|
+
% #########################################################################
|
|
18
|
+
function [tcorrected,y_curr_gyro_interp] = InterpData(tr,y_curr_gyro,Fs,unix_ticks_ms,ts)
|
|
19
|
+
|
|
20
|
+
[tunique, indunique] = unique(tr);
|
|
21
|
+
|
|
22
|
+
y_curr_gyro = y_curr_gyro(indunique,:);
|
|
23
|
+
|
|
24
|
+
ti = (0:1/Fs:tunique(end))';
|
|
25
|
+
|
|
26
|
+
if length(y_curr_gyro(:,1)) > 3
|
|
27
|
+
|
|
28
|
+
y_curr_gyro_interp = interp1(tunique,y_curr_gyro,ti,'spline'); % Use splines to interpolate the data
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
tcorrected = ti*unix_ticks_ms + ts;
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
function WeeklyAggregates(ppp_pep_userid,week_vector)
|
|
2
|
+
|
|
3
|
+
% #########################################################################
|
|
4
|
+
% Input:
|
|
5
|
+
% ppp_pep_userid - id of the subject
|
|
6
|
+
% week_vector - array of week numbers you want to calculate weekly
|
|
7
|
+
% aggregates for
|
|
8
|
+
|
|
9
|
+
% Output: Saves two binary files (Tremor_weeks.bin and Tremor_aggregates.bin) and a metadata file in TSDF format
|
|
10
|
+
% Saved in Tremor_weeks.bin per week:
|
|
11
|
+
% - Week number
|
|
12
|
+
% - Data availability flag
|
|
13
|
+
% - Number of valid days
|
|
14
|
+
% - Total number of windows available
|
|
15
|
+
% - Number of windows available during daytime (08:00-22:00)
|
|
16
|
+
% Saved in Tremor_aggreagtes.bin per week:
|
|
17
|
+
% Tremor time/ arm activity time measures:
|
|
18
|
+
% - tremor proportion overall (24h)
|
|
19
|
+
% - tremor proportion during daytime (08:00-22:00)
|
|
20
|
+
% - tremor proportion overall and in rest (without arm activity)
|
|
21
|
+
% - tremor proportion during daytime and in rest
|
|
22
|
+
% - arm activity proportion overall
|
|
23
|
+
% - arm activity proportion during daytime
|
|
24
|
+
% - tremor proportion during daytime and non-rest (with arm
|
|
25
|
+
% activity)
|
|
26
|
+
% - tremor proportion during nighttime
|
|
27
|
+
% Tremor amplitude and frequency measures (during daytime, based on dominant power 1.25
|
|
28
|
+
% Hz around the tremor peak):
|
|
29
|
+
% - median tremor amplitude
|
|
30
|
+
% - modus of tremor amplitude
|
|
31
|
+
% - 90th percentile of tremor amplitude
|
|
32
|
+
% - IQR of tremor amplitude
|
|
33
|
+
% - median tremor amplitude in rest (without arm activity)
|
|
34
|
+
% - modus of tremor amplitude in rest
|
|
35
|
+
% - 90th percentile of tremor amplitude in rest
|
|
36
|
+
% - IQR of tremor amplitude in rest
|
|
37
|
+
% - median tremor frequency
|
|
38
|
+
% - IQR of tremor frequency
|
|
39
|
+
% - median tremor frequency in rest
|
|
40
|
+
% - IQR of tremor frequency in rest
|
|
41
|
+
% #########################################################################
|
|
42
|
+
|
|
43
|
+
NWeeks = length(week_vector);
|
|
44
|
+
unix_ticks_ms = 1000;
|
|
45
|
+
arm_activity_threshold = 10^0.88; % threshold for arm activity detection (based on 0.5-3 Hz band power)
|
|
46
|
+
tremor_amplitude_threshold = 0.02; % treshold for estimating the tremor amplitude (based on tremor time)
|
|
47
|
+
valid_day_threshold = 10; % threshold for valid day (based on number of hours/day)
|
|
48
|
+
|
|
49
|
+
% Initialize
|
|
50
|
+
start_time_iso = [];
|
|
51
|
+
DataFlag = [];
|
|
52
|
+
total_number_windows = [];
|
|
53
|
+
number_windows_daytime = [];
|
|
54
|
+
tremor_proportion_24h = [];
|
|
55
|
+
tremor_proportion_daytime = [];
|
|
56
|
+
tremor_proportion_24h_rest = [];
|
|
57
|
+
tremor_proportion_daytime_rest = [];
|
|
58
|
+
arm_activity_proportion_24h = [];
|
|
59
|
+
arm_activity_proportion_daytime = [];
|
|
60
|
+
tremor_proportion_daytime_nonrest = [];
|
|
61
|
+
tremor_proportion_nighttime = [];
|
|
62
|
+
tremor_amplitude_median = [];
|
|
63
|
+
tremor_amplitude_modus = [];
|
|
64
|
+
tremor_amplitude_90th = [];
|
|
65
|
+
tremor_amplitude_IQR = [];
|
|
66
|
+
tremor_amplitude_median_rest = [];
|
|
67
|
+
tremor_amplitude_modus_rest = [];
|
|
68
|
+
tremor_amplitude_90th_rest = [];
|
|
69
|
+
tremor_amplitude_IQR_rest = [];
|
|
70
|
+
tremor_frequency_median = [];
|
|
71
|
+
tremor_frequency_IQR = [];
|
|
72
|
+
tremor_frequency_median_rest = [];
|
|
73
|
+
tremor_frequency_IQR_rest = [];
|
|
74
|
+
|
|
75
|
+
%% In case you want to remove the day of first visit (because of OFF state)
|
|
76
|
+
% load('Visit1_day.mat')
|
|
77
|
+
% idnum = char(ppp_pep_userid);
|
|
78
|
+
% idnum = string(idnum(:,5:end));
|
|
79
|
+
% Visit1_date = Visit1_day.Date(ismember(Visit1_day.ID,idnum));
|
|
80
|
+
% Visit1_day_num = day(Visit1_date);
|
|
81
|
+
|
|
82
|
+
for i = 1:NWeeks
|
|
83
|
+
|
|
84
|
+
subjectfolder = strcat('C:\Users\z835211\Documents\Data\TSDF output\WatchData.IMU.Week',num2str(week_vector(i)),'\',ppp_pep_userid);
|
|
85
|
+
|
|
86
|
+
if isfolder(subjectfolder)
|
|
87
|
+
|
|
88
|
+
DataFlag(i) = 1; % 1 if there is data for this week, 0 if there is no data (of enough good quality)
|
|
89
|
+
|
|
90
|
+
% load tremor predictions and features for specific subject and week:
|
|
91
|
+
[metadata, data] = load_tsdf_metadata_from_path(strcat(subjectfolder,'\Tremor_predictions_meta.json'));
|
|
92
|
+
[~, data2] = load_tsdf_metadata_from_path(strcat(subjectfolder,'\Tremor_features_meta.json'));
|
|
93
|
+
|
|
94
|
+
metafile_template = metadata{1};
|
|
95
|
+
|
|
96
|
+
% extract the dates to determine the dates of valid days
|
|
97
|
+
tremor_time = datetime(data{1,1}/unix_ticks_ms, "ConvertFrom", "posixtime", 'Format', 'dd-MMM-yyyy HH:mm:ss Z', 'TimeZone', 'Europe/Amsterdam');
|
|
98
|
+
|
|
99
|
+
days = unique(day(tremor_time));
|
|
100
|
+
|
|
101
|
+
Valid_days = [];
|
|
102
|
+
|
|
103
|
+
for k = 1:length(days)
|
|
104
|
+
|
|
105
|
+
NumWindows_daytime = length(find(day(tremor_time)==days(k) & ismember(hour(tremor_time),[8,9,10,11,12,13,14,15,16,17,18,19,20,21]))); % Find number of windows during daytime
|
|
106
|
+
|
|
107
|
+
if NumWindows_daytime*4/3600 >= valid_day_threshold % Determine which days are valid days
|
|
108
|
+
|
|
109
|
+
Valid_days = [Valid_days; days(k)];
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
if ~isempty(Valid_days)
|
|
115
|
+
|
|
116
|
+
% if i == 1
|
|
117
|
+
% Valid_days(Valid_days==Visit1_day_num) = []; % remove because of OFF-state around visit 1
|
|
118
|
+
% end
|
|
119
|
+
|
|
120
|
+
number_valid_days(i) = length(Valid_days);
|
|
121
|
+
|
|
122
|
+
% Create several flags to indicate for every window whether
|
|
123
|
+
% specific conditions are met:
|
|
124
|
+
valid = ismember(day(tremor_time),Valid_days); % window belongs to a valid day
|
|
125
|
+
tremor_valid = valid & data{1,2}(:,2)==1; % window belongs to a valid day and is classified as tremor
|
|
126
|
+
daytime = ismember(hour(tremor_time),[8,9,10,11,12,13,14,15,16,17,18,19,20,21]); % window belongs to daytime
|
|
127
|
+
daytime_valid = valid & daytime; % window belongs to daytime and to a valid day
|
|
128
|
+
tremor_daytime_valid = daytime_valid & data{1,2}(:,2)==1; % window belongs to daytime and a valid day and is classified as tremor
|
|
129
|
+
nighttime_valid = valid & ~daytime; % window belongs to nighttime and to a valid day
|
|
130
|
+
tremor_nighttime_valid = nighttime_valid & data{1,2}(:,2)==1; % window belongs to nighttime and to a valid day and is classified as tremor
|
|
131
|
+
|
|
132
|
+
rest_valid = data2{1,2}(:,17)<arm_activity_threshold & valid; % window belongs to a valid day and rest (no arm activity)
|
|
133
|
+
tremor_rest_valid = rest_valid & data{1,2}(:,2)==1; % window belongs to a valid day and rest and is classified as tremor
|
|
134
|
+
nonrest_valid = data2{1,2}(:,17)>=arm_activity_threshold & valid; % window belongs to a valid day and non-rest (with arm activity)
|
|
135
|
+
daytime_rest_valid = daytime & rest_valid; % window belongs to daytime, a valid day and rest
|
|
136
|
+
tremor_daytime_rest_valid = daytime_rest_valid & data{1,2}(:,2)==1; % window belongs to daytime, a valid day and rest and is classified as tremor
|
|
137
|
+
daytime_nonrest_valid= daytime & nonrest_valid; % window belongs to daytime, a valid day and non-rest
|
|
138
|
+
tremor_daytime_nonrest_valid = daytime_nonrest_valid & data{1,2}(:,2)==1; % window belongs to daytime, a valid day and non-rest and is classified as tremor
|
|
139
|
+
|
|
140
|
+
total_number_windows(i) = length(find(valid==1)); % total number of windows available during valid days
|
|
141
|
+
number_windows_daytime(i) = length(find(daytime_valid==1)); % total number of windows available during daytime on valid days
|
|
142
|
+
|
|
143
|
+
% Calculate the weekly aggregated measures for tremor time, arm
|
|
144
|
+
% activity and tremor frequency:
|
|
145
|
+
tremor_proportion_24h(i) = length(find(tremor_valid==1))/length(find(valid==1));
|
|
146
|
+
tremor_proportion_24h_rest(i) = length(find(tremor_rest_valid==1))/length(find(rest_valid==1));
|
|
147
|
+
arm_activity_proportion_24h(i) = length(find(nonrest_valid==1))/length(find(valid==1));
|
|
148
|
+
|
|
149
|
+
tremor_proportion_daytime(i) = length(find(tremor_daytime_valid==1))/length(find(daytime_valid==1));
|
|
150
|
+
tremor_proportion_daytime_rest(i) = length(find(tremor_daytime_rest_valid==1))/length(find(daytime_rest_valid==1));
|
|
151
|
+
arm_activity_proportion_daytime(i) = length(find(daytime_nonrest_valid==1))/length(find(daytime_valid==1));
|
|
152
|
+
|
|
153
|
+
tremor_proportion_daytime_nonrest(i) = length(find(tremor_daytime_nonrest_valid==1))/length(find(daytime_nonrest_valid==1));
|
|
154
|
+
tremor_proportion_nighttime(i) = length(find(tremor_nighttime_valid==1))/length(find(nighttime_valid==1));
|
|
155
|
+
|
|
156
|
+
tremor_frequency_median(i) = median(data2{1,2}(tremor_daytime_valid,10));
|
|
157
|
+
tremor_frequency_IQR(i) = iqr(data2{1,2}(tremor_daytime_valid,10));
|
|
158
|
+
tremor_frequency_median_rest(i) = median(data2{1,2}(tremor_daytime_rest_valid,10));
|
|
159
|
+
tremor_frequency_IQR_rest(i) = iqr(data2{1,2}(tremor_daytime_rest_valid,10));
|
|
160
|
+
|
|
161
|
+
if tremor_proportion_daytime(i)>=tremor_amplitude_threshold % determine whether there is enough tremor detected to calculate the amplitude
|
|
162
|
+
tremor_amplitude_median(i) = median(log10(1+data2{1,2}(tremor_daytime_valid,13)));
|
|
163
|
+
tremor_amplitude_90th(i) = prctile(log10(1+data2{1,2}(tremor_daytime_valid,13)),90);
|
|
164
|
+
tremor_amplitude_IQR(i) = iqr(log10(1+data2{1,2}(tremor_daytime_valid,13)));
|
|
165
|
+
% determine the modus:
|
|
166
|
+
binEdges = linspace(0,8,41); % Define the edges of the bins
|
|
167
|
+
Histogram = histcounts(log10(1+data2{1,2}(tremor_daytime_valid,13)), binEdges);
|
|
168
|
+
[~, maxIndex] = max(Histogram);
|
|
169
|
+
tremor_amplitude_modus(i) = mean([binEdges(maxIndex), binEdges(maxIndex + 1)]);
|
|
170
|
+
|
|
171
|
+
tremor_amplitude_median_rest(i) = median(log10(1+data2{1,2}(tremor_daytime_rest_valid,13)));
|
|
172
|
+
tremor_amplitude_90th_rest(i) = prctile(log10(1+data2{1,2}(tremor_daytime_rest_valid,13)),90);
|
|
173
|
+
tremor_amplitude_IQR_rest(i) = iqr(log10(1+data2{1,2}(tremor_daytime_rest_valid,13)));
|
|
174
|
+
% determine the modus:
|
|
175
|
+
binEdges = linspace(0,8,41); % Define the edges of the bins
|
|
176
|
+
Histogram = histcounts(log10(1+data2{1,2}(tremor_daytime_rest_valid,13)), binEdges);
|
|
177
|
+
[~, maxIndex] = max(Histogram);
|
|
178
|
+
tremor_amplitude_modus_rest(i) = mean([binEdges(maxIndex), binEdges(maxIndex + 1)]);
|
|
179
|
+
else % tremor amplitude is not calculated
|
|
180
|
+
tremor_amplitude_median(i) = NaN;
|
|
181
|
+
tremor_amplitude_modus(i) = NaN;
|
|
182
|
+
tremor_amplitude_90th(i) = NaN;
|
|
183
|
+
tremor_amplitude_IQR(i) = NaN;
|
|
184
|
+
tremor_amplitude_median_rest(i) = NaN;
|
|
185
|
+
tremor_amplitude_modus_rest(i) = NaN;
|
|
186
|
+
tremor_amplitude_90th_rest(i) = NaN;
|
|
187
|
+
tremor_amplitude_IQR_rest(i) = NaN;
|
|
188
|
+
end
|
|
189
|
+
else % there are no valid days for this week
|
|
190
|
+
number_valid_days(i) = 0;
|
|
191
|
+
total_number_windows(i) = 0;
|
|
192
|
+
number_windows_daytime(i) = 0;
|
|
193
|
+
tremor_proportion_24h(i) = NaN;
|
|
194
|
+
tremor_proportion_24h_rest(i) = NaN;
|
|
195
|
+
arm_activity_proportion_24h(i) = NaN;
|
|
196
|
+
tremor_proportion_daytime(i) = NaN;
|
|
197
|
+
tremor_proportion_daytime_rest(i) = NaN;
|
|
198
|
+
arm_activity_proportion_daytime(i) = NaN;
|
|
199
|
+
tremor_proportion_daytime_nonrest(i) = NaN;
|
|
200
|
+
tremor_proportion_nighttime(i) = NaN;
|
|
201
|
+
tremor_amplitude_median(i) = NaN;
|
|
202
|
+
tremor_amplitude_modus(i) = NaN;
|
|
203
|
+
tremor_amplitude_90th(i) = NaN;
|
|
204
|
+
tremor_amplitude_IQR(i) = NaN;
|
|
205
|
+
tremor_amplitude_median_rest(i) = NaN;
|
|
206
|
+
tremor_amplitude_modus_rest(i) = NaN;
|
|
207
|
+
tremor_amplitude_90th_rest(i) = NaN;
|
|
208
|
+
tremor_amplitude_IQR_rest(i) = NaN;
|
|
209
|
+
tremor_frequency_median(i) = NaN;
|
|
210
|
+
tremor_frequency_IQR(i) = NaN;
|
|
211
|
+
tremor_frequency_median_rest(i) = NaN;
|
|
212
|
+
tremor_frequency_IQR_rest(i) = NaN;
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
% Determine the start time of the first week
|
|
216
|
+
if isempty(start_time_iso)
|
|
217
|
+
start_time_iso = datetime(data{1,1}(1)/unix_ticks_ms,"ConvertFrom", "posixtime", 'Format', 'dd-MMM-yyyy Z', 'TimeZone', 'Europe/Amsterdam');
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
else % theres is no data available for this week
|
|
221
|
+
DataFlag(i) = 0;
|
|
222
|
+
number_valid_days(i) = NaN;
|
|
223
|
+
total_number_windows(i) = NaN;
|
|
224
|
+
number_windows_daytime(i) = NaN;
|
|
225
|
+
tremor_proportion_24h(i) = NaN;
|
|
226
|
+
tremor_proportion_24h_rest(i) = NaN;
|
|
227
|
+
arm_activity_proportion_24h(i) = NaN;
|
|
228
|
+
tremor_proportion_daytime(i) = NaN;
|
|
229
|
+
tremor_proportion_daytime_rest(i) = NaN;
|
|
230
|
+
arm_activity_proportion_daytime(i) = NaN;
|
|
231
|
+
tremor_proportion_daytime_nonrest(i) = NaN;
|
|
232
|
+
tremor_proportion_nighttime(i) = NaN;
|
|
233
|
+
tremor_amplitude_median(i) = NaN;
|
|
234
|
+
tremor_amplitude_modus(i) = NaN;
|
|
235
|
+
tremor_amplitude_90th(i) = NaN;
|
|
236
|
+
tremor_amplitude_IQR(i) = NaN;
|
|
237
|
+
tremor_amplitude_median_rest(i) = NaN;
|
|
238
|
+
tremor_amplitude_modus_rest(i) = NaN;
|
|
239
|
+
tremor_amplitude_90th_rest(i) = NaN;
|
|
240
|
+
tremor_amplitude_IQR_rest(i) = NaN;
|
|
241
|
+
tremor_frequency_median(i) = NaN;
|
|
242
|
+
tremor_frequency_IQR(i) = NaN;
|
|
243
|
+
tremor_frequency_median_rest(i) = NaN;
|
|
244
|
+
tremor_frequency_IQR_rest(i) = NaN;
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
% Determine the endtime of the last week:
|
|
249
|
+
end_time_iso = datetime(data{1,1}(end)/unix_ticks_ms,"ConvertFrom", "posixtime", 'Format', 'dd-MMM-yyyy Z', 'TimeZone', 'Europe/Amsterdam');
|
|
250
|
+
|
|
251
|
+
% Save output in TSDF:
|
|
252
|
+
|
|
253
|
+
metafile_template.ppp_source_protobuf = [];
|
|
254
|
+
metafile_template.freq_sampling_original = [];
|
|
255
|
+
metafile_template.freq_sampling_adjusted = [];
|
|
256
|
+
|
|
257
|
+
metafile_template.start_iso8601 = start_time_iso;
|
|
258
|
+
metafile_template.end_iso8601 = end_time_iso;
|
|
259
|
+
|
|
260
|
+
metafile_template.arm_activity_threshold = arm_activity_threshold;
|
|
261
|
+
metafile_template.amplitude_estimation_threshold = tremor_amplitude_threshold;
|
|
262
|
+
|
|
263
|
+
data_tsdf{1} = [int64(week_vector)' int64(DataFlag)' int64(number_valid_days)' int64(total_number_windows)' int64(number_windows_daytime)'];
|
|
264
|
+
data_tsdf{2} = [tremor_proportion_24h' tremor_proportion_24h_rest' arm_activity_proportion_24h' tremor_proportion_daytime' tremor_proportion_daytime_rest'...
|
|
265
|
+
arm_activity_proportion_daytime' tremor_proportion_daytime_nonrest' tremor_proportion_nighttime' tremor_amplitude_median' tremor_amplitude_modus' tremor_amplitude_90th' tremor_amplitude_IQR' tremor_amplitude_median_rest'...
|
|
266
|
+
tremor_amplitude_modus_rest' tremor_amplitude_90th_rest' tremor_amplitude_IQR_rest' tremor_frequency_median' tremor_frequency_IQR' tremor_frequency_median_rest'...
|
|
267
|
+
tremor_frequency_IQR_rest'];
|
|
268
|
+
|
|
269
|
+
metafile_weeks = metafile_template;
|
|
270
|
+
metafile_aggregates = metafile_template;
|
|
271
|
+
|
|
272
|
+
metafile_weeks.channels = {'week number','data availability','number of valid days','total number of windows','number of windows daytime'};
|
|
273
|
+
metafile_weeks.units = {'','boolean_num','','',''};
|
|
274
|
+
metafile_weeks.file_name = 'Tremor_weeks.bin';
|
|
275
|
+
|
|
276
|
+
metafile_aggregates.channels = {'tremor proportion','tremor proportion in rest','arm activity proportion','daytime tremor proportion',...
|
|
277
|
+
'daytime tremor proportion in rest','daytime arm activity proportion', 'daytime tremor proportion during arm activity','nighttime tremor proportion','median tremor amplitude','modus tremor amplitude',...
|
|
278
|
+
'tremor amplitude 90th cent','tremor amplitude IQR','median tremor amplitude in rest','modus tremor amplitude in rest',...
|
|
279
|
+
'tremor amplitude 90th cent in rest','tremor amplitude IQR in rest','median tremor frequency','tremor frequency IQR',...
|
|
280
|
+
'median tremor frequency in rest','tremor frequency IQR in rest'};
|
|
281
|
+
metafile_aggregates.units = {'proportion','proportion','proportion','proportion','proportion','proportion','proportion','proportion','','','','','','','','','Hz','Hz','Hz','Hz'};
|
|
282
|
+
metafile_aggregates.file_name = 'Tremor_aggregates.bin';
|
|
283
|
+
|
|
284
|
+
meta_tsdf{1} = metafile_weeks;
|
|
285
|
+
meta_tsdf{2} = metafile_aggregates;
|
|
286
|
+
|
|
287
|
+
metadata_file_name = "Tremor_weekly_aggregates_meta.json";
|
|
288
|
+
location = ['C:\Users\z835211\Documents\Data\TSDF output\Weekly aggregates\',ppp_pep_userid, '\'];
|
|
289
|
+
mkdir(['C:\Users\z835211\Documents\Data\TSDF output\Weekly aggregates\',ppp_pep_userid]);
|
|
290
|
+
|
|
291
|
+
save_tsdf_data(meta_tsdf, data_tsdf, location, metadata_file_name);
|
|
292
|
+
|
|
293
|
+
clear all
|
|
294
|
+
|
|
295
|
+
end
|
paradigma/util.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from datetime import timedelta
|
|
5
|
+
from dateutil import parser
|
|
6
|
+
from typing import Tuple
|
|
7
|
+
|
|
8
|
+
import tsdf
|
|
9
|
+
from tsdf import TSDFMetadata
|
|
10
|
+
|
|
11
|
+
def parse_iso8601_to_datetime(date_str):
|
|
12
|
+
return parser.parse(date_str)
|
|
13
|
+
|
|
14
|
+
def format_datetime_to_iso8601(datetime):
|
|
15
|
+
return datetime.strftime('%Y-%m-%dT%H:%M:%S') + 'Z'
|
|
16
|
+
|
|
17
|
+
def get_end_iso8601(start_iso8601, window_length_seconds):
|
|
18
|
+
start_date = parser.parse(start_iso8601)
|
|
19
|
+
end_date = start_date + timedelta(seconds=window_length_seconds)
|
|
20
|
+
return format_datetime_to_iso8601(end_date)
|
|
21
|
+
|
|
22
|
+
def write_data(metadata_time: TSDFMetadata, metadata_samples: TSDFMetadata,
|
|
23
|
+
output_path: str, output_filename: str, df: pd.DataFrame):
|
|
24
|
+
if not os.path.exists(output_path):
|
|
25
|
+
os.makedirs(output_path)
|
|
26
|
+
|
|
27
|
+
# Make sure the iso8601 format is correctly set
|
|
28
|
+
#TODO: this should be properly validated in the tsdf library instead
|
|
29
|
+
start_date = parser.parse(metadata_time.__getattribute__('start_iso8601'))
|
|
30
|
+
metadata_time.start_iso8601 = format_datetime_to_iso8601(start_date)
|
|
31
|
+
end_date = parser.parse(metadata_time.__getattribute__('end_iso8601'))
|
|
32
|
+
metadata_time.end_iso8601 = format_datetime_to_iso8601(end_date)
|
|
33
|
+
start_date = parser.parse(metadata_samples.__getattribute__('start_iso8601'))
|
|
34
|
+
metadata_samples.start_iso8601 = format_datetime_to_iso8601(start_date)
|
|
35
|
+
end_date = parser.parse(metadata_samples.__getattribute__('end_iso8601'))
|
|
36
|
+
metadata_samples.end_iso8601 = format_datetime_to_iso8601(end_date)
|
|
37
|
+
|
|
38
|
+
# TODO: improve the way the metadata is stored at a different location
|
|
39
|
+
metadata_time.file_dir_path = output_path
|
|
40
|
+
metadata_samples.file_dir_path = output_path
|
|
41
|
+
|
|
42
|
+
# store binaries and metadata
|
|
43
|
+
tsdf.write_dataframe_to_binaries(output_path, df, [metadata_time, metadata_samples])
|
|
44
|
+
tsdf.write_metadata([metadata_time, metadata_samples], output_filename)
|
|
45
|
+
|
|
46
|
+
def read_metadata(input_path: str, meta_filename: str, time_filename: str, values_filename: str) -> Tuple[TSDFMetadata, TSDFMetadata]:
|
|
47
|
+
metadata_dict = tsdf.load_metadata_from_path(os.path.join(input_path, meta_filename))
|
|
48
|
+
metadata_time = metadata_dict[time_filename]
|
|
49
|
+
metadata_samples = metadata_dict[values_filename]
|
|
50
|
+
return metadata_time, metadata_samples
|