def test_base_derivative_non_linear(self): self.maxDiff = None series1 = Series.from_array([ [0, 1], [1, 2], [2, 4], [3, 0], [4, 16], ]) factory = NodeFactory.transformer('test', 'Derivative') factory.set_param_value('lag', '1') factory.set_param_value('metric', 'sub') diff = factory.build() result, debug_info = diff.transform([series1], False) expected_series = Series.from_array([ [1, 1], [2, 2], [3, -4], [4, 16], ]) self.assertEqual(list(expected_series.pdseries.index), list(result.index)) self.assertEqual(list(expected_series.pdseries.values), list(result.values))
def test_integration_performance(self): self.maxDiff = None pipeline = Pipeline.from_json(self.load_json('pipeline')) input1 = Series.from_array(self.load_json('input1'), unit='ms') input2 = Series.from_array(self.load_json('input2'), unit='ms') analyzer = Analyzer(pipeline, True) result = analyzer.analyze({'1': input1, '2': input2}) # pr = cProfile.Profile() # pr.enable() actual_output = result.output_format() # pr.disable() # pr.dump_stats('output.prof') # s = io.StringIO() # sortby = 'cumulative' # ps = pstats.Stats(pr, stream=s).sort_stats(sortby) # ps.print_stats() # print(s.getvalue()) expected_file = os.path.join(os.path.dirname(__file__), 'resources/perf/expected_output.json') # Uncomment to fix test # print(json.dumps(actual_output, indent=2), file=open(expected_file, 'w')) expected_output = json.loads(Path(expected_file).read_text()) self.assertEqual(expected_output, actual_output)
def test_divide_discard_fill_zero_div(self): series1 = Series.from_array([[1, 1], [2, 2], [3, 3]]) series2 = Series.from_array([[1, 2], [2, 0], [3, 5]]) factory = NodeFactory.transformer('test', 'Divide') factory.set_param_value('zero_div', 0) divide = factory.build() result, debug_info = divide.transform([series1, series2], False) expected_series = pd.Series([1 / 2, 0.0, 3 / 5], index=series1.pdseries.index) self.assertEqual(list(expected_series.index), list(result.index)) self.assertEqual(list(expected_series.values), list(result.values))
def test_multi_rolling_aggregate_correlation(self): factory = NodeFactory.transformer('test', 'MultiRollingAggregate') factory.set_param_value('window', '2') factory.set_param_value('center', False) factory.set_param_value('min_periods', '0') factory.set_param_value('agg_method', 'correlation_pearson') factory.add_source(InputRef('lhs')) factory.add_source(InputRef('rhs')) ram = factory.build() s1 = Series.from_array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]]) s2 = Series.from_array([[0, 1], [1, 2], [2, 3], [3, 2], [4, 1]]) self.case(ram, s1, s2, list(s1.pdseries.index)[1:], [1, 1, -1, -1])
def test_multi_rolling_aggregate_mismatching_start(self): factory = NodeFactory.transformer('test', 'MultiRollingAggregate') factory.set_param_value('window', '1') factory.set_param_value('center', False) factory.set_param_value('min_periods', '0') factory.set_param_value('agg_method', 'proportion') factory.add_source(InputRef('lhs')) factory.add_source(InputRef('rhs')) ram = factory.build() s1 = Series.from_array([[0, 1], [1, 2], [2, 3], [3, 4]]) s2 = Series.from_array([[1, 5], [2, 5], [3, 5]]) self.case(ram, s1, s2, list(s2.pdseries.index), [2 / 5, 3 / 5, 4 / 5])
def test_multi_rolling_aggregate_proportion_window_min_periods_default( self): factory = NodeFactory.transformer('test', 'MultiRollingAggregate') factory.set_param_value('window', '2') factory.set_param_value('center', False) factory.set_param_value('min_periods', '') factory.set_param_value('agg_method', 'proportion') factory.add_source(InputRef('lhs')) factory.add_source(InputRef('rhs')) ram = factory.build() s1 = Series.from_array([[0, 1], [1, 2], [2, 3], [3, 4]]) s2 = Series.from_array([[0, 5], [1, 5], [2, 5], [3, 5]]) self.case(ram, s1, s2, list(s1.pdseries.index[1:]), [0.3, 0.5, 0.7])
def test_analysis_histogram_heatmap(self): self.maxDiff = None series = Series.from_array([ [1628294400, 0], [1628337600, 0], [1628380800, 1], [1628424000, 1], [1628467200, 1], [1628510400, 0], [1628553600, 0], [1628596800, 0], ]) factory = NodeFactory.detector('test_node', 'SimpleThreshold') factory.set_param_value('inside', False) factory.set_param_value('strict', False) factory.set_param_value('lower', None) factory.set_param_value('upper', 1) factory.add_source(InputRef('input')) node = factory.build() pipeline = Pipeline([node]) analyzer = Analyzer(pipeline=pipeline, debug=True) analysis = analyzer.analyze({'input': series}) actual_output = analysis.output_format() expected_file = os.path.join(os.path.dirname(__file__), 'resources/analysis/expected_histogram_heatmap.json') # Uncomment to fix test # print(json.dumps(actual_output, indent=2), file=open(expected_file, 'w')) expected_output = json.loads(Path(expected_file).read_text()) self.assertEqual(expected_output, actual_output)
def test_exog_seesaw(self): exog = Series.from_array([ [0, 1], [1, -1], [2, 1], [3, -1], [4, 1], [5, -1], [6, 1], [7, -1], [8, 1], [9, -1], ]) endog = TestSeriesBuilder.linear(10, 0, 1).build() factory = NodeFactory.transformer('test', 'SARIMAX') factory.set_param_value('p', '1') factory.set_param_value('d', 1) factory.set_param_value('output', 'resid') sarimax = factory.build() result, debug_info = sarimax.transform([endog, exog], True) expected_series = [0] * 8 actual_series = list(result.values) for i in range(0, len(expected_series)): self.assertAlmostEqual(expected_series[i], actual_series[i], 2) # With debug info self.assertEqual(set(['summary', 'offset_start', 'exog_coeff_x1']), set(debug_info.keys()))
def __init__(self, methodName): unittest.TestCase.__init__(self, methodName) self.series = Series.from_array([ [0, 0], [1, 1], [2, 1], [3, 0], ])
def test_anomalies_from_mock_edge_case(self): test_series = Series.from_array([[0, 1], [1, 0], [2, 1]]) anomalies = TestCase.anomalies_from_mock_series(test_series) self.assertEqual(2, len(anomalies)) self.assertEqual(test_series.pdseries.index[0], anomalies[0].start) self.assertEqual(test_series.pdseries.index[0], anomalies[0].end) self.assertEqual(test_series.pdseries.index[2], anomalies[1].start) self.assertEqual(test_series.pdseries.index[2], anomalies[1].end)
def case(self, node, fst_anomalies, snd_anomalies, expected_output, expected_debug): fst_node = Node('fst') snd_node = Node('snd') [a.set_source_node(fst_node) for a in fst_anomalies] [a.set_source_node(snd_node) for a in snd_anomalies] fst_series = Series.from_array([[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0]]) snd_series = Series.from_array([[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0]]) fst_input = NodeResult(None, None, output_series=fst_series, anomalies=fst_anomalies) snd_input = NodeResult(None, None, output_series=snd_series, anomalies=snd_anomalies) result = node.execute([fst_input, snd_input], True) expected_display_series = { 'input_1': fst_series, 'input_2': snd_series } self.assertEqual(expected_display_series, result.display_series()) actual_anomalies = list( map(lambda a: a.output_format(), result.anomalies)) self.assertEqual(expected_output, actual_anomalies) self.assertEqual(expected_debug, result.debug_info) # Check no anomaly sources outside of original anomalies all_anomaly_sources = set() for anomaly in result.anomalies: for source_anomaly in anomaly.source_anomalies: all_anomaly_sources.add(source_anomaly) self.assertEqual( set(), all_anomaly_sources - set(fst_anomalies + snd_anomalies))
def build_series(self): series = Series.from_array([ [0, 1], [1, 1], [2, 1], [3, 3], [4, 3], [5, 1], [6, 1], [7, 1], ]) return series
def case(self, node, fst_anomalies, snd_anomalies): self.maxDiff = None fst_node = Node('fst') snd_node = Node('snd') [a.set_source_node(fst_node) for a in fst_anomalies] [a.set_source_node(snd_node) for a in snd_anomalies] fst_series = Series.from_array([ [0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0] ]) snd_series = Series.from_array([ [0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0] ]) fst_input = NodeResult(None, None, output_series=fst_series, anomalies=fst_anomalies) snd_input = NodeResult(None, None, output_series=snd_series, anomalies=snd_anomalies) result = node.execute([fst_input, snd_input], False) expected_display_series = {'input_1': fst_series, 'input_2': snd_series} self.assertEqual(expected_display_series, result.display_series()) return result.anomalies
def test_seesaw(self): series = Series.from_array([[0, 1], [1, -1], [2, 1], [3, -1], [4, 1], [5, -1]]) factory = NodeFactory.transformer('test', 'SARIMAX') factory.set_param_value('p', '1') factory.set_param_value('output', 'resid') sarimax = factory.build() result, debug_info = sarimax.transform([series], True) expected_series = [0] * 5 actual_series = list(result.values) for i in range(0, len(expected_series)): self.assertAlmostEqual(expected_series[i], actual_series[i], 2)
def test_metrics_case1(self): test_series = Series.from_array([[0, 0], [1, 1], [2, 0], [3, 0], [4, 0], [5, 1], [6, 1], [7, 0]]) actual_anomalies = [ Anomaly.from_epoch(1, 1), Anomaly.from_epoch(2, 2), Anomaly.from_epoch(4, 4) ] analyzer = MockAnalyzer(actual_anomalies) expected_anomalies = TestCase.anomalies_from_mock_series(test_series) expected_analysis = Analysis(test_series, None, expected_anomalies, False) test = TestCase("testcase1", test_series, analyzer, expected_analysis) result = test.run() anomaly_metrics = result.anomaly_metrics expected_tp = mcb.epochs_to_timestamp([1]) expected_fp = mcb.epochs_to_timestamp([2, 4]) expected_tn = mcb.epochs_to_timestamp([0, 3, 7]) expected_fn = mcb.epochs_to_timestamp([5, 6]) self.assertEqual(expected_tp, anomaly_metrics.tp) self.assertEqual(expected_fp, anomaly_metrics.fp) self.assertEqual(expected_tn, anomaly_metrics.tn) self.assertEqual(expected_fn, anomaly_metrics.fn) self.assertEqual(1, anomaly_metrics.tp_count()) self.assertEqual(2, anomaly_metrics.fp_count()) self.assertEqual(2, anomaly_metrics.fn_count()) self.assertEqual(3, anomaly_metrics.tn_count()) expected_tp_ranges = mcb.epochs_to_ranges([[1, 2]]) expected_fp_ranges = mcb.epochs_to_ranges([[2, 3], [4, 5]]) expected_fn_ranges = mcb.epochs_to_ranges([[5, 7]]) self.assertEqual(expected_tp_ranges, anomaly_metrics.tp_ranges) self.assertEqual(expected_fp_ranges, anomaly_metrics.fp_ranges) self.assertEqual(expected_fn_ranges, anomaly_metrics.fn_ranges) self.assertAlmostEqual(0.33, anomaly_metrics.precision(), 2) self.assertAlmostEqual(0.33, anomaly_metrics.recall(), 2) self.assertAlmostEqual(0.33, anomaly_metrics.f1(), 2)
def test_base_derivative_lag2(self): series1 = TestSeriesBuilder.linear(5, 0, 1).build() factory = NodeFactory.transformer('test', 'Derivative') factory.set_param_value('lag', '2') factory.set_param_value('metric', 'sub') diff = factory.build() result, debug_info = diff.transform([series1], False) expected_series = Series.from_array([ [2, 2], [3, 2], [4, 2], ]) self.assertEqual(list(expected_series.pdseries.index), list(result.index)) self.assertEqual(list(expected_series.pdseries.values), list(result.values))
def build(self): return Series.from_array(self.data, self.unit)