tsadmetrics 0.1.17__py3-none-any.whl → 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. {docs_api → docs/add_docs/api_doc}/conf.py +3 -26
  2. {docs_manual → docs/add_docs/full_doc}/conf.py +2 -25
  3. docs/add_docs/manual_doc/conf.py +67 -0
  4. docs/conf.py +1 -1
  5. examples/example_direct_data.py +28 -0
  6. examples/example_direct_single_data.py +25 -0
  7. examples/example_file_reference.py +24 -0
  8. examples/example_global_config_file.py +13 -0
  9. examples/example_metric_config_file.py +19 -0
  10. examples/example_simple_metric.py +8 -0
  11. examples/specific_examples/AbsoluteDetectionDistance_example.py +24 -0
  12. examples/specific_examples/AffiliationbasedFScore_example.py +24 -0
  13. examples/specific_examples/AverageDetectionCount_example.py +24 -0
  14. examples/specific_examples/CompositeFScore_example.py +24 -0
  15. examples/specific_examples/DelayThresholdedPointadjustedFScore_example.py +24 -0
  16. examples/specific_examples/DetectionAccuracyInRange_example.py +24 -0
  17. examples/specific_examples/EnhancedTimeseriesAwareFScore_example.py +24 -0
  18. examples/specific_examples/LatencySparsityawareFScore_example.py +24 -0
  19. examples/specific_examples/MeanTimeToDetect_example.py +24 -0
  20. examples/specific_examples/NabScore_example.py +24 -0
  21. examples/specific_examples/PateFScore_example.py +24 -0
  22. examples/specific_examples/Pate_example.py +24 -0
  23. examples/specific_examples/PointadjustedAtKFScore_example.py +24 -0
  24. examples/specific_examples/PointadjustedAucPr_example.py +24 -0
  25. examples/specific_examples/PointadjustedAucRoc_example.py +24 -0
  26. examples/specific_examples/PointadjustedFScore_example.py +24 -0
  27. examples/specific_examples/RangebasedFScore_example.py +24 -0
  28. examples/specific_examples/SegmentwiseFScore_example.py +24 -0
  29. examples/specific_examples/TemporalDistance_example.py +24 -0
  30. examples/specific_examples/TimeTolerantFScore_example.py +24 -0
  31. examples/specific_examples/TimeseriesAwareFScore_example.py +24 -0
  32. examples/specific_examples/TotalDetectedInRange_example.py +24 -0
  33. examples/specific_examples/VusPr_example.py +24 -0
  34. examples/specific_examples/VusRoc_example.py +24 -0
  35. examples/specific_examples/WeightedDetectionDifference_example.py +24 -0
  36. tsadmetrics/__init__.py +0 -21
  37. tsadmetrics/base/Metric.py +188 -0
  38. tsadmetrics/evaluation/Report.py +25 -0
  39. tsadmetrics/evaluation/Runner.py +253 -0
  40. tsadmetrics/metrics/Registry.py +141 -0
  41. tsadmetrics/metrics/__init__.py +2 -0
  42. tsadmetrics/metrics/spm/PointwiseAucPr.py +62 -0
  43. tsadmetrics/metrics/spm/PointwiseAucRoc.py +63 -0
  44. tsadmetrics/metrics/spm/PointwiseFScore.py +86 -0
  45. tsadmetrics/metrics/spm/PrecisionAtK.py +81 -0
  46. tsadmetrics/metrics/spm/__init__.py +9 -0
  47. tsadmetrics/metrics/tem/dpm/DelayThresholdedPointadjustedFScore.py +83 -0
  48. tsadmetrics/metrics/tem/dpm/LatencySparsityawareFScore.py +76 -0
  49. tsadmetrics/metrics/tem/dpm/MeanTimeToDetect.py +47 -0
  50. tsadmetrics/metrics/tem/dpm/NabScore.py +60 -0
  51. tsadmetrics/metrics/tem/dpm/__init__.py +11 -0
  52. tsadmetrics/metrics/tem/ptdm/AverageDetectionCount.py +53 -0
  53. tsadmetrics/metrics/tem/ptdm/DetectionAccuracyInRange.py +66 -0
  54. tsadmetrics/metrics/tem/ptdm/PointadjustedAtKFScore.py +80 -0
  55. tsadmetrics/metrics/tem/ptdm/TimeseriesAwareFScore.py +248 -0
  56. tsadmetrics/metrics/tem/ptdm/TotalDetectedInRange.py +65 -0
  57. tsadmetrics/metrics/tem/ptdm/WeightedDetectionDifference.py +97 -0
  58. tsadmetrics/metrics/tem/ptdm/__init__.py +12 -0
  59. tsadmetrics/metrics/tem/tmem/AbsoluteDetectionDistance.py +48 -0
  60. tsadmetrics/metrics/tem/tmem/EnhancedTimeseriesAwareFScore.py +252 -0
  61. tsadmetrics/metrics/tem/tmem/TemporalDistance.py +68 -0
  62. tsadmetrics/metrics/tem/tmem/__init__.py +9 -0
  63. tsadmetrics/metrics/tem/tpdm/CompositeFScore.py +104 -0
  64. tsadmetrics/metrics/tem/tpdm/PointadjustedAucPr.py +123 -0
  65. tsadmetrics/metrics/tem/tpdm/PointadjustedAucRoc.py +119 -0
  66. tsadmetrics/metrics/tem/tpdm/PointadjustedFScore.py +96 -0
  67. tsadmetrics/metrics/tem/tpdm/RangebasedFScore.py +236 -0
  68. tsadmetrics/metrics/tem/tpdm/SegmentwiseFScore.py +73 -0
  69. tsadmetrics/metrics/tem/tpdm/__init__.py +12 -0
  70. tsadmetrics/metrics/tem/tstm/AffiliationbasedFScore.py +68 -0
  71. tsadmetrics/metrics/tem/tstm/Pate.py +62 -0
  72. tsadmetrics/metrics/tem/tstm/PateFScore.py +61 -0
  73. tsadmetrics/metrics/tem/tstm/TimeTolerantFScore.py +85 -0
  74. tsadmetrics/metrics/tem/tstm/VusPr.py +51 -0
  75. tsadmetrics/metrics/tem/tstm/VusRoc.py +55 -0
  76. tsadmetrics/metrics/tem/tstm/__init__.py +15 -0
  77. tsadmetrics/{_tsadeval/affiliation/_integral_interval.py → utils/functions_affiliation.py} +377 -9
  78. tsadmetrics/utils/functions_auc.py +393 -0
  79. tsadmetrics/utils/functions_conversion.py +63 -0
  80. tsadmetrics/utils/functions_counting_metrics.py +26 -0
  81. tsadmetrics/{_tsadeval/latency_sparsity_aware.py → utils/functions_latency_sparsity_aware.py} +1 -1
  82. tsadmetrics/{_tsadeval/nabscore.py → utils/functions_nabscore.py} +15 -1
  83. tsadmetrics-1.0.1.dist-info/METADATA +83 -0
  84. tsadmetrics-1.0.1.dist-info/RECORD +91 -0
  85. tsadmetrics-1.0.1.dist-info/top_level.txt +3 -0
  86. entorno/bin/activate_this.py +0 -32
  87. entorno/bin/rst2html.py +0 -23
  88. entorno/bin/rst2html4.py +0 -26
  89. entorno/bin/rst2html5.py +0 -33
  90. entorno/bin/rst2latex.py +0 -26
  91. entorno/bin/rst2man.py +0 -27
  92. entorno/bin/rst2odt.py +0 -28
  93. entorno/bin/rst2odt_prepstyles.py +0 -20
  94. entorno/bin/rst2pseudoxml.py +0 -23
  95. entorno/bin/rst2s5.py +0 -24
  96. entorno/bin/rst2xetex.py +0 -27
  97. entorno/bin/rst2xml.py +0 -23
  98. entorno/bin/rstpep2html.py +0 -25
  99. tests/test_binary.py +0 -946
  100. tests/test_non_binary.py +0 -450
  101. tests/test_utils.py +0 -49
  102. tsadmetrics/_tsadeval/affiliation/_affiliation_zone.py +0 -86
  103. tsadmetrics/_tsadeval/affiliation/_single_ground_truth_event.py +0 -68
  104. tsadmetrics/_tsadeval/affiliation/generics.py +0 -135
  105. tsadmetrics/_tsadeval/affiliation/metrics.py +0 -114
  106. tsadmetrics/_tsadeval/auc_roc_pr_plot.py +0 -295
  107. tsadmetrics/_tsadeval/discontinuity_graph.py +0 -109
  108. tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/File_IO.py +0 -175
  109. tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/Range.py +0 -50
  110. tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/Time_Plot.py +0 -184
  111. tsadmetrics/_tsadeval/eTaPR_pkg/DataManage/__init__.py +0 -0
  112. tsadmetrics/_tsadeval/eTaPR_pkg/__init__.py +0 -0
  113. tsadmetrics/_tsadeval/eTaPR_pkg/etapr.py +0 -386
  114. tsadmetrics/_tsadeval/eTaPR_pkg/tapr.py +0 -362
  115. tsadmetrics/_tsadeval/metrics.py +0 -698
  116. tsadmetrics/_tsadeval/prts/__init__.py +0 -0
  117. tsadmetrics/_tsadeval/prts/base/__init__.py +0 -0
  118. tsadmetrics/_tsadeval/prts/base/time_series_metrics.py +0 -165
  119. tsadmetrics/_tsadeval/prts/basic_metrics_ts.py +0 -121
  120. tsadmetrics/_tsadeval/prts/time_series_metrics/__init__.py +0 -0
  121. tsadmetrics/_tsadeval/prts/time_series_metrics/fscore.py +0 -61
  122. tsadmetrics/_tsadeval/prts/time_series_metrics/precision.py +0 -86
  123. tsadmetrics/_tsadeval/prts/time_series_metrics/precision_recall.py +0 -21
  124. tsadmetrics/_tsadeval/prts/time_series_metrics/recall.py +0 -85
  125. tsadmetrics/_tsadeval/tests.py +0 -376
  126. tsadmetrics/_tsadeval/threshold_plt.py +0 -30
  127. tsadmetrics/_tsadeval/time_tolerant.py +0 -33
  128. tsadmetrics/binary_metrics.py +0 -1652
  129. tsadmetrics/metric_utils.py +0 -98
  130. tsadmetrics/non_binary_metrics.py +0 -372
  131. tsadmetrics/scripts/__init__.py +0 -0
  132. tsadmetrics/scripts/compute_metrics.py +0 -42
  133. tsadmetrics/utils.py +0 -124
  134. tsadmetrics/validation.py +0 -35
  135. tsadmetrics-0.1.17.dist-info/METADATA +0 -54
  136. tsadmetrics-0.1.17.dist-info/RECORD +0 -66
  137. tsadmetrics-0.1.17.dist-info/entry_points.txt +0 -2
  138. tsadmetrics-0.1.17.dist-info/top_level.txt +0 -6
  139. {tests → tsadmetrics/base}/__init__.py +0 -0
  140. /tsadmetrics/{_tsadeval → evaluation}/__init__.py +0 -0
  141. /tsadmetrics/{_tsadeval/affiliation → metrics/tem}/__init__.py +0 -0
  142. /tsadmetrics/{_tsadeval/vus_utils.py → utils/functions_vus.py} +0 -0
  143. {tsadmetrics-0.1.17.dist-info → tsadmetrics-1.0.1.dist-info}/WHEEL +0 -0
@@ -1,135 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- from itertools import groupby
4
- from operator import itemgetter
5
- import math
6
- import gzip
7
- import glob
8
- import os
9
-
10
- def convert_vector_to_events(vector = [0, 1, 1, 0, 0, 1, 0]):
11
- """
12
- Convert a binary vector (indicating 1 for the anomalous instances)
13
- to a list of events. The events are considered as durations,
14
- i.e. setting 1 at index i corresponds to an anomalous interval [i, i+1).
15
-
16
- :param vector: a list of elements belonging to {0, 1}
17
- :return: a list of couples, each couple representing the start and stop of
18
- each event
19
- """
20
- positive_indexes = [idx for idx, val in enumerate(vector) if val > 0]
21
- events = []
22
- for k, g in groupby(enumerate(positive_indexes), lambda ix : ix[0] - ix[1]):
23
- cur_cut = list(map(itemgetter(1), g))
24
- events.append((cur_cut[0], cur_cut[-1]))
25
-
26
- # Consistent conversion in case of range anomalies (for indexes):
27
- # A positive index i is considered as the interval [i, i+1),
28
- # so the last index should be moved by 1
29
- events = [(x, y+1) for (x,y) in events]
30
-
31
- return(events)
32
-
33
- def infer_Trange(events_pred, events_gt):
34
- """
35
- Given the list of events events_pred and events_gt, get the
36
- smallest possible Trange corresponding to the start and stop indexes
37
- of the whole series.
38
- Trange will not influence the measure of distances, but will impact the
39
- measures of probabilities.
40
-
41
- :param events_pred: a list of couples corresponding to predicted events
42
- :param events_gt: a list of couples corresponding to ground truth events
43
- :return: a couple corresponding to the smallest range containing the events
44
- """
45
- if len(events_gt) == 0:
46
- raise ValueError('The gt events should contain at least one event')
47
- if len(events_pred) == 0:
48
- # empty prediction, base Trange only on events_gt (which is non empty)
49
- return(infer_Trange(events_gt, events_gt))
50
-
51
- min_pred = min([x[0] for x in events_pred])
52
- min_gt = min([x[0] for x in events_gt])
53
- max_pred = max([x[1] for x in events_pred])
54
- max_gt = max([x[1] for x in events_gt])
55
- Trange = (min(min_pred, min_gt), max(max_pred, max_gt))
56
- return(Trange)
57
-
58
- def has_point_anomalies(events):
59
- """
60
- Checking whether events contain point anomalies, i.e.
61
- events starting and stopping at the same time.
62
-
63
- :param events: a list of couples corresponding to predicted events
64
- :return: True is the events have any point anomalies, False otherwise
65
- """
66
- if len(events) == 0:
67
- return(False)
68
- return(min([x[1] - x[0] for x in events]) == 0)
69
-
70
- def _sum_wo_nan(vec):
71
- """
72
- Sum of elements, ignoring math.isnan ones
73
-
74
- :param vec: vector of floating numbers
75
- :return: sum of the elements, ignoring math.isnan ones
76
- """
77
- vec_wo_nan = [e for e in vec if not math.isnan(e)]
78
- return(sum(vec_wo_nan))
79
-
80
- def _len_wo_nan(vec):
81
- """
82
- Count of elements, ignoring math.isnan ones
83
-
84
- :param vec: vector of floating numbers
85
- :return: count of the elements, ignoring math.isnan ones
86
- """
87
- vec_wo_nan = [e for e in vec if not math.isnan(e)]
88
- return(len(vec_wo_nan))
89
-
90
- def read_gz_data(filename = 'data/machinetemp_groundtruth.gz'):
91
- """
92
- Load a file compressed with gz, such that each line of the
93
- file is either 0 (representing a normal instance) or 1 (representing)
94
- an anomalous instance.
95
- :param filename: file path to the gz compressed file
96
- :return: list of integers with either 0 or 1
97
- """
98
- with gzip.open(filename, 'rb') as f:
99
- content = f.read().splitlines()
100
- content = [int(x) for x in content]
101
- return(content)
102
-
103
- def read_all_as_events():
104
- """
105
- Load the files contained in the folder `data/` and convert
106
- to events. The length of the series is kept.
107
- The convention for the file name is: `dataset_algorithm.gz`
108
- :return: two dictionaries:
109
- - the first containing the list of events for each dataset and algorithm,
110
- - the second containing the range of the series for each dataset
111
- """
112
- filepaths = glob.glob('data/*.gz')
113
- datasets = dict()
114
- Tranges = dict()
115
- for filepath in filepaths:
116
- vector = read_gz_data(filepath)
117
- events = convert_vector_to_events(vector)
118
- # ad hoc cut for those files
119
- cut_filepath = (os.path.split(filepath)[1]).split('_')
120
- data_name = cut_filepath[0]
121
- algo_name = (cut_filepath[1]).split('.')[0]
122
- if not data_name in datasets:
123
- datasets[data_name] = dict()
124
- Tranges[data_name] = (0, len(vector))
125
- datasets[data_name][algo_name] = events
126
- return(datasets, Tranges)
127
-
128
- def f1_func(p, r):
129
- """
130
- Compute the f1 function
131
- :param p: precision numeric value
132
- :param r: recall numeric value
133
- :return: f1 numeric value
134
- """
135
- return(2*p*r/(p+r))
@@ -1,114 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- from .generics import (
4
- infer_Trange,
5
- has_point_anomalies,
6
- _len_wo_nan,
7
- _sum_wo_nan,
8
- read_all_as_events)
9
- from ._affiliation_zone import (
10
- get_all_E_gt_func,
11
- affiliation_partition)
12
- from ._single_ground_truth_event import (
13
- affiliation_precision_distance,
14
- affiliation_recall_distance,
15
- affiliation_precision_proba,
16
- affiliation_recall_proba)
17
-
18
- def test_events(events):
19
- """
20
- Verify the validity of the input events
21
- :param events: list of events, each represented by a couple (start, stop)
22
- :return: None. Raise an error for incorrect formed or non ordered events
23
- """
24
- if type(events) is not list:
25
- raise TypeError('Input `events` should be a list of couples')
26
- if not all([type(x) is tuple for x in events]):
27
- raise TypeError('Input `events` should be a list of tuples')
28
- if not all([len(x) == 2 for x in events]):
29
- raise ValueError('Input `events` should be a list of couples (start, stop)')
30
- if not all([x[0] <= x[1] for x in events]):
31
- raise ValueError('Input `events` should be a list of couples (start, stop) with start <= stop')
32
- if not all([events[i][1] < events[i+1][0] for i in range(len(events) - 1)]):
33
- raise ValueError('Couples of input `events` should be disjoint and ordered')
34
-
35
- def pr_from_events(events_pred, events_gt, Trange):
36
- """
37
- Compute the affiliation metrics including the precision/recall in [0,1],
38
- along with the individual precision/recall distances and probabilities
39
-
40
- :param events_pred: list of predicted events, each represented by a couple
41
- indicating the start and the stop of the event
42
- :param events_gt: list of ground truth events, each represented by a couple
43
- indicating the start and the stop of the event
44
- :param Trange: range of the series where events_pred and events_gt are included,
45
- represented as a couple (start, stop)
46
- :return: dictionary with precision, recall, and the individual metrics
47
- """
48
- # testing the inputs
49
- # test_events(events_pred)
50
- # test_events(events_gt)
51
-
52
- # other tests
53
- minimal_Trange = infer_Trange(events_pred, events_gt)
54
- if not Trange[0] <= minimal_Trange[0]:
55
- raise ValueError('`Trange` should include all the events')
56
- if not minimal_Trange[1] <= Trange[1]:
57
- raise ValueError('`Trange` should include all the events')
58
-
59
- if len(events_gt) == 0:
60
- raise ValueError('Input `events_gt` should have at least one event')
61
-
62
- if has_point_anomalies(events_pred) or has_point_anomalies(events_gt):
63
- raise ValueError('Cannot manage point anomalies currently')
64
-
65
- if Trange is None:
66
- # Set as default, but Trange should be indicated if probabilities are used
67
- raise ValueError('Trange should be indicated (or inferred with the `infer_Trange` function')
68
-
69
- E_gt = get_all_E_gt_func(events_gt, Trange)
70
- aff_partition = affiliation_partition(events_pred, E_gt)
71
-
72
- # # Computing precision distance
73
- # d_precision = [affiliation_precision_distance(Is, J) for Is, J in zip(aff_partition, events_gt)]
74
-
75
- # # Computing recall distance
76
- # d_recall = [affiliation_recall_distance(Is, J) for Is, J in zip(aff_partition, events_gt)]
77
-
78
- # Computing precision
79
- p_precision = [affiliation_precision_proba(Is, J, E) for Is, J, E in zip(aff_partition, events_gt, E_gt)]
80
-
81
- # Computing recall
82
- p_recall = [affiliation_recall_proba(Is, J, E) for Is, J, E in zip(aff_partition, events_gt, E_gt)]
83
-
84
- if _len_wo_nan(p_precision) > 0:
85
- p_precision_average = _sum_wo_nan(p_precision) / _len_wo_nan(p_precision)
86
- else:
87
- p_precision_average = p_precision[0] # math.nan
88
- p_recall_average = sum(p_recall) / len(p_recall)
89
-
90
- dict_out = dict({'precision': p_precision_average,
91
- 'recall': p_recall_average,
92
- 'individual_precision_probabilities': p_precision,
93
- 'individual_recall_probabilities': p_recall})
94
- return(dict_out)
95
-
96
- def produce_all_results():
97
- """
98
- Produce the affiliation precision/recall for all files
99
- contained in the `data` repository
100
- :return: a dictionary indexed by data names, each containing a dictionary
101
- indexed by algorithm names, each containing the results of the affiliation
102
- metrics (precision, recall, individual probabilities and distances)
103
- """
104
- datasets, Tranges = read_all_as_events() # read all the events in folder `data`
105
- results = dict()
106
- for data_name in datasets.keys():
107
- results_data = dict()
108
- for algo_name in datasets[data_name].keys():
109
- if algo_name != 'groundtruth':
110
- results_data[algo_name] = pr_from_events(datasets[data_name][algo_name],
111
- datasets[data_name]['groundtruth'],
112
- Tranges[data_name])
113
- results[data_name] = results_data
114
- return(results)
@@ -1,295 +0,0 @@
1
- # import numpy as np
2
- # from scipy.stats import norm
3
- # from matplotlib import pyplot as plt
4
-
5
- # from metrics import f1_from_pr
6
-
7
-
8
- # class Two_1d_normal_distributions:
9
- # def __init__(self, P_ampl, N_ampl, P_mu, N_mu, P_std, N_std, color="b", betas=None):
10
- # self.P_ampl = P_ampl
11
- # self.N_ampl = N_ampl
12
- # self.P_mu = P_mu
13
- # self.N_mu = N_mu
14
- # self.P_std = P_std
15
- # self.N_std = N_std
16
- # self.betas = (1 / 8, 1 / 4, 1 / 2, 1, 2, 4, 8, 16, 32) if betas == None else betas
17
-
18
- # self.color = color
19
- # self.N_color = "k"
20
- # self.P_color = "r"
21
-
22
- # def make(self, delta=0.05, steps=10001, start=-8, stop=8):
23
- # index = 0
24
-
25
- # # For plotting grahps
26
- # self.fpr = []
27
- # self.precision = []
28
- # self.recall = []
29
-
30
- # # For plotting x´s and o´s on the graphs
31
- # self.x_fpr = []
32
- # self.x_precision = []
33
- # self.x_recall = []
34
- # self.xs = 0
35
- # self.x_threshold = []
36
- # self.o_fpr = []
37
- # self.o_precision = []
38
- # self.o_recall = []
39
- # self.os = 0
40
- # self.o_threshold = []
41
-
42
- # # Track maximum f scores for various beta values
43
- # self.max_f = {i: 0 for i in self.betas}
44
- # self.max_f_fpr = {i: 0 for i in self.betas}
45
- # self.max_f_precision = {i: 0 for i in self.betas}
46
- # self.max_f_recall = {i: 0 for i in self.betas}
47
- # self.max_f_thresholds = {i: 0 for i in self.betas}
48
-
49
- # for threshold in np.linspace(start, stop, steps):
50
- # TN = self.N_ampl * norm.cdf(threshold, loc=self.N_mu, scale=self.N_std)
51
- # FP = self.N_ampl - TN
52
- # FN = self.P_ampl * norm.cdf(threshold, loc=self.P_mu, scale=self.P_std)
53
- # TP = self.P_ampl - FN
54
- # self.fpr.append(FP / (FP + TN))
55
- # self.precision.append(TP / (TP + FP))
56
- # self.recall.append(TP / (TP + FN))
57
-
58
- # for beta in self.betas:
59
- # if f1_from_pr(p=self.precision[-1], r=self.recall[-1], beta=beta) > self.max_f[beta]:
60
- # self.max_f[beta] = f1_from_pr(p=self.precision[-1], r=self.recall[-1], beta=beta)
61
- # self.max_f_fpr[beta] = self.fpr[-1]
62
- # self.max_f_precision[beta] = self.precision[-1]
63
- # self.max_f_recall[beta] = self.recall[-1]
64
- # self.max_f_thresholds[beta] = threshold
65
-
66
- # if (FN) / (self.P_ampl) >= self.xs * delta + delta * 0.5:
67
- # self.x_fpr.append(FP / (FP + TN))
68
- # self.x_precision.append(TP / (TP + FP))
69
- # self.x_recall.append(TP / (TP + FN))
70
- # self.xs += 1
71
- # # print(xs, TN+FN)
72
- # self.x_threshold.append(threshold)
73
- # if (TN / self.N_ampl) >= self.os * delta + delta * 0.5:
74
- # self.o_fpr.append(FP / (FP + TN))
75
- # self.o_precision.append(TP / (TP + FP))
76
- # self.o_recall.append(TP / (TP + FN))
77
- # self.os += 1
78
- # self.o_threshold.append(threshold)
79
- # # print(os, TN+FN)
80
-
81
- # def plot_roc_pr(self, roc_ax, pr_ax, plot_xs=True, plot_os=True, plot_fs=False):
82
- # roc_ax.plot(self.fpr, self.recall, self.color, zorder=1)
83
- # pr_ax.plot(self.precision, self.recall, self.color, zorder=1)
84
- # if plot_xs:
85
- # roc_ax.plot(self.x_fpr, self.x_recall, "x", color=self.color, zorder=1)
86
- # pr_ax.plot(self.x_precision, self.x_recall, "x", color=self.color, zorder=1)
87
- # if plot_os:
88
- # roc_ax.plot(self.o_fpr, self.o_recall, "o", color=self.color, fillstyle="none", zorder=1)
89
- # pr_ax.plot(self.o_precision, self.o_recall, "o", color=self.color, fillstyle="none", zorder=1)
90
- # if plot_fs:
91
- # roc_ax.plot(
92
- # list(self.max_f_fpr.values()),
93
- # list(self.max_f_recall.values()),
94
- # ".",
95
- # linestyle="None",
96
- # zorder=2,
97
- # color="k",
98
- # ) # self.color)
99
- # pr_ax.plot(
100
- # list(self.max_f_precision.values()), list(self.max_f_recall.values()), ".", zorder=2, color="k"
101
- # ) # self.color)
102
- # for beta in self.betas:
103
- # # roc_ax.plot([self.max_f_fpr[beta]],[self.max_f_recall[beta]], marker=f"$1/{int(1/beta)}$" if beta<1 else f"${beta}$", linestyle= "None", zorder=2, color="k")
104
- # # pr_ax.plot([self.max_f_precision[beta]], [self.max_f_recall[beta]], marker=f"$1/{int(1/beta)}$" if beta<1 else f"${beta}$", zorder=2, color="k")
105
- # if self.color == "forestgreen": # need to place the numbers differently
106
- # roc_ax.text(
107
- # self.max_f_fpr[beta],
108
- # self.max_f_recall[beta],
109
- # f" $1/{int(1/beta)}$" if beta < 1 else f" ${beta}$",
110
- # horizontalalignment="left",
111
- # verticalalignment="top",
112
- # color=self.color,
113
- # )
114
- # pr_ax.text(
115
- # self.max_f_precision[beta],
116
- # self.max_f_recall[beta],
117
- # f"$1/{int(1/beta)}$" if beta < 1 else f"${beta}$",
118
- # horizontalalignment="left",
119
- # verticalalignment="bottom",
120
- # color=self.color,
121
- # )
122
- # else:
123
- # roc_ax.text(
124
- # self.max_f_fpr[beta],
125
- # self.max_f_recall[beta],
126
- # f"$1/{int(1/beta)}$" if beta < 1 else f"${beta}$",
127
- # horizontalalignment="right",
128
- # verticalalignment="bottom",
129
- # color=self.color,
130
- # )
131
- # pr_ax.text(
132
- # self.max_f_precision[beta],
133
- # self.max_f_recall[beta],
134
- # f"$1/{int(1/beta)}$ " if beta < 1 else f"${beta}$ ",
135
- # horizontalalignment="right",
136
- # verticalalignment="top",
137
- # color=self.color,
138
- # )
139
-
140
- # # adjust axes to get the numbers within the figure
141
- # xmin, xmax = roc_ax.get_xlim()
142
- # xmin, xmax = pr_ax.get_xlim()
143
- # roc_ax.set_xlim([xmin - 0.04, xmax])
144
- # pr_ax.set_xlim([xmin - 0.01, xmax])
145
- # pr_ax.set_xlabel("Precision")
146
- # pr_ax.set_ylabel("Recall")
147
- # roc_ax.set_xlabel("False positive rate")
148
- # roc_ax.set_ylabel("Recall")
149
-
150
- # def plot_roc_prec(self):
151
- # plt.plot(self.fpr, self.recall, self.color, zorder=1)
152
- # plt.plot(self.fpr, self.precision, self.color, zorder=1)
153
- # plt.show()
154
-
155
- # def plot_roc_pr_lines(self, ax):
156
- # ax.plot(self.fpr, np.array(self.recall) + 1, self.color, zorder=1)
157
- # ax.plot(np.array(self.precision) * (-1) + 1, self.recall, self.color, zorder=1)
158
- # for i in range(0, len(self.recall), 5):
159
- # ax.plot(
160
- # [self.fpr[i], 1 - self.precision[i]],
161
- # [self.recall[i] + 1, self.recall[i]],
162
- # marker="o",
163
- # color=self.N_color,
164
- # zorder=1,
165
- # alpha=0.3,
166
- # )
167
-
168
- # def plot_distributions(
169
- # self, axes, start=-5, stop=7, steps=1001, normalize=True, plot_xs=True, plot_os=True, plot_fs=False, threshold=0
170
- # ):
171
- # grid = np.linspace(start, stop, steps)
172
- # fill_alpha = 0.2
173
-
174
- # y = lambda x: norm.pdf(x, loc=self.N_mu, scale=self.N_std) * (1 if normalize else self.N_ampl)
175
- # axes[0].plot(
176
- # grid,
177
- # y(grid),
178
- # color=self.N_color,
179
- # label=f"pdf_N/{self.N_ampl}",
180
- # )
181
-
182
- # axes[0].fill_between(
183
- # grid[grid <= threshold], 0, y(grid[grid <= threshold]), alpha=fill_alpha, lw=0, color="darkgreen"
184
- # )
185
- # axes[0].fill_between(
186
- # grid[grid >= threshold], 0, y(grid[grid >= threshold]), alpha=fill_alpha, lw=0, color="orchid"
187
- # )
188
- # tn_x = min(self.N_mu, threshold - 0.75)
189
- # fp_x = max(self.N_mu, threshold + 0.75)
190
- # axes[0].text(tn_x, y(tn_x) / 2 - 0.005, "TN", horizontalalignment="center", verticalalignment="top")
191
- # axes[0].text(fp_x, y(fp_x) / 2 - 0.005, "FP", horizontalalignment="center", verticalalignment="top")
192
- # # add thresholdline, on the whole y-range
193
- # ymin, ymax = axes[0].get_ylim()
194
- # axes[0].plot([threshold, threshold], [ymin - 1, ymax + 1], "--", color="gray", lw=1)
195
- # axes[0].set_ylim([ymin - 0.02, ymax])
196
-
197
- # # same for anomal distributions
198
- # y = lambda x: norm.pdf(x, loc=self.P_mu, scale=self.P_std) * (1 if normalize else self.P_ampl)
199
- # axes[1].plot(
200
- # grid,
201
- # y(grid),
202
- # color=self.P_color,
203
- # label=f"pdf_P/{self.P_ampl}",
204
- # )
205
- # axes[1].fill_between(
206
- # grid[grid <= threshold], 0, y(grid[grid <= threshold]), alpha=fill_alpha, lw=0, color="chocolate"
207
- # )
208
- # axes[1].fill_between(
209
- # grid[grid >= threshold], 0, y(grid[grid >= threshold]), alpha=fill_alpha, lw=0, color="darkcyan"
210
- # )
211
- # fn_x = min(self.P_mu, threshold - 0.75)
212
- # tp_x = max(self.P_mu, threshold + 0.75)
213
- # axes[1].text(fn_x, y(fn_x) / 2, "FN", horizontalalignment="center", verticalalignment="top")
214
- # axes[1].text(tp_x, y(tp_x) / 2, "TP", horizontalalignment="center", verticalalignment="top")
215
-
216
- # # add thresholdline, on the whole y-range
217
- # ymin, ymax = axes[1].get_ylim()
218
- # axes[1].plot([threshold, threshold], [ymin - 1, ymax + 1], "--", color="gray", lw=1)
219
- # axes[1].set_ylim([ymin, ymax])
220
-
221
-
222
- # def plot_cdf(self, ax, start=-6, stop=8, steps=1001, normalize=True):
223
- # grid = np.linspace(start, stop, steps)
224
-
225
- # ax.plot(
226
- # grid,
227
- # norm.cdf(grid, loc=self.N_mu, scale=self.N_std) * (1 if normalize else self.N_ampl),
228
- # color=self.N_color,
229
- # label=f"pdf_N/{self.N_ampl}",
230
- # )
231
- # ax.plot(
232
- # grid,
233
- # norm.cdf(grid, loc=self.P_mu, scale=self.P_std) * (1 if normalize else self.P_ampl),
234
- # color=self.P_color,
235
- # label=f"pdf_P/{self.P_ampl}",
236
- # )
237
-
238
-
239
- # if __name__ == "__main__":
240
-
241
- # # Make detector distributions
242
-
243
- # t1 = Two_1d_normal_distributions(
244
- # 1, 49, 1.8, -1, 2, 1, color="mediumblue", betas=(1 / 8, 1 / 4, 1 / 2, 1, 2, 4, 8, 16)
245
- # )
246
- # t2 = Two_1d_normal_distributions(
247
- # 1, 49, 1, -1, 1, 1, color="forestgreen", betas=(1 / 8, 1 / 4, 1 / 2, 1, 2, 4, 8, 16)
248
- # )
249
-
250
- # t1.make(steps=1001, delta=0.1)
251
- # t2.make(steps=1001, delta=0.1)
252
-
253
-
254
- # # Make roc and pr plots
255
-
256
- # figsize = (4, 4)
257
-
258
- # roc_fig, roc_ax = plt.subplots(figsize=figsize)
259
- # pr_fig, pr_ax = plt.subplots(figsize=figsize)
260
- # t1.plot_roc_pr(roc_ax, pr_ax, False, False, True)
261
- # t2.plot_roc_pr(roc_ax, pr_ax, False, False, True)
262
- # roc_fig.tight_layout()
263
- # pr_fig.tight_layout()
264
- # roc_fig.savefig("auc_roc_f.pdf")
265
- # pr_fig.savefig("auc_pr_f.pdf")
266
- # plt.show()
267
- # plt.close("all")
268
-
269
-
270
- # # Make distribution plots
271
-
272
- # figsize = (5, 3)
273
-
274
- # for beta in t1.betas: # [16,4,1,1/4,1/8]:
275
- # fig, axes = plt.subplots(2, 2, figsize=figsize, sharex=True, sharey=True)
276
- # t1.plot_distributions(
277
- # [axes[0][0], axes[1][0]], plot_xs=False, plot_os=False, plot_fs=True, threshold=t1.max_f_thresholds[beta]
278
- # )
279
- # t2.plot_distributions(
280
- # [axes[0][1], axes[1][1]], plot_xs=False, plot_os=False, plot_fs=True, threshold=t2.max_f_thresholds[beta]
281
- # )
282
-
283
- # axes[0][0].set_title(f"Blue detector", color=t1.color)
284
- # axes[0][1].set_title("Green detector", color=t2.color)
285
- # axes[1][0].set_xlabel("Anomaly \n score", color=t1.color)
286
- # axes[1][1].set_xlabel("Anomaly \n score", color=t2.color)
287
- # shadowaxes = fig.add_subplot(111, xticks=[], yticks=[], frame_on=False)
288
- # shadowaxes.set_ylabel("Probability density", labelpad=25)
289
- # fig.tight_layout()
290
- # axes[0][0].set_ylabel("Normal\nsamples", labelpad=25)
291
- # axes[1][0].set_ylabel("Anomalous\nsamples", labelpad=25)
292
-
293
- # plt.subplots_adjust(hspace=0.0)
294
- # plt.savefig(f"auc_distributions_b{beta}.pdf")
295
- # plt.show()
@@ -1,109 +0,0 @@
1
- # from maketable import *
2
-
3
-
4
- # class Score_graphs_table(Table):
5
- # def __init__(self, metric_names, results, marks=[]):
6
- # self.metric_names = metric_names
7
- # self.results = results
8
- # self.marks = marks
9
- # super().__init__(Table_content([], [], []), scale=2)
10
- # self.x_factor = 1 / 20 * self.scale
11
- # self.y_factor = 1 / 2
12
- # self.y_shift = -0.2
13
-
14
- # self.row_length = 2
15
- # self.n_rows = len(metric_names)
16
-
17
- # def add_top_row(self):
18
- # self.string += "Metric"
19
- # self.string += "&"
20
- # self.string += "Score"
21
- # self.end_row()
22
-
23
- # def add_next_row(self):
24
- # self.string += self.metric_names[self.rows_added]
25
- # self.string += "&"
26
- # self.add_graph(self.rows_added + 1)
27
- # self.end_row()
28
- # self.rows_added += 1
29
-
30
- # def add_graph(self, number):
31
- # self.add_line(f"\\begin{{tikzpicture}}[baseline=-\\the\\dimexpr\\fontdimen22\\textfont2\\relax]")
32
- # for x in self.marks:
33
- # self.add_line(
34
- # f"\draw[-, gray] ({x*self.x_factor},{self.y_shift}) -- ({x*self.x_factor},{0.2*self.y_factor + self.y_shift});"
35
- # )
36
- # self.add_line(
37
- # f"\draw[-, gray] (0,{self.y_shift}) -- ({self.x_factor*(len(self.results[self.metric_names[number-1]])-1)},{self.y_shift});"
38
- # )
39
- # self.add_line("\\foreach \\i/\\a in")
40
- # self.add_line(
41
- # str(
42
- # [
43
- # (round(i * self.x_factor, 3), round(a * self.y_factor + self.y_shift, 3))
44
- # for i, a in enumerate(self.results[self.metric_names[number - 1]])
45
- # ]
46
- # )
47
- # .replace(",", "/")
48
- # .replace(")/", ",")
49
- # .replace("(", "")
50
- # .replace("[", "{")
51
- # .replace("]", "}")
52
- # .replace(")}", "}{")
53
- # )
54
- # self.add_line("\\coordinate (now) at (\\i,\\a) {};")
55
- # self.add_line(" \\ifthenelse{\\equal{\\i}{0.0}}{}{")
56
- # self.add_line(" \\draw[-, teal, thick] (prev) -- (now);")
57
- # self.add_line(" }")
58
- # self.add_line(" \\coordinate (prev) at (\\i,\\a) {};")
59
- # self.add_line("}")
60
- # self.add_line("\\end{tikzpicture}")
61
-
62
-
63
- # def score_graphs():
64
- # # define scenario
65
- # ts_length = 100
66
- # pred_length = 5
67
- # gt_length = 20
68
- # gt_start = 40
69
- # marks = [35, 40, 55, 60]
70
- # assert pred_length % 2 == 1
71
-
72
- # # prepare metrics list
73
- # All_metrics.remove(metrics.Range_PR)
74
- # all_metrics_and_rffront = [*All_metrics, metrics.Range_PR, Range_PR_front]
75
-
76
- # # make results and names
77
- # metric_names = []
78
- # result = {}
79
- # for metric in all_metrics_and_rffront:
80
- # # set names
81
- # if metric == metrics.TaF:
82
- # metric_names.append(metric(5, [3, 4], [3], delta=10).name)
83
- # elif metric == metrics.Time_Tolerant:
84
- # metric_names.append(metric(5, [3, 4], [3], d=10).name)
85
- # else:
86
- # metric_names.append(metric(5, [3, 4], [3]).name)
87
-
88
- # # get results
89
- # current_result = []
90
- # for pred_mid in range(pred_length // 2, ts_length - pred_length // 2):
91
- # gt = [[gt_start, gt_start + gt_length - 1]]
92
- # pred = [[pred_mid - pred_length // 2, pred_mid + pred_length // 2]]
93
- # if metric == metrics.TaF:
94
- # current_result.append(metric(ts_length, gt, pred, delta=10).get_score())
95
- # elif metric == metrics.Time_Tolerant:
96
- # current_result.append(metric(ts_length, gt, pred, d=10).get_score())
97
- # else:
98
- # current_result.append(metric(ts_length, gt, pred).get_score())
99
- # current_result = np.array(current_result)
100
- # current_result = (current_result - min(current_result)) / (max(current_result) - min(current_result))
101
- # result[metric_names[-1]] = current_result
102
-
103
- # # make the table
104
- # table = Score_graphs_table(metric_names, result, marks)
105
- # table.write()
106
- # print(table)
107
-
108
-
109
- # score_graphs()