##############################################################################
# Author: Bernard Hernandez
# Filename: 03-main-create-sari-idxs.py
# Description : This file contains differnent statistics used in time-series.
# What it mainly does is to format the output of tests provided
# by external libraries and return them in a dataframe.
#
# TODO: Move it to a module.
#
###############################################################################
# Forces decimals on divisions.
from __future__ import division
# Libraries
import sys
import numpy as np
import pandas as pd
import statsmodels.api as sm
[docs]class SigmoidA:
def __init__(self, r=200, g=0.5, offset=0.0, scale=1.0,
percentiles=None, thresholds=None):
"""This function initialises the parameters.
Parameters
----------
r : affects the ....
g : affects the ....
offset : to offset the final sigmoid.
scale : to scale the [0,1] sigmoid to the new range.
percentiles :
thresholds :
"""
self.r = r
self.g = g
self.offset = offset
self.scale = scale
self.percentiles = percentiles
self.thresholds = thresholds
# ---------------------------------------------------------------------------
# HELPER METHODS
# ---------------------------------------------------------------------------
def _identifier(self, short=True):
"""This methods describes de model."""
# Return short description.
if short:
per = 'N' if self.percentiles is None else self.percentiles
ths = 'N' if self.thresholds is None else self.thresholds
return "Sig(%s, %s)" % (per, ths)
# Return full description.
return "%s(r=%s, g=%s, offset=%s, sc=%s, per=%s, ths=%s)" % \
(self.__class__.__name__, self.r, self.g, self.offset, self.scale,
self.percentiles, self.thresholds)
# ---------------------------------------------------------------------------
# SIGMOID
# ---------------------------------------------------------------------------
[docs] def approximated_sigmoid(self, x, x_curves=None):
"""This function computes the approximated sigmoid.
Note: The approximated sigmoid is defined within the interval [0,1].
.. note: Produces a RuntimeWarning: invalid value encountered in
true_divide z = (x-cmin) / (cmax-cmin) when the parameter
x has always the same value.
Parameters
----------
x: numpy.array
The values to be converted to weights.
x_curves: tuple
The values indicating where the low/upper curves should start.
Returns
-------
r : numpy.array
The weights.
"""
# Where the two curves should start.
cmin, cmax = x_curves if x_curves is not None else [np.min(x), np.max(x)]
# Sigmoid variables.
z = (x-cmin) / (cmax-cmin)
# Approximated sigmoid.
r = (lambda t: (1+self.r**(-t+self.g))**(-1)) (z)
# Normalize so it goes between zero and one.
# This happens when cmin=np.min(x) and cmax=n.max(x)
r = (r-np.min(r)) / (np.max(r)-np.min(r))
# Return
return r
# ---------------------------------------------------------------------------
# HELPER METHODS
# ---------------------------------------------------------------------------
[docs] def threshold(self, r, x, thresholds=(None,None)):
"""This function thresholds the r given the values of x.
Parameters
----------
x: numpy.array
The values to be converted to weights.
r: numpy.array
The weights to be thresholded.
threshold_low: number;
The values in x lower will have minimum weight.
treshold_high: number;
The values in x higher will have maximum weight.
Returns
-------
"""
# Get thresholds
threshold_low, threshold_high = thresholds
# Lower threshold.
if threshold_low is not None:
r = np.where(x<threshold_low, 0, r)
# Upper threshold.
if threshold_high is not None:
r = np.where(x>threshold_high, np.max(r), r)
# Return
return r
# ---------------------------------------------------------------------------
# WEIGHTS
# ---------------------------------------------------------------------------
[docs] def weights_standard(self, x):
"""This function returns the weights."""
return self.approximated_sigmoid(x)
[docs] def weights_percentile(self, x, percentiles):
"""This function returns the weights.
Parameters
----------
x :
x_percentiles :
Returns
-------
weights :
"""
# Get percentiles
percentile_low, percentile_high = percentiles
# Create sigmoid with curves in such percentiles.
r = self.approximated_sigmoid(x, [np.percentile(x, percentile_low), \
np.percentile(x, percentile_high)])
# Return
return r
[docs] def weights(self, x):
"""This cuntion computes the weights.
Parameters
----------
x :
x_percentiles :
x_threshold_low :
x_threshold_high :
Returns
-------
"""
# Get the standard sigmoid or a perso
if self.percentiles is None:
r = self.weights_standard(x)
else :
r = self.weights_percentile(x, self.percentiles)
# Treshold the result.
if self.thresholds is not None:
r = self.threshold(r, x, self.thresholds)
# Return
return self.offset + self.scale*r
if __name__ == '__main__': # pragma: no cover
# Libraries
import matplotlib as mpl
import matplotlib.pyplot as plt
import statsmodels.robust.norms as norms
# ------------
# Basic sample
# ------------
# Create SigmoidA instance
W = SigmoidA(r=200, g=0.5, offset=0.0, scale=1.0)
# Compute weights
w = np.ones((1, 5)) * 3
r = W.weights(w)
# Show
print("\nWeights:")
print(w)
print(r)
# ----------------
# Various samples
# ----------------
# Matplotlib options
mpl.rc('legend', fontsize=6)
mpl.rc('xtick', labelsize=6)
mpl.rc('ytick', labelsize=6)
mpl.rc('font', size=7)
# Set pandas configuration.
pd.set_option('display.max_colwidth', 14)
pd.set_option('display.width', 150)
pd.set_option('display.precision', 4)
# Constants
length = 100
# Create time-series.
x = np.linspace(0,100,100)
f = np.concatenate((np.random.rand(35)*50+50,
np.random.rand(30)*50+100,
np.random.rand(35)*50+150))
# Weight Functions
w_functions = [
SigmoidA(r=200, g=0.5, offset=0.0, scale=1.0),
SigmoidA(r=200, g=0.5, offset=0.0, scale=1.0, percentiles=[10,90]),
SigmoidA(r=200, g=0.5, offset=0.0, scale=1.0, percentiles=[25,75]),
SigmoidA(r=200, g=0.5, offset=0.0, scale=1.0, percentiles=[40,50]),
SigmoidA(r=200, g=0.5, offset=0.0, scale=1.0, thresholds=[15,85])]
# Create figure
fig, axes = plt.subplots(1,3, figsize=(10,4))
# Plot frequencies
axes[1].bar(x, f, color='gray', alpha=0.7, label='Frequency')
# Plot weights
for i,W in enumerate(w_functions):
axes[0].plot(x, W.weights(x), label=W._identifier(short=True))
axes[2].plot(x, W.weights(f), marker='o', alpha=0.5,
markeredgecolor='k', markeredgewidth=0.5, markersize=4,
linewidth=0.00, label=W._identifier(short=True))
# Titles
axes[0].set_title('Sigmoid Function')
axes[1].set_title('Frequencies')
axes[2].set_title('Weights')
# Legends
axes[0].legend()
axes[1].legend()
axes[2].legend()
# Tight layout
plt.tight_layout()
# Show
# plt.show()