import son_analyze
import son_scikit
print('Welcome to son-analyze v{} and son-scikit v{}.'.format(son_analyze.__version__, son_scikit.__version__))

"""
Explanation: son-analyze tutorial notebook

Setup
The son_analyze and son_scikit packages contains the function related to SONATA.
* son_analyze handles gathering data from the SONATA's SP or emulator
* son_scikit manipulates the metrics to work with analytics libraries
End of explanation
"""


import helpers
print('You can use and tweak the python code in the helpers.py file (example: "{}")'.format(helpers.foobar()))

"""
Explanation: You can write and use Python files and call their functions inside your notebooks to keep them simples.
End of explanation
"""


import reprlib
import json
import arrow
import requests
from son_analyze.core.prometheus import PrometheusData
from son_scikit.hl_prometheus import build_sonata_df_by_id

all_dataframes = None
with open('empty_vnf1_sonemu_rx_count_packets_180.json') as raw:
    x = PrometheusData(raw.read())
    all_dataframes = build_sonata_df_by_id(x)

"""
Explanation: Fetching metrics
To keep this example self-contained, the data is read from a static file. The metrics are stored held in a all_dataframes variable.
End of explanation
"""


print('The dictonnary of all dataframes by VNF names: {}'.format(reprlib.repr(all_dataframes)))
print(all_dataframes['empty_vnf1'].head())

"""
Explanation: Each VNF has its own dataframe where metrics have a corresponding column. Here, the empty_vnf1 VNF has a sonemu_rx_count_packets column for the monitored received packets on the network.
End of explanation
"""


import matplotlib
import matplotlib.pyplot as plt
matplotlib.style.use('ggplot')
%matplotlib inline
matplotlib.rcParams['figure.figsize'] = (20.0, 5.0)

df = all_dataframes['empty_vnf1']
ddf = df.diff().dropna()

df.plot();
ddf.plot();

"""
Explanation: Basic plotting
From there we use the df and ddf variables as shortcuts, before plotting them.
* df is the main dataframe we are going to work with
* ddf contains the discrete difference of df
End of explanation
"""


error_ddf = ddf.copy()
error_ddf.sonemu_rx_count_packets[1111] *= 2.6
error_ddf.sonemu_rx_count_packets[3333] *= 2.7

"""
Explanation: Injecting errors in the metrics
For this tutorial, we inject two errors in the metrics. This is done inside the error_ddf dataframe.
End of explanation
"""


from pyculiarity import detect_ts
import pandas as pd
import time


def f(x):
    dt = x.to_datetime()
    return time.mktime(dt.timetuple())

target = error_ddf
u = pd.DataFrame({'one': list(target.index.map(f)), 'two': target.sonemu_rx_count_packets})
results = detect_ts(u, max_anoms=0.004, alpha=0.01, direction='both') #, threshold='med_max')

"""
Explanation: Detecting anomalies
We use the pyculiarity package to detect anomalies in a dataframe using the detect_ts function.
End of explanation
"""


# make a nice plot
matplotlib.rcParams['figure.figsize'] = (20.0, 10.0)
f, ax = plt.subplots(2, 1, sharex=True)
ax[0].plot(target.index, target.sonemu_rx_count_packets, 'b')
ax[0].plot(results['anoms'].index, results['anoms']['anoms'], 'ro')
ax[0].set_title('Detected Anomalies')
ax[1].set_xlabel('Time Stamp')
ax[0].set_ylabel('Count')
ax[1].plot(results['anoms'].index, results['anoms']['anoms'], 'b')
ax[1].set_ylabel('Anomaly Magnitude')
plt.show()

"""
Explanation: The resulting plot clearly shows the 2 anomalies.
End of explanation
"""


