tsadmetrics 0.1.15__tar.gz → 0.1.17__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tsadmetrics-0.1.17/PKG-INFO +54 -0
- tsadmetrics-0.1.17/README.md +31 -0
- tsadmetrics-0.1.17/docs_api/conf.py +90 -0
- tsadmetrics-0.1.17/docs_manual/conf.py +90 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/pyproject.toml +5 -1
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/setup.py +7 -1
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tests/test_binary.py +194 -7
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tests/test_non_binary.py +138 -59
- tsadmetrics-0.1.17/tests/test_utils.py +49 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/__init__.py +1 -1
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/binary_metrics.py +214 -19
- tsadmetrics-0.1.17/tsadmetrics/metric_utils.py +98 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/non_binary_metrics.py +113 -110
- tsadmetrics-0.1.17/tsadmetrics/scripts/compute_metrics.py +42 -0
- tsadmetrics-0.1.17/tsadmetrics/utils.py +124 -0
- tsadmetrics-0.1.17/tsadmetrics/validation.py +35 -0
- tsadmetrics-0.1.17/tsadmetrics.egg-info/PKG-INFO +54 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics.egg-info/SOURCES.txt +8 -1
- tsadmetrics-0.1.17/tsadmetrics.egg-info/entry_points.txt +2 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics.egg-info/top_level.txt +2 -0
- tsadmetrics-0.1.15/PKG-INFO +0 -22
- tsadmetrics-0.1.15/tsadmetrics/metric_utils.py +0 -333
- tsadmetrics-0.1.15/tsadmetrics/utils.py +0 -55
- tsadmetrics-0.1.15/tsadmetrics.egg-info/PKG-INFO +0 -22
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/MANIFEST.in +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/docs/conf.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/activate_this.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2html.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2html4.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2html5.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2latex.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2man.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2odt.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2odt_prepstyles.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2pseudoxml.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2s5.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2xetex.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rst2xml.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/entorno/bin/rstpep2html.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/setup.cfg +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tests/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/affiliation/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/affiliation/_affiliation_zone.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/affiliation/_integral_interval.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/affiliation/_single_ground_truth_event.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/affiliation/generics.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/affiliation/metrics.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/auc_roc_pr_plot.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/discontinuity_graph.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/File_IO.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/Range.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/Time_Plot.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/etapr.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/eTaPR_pkg/tapr.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/latency_sparsity_aware.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/metrics.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/nabscore.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/base/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/base/time_series_metrics.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/basic_metrics_ts.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/time_series_metrics/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/time_series_metrics/fscore.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/time_series_metrics/precision.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/time_series_metrics/precision_recall.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/prts/time_series_metrics/recall.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/tests.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/threshold_plt.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/time_tolerant.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/_tsadeval/vus_utils.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics/py.typed +0 -0
- /tsadmetrics-0.1.15/README.md → /tsadmetrics-0.1.17/tsadmetrics/scripts/__init__.py +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics.egg-info/dependency_links.txt +0 -0
- {tsadmetrics-0.1.15 → tsadmetrics-0.1.17}/tsadmetrics.egg-info/requires.txt +0 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: tsadmetrics
|
3
|
+
Version: 0.1.17
|
4
|
+
Summary: Librería para evaluación de detección de anomalías en series temporales
|
5
|
+
Home-page: https://github.com/pathsko/TSADmetrics
|
6
|
+
Author: Pedro Rafael Velasco Priego
|
7
|
+
Author-email: Pedro Rafael Velasco Priego <i12veprp@uco.es>
|
8
|
+
Requires-Python: >=3.8
|
9
|
+
Description-Content-Type: text/markdown
|
10
|
+
Requires-Dist: joblib==1.4.2
|
11
|
+
Requires-Dist: numpy==1.24.4
|
12
|
+
Requires-Dist: pandas==2.0.3
|
13
|
+
Requires-Dist: PATE==0.1.1
|
14
|
+
Requires-Dist: patsy==0.5.6
|
15
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
16
|
+
Requires-Dist: pytz==2024.1
|
17
|
+
Requires-Dist: scikit-learn==1.3.2
|
18
|
+
Requires-Dist: scipy==1.10.1
|
19
|
+
Requires-Dist: six==1.16.0
|
20
|
+
Requires-Dist: statsmodels==0.14.1
|
21
|
+
Requires-Dist: threadpoolctl==3.5.0
|
22
|
+
Requires-Dist: tzdata==2024.1
|
23
|
+
|
24
|
+
# TSADmetrics - Time Series Anomaly Detection Metrics
|
25
|
+
|
26
|
+
**TSADmetrics** is a Python library for evaluating anomaly detection algorithms in time series data. It provides a comprehensive set of binary and non-binary metrics designed specifically for the challenges of anomaly detection in temporal contexts.
|
27
|
+
|
28
|
+
## Features
|
29
|
+
|
30
|
+
- **Binary Metrics**: Evaluate discrete anomaly predictions (0/1 labels)
|
31
|
+
|
32
|
+
- **Non-Binary Metrics**: Assess continuous anomaly scores
|
33
|
+
|
34
|
+
- **Efficient Computation**: Compute multiple metrics at once
|
35
|
+
|
36
|
+
- **CLI Tool**: Evaluate metrics directly from CSV/JSON files
|
37
|
+
|
38
|
+
## Installation
|
39
|
+
|
40
|
+
Install TSADmetrics via pip:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
pip install tsadmetrics
|
44
|
+
```
|
45
|
+
|
46
|
+
## Documentation
|
47
|
+
|
48
|
+
The complete documentation for TSADmetrics is available at:
|
49
|
+
📚 [https://tsadmetrics.readthedocs.io/](https://tsadmetrics.readthedocs.io/)
|
50
|
+
|
51
|
+
## Acknowledgements
|
52
|
+
|
53
|
+
This library is based on the concepts and implementations from:
|
54
|
+
Sørbø, S., & Ruocco, M. (2023). *Navigating the metric maze: a taxonomy of evaluation metrics for anomaly detection in time series*. https://doi.org/10.1007/s10618-023-00988-8
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# TSADmetrics - Time Series Anomaly Detection Metrics
|
2
|
+
|
3
|
+
**TSADmetrics** is a Python library for evaluating anomaly detection algorithms in time series data. It provides a comprehensive set of binary and non-binary metrics designed specifically for the challenges of anomaly detection in temporal contexts.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- **Binary Metrics**: Evaluate discrete anomaly predictions (0/1 labels)
|
8
|
+
|
9
|
+
- **Non-Binary Metrics**: Assess continuous anomaly scores
|
10
|
+
|
11
|
+
- **Efficient Computation**: Compute multiple metrics at once
|
12
|
+
|
13
|
+
- **CLI Tool**: Evaluate metrics directly from CSV/JSON files
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Install TSADmetrics via pip:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
pip install tsadmetrics
|
21
|
+
```
|
22
|
+
|
23
|
+
## Documentation
|
24
|
+
|
25
|
+
The complete documentation for TSADmetrics is available at:
|
26
|
+
📚 [https://tsadmetrics.readthedocs.io/](https://tsadmetrics.readthedocs.io/)
|
27
|
+
|
28
|
+
## Acknowledgements
|
29
|
+
|
30
|
+
This library is based on the concepts and implementations from:
|
31
|
+
Sørbø, S., & Ruocco, M. (2023). *Navigating the metric maze: a taxonomy of evaluation metrics for anomaly detection in time series*. https://doi.org/10.1007/s10618-023-00988-8
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
2
|
+
#
|
3
|
+
|
4
|
+
import os
|
5
|
+
import sys
|
6
|
+
sys.path.insert(0, os.path.abspath('../'))
|
7
|
+
|
8
|
+
|
9
|
+
project = 'TSADmetrics'
|
10
|
+
copyright = '2025, Pedro Rafael Velasco Priego'
|
11
|
+
author = 'Pedro Rafael Velasco Priego'
|
12
|
+
release = 'MIT'
|
13
|
+
|
14
|
+
# -- General configuration ---------------------------------------------------
|
15
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
16
|
+
|
17
|
+
|
18
|
+
extensions = ['sphinx.ext.duration', 'sphinx.ext.doctest', 'sphinx.ext.autodoc',]
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
templates_path = ['_templates']
|
23
|
+
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
24
|
+
|
25
|
+
html_theme = 'furo'
|
26
|
+
html_static_path = ['_static']
|
27
|
+
html_theme_options = {
|
28
|
+
#"sidebar_hide_name": True,
|
29
|
+
"light_css_variables": {
|
30
|
+
"color-brand-primary": "#2e5c7d",
|
31
|
+
"color-brand-content": "#2e5c7d",
|
32
|
+
"codebgcolor": "red",
|
33
|
+
"codetextcolor": "red",
|
34
|
+
},
|
35
|
+
"dark_css_variables": {
|
36
|
+
"color-brand-primary": "#6998b4",
|
37
|
+
"color-brand-content": "#6998b4",
|
38
|
+
"codebgcolor": "green",
|
39
|
+
"codetextcolor": "green",
|
40
|
+
},
|
41
|
+
"navigation_with_keys": True
|
42
|
+
|
43
|
+
}
|
44
|
+
html_baseurl = ''
|
45
|
+
|
46
|
+
html_css_files = [
|
47
|
+
'css/custom.css',
|
48
|
+
]
|
49
|
+
|
50
|
+
epub_show_urls = 'footnote'
|
51
|
+
|
52
|
+
# -- Options for HTML output -------------------------------------------------
|
53
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
### -- LaTeX options -------------------------------------------------
|
59
|
+
|
60
|
+
# comando para compilar: make latexpdf LATEXMKOPTS="-xelatex"
|
61
|
+
|
62
|
+
latex_elements = {
|
63
|
+
'maxlistdepth': '10', # Aumenta el límite de anidamiento
|
64
|
+
'papersize': 'a4paper',
|
65
|
+
'pointsize': '10pt',
|
66
|
+
'maketitle': r'''
|
67
|
+
\makeatletter
|
68
|
+
\begin{titlepage}
|
69
|
+
\noindent\rule{\textwidth}{1pt}\\[3cm]
|
70
|
+
\begin{center}
|
71
|
+
{\Huge\sffamily\bfseries TSADmetrics API Reference}\\[1.5cm]
|
72
|
+
{\Large\sffamily Time Series Anomaly Detection Metrics}\\[3cm]
|
73
|
+
\begin{minipage}{0.8\textwidth}
|
74
|
+
\centering
|
75
|
+
{\large\sffamily
|
76
|
+
\begin{tabular}{l@{\hspace{1cm}}l}
|
77
|
+
\textbf{Autor:} & Pedro Rafael Velasco Priego \\
|
78
|
+
\textbf{Directores:} & Dra. Amelia Zafra Gómez \\
|
79
|
+
& Dr. Sebastián Ventura Soto \\
|
80
|
+
\end{tabular}
|
81
|
+
}
|
82
|
+
\end{minipage}\\[5cm]
|
83
|
+
{\large\sffamily \@date}\\
|
84
|
+
{\large\sffamily \copyright\ 2025 Pedro Rafael Velasco Priego}
|
85
|
+
\end{center}
|
86
|
+
\noindent\rule{\textwidth}{1pt}
|
87
|
+
\end{titlepage}
|
88
|
+
\makeatother
|
89
|
+
''',
|
90
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
2
|
+
#
|
3
|
+
|
4
|
+
import os
|
5
|
+
import sys
|
6
|
+
sys.path.insert(0, os.path.abspath('../'))
|
7
|
+
|
8
|
+
|
9
|
+
project = 'TSADmetrics'
|
10
|
+
copyright = '2025, Pedro Rafael Velasco Priego'
|
11
|
+
author = 'Pedro Rafael Velasco Priego'
|
12
|
+
release = 'MIT'
|
13
|
+
|
14
|
+
# -- General configuration ---------------------------------------------------
|
15
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
16
|
+
|
17
|
+
|
18
|
+
extensions = ['sphinx.ext.duration', 'sphinx.ext.doctest', 'sphinx.ext.autodoc',]
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
templates_path = ['_templates']
|
23
|
+
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
24
|
+
|
25
|
+
html_theme = 'furo'
|
26
|
+
html_static_path = ['_static']
|
27
|
+
html_theme_options = {
|
28
|
+
#"sidebar_hide_name": True,
|
29
|
+
"light_css_variables": {
|
30
|
+
"color-brand-primary": "#2e5c7d",
|
31
|
+
"color-brand-content": "#2e5c7d",
|
32
|
+
"codebgcolor": "red",
|
33
|
+
"codetextcolor": "red",
|
34
|
+
},
|
35
|
+
"dark_css_variables": {
|
36
|
+
"color-brand-primary": "#6998b4",
|
37
|
+
"color-brand-content": "#6998b4",
|
38
|
+
"codebgcolor": "green",
|
39
|
+
"codetextcolor": "green",
|
40
|
+
},
|
41
|
+
"navigation_with_keys": True
|
42
|
+
|
43
|
+
}
|
44
|
+
html_baseurl = ''
|
45
|
+
|
46
|
+
html_css_files = [
|
47
|
+
'css/custom.css',
|
48
|
+
]
|
49
|
+
|
50
|
+
epub_show_urls = 'footnote'
|
51
|
+
|
52
|
+
# -- Options for HTML output -------------------------------------------------
|
53
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
### -- LaTeX options -------------------------------------------------
|
59
|
+
|
60
|
+
# comando para compilar: make latexpdf LATEXMKOPTS="-xelatex"
|
61
|
+
|
62
|
+
latex_elements = {
|
63
|
+
'maxlistdepth': '10', # Aumenta el límite de anidamiento
|
64
|
+
'papersize': 'a4paper',
|
65
|
+
'pointsize': '10pt',
|
66
|
+
'maketitle': r'''
|
67
|
+
\makeatletter
|
68
|
+
\begin{titlepage}
|
69
|
+
\noindent\rule{\textwidth}{1pt}\\[3cm]
|
70
|
+
\begin{center}
|
71
|
+
{\Huge\sffamily\bfseries TSADmetrics User Manual}\\[1.5cm]
|
72
|
+
{\Large\sffamily Time Series Anomaly Detection Metrics}\\[3cm]
|
73
|
+
\begin{minipage}{0.8\textwidth}
|
74
|
+
\centering
|
75
|
+
{\large\sffamily
|
76
|
+
\begin{tabular}{l@{\hspace{1cm}}l}
|
77
|
+
\textbf{Autor:} & Pedro Rafael Velasco Priego \\
|
78
|
+
\textbf{Directores:} & Dra. Amelia Zafra Gómez \\
|
79
|
+
& Dr. Sebastián Ventura Soto \\
|
80
|
+
\end{tabular}
|
81
|
+
}
|
82
|
+
\end{minipage}\\[5cm]
|
83
|
+
{\large\sffamily \@date}\\
|
84
|
+
{\large\sffamily \copyright\ 2025 Pedro Rafael Velasco Priego}
|
85
|
+
\end{center}
|
86
|
+
\noindent\rule{\textwidth}{1pt}
|
87
|
+
\end{titlepage}
|
88
|
+
\makeatother
|
89
|
+
''',
|
90
|
+
}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
[project]
|
2
2
|
name = "tsadmetrics"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.17"
|
4
4
|
description = "Librería para evaluación de detección de anomalías en series temporales"
|
5
|
+
readme = "README.md"
|
5
6
|
authors = [
|
6
7
|
{ name = "Pedro Rafael Velasco Priego", email = "i12veprp@uco.es" }
|
7
8
|
]
|
@@ -28,3 +29,6 @@ where = ["."]
|
|
28
29
|
[build-system]
|
29
30
|
requires = ["setuptools>=61.0", "wheel"]
|
30
31
|
build-backend = "setuptools.build_meta"
|
32
|
+
|
33
|
+
[project.scripts]
|
34
|
+
tsadmetrics-compute = "tsadmetrics.scripts.compute_metrics:main"
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
5
5
|
|
6
6
|
setup(
|
7
7
|
name="tsadmetrics",
|
8
|
-
version="0.1.
|
8
|
+
version="0.1.17",
|
9
9
|
author="Pedro Rafael Velasco Priego",
|
10
10
|
author_email="i12veprp@uco.es",
|
11
11
|
description="A library for time series anomaly detection metrics and evaluation.",
|
@@ -46,4 +46,10 @@ setup(
|
|
46
46
|
"myst-parser",
|
47
47
|
],
|
48
48
|
},
|
49
|
+
entry_points={
|
50
|
+
"console_scripts": [
|
51
|
+
"tsadmetrics-compute = scripts.compute_metrics:main",
|
52
|
+
],
|
53
|
+
},
|
49
54
|
)
|
55
|
+
|
@@ -593,8 +593,40 @@ class TestAverageDetectionCount(unittest.TestCase):
|
|
593
593
|
"""
|
594
594
|
pass
|
595
595
|
|
596
|
+
def setUp(self):
|
597
|
+
"""
|
598
|
+
Configuración inicial para las pruebas.
|
599
|
+
"""
|
600
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
601
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
602
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
603
|
+
|
604
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
605
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
606
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
607
|
+
|
596
608
|
|
597
609
|
|
610
|
+
def test_average_detection_count(self):
|
611
|
+
"""
|
612
|
+
Prueba para la función average_detection_count.
|
613
|
+
"""
|
614
|
+
metric = round(average_detection_count(self.y_true1, self.y_pred1),2)
|
615
|
+
expected_metric = 0.5
|
616
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
617
|
+
|
618
|
+
metric = round(average_detection_count(self.y_true1, self.y_pred2),2)
|
619
|
+
expected_metric = 0.12
|
620
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
621
|
+
|
622
|
+
metric = round(average_detection_count(self.y_true2, self.y_pred21),2)
|
623
|
+
expected_metric = 0.33
|
624
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
625
|
+
|
626
|
+
metric = round(average_detection_count(self.y_true2, self.y_pred22),2)
|
627
|
+
expected_metric = 0.67
|
628
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
629
|
+
|
598
630
|
|
599
631
|
def test_average_detection_count_consistency(self):
|
600
632
|
try:
|
@@ -615,9 +647,33 @@ class TestAbsoluteDetectionDistance(unittest.TestCase):
|
|
615
647
|
"""
|
616
648
|
Configuración inicial para las pruebas.
|
617
649
|
"""
|
618
|
-
|
650
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
651
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
652
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
619
653
|
|
620
|
-
|
654
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
655
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
656
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
657
|
+
|
658
|
+
def test_absolute_detection_distance(self):
|
659
|
+
"""
|
660
|
+
Prueba para la función absolute_detection_distance.
|
661
|
+
"""
|
662
|
+
metric = round(absolute_detection_distance(self.y_true1, self.y_pred1),2)
|
663
|
+
expected_metric = 0.25
|
664
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
665
|
+
|
666
|
+
metric = round(absolute_detection_distance(self.y_true1, self.y_pred2),2)
|
667
|
+
expected_metric = 0.25
|
668
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
669
|
+
|
670
|
+
metric = round(absolute_detection_distance(self.y_true2, self.y_pred21),2)
|
671
|
+
expected_metric = 0.06
|
672
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
673
|
+
|
674
|
+
metric = round(absolute_detection_distance(self.y_true2, self.y_pred22),2)
|
675
|
+
expected_metric = 0.12
|
676
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
621
677
|
|
622
678
|
|
623
679
|
def test_absolute_detection_distance_consistency(self):
|
@@ -639,7 +695,33 @@ class TestTotalDetectedInRange(unittest.TestCase):
|
|
639
695
|
"""
|
640
696
|
Configuración inicial para las pruebas.
|
641
697
|
"""
|
642
|
-
|
698
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
699
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
700
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
701
|
+
|
702
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
703
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
704
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
705
|
+
|
706
|
+
def test_total_detected_in_range(self):
|
707
|
+
"""
|
708
|
+
Prueba para la función total_detected_in_range.
|
709
|
+
"""
|
710
|
+
metric = round(total_detected_in_range(self.y_true1, self.y_pred1,k=3),2)
|
711
|
+
expected_metric = 0.5
|
712
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
713
|
+
|
714
|
+
metric = round(total_detected_in_range(self.y_true1, self.y_pred2,k=3),2)
|
715
|
+
expected_metric = 0.5
|
716
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
717
|
+
|
718
|
+
metric = round(total_detected_in_range(self.y_true2, self.y_pred21,k=3),2)
|
719
|
+
expected_metric = 0.56
|
720
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
721
|
+
|
722
|
+
metric = round(total_detected_in_range(self.y_true2, self.y_pred22,k=3),2)
|
723
|
+
expected_metric = 0.44
|
724
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
643
725
|
|
644
726
|
|
645
727
|
|
@@ -663,7 +745,33 @@ class TestDetectionAccuracyInRange(unittest.TestCase):
|
|
663
745
|
"""
|
664
746
|
Configuración inicial para las pruebas.
|
665
747
|
"""
|
666
|
-
|
748
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
749
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
750
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
751
|
+
|
752
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
753
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
754
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
755
|
+
|
756
|
+
def test_detection_accuracy_in_range(self):
|
757
|
+
"""
|
758
|
+
Prueba para la función detection_accuracy_in_range.
|
759
|
+
"""
|
760
|
+
metric = round(detection_accuracy_in_range(self.y_true1, self.y_pred1,k=3),2)
|
761
|
+
expected_metric = 1.0
|
762
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
763
|
+
|
764
|
+
metric = round(detection_accuracy_in_range(self.y_true1, self.y_pred2,k=3),2)
|
765
|
+
expected_metric = 1.0
|
766
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
767
|
+
|
768
|
+
metric = round(detection_accuracy_in_range(self.y_true2, self.y_pred21,k=3),2)
|
769
|
+
expected_metric = 1.0
|
770
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
771
|
+
|
772
|
+
metric = round(detection_accuracy_in_range(self.y_true2, self.y_pred22,k=3),2)
|
773
|
+
expected_metric = 1.0
|
774
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
667
775
|
|
668
776
|
|
669
777
|
|
@@ -688,7 +796,33 @@ class TestWeightedDetectionDifference(unittest.TestCase):
|
|
688
796
|
"""
|
689
797
|
Configuración inicial para las pruebas.
|
690
798
|
"""
|
691
|
-
|
799
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
800
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
801
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
802
|
+
|
803
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
804
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
805
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
806
|
+
|
807
|
+
def test_weighted_detection_difference(self):
|
808
|
+
"""
|
809
|
+
Prueba para la función weighted_detection_difference.
|
810
|
+
"""
|
811
|
+
metric = round(weighted_detection_difference(self.y_true1, self.y_pred1,k=3),2)
|
812
|
+
expected_metric = 18.89
|
813
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
814
|
+
|
815
|
+
metric = round(weighted_detection_difference(self.y_true1, self.y_pred2,k=3),2)
|
816
|
+
expected_metric = 24.89
|
817
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
818
|
+
|
819
|
+
metric = round(weighted_detection_difference(self.y_true2, self.y_pred21,k=3),2)
|
820
|
+
expected_metric = 15.73
|
821
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
822
|
+
|
823
|
+
metric = round(weighted_detection_difference(self.y_true2, self.y_pred22,k=3),2)
|
824
|
+
expected_metric = 16.73
|
825
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
692
826
|
|
693
827
|
|
694
828
|
|
@@ -712,7 +846,33 @@ class TestPATE(unittest.TestCase):
|
|
712
846
|
"""
|
713
847
|
Configuración inicial para las pruebas.
|
714
848
|
"""
|
715
|
-
|
849
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
850
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
851
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
852
|
+
|
853
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
854
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
855
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
856
|
+
|
857
|
+
def test_binary_pate(self):
|
858
|
+
"""
|
859
|
+
Prueba para la función binary_pate.
|
860
|
+
"""
|
861
|
+
metric = round(binary_pate(self.y_true1, self.y_pred1,early=2, delay=2),2)
|
862
|
+
expected_metric = 0.67
|
863
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
864
|
+
|
865
|
+
metric = round(binary_pate(self.y_true1, self.y_pred2,early=2, delay=2),2)
|
866
|
+
expected_metric = 0.27
|
867
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
868
|
+
|
869
|
+
metric = round(binary_pate(self.y_true2, self.y_pred21,early=2, delay=2),2)
|
870
|
+
expected_metric = 0.71
|
871
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
872
|
+
|
873
|
+
metric = round(binary_pate(self.y_true2, self.y_pred22,early=2, delay=2),2)
|
874
|
+
expected_metric = 0.62
|
875
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
716
876
|
|
717
877
|
|
718
878
|
|
@@ -737,7 +897,34 @@ class TestMeanTimeToDetect(unittest.TestCase):
|
|
737
897
|
"""
|
738
898
|
Configuración inicial para las pruebas.
|
739
899
|
"""
|
740
|
-
|
900
|
+
self.y_true1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1])
|
901
|
+
self.y_pred1 = np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
902
|
+
self.y_pred2 = np.array([0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0])
|
903
|
+
|
904
|
+
self.y_true2 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
905
|
+
self.y_pred21 = np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1])
|
906
|
+
self.y_pred22 = np.array([0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
907
|
+
|
908
|
+
def test_mean_time_to_detect(self):
|
909
|
+
"""
|
910
|
+
Prueba para la función mean_time_to_detect.
|
911
|
+
"""
|
912
|
+
metric = round(mean_time_to_detect(self.y_true1, self.y_pred1),2)
|
913
|
+
expected_metric = 0.0
|
914
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
915
|
+
|
916
|
+
metric = round(mean_time_to_detect(self.y_true1, self.y_pred2),2)
|
917
|
+
expected_metric = 0.0
|
918
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
919
|
+
|
920
|
+
metric = round(mean_time_to_detect(self.y_true2, self.y_pred21),2)
|
921
|
+
expected_metric = 8.0
|
922
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
923
|
+
|
924
|
+
metric = round(mean_time_to_detect(self.y_true2, self.y_pred22),2)
|
925
|
+
expected_metric = 0.0
|
926
|
+
self.assertAlmostEqual(metric, expected_metric, places=4)
|
927
|
+
|
741
928
|
|
742
929
|
|
743
930
|
|