import pyisc;
import numpy as np
from scipy.stats import poisson
%matplotlib inline
from pylab import hist, plot, figure

"""
Explanation: pyISC Example: Simple Anomaly Detection with Frequency Data
This is a simple example on how to use the pyISC anomaly detector for computing the anomaly scores of Poisson distributed data.
End of explanation
"""


po_normal = poisson(10)
po_anomaly = poisson(25)

freq_normal = po_normal.rvs(10000)
freq_anomaly = po_anomaly.rvs(15)

"""
Explanation: Data Creation
Create two arrays with normal and anomalous frequency data respectively.</b>
End of explanation
"""


data = np.column_stack([
        list(freq_normal)+list(freq_anomaly), 
        [1.0]*(len(freq_normal)+len(freq_anomaly))
    ])
data[:5]

"""
Explanation: Create an 2D array with two columns that combines random frequency and time period equal to 1.
End of explanation
"""


hist(data.T[0],100);

"""
Explanation: If we plot the histogram from the frequency data, we can see that the distribution tail is thicker at the right side because of the anomalous data points:
End of explanation
"""


anomaly_detector = pyisc.AnomalyDetector(
    pyisc.P_PoissonOnesided(frequency_column=0,period_column=1)
)

"""
Explanation: Used Anomaly Detector
Create an anomaly detector using as first argument the P_PoissonOneside statistical model, that is, we use a Poisson distribution for modelling data, but we only care of anomalous large frequencies. The second argument is an array containg the column index used as input to the statsitical model where 0 is the column index of frequencies and 1 is the column index of the period in the data object:
End of explanation
"""


%timeit anomaly_detector.fit(data);

"""
Explanation: Train the anomaly detector:
End of explanation
"""


scores = anomaly_detector.anomaly_score(data)

"""
Explanation: Compute the anomaly scores for each data point:
End of explanation
"""


for s in zip(freq_normal[:15], scores[:15]):
    print s

"""
Explanation: Anomaly Scores
Now we can print some example of normal frequencies vs. anomaly scores:
End of explanation
"""


for s in zip(freq_anomaly, scores[-15:]):
    print s

"""
Explanation: The anomalous frequencies vs. anomaly scores:
End of explanation
"""


plot(data.T[0], scores, '.');

"""
Explanation: As can be seen above, the anomalous frequences also have higher anomaly scores than the normal frequencies as it should be.<br/><br/> This becomes even more visible if we plot the frequency (x-axis) against anomaly scores (y-axis):
End of explanation
"""


data2 = np.column_stack([
            poisson(15).rvs(15), 
            [1.0]*15
        ])
anomaly_detector.fit_incrementally(data2);

scores_ = anomaly_detector.anomaly_score(data)

figure(1);plot(data.T[0], scores, 'b.');plot(data.T[0], scores_, 'gx');

"""
Explanation: So, depending on at what level we would consider a frequency an anomaly, we can set a threshold to decide if a frequency is anomalous.
We can also "confuse" the anomaly detector by adding more normal training data closer to the anomalous data:
End of explanation
"""


