diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index d34cd40a..695cdaa4 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -35,6 +35,6 @@ jobs: run: poetry install --all-extras - name: Run benchmarks - uses: CodSpeedHQ/action@v1 + uses: CodSpeedHQ/action@v2 with: run: "poetry run pytest tests/benchmarks/ --codspeed" diff --git a/Makefile b/Makefile index 10bbfd2e..714fbfd2 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ clean: rm -rf `find . -name __pycache__` rm -rf .cache rm -rf .pytest_cache + rm -rf .benchmarks rm -rf *.egg-info rm -rf .ruff_cache rm -f .coverage diff --git a/examples/README.md b/examples/README.md index c063ae3c..b9f8c38b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,8 +5,7 @@ This folder contains several examples, indicating (1.) the cross-domain applicab ## 0. general examples **Paper example**: [tsflex_paper.ipynb](https://github.com/predict-idlab/tsflex/blob/main/examples/tsflex_paper.ipynb) -Example used in the tsflex paper. The example elaborates shows how tsflex can be applied for processing & feature extraction on multivariate (and even irregularly sampled) time series data. - +Example used in the [tsflex paper](https://www.sciencedirect.com/science/article/pii/S2352711021001904). The example shows how tsflex can be applied for processing & feature extraction on multivariate (and even irregularly sampled) time series data. **Verbose example**: [verbose_example.ipynb](https://github.com/predict-idlab/tsflex/blob/main/examples/verbose_example.ipynb) Example that elaborates in great detail (very verbose) the various functionalities of tsflex. In addition to processing & feature extraction, this example shows how to use the logging functionality, serialization, and chunking. diff --git a/examples/data/grouped_data.parquet b/examples/data/grouped_data.parquet new file mode 100644 index 00000000..a187d048 Binary files /dev/null and b/examples/data/grouped_data.parquet differ diff --git a/examples/verbose_example.ipynb b/examples/verbose_example.ipynb index 643739f7..0acc0528 100644 --- a/examples/verbose_example.ipynb +++ b/examples/verbose_example.ipynb @@ -13,7 +13,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -69,7 +68,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -79,7 +77,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -103,7 +100,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -111,7 +107,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -121,7 +116,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -225,7 +219,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -233,7 +226,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -246,7 +238,16 @@ "cell_type": "code", "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/snil/Documents/tsflex/tsflex/utils/logging.py:81: RuntimeWarning: Logging file (example_processing_logs.log) already exists. This file will be overwritten!\n", + " warnings.warn(\n" + ] + } + ], "source": [ "_ = series_pipe.process([df_gsr, df_acc, df_tmp], logging_file_path=\"example_processing_logs.log\")" ] @@ -288,48 +289,48 @@ " \n", " \n", " 0\n", - " 2023-05-05 12:16:53.596\n", + " 2023-08-09 11:27:14.106\n", " clip_quantiles\n", " (TMP,)\n", " TMP\n", - " 0 days 00:00:00.002578633\n", - " 4.73\n", + " 0 days 00:00:00.001249584\n", + " 6.05\n", " \n", " \n", " 1\n", - " 2023-05-05 12:16:53.597\n", + " 2023-08-09 11:27:14.107\n", " savgol_filter\n", " (EDA,)\n", " EDA\n", - " 0 days 00:00:00.000956786\n", - " 1.76\n", + " 0 days 00:00:00.000535822\n", + " 2.59\n", " \n", " \n", " 2\n", - " 2023-05-05 12:16:53.628\n", + " 2023-08-09 11:27:14.118\n", " savgol_filter\n", " (ACC_x,), (ACC_y,), (ACC_z,)\n", " ACC_x, ACC_y, ACC_z\n", - " 0 days 00:00:00.030402122\n", - " 55.82\n", + " 0 days 00:00:00.011542282\n", + " 55.89\n", " \n", " \n", " 3\n", - " 2023-05-05 12:16:53.635\n", + " 2023-08-09 11:27:14.122\n", " smv\n", " (ACC_x, ACC_y, ACC_z)\n", " ACC_SMV\n", - " 0 days 00:00:00.006881422\n", - " 12.63\n", + " 0 days 00:00:00.003439890\n", + " 16.66\n", " \n", " \n", " 4\n", - " 2023-05-05 12:16:53.649\n", + " 2023-08-09 11:27:14.126\n", " clip_quantiles\n", " (ACC_SMV,)\n", " ACC_SMV\n", - " 0 days 00:00:00.013646172\n", - " 25.05\n", + " 0 days 00:00:00.003885668\n", + " 18.81\n", " \n", " \n", "\n", @@ -337,18 +338,18 @@ ], "text/plain": [ " log_time function series_names \\\n", - "0 2023-05-05 12:16:53.596 clip_quantiles (TMP,) \n", - "1 2023-05-05 12:16:53.597 savgol_filter (EDA,) \n", - "2 2023-05-05 12:16:53.628 savgol_filter (ACC_x,), (ACC_y,), (ACC_z,) \n", - "3 2023-05-05 12:16:53.635 smv (ACC_x, ACC_y, ACC_z) \n", - "4 2023-05-05 12:16:53.649 clip_quantiles (ACC_SMV,) \n", + "0 2023-08-09 11:27:14.106 clip_quantiles (TMP,) \n", + "1 2023-08-09 11:27:14.107 savgol_filter (EDA,) \n", + "2 2023-08-09 11:27:14.118 savgol_filter (ACC_x,), (ACC_y,), (ACC_z,) \n", + "3 2023-08-09 11:27:14.122 smv (ACC_x, ACC_y, ACC_z) \n", + "4 2023-08-09 11:27:14.126 clip_quantiles (ACC_SMV,) \n", "\n", " output_names duration duration % \n", - "0 TMP 0 days 00:00:00.002578633 4.73 \n", - "1 EDA 0 days 00:00:00.000956786 1.76 \n", - "2 ACC_x, ACC_y, ACC_z 0 days 00:00:00.030402122 55.82 \n", - "3 ACC_SMV 0 days 00:00:00.006881422 12.63 \n", - "4 ACC_SMV 0 days 00:00:00.013646172 25.05 " + "0 TMP 0 days 00:00:00.001249584 6.05 \n", + "1 EDA 0 days 00:00:00.000535822 2.59 \n", + "2 ACC_x, ACC_y, ACC_z 0 days 00:00:00.011542282 55.89 \n", + "3 ACC_SMV 0 days 00:00:00.003439890 16.66 \n", + "4 ACC_SMV 0 days 00:00:00.003885668 18.81 " ] }, "execution_count": 8, @@ -361,7 +362,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -369,7 +369,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -382,16 +381,7 @@ "cell_type": "code", "execution_count": 9, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jeroen/.cache/pypoetry/virtualenvs/tsflex-5Y4iXlk8-py3.10/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], + "outputs": [], "source": [ "try: \n", " from tsflex.features import FeatureCollection, FuncWrapper\n", @@ -406,7 +396,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -416,7 +405,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -515,7 +503,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -525,7 +512,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -537,12 +523,12 @@ "\n", "## Featuredescriptor constructor args:\n", "\n", - "| attribute \t| type \t| info \t|\n", - "|-----------:\t|:-------------------------------------:\t|------------------------------------------------------------------------------------------------------------------\t|\n", - "| `function` \t| Union[Callable,
NumpyFuncWrapper] \t| The `function` that calculates this feature. \t|\n", - "| `key` \t| Tuple[str, ...] \t| The signal key; i.e., the `pd.DataFrame` column name or
`pd.Series` name on which the function will operate. \t|\n", - "| `window` \t| Union[str, pd.timedelta] \t| The window size on which this feature will be applied,
expressed in a **time-based** manner. \t|\n", - "| `stride` \t| Union[str, pd.timedelta] \t| The stride of the window rolling process, also as
expressed in a **time-based** manner|\n", + "| attribute | type | info |\n", + "| --------: | :--: | ---- |\n", + "| `function` | Union[Callable,
NumpyFuncWrapper] | The `function` that calculates this feature. |\n", + "| `key` | Tuple[str, ...] | The signal key; i.e., the `pd.DataFrame` column name or
`pd.Series` name on which the function will operate. |\n", + "| `window` | Union[str, pd.timedelta] | The window size on which this feature will be applied,
expressed in a **time-based** manner. |\n", + "| `stride` | Union[str, pd.timedelta] | The stride of the window rolling process, also as
expressed in a **time-based** manner |\n", "\n", "\n", "\n", @@ -551,7 +537,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -561,7 +546,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -574,7 +558,6 @@ "cell_type": "code", "execution_count": 11, "metadata": { - "collapsed": false, "pycharm": { "name": "#%%\n" } @@ -610,12 +593,12 @@ " \n", " \n", " \n", - " 2017-06-13 15:41:21+02:00\n", - " 34.369999\n", + " 2017-06-13 15:14:15.500000+02:00\n", + " 34.450001\n", " \n", " \n", - " 2017-06-13 15:00:18.750000+02:00\n", - " 35.500000\n", + " 2017-06-13 15:37:18.750000+02:00\n", + " 34.970001\n", " \n", " \n", "\n", @@ -624,8 +607,8 @@ "text/plain": [ " TMP\n", "timestamp \n", - "2017-06-13 15:41:21+02:00 34.369999\n", - "2017-06-13 15:00:18.750000+02:00 35.500000" + "2017-06-13 15:14:15.500000+02:00 34.450001\n", + "2017-06-13 15:37:18.750000+02:00 34.970001" ] }, "execution_count": 11, @@ -638,7 +621,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -753,36 +735,36 @@ " \n", " \n", " \n", - " 2017-06-13 15:19:13+02:00\n", - " 35.029999\n", - " 34.930000\n", - " 8394.200195\n", - " -0.810092\n", - " 34.975834\n", - " 34.950001\n", - " 34.990002\n", - " 34.990002\n", - " 34.975845\n", - " -0.058798\n", - " -0.000345\n", - " 0.028884\n", - " 0.000834\n", + " 2017-06-13 16:10:43+02:00\n", + " 30.670000\n", + " 30.51\n", + " 7341.119629\n", + " -0.190920\n", + " 30.587999\n", + " 30.570000\n", + " 30.590000\n", + " 30.610001\n", + " 30.588018\n", + " 0.184326\n", + " 0.000359\n", + " 0.032599\n", + " 0.001063\n", " \n", " \n", - " 2017-06-13 16:17:43+02:00\n", - " 30.250000\n", - " 29.809999\n", - " 7206.559570\n", - " -1.437857\n", - " 30.027332\n", - " 29.889999\n", - " 30.030001\n", - " 30.170000\n", - " 30.027679\n", - " 0.071025\n", - " 0.001219\n", - " 0.144382\n", - " 0.020846\n", + " 2017-06-13 15:14:43+02:00\n", + " 34.610001\n", + " 34.43\n", + " 8282.679688\n", + " -1.381112\n", + " 34.511166\n", + " 34.450001\n", + " 34.490002\n", + " 34.570000\n", + " 34.511223\n", + " 0.391330\n", + " -0.000798\n", + " 0.061267\n", + " 0.003754\n", " \n", " \n", "\n", @@ -791,33 +773,33 @@ "text/plain": [ " TMP__amax__w=1m TMP__amin__w=1m TMP__area__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 35.029999 34.930000 8394.200195 \n", - "2017-06-13 16:17:43+02:00 30.250000 29.809999 7206.559570 \n", + "2017-06-13 16:10:43+02:00 30.670000 30.51 7341.119629 \n", + "2017-06-13 15:14:43+02:00 34.610001 34.43 8282.679688 \n", "\n", " TMP__kurtosis__w=1m TMP__mean__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 -0.810092 34.975834 \n", - "2017-06-13 16:17:43+02:00 -1.437857 30.027332 \n", + "2017-06-13 16:10:43+02:00 -0.190920 30.587999 \n", + "2017-06-13 15:14:43+02:00 -1.381112 34.511166 \n", "\n", " TMP__quantile_0.25__w=1m TMP__quantile_0.5__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 34.950001 34.990002 \n", - "2017-06-13 16:17:43+02:00 29.889999 30.030001 \n", + "2017-06-13 16:10:43+02:00 30.570000 30.590000 \n", + "2017-06-13 15:14:43+02:00 34.450001 34.490002 \n", "\n", " TMP__quantile_0.75__w=1m TMP__rms__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 34.990002 34.975845 \n", - "2017-06-13 16:17:43+02:00 30.170000 30.027679 \n", + "2017-06-13 16:10:43+02:00 30.610001 30.588018 \n", + "2017-06-13 15:14:43+02:00 34.570000 34.511223 \n", "\n", " TMP__skew__w=1m TMP__slope__w=1m TMP__std__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 -0.058798 -0.000345 0.028884 \n", - "2017-06-13 16:17:43+02:00 0.071025 0.001219 0.144382 \n", + "2017-06-13 16:10:43+02:00 0.184326 0.000359 0.032599 \n", + "2017-06-13 15:14:43+02:00 0.391330 -0.000798 0.061267 \n", "\n", " TMP__var__w=1m \n", "timestamp \n", - "2017-06-13 15:19:13+02:00 0.000834 \n", - "2017-06-13 16:17:43+02:00 0.020846 " + "2017-06-13 16:10:43+02:00 0.001063 \n", + "2017-06-13 15:14:43+02:00 0.003754 " ] }, "execution_count": 13, @@ -838,7 +820,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -846,7 +827,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -854,7 +834,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -871,24 +850,24 @@ "output_type": "stream", "text": [ "EDA: (\n", - "\twin: 1h : [\n", + "\twin: 30s : [\n", "\t\tFeatureDescriptor - func: FuncWrapper(mean, ['mean'], {}) stride: ['30s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(skew, ['skew'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(kurtosis, ['kurtosis'], {}) stride: ['30s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(var, ['var'], {}) stride: ['30s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(slope, ['slope'], {}) stride: ['15s'],\n", + "\t]\n", + "\twin: 1m30s : [\n", + "\t\tFeatureDescriptor - func: FuncWrapper(std, ['std'], {}) stride: ['30s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(kurtosis, ['kurtosis'], {}) stride: ['15s'],\n", "\t\tFeatureDescriptor - func: FuncWrapper(sum, ['area'], {}) stride: ['30s'],\n", "\t]\n", - "\twin: 30s : [\n", - "\t\tFeatureDescriptor - func: FuncWrapper(std, ['std'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(var, ['var'], {}) stride: ['15s'],\n", + "\twin: 1h : [\n", + "\t\tFeatureDescriptor - func: FuncWrapper(amax, ['amax'], {}) stride: ['30s'],\n", "\t\tFeatureDescriptor - func: FuncWrapper(quantile, ['quantile_0.25', 'quantile_0.5', 'quantile_0.75'], {'q': [0.25, 0.5, 0.75]}) stride: ['30s'],\n", "\t]\n", - "\twin: 1m30s : [\n", - "\t\tFeatureDescriptor - func: FuncWrapper(amax, ['amax'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(amin, ['amin'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(, ['rms'], {}) stride: ['30s'],\n", - "\t]\n", "\twin: 2m : [\n", - "\t\tFeatureDescriptor - func: FuncWrapper(slope, ['slope'], {}) stride: ['15s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(amin, ['amin'], {}) stride: ['15s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(skew, ['skew'], {}) stride: ['15s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(, ['rms'], {}) stride: ['15s'],\n", "\t]\n", ")\n", "\n", @@ -916,18 +895,18 @@ " \n", " \n", " \n", - " EDA__amax__w=1m30s\n", - " EDA__amin__w=1m30s\n", - " EDA__area__w=1h\n", - " EDA__kurtosis__w=1h\n", - " EDA__mean__w=1h\n", - " EDA__quantile_0.25__w=30s\n", - " EDA__quantile_0.5__w=30s\n", - " EDA__quantile_0.75__w=30s\n", - " EDA__rms__w=1m30s\n", - " EDA__skew__w=1h\n", - " EDA__slope__w=2m\n", - " EDA__std__w=30s\n", + " EDA__amax__w=1h\n", + " EDA__amin__w=2m\n", + " EDA__area__w=1m30s\n", + " EDA__kurtosis__w=1m30s\n", + " EDA__mean__w=30s\n", + " EDA__quantile_0.25__w=1h\n", + " EDA__quantile_0.5__w=1h\n", + " EDA__quantile_0.75__w=1h\n", + " EDA__rms__w=2m\n", + " EDA__skew__w=2m\n", + " EDA__slope__w=30s\n", + " EDA__std__w=1m30s\n", " EDA__var__w=30s\n", " \n", " \n", @@ -949,76 +928,71 @@ " \n", " \n", " \n", - " 2017-06-13 16:09:43+02:00\n", - " 1.207757\n", - " 1.139973\n", - " 30162.832031\n", - " -0.272705\n", - " 2.094641\n", - " 1.157878\n", - " 1.160436\n", - " 1.166831\n", - " 1.168666\n", - " 0.94309\n", - " -0.000009\n", - " 0.005837\n", - " 0.000034\n", - " \n", - " \n", - " 2017-06-13 15:02:58+02:00\n", - " 0.780491\n", - " 0.703754\n", + " 2017-06-13 16:10:58+02:00\n", " NaN\n", + " 1.110558\n", " NaN\n", + " 1.415249\n", " NaN\n", " NaN\n", " NaN\n", " NaN\n", + " 1.146106\n", + " 0.161287\n", + " -0.000208\n", " NaN\n", " NaN\n", - " -0.000113\n", - " 0.005096\n", - " 0.000026\n", + " \n", + " \n", + " 2017-06-13 16:26:13+02:00\n", + " 4.738588\n", + " 0.753633\n", + " 350.18045\n", + " 1.489872\n", + " 0.896758\n", + " 1.053005\n", + " 1.526214\n", + " 2.536808\n", + " 0.979037\n", + " -0.808600\n", + " -0.000461\n", + " 0.084573\n", + " 0.010754\n", " \n", " \n", "\n", "" ], "text/plain": [ - " EDA__amax__w=1m30s EDA__amin__w=1m30s \\\n", - "timestamp \n", - "2017-06-13 16:09:43+02:00 1.207757 1.139973 \n", - "2017-06-13 15:02:58+02:00 0.780491 0.703754 \n", + " EDA__amax__w=1h EDA__amin__w=2m \\\n", + "timestamp \n", + "2017-06-13 16:10:58+02:00 NaN 1.110558 \n", + "2017-06-13 16:26:13+02:00 4.738588 0.753633 \n", "\n", - " EDA__area__w=1h EDA__kurtosis__w=1h \\\n", - "timestamp \n", - "2017-06-13 16:09:43+02:00 30162.832031 -0.272705 \n", - "2017-06-13 15:02:58+02:00 NaN NaN \n", - "\n", - " EDA__mean__w=1h EDA__quantile_0.25__w=30s \\\n", + " EDA__area__w=1m30s EDA__kurtosis__w=1m30s \\\n", "timestamp \n", - "2017-06-13 16:09:43+02:00 2.094641 1.157878 \n", - "2017-06-13 15:02:58+02:00 NaN NaN \n", + "2017-06-13 16:10:58+02:00 NaN 1.415249 \n", + "2017-06-13 16:26:13+02:00 350.18045 1.489872 \n", "\n", - " EDA__quantile_0.5__w=30s \\\n", - "timestamp \n", - "2017-06-13 16:09:43+02:00 1.160436 \n", - "2017-06-13 15:02:58+02:00 NaN \n", + " EDA__mean__w=30s EDA__quantile_0.25__w=1h \\\n", + "timestamp \n", + "2017-06-13 16:10:58+02:00 NaN NaN \n", + "2017-06-13 16:26:13+02:00 0.896758 1.053005 \n", "\n", - " EDA__quantile_0.75__w=30s EDA__rms__w=1m30s \\\n", - "timestamp \n", - "2017-06-13 16:09:43+02:00 1.166831 1.168666 \n", - "2017-06-13 15:02:58+02:00 NaN NaN \n", + " EDA__quantile_0.5__w=1h EDA__quantile_0.75__w=1h \\\n", + "timestamp \n", + "2017-06-13 16:10:58+02:00 NaN NaN \n", + "2017-06-13 16:26:13+02:00 1.526214 2.536808 \n", "\n", - " EDA__skew__w=1h EDA__slope__w=2m EDA__std__w=30s \\\n", + " EDA__rms__w=2m EDA__skew__w=2m EDA__slope__w=30s \\\n", "timestamp \n", - "2017-06-13 16:09:43+02:00 0.94309 -0.000009 0.005837 \n", - "2017-06-13 15:02:58+02:00 NaN -0.000113 0.005096 \n", + "2017-06-13 16:10:58+02:00 1.146106 0.161287 -0.000208 \n", + "2017-06-13 16:26:13+02:00 0.979037 -0.808600 -0.000461 \n", "\n", - " EDA__var__w=30s \n", - "timestamp \n", - "2017-06-13 16:09:43+02:00 0.000034 \n", - "2017-06-13 15:02:58+02:00 0.000026 " + " EDA__std__w=1m30s EDA__var__w=30s \n", + "timestamp \n", + "2017-06-13 16:10:58+02:00 NaN NaN \n", + "2017-06-13 16:26:13+02:00 0.084573 0.010754 " ] }, "execution_count": 14, @@ -1052,7 +1026,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1094,7 +1067,7 @@ " \n", " \n", " \n", - " EDA__area__w=1h\n", + " EDA__area__w=1m30s\n", " \n", " \n", " timestamp\n", @@ -1103,27 +1076,27 @@ " \n", " \n", " \n", - " 2017-06-13 15:26:43+02:00\n", - " 15623.870117\n", + " 2017-06-13 15:14:43+02:00\n", + " 596.880798\n", " \n", " \n", - " 2017-06-13 16:18:13+02:00\n", - " 28911.509766\n", + " 2017-06-13 15:40:43+02:00\n", + " 789.627686\n", " \n", " \n", - " 2017-06-13 16:19:43+02:00\n", - " 28819.720703\n", + " 2017-06-13 15:16:43+02:00\n", + " 518.155457\n", " \n", " \n", "\n", "" ], "text/plain": [ - " EDA__area__w=1h\n", - "timestamp \n", - "2017-06-13 15:26:43+02:00 15623.870117\n", - "2017-06-13 16:18:13+02:00 28911.509766\n", - "2017-06-13 16:19:43+02:00 28819.720703" + " EDA__area__w=1m30s\n", + "timestamp \n", + "2017-06-13 15:14:43+02:00 596.880798\n", + "2017-06-13 15:40:43+02:00 789.627686\n", + "2017-06-13 15:16:43+02:00 518.155457" ] }, "execution_count": 15, @@ -1138,7 +1111,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -1151,6 +1123,7 @@ "cell_type": "code", "execution_count": 16, "metadata": { + "scrolled": true, "tags": [] }, "outputs": [ @@ -1159,24 +1132,24 @@ "output_type": "stream", "text": [ "EDA: (\n", - "\twin: 1h : [\n", + "\twin: 30s : [\n", "\t\tFeatureDescriptor - func: FuncWrapper(mean, ['mean'], {}) stride: ['30s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(skew, ['skew'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(kurtosis, ['kurtosis'], {}) stride: ['30s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(var, ['var'], {}) stride: ['30s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(slope, ['slope'], {}) stride: ['15s'],\n", + "\t]\n", + "\twin: 1m30s : [\n", + "\t\tFeatureDescriptor - func: FuncWrapper(std, ['std'], {}) stride: ['30s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(kurtosis, ['kurtosis'], {}) stride: ['15s'],\n", "\t\tFeatureDescriptor - func: FuncWrapper(sum, ['area'], {}) stride: ['30s'],\n", "\t]\n", - "\twin: 30s : [\n", - "\t\tFeatureDescriptor - func: FuncWrapper(std, ['std'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(var, ['var'], {}) stride: ['15s'],\n", + "\twin: 1h : [\n", + "\t\tFeatureDescriptor - func: FuncWrapper(amax, ['amax'], {}) stride: ['30s'],\n", "\t\tFeatureDescriptor - func: FuncWrapper(quantile, ['quantile_0.25', 'quantile_0.5', 'quantile_0.75'], {'q': [0.25, 0.5, 0.75]}) stride: ['30s'],\n", "\t]\n", - "\twin: 1m30s : [\n", - "\t\tFeatureDescriptor - func: FuncWrapper(amax, ['amax'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(amin, ['amin'], {}) stride: ['15s'],\n", - "\t\tFeatureDescriptor - func: FuncWrapper(, ['rms'], {}) stride: ['30s'],\n", - "\t]\n", "\twin: 2m : [\n", - "\t\tFeatureDescriptor - func: FuncWrapper(slope, ['slope'], {}) stride: ['15s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(amin, ['amin'], {}) stride: ['15s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(skew, ['skew'], {}) stride: ['15s'],\n", + "\t\tFeatureDescriptor - func: FuncWrapper(, ['rms'], {}) stride: ['15s'],\n", "\t]\n", ")\n", "TMP: (\n", @@ -1219,16 +1192,16 @@ " \n", " \n", " \n", - " EDA__amax__w=1m30s\n", - " EDA__amin__w=1m30s\n", - " EDA__area__w=1h\n", - " EDA__kurtosis__w=1h\n", - " EDA__mean__w=1h\n", - " EDA__quantile_0.25__w=30s\n", - " EDA__quantile_0.5__w=30s\n", - " EDA__quantile_0.75__w=30s\n", - " EDA__rms__w=1m30s\n", - " EDA__skew__w=1h\n", + " EDA__amax__w=1h\n", + " EDA__amin__w=2m\n", + " EDA__area__w=1m30s\n", + " EDA__kurtosis__w=1m30s\n", + " EDA__mean__w=30s\n", + " EDA__quantile_0.25__w=1h\n", + " EDA__quantile_0.5__w=1h\n", + " EDA__quantile_0.75__w=1h\n", + " EDA__rms__w=2m\n", + " EDA__skew__w=2m\n", " ...\n", " TMP__kurtosis__w=1m\n", " TMP__mean__w=1m\n", @@ -1268,52 +1241,52 @@ " \n", " \n", " \n", - " 2017-06-13 15:19:13+02:00\n", - " 1.272983\n", - " 1.141252\n", + " 2017-06-13 15:26:58+02:00\n", + " NaN\n", + " 1.722092\n", + " NaN\n", + " -0.796609\n", " NaN\n", " NaN\n", " NaN\n", - " 1.150205\n", - " 1.156600\n", - " 1.164273\n", - " 1.191974\n", " NaN\n", + " 1.949415\n", + " 0.345014\n", " ...\n", - " -0.810092\n", - " 34.975834\n", - " 34.950001\n", - " 34.990002\n", - " 34.990002\n", - " 34.975845\n", - " -0.058798\n", - " -0.000345\n", - " 0.028884\n", - " 0.000834\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", - " 2017-06-13 15:29:43+02:00\n", - " 1.610625\n", - " 1.311352\n", - " 16156.117188\n", - " -0.311375\n", - " 1.121953\n", - " 1.327978\n", - " 1.352278\n", - " 1.368264\n", - " 1.439992\n", - " 0.933501\n", + " 2017-06-13 15:00:58+02:00\n", + " NaN\n", + " 0.726775\n", + " NaN\n", + " 0.724335\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " 0.751184\n", + " 0.649367\n", " ...\n", - " -0.514506\n", - " 33.743000\n", - " 33.730000\n", - " 33.740000\n", - " 33.750000\n", - " 33.743008\n", - " 0.442661\n", - " 0.000050\n", - " 0.022753\n", - " 0.000518\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", + " NaN\n", " \n", " \n", "\n", @@ -1321,55 +1294,55 @@ "" ], "text/plain": [ - " EDA__amax__w=1m30s EDA__amin__w=1m30s \\\n", - "timestamp \n", - "2017-06-13 15:19:13+02:00 1.272983 1.141252 \n", - "2017-06-13 15:29:43+02:00 1.610625 1.311352 \n", + " EDA__amax__w=1h EDA__amin__w=2m \\\n", + "timestamp \n", + "2017-06-13 15:26:58+02:00 NaN 1.722092 \n", + "2017-06-13 15:00:58+02:00 NaN 0.726775 \n", "\n", - " EDA__area__w=1h EDA__kurtosis__w=1h \\\n", - "timestamp \n", - "2017-06-13 15:19:13+02:00 NaN NaN \n", - "2017-06-13 15:29:43+02:00 16156.117188 -0.311375 \n", - "\n", - " EDA__mean__w=1h EDA__quantile_0.25__w=30s \\\n", + " EDA__area__w=1m30s EDA__kurtosis__w=1m30s \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 NaN 1.150205 \n", - "2017-06-13 15:29:43+02:00 1.121953 1.327978 \n", + "2017-06-13 15:26:58+02:00 NaN -0.796609 \n", + "2017-06-13 15:00:58+02:00 NaN 0.724335 \n", "\n", - " EDA__quantile_0.5__w=30s \\\n", - "timestamp \n", - "2017-06-13 15:19:13+02:00 1.156600 \n", - "2017-06-13 15:29:43+02:00 1.352278 \n", + " EDA__mean__w=30s EDA__quantile_0.25__w=1h \\\n", + "timestamp \n", + "2017-06-13 15:26:58+02:00 NaN NaN \n", + "2017-06-13 15:00:58+02:00 NaN NaN \n", "\n", - " EDA__quantile_0.75__w=30s EDA__rms__w=1m30s \\\n", - "timestamp \n", - "2017-06-13 15:19:13+02:00 1.164273 1.191974 \n", - "2017-06-13 15:29:43+02:00 1.368264 1.439992 \n", + " EDA__quantile_0.5__w=1h EDA__quantile_0.75__w=1h \\\n", + "timestamp \n", + "2017-06-13 15:26:58+02:00 NaN NaN \n", + "2017-06-13 15:00:58+02:00 NaN NaN \n", "\n", - " EDA__skew__w=1h ... TMP__kurtosis__w=1m \\\n", - "timestamp ... \n", - "2017-06-13 15:19:13+02:00 NaN ... -0.810092 \n", - "2017-06-13 15:29:43+02:00 0.933501 ... -0.514506 \n", + " EDA__rms__w=2m EDA__skew__w=2m ... \\\n", + "timestamp ... \n", + "2017-06-13 15:26:58+02:00 1.949415 0.345014 ... \n", + "2017-06-13 15:00:58+02:00 0.751184 0.649367 ... \n", "\n", - " TMP__mean__w=1m TMP__quantile_0.25__w=1m \\\n", - "timestamp \n", - "2017-06-13 15:19:13+02:00 34.975834 34.950001 \n", - "2017-06-13 15:29:43+02:00 33.743000 33.730000 \n", + " TMP__kurtosis__w=1m TMP__mean__w=1m \\\n", + "timestamp \n", + "2017-06-13 15:26:58+02:00 NaN NaN \n", + "2017-06-13 15:00:58+02:00 NaN NaN \n", "\n", - " TMP__quantile_0.5__w=1m TMP__quantile_0.75__w=1m \\\n", + " TMP__quantile_0.25__w=1m TMP__quantile_0.5__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 34.990002 34.990002 \n", - "2017-06-13 15:29:43+02:00 33.740000 33.750000 \n", + "2017-06-13 15:26:58+02:00 NaN NaN \n", + "2017-06-13 15:00:58+02:00 NaN NaN \n", "\n", - " TMP__rms__w=1m TMP__skew__w=1m TMP__slope__w=1m \\\n", + " TMP__quantile_0.75__w=1m TMP__rms__w=1m \\\n", + "timestamp \n", + "2017-06-13 15:26:58+02:00 NaN NaN \n", + "2017-06-13 15:00:58+02:00 NaN NaN \n", + "\n", + " TMP__skew__w=1m TMP__slope__w=1m TMP__std__w=1m \\\n", "timestamp \n", - "2017-06-13 15:19:13+02:00 34.975845 -0.058798 -0.000345 \n", - "2017-06-13 15:29:43+02:00 33.743008 0.442661 0.000050 \n", + "2017-06-13 15:26:58+02:00 NaN NaN NaN \n", + "2017-06-13 15:00:58+02:00 NaN NaN NaN \n", "\n", - " TMP__std__w=1m TMP__var__w=1m \n", - "timestamp \n", - "2017-06-13 15:19:13+02:00 0.028884 0.000834 \n", - "2017-06-13 15:29:43+02:00 0.022753 0.000518 \n", + " TMP__var__w=1m \n", + "timestamp \n", + "2017-06-13 15:26:58+02:00 NaN \n", + "2017-06-13 15:00:58+02:00 NaN \n", "\n", "[2 rows x 26 columns]" ] @@ -1396,36 +1369,16 @@ ] }, { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Logging" - ] - }, - { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "The `FeatureCollection` can also log the duration of it's `Features`\n", - "\n", - "To do so, one needs to set the `logging_file_path` argumetn and then call the `get_feature_logs()` method with this corresponding path to see the output dataframe." + "## Grouping feature extraction" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, - "outputs": [], - "source": [ - "multimodal_feature_extraction.calculate(out_data, logging_file_path=\"example_feature_logs.log\");" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, "outputs": [ { "data": { @@ -1448,335 +1401,324 @@ " \n", " \n", " \n", - " log_time\n", - " function\n", - " series_names\n", - " window\n", - " stride\n", - " output_names\n", - " duration\n", - " duration %\n", + " store\n", + " product\n", + " number_sold\n", " \n", " \n", " \n", " \n", - " 0\n", - " 2023-05-05 12:17:13.103\n", - " sum\n", - " (EDA,)\n", - " 1h\n", - " (30s,)\n", - " EDA__area__w=1h\n", - " 0 days 00:00:00.003769857\n", - " 0.21\n", + " 2019-01-01\n", + " 0\n", + " 0\n", + " 845\n", " \n", " \n", - " 1\n", - " 2023-05-05 12:17:13.106\n", - " mean\n", - " (EDA,)\n", - " 1h\n", - " (30s,)\n", - " EDA__mean__w=1h\n", - " 0 days 00:00:00.006607244\n", - " 0.37\n", + " 2019-01-02\n", + " 3\n", + " 7\n", + " 357\n", " \n", " \n", - " 2\n", - " 2023-05-05 12:17:13.144\n", - " var\n", - " (EDA,)\n", - " 30s\n", - " (15s,)\n", - " EDA__var__w=30s\n", - " 0 days 00:00:00.032368199\n", - " 1.82\n", + " 2019-01-03\n", + " 6\n", + " 1\n", + " 904\n", " \n", " \n", - " 3\n", - " 2023-05-05 12:17:13.150\n", - " amax\n", - " (EDA,)\n", - " 1m30s\n", - " (15s,)\n", - " EDA__amax__w=1m30s\n", - " 0 days 00:00:00.010895506\n", - " 0.61\n", + " 2019-01-04\n", + " 3\n", + " 8\n", + " 273\n", " \n", " \n", - " 4\n", - " 2023-05-05 12:17:13.153\n", - " amin\n", - " (EDA,)\n", - " 1m30s\n", - " (15s,)\n", - " EDA__amin__w=1m30s\n", - " 0 days 00:00:00.007409622\n", - " 0.42\n", + " 2019-01-05\n", + " 3\n", + " 9\n", + " 326\n", " \n", " \n", - " 5\n", - " 2023-05-05 12:17:13.158\n", - " std\n", - " (EDA,)\n", - " 30s\n", - " (15s,)\n", - " EDA__std__w=30s\n", - " 0 days 00:00:00.058665547\n", - " 3.30\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", " \n", " \n", - " 6\n", - " 2023-05-05 12:17:13.160\n", - " <lambda>\n", - " (EDA,)\n", - " 1m30s\n", - " (30s,)\n", - " EDA__rms__w=1m30s\n", - " 0 days 00:00:00.014571842\n", - " 0.82\n", + " 2088-12-09\n", + " 4\n", + " 7\n", + " 982\n", " \n", " \n", - " 7\n", - " 2023-05-05 12:17:13.173\n", - " mean\n", - " (TMP,)\n", - " 1m\n", - " (30s,)\n", - " TMP__mean__w=1m\n", - " 0 days 00:00:00.009052561\n", - " 0.51\n", + " 2088-12-10\n", + " 4\n", + " 8\n", + " 967\n", " \n", " \n", - " 8\n", - " 2023-05-05 12:17:13.177\n", - " quantile\n", - " (EDA,)\n", - " 30s\n", - " (30s,)\n", - " EDA__quantile_0.25__w=30s, EDA__quantile_0.5__...\n", - " 0 days 00:00:00.044969643\n", - " 2.53\n", + " 2088-12-11\n", + " 4\n", + " 9\n", + " 1020\n", " \n", " \n", - " 9\n", - " 2023-05-05 12:17:13.186\n", - " amax\n", - " (TMP,)\n", - " 1m\n", - " (30s,)\n", - " TMP__amax__w=1m\n", - " 0 days 00:00:00.003757103\n", - " 0.21\n", + " 2088-12-12\n", + " 4\n", + " 3\n", + " 976\n", " \n", " \n", - " 10\n", - " 2023-05-05 12:17:13.188\n", - " amin\n", - " (TMP,)\n", - " 1m\n", - " (30s,)\n", - " TMP__amin__w=1m\n", - " 0 days 00:00:00.003863213\n", - " 0.22\n", + " 2088-12-13\n", + " 6\n", + " 9\n", + " 886\n", + " \n", + " \n", + "\n", + "

25550 rows × 3 columns

\n", + "" + ], + "text/plain": [ + " store product number_sold\n", + "2019-01-01 0 0 845\n", + "2019-01-02 3 7 357\n", + "2019-01-03 6 1 904\n", + "2019-01-04 3 8 273\n", + "2019-01-05 3 9 326\n", + "... ... ... ...\n", + "2088-12-09 4 7 982\n", + "2088-12-10 4 8 967\n", + "2088-12-11 4 9 1020\n", + "2088-12-12 4 3 976\n", + "2088-12-13 6 9 886\n", + "\n", + "[25550 rows x 3 columns]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Loading data\n", + "df_grp = pd.read_parquet(\"data/grouped_data.parquet\").set_index(\"Date\")\n", + "df_grp = df_grp.sort_index()\n", + "df_grp.set_index(\n", + " pd.date_range(\"2019-01-01\", periods=len(df_grp.index), freq=\"D\"), inplace=True\n", + ")\n", + "\n", + "\n", + "# !!! The data MUST datetime Indexed\n", + "assert isinstance(df_grp.index, pd.DatetimeIndex)\n", + "\n", + "df_grp" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", + " \n", + " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
number_sold__amin__w=manualnumber_sold__amax__w=manualnumber_sold__mean__w=manualnumber_sold__var__w=manualnumber_sold__std__w=manualstore__start__end
112023-05-05 12:17:13.201var(TMP,)1m(30s,)TMP__var__w=1m0 days 00:00:00.0211232531.190845845845.0000.0000000.00000002019-01-012019-01-01
122023-05-05 12:17:13.211std(TMP,)1m(30s,)TMP__std__w=1m0 days 00:00:00.0388828622.191357357357.0000.0000000.00000032019-01-022019-01-02
132023-05-05 12:17:13.239<lambda>(TMP,)1m(30s,)TMP__rms__w=1m0 days 00:00:00.0163983100.922904904904.0000.0000000.00000062019-01-032019-01-03
142023-05-05 12:17:13.262sum(TMP,)1m(30s,)TMP__area__w=1m0 days 00:00:00.0066541520.373273326299.500702.25000026.50000032019-01-042019-01-05
152023-05-05 12:17:13.279quantile(TMP,)1m(30s,)TMP__quantile_0.25__w=1m, TMP__quantile_0.5__w...0 days 00:00:00.0749888284.224871871871.0000.0000000.00000002019-01-062019-01-06
162023-05-05 12:17:13.296slope(TMP,)1m(30s,)TMP__slope__w=1m0 days 00:00:00.0817669144.60...........................
172023-05-05 12:17:13.331slope(EDA,)2m(15s,)EDA__slope__w=2m0 days 00:00:00.1746242229.8222117275360333.0001158.50000034.03674532088-11-282088-12-01
182023-05-05 12:17:13.355kurtosis(EDA,)1h(30s,)EDA__kurtosis__w=1h0 days 00:00:00.25611420414.402211896310841023.5003660.25000060.50000042088-12-022088-12-03
192023-05-05 12:17:13.457skew(TMP,)1m(30s,)TMP__skew__w=1m0 days 00:00:00.26695373315.0122119323323323.0000.0000000.00000032088-12-042088-12-04
202023-05-05 12:17:13.468skew(EDA,)1h(15s,)EDA__skew__w=1h0 days 00:00:00.36793277720.69221208871045982.8752350.85937548.48566242088-12-052088-12-12
212023-05-05 12:17:13.476kurtosis(TMP,)1m(30s,)TMP__kurtosis__w=1m0 days 00:00:00.27718257515.5822121886886886.0000.0000000.00000062088-12-132088-12-13
\n", + "

22122 rows × 8 columns

\n", "
" ], "text/plain": [ - " log_time function series_names window stride \\\n", - "0 2023-05-05 12:17:13.103 sum (EDA,) 1h (30s,) \n", - "1 2023-05-05 12:17:13.106 mean (EDA,) 1h (30s,) \n", - "2 2023-05-05 12:17:13.144 var (EDA,) 30s (15s,) \n", - "3 2023-05-05 12:17:13.150 amax (EDA,) 1m30s (15s,) \n", - "4 2023-05-05 12:17:13.153 amin (EDA,) 1m30s (15s,) \n", - "5 2023-05-05 12:17:13.158 std (EDA,) 30s (15s,) \n", - "6 2023-05-05 12:17:13.160 (EDA,) 1m30s (30s,) \n", - "7 2023-05-05 12:17:13.173 mean (TMP,) 1m (30s,) \n", - "8 2023-05-05 12:17:13.177 quantile (EDA,) 30s (30s,) \n", - "9 2023-05-05 12:17:13.186 amax (TMP,) 1m (30s,) \n", - "10 2023-05-05 12:17:13.188 amin (TMP,) 1m (30s,) \n", - "11 2023-05-05 12:17:13.201 var (TMP,) 1m (30s,) \n", - "12 2023-05-05 12:17:13.211 std (TMP,) 1m (30s,) \n", - "13 2023-05-05 12:17:13.239 (TMP,) 1m (30s,) \n", - "14 2023-05-05 12:17:13.262 sum (TMP,) 1m (30s,) \n", - "15 2023-05-05 12:17:13.279 quantile (TMP,) 1m (30s,) \n", - "16 2023-05-05 12:17:13.296 slope (TMP,) 1m (30s,) \n", - "17 2023-05-05 12:17:13.331 slope (EDA,) 2m (15s,) \n", - "18 2023-05-05 12:17:13.355 kurtosis (EDA,) 1h (30s,) \n", - "19 2023-05-05 12:17:13.457 skew (TMP,) 1m (30s,) \n", - "20 2023-05-05 12:17:13.468 skew (EDA,) 1h (15s,) \n", - "21 2023-05-05 12:17:13.476 kurtosis (TMP,) 1m (30s,) \n", + " number_sold__amin__w=manual number_sold__amax__w=manual \\\n", + "0 845 845 \n", + "1 357 357 \n", + "2 904 904 \n", + "3 273 326 \n", + "4 871 871 \n", + "... ... ... \n", + "22117 275 360 \n", + "22118 963 1084 \n", + "22119 323 323 \n", + "22120 887 1045 \n", + "22121 886 886 \n", + "\n", + " number_sold__mean__w=manual number_sold__var__w=manual \\\n", + "0 845.000 0.000000 \n", + "1 357.000 0.000000 \n", + "2 904.000 0.000000 \n", + "3 299.500 702.250000 \n", + "4 871.000 0.000000 \n", + "... ... ... \n", + "22117 333.000 1158.500000 \n", + "22118 1023.500 3660.250000 \n", + "22119 323.000 0.000000 \n", + "22120 982.875 2350.859375 \n", + "22121 886.000 0.000000 \n", "\n", - " output_names \\\n", - "0 EDA__area__w=1h \n", - "1 EDA__mean__w=1h \n", - "2 EDA__var__w=30s \n", - "3 EDA__amax__w=1m30s \n", - "4 EDA__amin__w=1m30s \n", - "5 EDA__std__w=30s \n", - "6 EDA__rms__w=1m30s \n", - "7 TMP__mean__w=1m \n", - "8 EDA__quantile_0.25__w=30s, EDA__quantile_0.5__... \n", - "9 TMP__amax__w=1m \n", - "10 TMP__amin__w=1m \n", - "11 TMP__var__w=1m \n", - "12 TMP__std__w=1m \n", - "13 TMP__rms__w=1m \n", - "14 TMP__area__w=1m \n", - "15 TMP__quantile_0.25__w=1m, TMP__quantile_0.5__w... \n", - "16 TMP__slope__w=1m \n", - "17 EDA__slope__w=2m \n", - "18 EDA__kurtosis__w=1h \n", - "19 TMP__skew__w=1m \n", - "20 EDA__skew__w=1h \n", - "21 TMP__kurtosis__w=1m \n", + " number_sold__std__w=manual store __start __end \n", + "0 0.000000 0 2019-01-01 2019-01-01 \n", + "1 0.000000 3 2019-01-02 2019-01-02 \n", + "2 0.000000 6 2019-01-03 2019-01-03 \n", + "3 26.500000 3 2019-01-04 2019-01-05 \n", + "4 0.000000 0 2019-01-06 2019-01-06 \n", + "... ... ... ... ... \n", + "22117 34.036745 3 2088-11-28 2088-12-01 \n", + "22118 60.500000 4 2088-12-02 2088-12-03 \n", + "22119 0.000000 3 2088-12-04 2088-12-04 \n", + "22120 48.485662 4 2088-12-05 2088-12-12 \n", + "22121 0.000000 6 2088-12-13 2088-12-13 \n", "\n", - " duration duration % \n", - "0 0 days 00:00:00.003769857 0.21 \n", - "1 0 days 00:00:00.006607244 0.37 \n", - "2 0 days 00:00:00.032368199 1.82 \n", - "3 0 days 00:00:00.010895506 0.61 \n", - "4 0 days 00:00:00.007409622 0.42 \n", - "5 0 days 00:00:00.058665547 3.30 \n", - "6 0 days 00:00:00.014571842 0.82 \n", - "7 0 days 00:00:00.009052561 0.51 \n", - "8 0 days 00:00:00.044969643 2.53 \n", - "9 0 days 00:00:00.003757103 0.21 \n", - "10 0 days 00:00:00.003863213 0.22 \n", - "11 0 days 00:00:00.021123253 1.19 \n", - "12 0 days 00:00:00.038882862 2.19 \n", - "13 0 days 00:00:00.016398310 0.92 \n", - "14 0 days 00:00:00.006654152 0.37 \n", - "15 0 days 00:00:00.074988828 4.22 \n", - "16 0 days 00:00:00.081766914 4.60 \n", - "17 0 days 00:00:00.174624222 9.82 \n", - "18 0 days 00:00:00.256114204 14.40 \n", - "19 0 days 00:00:00.266953733 15.01 \n", - "20 0 days 00:00:00.367932777 20.69 \n", - "21 0 days 00:00:00.277182575 15.58 " + "[22122 rows x 8 columns]" ] }, "execution_count": 18, @@ -1784,12 +1726,76 @@ "output_type": "execute_result" } ], + "source": [ + "# Grouping data\n", + "\n", + "grp_segment_funcs = [\n", + " np.mean,\n", + " np.std,\n", + " np.var,\n", + " np.max,\n", + " np.min\n", + "]\n", + "\n", + "grp_feat_extr = FeatureCollection(\n", + " feature_descriptors=[\n", + " MultipleFeatureDescriptors(\n", + " functions=grp_segment_funcs, # The list of functions we constructed earlier\n", + " series_names=[\"number_sold\"],\n", + " )\n", + " ]\n", + ")\n", + "\n", + "\n", + "grp_grouped_df = grp_feat_extr.calculate(df_grp, group_by=\"store\", return_df=True)\n", + "\n", + "grp_grouped_df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Logging" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `FeatureCollection` can also log the duration of it's `Features`\n", + "\n", + "To do so, one needs to set the `logging_file_path` argumetn and then call the `get_feature_logs()` method with this corresponding path to see the output dataframe." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/snil/Documents/tsflex/tsflex/utils/logging.py:81: RuntimeWarning: Logging file (example_feature_logs.log) already exists. This file will be overwritten!\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "multimodal_feature_extraction.calculate(out_data, logging_file_path=\"example_feature_logs.log\");" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "get_feature_logs(\"example_feature_logs.log\")" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1797,7 +1803,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -1808,7 +1813,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1816,7 +1821,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1825,7 +1829,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1837,7 +1841,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -1847,7 +1850,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1857,7 +1859,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1865,7 +1867,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": { "tags": [] @@ -1875,7 +1876,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -1885,7 +1885,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1899,24 +1899,9 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "e54a8fb2f11b45e5a792a4930b8f7405", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "interactive(children=(SelectMultiple(description='features', options=('EDA__amax__w=1m30s', 'EDA__amin__w=1m30…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "df_dict = {\"tmp\": df_tmp, \"gsr\": df_gsr}\n", "feat_widget = widgets.SelectMultiple(options=df_feat.columns)\n", @@ -1973,7 +1958,7 @@ "hash": "bb9f799bd6e477ee22986cb3017f2b22764a696a803a513374640b5de3a6fdad" }, "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1987,7 +1972,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.11.3" }, "metadata": { "interpreter": { diff --git a/poetry.lock b/poetry.lock index 29c9843f..ef948f9d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiofiles" version = "22.1.0" description = "File support for asyncio." -category = "dev" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -16,7 +15,6 @@ files = [ name = "aiosqlite" version = "0.19.0" description = "asyncio bridge to the standard sqlite3 module" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -35,7 +33,6 @@ docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -47,7 +44,6 @@ files = [ name = "antropy" version = "0.1.5" description = "AntroPy: entropy and complexity of time-series in Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -65,7 +61,6 @@ stochastic = "*" name = "antropy" version = "0.1.6" description = "AntroPy: entropy and complexity of time-series in Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -83,7 +78,6 @@ stochastic = "*" name = "anyio" version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -106,7 +100,6 @@ trio = ["trio (<0.22)"] name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" -category = "dev" optional = false python-versions = "*" files = [ @@ -118,7 +111,6 @@ files = [ name = "argon2-cffi" version = "23.1.0" description = "Argon2 for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -140,7 +132,6 @@ typing = ["mypy"] name = "argon2-cffi-bindings" version = "21.2.0" description = "Low-level CFFI bindings for Argon2" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -178,7 +169,6 @@ tests = ["pytest"] name = "arrow" version = "1.2.3" description = "Better dates & times for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -194,7 +184,6 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} name = "atomicwrites" version = "1.4.1" description = "Atomic file writes." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -205,7 +194,6 @@ files = [ name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -225,14 +213,13 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte [[package]] name = "babel" -version = "2.13.0" +version = "2.13.1" description = "Internationalization utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "Babel-2.13.0-py3-none-any.whl", hash = "sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec"}, - {file = "Babel-2.13.0.tar.gz", hash = "sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210"}, + {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, + {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, ] [package.dependencies] @@ -245,7 +232,6 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" -category = "dev" optional = false python-versions = "*" files = [ @@ -257,7 +243,6 @@ files = [ name = "beautifulsoup4" version = "4.12.2" description = "Screen-scraping library" -category = "dev" optional = false python-versions = ">=3.6.0" files = [ @@ -276,7 +261,6 @@ lxml = ["lxml"] name = "black" version = "22.12.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -313,7 +297,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "bleach" version = "6.0.0" description = "An easy safelist-based HTML-sanitizing tool." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -332,7 +315,6 @@ css = ["tinycss2 (>=1.1.0,<1.2)"] name = "cached-property" version = "1.5.2" description = "A decorator for caching properties in classes." -category = "dev" optional = false python-versions = "*" files = [ @@ -342,21 +324,19 @@ files = [ [[package]] name = "cachetools" -version = "5.3.1" +version = "5.3.2" description = "Extensible memoizing collections and decorators" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"}, - {file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"}, + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, ] [[package]] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -368,7 +348,6 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "dev" optional = false python-versions = "*" files = [ @@ -443,109 +422,107 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.3.0" +version = "3.3.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4162918ef3098851fcd8a628bf9b6a98d10c380725df9e04caf5ca6dd48c847a"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0570d21da019941634a531444364f2482e8db0b3425fcd5ac0c36565a64142c8"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5707a746c6083a3a74b46b3a631d78d129edab06195a92a8ece755aac25a3f3d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:278c296c6f96fa686d74eb449ea1697f3c03dc28b75f873b65b5201806346a69"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b71f4d1765639372a3b32d2638197f5cd5221b19531f9245fcc9ee62d38f56"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5969baeaea61c97efa706b9b107dcba02784b1601c74ac84f2a532ea079403e"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f93dab657839dfa61025056606600a11d0b696d79386f974e459a3fbc568ec"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:db756e48f9c5c607b5e33dd36b1d5872d0422e960145b08ab0ec7fd420e9d649"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:232ac332403e37e4a03d209a3f92ed9071f7d3dbda70e2a5e9cff1c4ba9f0678"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e5c1502d4ace69a179305abb3f0bb6141cbe4714bc9b31d427329a95acfc8bdd"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2502dd2a736c879c0f0d3e2161e74d9907231e25d35794584b1ca5284e43f596"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23e8565ab7ff33218530bc817922fae827420f143479b753104ab801145b1d5b"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win32.whl", hash = "sha256:1872d01ac8c618a8da634e232f24793883d6e456a66593135aeafe3784b0848d"}, - {file = "charset_normalizer-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:557b21a44ceac6c6b9773bc65aa1b4cc3e248a5ad2f5b914b91579a32e22204d"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d7eff0f27edc5afa9e405f7165f85a6d782d308f3b6b9d96016c010597958e63"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a685067d05e46641d5d1623d7c7fdf15a357546cbb2f71b0ebde91b175ffc3e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3d5b7db9ed8a2b11a774db2bbea7ba1884430a205dbd54a32d61d7c2a190fa"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2935ffc78db9645cb2086c2f8f4cfd23d9b73cc0dc80334bc30aac6f03f68f8c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fe359b2e3a7729010060fbca442ca225280c16e923b37db0e955ac2a2b72a05"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:380c4bde80bce25c6e4f77b19386f5ec9db230df9f2f2ac1e5ad7af2caa70459"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0d1e3732768fecb052d90d62b220af62ead5748ac51ef61e7b32c266cac9293"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b2919306936ac6efb3aed1fbf81039f7087ddadb3160882a57ee2ff74fd2382"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f8888e31e3a85943743f8fc15e71536bda1c81d5aa36d014a3c0c44481d7db6e"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:82eb849f085624f6a607538ee7b83a6d8126df6d2f7d3b319cb837b289123078"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7b8b8bf1189b3ba9b8de5c8db4d541b406611a71a955bbbd7385bbc45fcb786c"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5adf257bd58c1b8632046bbe43ee38c04e1038e9d37de9c57a94d6bd6ce5da34"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c350354efb159b8767a6244c166f66e67506e06c8924ed74669b2c70bc8735b1"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win32.whl", hash = "sha256:02af06682e3590ab952599fbadac535ede5d60d78848e555aa58d0c0abbde786"}, - {file = "charset_normalizer-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:86d1f65ac145e2c9ed71d8ffb1905e9bba3a91ae29ba55b4c46ae6fc31d7c0d4"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3b447982ad46348c02cb90d230b75ac34e9886273df3a93eec0539308a6296d7"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:abf0d9f45ea5fb95051c8bfe43cb40cda383772f7e5023a83cc481ca2604d74e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b09719a17a2301178fac4470d54b1680b18a5048b481cb8890e1ef820cb80455"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3d9b48ee6e3967b7901c052b670c7dda6deb812c309439adaffdec55c6d7b78"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:edfe077ab09442d4ef3c52cb1f9dab89bff02f4524afc0acf2d46be17dc479f5"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3debd1150027933210c2fc321527c2299118aa929c2f5a0a80ab6953e3bd1908"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86f63face3a527284f7bb8a9d4f78988e3c06823f7bea2bd6f0e0e9298ca0403"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24817cb02cbef7cd499f7c9a2735286b4782bd47a5b3516a0e84c50eab44b98e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c71f16da1ed8949774ef79f4a0260d28b83b3a50c6576f8f4f0288d109777989"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9cf3126b85822c4e53aa28c7ec9869b924d6fcfb76e77a45c44b83d91afd74f9"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b3b2316b25644b23b54a6f6401074cebcecd1244c0b8e80111c9a3f1c8e83d65"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:03680bb39035fbcffe828eae9c3f8afc0428c91d38e7d61aa992ef7a59fb120e"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cc152c5dd831641e995764f9f0b6589519f6f5123258ccaca8c6d34572fefa8"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win32.whl", hash = "sha256:b8f3307af845803fb0b060ab76cf6dd3a13adc15b6b451f54281d25911eb92df"}, - {file = "charset_normalizer-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:8eaf82f0eccd1505cf39a45a6bd0a8cf1c70dcfc30dba338207a969d91b965c0"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dc45229747b67ffc441b3de2f3ae5e62877a282ea828a5bdb67883c4ee4a8810"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f4a0033ce9a76e391542c182f0d48d084855b5fcba5010f707c8e8c34663d77"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ada214c6fa40f8d800e575de6b91a40d0548139e5dc457d2ebb61470abf50186"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1121de0e9d6e6ca08289583d7491e7fcb18a439305b34a30b20d8215922d43c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1063da2c85b95f2d1a430f1c33b55c9c17ffaf5e612e10aeaad641c55a9e2b9d"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70f1d09c0d7748b73290b29219e854b3207aea922f839437870d8cc2168e31cc"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:250c9eb0f4600361dd80d46112213dff2286231d92d3e52af1e5a6083d10cad9"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:750b446b2ffce1739e8578576092179160f6d26bd5e23eb1789c4d64d5af7dc7"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:fc52b79d83a3fe3a360902d3f5d79073a993597d48114c29485e9431092905d8"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:588245972aca710b5b68802c8cad9edaa98589b1b42ad2b53accd6910dad3545"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e39c7eb31e3f5b1f88caff88bcff1b7f8334975b46f6ac6e9fc725d829bc35d4"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win32.whl", hash = "sha256:abecce40dfebbfa6abf8e324e1860092eeca6f7375c8c4e655a8afb61af58f2c"}, - {file = "charset_normalizer-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a91a981f185721542a0b7c92e9054b7ab4fea0508a795846bc5b0abf8118d4"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:67b8cc9574bb518ec76dc8e705d4c39ae78bb96237cb533edac149352c1f39fe"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac71b2977fb90c35d41c9453116e283fac47bb9096ad917b8819ca8b943abecd"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3ae38d325b512f63f8da31f826e6cb6c367336f95e418137286ba362925c877e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:542da1178c1c6af8873e143910e2269add130a299c9106eef2594e15dae5e482"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30a85aed0b864ac88309b7d94be09f6046c834ef60762a8833b660139cfbad13"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aae32c93e0f64469f74ccc730a7cb21c7610af3a775157e50bbd38f816536b38"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b26ddf78d57f1d143bdf32e820fd8935d36abe8a25eb9ec0b5a71c82eb3895"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f5d10bae5d78e4551b7be7a9b29643a95aded9d0f602aa2ba584f0388e7a557"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:249c6470a2b60935bafd1d1d13cd613f8cd8388d53461c67397ee6a0f5dce741"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c5a74c359b2d47d26cdbbc7845e9662d6b08a1e915eb015d044729e92e7050b7"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b5bcf60a228acae568e9911f410f9d9e0d43197d030ae5799e20dca8df588287"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:187d18082694a29005ba2944c882344b6748d5be69e3a89bf3cc9d878e548d5a"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81bf654678e575403736b85ba3a7867e31c2c30a69bc57fe88e3ace52fb17b89"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win32.whl", hash = "sha256:85a32721ddde63c9df9ebb0d2045b9691d9750cb139c161c80e500d210f5e26e"}, - {file = "charset_normalizer-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:468d2a840567b13a590e67dd276c570f8de00ed767ecc611994c301d0f8c014f"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e0fc42822278451bc13a2e8626cf2218ba570f27856b536e00cfa53099724828"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:09c77f964f351a7369cc343911e0df63e762e42bac24cd7d18525961c81754f4"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:12ebea541c44fdc88ccb794a13fe861cc5e35d64ed689513a5c03d05b53b7c82"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:805dfea4ca10411a5296bcc75638017215a93ffb584c9e344731eef0dcfb026a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:96c2b49eb6a72c0e4991d62406e365d87067ca14c1a729a870d22354e6f68115"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaf7b34c5bc56b38c931a54f7952f1ff0ae77a2e82496583b247f7c969eb1479"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:619d1c96099be5823db34fe89e2582b336b5b074a7f47f819d6b3a57ff7bdb86"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0ac5e7015a5920cfce654c06618ec40c33e12801711da6b4258af59a8eff00a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93aa7eef6ee71c629b51ef873991d6911b906d7312c6e8e99790c0f33c576f89"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7966951325782121e67c81299a031f4c115615e68046f79b85856b86ebffc4cd"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:02673e456dc5ab13659f85196c534dc596d4ef260e4d86e856c3b2773ce09843"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:c2af80fb58f0f24b3f3adcb9148e6203fa67dd3f61c4af146ecad033024dde43"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:153e7b6e724761741e0974fc4dcd406d35ba70b92bfe3fedcb497226c93b9da7"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win32.whl", hash = "sha256:d47ecf253780c90ee181d4d871cd655a789da937454045b17b5798da9393901a"}, - {file = "charset_normalizer-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:d97d85fa63f315a8bdaba2af9a6a686e0eceab77b3089af45133252618e70884"}, - {file = "charset_normalizer-3.3.0-py3-none-any.whl", hash = "sha256:e46cd37076971c1040fc8c41273a8b3e2c624ce4f2be3f5dfcb7a430c1d3acc2"}, + {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, + {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, ] [[package]] name = "click" version = "8.1.7" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -561,7 +538,6 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} name = "cloudpickle" version = "2.2.1" description = "Extended pickling support for Python objects" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -573,7 +549,6 @@ files = [ name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -585,7 +560,6 @@ files = [ name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -658,7 +632,6 @@ toml = ["tomli"] name = "dask" version = "2022.2.0" description = "Parallel PyData with Task Scheduling" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -688,7 +661,6 @@ test = ["pre-commit", "pytest", "pytest-rerunfailures", "pytest-xdist"] name = "debugpy" version = "1.7.0" description = "An implementation of the Debug Adapter Protocol for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -720,7 +692,6 @@ files = [ name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -732,7 +703,6 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -744,7 +714,6 @@ files = [ name = "dill" version = "0.3.7" description = "serialize all of Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -759,7 +728,6 @@ graph = ["objgraph (>=1.7.2)"] name = "distributed" version = "2022.2.0" description = "Distributed scheduler for Dask" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -790,7 +758,6 @@ zict = ">=0.1.3" name = "docutils" version = "0.16" description = "Docutils -- Python Documentation Utilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -802,7 +769,6 @@ files = [ name = "entrypoints" version = "0.4" description = "Discover and load entry points from installed packages." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -814,7 +780,6 @@ files = [ name = "exceptiongroup" version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -829,7 +794,6 @@ test = ["pytest (>=6)"] name = "fastjsonschema" version = "2.18.1" description = "Fastest Python implementation of JSON schema" -category = "dev" optional = false python-versions = "*" files = [ @@ -844,7 +808,6 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc name = "filelock" version = "3.12.2" description = "A platform independent file lock." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -860,7 +823,6 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p name = "fqdn" version = "1.5.1" description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" -category = "dev" optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" files = [ @@ -875,7 +837,6 @@ cached-property = {version = ">=1.3.0", markers = "python_version < \"3.8\""} name = "fsspec" version = "2023.1.0" description = "File-system specification" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -910,7 +871,6 @@ tqdm = ["tqdm"] name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -919,14 +879,13 @@ files = [ [[package]] name = "google-auth" -version = "2.23.2" +version = "2.23.3" description = "Google Authentication Library" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "google-auth-2.23.2.tar.gz", hash = "sha256:5a9af4be520ba33651471a0264eead312521566f44631cbb621164bc30c8fd40"}, - {file = "google_auth-2.23.2-py2.py3-none-any.whl", hash = "sha256:c2e253347579d483004f17c3bd0bf92e611ef6c7ba24d41c5c59f2e7aeeaf088"}, + {file = "google-auth-2.23.3.tar.gz", hash = "sha256:6864247895eea5d13b9c57c9e03abb49cb94ce2dc7c58e91cba3248c7477c9e3"}, + {file = "google_auth-2.23.3-py2.py3-none-any.whl", hash = "sha256:a8f4608e65c244ead9e0538f181a96c6e11199ec114d41f1d7b1bffa96937bda"}, ] [package.dependencies] @@ -945,7 +904,6 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] name = "google-auth-oauthlib" version = "1.1.0" description = "Google Authentication Library" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -962,14 +920,13 @@ tool = ["click (>=6.0.0)"] [[package]] name = "gspread" -version = "5.11.3" +version = "5.12.0" description = "Google Spreadsheets Python API" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "gspread-5.11.3-py3-none-any.whl", hash = "sha256:665a77fe9be4a79b606e6beb9baf8855d63dce211055cb1df1de9c2c70deb882"}, - {file = "gspread-5.11.3.tar.gz", hash = "sha256:7512ade467590d5ee8d49e8981c7f1ba5813fd56e78cb4dcd7a77e0cb4ce2b86"}, + {file = "gspread-5.12.0-py3-none-any.whl", hash = "sha256:6fc8e0e627ec878b57caa69ce1c86225b54bee073bbfe5252f3868ea9a61d965"}, + {file = "gspread-5.12.0.tar.gz", hash = "sha256:a3fb9bdf1c185aeee32a6cf533b32628012f065327c50a810f1c909dc5eba64b"}, ] [package.dependencies] @@ -980,7 +937,6 @@ google-auth-oauthlib = ">=0.4.1" name = "heapdict" version = "1.0.1" description = "a heap with decrease-key and increase-key operations" -category = "dev" optional = false python-versions = "*" files = [ @@ -992,7 +948,6 @@ files = [ name = "httplib2" version = "0.22.0" description = "A comprehensive HTTP client library." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1007,7 +962,6 @@ pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0 name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1019,7 +973,6 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1031,7 +984,6 @@ files = [ name = "importlib-metadata" version = "6.7.0" description = "Read metadata from Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1052,7 +1004,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "importlib-resources" version = "5.12.0" description = "Read resources from Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1071,7 +1022,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1083,7 +1033,6 @@ files = [ name = "ipykernel" version = "6.16.2" description = "IPython Kernel for Jupyter" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1112,7 +1061,6 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-cov", "p name = "ipython" version = "7.34.0" description = "IPython: Productive Interactive Computing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1149,7 +1097,6 @@ test = ["ipykernel", "nbformat", "nose (>=0.10.1)", "numpy (>=1.17)", "pygments" name = "ipython-genutils" version = "0.2.0" description = "Vestigial utilities from IPython" -category = "dev" optional = false python-versions = "*" files = [ @@ -1161,7 +1108,6 @@ files = [ name = "isoduration" version = "20.11.0" description = "Operations with ISO 8601 durations" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1176,7 +1122,6 @@ arrow = ">=0.15.0" name = "jedi" version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1196,7 +1141,6 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1214,7 +1158,6 @@ i18n = ["Babel (>=2.7)"] name = "joblib" version = "1.3.2" description = "Lightweight pipelining with Python functions" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1226,7 +1169,6 @@ files = [ name = "json5" version = "0.9.14" description = "A Python implementation of the JSON5 data format." -category = "dev" optional = false python-versions = "*" files = [ @@ -1241,19 +1183,16 @@ dev = ["hypothesis"] name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] [[package]] name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1285,7 +1224,6 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "jupyter-client" version = "7.4.9" description = "Jupyter protocol implementation and client libraries" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1310,7 +1248,6 @@ test = ["codecov", "coverage", "ipykernel (>=6.12)", "ipython", "mypy", "pre-com name = "jupyter-core" version = "4.12.0" description = "Jupyter core package. A base package on which Jupyter projects rely." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1329,7 +1266,6 @@ test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] name = "jupyter-events" version = "0.6.3" description = "Jupyter Event System library" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1354,7 +1290,6 @@ test = ["click", "coverage", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>= name = "jupyter-server" version = "1.24.0" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1367,7 +1302,7 @@ anyio = ">=3.1.0,<4" argon2-cffi = "*" jinja2 = "*" jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" nbconvert = ">=6.4.4" nbformat = ">=5.2.0" packaging = "*" @@ -1387,7 +1322,6 @@ test = ["coverage", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console name = "jupyter-server-fileid" version = "0.9.0" description = "" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1407,7 +1341,6 @@ test = ["jupyter-server[test] (>=1.15,<3)", "pytest", "pytest-cov"] name = "jupyter-server-ydoc" version = "0.8.0" description = "A Jupyter Server Extension Providing Y Documents." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1427,7 +1360,6 @@ test = ["coverage", "jupyter-server[test] (>=2.0.0a0)", "pytest (>=7.0)", "pytes name = "jupyter-ydoc" version = "0.2.5" description = "Document structures for collaborative editing using Ypy" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1447,7 +1379,6 @@ test = ["pre-commit", "pytest", "pytest-asyncio", "websockets (>=10.0)", "ypy-we name = "jupyterlab" version = "3.6.6" description = "JupyterLab computational environment" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1476,7 +1407,6 @@ test = ["check-manifest", "coverage", "jupyterlab-server[test]", "pre-commit", " name = "jupyterlab-pygments" version = "0.2.2" description = "Pygments theme using JupyterLab CSS variables" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1488,7 +1418,6 @@ files = [ name = "jupyterlab-server" version = "2.24.0" description = "A set of server components for JupyterLab and JupyterLab like applications." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1515,7 +1444,6 @@ test = ["hatch", "ipykernel", "jupyterlab-server[openapi]", "openapi-spec-valida name = "llvmlite" version = "0.39.1" description = "lightweight wrapper around basic LLVM functionality" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1551,43 +1479,41 @@ files = [ [[package]] name = "llvmlite" -version = "0.41.0" +version = "0.41.1" description = "lightweight wrapper around basic LLVM functionality" -category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "llvmlite-0.41.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acc81c1279f858e5eab460844cc381e30d6666bc8eea04724b54d4eeb1fd1e54"}, - {file = "llvmlite-0.41.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:013000a11df84a8b5e4f7fbf2513896ca48441c527d9ae8e375da92bc5575d08"}, - {file = "llvmlite-0.41.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1b5df30581eb8dbdee0e17a1217debb1d7dcd61a092a09726afff441dad5a67"}, - {file = "llvmlite-0.41.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe265129ecd18957d3653cfb17df1632fa2c57fd0bac1960bc20a8c3ca961197"}, - {file = "llvmlite-0.41.0-cp310-cp310-win32.whl", hash = "sha256:6e477d23afbdddb3dde789d29a771e23bcfa1b12485156370dba9df05d529d94"}, - {file = "llvmlite-0.41.0-cp310-cp310-win_amd64.whl", hash = "sha256:93ce07a0a6d98ff2fcc34e7d2d315d8d09f6a737539e089f1a8cbe4a3a0313bf"}, - {file = "llvmlite-0.41.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dabfb1a28d26b8c01228f59aec90a61324203dda6b1465c596d577d6380545e8"}, - {file = "llvmlite-0.41.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:741bb2ab7712c4763483189f0684163fb3ac44087c617698c50654c7d7ab6a24"}, - {file = "llvmlite-0.41.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7b7022f1e2f652722ddd5697987f1aeaf0c9a64f2ee324e03f6e060b28a1bbd"}, - {file = "llvmlite-0.41.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70feadac822f8840f2db6cbb662f1b349fe5d375d8ceb9c907f3919e005dc705"}, - {file = "llvmlite-0.41.0-cp311-cp311-win_amd64.whl", hash = "sha256:21191c6a9fb4a86d71ec72debbaf39db49590a950c8a2a4ac792c41d16b0a61a"}, - {file = "llvmlite-0.41.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0d94e531c763340344198f2c31af6af7b665e9cd2b354e31afa5cf4abfce0a8e"}, - {file = "llvmlite-0.41.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d8997264291e822689f7d6df4716638f35ff586bef5b8be40e2ba77d6bd9405c"}, - {file = "llvmlite-0.41.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de31585b867e8d9bae0c15f03e8bf541afcff66ffa5f61e401a738274702bdcd"}, - {file = "llvmlite-0.41.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57c0a3fd031936461f9f24f4cace80a86c9ba09d8b02fa87c209607aae2463cb"}, - {file = "llvmlite-0.41.0-cp38-cp38-win32.whl", hash = "sha256:0c79cb7e88403d6c64385bf1e63797af0884caf1f4afa3c8c4bbef1920e28148"}, - {file = "llvmlite-0.41.0-cp38-cp38-win_amd64.whl", hash = "sha256:6c40e290d930b09bbebe0d05c750b8a9e20af147e8cec8d62aa42e874f46dbfa"}, - {file = "llvmlite-0.41.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24b3f7e258ea7c07ebf9f70c772e25619de8d207192254beb7644b818a97440b"}, - {file = "llvmlite-0.41.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:876cd5f53cfe51d3a5cf7952dc1a25bd6158f5795739b1f8159c3591b32ed3cb"}, - {file = "llvmlite-0.41.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8218d307bd89535207fea1cc1ef5498afcb6d0203153dba214058715fecdb699"}, - {file = "llvmlite-0.41.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27d9d11c8dcdb8a8e14e92d0be5bba60f15bdf2fc116b8d27cab40221093a1b0"}, - {file = "llvmlite-0.41.0-cp39-cp39-win32.whl", hash = "sha256:a4af8722ad6cb0dd2d5454ebc5a7bf90867df5f3fcb0787396a3261052caefda"}, - {file = "llvmlite-0.41.0-cp39-cp39-win_amd64.whl", hash = "sha256:f150e127d6bc0e74633b8ba210776b0b6fdc82af6dfebf0794318ea97634acd0"}, - {file = "llvmlite-0.41.0.tar.gz", hash = "sha256:7d41db345d76d2dfa31871178ce0d8e9fd8aa015aa1b7d4dab84b5cb393901e0"}, + {file = "llvmlite-0.41.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1e1029d47ee66d3a0c4d6088641882f75b93db82bd0e6178f7bd744ebce42b9"}, + {file = "llvmlite-0.41.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:150d0bc275a8ac664a705135e639178883293cf08c1a38de3bbaa2f693a0a867"}, + {file = "llvmlite-0.41.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1eee5cf17ec2b4198b509272cf300ee6577229d237c98cc6e63861b08463ddc6"}, + {file = "llvmlite-0.41.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd0338da625346538f1173a17cabf21d1e315cf387ca21b294ff209d176e244"}, + {file = "llvmlite-0.41.1-cp310-cp310-win32.whl", hash = "sha256:fa1469901a2e100c17eb8fe2678e34bd4255a3576d1a543421356e9c14d6e2ae"}, + {file = "llvmlite-0.41.1-cp310-cp310-win_amd64.whl", hash = "sha256:2b76acee82ea0e9304be6be9d4b3840208d050ea0dcad75b1635fa06e949a0ae"}, + {file = "llvmlite-0.41.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:210e458723436b2469d61b54b453474e09e12a94453c97ea3fbb0742ba5a83d8"}, + {file = "llvmlite-0.41.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:855f280e781d49e0640aef4c4af586831ade8f1a6c4df483fb901cbe1a48d127"}, + {file = "llvmlite-0.41.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b67340c62c93a11fae482910dc29163a50dff3dfa88bc874872d28ee604a83be"}, + {file = "llvmlite-0.41.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2181bb63ef3c607e6403813421b46982c3ac6bfc1f11fa16a13eaafb46f578e6"}, + {file = "llvmlite-0.41.1-cp311-cp311-win_amd64.whl", hash = "sha256:9564c19b31a0434f01d2025b06b44c7ed422f51e719ab5d24ff03b7560066c9a"}, + {file = "llvmlite-0.41.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5940bc901fb0325970415dbede82c0b7f3e35c2d5fd1d5e0047134c2c46b3281"}, + {file = "llvmlite-0.41.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8b0a9a47c28f67a269bb62f6256e63cef28d3c5f13cbae4fab587c3ad506778b"}, + {file = "llvmlite-0.41.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8afdfa6da33f0b4226af8e64cfc2b28986e005528fbf944d0a24a72acfc9432"}, + {file = "llvmlite-0.41.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8454c1133ef701e8c050a59edd85d238ee18bb9a0eb95faf2fca8b909ee3c89a"}, + {file = "llvmlite-0.41.1-cp38-cp38-win32.whl", hash = "sha256:2d92c51e6e9394d503033ffe3292f5bef1566ab73029ec853861f60ad5c925d0"}, + {file = "llvmlite-0.41.1-cp38-cp38-win_amd64.whl", hash = "sha256:df75594e5a4702b032684d5481db3af990b69c249ccb1d32687b8501f0689432"}, + {file = "llvmlite-0.41.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04725975e5b2af416d685ea0769f4ecc33f97be541e301054c9f741003085802"}, + {file = "llvmlite-0.41.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bf14aa0eb22b58c231243dccf7e7f42f7beec48970f2549b3a6acc737d1a4ba4"}, + {file = "llvmlite-0.41.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92c32356f669e036eb01016e883b22add883c60739bc1ebee3a1cc0249a50828"}, + {file = "llvmlite-0.41.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24091a6b31242bcdd56ae2dbea40007f462260bc9bdf947953acc39dffd54f8f"}, + {file = "llvmlite-0.41.1-cp39-cp39-win32.whl", hash = "sha256:880cb57ca49e862e1cd077104375b9d1dfdc0622596dfa22105f470d7bacb309"}, + {file = "llvmlite-0.41.1-cp39-cp39-win_amd64.whl", hash = "sha256:92f093986ab92e71c9ffe334c002f96defc7986efda18397d0f08534f3ebdc4d"}, + {file = "llvmlite-0.41.1.tar.gz", hash = "sha256:f19f767a018e6ec89608e1f6b13348fa2fcde657151137cb64e56d48598a92db"}, ] [[package]] name = "locket" version = "1.0.0" description = "File-based locks for Python on Linux and Windows" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1599,7 +1525,6 @@ files = [ name = "mako" version = "1.2.4" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1620,7 +1545,6 @@ testing = ["pytest"] name = "markdown" version = "3.4.4" description = "Python implementation of John Gruber's Markdown." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1639,7 +1563,6 @@ testing = ["coverage", "pyyaml"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1699,7 +1622,6 @@ files = [ name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1714,7 +1636,6 @@ traitlets = "*" name = "memory-profiler" version = "0.58.0" description = "A module for monitoring memory usage of a python program" -category = "dev" optional = false python-versions = ">=3.4" files = [ @@ -1728,7 +1649,6 @@ psutil = "*" name = "mistune" version = "3.0.2" description = "A sane and fast Markdown parser with useful plugins and renderers" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1740,7 +1660,6 @@ files = [ name = "msgpack" version = "1.0.5" description = "MessagePack serializer" -category = "dev" optional = false python-versions = "*" files = [ @@ -1813,7 +1732,6 @@ files = [ name = "multiprocess" version = "0.70.15" description = "better multiprocessing and multithreading in Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1842,7 +1760,6 @@ dill = ">=0.3.7" name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1854,7 +1771,6 @@ files = [ name = "nbclassic" version = "1.0.0" description = "Jupyter Notebook as a Jupyter Server extension." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1890,7 +1806,6 @@ test = ["coverage", "nbval", "pytest", "pytest-cov", "pytest-jupyter", "pytest-p name = "nbclient" version = "0.7.4" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -1900,7 +1815,7 @@ files = [ [package.dependencies] jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" nbformat = ">=5.1" traitlets = ">=5.3" @@ -1913,7 +1828,6 @@ test = ["flaky", "ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "p name = "nbconvert" version = "7.6.0" description = "Converting Jupyter Notebooks" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1952,7 +1866,6 @@ webpdf = ["pyppeteer (>=1,<1.1)"] name = "nbformat" version = "5.8.0" description = "The Jupyter Notebook format" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1975,7 +1888,6 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] name = "nest-asyncio" version = "1.5.8" description = "Patch asyncio to allow nested event loops" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1987,7 +1899,6 @@ files = [ name = "nolds" version = "0.5.2" description = "Nonlinear measures for dynamical systems (based on one-dimensional time series)" -category = "dev" optional = false python-versions = "*" files = [ @@ -2007,7 +1918,6 @@ ransac = ["sklearn (>=0.19)"] name = "notebook" version = "6.5.4" description = "A web-based notebook environment for interactive computing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2042,7 +1952,6 @@ test = ["coverage", "nbval", "pytest", "pytest-cov", "requests", "requests-unixs name = "notebook-shim" version = "0.2.3" description = "A shim layer for notebook traits and config" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2060,7 +1969,6 @@ test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync" name = "numba" version = "0.56.4" description = "compiling Python code using LLVM" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2096,51 +2004,49 @@ files = [ [package.dependencies] importlib-metadata = {version = "*", markers = "python_version < \"3.9\""} -llvmlite = ">=0.39.0dev0,<0.40" +llvmlite = "==0.39.*" numpy = ">=1.18,<1.24" setuptools = "*" [[package]] name = "numba" -version = "0.58.0" +version = "0.58.1" description = "compiling Python code using LLVM" -category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "numba-0.58.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f146c11af62ad25021d93fccf48715a96d1ea76d43c1c3bc97dca561c6a2693"}, - {file = "numba-0.58.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8059ee491651885f89655f08856a107aa610e3355b373f3b7437f1da96f09703"}, - {file = "numba-0.58.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8bd9edd27ab29e80bcf4083f9955c4a8871075a13a370b3bef99f81e184541fa"}, - {file = "numba-0.58.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ee9f5fd962e0ada0e68df67a6ff881f95b45e0ae7cb96141e913337040d490b"}, - {file = "numba-0.58.0-cp310-cp310-win_amd64.whl", hash = "sha256:398ab539257df8e980ec2f9cdfae836bb965fadc2dd30db3fcfbf3aefa542836"}, - {file = "numba-0.58.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e61a1fa0ab7d290f0a43d8523b372f96765db6ceb6a691660c17e9ed609cb470"}, - {file = "numba-0.58.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8a9b69cc6259131791822c5eb893b03cd9372f4aae669d020500565b6d5d80bc"}, - {file = "numba-0.58.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7b42b23c36cf08fcfe1a8f2acf3a0af95b41f9ee07fc81b28d7b9b5ada85d8c"}, - {file = "numba-0.58.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0d7a5e81e4047a23986f816b48ac46616ceb4eadbff6bbe739944d36b3bdbfe7"}, - {file = "numba-0.58.0-cp311-cp311-win_amd64.whl", hash = "sha256:0ce322178ff7006b7f50dad25b042ef64c6393f2fafafa79c0498d789b1aac27"}, - {file = "numba-0.58.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3934eab4eb1c07c8f067e99350b99f70b2ca77d5aa3911d365643171f771157"}, - {file = "numba-0.58.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cee5f22f7fbb2ef445e422aeafe5d38bf71a52c8bb34d22c1e145afa4034d6b"}, - {file = "numba-0.58.0-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:121bf98a2b02e0611af3bfab3995fed990db58c4bfc6c225332ccdaf37e312e7"}, - {file = "numba-0.58.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0734614d3e92eb01f848b8595be116f9c8ad997f8cf77672f3ba53c511f1429d"}, - {file = "numba-0.58.0-cp38-cp38-win_amd64.whl", hash = "sha256:48bcaae337ee450e38bf3796b4e1a166909c339f1757b6110e6adcf42c1e6c3e"}, - {file = "numba-0.58.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a5f99806d5c9671dc927a8a489bc0c88e79be51e9775d6a3c68dbfdf585cd7e9"}, - {file = "numba-0.58.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9dade55ee5f1b8c5e3e0db95449fdc5b7b4244c1a7fa133bd664cbfc1027bafe"}, - {file = "numba-0.58.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7e182f3296dfcbafcd23b9263baeb350ad5adcacd081f1b3ec927a9fb325cca8"}, - {file = "numba-0.58.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f80aee7889e82ab9c4770e02b21ca4e3ca15cc8c829c173fc27b77ab0529b5cb"}, - {file = "numba-0.58.0-cp39-cp39-win_amd64.whl", hash = "sha256:477f429bb593dd3fc8d84b44f199e8e30268a7cfeb96c8464cb393d401de4f45"}, - {file = "numba-0.58.0.tar.gz", hash = "sha256:e5d5a318dc65a101ef846d7fd93f3cf2f7942494019e8342e51238b360739125"}, + {file = "numba-0.58.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:07f2fa7e7144aa6f275f27260e73ce0d808d3c62b30cff8906ad1dec12d87bbe"}, + {file = "numba-0.58.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7bf1ddd4f7b9c2306de0384bf3854cac3edd7b4d8dffae2ec1b925e4c436233f"}, + {file = "numba-0.58.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bc2d904d0319d7a5857bd65062340bed627f5bfe9ae4a495aef342f072880d50"}, + {file = "numba-0.58.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e79b6cc0d2bf064a955934a2e02bf676bc7995ab2db929dbbc62e4c16551be6"}, + {file = "numba-0.58.1-cp310-cp310-win_amd64.whl", hash = "sha256:81fe5b51532478149b5081311b0fd4206959174e660c372b94ed5364cfb37c82"}, + {file = "numba-0.58.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bcecd3fb9df36554b342140a4d77d938a549be635d64caf8bd9ef6c47a47f8aa"}, + {file = "numba-0.58.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1eaa744f518bbd60e1f7ccddfb8002b3d06bd865b94a5d7eac25028efe0e0ff"}, + {file = "numba-0.58.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bf68df9c307fb0aa81cacd33faccd6e419496fdc621e83f1efce35cdc5e79cac"}, + {file = "numba-0.58.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:55a01e1881120e86d54efdff1be08381886fe9f04fc3006af309c602a72bc44d"}, + {file = "numba-0.58.1-cp311-cp311-win_amd64.whl", hash = "sha256:811305d5dc40ae43c3ace5b192c670c358a89a4d2ae4f86d1665003798ea7a1a"}, + {file = "numba-0.58.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea5bfcf7d641d351c6a80e8e1826eb4a145d619870016eeaf20bbd71ef5caa22"}, + {file = "numba-0.58.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e63d6aacaae1ba4ef3695f1c2122b30fa3d8ba039c8f517784668075856d79e2"}, + {file = "numba-0.58.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6fe7a9d8e3bd996fbe5eac0683227ccef26cba98dae6e5cee2c1894d4b9f16c1"}, + {file = "numba-0.58.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:898af055b03f09d33a587e9425500e5be84fc90cd2f80b3fb71c6a4a17a7e354"}, + {file = "numba-0.58.1-cp38-cp38-win_amd64.whl", hash = "sha256:d3e2fe81fe9a59fcd99cc572002101119059d64d31eb6324995ee8b0f144a306"}, + {file = "numba-0.58.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c765aef472a9406a97ea9782116335ad4f9ef5c9f93fc05fd44aab0db486954"}, + {file = "numba-0.58.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e9356e943617f5e35a74bf56ff6e7cc83e6b1865d5e13cee535d79bf2cae954"}, + {file = "numba-0.58.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:240e7a1ae80eb6b14061dc91263b99dc8d6af9ea45d310751b780888097c1aaa"}, + {file = "numba-0.58.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:45698b995914003f890ad839cfc909eeb9c74921849c712a05405d1a79c50f68"}, + {file = "numba-0.58.1-cp39-cp39-win_amd64.whl", hash = "sha256:bd3dda77955be03ff366eebbfdb39919ce7c2620d86c906203bed92124989032"}, + {file = "numba-0.58.1.tar.gz", hash = "sha256:487ded0633efccd9ca3a46364b40006dbdaca0f95e99b8b83e778d1195ebcbaa"}, ] [package.dependencies] importlib-metadata = {version = "*", markers = "python_version < \"3.9\""} -llvmlite = ">=0.41.0dev0,<0.42" -numpy = ">=1.21,<1.26" +llvmlite = "==0.41.*" +numpy = ">=1.22,<1.27" [[package]] name = "numpy" version = "1.21.6" description = "NumPy is the fundamental package for array computing with Python." -category = "main" optional = false python-versions = ">=3.7,<3.11" files = [ @@ -2181,7 +2087,6 @@ files = [ name = "numpy" version = "1.22.4" description = "NumPy is the fundamental package for array computing with Python." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2213,7 +2118,6 @@ files = [ name = "numpy" version = "1.24.4" description = "Fundamental package for array computing in Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2251,7 +2155,6 @@ files = [ name = "oauth2client" version = "4.1.3" description = "OAuth 2.0 client library" -category = "dev" optional = false python-versions = "*" files = [ @@ -2270,7 +2173,6 @@ six = ">=1.6.1" name = "oauthlib" version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2287,7 +2189,6 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "packaging" version = "23.2" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2299,7 +2200,6 @@ files = [ name = "pandas" version = "1.3.5" description = "Powerful data structures for data analysis, time series, and statistics" -category = "main" optional = false python-versions = ">=3.7.1" files = [ @@ -2332,7 +2232,7 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.17.3", markers = "platform_machine != \"aarch64\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, + {version = ">=1.17.3", markers = "(platform_machine != \"aarch64\" and platform_machine != \"arm64\") and python_version < \"3.10\""}, {version = ">=1.19.2", markers = "platform_machine == \"aarch64\" and python_version < \"3.10\""}, {version = ">=1.20.0", markers = "platform_machine == \"arm64\" and python_version < \"3.10\""}, {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, @@ -2347,7 +2247,6 @@ test = ["hypothesis (>=3.58)", "pytest (>=6.0)", "pytest-xdist"] name = "pandocfilters" version = "1.5.0" description = "Utilities for writing pandoc filters in python" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2359,7 +2258,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2375,7 +2273,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "partd" version = "1.4.1" description = "Appendable key-value storage" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2394,7 +2291,6 @@ complete = ["blosc", "numpy (>=1.9.0)", "pandas (>=0.19.0)", "pyzmq"] name = "pathspec" version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2406,7 +2302,6 @@ files = [ name = "patsy" version = "0.5.3" description = "A Python package for describing statistical models and for building design matrices." -category = "dev" optional = false python-versions = "*" files = [ @@ -2425,7 +2320,6 @@ test = ["pytest", "pytest-cov", "scipy"] name = "pdoc3" version = "0.9.2" description = "Auto-generate API documentation for Python projects." -category = "dev" optional = false python-versions = ">= 3.5" files = [ @@ -2440,7 +2334,6 @@ markdown = ">=3.0" name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." -category = "dev" optional = false python-versions = "*" files = [ @@ -2455,7 +2348,6 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" -category = "dev" optional = false python-versions = "*" files = [ @@ -2467,7 +2359,6 @@ files = [ name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2479,7 +2370,6 @@ files = [ name = "platformdirs" version = "3.11.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2498,7 +2388,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2517,7 +2406,6 @@ testing = ["pytest", "pytest-benchmark"] name = "prometheus-client" version = "0.17.1" description = "Python client for the Prometheus monitoring system." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2532,7 +2420,6 @@ twisted = ["twisted"] name = "prompt-toolkit" version = "3.0.39" description = "Library for building powerful interactive command lines in Python" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -2545,26 +2432,27 @@ wcwidth = "*" [[package]] name = "psutil" -version = "5.9.5" +version = "5.9.6" description = "Cross-platform lib for process and system monitoring in Python." -category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, - {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, - {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, - {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, - {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, - {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, - {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, - {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, + {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, + {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, + {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, + {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, + {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, + {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, + {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, + {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, + {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, ] [package.extras] @@ -2574,7 +2462,6 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -2586,7 +2473,6 @@ files = [ name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2598,7 +2484,6 @@ files = [ name = "py-cpuinfo" version = "9.0.0" description = "Get CPU info with pure Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -2610,7 +2495,6 @@ files = [ name = "pyarrow" version = "12.0.1" description = "Python library for Apache Arrow" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2648,7 +2532,6 @@ numpy = ">=1.16.6" name = "pyasn1" version = "0.5.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2660,7 +2543,6 @@ files = [ name = "pyasn1-modules" version = "0.3.0" description = "A collection of ASN.1-based protocols modules" -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2675,7 +2557,6 @@ pyasn1 = ">=0.4.6,<0.6.0" name = "pycatch22" version = "0.4.2" description = "22 CAnonical Time-series Features" -category = "dev" optional = false python-versions = "*" files = [ @@ -2687,7 +2568,6 @@ files = [ name = "pycparser" version = "2.21" description = "C parser in Python" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2699,7 +2579,6 @@ files = [ name = "pydocstyle" version = "5.1.1" description = "Python docstring style checker" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -2714,7 +2593,6 @@ snowballstemmer = "*" name = "pyentrp" version = "0.7.1" description = "Functions on top of NumPy for computing different types of entropy" -category = "dev" optional = false python-versions = "*" files = [ @@ -2728,7 +2606,6 @@ numpy = ">=1.7.0" name = "pyentrp" version = "0.8.5" description = "A Python library for computing entropy measures for time series analysis." -category = "dev" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -2743,7 +2620,6 @@ numpy = ">=1.22,<2.0" name = "pygments" version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2758,7 +2634,6 @@ plugins = ["importlib-metadata"] name = "pyparsing" version = "3.1.1" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" optional = false python-versions = ">=3.6.8" files = [ @@ -2773,7 +2648,6 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2810,7 +2684,6 @@ files = [ name = "pytest" version = "6.2.5" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2836,7 +2709,6 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm name = "pytest-benchmark" version = "4.0.0" description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2857,7 +2729,6 @@ histogram = ["pygal", "pygaljs"] name = "pytest-codspeed" version = "2.2.0" description = "Pytest plugin to create CodSpeed benchmarks" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2879,7 +2750,6 @@ test = ["pytest (>=7.0,<8.0)", "pytest-cov (>=4.0.0,<4.1.0)"] name = "pytest-cov" version = "2.12.1" description = "Pytest plugin for measuring coverage." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2899,7 +2769,6 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -2914,7 +2783,6 @@ six = ">=1.5" name = "python-json-logger" version = "2.0.7" description = "A python library adding a json log formatter" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2926,7 +2794,6 @@ files = [ name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ @@ -2938,7 +2805,6 @@ files = [ name = "pywin32" version = "306" description = "Python for Window Extensions" -category = "dev" optional = false python-versions = "*" files = [ @@ -2962,7 +2828,6 @@ files = [ name = "pywinpty" version = "2.0.10" description = "Pseudo terminal support for Windows from Python." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2978,7 +2843,6 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2987,6 +2851,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2994,8 +2859,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -3012,6 +2884,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -3019,6 +2892,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -3028,7 +2902,6 @@ files = [ name = "pyzmq" version = "25.1.1" description = "Python bindings for 0MQ" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -3134,7 +3007,6 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3156,7 +3028,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-oauthlib" version = "1.3.1" description = "OAuthlib authentication support for Requests." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3175,7 +3046,6 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] name = "rfc3339-validator" version = "0.1.4" description = "A pure python RFC3339 validator" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3190,7 +3060,6 @@ six = "*" name = "rfc3986-validator" version = "0.1.1" description = "Pure python rfc3986 validator" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3202,7 +3071,6 @@ files = [ name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" -category = "dev" optional = false python-versions = ">=3.6,<4" files = [ @@ -3217,7 +3085,6 @@ pyasn1 = ">=0.1.3" name = "ruff" version = "0.0.264" description = "An extremely fast Python linter, written in Rust." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3244,7 +3111,6 @@ files = [ name = "scikit-learn" version = "1.0.2" description = "A set of python modules for machine learning and data mining" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3296,38 +3162,37 @@ tests = ["black (>=21.6b0)", "flake8 (>=3.8.2)", "matplotlib (>=2.2.3)", "mypy ( [[package]] name = "scikit-learn" -version = "1.3.1" +version = "1.3.2" description = "A set of python modules for machine learning and data mining" -category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "scikit-learn-1.3.1.tar.gz", hash = "sha256:1a231cced3ee3fa04756b4a7ab532dc9417acd581a330adff5f2c01ac2831fcf"}, - {file = "scikit_learn-1.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3153612ff8d36fa4e35ef8b897167119213698ea78f3fd130b4068e6f8d2da5a"}, - {file = "scikit_learn-1.3.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6bb9490fdb8e7e00f1354621689187bef3cab289c9b869688f805bf724434755"}, - {file = "scikit_learn-1.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7135a03af71138669f19bc96e7d0cc8081aed4b3565cc3b131135d65fc642ba"}, - {file = "scikit_learn-1.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d8dee8c1f40eeba49a85fe378bdf70a07bb64aba1a08fda1e0f48d27edfc3e6"}, - {file = "scikit_learn-1.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:4d379f2b34096105a96bd857b88601dffe7389bd55750f6f29aaa37bc6272eb5"}, - {file = "scikit_learn-1.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14e8775eba072ab10866a7e0596bc9906873e22c4c370a651223372eb62de180"}, - {file = "scikit_learn-1.3.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:58b0c2490eff8355dc26e884487bf8edaccf2ba48d09b194fb2f3a026dd64f9d"}, - {file = "scikit_learn-1.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f66eddfda9d45dd6cadcd706b65669ce1df84b8549875691b1f403730bdef217"}, - {file = "scikit_learn-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6448c37741145b241eeac617028ba6ec2119e1339b1385c9720dae31367f2be"}, - {file = "scikit_learn-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c413c2c850241998168bbb3bd1bb59ff03b1195a53864f0b80ab092071af6028"}, - {file = "scikit_learn-1.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ef540e09873e31569bc8b02c8a9f745ee04d8e1263255a15c9969f6f5caa627f"}, - {file = "scikit_learn-1.3.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:9147a3a4df4d401e618713880be023e36109c85d8569b3bf5377e6cd3fecdeac"}, - {file = "scikit_learn-1.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2cd3634695ad192bf71645702b3df498bd1e246fc2d529effdb45a06ab028b4"}, - {file = "scikit_learn-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c275a06c5190c5ce00af0acbb61c06374087949f643ef32d355ece12c4db043"}, - {file = "scikit_learn-1.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:0e1aa8f206d0de814b81b41d60c1ce31f7f2c7354597af38fae46d9c47c45122"}, - {file = "scikit_learn-1.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:52b77cc08bd555969ec5150788ed50276f5ef83abb72e6f469c5b91a0009bbca"}, - {file = "scikit_learn-1.3.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a683394bc3f80b7c312c27f9b14ebea7766b1f0a34faf1a2e9158d80e860ec26"}, - {file = "scikit_learn-1.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15d964d9eb181c79c190d3dbc2fff7338786bf017e9039571418a1d53dab236"}, - {file = "scikit_learn-1.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ce9233cdf0cdcf0858a5849d306490bf6de71fa7603a3835124e386e62f2311"}, - {file = "scikit_learn-1.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:1ec668ce003a5b3d12d020d2cde0abd64b262ac5f098b5c84cf9657deb9996a8"}, - {file = "scikit_learn-1.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccbbedae99325628c1d1cbe3916b7ef58a1ce949672d8d39c8b190e10219fd32"}, - {file = "scikit_learn-1.3.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:845f81c7ceb4ea6bac64ab1c9f2ce8bef0a84d0f21f3bece2126adcc213dfecd"}, - {file = "scikit_learn-1.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8454d57a22d856f1fbf3091bd86f9ebd4bff89088819886dc0c72f47a6c30652"}, - {file = "scikit_learn-1.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d993fb70a1d78c9798b8f2f28705bfbfcd546b661f9e2e67aa85f81052b9c53"}, - {file = "scikit_learn-1.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:66f7bb1fec37d65f4ef85953e1df5d3c98a0f0141d394dcdaead5a6de9170347"}, + {file = "scikit-learn-1.3.2.tar.gz", hash = "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05"}, + {file = "scikit_learn-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1"}, + {file = "scikit_learn-1.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a"}, + {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c"}, + {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161"}, + {file = "scikit_learn-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c"}, + {file = "scikit_learn-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66"}, + {file = "scikit_learn-1.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157"}, + {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb"}, + {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433"}, + {file = "scikit_learn-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b"}, + {file = "scikit_learn-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028"}, + {file = "scikit_learn-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5"}, + {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525"}, + {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c"}, + {file = "scikit_learn-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107"}, + {file = "scikit_learn-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a19f90f95ba93c1a7f7924906d0576a84da7f3b2282ac3bfb7a08a32801add93"}, + {file = "scikit_learn-1.3.2-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:b8692e395a03a60cd927125eef3a8e3424d86dde9b2370d544f0ea35f78a8073"}, + {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15e1e94cc23d04d39da797ee34236ce2375ddea158b10bee3c343647d615581d"}, + {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:785a2213086b7b1abf037aeadbbd6d67159feb3e30263434139c98425e3dcfcf"}, + {file = "scikit_learn-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:64381066f8aa63c2710e6b56edc9f0894cc7bf59bd71b8ce5613a4559b6145e0"}, + {file = "scikit_learn-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6c43290337f7a4b969d207e620658372ba3c1ffb611f8bc2b6f031dc5c6d1d03"}, + {file = "scikit_learn-1.3.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:dc9002fc200bed597d5d34e90c752b74df516d592db162f756cc52836b38fe0e"}, + {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d08ada33e955c54355d909b9c06a4789a729977f165b8bae6f225ff0a60ec4a"}, + {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f0ae4b79b0ff9cca0bf3716bcc9915bdacff3cebea15ec79652d1cc4fa5c9"}, + {file = "scikit_learn-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:ed932ea780517b00dae7431e031faae6b49b20eb6950918eb83bd043237950e0"}, ] [package.dependencies] @@ -3346,7 +3211,6 @@ tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc ( name = "scipy" version = "1.7.3" description = "SciPy: Scientific Library for Python" -category = "main" optional = false python-versions = ">=3.7,<3.11" files = [ @@ -3388,7 +3252,6 @@ numpy = ">=1.16.5,<1.23.0" name = "scipy" version = "1.11.3" description = "Fundamental algorithms for scientific computing in Python" -category = "main" optional = false python-versions = "<3.13,>=3.9" files = [ @@ -3431,7 +3294,6 @@ test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeo name = "seglearn" version = "1.2.5" description = "A template for scikit-learn compatible packages." -category = "dev" optional = false python-versions = "*" files = [ @@ -3452,7 +3314,6 @@ tests = ["pytest", "pytest-cov"] name = "send2trash" version = "1.8.2" description = "Send file to trash natively under Mac OS X, Windows and Linux" -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -3469,7 +3330,6 @@ win32 = ["pywin32"] name = "setuptools" version = "68.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3486,7 +3346,6 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3498,7 +3357,6 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3510,7 +3368,6 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" optional = false python-versions = "*" files = [ @@ -3522,7 +3379,6 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -category = "dev" optional = false python-versions = "*" files = [ @@ -3534,7 +3390,6 @@ files = [ name = "soupsieve" version = "2.4.1" description = "A modern CSS selector implementation for Beautiful Soup." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3546,7 +3401,6 @@ files = [ name = "sphinx" version = "3.5.4" description = "Python documentation generator" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3582,7 +3436,6 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] name = "sphinxcontrib-applehelp" version = "1.0.2" description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3598,7 +3451,6 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3614,7 +3466,6 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -3630,7 +3481,6 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3645,7 +3495,6 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3661,7 +3510,6 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3677,7 +3525,6 @@ test = ["pytest"] name = "statsmodels" version = "0.13.5" description = "Statistical computations and models for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3717,9 +3564,9 @@ packaging = ">=21.3" pandas = ">=0.25" patsy = ">=0.5.2" scipy = [ - {version = ">=1.3", markers = "python_version > \"3.9\" and python_version < \"3.12\" or platform_system != \"Windows\" and python_version < \"3.12\" or platform_machine != \"x86\" and python_version < \"3.12\""}, + {version = ">=1.3", markers = "(python_version > \"3.9\" or platform_system != \"Windows\" or platform_machine != \"x86\") and python_version < \"3.12\""}, {version = ">=1.3,<1.8", markers = "python_version == \"3.7\""}, - {version = ">=1.3,<1.9", markers = "python_version == \"3.8\" and platform_system == \"Windows\" and platform_machine == \"x86\" or python_version == \"3.9\" and platform_system == \"Windows\" and platform_machine == \"x86\""}, + {version = ">=1.3,<1.9", markers = "(python_version == \"3.8\" or python_version == \"3.9\") and platform_system == \"Windows\" and platform_machine == \"x86\""}, ] [package.extras] @@ -3731,7 +3578,6 @@ docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "n name = "stochastic" version = "0.6.0" description = "Generate realizations of stochastic processes" -category = "dev" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -3747,7 +3593,6 @@ scipy = ">=1.3,<2.0" name = "stumpy" version = "1.12.0" description = "A powerful and scalable library that can be used for a variety of time series data mining tasks" -category = "dev" optional = false python-versions = "*" files = [ @@ -3767,7 +3612,6 @@ ci = ["black (>=22.1.0)", "coverage (>=4.5.3)", "dask (>=1.2.2)", "distributed ( name = "tblib" version = "2.0.0" description = "Traceback serialization library." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3779,7 +3623,6 @@ files = [ name = "terminado" version = "0.17.1" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3800,7 +3643,6 @@ test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] name = "threadpoolctl" version = "3.1.0" description = "threadpoolctl" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3812,7 +3654,6 @@ files = [ name = "threadpoolctl" version = "3.2.0" description = "threadpoolctl" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3824,7 +3665,6 @@ files = [ name = "tinycss2" version = "1.2.1" description = "A tiny CSS parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3843,7 +3683,6 @@ test = ["flake8", "isort", "pytest"] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3855,7 +3694,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3867,7 +3705,6 @@ files = [ name = "toolz" version = "0.12.0" description = "List processing tools and functional utilities" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -3879,7 +3716,6 @@ files = [ name = "tornado" version = "6.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "dev" optional = false python-versions = ">= 3.7" files = [ @@ -3900,7 +3736,6 @@ files = [ name = "tqdm" version = "4.66.1" description = "Fast, Extensible Progress Meter" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3921,7 +3756,6 @@ telegram = ["requests"] name = "traitlets" version = "5.9.0" description = "Traitlets Python configuration system" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3937,7 +3771,6 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] name = "tsfel" version = "0.1.4" description = "Library for time series feature extraction" -category = "dev" optional = false python-versions = "*" files = [ @@ -3959,7 +3792,6 @@ Sphinx = ">=1.8.5" name = "tsfresh" version = "0.20.1" description = "tsfresh extracts relevant characteristics from time series" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3990,7 +3822,6 @@ testing = ["ipython (>=5.3.0)", "matplotlib (>=2.0.0)", "mock (>=2.0.0)", "noteb name = "typed-ast" version = "1.5.5" description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -4041,7 +3872,6 @@ files = [ name = "typing-extensions" version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4053,7 +3883,6 @@ files = [ name = "uri-template" version = "1.3.0" description = "RFC 6570 URI Template Processor" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4066,14 +3895,13 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "2.0.6" +version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"}, - {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"}, + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, ] [package.extras] @@ -4086,7 +3914,6 @@ zstd = ["zstandard (>=0.18.0)"] name = "wcwidth" version = "0.2.8" description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -4098,7 +3925,6 @@ files = [ name = "webcolors" version = "1.13" description = "A library for working with the color formats defined by HTML and CSS." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4114,7 +3940,6 @@ tests = ["pytest", "pytest-cov"] name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" -category = "dev" optional = false python-versions = "*" files = [ @@ -4126,7 +3951,6 @@ files = [ name = "websocket-client" version = "1.6.1" description = "WebSocket client for Python with low level API options" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4141,85 +3965,91 @@ test = ["websockets"] [[package]] name = "y-py" -version = "0.6.0" +version = "0.6.2" description = "Python bindings for the Y-CRDT built from yrs (Rust)" -category = "dev" optional = false python-versions = "*" files = [ - {file = "y_py-0.6.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:ebbebc4f6a9e0c89c7b57035f91043b038e804dd1953845d8a66066f4526c853"}, - {file = "y_py-0.6.0-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:2c230bc01b96081550b7583b77d00404fd39825657f4064b919a10515f660cdf"}, - {file = "y_py-0.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f5975c1a8c2ca99980571b8811d151db8590de9cc96346572a81e0f6f1e30e"}, - {file = "y_py-0.6.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e5f89cf9ef1daf12f438a075415a02f227594e4b0494c78d3b83cb83651631f5"}, - {file = "y_py-0.6.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:efb3225b58dc67152c004da3c26ae5bad0afebbb3c7509d853bdd87eaa655137"}, - {file = "y_py-0.6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaaec9718f8a23924c95294d41d87829b113bc9a606a3667dfb995afc45c9920"}, - {file = "y_py-0.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fb03947937b0fcb09eb2b94eb08d8e8030ef0ed70af777684ab670bd369bc3c"}, - {file = "y_py-0.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f79ef7303e332e91d738e66e9bb7fce0243d0407a02631a58ebc0bf2fb8743d0"}, - {file = "y_py-0.6.0-cp310-none-win32.whl", hash = "sha256:1667b8a67ace756c04f03778e86fc359028c98905212f8686afb48c26c252bda"}, - {file = "y_py-0.6.0-cp310-none-win_amd64.whl", hash = "sha256:cca539c3804a580992304b18a33f1980282d9097a723f0bd01971477cb365b28"}, - {file = "y_py-0.6.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:5743e94c982585f05e02d9a3345dd9b1f28d90fa128df9f60b0eb357a76d2c32"}, - {file = "y_py-0.6.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:281535bb4f18fe09e5517a63b8206dd6f26ad6fb7e7c25c62bf785e594adab4d"}, - {file = "y_py-0.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69e05e01594e99c934562124b159720533b7ad887dde7762d460916aac47a8e4"}, - {file = "y_py-0.6.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a752ba8875ed2038dfc7d62738536cb22b4e308951cb925a7fe8fef782c6db08"}, - {file = "y_py-0.6.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea7d796bb55d08dd1a60736beb724004f2cbdc207592b5f301a5ff314b17137"}, - {file = "y_py-0.6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5126786f914ff53ea2f04f9da790db168db172521cc4f114d5501badd2f6b96"}, - {file = "y_py-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b71cd495d322da25a53a6a830b591a2c0c46db22bb0b3556fca0bbdb1d45a18e"}, - {file = "y_py-0.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0624a5adf29d29330a336eecdf15874871f559d50944d542012665e1c3a18265"}, - {file = "y_py-0.6.0-cp311-none-win32.whl", hash = "sha256:374ffef1939c42286ea18e2a413c9974430226227f8f1480bbee469933aa675b"}, - {file = "y_py-0.6.0-cp311-none-win_amd64.whl", hash = "sha256:9242f3a5c6293e634817d9984c60523ffb34cf5b41501c5958681a75745946e6"}, - {file = "y_py-0.6.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9dad6af2d83a2b0618ba3c1a2fc6657c5303cf4e9f1a65cc3fea40ffbcc552e2"}, - {file = "y_py-0.6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74d5ebb5f9ef0c4c1f7bdd9ab5e53b9d8be4c7464905f39761b22b6ce0d327d3"}, - {file = "y_py-0.6.0-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a027c39296c925f0b81e28a0fefab8c5964a0ea2b50fa05cbddf5e5ab167a380"}, - {file = "y_py-0.6.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49adf7e25c3b3bac9f19bee181ef5253659ebe5747a7141860692015222b2007"}, - {file = "y_py-0.6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47b3604c874d25616a097adaaabcad6e77729e23c5d029092b8149af1a08b2a5"}, - {file = "y_py-0.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a5a882591c8e1b1d6fbdb7ab43884907cef2b6a18e36c7ae85589e5f55371e5"}, - {file = "y_py-0.6.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:30b9337e4f3d541879a8187af121be1bd42ea110372a21895a1a3f800a6bd1c3"}, - {file = "y_py-0.6.0-cp37-none-win32.whl", hash = "sha256:ef0f08edb2094869e4d12346ee68d5154cb3d23bc3b1e7679222fae12228261c"}, - {file = "y_py-0.6.0-cp37-none-win_amd64.whl", hash = "sha256:391a232c328c2be1de4cb152ed3e9427826e4cbd9d645feacb3dbb344b122e10"}, - {file = "y_py-0.6.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:eb60fe68774117378efdbd368ef83cf1417e61d4bc39c6be8e7f4ee91fb7428a"}, - {file = "y_py-0.6.0-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:4f025c50301d9ddbbc2384f98d3ff1dbfe43606146b747e23a17774a02faffe9"}, - {file = "y_py-0.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4181b28f736cae3bb4517090ae5eeca318c075c0106466f13a4ed6682265fc8a"}, - {file = "y_py-0.6.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6273d84605ee55b3ac52742018f94602dab9b0457f29e6f787021c473b02fed"}, - {file = "y_py-0.6.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1eefb6371cd6e072cf467b897f85bd0d7575f3a3e944fb8675f84fb59aedd071"}, - {file = "y_py-0.6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b75c2199a125ef8926f3216fb324c3bcd8b1b4b6c0b428888cc753ee4c85f81f"}, - {file = "y_py-0.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035ba7ce31bb87bd7b5977eee71ee2ff71e54d347a35e2079362b1c23731dccd"}, - {file = "y_py-0.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:418aaa796a22b0102de09b36b6c6294d0a485f04bc8866c3b28f17e7022c44ba"}, - {file = "y_py-0.6.0-cp38-none-win32.whl", hash = "sha256:fc48db294d327a5cc10ee49f73f1fa1478240cc827c9029e0871106e327353ac"}, - {file = "y_py-0.6.0-cp38-none-win_amd64.whl", hash = "sha256:d1301bfeaa26f78f4b0e5f96e0f22761b38cc407713f70550a1be490945fd6d7"}, - {file = "y_py-0.6.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:e48b5b30242c7d517be85b48246b21e4e26540505a1ffe4fe473e239a8ec56d3"}, - {file = "y_py-0.6.0-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:479da40ef1205de52d87209534bf8e713a782e01eeed3df8dff44d21085e3f63"}, - {file = "y_py-0.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7c3eaf65b162e59486a48bea5dd2035937952f15e008a14813e8cb7c24d7b"}, - {file = "y_py-0.6.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a20a4d10c8f0ee2b6df265d182d0be0ecd2ba7348c0a20b9df7d4d39df895801"}, - {file = "y_py-0.6.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:304e88a3deaff9906faa7ba514cf82f4ca4bad1ea88728206ff906e66179abd3"}, - {file = "y_py-0.6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6377e3cbab8f5b8b918130e9f924358f98ca1bea12a8096d3fadea191f7137f1"}, - {file = "y_py-0.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b44fdd64598e9ed4008158e5e60be5e1e2daeed6fae0ab2bf0002461e960709d"}, - {file = "y_py-0.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:51f1997dae6d77b12b50502871c7a9aae22e84048e83b64fe6d4f18dec2e4700"}, - {file = "y_py-0.6.0-cp39-none-win32.whl", hash = "sha256:9f56888aeb07ca76a5cd552581bb3735fcd2d8c18165b946fdb6e4507b10e76c"}, - {file = "y_py-0.6.0-cp39-none-win_amd64.whl", hash = "sha256:11345294820908d5b8af9c6616ea908dda8b3e554ee6f6d50be6a2e15940f63e"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4c16d50d0728abd915bd9e2e0c3ce982005ba78b60e4b6666aadc592d9982c79"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:eccf67d09a4df42a7be2a5427c1b2e0b89bec862f519ded754bd452df516b380"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:513a2fe1318c247fc3b3c3ad208488e870a216784f2a3e6dbe2688c92f671c86"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76e2b14004cadb237499a8a068fd7a8b805b5c1fd0508530473e087c7dd25163"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c276a7eb3ae3360f5a2fc503f1e4535d4a2f1c8cfc22af4595ad752e9a94fd77"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71f7689c25bd7608e1e7a76a13138cb202455fac165018693a3e8e5675f54b82"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0505e2ca36408b754774a2bb20d93b5c7def3873406c13e1855de6f007f8a94"}, - {file = "y_py-0.6.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f143fdcda7a6a89bf96d9b359142a7ca3315e8a9018aa46b0abbdeb47d7192e"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:9a920bf096d1eecb0f30afc38ee56bfcb9e2c863c33db96fc9d30d4ac0dbee58"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:97812f9443fd846012d60ecacffa2a11992d02ad9f8618d4faae8e596736c646"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83115cbbd4f6d3b38ebe06d80b1d0dbf1b10e53947f71df16f6145a4f0d14716"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4cac9259839b32706336b3f521cacfd16fc7cefee609bd9c2b5123099328d696"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e76be7258010ce8cbb93a841f78f52901bba1253a51213d3535972d13aa4e89e"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a4b488be17d83173acb7f07c7e3430d2c66d0bd55b821683089311699562b58b"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b9f24b00972e5685d0b9bbd01413d9c33d124145343fb92667f0e076f040ad"}, - {file = "y_py-0.6.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:95083c4cdbd593497a695e841b2ad050c0b9a8a9e374f8496aa478cebfcf9cc9"}, - {file = "y_py-0.6.0.tar.gz", hash = "sha256:46836169f7dc2957df8513cfe4bc2009175b3a473e630af421a8e75ee1c48f98"}, + {file = "y_py-0.6.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:c26bada6cd109095139237a46f50fc4308f861f0d304bc9e70acbc6c4503d158"}, + {file = "y_py-0.6.2-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:bae1b1ad8d2b8cf938a60313f8f7461de609621c5dcae491b6e54975f76f83c5"}, + {file = "y_py-0.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e794e44fa260300b8850246c6371d94014753c73528f97f6ccb42f5e7ce698ae"}, + {file = "y_py-0.6.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2686d7d8ca31531458a48e08b0344a8eec6c402405446ce7d838e2a7e43355a"}, + {file = "y_py-0.6.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d917f5bc27b85611ceee4eb85f0e4088b0a03b4eed22c472409933a94ee953cf"}, + {file = "y_py-0.6.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f6071328aad06fdcc0a4acc2dc4839396d645f5916de07584af807eb7c08407"}, + {file = "y_py-0.6.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:266ec46ab9f9cb40fbb5e649f55c329fc4620fa0b1a8117bdeefe91595e182dc"}, + {file = "y_py-0.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce15a842c2a0bf46180ae136743b561fa276300dd7fa61fe76daf00ec7dc0c2d"}, + {file = "y_py-0.6.2-cp310-none-win32.whl", hash = "sha256:1d5b544e79ace93fdbd0b36ed329c86e346898153ac7ba2ec62bc9b4c6b745c9"}, + {file = "y_py-0.6.2-cp310-none-win_amd64.whl", hash = "sha256:80a827e173372682959a57e6b8cc4f6468b1a4495b4bc7a775ef6ca05ae3e8e8"}, + {file = "y_py-0.6.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:a21148b8ea09a631b752d975f9410ee2a31c0e16796fdc113422a6d244be10e5"}, + {file = "y_py-0.6.2-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:898fede446ca1926b8406bdd711617c2aebba8227ee8ec1f0c2f8568047116f7"}, + {file = "y_py-0.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce7c20b9395696d3b5425dccf2706d374e61ccf8f3656bff9423093a6df488f5"}, + {file = "y_py-0.6.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a3932f53418b408fa03bd002e6dc573a74075c2c092926dde80657c39aa2e054"}, + {file = "y_py-0.6.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df35ea436592eb7e30e59c5403ec08ec3a5e7759e270cf226df73c47b3e739f5"}, + {file = "y_py-0.6.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26cb1307c3ca9e21a3e307ab2c2099677e071ae9c26ec10ddffb3faceddd76b3"}, + {file = "y_py-0.6.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:863e175ce5585f9ff3eba2aa16626928387e2a576157f02c8eb247a218ecdeae"}, + {file = "y_py-0.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:35fcb9def6ce137540fdc0e91b08729677548b9c393c0151a6359fd199da3bd7"}, + {file = "y_py-0.6.2-cp311-none-win32.whl", hash = "sha256:86422c6090f34906c062fd3e4fdfdccf3934f2922021e979573ae315050b4288"}, + {file = "y_py-0.6.2-cp311-none-win_amd64.whl", hash = "sha256:6c2f2831c5733b404d2f2da4bfd02bb4612ae18d0822e14ae79b0b92436b816d"}, + {file = "y_py-0.6.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:7cbefd4f1060f05768227ddf83be126397b1d430b026c64e0eb25d3cf50c5734"}, + {file = "y_py-0.6.2-cp312-cp312-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:032365dfe932bfab8e80937ad6093b4c22e67d63ad880096b5fa8768f8d829ba"}, + {file = "y_py-0.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a70aee572da3994238c974694767365f237fc5949a550bee78a650fe16f83184"}, + {file = "y_py-0.6.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae80d505aee7b3172cdcc2620ca6e2f85586337371138bb2b71aa377d2c31e9a"}, + {file = "y_py-0.6.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a497ebe617bec6a420fc47378856caae40ab0652e756f3ed40c5f1fe2a12220"}, + {file = "y_py-0.6.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e8638355ae2f996356f7f281e03a3e3ce31f1259510f9d551465356532e0302c"}, + {file = "y_py-0.6.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8448da4092265142662bbd3fc46cb8b0796b1e259189c020bc8f738899abd0b5"}, + {file = "y_py-0.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:69cfbcbe0a05f43e780e6a198080ba28034bf2bb4804d7d28f71a0379bfd1b19"}, + {file = "y_py-0.6.2-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:1f798165158b76365a463a4f8aa2e3c2a12eb89b1fc092e7020e93713f2ad4dc"}, + {file = "y_py-0.6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92878cc05e844c8da937204bc34c2e6caf66709ce5936802fbfb35f04132892"}, + {file = "y_py-0.6.2-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9b8822a5c0fd9a8cffcabfcc0cd7326bad537ee614fc3654e413a03137b6da1a"}, + {file = "y_py-0.6.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e13cba03c7af8c8a846c4495875a09d64362cc4caeed495ada5390644411bbe7"}, + {file = "y_py-0.6.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82f2e5b31678065e7a7fa089ed974af5a4f076673cf4f414219bdadfc3246a21"}, + {file = "y_py-0.6.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1935d12e503780b859d343161a80df65205d23cad7b4f6c3df6e50321e188a3"}, + {file = "y_py-0.6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd302c6d46a3be57664571a5f0d4224646804be9890a01d73a0b294f2d3bbff1"}, + {file = "y_py-0.6.2-cp37-none-win32.whl", hash = "sha256:5415083f7f10eac25e1c434c87f07cb9bfa58909a6cad6649166fdad21119fc5"}, + {file = "y_py-0.6.2-cp37-none-win_amd64.whl", hash = "sha256:376c5cc0c177f03267340f36aec23e5eaf19520d41428d87605ca2ca3235d845"}, + {file = "y_py-0.6.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:3c011303eb2b360695d2bd4bd7ca85f42373ae89fcea48e7fa5b8dc6fc254a98"}, + {file = "y_py-0.6.2-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c08311db17647a47d4898fc6f8d9c1f0e58b927752c894877ff0c38b3db0d6e1"}, + {file = "y_py-0.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b7cafbe946b4cafc1e5709957e6dd5c6259d241d48ed75713ded42a5e8a4663"}, + {file = "y_py-0.6.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3ba99d0bdbd9cabd65f914cd07b4fb2e939ce199b54ae5ace1639ce1edf8e0a2"}, + {file = "y_py-0.6.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dab84c52f64e10adc79011a08673eb80286c159b14e8fb455524bf2994f0cb38"}, + {file = "y_py-0.6.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72875641a907523d37f4619eb4b303611d17e0a76f2ffc423b62dd1ca67eef41"}, + {file = "y_py-0.6.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c31240e30d5636ded02a54b7280aa129344fe8e964fd63885e85d9a8a83db206"}, + {file = "y_py-0.6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c28d977f516d4928f6bc0cd44561f6d0fdd661d76bac7cdc4b73e3c209441d9"}, + {file = "y_py-0.6.2-cp38-none-win32.whl", hash = "sha256:c011997f62d0c3b40a617e61b7faaaf6078e4eeff2e95ce4c45838db537816eb"}, + {file = "y_py-0.6.2-cp38-none-win_amd64.whl", hash = "sha256:ce0ae49879d10610cf3c40f4f376bb3cc425b18d939966ac63a2a9c73eb6f32a"}, + {file = "y_py-0.6.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:47fcc19158150dc4a6ae9a970c5bc12f40b0298a2b7d0c573a510a7b6bead3f3"}, + {file = "y_py-0.6.2-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:2d2b054a1a5f4004967532a4b82c6d1a45421ef2a5b41d35b6a8d41c7142aabe"}, + {file = "y_py-0.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0787e85645bb4986c27e271715bc5ce21bba428a17964e5ec527368ed64669bc"}, + {file = "y_py-0.6.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:17bce637a89f6e75f0013be68becac3e38dc082e7aefaf38935e89215f0aa64a"}, + {file = "y_py-0.6.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:beea5ad9bd9e56aa77a6583b6f4e347d66f1fe7b1a2cb196fff53b7634f9dc84"}, + {file = "y_py-0.6.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1dca48687f41efd862355e58b0aa31150586219324901dbea2989a506e291d4"}, + {file = "y_py-0.6.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17edd21eef863d230ea00004ebc6d582cc91d325e7132deb93f0a90eb368c855"}, + {file = "y_py-0.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:de9cfafe97c75cd3ea052a24cd4aabf9fb0cfc3c0f9f810f00121cdf123db9e4"}, + {file = "y_py-0.6.2-cp39-none-win32.whl", hash = "sha256:82f5ca62bedbf35aaf5a75d1f53b4457a1d9b6ff033497ca346e2a0cedf13d14"}, + {file = "y_py-0.6.2-cp39-none-win_amd64.whl", hash = "sha256:7227f232f2daf130ba786f6834548f2cfcfa45b7ec4f0d449e72560ac298186c"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0649a41cd3c98e290c16592c082dbe42c7ffec747b596172eebcafb7fd8767b0"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:bf6020560584671e76375b7a0539e0d5388fc70fa183c99dc769895f7ef90233"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cf817a72ffec4295def5c5be615dd8f1e954cdf449d72ebac579ff427951328"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c7302619fc962e53093ba4a94559281491c045c925e5c4defec5dac358e0568"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cd6213c3cf2b9eee6f2c9867f198c39124c557f4b3b77d04a73f30fd1277a59"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b4fac4ea2ce27b86d173ae45765ced7f159120687d4410bb6d0846cbdb170a3"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:932abb560fe739416b50716a72ba6c6c20b219edded4389d1fc93266f3505d4b"}, + {file = "y_py-0.6.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e42258f66ad9f16d9b62e9c9642742982acb1f30b90f5061522048c1cb99814f"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cfc8381df1f0f873da8969729974f90111cfb61a725ef0a2e0e6215408fe1217"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:613f83713714972886e81d71685403098a83ffdacf616f12344b52bc73705107"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:316e5e1c40259d482883d1926fd33fa558dc87b2bd2ca53ce237a6fe8a34e473"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:015f7f6c1ce8a83d57955d1dc7ddd57cb633ae00576741a4fc9a0f72ed70007d"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff32548e45e45bf3280ac1d28b3148337a5c6714c28db23aeb0693e33eba257e"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f2d881f0f8bf5674f8fe4774a438c545501e40fa27320c73be4f22463af4b05"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3bbe2f925cc587545c8d01587b4523177408edd252a32ce6d61b97113fe234d"}, + {file = "y_py-0.6.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f5c14d25611b263b876e9ada1701415a13c3e9f02ea397224fbe4ca9703992b"}, + {file = "y_py-0.6.2.tar.gz", hash = "sha256:4757a82a50406a0b3a333aa0122019a331bd6f16e49fed67dca423f928b3fd4d"}, ] [[package]] name = "ypy-websocket" version = "0.8.4" description = "WebSocket connector for Ypy" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4239,7 +4069,6 @@ test = ["mypy", "pre-commit", "pytest", "pytest-asyncio", "websockets (>=10.0)"] name = "zict" version = "2.2.0" description = "Mutable mapping tools" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4254,7 +4083,6 @@ heapdict = "*" name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4268,5 +4096,5 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" -python-versions = ">=3.7.1,<3.12" # When deploying set this to 3.7 -content-hash = "9a861cc02af85c23e4c8ac66ca87c2e324012cdec6e5135d8ece226561f4a830" +python-versions = ">=3.7.1,<3.12" +content-hash = "6958197e6f6defb1de0475b9229b0f52cce04b05f8a5e2ed9313e8aa848d07e9" diff --git a/pyproject.toml b/pyproject.toml index adc43e75..90bad2ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ memory-profiler = "^0.58.0" pytest = "^6.2.3" pytest-cov = "^2.12.1" pytest-benchmark = "^4.0.0" -pytest-codspeed = "^2.0.1" +pytest-codspeed = "^2.2" pdoc3 = "^0.9.2" scipy = [ { version = "^1.7.3", python = "<3.11" }, @@ -47,7 +47,7 @@ tsfresh = "^0.20.0" tsfel = "^0.1.4" #fastparquet = "0.8.0" # Lock to this version to resolve issue on macos with python 3.7 pyarrow = "^12.0.0" -pycatch22 = "^0.4.2" +pycatch22 = "0.4.2" # Temporarily lock this version to avoid Windows install error antropy = [ { version = "^0.1.5", python = "<3.8" }, { version = ">=0.1.6", python = ">=3.8" } @@ -79,9 +79,14 @@ ignore = ["E501"] # Never enforce `E501` (line length violations). "tests/test_stroll_factory.py" = ["F401", "F811"] "tests/test_utils.py" = ["F401", "F811"] +# Testing +[tool.pytest.ini_options] +addopts = "--cov=tsflex --cov-report=term-missing --benchmark-disable" +testpaths = "tests/" + # Formatting [tool.black] -color = true +color = false line-length = 88 [build-system] diff --git a/tests/benchmarks/test_featurecollection.py b/tests/benchmarks/test_featurecollection.py index ba59a007..71232e83 100644 --- a/tests/benchmarks/test_featurecollection.py +++ b/tests/benchmarks/test_featurecollection.py @@ -6,7 +6,7 @@ from tsflex.features.feature import FeatureDescriptor, MultipleFeatureDescriptors from tsflex.features.feature_collection import FeatureCollection -from ..utils import dummy_data # noqa: F401 +from ..utils import dummy_data, dummy_group_data # noqa: F401 FUNCS = [np.sum, np.min, np.max, np.mean, np.median, np.std, np.var] MAX_CPUS = os.cpu_count() or 2 @@ -50,3 +50,17 @@ def test_single_series_feature_collection_multiple_descriptors( fc = FeatureCollection(mfd) benchmark(fc.calculate, dummy_data, n_jobs=n_cores) + + +@pytest.mark.benchmark(group="group_by collection") +@pytest.mark.parametrize("n_cores", NB_CORES) +@pytest.mark.parametrize("func", FUNCS) +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_single_series_feature_collection_group_by_consecutive( + benchmark, n_cores, func, group_by, dummy_group_data # noqa: F811 +): + fd = FeatureDescriptor(function=func, series_name="number_sold") + + fc = FeatureCollection(feature_descriptors=fd) + + benchmark(fc.calculate, dummy_group_data, n_jobs=n_cores, **{group_by: "store"}) diff --git a/tests/test_features_feature_collection.py b/tests/test_features_feature_collection.py index ea931dc8..0546c3aa 100644 --- a/tests/test_features_feature_collection.py +++ b/tests/test_features_feature_collection.py @@ -24,11 +24,462 @@ ) from tsflex.utils.data import flatten -from .utils import dummy_data +from .utils import dummy_data, dummy_group_data # noqa: F401 ## FeatureCollection +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_single_series_group_by_feature_collection(dummy_group_data, group_by): + fd = FeatureDescriptor( + function=sum, + series_name="number_sold", + ) + + fc = FeatureCollection(feature_descriptors=fd) + + assert fc.get_required_series() == ["number_sold"] + assert fc.get_nb_output_features() == 1 + res_list = fc.calculate(dummy_group_data, return_df=False, **{group_by: "store"}) + res_df = fc.calculate(dummy_group_data, return_df=True, **{group_by: "store"}) + + assert isinstance(res_list, list) + assert isinstance(res_df, pd.DataFrame) + + concatted_df = pd.concat(res_list, axis=1) + + assert_frame_equal(concatted_df, res_df) + + data_counts = dummy_group_data.groupby("store")["number_sold"].sum() + if "consecutive" in group_by: # group_by_consecutive + result_data_counts = res_df.groupby("store")["number_sold__sum__w=manual"].sum() + else: # group_by_all + result_data_counts = res_df["number_sold__sum__w=manual"] + + for index in data_counts.index: + assert data_counts[index] == result_data_counts[index] + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_group_by_feature_collection_with_warnings(dummy_group_data, group_by): + fd = FeatureDescriptor( + function=sum, + series_name="number_sold", + ) + + fc = FeatureCollection(feature_descriptors=fd) + + assert fc.get_required_series() == ["number_sold"] + assert fc.get_nb_output_features() == 1 + + with warnings.catch_warnings(record=True) as w: + # Trigger the warning + # Note -> for some (yet unkknown) reason, the warning's aren't caught anymore + # when using multiprocess (they are thrown nevertheless!), so we changed + # n_jobs=1 + res_df = fc.calculate( + dummy_group_data, + n_jobs=1, + stride=5, + segment_start_idxs=[0], + segment_end_idxs=[0], + window_idx="start", + include_final_window=True, + return_df=True, + **{group_by: "store"}, + ) + # Verify the warning + assert len(w) == 5 + assert all([issubclass(warn.category, UserWarning) for warn in w]) + assert all( + [ + "will be ignored in case of GroupBy feature calculation." in str(warn) + for warn in w + ] + ) + # Check the output + assert isinstance(res_df, pd.DataFrame) + + data_counts = dummy_group_data.groupby("store")["number_sold"].sum() + if "consecutive" in group_by: # group_by_consecutive + result_data_counts = res_df.groupby("store")["number_sold__sum__w=manual"].sum() + else: # group_by_all + result_data_counts = res_df["number_sold__sum__w=manual"] + + for index in data_counts.index: + assert data_counts[index] == result_data_counts[index] + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_single_series_group_feature_non_existent_group_by( + dummy_group_data, + group_by, +): + fd = FeatureDescriptor( + function=sum, + series_name="count", + ) + + fc = FeatureCollection(feature_descriptors=fd) + + assert fc.get_required_series() == ["count"] + assert fc.get_nb_output_features() == 1 + with pytest.raises(Exception): + fc.calculate(dummy_group_data, return_df=False, **{group_by: "non_existent"}) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +@pytest.mark.parametrize("n_jobs", [1, 3]) +def test_single_series_multiple_features_group_by(dummy_group_data, group_by, n_jobs): + fd1 = FeatureDescriptor(function=np.sum, series_name="number_sold") + fd2 = FeatureDescriptor(function=np.min, series_name="number_sold") + fd3 = FeatureDescriptor(function=np.max, series_name="number_sold") + + fc = FeatureCollection(feature_descriptors=[fd1, fd2, fd3]) + + assert fc.get_required_series() == ["number_sold"] + assert fc.get_nb_output_features() == 3 + + res_list = fc.calculate( + dummy_group_data, return_df=False, n_jobs=n_jobs, **{group_by: "store"} + ) + res_df = fc.calculate( + dummy_group_data, return_df=True, n_jobs=n_jobs, **{group_by: "store"} + ) + + assert isinstance(res_list, list) + assert isinstance(res_df, pd.DataFrame) + + concatted_df = pd.concat(res_list, axis=1) + assert len(concatted_df.columns) == len(res_df.columns) + concatted_df = concatted_df[res_df.columns] # assure column order is the same + + assert_frame_equal(concatted_df, res_df) + + data_count_sum = dummy_group_data.groupby("store")["number_sold"].sum() + data_count_min = dummy_group_data.groupby("store")["number_sold"].min() + data_count_max = dummy_group_data.groupby("store")["number_sold"].max() + + grouped_res_df_sum = ( + res_df.reset_index().groupby("store")["number_sold__sum__w=manual"].sum() + ) + grouped_res_df_min = ( + res_df.reset_index().groupby("store")["number_sold__amin__w=manual"].min() + ) + grouped_res_df_max = ( + res_df.reset_index().groupby("store")["number_sold__amax__w=manual"].max() + ) + + def assert_results(data, res_data): + for index in data.index: + assert data[index] == res_data[index] + + assert_results(data_count_sum, grouped_res_df_sum) + assert_results(data_count_min, grouped_res_df_min) + assert_results(data_count_max, grouped_res_df_max) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_multiple_series_multiple_features_group_by(dummy_group_data, group_by): + def sum_2(x: np.ndarray, y: np.ndarray) -> float: + return np.sum(x) + np.sum(y) + + fd1 = FeatureDescriptor(function=np.sum, series_name="number_sold") + fd2 = FeatureDescriptor(function=np.sum, series_name="product") + fd3 = FeatureDescriptor(function=sum_2, series_name=("number_sold", "product")) + + fc = FeatureCollection(feature_descriptors=[fd1, fd2, fd3]) + + assert set(fc.get_required_series()) == set(["number_sold", "product"]) + assert fc.get_nb_output_features() == 3 + + res_list = fc.calculate( + dummy_group_data, return_df=False, n_jobs=1, **{group_by: "store"} + ) + res_df = fc.calculate( + dummy_group_data, return_df=True, n_jobs=1, **{group_by: "store"} + ) + + assert isinstance(res_list, list) + assert isinstance(res_df, pd.DataFrame) + + concatted_df = pd.concat(res_list, axis=1) + assert len(concatted_df.columns) == len(res_df.columns) + concatted_df = concatted_df[res_df.columns] # assure column order is the same + + assert_frame_equal(concatted_df, res_df) + + assert all( + res_df["number_sold__sum__w=manual"].values + + res_df["product__sum__w=manual"].values + == res_df["number_sold|product__sum_2__w=manual"].values + ) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_group_by_with_nan_values(dummy_group_data, group_by): + fd = FeatureDescriptor( + function=np.sum, + series_name="number_sold", + ) + + nan_dummy_group_data = dummy_group_data.copy(deep=True) + for random_idx in np.random.randint(0, len(dummy_group_data.index), size=1000): + nan_dummy_group_data["store"].iloc[random_idx] = np.nan + + fc = FeatureCollection(feature_descriptors=fd) + + assert fc.get_required_series() == ["number_sold"] + assert fc.get_nb_output_features() == 1 + res_list = fc.calculate( + nan_dummy_group_data, return_df=False, **{group_by: "store"} + ) + res_df = fc.calculate(nan_dummy_group_data, return_df=True, **{group_by: "store"}) + + assert isinstance(res_list, list) + assert isinstance(res_df, pd.DataFrame) + + concatted_df = pd.concat(res_list, axis=1) + assert len(concatted_df.columns) == len(res_df.columns) + concatted_df = concatted_df[res_df.columns] # assure column order is the same + + assert_frame_equal(concatted_df, res_df) + + assert ( + dummy_group_data["number_sold"].sum() + > res_df["number_sold__sum__w=manual"].sum() + ) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_group_by_with_unequal_lengths(group_by): + fd1 = FeatureDescriptor(function=np.sum, series_name="count") + fd2 = FeatureDescriptor(function=np.nansum, series_name="count") + + fc = FeatureCollection(feature_descriptors=[fd1, fd2]) + + # create the dummy data + s_group = pd.Series( + index=pd.date_range("2018-01-01", freq="10m", periods=30), + name="user_id", + data=["a"] * 10 + + ["b"] * 2 + + ["c"] + + ["d"] * 2 + + [None] * 3 + + ["e"] * 10 + + ["b"] * 2, + ) + s_group2 = pd.Series( + index=pd.date_range("2018-01-01", freq="10m", periods=100), + name="user_id", + data=( + ["a"] * 10 + + ["b"] * 2 + + ["c"] + + ["d"] * 2 + + [None] * 3 + + ["e"] * 10 + + ["b"] * 2 + + ["f"] * 14 + + ["b"] * 9 + + [None] * 7 + + ["a"] * 23 + + ["e"] * 17 + ), + ) + s_val = pd.Series( + index=pd.date_range("2018-01-01", freq="10m", periods=100), + data=np.arange(100), + name="count", + ) + s_val2 = pd.Series( + index=pd.date_range("2018-01-01", freq="10m", periods=30), + data=np.arange(30), + name="count", + ) + res_list = fc.calculate( + [s_group, s_val], return_df=True, n_jobs=1, **{group_by: "user_id"} + ) + res_list2 = fc.calculate( + [s_group2, s_val2], return_df=True, n_jobs=1, **{group_by: "user_id"} + ) + correct_res_list = fc.calculate( + [s_group, s_val2], return_df=True, n_jobs=1, **{group_by: "user_id"} + ) + + for c in res_list.columns: + # compare (compare_col) only with nan-safe col in case of group_by_all + compare_col = c if "consecutive" in group_by else "count__nansum__w=manual" + assert np.all( + res_list[c] + == res_list2.loc[res_list.index, compare_col].astype(res_list.dtypes[c]) + ) + assert_frame_equal(res_list, correct_res_list) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_group_by_non_aligned_indices(group_by): + fd = FeatureDescriptor(function=np.nansum, series_name="count") + fc = FeatureCollection(feature_descriptors=fd) + + # create the dummy data + s_group = pd.Series( + index=pd.date_range("2018-01-01", freq="10m", periods=30), + name="user_id", + data=["a"] * 10 + ["b"] * 2 + ["c"] + ["d"] * 2 + [None] * 3 + ["e"] * 12, + ) + s_val = pd.Series( + index=pd.date_range("2018-01-01", freq="3m", periods=100), + data=np.arange(100), + name="count", + ) + df = pd.DataFrame({"groups": s_group, "values": s_val}) + non_nan_df = df.loc[df["groups"].notna() & df["values"].notna()] + res_list = fc.calculate( + [s_group, s_val], return_df=True, **{group_by: "user_id"} + ).reset_index() + grouped_non_nan_df_sums = non_nan_df.groupby("groups").sum() + + new_res_list = pd.DataFrame( + {"groups": res_list["user_id"], "values": res_list["count__nansum__w=manual"]} + ) + new_res_list = new_res_list.set_index("groups") + + assert_frame_equal( + new_res_list.loc[grouped_non_nan_df_sums.index], grouped_non_nan_df_sums + ) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_group_by_with_numeric_index(group_by): + fd = FeatureDescriptor(function=np.nansum, series_name="count") + fc = FeatureCollection(feature_descriptors=fd) + + s_group = pd.Series( + index=np.arange(40), + name="user_id", + data=["a"] * 10 + + ["b"] * 2 + + ["c"] + + ["d"] * 2 + + [None] * 3 + + ["e"] * 12 + + ["a"] * 5 + + [None] * 2 + + ["a"] * 3, + ) + + s_val = pd.Series( + index=np.arange(30), + data=np.arange(30), + name="count", + ) + + res_df = fc.calculate([s_group, s_val], return_df=True, **{group_by: "user_id"}) + res_list = fc.calculate([s_group, s_val], return_df=False, **{group_by: "user_id"}) + assert isinstance(res_list, list) + assert isinstance(res_df, pd.DataFrame) + + concatted_df = pd.concat(res_list, axis=1) + + assert_frame_equal(concatted_df, res_df) + + s_df = pd.DataFrame({"groups": s_group, "values": s_val}) + + data_counts = s_df.groupby("groups")["values"].sum() + result_data_counts = res_df.groupby("user_id")["count__nansum__w=manual"].sum() + + for index in data_counts.index: + assert data_counts[index] == result_data_counts[index] + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_failing_function_group_by(dummy_group_data, group_by): + def failing_func(_): + raise RuntimeError() + + fd = FeatureDescriptor( + function=failing_func, + series_name="number_sold", + ) + + fc = FeatureCollection(feature_descriptors=fd) + + assert fc.get_required_series() == ["number_sold"] + assert fc.get_nb_output_features() == 1 + with pytest.raises(RuntimeError): + fc.calculate(dummy_group_data, return_df=True, **{group_by: "store"}) + + +def test_group_by_all_subcall(): + s_val = pd.Series( + index=np.arange(40), + name="user_id", + data=["a"] * 10 + + ["b"] * 2 + + ["c"] + + ["d"] * 2 + + [None] * 3 + + ["e"] * 12 + + ["a"] * 5 + + [None] * 2 + + ["a"] * 3, + ) + + expected = s_val.to_frame().groupby("user_id") + + res = FeatureCollection._group_by_all({"user_id": s_val}, "user_id") + assert isinstance(res, pd.core.groupby.DataFrameGroupBy) + + # check for equal indices and keys + assert len(res.indices.keys()) == len(expected.indices.keys()) + for key in res.indices.keys(): + assert key in expected.indices.keys() + assert len(res.indices[key]) == len(expected.indices[key]) + + +def test_group_by_consecutive_subcall(): + s_val = pd.Series( + index=np.arange(40), + name="user_id", + data=["a"] * 10 + + ["b"] * 2 + + ["c"] + + ["d"] * 2 + + [None] * 3 + + ["e"] * 12 + + ["a"] * 5 + + [None] * 2 + + ["a"] * 3, + ) + + expected_df = pd.DataFrame( + { + "start": [0, 10, 12, 13, 18, 30], + "end": [9, 11, 12, 14, 29, 39], + "user_id": ["a", "b", "c", "d", "e", "a"], + } + ) + + res = FeatureCollection._group_by_consecutive(s_val) + assert_frame_equal(res, expected_df) + + +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_groupby_multiple_window_sizes_error(dummy_group_data, group_by): + fc = FeatureCollection( + MultipleFeatureDescriptors( + functions=[np.sum, np.min], + series_names=["number_sold"], + windows=["5D", "10D"], + ) + ) + + with pytest.raises(Exception): + fc.calculate(dummy_group_data, return_df=True, **{group_by: "store"}) + + def test_single_series_feature_collection(dummy_data): fd = FeatureDescriptor( function=np.sum, @@ -515,6 +966,44 @@ def test_time_segment_start_and_end_idxs_empty_array(): assert np.all(res["dummy__len__w=manual"] == []) +def test_sequence_segment_start_and_end_idxs_no_multiple_windows(): + s = pd.Series(np.arange(20), name="dummy") + segment_start_idxs = [0, 5, 3, 3] + segment_end_idxs = [5, 10, 8, 5] + + fc = FeatureCollection( + MultipleFeatureDescriptors([np.min], "dummy", windows=[3, 5]) + ) + # this should all pass + _ = fc.calculate(s, stride=5) + _ = fc.calculate(s, segment_start_idxs=segment_start_idxs) + _ = fc.calculate(s, segment_end_idxs=segment_end_idxs) + + with pytest.raises(Exception): + # Should only fail when both are provided + _ = fc.calculate( + s, segment_start_idxs=segment_start_idxs, segment_end_idxs=segment_end_idxs + ) + + +def test_time_segment_start_and_end_idxs_no_multiple_windows(): + s = pd.Series(np.arange(20), name="dummy") + s.index = pd.date_range("2021-08-09", freq="1h", periods=20) + segment_start_idxs = s.index[[0, 5, 3, 3]] + segment_end_idxs = s.index[[5, 10, 8, 5]] + + fc = FeatureCollection(MultipleFeatureDescriptors([np.min], "dummy", ["3h", "5h"])) + _ = fc.calculate(s, stride="5h") + _ = fc.calculate(s, segment_start_idxs=segment_start_idxs) + _ = fc.calculate(s, segment_end_idxs=segment_end_idxs) + + with pytest.raises(Exception): + # Should only fail when both are provided + _ = fc.calculate( + s, segment_start_idxs=segment_start_idxs, segment_end_idxs=segment_end_idxs + ) + + def test_sequence_segment_start_or_end_idxs_of_wrong_dtype(): s = pd.Series(np.arange(20), name="dummy") wrong_segment_idx = pd.date_range("2021-08-09", freq="1h", periods=20)[5:9] diff --git a/tests/test_features_logging.py b/tests/test_features_logging.py index 9118b880..00bb2dff 100644 --- a/tests/test_features_logging.py +++ b/tests/test_features_logging.py @@ -6,6 +6,7 @@ import warnings import numpy as np +import pytest from tsflex.features import ( FeatureCollection, @@ -17,7 +18,7 @@ ) from tsflex.utils.data import flatten -from .utils import dummy_data, logging_file_path +from .utils import dummy_data, dummy_group_data, logging_file_path test_path = os.path.abspath(os.path.dirname(__file__)) @@ -651,6 +652,96 @@ def test_simple_features_logging_segment_start_and_end_idxs_overrule_stride_and_ assert all(series_names_df["duration %"]["mean"] > 0) +@pytest.mark.parametrize("group_by", ["group_by_all", "group_by_consecutive"]) +def test_simple_features_logging_groupby(dummy_group_data, logging_file_path, group_by): + dummy_data = dummy_group_data.reset_index(drop=True) + fd = FeatureDescriptor( + function=np.sum, + series_name="number_sold", + window=50, + stride=120, + ) + fc = FeatureCollection(feature_descriptors=fd) + fc.add( + MultipleFeatureDescriptors( + np.min, series_names=["product", "number_sold"], windows=50, strides=20 + ) + ) + for fd in flatten(fc._feature_desc_dict.values()): + assert fd.stride is not None + + assert set(fc.get_required_series()) == set(["number_sold", "product"]) + assert len(fc.get_required_series()) == 2 + + assert not os.path.exists(logging_file_path) + + # Sequential (n_jobs <= 1), otherwise file_path gets cleared + _ = fc.calculate( + dummy_data, logging_file_path=logging_file_path, n_jobs=1, **{group_by: "store"} + ) + + assert os.path.exists(logging_file_path) + logging_df = get_feature_logs(logging_file_path) + + assert all( + logging_df.columns.values + == [ + "log_time", + "function", + "series_names", + "window", + "stride", + "output_names", + "duration", + "duration %", + ] + ) + + assert len(logging_df) == 3 + assert logging_df.select_dtypes(include=[np.datetime64]).columns.values == [ + "log_time" + ] + assert logging_df.select_dtypes(include=[np.timedelta64]).columns.values == [ + "duration" + ] + + assert np.isclose(logging_df["duration %"].sum(), 100, atol=0.5) + + assert set(logging_df["function"].values) == set(["amin", "sum"]) + assert set(logging_df["series_names"].values) == set( + ["(number_sold,)", "(product,)"] + ) + assert set(logging_df["output_names"].values) == set( + [ + "number_sold__sum__w=manual", + "number_sold__amin__w=manual", + "product__amin__w=manual", + ] + ) + assert all(logging_df["window"] == "manual") + assert all(logging_df["stride"] == "manual") + + function_stats_df = get_function_stats(logging_file_path) + assert len(function_stats_df) == 2 + assert set(function_stats_df.index) == set( + [(s, "manual", "manual") for s in ["sum", "amin"]] + ) + assert all(function_stats_df["duration"]["mean"] > 0) + assert function_stats_df["duration"]["count"].sum() == 3 + assert np.isclose(function_stats_df["duration %"]["sum"].sum(), 100, atol=0.5) + assert all(function_stats_df["duration %"]["mean"] > 0) + + series_names_df = get_series_names_stats(logging_file_path) + assert len(series_names_df) == 2 + assert set(series_names_df.index) == set( + [(s, "manual", "manual") for s in ["(number_sold,)", "(product,)"]] + ) + assert all(series_names_df["duration"]["mean"] > 0) + assert series_names_df["duration"]["count"].sum() == 3 + assert np.isclose(series_names_df["duration %"]["sum"].sum(), 100, atol=0.5) + assert all(series_names_df["duration %"]["mean"] > 0) + + def test_file_warning_features_logging(dummy_data, logging_file_path): fd = FeatureDescriptor( function=np.sum, diff --git a/tests/utils.py b/tests/utils.py index 3e1e5e9c..620f5ac4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -24,6 +24,17 @@ def dummy_data() -> pd.DataFrame: return df +@pytest.fixture +def dummy_group_data() -> pd.DataFrame: + df = pd.read_parquet(proj_dir + "/examples/data/grouped_data.parquet") + df.set_index("Date", inplace=True) + df = df.sort_index() + df.set_index( + pd.date_range("2019-01-01", periods=len(df.index), freq="D"), inplace=True + ) + return df + + @pytest.fixture def logging_file_path() -> str: logging_path = proj_dir + "/tests/logging.log" diff --git a/tsflex/features/feature_collection.py b/tsflex/features/feature_collection.py index b4ed870a..c6a225e1 100644 --- a/tsflex/features/feature_collection.py +++ b/tsflex/features/feature_collection.py @@ -12,7 +12,9 @@ __author__ = "Jonas Van Der Donckt, Emiel Deprost, Jeroen Van Der Donckt" +import logging import os +import time import traceback import uuid from copy import deepcopy @@ -23,6 +25,7 @@ import numpy as np import pandas as pd from multiprocess import Pool +from pandas.api.types import is_datetime64_any_dtype from tqdm.auto import tqdm from ..features.function_wrapper import FuncWrapper @@ -33,7 +36,12 @@ from .feature import FeatureDescriptor, MultipleFeatureDescriptors from .logger import logger from .segmenter import StridedRolling, StridedRollingFactory -from .utils import _check_start_end_array, _determine_bounds +from .utils import ( + _check_start_end_array, + _determine_bounds, + _log_func_execution, + _process_func_output, +) class FeatureCollection: @@ -139,6 +147,9 @@ def _get_nb_output_features_without_window(self) -> int: ) ) + def _get_nb_feat_funcs(self) -> int: + return sum(map(len, self._feature_desc_dict.values())) + @staticmethod def _get_collection_key( feature: FeatureDescriptor, @@ -260,13 +271,87 @@ def add( self._check_feature_descriptors(skip_none=True) @staticmethod - def _executor(idx: int): - # global get_stroll_func + def _executor_stroll(idx: int) -> pd.DataFrame: + """Executor function for the StridedRolling.apply_func method. + + Strided rolling feature calculation occurs when either; + - a `window` and `stride` argument are stored in the `FeatureDescriptor` object + - the `window` is stored in the `FeatureDescriptor` object and the `stride` + argument is passed to the `calculate` method, potentially overriding the + `stride` + - segment indices are passed to the `calculate` method + - a `group_by_consecutive` argument is passed to the `calculate` method (since + we calculate the segment indices for the consecutive groups) + + This method uses the global `get_stroll_func` function, which returns the + StridedRolling object and the function that needs to be applied to the + StridedRolling object. Using a global function is necessary to facilitate + multiprocessing. + """ + # Uses the global get_stroll_func stroll, function = get_stroll_func(idx) - return stroll.apply_func(function) + return stroll.apply_func(function) # execution time is logged in apply_func + + @staticmethod + def _executor_grouped(idx: int) -> pd.DataFrame: + """Executor function for grouped feature calculation. + + Grouped feature calculation occurs when either; + - a `group_by_all` argument is passed to the `calculate` method + - a `DataFrameGroupBy` is passed as `data` argument to the `calculate` method + + Note that passing a `group_by_consecutive` argument to the `calculate` method + will not use this executor function, but will use the `_executor_stroll` as + executor function (since we calculate the segment indices for the consecutive + groups). + + This method uses the global `get_group_func` function, which returns a + pd.DataFrame (containing only the necessary data for the function) and the + function that needs to be applied to the pd.DataFrame. In addition, the global + `group_indices` and `group_id_name` are used to access the grouped data and the + group id name respectively. Using a global function is necessary to facilitate + multiprocessing. + """ + # Uses the global get_group_func, group_indices, and group_id_name + data, function = get_group_func(idx) + group_ids = group_indices.keys() # group_ids are the keys of the group_indices + cols_tuple = tuple(data.columns.values) + + t_start = time.perf_counter() + + # Wrap the function to handle multiple inputs and convert the inputs to numpy + # array if necessary + f = function + if function.input_type is np.array: + + def f(x: pd.DataFrame): + # pass the inputs as positional arguments of numpy array type + return function(*[x[c].values for c in cols_tuple]) + + else: # function.input_type is pd.Series - # def _get_stroll(self, kwargs): - # return StridedRollingFactory.get_segmenter(**kwargs) + def f(x: pd.DataFrame): + # pass the inputs as positional arguments of pd.Series type + return function(*[x[c] for c in cols_tuple]) + + # Function execution over the grouped data (accessed by using the group_indices) + out = np.array(list(map(f, [data.iloc[idx] for idx in group_indices.values()]))) + + # Aggregate function output in a dictionary + output_names = [ + StridedRolling.construct_output_index( + cols_tuple, feat_name, win_str="manual" + ) + for feat_name in function.output_names + ] + feat_out = _process_func_output(out, group_ids, output_names, str(function)) + + # Log the function execution time + _log_func_execution( + t_start, function, cols_tuple, "manual", "manual", output_names + ) + + return pd.DataFrame(feat_out, index=group_ids).rename_axis(index=group_id_name) def _stroll_feat_generator( self, @@ -316,20 +401,75 @@ def get_stroll_function(idx) -> Tuple[StridedRolling, FuncWrapper]: return get_stroll_function - def _get_stroll_feat_length(self) -> int: - return sum( - len(self._feature_desc_dict[k]) for k in self._feature_desc_dict.keys() - ) + def _group_feat_generator( + self, + grouped_df: pd.api.typing.DataFrameGroupBy, + ) -> Callable[[int], Tuple[pd.api.typing.DataFrameGroupBy, FuncWrapper,],]: + """Return a function that returns the necessary columns of the grouped data and + the function that needs to be applied to the grouped data. + + Note that the function does not return groups, but rather the necessary columns + of the grouped data (i.e. the data on which the function needs to be applied). + To access the groups, the global `group_indices` and `group_id_name` are used. + """ + keys_wins = list(self._feature_desc_dict.keys()) + lengths = np.cumsum([len(self._feature_desc_dict[k]) for k in keys_wins]) + + def get_group_function( + idx, + ) -> Tuple[pd.api.typing.DataFrameGroupBy, FuncWrapper,]: + key_idx = np.searchsorted(lengths, idx, "right") # right bc idx starts at 0 + key, win = keys_wins[key_idx] + + feature = self._feature_desc_dict[keys_wins[key_idx]][ + idx - lengths[key_idx] + ] + function: FuncWrapper = feature.function + return grouped_df.obj[list(key)], function - def _check_no_multiple_windows(self): + return get_group_function + + def _check_no_multiple_windows(self, error_case: str): + """Check whether there are no multiple windows in the feature collection. + + Parameters + ---------- + error_case : str + The case in which no multiple windows are allowed. + + """ assert ( self._get_nb_output_features_without_window() == self.get_nb_output_features() ), ( - "When using `segment_XXX_idxs`; each output name - series_input combination" - + " can only have 1 window (or None)" + error_case + + "; each output name - series_input combination can only have 1 window" + + " (or None)" ) + @staticmethod + def _data_to_series_dict( + data: Union[pd.DataFrame, pd.Series, List[Union[pd.Series, pd.DataFrame]]], + required_series: List[str], + ) -> Dict[str, pd.Series]: + series_dict: Dict[str, pd.Series] = {} + for s in to_series_list(data): + if not s.index.is_monotonic_increasing: + warnings.warn( + f"The index of series '{s.name}' is not monotonic increasing. " + + "The series will be sorted by the index.", + RuntimeWarning, + ) + s = s.sort_index(ascending=True, inplace=False, ignore_index=False) + + # Assert the assumptions we make! + assert s.index.is_monotonic_increasing + + if s.name in required_series: + series_dict[str(s.name)] = s + + return series_dict + @staticmethod def _process_segment_idxs( segment_idxs: Union[list, np.ndarray, pd.Series, pd.Index] @@ -341,9 +481,357 @@ def _process_segment_idxs( segment_idxs = segment_idxs.squeeze() # remove singleton dimensions return segment_idxs - def calculate( + @staticmethod + def _group_by_all( + series_dict: Dict[str, pd.Series], col_name: str = None + ) -> pd.api.typing.DataFrameGroupBy: + """Group all `column_name` values and return the grouped data. + + GroupBy ignores all rows with NaN values for the column on which we group. + + Parameters + ---------- + series_dict : Dict[str, pd.Series] + Input data. + col_name : str + The column name on which the grouping will need to take place. + + Returns + ------- + pd.api.typing.DataFrameGroupBy + A `DataFrameGroupBy` object, with the group names as keys and the indices + as values. + + """ + df = pd.DataFrame(series_dict) + assert col_name in df.columns + + # Check if there are nan values in the column on which we group + if df[col_name].isna().any(): + warnings.warn( + f"NaN values were found in the column '{col_name}' (when expanding the " + + f"data to a pd.DataFrame which contains {df.columns}. " + + "Rows with NaN values for the grouping column will be ignored.", + RuntimeWarning, + ) + + # GroupBy ignores all rows with NaN values for the column on which we group + return df.groupby(col_name) + + def _calculate_group_by_all( + self, + grouped_data: pd.api.typing.DataFrameGroupBy, + return_df: Optional[bool], + show_progress: Optional[bool], + n_jobs: Optional[int], + f_handler: Optional[logging.FileHandler], + ) -> Union[List[pd.DataFrame], pd.DataFrame]: + """Calculate features on each group of the grouped data. + + Parameters + ---------- + grouped_data : pd.api.typing.DataFrameGroupBy + The grouped data. + return_df: bool, optional + Whether the output needs to be a DataFrame or a list thereof. + show_progress: bool, optional + Whether to show a progress bar. + n_jobs: int, optional + The number of jobs to run in parallel. + f_handler: logging.FileHandler, optional + The file handler that is used to log the function execution times. + + .. Note:: + Is comparable to following pseudo-SQL code: + ```sql + SELECT func(x) + FROM `data` + GROUP BY ... + ``` + where `func` is the FeatureDescriptor function and `x` is the name + on which the FeatureDescriptor operates. The group by is already done by + passing a `DataFrameGroupBy` object to this method. + """ + global group_indices, group_id_name, get_group_func + group_indices = grouped_data.indices # dict - group_id as key; indices as value + group_id_name = grouped_data.grouper.names # name of the group col(s) + get_group_func = self._group_feat_generator(grouped_data) + + return self._calculate_feature_list( + self._executor_grouped, n_jobs, show_progress, return_df, f_handler + ) + + @staticmethod + def _group_by_consecutive( + df: Union[pd.Series, pd.DataFrame], col_name: str = None + ) -> pd.DataFrame: + """Group consecutive `col_name` values in a single DataFrame. + + This is especially useful if you want to represent sparse data in a more + compact format. + + Parameters + ---------- + df : Union[pd.Series, pd.DataFrame] + Input data. + col_name : str, optional + If a dataFrame is passed, you will need to specify the `col_name` on which + the consecutive-grouping will need to take place. + + Returns + ------- + pd.DataFrame + A new `DataFrame` view, with columns: + [`start`, `end`, `col_name`], representing the + start- and endtime of the consecutive range, and the col_name's consecutive + values. + """ + if type(df) == pd.Series: + col_name = df.name + df = df.to_frame() + + assert col_name in df.columns + assert col_name not in [ + "start", + "end", + ], "Grouping column cannot be 'start' or 'end'" + + # Check if there are nan values in the column on which we group + if df[col_name].isna().any(): + warnings.warn( + f"NaN values were found in the column '{col_name}' (when expanding the " + + f"data to a pd.DataFrame which contains {df.columns}. " + + "Rows with NaN values for the grouping column will be ignored.", + RuntimeWarning, + ) + + # Drop all rows with NaN values for the column on which we group + df.dropna(subset=[col_name], inplace=True) + + df_cum = ( + (df[col_name] != df[col_name].shift(1)) + .astype("int") + .cumsum() + .rename("value_grp") + .to_frame() + ) + df_cum["sequence_idx"] = df.index + df_cum[col_name] = df[col_name] + + df_cum_grouped = df_cum.groupby("value_grp") + df_grouped = pd.DataFrame( + { + "start": df_cum_grouped["sequence_idx"].first(), + "end": df_cum_grouped["sequence_idx"].last(), + col_name: df_cum_grouped[col_name].first(), + } + ).reset_index(drop=True) + + return df_grouped + + def _calculate_group_by_consecutive( self, data: Union[pd.Series, pd.DataFrame, List[Union[pd.Series, pd.DataFrame]]], + group_by: str, + return_df: Optional[bool] = False, + **calculate_kwargs, + ) -> Union[List[pd.DataFrame], pd.DataFrame]: + """Calculate features on each consecutive group of the data. + + Parameters + ---------- + data : Union[pd.Series, pd.DataFrame, List[Union[pd.Series, pd.DataFrame]]] + Must be time-indexed! + group_by: str + Name of column by which to group values. + return_df: bool, optional + Whether the output needs to be a DataFrame or a list thereof, by default + False. If `True` the output dataframes will be merged to a DataFrame with an + outer merge. + **calculate_kwargs: + Keyword arguments that will be passed to the `calculate` method. + + .. Note:: + Is comparable to following pseudo-SQL code: + ```sql + SELECT func(x) + FROM `data` + GROUP BY `group_by` + ``` + where `func` is the FeatureDescriptor function and `x` is the name + on which the FeatureDescriptor operates. Note however that the grouping is + done on consecutive values of `group_by` (i.e. `group_by` values that are + the same and are next to each other are grouped together). + """ + # 0. Transform to dataframe + series_dict = FeatureCollection._data_to_series_dict( + data, self.get_required_series() + [group_by] + ) + df = pd.DataFrame(series_dict) + # 1. Group by `group_by` column + consecutive_grouped_by_df = self._group_by_consecutive(df, col_name=group_by) + # 2. Get start and end idxs of consecutive groups + start_segment_idxs = consecutive_grouped_by_df["start"] + end_segment_idxs = start_segment_idxs.shift(-1) + # fill the nan value with the last end idx + end_segment_idxs.iloc[-1] = consecutive_grouped_by_df["end"].iloc[-1] + # because segment end idxs are exclusive, we need to add an offset to the last + # end idx so that all data gets used + segment_vals = end_segment_idxs.values + if is_datetime64_any_dtype(segment_vals): + segment_vals[-1] += pd.Timedelta(days=1) + else: + segment_vals[-1] += 1 + # 3. Calculate features + try: + # Filter out the warnings that are raised when segment indices are passed + # (since users expect irregular window sizes when grouping) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", category=RuntimeWarning, message="^.*segment indexes.*$" + ) + warnings.filterwarnings( + "ignore", category=RuntimeWarning, message="^.*gaps.*$" + ) + # 3.1. Calculate features using the groupby segment idxs + calc_results = self.calculate( + data=df, + segment_start_idxs=start_segment_idxs, + segment_end_idxs=end_segment_idxs, + **calculate_kwargs, + ) + + # 3.2 Concatenate results and add the group_by column as well as the + # start and end idxs of the segments + calc_result = pd.concat(calc_results, join="outer", copy=False, axis=1) + calc_result.reset_index(inplace=True, drop=True) + calc_result[group_by] = consecutive_grouped_by_df[group_by] + calc_result["__start"] = consecutive_grouped_by_df["start"] + calc_result["__end"] = consecutive_grouped_by_df["end"] + + if return_df: + # concatenate rows + return calc_result + else: + return [calc_result[col] for col in calc_result.columns] + + except Exception as e: + raise RuntimeError( + f"An exception was raised during feature extraction:\n{e}" + ) + + @staticmethod + def _process_njobs(n_jobs: Union[int, None], nb_funcs: int) -> int: + """Process the number of jobs to run in parallel. + + On Windows no multiprocessing is supported, see + https://github.com/predict-idlab/tsflex/issues/51 + + Parameters + ---------- + n_jobs : Union[int, None] + The number of jobs to run in parallel. + nb_funcs : int + The number of feature functions. + + Returns + ------- + int + The number of jobs to run in parallel. + + """ + if os.name == "nt": # On Windows no multiprocessing is supported + n_jobs = 1 + elif n_jobs is None: + n_jobs = os.cpu_count() + return min(n_jobs, nb_funcs) + + def _calculate_feature_list( + self, + executor: Callable[[int], pd.DataFrame], + n_jobs: Optional[int], + show_progress: Optional[bool], + return_df: Optional[bool], + f_handler: Optional[logging.FileHandler], + ) -> Union[List[pd.DataFrame], pd.DataFrame]: + """Calculate the features for the given executor. + + Parameters + ---------- + executor : Callable[[int], pd.DataFrame] + The executor function that will be used to calculate the features. + n_jobs : Optional[int], optional + The number of jobs to run in parallel. + show_progress : Optional[bool], optional + Whether to show a progress bar. + return_df : Optional[bool], optional + Whether to return a DataFrame or a list of DataFrames. + f_handler : Optional[logging.FileHandler], optional + The file handler that is used to log the function execution times. + + Returns + ------- + Union[List[pd.DataFrame], pd.DataFrame] + The calculated features. + + """ + nb_feat_funcs = self._get_nb_feat_funcs() + n_jobs = FeatureCollection._process_njobs(n_jobs, nb_feat_funcs) + + calculated_feature_list: List[pd.DataFrame] = None + + if n_jobs in [0, 1]: + # No multiprocessing + idxs = range(nb_feat_funcs) + if show_progress: + idxs = tqdm(idxs) + try: + calculated_feature_list = [executor(idx) for idx in idxs] + except Exception: + traceback.print_exc() + else: + # Multiprocessing + with Pool(processes=n_jobs) as pool: + results = pool.imap_unordered(executor, range(nb_feat_funcs)) + if show_progress: + results = tqdm(results, total=nb_feat_funcs) + try: + calculated_feature_list = [f for f in results] + except Exception: + traceback.print_exc() + pool.terminate() + finally: + # Close & join because: https://github.com/uqfoundation/pathos/issues/131 + pool.close() + pool.terminate() + pool.join() + + # Close the file handler (this avoids PermissionError: [WinError 32]) + if f_handler is not None: + f_handler.close() + logger.removeHandler(f_handler) + + if calculated_feature_list is None: + raise RuntimeError( + "Feature Extraction halted due to error while extracting one " + + "(or multiple) feature(s)! See stack trace above." + ) + + if return_df: + # Concatenate & sort the columns + df = pd.concat(calculated_feature_list, axis=1, join="outer", copy=False) + return df.reindex(sorted(df.columns), axis=1) + else: + return calculated_feature_list + + def calculate( + self, + data: Union[ + pd.Series, + pd.DataFrame, + List[Union[pd.Series, pd.DataFrame]], + pd.core.groupby.DataFrameGroupby, + ], stride: Optional[Union[float, str, pd.Timedelta, List, None]] = None, segment_start_idxs: Optional[ Union[list, np.ndarray, pd.Series, pd.Index] @@ -352,6 +840,8 @@ def calculate( return_df: Optional[bool] = False, window_idx: Optional[str] = "end", include_final_window: Optional[bool] = False, + group_by_all: Optional[str] = None, # TODO: support multiple columns + group_by_consecutive: Optional[str] = None, # TODO: support multiple columns bound_method: Optional[str] = "inner", approve_sparsity: Optional[bool] = False, show_progress: Optional[bool] = False, @@ -362,7 +852,7 @@ def calculate( Parameters ---------- - data : Union[pd.Series, pd.DataFrame, List[Union[pd.Series, pd.DataFrame]]] + data : Union[pd.Series, pd.DataFrame, List[Union[pd.Series, pd.DataFrame]], pd.core.groupby.DataFrameGroupby] Dataframe or Series or list thereof, with all the required data for the feature calculation. \n **Assumptions**: \n @@ -371,6 +861,9 @@ def calculate( numeric or a ``pd.DatetimeIndex``. * each Series / DataFrame index must be comparable with all others * we assume that each series-name / dataframe-column-name is unique. + Can also be a `DataFrameGroupBy` object, in which case the expected + behaviour is similar to grouping by all values in `group_by_all` (i.e., + for each group, the features are calculated on the group's data). stride: Union[float, str, pd.Timedelta, List[Union[float, str, pd.Timedelta], None], optional The stride size. By default None. This argument supports multiple types: \n * If None, the stride of the `FeatureDescriptor` objects will be used. @@ -458,6 +951,43 @@ def calculate( window (which is a full) window will not be included! - *(len * sampling_rate - window_size) % stride = 0*. Remark that the above case is a base case of this. + group_by_all : str, optional + The name of the column by which to perform grouping. For each group, the + features will be calculated. The output that is returned contains this + `group_by` column as index to allow identifying the groups. + If this parameter is used, the parameters `stride`, `segment_start_idxs`, + `segment_end_idxs`, `window_idx` and `include_final_window` will be ignored. + Rows with NaN values for this column will not be considered (as pandas + ignores these rows when grouping). + .. note:: + This is similar as passing a `DataFrameGroupBy` object as `data` + argument to the `calculate` method, where the `DataFrameGroupBy` object + is created by calling `data.groupby(group_by_all)`. + group_by_consecutive: str, optional + The name of the column by which to perform consecutive grouping. A + consecutive group is a group of values that are the same and are next to + each other. For each consecutive group, the features will be calculated. + The output that is returned contains this `group_by` column to allow + identifying the groups, and also contains fields [`__start`, "__end"] which + contain start and end time range for each result row. + If this parameter is used, the parameters `stride`, `segment_start_idxs`, + `segment_end_idxs`, `window_idx` and `include_final_window` will be ignored. + Rows with NaN values for this column will not be considered (as we deem NaN + not as a groupable value). + Note that for consecutive grouping, groups can appear multiple times if they + appear in different time-gaps. + + Example output: + .. example:: + ```python + number_sold__sum__w=manual store __start __end + 0 845 0 2019-01-01 2019-01-01 + 1 357 3 2019-01-02 2019-01-02 + 2 904 6 2019-01-03 2019-01-03 + 3 599 3 2019-01-04 2019-01-05 + 4 871 0 2019-01-06 2019-01-06 + ... ... ... ... ... + ``` bound_method: str, optional The start-end bound methodology which is used to generate the slice ranges when ``data`` consists of multiple series / columns. @@ -518,12 +1048,113 @@ def calculate( """ + + # Check valid data + if isinstance(data, list): + assert all( + isinstance(d, (pd.Series, pd.DataFrame)) for d in data + ), "All elements of the data list must be either a Series or a DataFrame!" + else: + assert isinstance( + data, (pd.Series, pd.DataFrame, pd.core.groupby.DataFrameGroupBy) + ), "The data must be either a Series, a DataFrame or a DataFrameGroupBy!" + + # check valid group_by + assert group_by_all is None or group_by_consecutive is None, ( + "Only max one of the following parameters can be set: " + + "`group_by_all` or `group_by_consecutive`" + ) + assert not ( + (group_by_all is not None or group_by_consecutive is not None) + and isinstance(data, pd.core.groupby.DataFrameGroupBy) + ), ( + "Cannot use `group_by_all` or `group_by_consecutive` when `data` is" + + " already a grouped DataFrame!" + ) + # Delete other logging handlers delete_logging_handlers(logger) # Add logging handler (if path provided) + f_handler = None if logging_file_path: f_handler = add_logging_handler(logger, logging_file_path) + if ( + group_by_all + or group_by_consecutive + or isinstance(data, pd.core.groupby.DataFrameGroupBy) + ): + self._check_no_multiple_windows( + error_case="When using the groupby behavior" + ) + + # The grouping column must be part of the required series + if group_by_all: + # group_by_consecutive should be None (checked by asserts above) + # data should not be a grouped DataFrame (checked by asserts above) + assert ( + group_by_all not in self.get_required_series() + ), "The `group_by_all` column cannot be part of the required series!" + elif group_by_consecutive: + # group_by_all should be None (checked by asserts above) + # data should not be a grouped DataFrame (checked by asserts above) + assert group_by_consecutive not in self.get_required_series(), ( + "The `group_by_consecutive` column cannot be part of the required " + + "series!" + ) + # __start and __end should not be part of the output names + assert "__start" not in self.get_required_series() + assert "__end" not in self.get_required_series() + + # if any of the following params are not None, warn that they won't be of use + # in the grouped calculation + ignored_params = [ + ("stride", None), + ("segment_start_idxs", None), + ("segment_end_idxs", None), + ("window_idx", "end"), + ("include_final_window", False), + ] + local_params = locals() + + for ip, default_value in ignored_params: + if local_params[ip] is not default_value: + warnings.warn( + f"Parameter `{ip}` will be ignored in case of GroupBy feature" + + " calculation." + ) + + if group_by_consecutive: + # Strided rollling feature extraction will take place + return self._calculate_group_by_consecutive( + data, + group_by_consecutive, + return_df, + bound_method=bound_method, + approve_sparsity=approve_sparsity, + show_progress=show_progress, + logging_file_path=logging_file_path, + n_jobs=n_jobs, + ) + else: + # Grouped feature extraction will take place + if not isinstance(data, pd.core.groupby.generic.DataFrameGroupBy): + # group_by_all should not be None (checked by asserts above) + # 0. Transform to dataframe + series_dict = FeatureCollection._data_to_series_dict( + data, self.get_required_series() + [group_by_all] + ) + # 1. Group by `group_by_all` column + data = self._group_by_all(series_dict, col_name=group_by_all) + + return self._calculate_group_by_all( + data, # should be a DataFrameGroupBy + return_df, + show_progress=show_progress, + n_jobs=n_jobs, + f_handler=f_handler, + ) + # Convert to numpy array (if necessary) if segment_start_idxs is not None: segment_start_idxs = FeatureCollection._process_segment_idxs( @@ -538,7 +1169,9 @@ def calculate( _check_start_end_array(segment_start_idxs, segment_end_idxs) # Check if there is either 1 or No(ne) window value for every output name - # input_series combination - self._check_no_multiple_windows() + self._check_no_multiple_windows( + error_case="When using both `segment_start_idxs` and `segment_end_idxs`" + ) if segment_start_idxs is None or segment_end_idxs is None: assert all( @@ -573,21 +1206,9 @@ def calculate( self._check_feature_descriptors(skip_none=False, calc_stride=stride) # Convert the data to a series_dict - series_dict: Dict[str, pd.Series] = {} - for s in to_series_list(data): - if not s.index.is_monotonic_increasing: - warnings.warn( - f"The index of series '{s.name}' is not monotonic increasing. " - + "The series will be sorted by the index.", - RuntimeWarning, - ) - s = s.sort_index(ascending=True, inplace=False, ignore_index=False) - - # Assert the assumptions we make! - assert s.index.is_monotonic_increasing - - if s.name in self.get_required_series(): - series_dict[str(s.name)] = s + series_dict = FeatureCollection._data_to_series_dict( + data, self.get_required_series() + ) # Determine the bounds of the series dict items and slice on them # TODO: is dit wel nodig `hier? want we doen dat ook in de strided rolling @@ -613,57 +1234,10 @@ def calculate( include_final_window=include_final_window, approve_sparsity=approve_sparsity, ) - nb_stroll_funcs = self._get_stroll_feat_length() - - if ( - os.name == "nt" - ): # On Windows no multiprocessing is supported, see https://github.com/predict-idlab/tsflex/issues/51 - n_jobs = 1 - elif n_jobs is None: - n_jobs = os.cpu_count() - n_jobs = min(n_jobs, nb_stroll_funcs) - calculated_feature_list = None - if n_jobs in [0, 1]: - idxs = range(nb_stroll_funcs) - if show_progress: - idxs = tqdm(idxs) - try: - calculated_feature_list = [self._executor(idx) for idx in idxs] - except Exception: - traceback.print_exc() - else: - with Pool(processes=n_jobs) as pool: - results = pool.imap_unordered(self._executor, range(nb_stroll_funcs)) - if show_progress: - results = tqdm(results, total=nb_stroll_funcs) - try: - calculated_feature_list = [f for f in results] - except Exception: - traceback.print_exc() - pool.terminate() - finally: - # Close & join because: https://github.com/uqfoundation/pathos/issues/131 - pool.close() - pool.join() - - # Close the file handler (this avoids PermissionError: [WinError 32]) - if logging_file_path: - f_handler.close() - logger.removeHandler(f_handler) - - if calculated_feature_list is None: - raise RuntimeError( - "Feature Extraction halted due to error while extracting one " - + "(or multiple) feature(s)! See stack trace above." - ) - - if return_df: - # concatenate & sort the columns - df = pd.concat(calculated_feature_list, axis=1, join="outer", copy=False) - return df.reindex(sorted(df.columns), axis=1) - else: - return calculated_feature_list + return self._calculate_feature_list( + self._executor_stroll, n_jobs, show_progress, return_df, f_handler + ) def serialize(self, file_path: Union[str, Path]): """Serialize this FeatureCollection instance. @@ -718,7 +1292,9 @@ def reduce(self, feat_cols_to_keep: List[str]) -> FeatureCollection: assert all(c.endswith("w=manual") for c in feat_cols_to_keep) # As the windows are created manual, the FeatureCollection cannot contain # multiple windows for the same output name - input_series combination - self._check_no_multiple_windows() + self._check_no_multiple_windows( + error_case="When reducing a FeatureCollection with manual windows" + ) manual_window = True feat_col_fd_mapping: Dict[str, Tuple[str, FeatureDescriptor]] = {} for (s_names, window), fd_list in self._feature_desc_dict.items(): diff --git a/tsflex/features/segmenter/strided_rolling.py b/tsflex/features/segmenter/strided_rolling.py index c5f92554..2f00c8c8 100644 --- a/tsflex/features/segmenter/strided_rolling.py +++ b/tsflex/features/segmenter/strided_rolling.py @@ -25,9 +25,13 @@ from ...utils.attribute_parsing import AttributeParser, DataType from ...utils.data import SUPPORTED_STROLL_TYPES, to_list, to_series_list, to_tuple from ...utils.time import timedelta_to_str -from ..function_wrapper import FuncWrapper, _get_name -from ..logger import logger -from ..utils import _check_start_end_array, _determine_bounds +from ..function_wrapper import FuncWrapper +from ..utils import ( + _check_start_end_array, + _determine_bounds, + _log_func_execution, + _process_func_output, +) # Declare a type variable T = TypeVar("T") @@ -299,11 +303,12 @@ def _construct_series_containers( # note: using pd.RangeIndex instead of arange gives the same performance series_name = series.name - if self.data_type is np.array: + if self.data_type is np.array: # FuncWrapper.input_type is np.array # create a non-writeable view of the series - series = series.values + series = series.values # np.array will be stored in the SeriesContainer series.flags.writeable = False - elif self.data_type is pd.Series: + elif self.data_type is pd.Series: # FuncWrapper.input_type is pd.Series + # pd.Series will be stored in the SeriesContainer series.values.flags.writeable = False series.index.values.flags.writeable = False else: @@ -444,7 +449,7 @@ def apply_func(self, func: FuncWrapper) -> pd.DataFrame: out = out.T if out_type is tuple else out else: - # Sequential function execution (default) + # Function execution over slices (default) out = np.array( list( map( @@ -466,38 +471,18 @@ def apply_func(self, func: FuncWrapper) -> pd.DataFrame: assert out.ndim > 0, "Vectorized function returned only 1 (non-array) value!" # Aggregate function output in a dictionary - feat_out = {} - if out.ndim == 1 and not len(out): - # When there are no features calculated (due to no feature windows) - assert not len(self.index) - for f_name in feat_names: - # Will be discarded (bc no index) - feat_out[self._create_feat_col_name(f_name)] = None - elif out.ndim == 1 or (out.ndim == 2 and out.shape[1] == 1): - assert len(feat_names) == 1, f"Func {func} returned more than 1 output!" - feat_out[self._create_feat_col_name(feat_names[0])] = out.flatten() - else: - assert out.ndim == 2 and out.shape[1] > 1 - assert ( - len(feat_names) == out.shape[1] - ), f"Func {func} returned incorrect number of outputs ({out.shape[1]})!" - for col_idx in range(out.shape[1]): - feat_out[self._create_feat_col_name(feat_names[col_idx])] = out[ - :, col_idx - ] - - elapsed = time.perf_counter() - t_start + output_names = list(map(self._create_feat_col_name, feat_names)) + feat_out = _process_func_output(out, self.index, output_names, str(func)) + # Log the function execution time log_strides = ( "manual" if self.strides is None else tuple(map(str, self.strides)) ) log_window = "manual" if self.window is None else self.window - logger.info( - f"Finished function [{_get_name(func.func)}] on " - f"{[self.series_key]} with window-stride [{log_window}, {log_strides}] " - f"with output {list(feat_out.keys())} in [{elapsed} seconds]!" + _log_func_execution( + t_start, func, self.series_key, log_window, log_strides, output_names ) - return pd.DataFrame(index=self.index, data=feat_out) + return pd.DataFrame(feat_out, index=self.index) # --------------------------------- STATIC METHODS --------------------------------- @staticmethod diff --git a/tsflex/features/utils.py b/tsflex/features/utils.py index 0aab6eb9..9a2bb309 100644 --- a/tsflex/features/utils.py +++ b/tsflex/features/utils.py @@ -2,15 +2,62 @@ __author__ = "Jeroen Van Der Donckt, Jonas Van Der Donckt" -from typing import Any, Callable, List, Optional, Tuple, Union +import time +from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union import numpy as np import pandas as pd from .function_wrapper import FuncWrapper, _get_name +from .logger import logger +# Declare a type variable +T = TypeVar("T") # ---------------------------------- PRIVATE METHODS ---------------------------------- +def _process_func_output( + out: np.ndarray, index: np.ndarray, output_names: List[str], func_str: str +) -> Dict[str, np.ndarray]: + """Process the output of a feature function into a dictionary.""" + feat_out = {} + if out.ndim == 1 and not len(out): + # When there are no features calculated (due to no feature windows) + assert not len(index) + for o_name in output_names: + # Will be discarded (bc no index) + feat_out[o_name] = None + elif out.ndim == 1 or (out.ndim == 2 and out.shape[1] == 1): + assert len(output_names) == 1, f"Func {func_str} returned more than 1 output!" + feat_out[output_names[0]] = out.flatten() + else: + assert out.ndim == 2 and out.shape[1] > 1 + assert ( + len(output_names) == out.shape[1] + ), f"Func {func_str} returned incorrect number of outputs ({out.shape[1]})!" + for col_idx in range(out.shape[1]): + feat_out[output_names[col_idx]] = out[:, col_idx] + + return feat_out + + +def _log_func_execution( + t_start: float, + func: FuncWrapper, + series_key: Tuple[str], + log_window: Optional[T], + log_strides: Optional[Union[str, Tuple[str]]], + output_names: List[str], +): + """Log the execution time of a feature function.""" + elapsed = time.perf_counter() - t_start + + logger.info( + f"Finished function [{_get_name(func.func)}] on " + f"{[series_key]} with window-stride [{log_window}, {log_strides}] " + f"with output {output_names} in [{elapsed} seconds]!" + ) + + def _determine_bounds(bound_method, series_list: List[pd.Series]) -> Tuple[Any, Any]: """Determine the bounds of the passed series.