tsfel 0.1.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.
tests/__init__.py ADDED
File without changes
tests/benchmark.py ADDED
@@ -0,0 +1,160 @@
1
+ import time
2
+
3
+ import matplotlib.pyplot as plt
4
+ import pandas as pd
5
+ import seaborn as sns
6
+ from datasets.empirical1000_dataset import Empirical1000Dataset
7
+
8
+ import tsfel
9
+
10
+ DOMAINS = [
11
+ "statistical",
12
+ "temporal",
13
+ "spectral",
14
+ ] # It specifies the domains included in the analysis.
15
+
16
+ emp_dataset = Empirical1000Dataset()
17
+
18
+ #########################################################################################################
19
+ # Experiment 1 - Overall executing time benchmarking per domain #
20
+ #########################################################################################################
21
+ execution_times_global = pd.DataFrame(
22
+ {
23
+ "Domain": pd.Series(dtype="str"),
24
+ "Execution Time (s)": pd.Series(dtype="int"),
25
+ "Normalized Execution Time (s/feature)": pd.Series(dtype="float32"),
26
+ },
27
+ )
28
+
29
+ for domain in DOMAINS:
30
+ n_features_domain = len(tsfel.get_features_by_domain(domain)[domain])
31
+
32
+ init_time = time.perf_counter()
33
+ for _id, ts in emp_dataset.raw.items():
34
+ _ = tsfel.time_series_features_extractor(
35
+ tsfel.get_features_by_domain(domain),
36
+ ts.sig,
37
+ fs=100,
38
+ verbose=False,
39
+ )
40
+ end_time = time.perf_counter()
41
+ total_time = end_time - init_time
42
+
43
+ execution_times_global = pd.concat(
44
+ [
45
+ execution_times_global,
46
+ pd.DataFrame(
47
+ {
48
+ "Domain": [domain],
49
+ "Execution Time (s)": [int(total_time)],
50
+ "Normalized Execution Time (s/feature)": [
51
+ total_time / n_features_domain,
52
+ ],
53
+ },
54
+ ),
55
+ ],
56
+ ignore_index=True,
57
+ )
58
+
59
+ #########################################################################################################
60
+ # Experiment 2 - Detailed time benchmarking as function of time series length grouped by feature domain #
61
+ #########################################################################################################
62
+ execution_times_individual = pd.DataFrame(
63
+ {
64
+ "Domain": pd.Series(dtype="str"),
65
+ "ID": pd.Series(dtype="int"),
66
+ "Execution Time (s)": pd.Series(dtype="float32"),
67
+ "Length": pd.Series(dtype="int"),
68
+ },
69
+ )
70
+
71
+ for domain in ["statistical", "temporal", "spectral"]:
72
+ for id, ts in emp_dataset.raw.items():
73
+ init_time = time.perf_counter()
74
+ _ = tsfel.time_series_features_extractor(
75
+ tsfel.get_features_by_domain(domain),
76
+ ts.sig,
77
+ fs=100,
78
+ verbose=False,
79
+ )
80
+ end_time = time.perf_counter()
81
+ total_time = end_time - init_time
82
+
83
+ execution_times_individual = pd.concat(
84
+ [
85
+ execution_times_individual,
86
+ pd.DataFrame(
87
+ {
88
+ "Domain": [domain],
89
+ "ID": [id],
90
+ "Execution Time (s)": [total_time],
91
+ "Length": [ts.len],
92
+ },
93
+ ),
94
+ ],
95
+ ignore_index=True,
96
+ )
97
+
98
+ # Some lengths have a low number of time series for statistical analysis (< 25 samples). We only consider lengths that
99
+ # have at least 25 samples for the analysis. For each length, we calculate the average and standard deviation and plot
100
+ # them on normal and log-log scales.
101
+ length_counts = execution_times_individual["Length"].value_counts()
102
+ valid_lengths = length_counts[length_counts >= 25].index
103
+ filtered_df = execution_times_individual[execution_times_individual["Length"].isin(valid_lengths)]
104
+ grouped_stats = filtered_df.groupby(["Length", "Domain"])["Execution Time (s)"].agg(["mean", "std"]).reset_index()
105
+
106
+
107
+ fig, (ax0, ax1) = plt.subplots(ncols=2)
108
+ for domain, marker in zip(DOMAINS, ["o", "v", "^"]):
109
+ _data_slice = grouped_stats[grouped_stats["Domain"] == domain]
110
+ ax0.errorbar(
111
+ _data_slice["Length"],
112
+ _data_slice["mean"],
113
+ yerr=_data_slice["std"],
114
+ label=domain,
115
+ marker=marker,
116
+ capsize=4,
117
+ )
118
+ ax1.errorbar(
119
+ _data_slice["Length"],
120
+ _data_slice["mean"],
121
+ yerr=_data_slice["std"],
122
+ label=domain,
123
+ marker=marker,
124
+ capsize=4,
125
+ )
126
+
127
+ [ax.set(xlabel="Length (#)", ylabel="Execution Time (s)") for ax in [ax0, ax1]]
128
+ [ax.spines[loc].set_visible(False) for ax in [ax0, ax1] for loc in ["top", "right"]]
129
+ [ax.legend() for ax in [ax0, ax1]]
130
+ ax1.set_xscale("log")
131
+ ax1.set_yscale("log")
132
+
133
+ #########################################################################################################
134
+ # Experiment 4 - Measure the overall execution time per feature #
135
+ #########################################################################################################
136
+ execution_times_feature = pd.DataFrame(columns=["Domain", "Feature_Name", "Execution_Time"])
137
+ cfg = tsfel.get_features_by_domain()
138
+ for domain in DOMAINS:
139
+ for feature in cfg[domain]:
140
+ print(domain, feature)
141
+ init_time = time.perf_counter()
142
+ for _, ts in emp_dataset.raw.items():
143
+ _ = tsfel.time_series_features_extractor(
144
+ {domain: {feature: cfg[domain][feature]}},
145
+ ts.sig,
146
+ fs=100,
147
+ verbose=False,
148
+ )
149
+ execution_time = time.perf_counter() - init_time
150
+
151
+ execution_times_feature.loc[len(execution_times_feature)] = {
152
+ "Domain": domain,
153
+ "Feature_Name": feature,
154
+ "Execution_Time": execution_time,
155
+ }
156
+
157
+ fig, ax = plt.subplots(1, 1)
158
+ sns.barplot(execution_times_feature, x="Feature_Name", y="Execution_Time", hue="Domain", ax=ax)
159
+ ax.tick_params(axis="x", rotation=90)
160
+ plt.show(block=False)
@@ -0,0 +1,93 @@
1
+ """This module offers helper functions designed to facilitate testing and
2
+ enhance understanding of features that quantify repetitiveness in dynamic
3
+ systems."""
4
+
5
+ import matplotlib.pyplot as plt
6
+ import neurokit2 as nk
7
+ import numpy as np
8
+ from statsmodels.graphics.tsaplots import plot_acf
9
+ from statsmodels.tsa.stattools import acf
10
+
11
+ from tests.tests_tools.test_data.complexity_datasets import load_complexities_datasets
12
+
13
+
14
+ def plot_dfa(info, scale, fluctuations, ax):
15
+ """Plot log-log visualization of the detrended fluctuation analysis
16
+ (DFA)."""
17
+
18
+ polyfit = np.polyfit(np.log2(scale), np.log2(fluctuations), 1)
19
+ fluctfit = 2 ** np.polyval(polyfit, np.log2(scale))
20
+ ax.loglog(scale, fluctuations, "o", c="#90A4AE")
21
+ ax.loglog(
22
+ scale,
23
+ fluctfit,
24
+ c="#E91E63",
25
+ label=r"$\alpha$ = {:.3f}".format(info["Alpha"]),
26
+ )
27
+
28
+ return ax
29
+
30
+
31
+ def plot_multiscale_entropy(info, ax):
32
+ """Plots the entropy values for each scale factor."""
33
+
34
+ ax.plot(
35
+ info["Scale"][np.isfinite(info["Value"])],
36
+ info["Value"][np.isfinite(info["Value"])],
37
+ color="#FF9800",
38
+ )
39
+
40
+ return ax
41
+
42
+
43
+ def get_first_acf_time_constant(signal):
44
+ """Captures the approximate scale of the autocorrelation function by
45
+ measuring the first time lag at which the autocorrelation function (acf)
46
+ drops below 1/e = 0.3679."""
47
+ n = signal.size
48
+ maxlag = int(n / 4)
49
+ threshold = 0.36787944117144233 # 1 / np.exp(1)
50
+
51
+ acf_vec = acf(signal, adjusted=True, fft=n > 400, nlags=maxlag)[
52
+ 1:
53
+ ] # n > 400 empirically selected based on performance tests
54
+ idxs = np.where(acf_vec < threshold)[0]
55
+ first_lag = idxs[0] + 1 if idxs.size > 0 else maxlag
56
+
57
+ return first_lag
58
+
59
+
60
+ dataset = load_complexities_datasets()
61
+
62
+ f, ax = plt.subplots(4, len(dataset), figsize=(15, 5))
63
+ for i, (k, _v) in enumerate(dataset.items()):
64
+ signal = dataset[k]
65
+
66
+ # First row (raw data)
67
+ ax[0, i].plot(signal, "k")
68
+ ax[0, i].set_title(k)
69
+ ax[0, i].spines[["left", "top", "right"]].set_visible(False)
70
+ ax[0, i].tick_params(left=False, right=False, labelleft=False)
71
+
72
+ # Second row (first_acf_time_constant)
73
+ plot_acf(signal, ax[1, i], adjusted=True, fft=len(signal) > 1250, title="")
74
+ ax[1, i].axhline(y=(1 / np.e), color="r", linestyle="--")
75
+ ax[1, i].spines[["top", "right"]].set_visible(False)
76
+ ax[1, i].set_title("$\\tau = %d$" % get_first_acf_time_constant(signal))
77
+
78
+ # Third row (dfa)
79
+ # TODO: Change to our own implementation instead of relying on neurokit2
80
+ _, info = nk.fractal_dfa(signal)
81
+ plot_dfa(info, info["scale"], info["Fluctuations"], ax[2, i])
82
+ ax[2, i].set_title("$\\alpha = %0.2f$" % info["Alpha"])
83
+ ax[2, i].set_axis_off()
84
+
85
+ # Forth row (mse)
86
+ mse, info = nk.entropy_multiscale(signal)
87
+ plot_multiscale_entropy(info, ax[3, i])
88
+ ax[3, i].set_title("mse = %0.2f" % mse)
89
+ ax[3, i].set_ylim([0, 2.5])
90
+ ax[3, i].spines[["top", "right"]].set_visible(False)
91
+
92
+ f.tight_layout()
93
+ plt.show(block=False)
@@ -0,0 +1,4 @@
1
+ """A utility module providing simplified access to time series datasets used
2
+ for benchmarking and testing."""
3
+
4
+ from .empirical1000_dataset import Empirical1000Dataset
@@ -0,0 +1,188 @@
1
+ import os
2
+ import shutil
3
+ import zipfile
4
+ from pathlib import Path
5
+ from urllib.parse import urlparse
6
+
7
+ import numpy as np
8
+ import pandas as pd
9
+ import requests
10
+ import scipy.io as sio
11
+ from tqdm import tqdm
12
+
13
+ module_path = os.path.dirname(__file__)
14
+ data_path = os.path.join(module_path, "cached_datasets")
15
+
16
+
17
+ class Empirical1000Dataset:
18
+ """A convenience class to access the Empirical1000 dataset.
19
+
20
+ When using one this dataset, please cite [1]_.
21
+
22
+ Parameters
23
+ ----------
24
+ use_cache : bool (default: True)
25
+ Whether a cached version of the dataset should be used, if one is found.
26
+ The dataset is always cached upon loading, and this parameter only determines
27
+ whether the cached version shall be refreshed upon loading.
28
+
29
+ extract_features : bool (default: False)
30
+ Whether a feature extraction routine should be called after loading the data files.
31
+ TODO: Implement this functionality.
32
+
33
+ Notes
34
+ -----
35
+ To optimize running times it is recommended to use `use_cache=True` (default) in order
36
+ to only experience a time once downloading and work on a cached version of the dataset afterward.
37
+
38
+
39
+ References
40
+ ----------
41
+ .. [1] Fulcher, B. D., Lubba, C. H., Sethi, S. S., & Jones, N. S. (2020).
42
+ A self-organizing, living library of time-series data. Scientific data, 7(1), 213.
43
+ """
44
+
45
+ def __init__(self, use_cache=True, extract_features=False):
46
+ self.use_cache = use_cache
47
+
48
+ self.raw = {}
49
+ self.features = {} # An add-on to this class will contain a featurized data representation.
50
+
51
+ self.__dataset_url = "https://figshare.com/ndownloader/articles/5436136/versions/10"
52
+ self.cache_folder_path = data_path
53
+ self.__empirical1000_folder_path = os.path.join(
54
+ self.cache_folder_path,
55
+ "Empirical1000",
56
+ )
57
+
58
+ if not os.path.exists(self.cache_folder_path) or not os.listdir(self.cache_folder_path) or not use_cache:
59
+ print("Cache folder is empty. Downloading the Empirical1000 dataset...")
60
+ Path(os.path.join(self.cache_folder_path, "Empirical1000")).mkdir(
61
+ parents=True,
62
+ exist_ok=True,
63
+ )
64
+ self.__download_dataset()
65
+
66
+ self.__data_files = sio.loadmat(
67
+ os.path.join(self.__empirical1000_folder_path, "INP_1000ts.mat"),
68
+ )
69
+ self.metadata = pd.read_csv(
70
+ os.path.join(self.__empirical1000_folder_path, "hctsa_timeseries-info.csv"),
71
+ )
72
+
73
+ for i, name in enumerate(self.metadata["Name"]):
74
+ self.raw[i] = EmpiricalTimeSeries(
75
+ name,
76
+ self.__data_files["timeSeriesData"][0][i].flatten(),
77
+ )
78
+ if extract_features:
79
+ tqdm_iterator = tqdm(
80
+ total=len(self.metadata["Name"]),
81
+ desc="Extracting features.",
82
+ )
83
+ tqdm_iterator.update(1)
84
+
85
+ def __download_dataset(self):
86
+ try:
87
+ # Send a request to the dataset URL with allow_redirects=False to handle redirection
88
+ response = requests.get(
89
+ self.__dataset_url,
90
+ stream=True,
91
+ allow_redirects=False,
92
+ )
93
+
94
+ # Check if the request was successful (status code 200)
95
+ if response.status_code == 200:
96
+ total_size = int(response.headers.get("content-length", 0)) or None
97
+ filename = self.__extract_filename(response)
98
+
99
+ with tqdm(
100
+ total=total_size,
101
+ unit="B",
102
+ unit_scale=True,
103
+ desc="Downloading Empirical1000 dataset",
104
+ dynamic_ncols=True,
105
+ ) as pbar:
106
+ with open(
107
+ os.path.join(self.cache_folder_path, filename),
108
+ "wb",
109
+ ) as out_file:
110
+ shutil.copyfileobj(response.raw, out_file)
111
+ pbar.update(os.path.getsize(out_file.name))
112
+
113
+ zip_file_path = os.path.join(self.cache_folder_path, filename)
114
+ with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
115
+ zip_ref.extractall(self.__empirical1000_folder_path)
116
+
117
+ # A sanitizing routine that deletes non-relevant files.
118
+ os.remove(zip_file_path)
119
+ extracted_files = os.listdir(self.__empirical1000_folder_path)
120
+ timeseries_files = [
121
+ file for file in extracted_files if "timeseries-info" in file.lower() or "inp" in file.lower()
122
+ ]
123
+
124
+ for file in extracted_files:
125
+ if file not in timeseries_files:
126
+ os.remove(os.path.join(self.__empirical1000_folder_path, file))
127
+
128
+ print(f"Dataset downloaded and saved to: {self.cache_folder_path}")
129
+ else:
130
+ print(
131
+ f"Failed to download dataset. Status code: {response.status_code}",
132
+ )
133
+
134
+ except Exception as e:
135
+ print(f"An error occurred: {e}")
136
+
137
+ @staticmethod
138
+ def __extract_filename(response):
139
+ # Try to extract the filename from the Content-Disposition header.
140
+ # If the header is not present, extract the filename from the URL
141
+ content_disposition = response.headers.get("Content-Disposition")
142
+ if content_disposition and "filename=" in content_disposition:
143
+ filename = content_disposition.split("filename=")[1].strip("\";'")
144
+ else:
145
+ filename = os.path.basename(urlparse(response.url).path)
146
+
147
+ return filename
148
+
149
+ def get_by_len(self, l):
150
+ query = np.nonzero(self.metadata["Length"] == l)[0]
151
+ filtered_data = {key: self.raw[key] for key in query if key in self.raw}
152
+
153
+ return filtered_data
154
+
155
+
156
+ class EmpiricalTimeSeries:
157
+ """The object representing a time series from the Empirical1000 dataset.
158
+
159
+ Attributes:
160
+ name (str): The name of the time series.
161
+ sig (array-like): The time series data.
162
+ len (int): The length of the time series.
163
+
164
+ Methods:
165
+ __init__(self, name, sig):
166
+ Initializes a new EmpiricalTimeSeries object.
167
+ """
168
+
169
+ def __init__(self, name, sig):
170
+ """Initializes a new EmpiricalTimeSeries object.
171
+
172
+ Parameters:
173
+ name (str): The name or identifier of the time series.
174
+ sig (list or array-like): The time series data.
175
+ """
176
+ self.name = name
177
+ self.sig = sig
178
+ self.len = len(sig)
179
+
180
+
181
+ class FeaturizedEmpiricalTimeSeries(EmpiricalTimeSeries):
182
+ def __init__(self, empirical_time_series):
183
+ super().__init__(empirical_time_series.name, empirical_time_series.sig)
184
+ self.example_feature = self.get_feature()
185
+
186
+ @staticmethod
187
+ def get_feature(self):
188
+ return -1
@@ -0,0 +1,46 @@
1
+ import timeit
2
+
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+ from mpl_toolkits.axes_grid1.inset_locator import inset_axes
6
+ from statsmodels.tsa.stattools import acf
7
+
8
+ use_fft = [False, True]
9
+ signal_lengths = np.hstack((np.arange(15, 515, 15), np.arange(500, 5500, 500)))
10
+ results = [[], []]
11
+
12
+ for i, use_fft in enumerate([False, True]):
13
+ for length in signal_lengths:
14
+ signal = np.random.randn(length)
15
+
16
+ def measure_acf(signal, use_fft):
17
+ return acf(signal, adjusted=True, fft=use_fft, nlags=int(len(signal) / 4))[1:]
18
+
19
+ cpu_time = timeit.timeit("measure_acf()", globals=globals(), number=10)
20
+ mean_cpu_time = cpu_time / 10 # Average time per execution
21
+
22
+ results[i].append(mean_cpu_time * 1000)
23
+ results = np.array(results)
24
+
25
+ fig, ax = plt.subplots(1, 1)
26
+ ax.plot(signal_lengths, results[0], "o-", label="full convolution")
27
+ ax.plot(signal_lengths, results[1], "o-", label="fft")
28
+ ax.set_ylabel("CPU time / ms")
29
+ ax.set_xlabel("Signal size / #")
30
+ ax.spines[["top", "right"]].set_visible(False)
31
+ ax.legend()
32
+
33
+ ax_inset = inset_axes(ax, width="30%", height="30%", loc=1) # loc=2 is for upper left
34
+ ax_inset.plot(signal_lengths, results[0], "o-", label="full convolution")
35
+ ax_inset.plot(signal_lengths, results[1], "o-", label="FFT")
36
+ ax_inset.set_xlim(0, 500)
37
+ ax_inset.set_ylim(0, 0.10)
38
+ ax_inset.yaxis.set_visible(False)
39
+ ax_inset.yaxis.set_ticks([])
40
+ ax_inset.axvline(
41
+ x=signal_lengths[np.where(results[0] > results[1])[0][0]],
42
+ color="r",
43
+ linestyle="--",
44
+ )
45
+
46
+ plt.show(block=False)
@@ -0,0 +1,151 @@
1
+ import glob
2
+ import json
3
+ import os
4
+ from pathlib import Path
5
+
6
+ # import tsfel
7
+ import pandas as pd
8
+
9
+ from tsfel.feature_extraction.calc_features import dataset_features_extractor, time_series_features_extractor
10
+ from tsfel.feature_extraction.features_settings import get_features_by_domain, get_features_by_tag
11
+ from tsfel.utils.add_personal_features import add_feature_json
12
+ from tsfel.utils.signal_processing import merge_time_series, signal_window_splitter
13
+
14
+
15
+ # Example of user preprocess sensor data
16
+ def pre_process(sensor_data):
17
+ if "Accelerometer" in sensor_data:
18
+ sensor_data["Accelerometer"].iloc[:, 1] = sensor_data["Accelerometer"].iloc[:, 1] * 10
19
+ return sensor_data
20
+
21
+
22
+ # DATASET DIR
23
+ main_directory = os.path.join("tests", "tests_tools", "test_dataset", "")
24
+
25
+ # JSON DIR
26
+ # tsfel_path_json = tsfel.__path__[0] + os.sep + "feature_extraction" + os.sep + "features.json"
27
+ personal_path_json = os.path.join("tests", "tests_tools", "test_features.json")
28
+ personal_features_path = os.path.join(
29
+ "tests",
30
+ "tests_tools",
31
+ "test_personal_features.py",
32
+ )
33
+
34
+ # DEFAULT PARAM for testing
35
+ time_unit = 1e9 # seconds
36
+ resample_rate = 30 # resample sampling frequency
37
+ window_size = 100 # number of points
38
+ overlap = 0 # varies between 0 and 1
39
+ search_criteria = ["Accelerometer.txt", "Gyroscope.txt"]
40
+ output_directory = str(Path.home()) + os.sep + "Documents" + os.sep + "tsfel_output" + os.sep
41
+ sensor_data = {}
42
+ key = "Accelerometer"
43
+
44
+ folders = list(glob.glob(main_directory + "**/", recursive=True))
45
+ sensor_data[key] = pd.read_csv(folders[-1] + key + ".txt", header=None)
46
+
47
+
48
+ # Features Dictionary
49
+ # settings0 = json.load(open(tsfel_path_json))
50
+ settings2 = get_features_by_domain("statistical")
51
+ settings3 = get_features_by_domain("temporal")
52
+ settings4 = get_features_by_domain("spectral")
53
+ settings5 = get_features_by_domain("fractal")
54
+ settings6 = get_features_by_domain()
55
+ settings8 = get_features_by_tag("inertial")
56
+ settings10 = get_features_by_tag()
57
+
58
+ # Signal processing
59
+ data_new = merge_time_series(sensor_data, resample_rate, time_unit)
60
+ data_new = data_new[data_new.columns[:-1]]
61
+ windows = signal_window_splitter(data_new, window_size, overlap)
62
+
63
+ n_jobs = 1
64
+ # time_series_features_extractor
65
+
66
+ # multi windows and multi axis
67
+ # input: list
68
+ features0 = time_series_features_extractor(
69
+ settings6,
70
+ windows,
71
+ fs=resample_rate,
72
+ n_jobs=n_jobs,
73
+ )
74
+
75
+ # multiple windows and single axis
76
+ # input: np.array
77
+ features1 = time_series_features_extractor(
78
+ settings6,
79
+ data_new.values[:, 0],
80
+ fs=resample_rate,
81
+ n_jobs=n_jobs,
82
+ window_size=window_size,
83
+ overlap=overlap,
84
+ )
85
+ # input: pd.series
86
+ features2 = time_series_features_extractor(
87
+ settings6,
88
+ data_new.iloc[:, 0],
89
+ fs=resample_rate,
90
+ n_jobs=n_jobs,
91
+ window_size=window_size,
92
+ overlap=overlap,
93
+ )
94
+
95
+ # single window and multi axis
96
+ # input: pd.DataFrame
97
+ features3 = time_series_features_extractor(
98
+ settings6,
99
+ data_new,
100
+ fs=resample_rate,
101
+ n_jobs=n_jobs,
102
+ )
103
+ # input: np.array
104
+ features4 = time_series_features_extractor(
105
+ settings4,
106
+ data_new.values,
107
+ fs=resample_rate,
108
+ n_jobs=n_jobs,
109
+ )
110
+
111
+ # single window and single axis
112
+ # input: pd.Series
113
+ features5 = time_series_features_extractor(
114
+ settings2,
115
+ data_new.iloc[:, 0],
116
+ fs=resample_rate,
117
+ n_jobs=n_jobs,
118
+ )
119
+ # input: np.array
120
+ features6 = time_series_features_extractor(
121
+ settings5,
122
+ data_new.values[:, 0],
123
+ fs=resample_rate,
124
+ n_jobs=n_jobs,
125
+ )
126
+
127
+ # personal features
128
+ settings1 = json.load(open(personal_path_json))
129
+ add_feature_json(personal_features_path, personal_path_json)
130
+ features7 = time_series_features_extractor(
131
+ settings1,
132
+ data_new.values[:, 0],
133
+ fs=resample_rate,
134
+ n_jobs=n_jobs,
135
+ features_path=personal_features_path,
136
+ )
137
+
138
+
139
+ # Dataset features extractor
140
+ data = dataset_features_extractor(
141
+ main_directory,
142
+ settings4,
143
+ search_criteria=search_criteria,
144
+ time_unit=time_unit,
145
+ resample_rate=resample_rate,
146
+ window_size=window_size,
147
+ overlap=overlap,
148
+ pre_process=pre_process,
149
+ output_directory=output_directory,
150
+ )
151
+ print("-----------------------------------OK-----------------------------------")