import pandas as pd
pd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import coint
import seaborn

from pandas_datareader import data

symbolsIds = ['SPY','AAPL','ADBE','LUV','MSFT',\
              'SKYW','QCOM',
                 'HPQ','JNPR','AMD','IBM']

def load_financial_data(symbols, start_date, end_date,output_file):
    try:
        df = pd.read_pickle(output_file)
        print('File data found...reading symbols data')
    except FileNotFoundError:
        print('File not found...downloading the symbols data')
        df = data.DataReader(symbols, 'yahoo', start_date, end_date)
        df.to_pickle(output_file)
    return df

data=load_financial_data(symbolsIds,start_date='2001-01-01',
                    end_date = '2018-01-01',
                    output_file='multi_data_large.pkl')

def find_cointegrated_pairs(data):
    n = data.shape[1]
    pvalue_matrix = np.ones((n, n))
    keys = data.keys()
    pairs = []
    for i in range(n):
        for j in range(i+1, n):
            result = coint(data[keys[i]], data[keys[j]])
            pvalue_matrix[i, j] = result[1]
            if result[1] < 0.02:
                pairs.append((keys[i], keys[j]))
    return pvalue_matrix, pairs

pvalues, pairs = find_cointegrated_pairs(data['Adj Close'])
print(pairs)

seaborn.heatmap(pvalues, xticklabels=symbolsIds,
                yticklabels=symbolsIds, cmap='RdYlGn_r',
                mask = (pvalues >= 0.98))
plt.show()
print (pairs)

print(data.head(3))


import numpy as np
import pandas as pd
from sklearn import linear_model
from scipy import stats

def normality_test(X, y, p_value_thresh = 0.05):
    """This function recieves a linear regression model and p-value threshold
     and outputs the p-value from a shapiro wilks test along with a statement
     indicating the results of the normality test

    Parameters
    ----------
    X : pd.Dataframe
        Dataframe containing exploratory variable data
    y : pd.Series
        Dataframe containing response variable data
    p_value_thresh: float
        The threshold user defines for the p-value, default set to 0.05

    Returns
    -------
    float
        p-value of the shapiro wilk test

    Examples
    --------
    >>> normality_test(X_train, y_train, p_value_thresh = 0.05).
    """

    if not isinstance(X, pd.DataFrame):
        raise TypeError("Error: X must be a dataframe")

    if not isinstance(y, pd.Series):
        raise TypeError("Error: y must be a series")

    if not X.shape[1] == X.select_dtypes(include=np.number).shape[1]:
        raise TypeError("Error: X must only contain numeric data.")

    if not pd.api.types.is_numeric_dtype(y):
        raise TypeError("Error: y must only contain numeric data.")

    if not X.shape[0] == len(y):
        raise ValueError("Error: x and y must have the same number of data points")

    lr = linear_model.LinearRegression()
    lr.fit(X, y)
    preds = lr.predict(X)
    residuals = y-preds
    shapiro_test = stats.shapiro(residuals)
    p_value = shapiro_test.pvalue
    res = "Pass"

    if p_value >= p_value_thresh:
        print("After applying the Shapiro Wilks test for normality of the residuals the regression assumption of normality has passed and you can continue with your analysis")
    else:
        print("After applying the Shapiro Wilks test for normality of the residuals the regression assumption of normality has failed and you should make some djustments before continuing with your analysis")
        res = "Fail"

    return (p_value,res)


import numpy as np

def init_centroid(X, n_data, k):
    # 各データ点の中からクラスタの重心となる点をk個ランダムに選択
    idx = np.random.permutation(n_data)[:k]
    centroids = X[idx]
    return centroids

def compute_distances(X, k, n_data, centroids):
    distances = np.zeros((n_data, k))
    for idx_centroids in range(k):
        dist = np.sqrt(np.sum((X - centroids[idx_centroids]) ** 2, axis=1))
        distances[:, idx_centroids] = dist
    return distances

def k_means(k, X, max_iter=300):
    """
    X.shape = (データ数, 次元数)
    k = クラスタ数
    """
    n_data, n_features = X.shape

    # 重心の初期値
    centroids = init_centroid(X, n_data, k)

    # 新しいクラスタを格納するための配列
    new_cluster = np.zeros(n_data)

    # 各データの所属クラスタを保存する配列
    cluster = np.zeros(n_data)

    for epoch in range(max_iter):
        # 各データ点と重心との距離を計算
        distances = compute_distances(X, k, n_data, centroids)

        # 新たな所属クラスタを計算
        new_cluster = np.argmin(distances, axis=1)

        # すべてのクラスタに対して重心を再計算
        for idx_centroids in range(k):
            centroids[idx_centroids] = X[new_cluster == idx_centroids].mean(axis=0)

        # クラスタによるグループ分けに変化がなかったら終了
        if (new_cluster == cluster).all():
            break

        cluster = new_cluster

    return cluster

if __name__=="__main__":
    X = np.arange(10*5).reshape(10, 5)
    print("X\n", X)
    k = 3
    print("k=",k)

    cluster = k_means(k, X, max_iter=300)
    print("cluster", cluster)


#######################
#Jose Barreiros, 2016 #
#Complex Systems      #
#Cornell University   #
#######################

#plot return map with Rugge Kutta
import math, operator, random
import numpy as np
import matplotlib.pyplot as plt

dataX0 = []
dataY0 = []
dataZ0 = []
yList = []
xList = []
zList = []
y_v=[]
z_v=[]

count = 1
t = 1
##
x = 0
y = 0
z = 0

xList.append(x)
yList.append(y)
zList.append(z)

h = .01

a = .398
b = 2
c = 4

def f(x,y,z):
	global a,b,c
	dxdt = -y-z
	return dxdt

def g(x,y,z):
	global a,b,c
	dydt = x + a * y
	return dydt

def e(x,y,z):
	global a,b,c
	dzdt = b + z * (x - c)
	return dzdt

def rk4o(x, y, z):
	global h
	k1x = h*f(x, y, z)
	k1y = h*g(x, y, z)
	k1z = h*e(x, y, z)

	k2x = h*f(x + k1x/2.0, y + k1y/2.0, z + k1z/2.0)
	k2y = h*g(x + k1x/2.0, y + k1y/2.0, z + k1z/2.0)
	k2z = h*e(x + k1x/2.0, y + k1y/2.0, z + k1z/2.0)

	k3x = h*f(x + k2x/2.0, y + k2y/2.0, z + k2z/2.0)
	k3y = h*g(x + k2x/2.0, y + k2y/2.0, z + k2z/2.0)
	k3z = h*e(x + k2x/2.0, y + k2y/2.0, z + k2z/2.0)

	k4x = h*f(x + k3x, y + k3y, z + k3z)
	k4y = h*g(x + k3x, y + k3y, z + k3z)
	k4z = h*e(x + k3x, y + k3y, z + k3z)

	x = x + k1x/6.0 + k2x/3.0 + k3x/3.0 + k4x/6.0
	y = y + k1y/6.0 + k2y/3.0 + k3y/3.0 + k4y/6.0
	z = z + k1z/6.0 + k2z/3.0 + k3z/3.0 + k4z/6.0

	return [x,y,z]

X0 = []
Y0 = []
Z0 = []
previousLocalMax = x
localMax = x
t = 1
changeInTime = h
avgChange = []
LastPoint = changeInTime
while changeInTime < 20000 and len(dataX0) < 1000:

	[x,y,z] = rk4o(xList[t-1], yList[t-1], zList[t-1])

	xList.append(x)
	yList.append(y)
	zList.append(z)
	if 201 < changeInTime:
                # Print y and z points when x is between 0.3 and 0.4
		if x <= 0.4 and x >= 0.3:
			print(y , "," , z)
			y_v.append(y)
			z_v.append(z)

		if x < xList[t-1] and xList[t-2] < xList[t-1]:
			previousLocalMax = localMax
			localMax = xList[t-1]
			dataX0.append(localMax)
			dataY0.append(previousLocalMax)
			# Calculate the change between this and last point
			avgChange.append(changeInTime - LastPoint)
			LastPoint = changeInTime

	t = t + 1
	changeInTime += h
#plt.plot(dataY0, dataX0, 'bo', y_v, z_v, 'mo')

ax=plt.figure(facecolor='white')
plt.plot(dataY0, dataX0, 'b.', markersize=2)
ax.suptitle('Return map - Rossler attractor\n a=%s b=%s c=%s'%(str(a),str(b),str(c)),fontsize=18)
plt.xlabel('X[n]', fontsize=14)
plt.ylabel('X[n+1]', fontsize=14)
plt.show()

#plt.plot(y_v, z_v, 'mo')
#plt.show()


""" Example of ordinary Monte Carlo rejection sampling integrating circle area """
import numpy as np
import scipy.stats
from matplotlib.colors import Normalize
from pylab import *; ion()
import probayes as pb

# PARAMETERS
radius = 1.
set_size = {-10000}

# SETUP CIRCLE FUNCTION AND RVs
def inside(x, y):
  return np.array(x**2 + y**2 <= radius**2, dtype=float)

def norm2d(x, y, loc=0., scale=radius):
  return scipy.stats.norm.pdf(x, loc=loc, scale=scale) * \
         scipy.stats.norm.pdf(y, loc=loc, scale=scale)

xy_range = [-radius, radius]
x = pb.RV("x", xy_range)
y = pb.RV("y", xy_range)

# DEFINE STOCHASTIC CONDITION
xy = x & y
xy.set_prob(inside)

# DEFINE PROPOSAL DENSITY AND COEFFICIENT VARIABLE
xy.set_prop(norm2d)
coef_max = float(norm2d(radius, 1.))
coef = pb.RV('coef', {0., coef_max})
coefs = coef(set_size)
p_prop = xy.propose({(x,y): set_size}, suffix=False)
thresholds = coefs['coef'] * p_prop.prob

# CALL TARGET DENSITY AND APPLY REJECTION SAMPLING
xy_vals = p_prop('marg')
p_xy = xy(xy_vals)
accept = p_xy.prob >= thresholds
reject = np.logical_not(accept)
expectation = np.mean(accept)
square_area = 4. * radius**2
circle_area = square_area * expectation

# PLOT DATA
figure()
x_accept, x_reject = xy_vals['x,y'][0][accept], xy_vals['x,y'][0][reject]
y_accept, y_reject = xy_vals['x,y'][1][accept], xy_vals['x,y'][1][reject]
c_norm = Normalize(vmin=np.min(p_prop.prob), vmax=np.max(p_prop.prob))
c_map = cm.jet(c_norm(p_prop.prob))
c_accept, c_reject = c_map[accept], c_map[reject]
scatter(x_accept, y_accept, color=c_accept, marker='.', linewidths=0.5)
scatter(x_reject, y_reject, color=c_reject, marker='x', linewidths=0.5)
xlabel('x')
ylabel('y')
title('Est. circle area={}'.format(circle_area))


# importing a "secure" pRNG source
# note: the `random` stdlib also exists and would be perfectly applicable here.
#       `secrets` was chosen out of personal preference.
from secrets import randbelow

import numpy as np

# Libraries in the SciPy stack tend to shorthand their module names upon import.
# In an effort to be consistent with existing documentation, I will follow that convention.

# Generating some test data
vanilla_list = [randbelow(2 ** 32) for _ in range(500)]

# Declaring an 1d array from the vanilla list.
array = np.array(vanilla_list)

# Taking the sum via vanilla means
print(sum(vanilla_list))
# Taking the sum via numpy
print(array.sum())

# Taking the subset of values that are even
evens = array[array % 2 == 0]
# and the equivalent pure-python list:
evens_list = [value for value in vanilla_list if value % 2 == 0]  # "list comprehension"

# multiplying all values of the array by a scalar
double_array = array * 2
double_list = [value * 2 for value in vanilla_list]  # "list comprehension"

# Taking the dot product of two arrays:
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])
dot = v1.dot(v2)
# alternatively,
dot = v1 @ v2
print(dot)

# Note: the pure-python equivalent to this is not clean.


import numpy as np
from scipy.optimize import fmin_l_bfgs_b

def simpSample(f, numTest, xMin, xMax, verb=False, maxIter=1000):
    '''
    Simple Rejection Sampling

    Args:
        f (callable): Probability density function (may be
            unnormalized).  Function or lambda function.
        numTest (int): Number of samples to generate
        xMin (float): Minimum sampling range
        xMax (float): Maximum sampling range
        verb (Optional[bool]): Print number of iterations taken
            (default False)
        maxIter (Optional[int]): Maximum number of iterations to
            take (default 1000).

    Returns:
        X (ndarray): Array of samples from given PDF

    Raises:
        ArithmeticError: if maximum number of iterations is reached
            before enough samples are collected

    Example:
        #sample from a log-uniform distribution
        X = simpSample(lambda x: 1./x, 1000, 0.1,100)
    '''

    #find max value
    #first do a coarse grid to get ic
    dx = np.linspace(xMin,xMax,100)
    ic = np.argmax(f(dx))
    g = lambda x: -f(x)
    M = fmin_l_bfgs_b(g,[dx[ic]],approx_grad=True,bounds=[(xMin,xMax)])
    M = f(M[0])

    #initialize
    n = 0
    X = np.zeros(numTest);
    numIter = 0;

    nSamp = np.max([2*numTest,1e6])
    while n < numTest and numIter < maxIter:
        xd = np.random.random(nSamp) * (xMax - xMin) + xMin
        yd = np.random.random(nSamp) * M
        pd = f(xd)

        xd = xd[yd < pd]
        X[n:min(n+len(xd), numTest)] = xd[:min(len(xd),numTest-n)]
        n += len(xd)
        numIter += 1

    if numIter == maxIter:
        raise ArithmeticError("Failed to converge.")

    if verb:
        print 'Finished in '+repr(numIter)+' iterations.'

    return X


import numpy as np

def squared(x):
    """
    Input:
    x, float or int
        Base value
    Output:
        float, base to the power 2.
    """

    return float(x) * float(x)

def pow(x, exponent):
    """
    Input:
        x: float or int
            Base value
        exponent: float or int
            Exponent value

    Output:
        float, base to the power exponent.
    """
    return float(x) ** n

def CentralDiff(f, x, dx):
    """
    Computes the 1st derivative of a function of a single variable f(x)
    by central differencing:

    \begin{equation}
    f'(x) \approx \frac{f(x + dx) - f(x - dx)}{2 * dx}
    \end{equation}

    Input:
        f: function
            Function of a single variable that returns a float
        x:
            Point at which the derivative will be computed
        dx:
            Step size in the central difference algorithm
    """
    return (f(x + dx) - f(x - dx)) / (2*dx)

def Newton(f, x0, tol=1e-5, dx=1e-8):
    """
    Root finding using Newton's method.
    Uses central differencing to find the derivative in the formula:

    \begin{equation}
    x_n+1 = x_n - f(x) / f'(x)
    \end{equation}

    Input:
        f: function
            Function of a single variable that returns a float.
        x0: Float
           Initial guess at root.
        tol: Float
           Algorithm stops when abs(x - x0) >= tol.
        dx: Float
           Step size for central differencing
    """

    x = x0 - f(x0)/CentralDiff(f, x0, dx)

    while(np.abs(x - x0) >=tol):
        x0 = x
        x = x0 - f(x0)/CentralDiff(f, x0, dx)

    return x


"""
"""

import cvxpy as cp
import fire
import numpy as np

from swissknife import utils

N = 10
n = 100

q = [(np.exp(-(i - 30) ** 2 / 100) + 2 * np.exp(-(i - 68) ** 2 / 100)) for i in range(1, 101)]
q = np.array(q)
r = np.array([np.exp(-(i - 50) ** 2 / 100) for i in range(1, 101)])

q = q / sum(q)
r = r / sum(r)

def plot(p):
    utils.plot_wrapper(
        plots=[
            dict(x=np.arange(n), y=p.value[i], label=f'{i}')
            for i in range(N)
        ]
    )

def parta():
    p = cp.Variable(shape=(N, n))
    cons = [
        p[0] == q,
        p[N - 1] == r,
    ]
    cons += [p[i] >= 0. for i in range(N)]
    cons += [sum(p[i]) == 1. for i in range(N)]

    obj = cp.Minimize(
        sum([
            cp.norm2(_next - _this) ** 2 for _next, _this in zip(p[1:], p[:-1])
        ])
    )
    cp.Problem(objective=obj, constraints=cons).solve()

    plot(p)

def partb():
    p = cp.Variable(shape=(N, n))
    cons = [
        p[0] == q,
        p[N - 1] == r,
    ]
    cons += [p[i] >= 0. for i in range(N)]
    cons += [sum(p[i]) == 1. for i in range(N)]

    loss = 0
    for _next, _this in zip(p[1:], p[:-1]):
        loss = loss + sum(_next) + sum(_this)

        for ui, vi in zip(_next, _this):
            loss = loss - 2. * cp.geo_mean(
                cp.vstack([ui, vi])
            )

    obj = cp.Minimize(loss)
    cp.Problem(objective=obj, constraints=cons).solve(solver=cp.ECOS)
    for i in range(N):
        print(sum(p[i].value))

    plot(p)

def partc():
    p = cp.Variable(shape=(N, n))
    cons = [
        p[0] == q,
        p[N - 1] == r,
    ]
    cons += [p[i] >= 0. for i in range(N)]
    cons += [sum(p[i]) == 1. for i in range(N)]

    pcum = cp.cumsum(p, axis=1)
    obj = cp.Minimize(
        sum([
            cp.norm_inf(_next - _this) for _next, _this in zip(pcum[1:], pcum[:-1])
        ])
    )
    cp.Problem(objective=obj, constraints=cons).solve()

    plot(p)

def main():
    # parta()
    partb()
    # partc()

if __name__ == "__main__":
    fire.Fire(main)


# coding: utf-8
import numpy as np
import scipy as sp
import math
from scipy.misc import comb
import sys

def detect_burst(relevant_list, total_list):
    """ Assume (num. of relevant docs, total num. docs) as the two input lists
        returns state costs
    """

    state_costs = [(0.0, 0.0)] # for the initial step
    s = 2
    R = sum(relevant_list)
    D = sum(total_list)
    p_0 = (1.0 * R) / D
    p_1 = p_0 * s
    n = len(relevant_list)
    for i in range(n):
        r_t = relevant_list[i]
        d_t = total_list[i]
        nonburst_state_cost = calc_state_cost(0, r_t, d_t, p_0)
        burst_state_cost = calc_state_cost(1, r_t, d_t, p_1)
        state_costs.append((nonburst_state_cost, burst_state_cost))

    print state_costs
    best_state_sequence = calc_best_state_sequence(state_costs)

    return best_state_sequence

def calc_state_cost(i, r_t, d_t, p_i):
    coef = comb(d_t, r_t, exact=True) # binomial coefficient
    #print coef, p_i
    return -1.0 * (math.log(coef) + r_t * math.log(p_i) + (d_t - r_t) * math.log(1 - p_i))

#def calculate_weight():
#    """ Calculating the weight of the bursts. Used for ranking the detected bursts
#    """

def calc_transition_cost(current_state, next_state, r):
    cost = 0
    if next_state > current_state:
        cost = r * (next_state - current_state)
    return cost

def calc_best_state_sequence(state_costs, r = 1):
    """ State costs: (non-burst state cost, burst state cost)
    """
    n = len(state_costs)
    subtotal_cost = 0 # unnecessary?
    current_state = 0 # non-burst state
    best_state_sequence = []

    for j in range(n):
        #current_state_cost = state_costs[j][current_state]
        to_burst_state = state_costs[j][1] + calc_transition_cost(current_state, 1, r)
        to_nonburst_state = state_costs[j][0] + calc_transition_cost(current_state, 0, r)
        #import ipdb; ipdb.set_trace()

        best_cost = 0
        if to_burst_state < to_nonburst_state:
            best_cost = to_burst_state
            current_state = 1
        else:
            best_cost = to_nonburst_state
            current_state = 0

        best_state_sequence.append(current_state)
        subtotal_cost += best_cost

    return best_state_sequence

def main():
    f = open(sys.argv[1])
    f_out = open(sys.argv[1] + "_predicted_burst_timestamps", "w")
    relevant_list = []
    total_list = []

    for line in f:
        relevant, total = map(int, line[:-1].split("\t"))
        relevant_list.append(relevant)
        total_list.append(total)

    best_state_sequence = detect_burst(relevant_list, total_list)
    print best_state_sequence

    for i in range(1, len(best_state_sequence)):
      f_out.write(str(best_state_sequence[i]) + "\n")

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""Exercise 2.

Grid Search
"""

import numpy as np

def generate_w(num_intervals):
    """Generate a grid of values for w0 and w1."""
    w0 = np.linspace(-100, 200, num_intervals)
    w1 = np.linspace(-150, 150, num_intervals)
    return w0, w1

def grid_search(y, tx, w0, w1):
    """Algorithm for grid search."""
    losses = np.zeros((len(w0), len(w1)))
    # compute loss for each combination of w0 and w1.
    for ind_row, row in enumerate(w0):
        for ind_col, col in enumerate(w1):
            w = np.array([row, col])
            e = y - tx.dot(w)
            losses[ind_row, ind_col] = 1/2*np.mean(e**2)
    return losses

def get_best_parameters(w0, w1, losses):
    """Get the best w from the result of grid search."""
    min_row, min_col = np.unravel_index(np.argmin(losses), losses.shape)
    return losses[min_row, min_col], w0[min_row], w1[min_col]


import networkx as nx
#  import matplotlib.pyplot as plt

###
#  Load the Graph
###

filename = 'dijkstraData.txt'
DG = nx.DiGraph()

with open(filename) as f:
    for line in f:
        # Parse the line
        parsed_line = line.rsplit('\t')
        node_from = int(parsed_line.pop(0))
        # Get rid of the line element
        parsed_line.pop()
        for node_weight in parsed_line:
            node_to = int(node_weight.rsplit(',')[0])
            weight = int(node_weight.rsplit(',')[1])
            DG.add_edge(node_from, node_to, weight=weight)

###
# Dijkstra algorithm
###

total_nodes = set(DG.nodes())

source = 1
X = set()
A = {i : 0 for i in range(DG.number_of_nodes() + 1)}
# A = [0] * (DG.number_of_nodes() + 1)
X.add(source)  # Nodes already calculated
Y = total_nodes.difference(X)

while(X != total_nodes):
    print 'X has size', len(X)
    print 'Y has size', len(Y)
    print 'Total number of nodes', len(total_nodes)
    aux = []
    for v in X:
        for w in Y:
            if w in DG.neighbors(v):
                score = A[v] + DG[v][w]['weight']
                aux.append((score, v, w))

    score_start, v_star, w_star = min(aux)

    X.add(w_star)
    A[w_star] = score_start
    Y = total_nodes.difference(X)

# This is the one by nx
correct =  nx.single_source_dijkstra_path_length(DG, source)

# Print the result
print 'Result'
print A[7], A[37], A[59],A[82], A[99], A[115],A[133],A[165], A[188], A[197]


import numpy as np

def quantile_1D(data, weights, quantile):
    """
    Compute the weighted quantile of a 1D numpy array.
    Parameters
    ----------
    data : ndarray
        Input array (one dimension).
    weights : ndarray
        Array with the weights of the same size of `data`.
    quantile : float
        Quantile to compute. It must have a value between 0 and 1.
    Returns
    -------
    quantile_1D : float
        The output value.
    """
    # Check the data
    if not isinstance(data, np.matrix):
        data = np.asarray(data)
    if not isinstance(weights, np.matrix):
        weights = np.asarray(weights)
    nd = data.ndim
    if nd != 1:
        raise TypeError("data must be a one dimensional array")
    ndw = weights.ndim
    if ndw != 1:
        raise TypeError("weights must be a one dimensional array")
    if data.shape != weights.shape:
        raise TypeError("the length of data and weights must be the same")
    if ((quantile > 1.) or (quantile < 0.)):
        raise ValueError("quantile must have a value between 0. and 1.")
    # Sort the data
    ind_sorted = np.argsort(data)
    sorted_data = data[ind_sorted]
    sorted_weights = weights[ind_sorted]
    # Compute the auxiliary arrays
    Sn = np.cumsum(sorted_weights)
    # TODO: Check that the weights do not sum zero
    # assert Sn != 0, "The sum of the weights must not be zero"
    Pn = (Sn-0.5*sorted_weights)/Sn[-1]
    # Get the value of the weighted median
    return np.interp(quantile, Pn, sorted_data)

def quantile(data, weights, quantile):
    """
    Weighted quantile of an array with respect to the last axis.
    Parameters
    ----------
    data : ndarray
        Input array.
    weights : ndarray
        Array with the weights. It must have the same size of the last
        axis of `data`.
    quantile : float
        Quantile to compute. It must have a value between 0 and 1.
    Returns
    -------
    quantile : float
        The output value.
    """
    # TODO: Allow to specify the axis
    nd = data.ndim
    if nd == 0:
        TypeError("data must have at least one dimension")
    elif nd == 1:
        return quantile_1D(data, weights, quantile)
    elif nd > 1:
        n = data.shape
        imr = data.reshape((np.prod(n[:-1]), n[-1]))
        result = np.apply_along_axis(quantile_1D, -1, imr, weights, quantile)
        return result.reshape(n[:-1])

def median(data, weights):
    """
    Weighted median of an array with respect to the last axis.
    Alias for `quantile(data, weights, 0.5)`.
    """
    return quantile(data, weights, 0.5)


#############################################################################################################
# Visualize the data
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import statsmodels.api as sm
# Load a statsmodels sample data using macro data
df = sm.datasets.macrodata.load_pandas().data
print(sm.datasets.macrodata.NOTE)
df.head()
# tsa is time series analysis
# index needs to have a date, so how to create using statsmodels functions (similar to matplotlib and datetime)
# use head and tail to see what the range should be
index = pd.Index(sm.tsa.datetools.dates_from_range('1959Q1','2009Q3') )
df.index = index
df.head()
df['realgdp'].plot()
result = sm.tsa.filters.hpfilter(df['realgdp'])
type(result) # returns a tuple of (cycle and trend), trend line tends upwards
# tuple unpacking to grab the individual series
gdp_cycle, gdp_trend = sm.tsa.filters.hpfilter(df['realgdp'])
# grab trend value and plot with realgdp data
df['trend'] = gdp_trend
df[['realgdp','trend']].plot()
# plot that is zoomed into a time you're interested in
df[['realgdp','trend']]['2000-03-31':].plot(figsize=(12,8))
# ETS Decomposition
# Break down a Time Series into ETS = Error, Trend, Seasonality attributes
# Used for Exponential Smoothing, Trend Method Models, ETS Decomposition
# Then Observed = Trend + Seasonal + Residual terms

#############################################################################################################
# Objective: Plot exponentially weighted moving average with your existing time series
# Using the EWMA Model
#
# Exponentially Weighted Moving Average models
# better than simple moving average weaknesses (averaging effects and extreme value effects, doesn't inform future behavior)
# reduce lag effect by putting more weights on recent values
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
airline = pd.read_csv('airline_passengers.csv',index_col='Month')
# now look at index
airline.index
# seems gappy/data clean up issues - get rid of missing values
airline.dropna(inplace=True)
# now modify index to a datetime object
airline.index=pd.to_datetime(airline.index)
# calculate simple 6 month MA
airline['6-month-SMA'] = airline['Thousands of Passengers'].rolling(window=6).mean()
airline['12-month-SMA'] = airline['Thousands of Passengers'].rolling(window=12).mean()
airline.plot(figsize=(10,8))
# now calculate EWMA, can use tab for column names and shift tab for ewm features
# different ways to calculate alpha: span, center of mass, half life, or if you want, alpha explicitly set
airline['EWMA-12'] = airline['Thousands of Passengers'].ewm(span=12).mean()

# other calibrations:
# s is span: n-day exponentially weighted moving average period (ex. 7 day or 14 day)
# c is center of mass: c = (span-1)/2  (ex. inverse with span)
# half life = period of time for exponential weight to reduce to one half
# alpha = smoothing factor
airline['EWMA-0.5 Alpha'] = airline['Thousands of Passengers'].ewm(alpha=0.5,adjust=True).mean()
airline['EWMA-2 COM'] = airline['Thousands of Passengers'].ewm(com=2,adjust=True).mean()
airline['EWMA-12 Halflife'] = airline['Thousands of Passengers'].ewm(halflife=12,adjust=True).mean()
# plot it:
airline[['Thousands of Passengers','EWMA-12','EWMA-0.5 Alpha','EWMA-2 COM','EWMA-12 Halflife']].plot(figsize=(10,8))

# more here: https://pandas.pydata.org/pandas-docs/stable/user_guide/computation.html
# When adjust is True (default), weighted averages are calculated using weights (1-alpha)**(n-1), (1-alpha)**(n-2), …, 1-alpha, 1.
# When adjust is False, weighted averages are calculated recursively as: weighted_average[0] = arg[0]; weighted_average[i] = (1-alpha)*weighted_average[i-1] + alpha*arg[i].
# One must have 0 < α <= 1, and while since version 0.18.0 it has been possible to pass α directly:
# it's often easier to think about either the span, center of mass (com) or half-life of an EW moment
# what does adjust do?
# Adjust is True is default
# not sure, not much diff in this example
# when Adjust is True, x0 is not an ordinary value but rather an exponentially weighted moment of the infinite series up to that point
# some other different calibrations:
airline['EWMA-12'] = airline['Thousands of Passengers'].ewm(span=12).mean()
airline['EWMA-0.5 Alpha'] = airline['Thousands of Passengers'].ewm(alpha=0.5,adjust=False).mean()
airline['EWMA-2 COM'] = airline['Thousands of Passengers'].ewm(com=2,adjust=False).mean()
airline['EWMA-12 Halflife'] = airline['Thousands of Passengers'].ewm(halflife=12,adjust=False).mean()
airline[['Thousands of Passengers','EWMA-12','EWMA-0.5 Alpha','EWMA-2 COM','EWMA-12 Halflife']].plot(figsize=(10,8))

#############################################################################################################
# Objective: ETS Decomposition to see Seasonality
#
# ETS Decomposition Code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
airline = pd.read_csv('airline_passengers.csv',index_col='Month')
# now look at index, seems gappy - get rid of missing values
airline.index
airline.dropna(inplace=True)
# now modify index to a datetime object
airline.index=pd.to_datetime(airline.index)
airline.plot()
from statsmodels.tsa.seasonal import seasonal_decompose
# run the model: is it exponential growth or linear? if exponential use multiplicative, use 'additive' model for linear
result = seasonal_decompose(airline['Thousands of Passengers'], model='multiplicative')
result.trend.plot()
fig = result.plot() # may show twice in jupyter notebook

#############################################################################################################
# Objective: First ARIMA Model
#
# Not a scientific explanation of choosing p,d,q
# ARIMA Model = Auto Regressive Integrated Moving Average
# has 2 types of ARIMA models: Non-Seasonal and Seasonal

# arima(p,d,q)
# p=auto-regression to model dependent relationship
# d=integration is differencing to make series stationary
# q=moving average to model dependency on moving average error

# stationary - can we visually see it?
# stationary = good, nonstationary = bad
# stationary series has constant mean and variance over time (good = mean and variance will be same in future periods)
# 1) mean has to be constant to be stationary (no upward trend)
# 2) variance should not be changing as a function of time (bad = variance big and small over diff time periods)
# 3) covariance (change in variance) should not be a function of time (good = nice accordion, bad = partly squished accordian)
# don't need to visualize all the time, just use mathematically (Augmented Dickey Fuller Test)

# conversion from non-stationarity to stationarity can be done through differencing
# differencing = (first difference = t minus t-1, second difference = first diff t minus first diff t-1)
# also could try: differencing then seasonal differencing
# each differencing step loses a row of data

# Choosing Values for p,d,q (ARIMA model) and additional P, D, Q (seasonal ARIMA model)

# Autocorrelation Plots (ACF) - MA model identification
#
# Shows the correlation of a time series with "itself lagged by x time units"
# y axis is correlation coefficient, x axis is # of units of time lag (ex. 1D, 2D, ... 10D)
#
# ACF two common plots:
#
# 1) Gradual decline
# 2) Large drop off
# if ACF shows positive autocorrelation in first lag (lag at time 1) then suggest to use the AR term in relation to the lag
# if ACF shows negative autocorrelation in first lag (lag at time 1) then suggest to use the MA term

# Partial Correlation (PACF) - AR model identification
#
# Calculate partial correlation between the variables (y and x3)
# Partial correlation is the correlation between how y and x3 each are related to x1 and x2
# Partial autocorrelation plot would show some sharp drop off after lag "k", suggesting AR-k should be used
# If gradual decline in PACF, then choose MA

# So AR or MA?
#
# Identify an AR model usually using PACF (Partial Autocorrelation Function)
# Identify an MA model usually best done with ACF (Autocorrelation Function) rather than PACF
# Typically would choose MA or AR, rarely both (choose p or choose q)
# p is # of lag observations included in the model
# d is # of times raw observations are differenced
# q is size of moving average window (also called "order of MA")

# ARIMA Code Along
# 1) Visualize the Time Series
# 2) Make the time series stationary
# 3) Plot Correlation and Autocorrelation Charts
# 4) Construct ARIMA model
# 5) Use model to make predictions (forecasting)

import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
%matplotlib inline
#Step 1############################################################################################################
df = pd.read_csv('monthly-milk-production-pounds-p.csv')
df.head()

# rename that long column
df.columns = ['Month','Milk in Pounds per Cow']

# check tail
df.tail()
df.drop(168,axis=0,inplace=True)
df.tail()

# get rid of normal index, change month to datetime and index,
df['Month'] = pd.to_datetime(df['Month'])
df.set_index('Month',inplace=True)
df.head()

# see the statistics
df.describe().transpose()

# visualize the data
# has a trend aspect and has a seasonality aspect
df.plot()

# plot moving averages
time_series = df['Milk in Pounds per Cow']
type(time_series) # pandas.core.series.Series
time_series.rolling(12).mean().plot(label='12 Month Rolling Mean')
time_series.rolling(12).std().plot(label='12 Month Rolling Std')
time_series.plot()
plt.legend()

#Step 2############################################################################################################
# plot ETS to see seasonal or not
# ETSD Decomposition Plot
from statsmodels.tsa.seasonal import seasonal_decompose
decomp = seasonal_decompose(time_series,freq=12,model='additive') # the trend does not appear multiplicative
fig = decomp.plot()
fig.set_size_inches(15,8)

# test for stationarity
# try and test if need first difference or second difference
# Test for stationarity using Augmented Dickey Fuller Test
df.head() # shows us datetime index of month and some milk
# null hypothesis = is not stationary
# alternative = is stationary
# p value less than 0.05 to reject the null hypothesis
from statsmodels.tsa.stattools import adfuller
# calculate adfuller
# returns a tuple, hard to handle
result = adfuller(df['Milk in Pounds per Cow'])
# returns an ugly format: with p value, number of lags used, critical values
# use a function to unwrap it, see below

# build an adf_check function to pull out p value results
# will succeed if p <= 0.05
def adf_check(time_series):
    result = adfuller(time_series)
    print('Augmented Dicky Fuller Test')
    print('***************************')
    labels = ['ADF Test Statistics','p-value','# of lags used', '# of Observations Used']
    for value,label in zip(result,labels):
        print(label + ' : ' +str(value))

    # result[1] is the p-value
    if result[1] <= 0.05:
        print('Strong evidence against null hypothesis')
        print('Reject null hypothesis')
        print('Data has no unit root and is stationary')
        print('Good')
    else:
        print('Weak evidence against null hypothesis')
        print('Fail to reject null hypothesis')
        print('Data has a unit root and is nonstationary')
        print('Bad')

# usage of the function
# run adf check on the original data
adf_check(df['Milk in Pounds per Cow'])     # seasonality has clearly shown that it is not stationary

# Since non stationary, take a first difference and try again
# shift it over one time step
df['First Difference'] = df['Milk in Pounds per Cow'] - df['Milk in Pounds per Cow'].shift(1)
df['First Difference'].plot()
plt.show()
# dropna because issue with shift(1) missing one value that messes up the adf function
adf_check(df['First Difference'].dropna()) # looks stationary

# Try second difference and see
df['Second Difference'] = df['First Difference'] - df['First Difference'].shift(1)
df['Second Difference'].plot()
plt.show()
adf_check(df['Second Difference'].dropna()) # try again if first one does not look stationary

# can also take a seasonal difference
df['Seasonal Difference'] = df['Milk in Pounds per Cow'] - df['Milk in Pounds per Cow'].shift(12) # seasonal diff is 12
df['Seasonal Difference'].plot()
plt.show()
adf_check(df['Seasonal Difference'].dropna())

# can also take a seasonal first difference
df['Seasonal First Difference'] = df['First Difference'] - df['First Difference'].shift(12) # seasonal first diff is 12
df['Seasonal First Difference'].plot()
plt.show()
adf_check(df['Seasonal First Difference'].dropna())

#Step 3############################################################################################################
# ACF and PACF Plots (Autocorrelation)
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
fig_first = plot_acf(df['First Difference'].dropna(),title='First Difference')
fig_seasonal_first = plot_acf(df['Seasonal First Difference'].dropna(), title='Seasonal First Difference')

# PACF Plot
# https://www.itl.nist.gov/div898/handbook/pmc/section4/pmc4463.htm
result = plot_pacf(df['Seasonal First Difference'].dropna()) # common to see sudden drop off then use AR, if gradual then use MA

# Final plots
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(211)
fig = sm.graphics.tsa.plot_acf(df['Seasonal First Difference'].iloc[13:], lags=40, ax=ax1)
ax2 = fig.add_subplot(212)
fig = sm.graphics.tsa.plot_pacf(df['Seasonal First Difference'].iloc[13:], lags=40, ax=ax2)

#Step 4############################################################################################################
# ARIMA Model
# Now that we have a stationary model
from statsmodels.tsa.arima_model import ARIMA

# SARIMAX = S is for seasonal, X is for exogeneous for external variables
# for full documentation string --> help(ARIMA)
# Some additional docs https://www.statsmodels.org/dev/examples/notebooks/generated/statespace_sarimax_stata.html
"""
What does ARIMA(1, 0, 12) mean?
Specifically for your model, ARIMA(1, 0, 12) means that it you are describing some response variable (Y) by combining a 1st order Auto-Regressive model and a 12th order Moving Average model. A good way to think about it is (AR, I, MA). This makes your model look the following, in simple terms:
Y = (Auto-Regressive Parameters) + (Moving Average Parameters)
The 0 in the between the 1 and the 12 represents the 'I' part of the model (the Integrative part) and it signifies a model where you're taking the difference between response variable data - this can be done with non-stationary data and it doesn't seem like you're dealing with that, so you can just ignore it.

What values can be assigned to p, d, q?
Lots of different whole numbers. There are diagnostic tests you can do to try to find the best values of p,d,q (see part 3).

What is the process to find the values of p, d, q?
There are a number of ways, and I don't intend this to be exhaustive:
look at an autocorrelation graph of the data (will help if Moving Average (MA) model is appropriate)
look at a partial autocorrelation graph of the data (will help if AutoRegressive (AR) model is appropriate)
look at extended autocorrelation chart of the data (will help if a combination of AR and MA are needed)
try Akaike's Information Criterion (AIC) on a set of models and investigate the models with the lowest AIC values
try the Schwartz Bayesian Information Criterion (BIC) and investigate the models with the lowest BIC values

Resource for choosing p,d,q?
# https://people.duke.edu/~rnau/arimrule.htm
"""

# Here we have seasonal so use seasonal ARIMA model
# p=auto-regression to model dependent relationship
# d=integration is differencing to make series stationary
# q=moving average to model dependency on moving average error
# p is # of autoregressive lag observations included in the model
# d is # of times raw observations are differenced
# q is size of moving average window (also called "order of MA")
# seasonal_order is (Seasonal AR spec, Seasonal Integration Order, Seasonal MA, Seasonal Periodicity)
# (p = 0, d = 1, q = 0)  and (P = 1, D = 1, Q = 1) Periodicity = 12
model = sm.tsa.statespace.SARIMAX(df['Milk in Pounds per Cow'], order=(0,1,0), seasonal_order=(1,1,1,12))

# This warning basically says it assumes your time series periods are assumed and have no gaps in data:
# ValueWarning: No frequency information was provided, so inferred frequency MS will be used.

# This function may take a while
results = model.fit()
print(results.summary())

# to see the residual value
results.resid
results.resid.plot()

# to see distribution of our errors
results.resid.plot(kind='kde')
# note we see it is around zero, which is good

#Step 5############################################################################################################
# forecast on yourself on data that you already know
df['forecast'] = results.predict(start=150, end=168)
df[['Milk in Pounds per Cow','forecast']].plot(figsize=(12,8))
# see how good the forecast is on in sample data

# Forecast beyond current time period
df.tail()

# Add on more months with empty values, date increment for date range
from pandas.tseries.offsets import DateOffset
# df.index[-1] is the last date then ADD an offset of 1 month, 2 month... not +0 month because duplicate = not 0,24 but 1,24
future_dates = [df.index[-1] + DateOffset(months=x) for x in range(1,24)]
future_dates

# Create a new dataframe
future_df = pd.DataFrame(index=future_dates,columns=df.columns)
final_df = pd.concat([df,future_df])
final_df.head() # see if old data still there and has a new column
final_df.tail() # see if the new time series were created

# Populate a forecast into the dataframe
final_df['forecast'] = results.predict(start=168,end=192)
final_df.tail()

# Plot the new forecast
final_df[['Milk in Pounds per Cow','forecast']].plot(figsize=(12,8))
# why ARIMA works well?
# time has a clear impact on y value
# ARIMA assumes time is an important component
# why ARIMA doesn't work well for stocks?
# Financial stock prices tend to be more random, so more Brownian Motion and Monte Carlo

import numpy,import statsmodels,from statsmodels


#!/usr/bin/python
"""
    disclaimer: I acquired this function the course website or
    directly from: http://blue.math.buffalo.edu/sauer2py/romberg.py
"""
# Program 5.1 Romberg integration
# Translated to Python by JR 2/17/2012.
# Computes approximation to definite integral
# Inputs: Matlab inline function specifying integrand f,
#    a,b integration interval, n=number of rows
# Output: Romberg tableau r
from numpy import *
from math import sin

def romberg(f,a,b,n):
	h=(b-a)/2.**linspace(0,n-1,n)
	r = zeros((n,n))
	r[0,0]=(b-a)*(f(a)+f(b))/2.
	for j in range(2,n+1):
		subtotal = 0.
		for i in range(1,2**(j-2)+1):
			subtotal = subtotal + f(a+(2*i-1)*h[j-1])
		r[j-1,0] = r[j-2,0]/2. + h[j-1]*subtotal
		for k in range(2,j+1):
			r[j-1,k-1] = (4**(k-1)*r[j-1,k-2]-r[j-2,k-2])/(4.**(k-1)-1)
	return r
if __name__ == "__main__":
    f = lambda x: sin(1.7*x)-x**2.5
    set_printoptions(precision=5)
    print romberg(f,1,3,5)


from typing import Optional

import numpy as np

from mockseries.noise.noise import Noise

class RedNoise(Noise):
    """Gaussian noise generator.

    This class adds uncorrelated, additive white noise to your signal.

    Args:
        mean: mean of the noise
    std : float
        standard deviation of the noise

    Notes:
        https://atmos.washington.edu/~breth/classes/AM582/lect/lect8-notes.pdf
        https://rts-gen.readthedocs.io/en/latest/generators.html#gaussian-noise-generator
    """

    def __init__(
        self,
        mean: float = 0.0,
        std: float = 1.0,
        correlation: float = 0.5,
        random_seed: Optional[int] = None,
    ) -> None:
        super().__init__(random_seed)
        self.mean = mean
        self.std = std
        if not (0 < correlation < 1):
            raise ValueError("Correlation coefficient r has to be between 0 and 1.")
        self.correlation = correlation

    def _sample_at(self, time_points: np.ndarray) -> np.ndarray:
        """Samples a red noise."""
        # todo optimize
        if self.random_seed:
            np.random.seed(self.random_seed)

        white_noise = np.random.normal(
            loc=self.mean, scale=self.std, size=len(time_points)
        )
        red_noise = np.zeros(len(time_points))
        red_noise[0] = white_noise[0]

        for i in range(1, len(red_noise)):
            red_noise[i] = (
                self.correlation * red_noise[i - 1]
                + np.sqrt((1 - self.correlation * self.correlation)) * white_noise[i]
            )

        return red_noise


# ====================================
# Creating and using a quadrature rule
# ====================================
#
# This demo shows how quadrature rules can be obtained from Basix and how these
# can be used to compute the integrals of functions. A quadrature rule uses a
# set of points (:math:`p_0` to :math:`p_{n-1}`) and weights (:math:`w_0` to
# :math:`w_{n-1}`), and approximates an integral as the weighted sum of the
# values of the function at these points, ie
#
# .. math::
#
#    \int f\,\mathrm{d}x \approx \sum_i w_if(p_i).
#
# First, we import Basix and Numpy.

import basix
import numpy as np
from basix import ElementFamily, CellType, LagrangeVariant

# To get a quadrature rule on a triangle, we use the function `make_quadrature`.
# This function takes two or three three inputs. We want to use the default
# quadrature, pass in two inputs: a cell type and an order. The order of the rule
# is equal to the degree of the highest degree polynomial that will be exactly
# integrated by this rule. In this example, we use an order 4 rule, so all quartic
# polynomials will be integrated exactly.
#
# `make_quadrature` returns two values: the points and the weights of the
# quadrature rule.

points, weights = basix.make_quadrature(CellType.triangle, 4)

# If we want to control the type of quadrature used, we can pass in three
# inputs to `make_quadrautre`. For example, the following code would force basix
# to use a Gauss-Jacobi quadrature rule:

points, weights = basix.make_quadrature(
    basix.QuadratureType.gauss_jacobi, CellType.triangle, 4)

# We now use this quadrature rule to integrate the functions :math:`f(x,y)=x^3y`
# and :math:`g(x,y)=x^3y^2` over the triangle. The exact values of these integrals
# are 1/120 (0.00833333333333...) and 1/420 (0.00238095238095...) respectively.
#
# As :math:`f` is a degree 4 polynomial, we expect our quadrature rule to be able
# to compute its integral exactly (within machine precision). :math:`g` on the
# other hand is a degree 5 polynomial, so its integral will not be computed exactly.
#
# We define Python functions that compute :math:`f` and :math:`g` for every point.
# These functions use features of Numpy to compute all the values at once.

def f(points):
    return points[:, 0] ** 3 * points[:, 1]

def g(points):
    return points[:, 0] ** 3 * points[:, 1] ** 2

# We can now use Numpy features to compute the integrals.

print(np.sum(weights * f(points)))
print(np.sum(weights * g(points)))

# We obtain the values 0.00833333333333334 and 0.002393509368731209. As expected,
# the integral of :math:`f` has been computed to within machine precision, while
# the integral of :math:`g` is correct to 4 decimal places, but is not exact.
#
# Integrating a basis function
# ============================
#
# We next use the quadrature rule to compute the integral of a basis function in
# a degree 3 Lagrange space. We first create the space and tabulate its basis
# functions at the quadrature points.

lagrange = basix.create_element(
    ElementFamily.P, CellType.triangle, 3, LagrangeVariant.equispaced)

values = lagrange.tabulate(0, points)

# We compute the integral of the third (note that the counting starts at 0) basis
# function in this space. We can obtain the values of this basis function from
# `values` by using the indices `[0, :, 3, 0]`. The integral can therefore
# computed as follows. As this basis function will be degree three, the result
# will again be exact (withing machine precision).

print(np.sum(weights * values[0, :, 3, 0]))


import numpy as np
import random

# Create a random distribution
def get_random_distribution(distribution_type, lower_bound, upper_bound, set_size, \
                            round = True, no_of_type_in_set = None, sample_size = None):
    if distribution_type == "uniform_ditribution":  #use global constant/enum for this?
        randomNums = np.random.uniform(low= lower_bound, high= upper_bound, size=set_size)
        if round == True:
            randomNums = np.round(randomNums)
    elif distribution_type == "normal":
        # Generate normal Distribution:
        randomNums = np.random.normal((int((lower_bound + upper_bound)/2)), size=set_size)
        if round == True:
            randomNums = np.round(randomNums)
    elif distribution_type == "poisson":
        randomNums = np.random.poisson((int((lower_bound + upper_bound)/2)), size=set_size)
        if round == True:
            randomNums = np.round(randomNums)
    elif distribution_type == "hypergeometric_distribution":
        remainder_in_set = set_size - no_of_type_in_set
        randomNums = np.random.hypergeometric(remainder_in_set, no_of_type_in_set, sample_size, size=set_size)
        if round == True:
            randomNums = np.round(randomNums) + lower_bound
    else:
        print('Error! Undefined `distribution_type`: %s' % (distribution_type))
    #print(randomNums)
    return randomNums

# Create a random index
def get_random_index(distribution_type, lower_bound, upper_bound, round = True):
    index = np.int64(0)
    if distribution_type == "uniform_ditribution":  #use global constant/enum for this?
        index = random.randint(lower_bound, upper_bound)
    elif distribution_type == "normal":
        index = random.randint(lower_bound, upper_bound)  # ToDo: change to normal
    else:
        index = random.randint(lower_bound, upper_bound)  # ToDo: Add more options here
    return index


from numpy import sum,asarray,abs,sign

def spearman_footrule_distance(s,t):
    """
    Computes the Spearman footrule distance between two full lists of ranks:

        F(s,t) = (2/|S|^2)*sum( |s(i) - t(i)| )

    the normalized sum over all elements in a set of the absolute difference
    between the rank according to two different lists s and t.  As defined,
    0 <= F(s,t) <= 1.

    s,t should be array-like (lists are OK).

    If s,t are *not* full, this function should not be used.
    """
    # check that the lists are both full
    assert len(s) == len(t)
    return (2.0/len(s)**2)*sum(abs(asarray(s) - asarray(t)))

def kendall_tau_distance(s,t):
    """
    Computes the Kendall tau distance between two full lists of ranks,
    which counts all discordant pairs (where s(i) < s(j) but t(i) > t(j),
    or vice versa) and divides by:

            k*(k-1)/2

    This is a slow version of the distance; a faster version can be
    implemented using a version of merge sort (TODO).

    s,t should be array-like (lists are OK).

    If s,t are *not* full, this function should not be used.
    """
    numDiscordant = 0
    for i in range(0,len(s)):
        for j in range(i+1,len(t)):
            if (s[i] < s[j] and t[i] > t[j]) or (s[i] > s[j] and t[i] < t[j]):
                numDiscordant += 1
    return 2.0*numDiscordant/(len(s)*(len(s)-1))

def partial_kendall(s1,s2,p=0.5):
    """
    Kendall distance with penalty p between two partial rank lists (lists with ties).
    This could be sped up with more efficient computation of the size of the sets R1,
    R2, and D. I normalize the distance by dividing by k*(k-1)/2.
    """
    cardD = 0
    cardR1 = 0
    cardR2 = 0
    k = len(s1)
    for i in range(len(s1)):
        for j in range(len(s2)):
            if s1[i] < s1[j] and s2[i] > s2[j]:
                cardD += 1
            elif s1[i] == s1[j] and s2[i] != s2[j]:
                cardR1 += 1
            elif s2[i] == s2[j] and s1[i] != s1[j]:
                cardR2 += 1
    return (2/(k*(k-1)))*(cardD + p*(cardR1 + cardR2))

def partial_hausdorff(s1,s2):
    """
    Hausdorff distance for partial rank lists; as in partial_kendall, could be
    sped up by more efficient set size calculation.  I normalize the distance by
    dividing by k*(k-1)/2.
    """
    cardD = 0
    cardR1 = 0
    cardR2 = 0
    k = len(s1)
    for i in range(len(s1)):
        for j in range(len(s2)):
            if s1[i] < s1[j] and s2[i] > s2[j]:
                cardD += 1
            elif s1[i] == s1[j] and s2[i] != s2[j]:
                cardR1 += 1
            elif s2[i] == s2[j] and s1[i] != s1[j]:
                cardR2 += 1
    return (2./(k*(k-1)))*(cardD + max(cardR1,cardR2))


import numpy as np
import matplotlib.pyplot as plt
from math import floor
from functools import partial
from typing import List, Union, Tuple

def find_offsets(minimum: int, maximum: int) -> Tuple[int]:
    '''
    Finds the required coefficient and offset to map a random number generator that
    produces between (0, 1) to a given minimum/maximum range
    '''
    # Find range
    coefficient_range = maximum - minimum

    # Find offset
    offset = abs(maximum - coefficient_range)
    if maximum < coefficient_range:
        offset *= -1

    return coefficient_range, offset

def random_polynomial_coefficients(minimum: int, maximum: int, degree: int) -> List[float]:
    '''
    Create a polynomial of form:
    ax^n + bx^n-1 + cx^n-2 .... + yx^1 + z

    ::param min:: Minimum coefficient value
    ::param max:: Maximum coefficient value

    ::return:: coefficients should be interpreted as in ascending order for simplicity
    '''
    if maximum <= minimum:
        raise ValueError('Maximum must be larger than minimum')

    coefficient_range, offset = find_offsets(minimum, maximum)
    coefficients = np.random.random((degree + 1)) * coefficient_range + offset

    return coefficients

def apply_polynomial(coefficients: List[float], x: Union[float, int]) -> Union[float, int]:
    '''
    Determine the return value of a polynomial with given coefficients at value x
    '''
    y = sum(coefficients[i] * (x**i) for i in range(len(coefficients)))

    return y

def create_data(minimum: int, maximum: int,
                coefficients: List[float], percent_training_data: float =0.5,
                data_point_count: int=10000) -> Tuple[List[float]]:
    '''
    Creates a sample set of data for testing and training based on the polynomial
    with given coefficients.

    ::params minimum, maximum:: the min/max values on the x domain to evaluate
    the polynomial
    ::return train_x, train_y, test_x, test_y:: -> ([x_data], [y_data], [x_data], [y_data])
    '''

    if percent_training_data <= 0:
        raise ValueError('Percent Training Data Must Be Positive')
    elif percent_training_data >= 1:
        raise ValueError('Percent Training Data Must Be Less Than 1')
    elif maximum <= minimum:
        raise ValueError('Maximum Must Be Larger Than Minimum')

    apply_poly_partial = partial(apply_polynomial, coefficients)
    training_data_count = floor(data_point_count * percent_training_data)
    coefficient_range, offset = find_offsets(maximum, minimum)

    x_points = np.random.random((data_point_count)) * coefficient_range + offset
    y_points = np.array(list(map(apply_poly_partial, x_points)))

    training_x_points = x_points[:training_data_count]
    training_y_points = y_points[:training_data_count]
    testing_x_points = x_points[training_data_count:]
    testing_y_points = y_points[training_data_count:]

    return training_x_points, training_y_points, testing_x_points, testing_y_points

def plot_data(data: List[List[float]]):
    '''
    Graph the training and testing data

    ::param data:: training/testing x and y arrays
    '''
    plt.scatter(data[0], data[1], color='blue', s=2, label='training')
    plt.scatter(data[2], data[3], color='red', s=2, label='testing')
    plt.legend()
    plt.show()

coefs = random_polynomial_coefficients(-1, 1, 4)
data = create_data(-6, 6, coefs, 0.5, data_point_count=100)
plot_data(data)


import matplotlib.pyplot as plt
import numpy as np
from sklearn.neighbors import NearestNeighbors

def lp(x, y, p=2):
# https://en.wikipedia.org/wiki/Lp_space#The_p-norm_in_finite_dimensions

    d = np.sum((np.abs(x-y))**p)**(1/p)
    return d

def nns(data, n_neighbors=2, p=2, n_jobs=6):

    NNs = NearestNeighbors(n_neighbors=n_neighbors, algorithm='auto', metric=lp, metric_params={'p': p}, n_jobs=n_jobs)
    NNs_data = NNs.fit(data)
    dd, idxx = NNs_data.kneighbors(data)

    return dd[:, 1:], idxx[:, 1:]

def plt_data(data, fname, path='./', alpha=0.2, face_color = True):

    fig, ax = plt.subplots(figsize=(12, 8))
    ax.set_ylabel('$y$')
    ax.set_xlabel('$x$')
    ax.set_yticklabels([])
    ax.set_xticklabels([])
    ax.axis('off')

    ax.scatter(data[:, 0], data[:, 1], alpha=alpha, color='blue')
    plt.tight_layout()

    fig.savefig(f'{path}/{fname}.pdf')
    if face_color:
        fig.savefig(f'{path}/{fname}.png')
    else:
        fig.savefig(f'{path}/{fname}.png', facecolor='none')


# -*- coding: UTF-8 -*-
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 统计数组最大值/最小值
print(np.amin(a))
print(np.amin(a, 0))
print(np.amin(a, 1))
print(np.amax(a))
print(np.amax(a, 0))
print(np.amax(a, 1))

# 统计最大值与最小值之差
print(np.ptp(a))
print(np.ptp(a, 0))
print(np.ptp(a, 1))

# 统计数组的百分位数
print(np.percentile(a, 50))
print(np.percentile(a, 50, axis=0))
print(np.percentile(a, 50, axis=1))

# 统计中位数/平均数
print(np.median(a))
print(np.median(a, axis=0))
print(np.median(a, axis=1))
print(np.mean(a))
print(np.mean(a, axis=0))
print(np.mean(a, axis=1))

# 统计加权平均值
b = np.array([1, 2, 3, 4])
wts = np.array([1, 2, 3, 4])
print(np.average(b))
print(np.average(b, weights=wts))

# 统计标准差/方差
print(np.std(b))
print(np.var(b))


#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt

def lissajous(b=1, a=1, A=2, B=1, d=np.pi/2, col='r-'):
    xs = np.linspace(0, 30, 600)
    plt.plot(A*np.sin(a*xs + d), B*np.sin(b*xs), col, linewidth=1)

lissajous(b=1, col='r-')
lissajous(b=2, col='g-')
lissajous(b=3, col='b-')
lissajous(b=np.pi, col='y-')
lissajous(b=np.e, col='c-')
plt.show()


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib
import os

class perceptron:
  def __init__(self,eta,epochs):
    #eta is learning rate
    np.random.seed(42)
    self.weights=np.random.randn(3) * 1e-4 # Random weight initilization
    print(f"Initial weights before Training: {self.weights}")
    self.eta=eta
    self.epochs=epochs

  def activationfunction(self,input,weights):

    z=np.dot(input,weights) # z=x * w
    return np.where(z>0,1,0)

  def fit(self,x,y):
    self.x=x
    self.y=y

    x_with_bias=np.c_[self.x,-np.ones((len(self.x),1))] #concatination
    print(f"x_with_bias :{x_with_bias}")
    for epochs in range(self.epochs):
      print("--"*10)
      print(f"for epoch :{epochs}")
      print("--"*10)
      y_hat=self.activationfunction(x_with_bias,self.weights)  # forward propogation
      print(f"predicted value:{y_hat}")
      self.error=self.y -y_hat
      print(f"error:\n{self.error}")
      self.weights=self.weights + self.eta * np.dot(x_with_bias.T,self.error) # backward propogation
      print(f"updated weights after epoch:{epochs}/{self.epochs}:{self.weights}")
      print("##"*10)

  def predict(self,x):
    x_with_bias=np.c_[x,np.ones((len(x),1))]
    return self.activationfunction(x_with_bias,self.weights)

  def total_loss(self):
    total_loss=np.sum(self.error)
    print(f"total_loss:{total_loss}")
    return total_loss


import numpy as np

class BinaryLogisticRegression:
    """
    Binary logistic regression classifier.

    Uses gradient descent to determine the parameters of the logistic
    regression classifier.

    Parameters
    ----------
    max_iter : int, default=1000
        Maximum number of iterations allowed in gradient descent.
    eta : float, default=0.1
        Learning rate of gradient descent. Must be greater than 0.
    alpha : float, default=0.1
        Regularization hyperparameter. Larger alpha results in stronger
        regularization. Should be greater than 0.
    reg : {'l1', 'l2'}, default='l2'
        Determines whether L1 or L2 regularization will be used.
    eps : float, default=1E-6
        Training termination criterion. If a norm of a gradient during
        gradient descent is less than eps then training is finished.
    log : bool, default=False
        If set to True training progress will be printed to console.

    Attributes
    ----------
    w : ndarray of shape (n_features,)
        Vector of weights in the decision function. n_features is the
        number of features as given in fit method.
    b : float
        Bias used in the decision function.
    """

    L1 = 1
    L2 = 2

    def __init__(self, max_iter=1000, eta=0.1, alpha=0.1, reg='l2', eps=1E-6,
                 log=False):
        self._max_iter = max_iter
        self._eta = eta
        self._alpha = alpha
        self._reg = None
        if reg == 'l2':
            self._reg = self.L2
        elif reg == 'l1':
            self._reg = self.L1
        else:
            raise ValueError('invalid reg value: ' + reg)
        self._eps = eps
        self._log = log
        self._w, self._b = None, None

    @property
    def w(self):
        return self._w.copy()

    @property
    def b(self):
        return self._b

    def fit(self, X, y):
        """
        Fits this model to the given training data.

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Training datapoints. n_samples is the number of samples and
            n_features is the number of features.
        y : ndarray of shape (n_samples,)
            Target vector. Since this is a binary classifier classes
            must be encoded by values 0 and 1.
        """
        N, d = X.shape
        w = np.random.randn(d)
        b = 0
        for i in range(self._max_iter):
            scores = X @ w + b
            e = np.exp(scores)
            probs = e / (1 + e)

            if self._log and i % 10 == 0:
                loss = -1/N * np.sum(np.log(np.abs(1 - y - probs)))
                if self._reg == self.L1:
                    loss += self._alpha * np.sum(np.abs(w))
                else:
                    loss += self._alpha * 1/2 * w @ w
                print('Iteration {}, loss = {}'.format(i, loss))

            gs = probs - y
            # .T not needed since gs is a 1D array
            grad_w = 1/N * gs.T @ X
            grad_b = 1/N * np.sum(gs)

            if self._reg == self.L1:
                grad_w += (self._alpha *
                    np.array([1 if wi > 0 else -1 for wi in w]))
            else:
                grad_w += self._alpha * w

            if np.linalg.norm(np.append(grad_w, grad_b)) < self._eps:
                break

            w -= self._eta * grad_w
            b -= self._eta * grad_b

        self._w = w
        self._b = b

    def decision_function(self, X):
        """
        Returns the values of the decision function for given data.

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Datapoints for which the decision function values should be
            computed. n_samples is the number of samples and n_features
            is the number of features.

        Returns
        -------
        y : ndarray of shape (n_samples,)
            Decision function values of given datapoints.
        """
        return X @ self._w + self._b

    def predict_proba(self, X):
        """
        Predicts the probabilities of given data.

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Array of datapoints. Classification probabilitiy of each
            datapoint is computed and returned. n_samples is the
            number of samples and n_features is the number of features.

        Returns
        -------
        probs : ndarray of shape (n_samples, 2)
            Classification probabilities. probs[i, 0] is the
            probability of the datapoint X[i] belonging to class
            encoded by 0 and probs[i, 1] is the probability of
            datapoint X[i] belonging to class encoded by 1.
        """
        if self._w is None:
            raise RuntimeError(
                'fit must be called before a call to predict_proba')
        scores = self.decision_function(X)
        scores.resize(X.shape[0], 1)
        e = np.exp(scores)
        probs = e / (1 + e)
        return np.hstack((1 - probs, probs))

    def predict(self, X):
        """
        Predicts the classes of given datapoints.

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Datapoints to be classified. n_samples is the number of
            samples and n_features is the number of features.

        Returns
        -------
        y : ndarray of shape (n_samples,)
            Vector of predicted classes. y[i] is the class of the
            datapoint X[i]. Classes are encoded by 0s and 1s (as given
            in fit method).
        """
        if self._w is None:
            raise RuntimeError('fit must be called before a call to predict')
        probs = self.predict_proba(X)[:, 1]
        return (probs > 0.5).astype(np.int)

def _print_performance(y, y_predicted):
    accuracy, precision, recall = performance_binary(y, y_predicted)
    print('Accuracy:  {:.5f}'.format(accuracy))
    print('Precision: {:.5f}'.format(precision))
    print('Recall:    {:.5f}'.format(recall))

def _get_range(X, margin=0.2):
    xmin, ymin = tuple(np.min(X, axis=0))
    xmax, ymax = tuple(np.max(X, axis=0))
    xrange = (xmin - margin * (xmax-xmin), xmax + margin * (xmax-xmin))
    yrange = (ymin - margin * (ymax-ymin), ymax + margin * (ymax-ymin))
    return xrange, yrange

def _plot_results(clf, X, y, y_predicted):
    xrange, yrange = _get_range(X)
    plot_surface(lambda x: clf.predict_proba(x)[:, 1],
                 xrange=xrange, yrange=yrange, offset=0.5)
    cmap = lambda x: (0.2, 0.2, 0.2, 1) if x == 0 else (1, 1, 1, 1)
    plot_classification(X, y, y_predicted, cmap=cmap)
    plt.xlim(xrange[0], xrange[1])
    plt.ylim(yrange[0], yrange[1])
    plt.show()

def main():
    seed = np.random.randint(1E9)
    print('Using seed {}.'.format(seed))
    np.random.seed(seed)

    X, y = sample_gaussian_2d(2, 100)
    clf = BinaryLogisticRegression(alpha=0.2)
    clf.fit(X, y)
    y_predicted = clf.predict(X)

    w, b = clf.w, clf.b
    print('w = ({:.3f}, {:.3f}), b = {:.3f}'.format(w[0], w[1], b))
    _print_performance(y, y_predicted)
    _plot_results(clf, X, y, y_predicted)

if __name__ == '__main__':
    from data import sample_gaussian_2d
    from metrics import performance_binary
    from plotting import plot_classification, plot_surface
    import matplotlib.pyplot as plt
    main()


"""
 Copyright 2018 Johns Hopkins University  (Author: Jesus Villalba)
 Apache 2.0  (http://www.apache.org/licenses/LICENSE-2.0)

 Some math functions.
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
from six.moves import xrange

import numpy as np
import scipy.linalg as la

from ..hyp_defs import float_cpu

def logdet_pdmat(A):
    """Log determinant of positive definite matrix.
    """
    assert(A.shape[0] == A.shape[1])
    R=la.cholesky(A)
    return 2*np.sum(np.log(np.diag(R)))

def invert_pdmat(A, right_inv=False, return_logdet=False, return_inv=False):
    """Inversion of positive definite matrices.
       Returns lambda function f that multiplies the inverse of A times a vector.

    Args:
      A: Positive definite matrix
      right_inv: If False, f(v)=A^{-1}v; if True f(v)=v' A^{-1}
      return_logdet: If True, it also returns the log determinant of A.
      return_inv: If True, it also returns A^{-1}

    Returns:
      Lambda function that multiplies A^{-1} times vector.
      Cholesky transform of A upper triangular
      Log determinant of A
      A^{-1}
    """
    assert(A.shape[0] == A.shape[1])
    R=la.cholesky(A, lower=False)

    if right_inv:
        fh=lambda x: la.cho_solve((R, False), x.T).T
    else:
        fh=lambda x: la.cho_solve((R, False), x)
        #fh=lambda x: la.solve_triangular(R, la.solve_triangular(R.T, x, lower=True), lower=False)

    r = [fh, R]

    logdet = None
    invA = None

    if return_logdet:
        logdet=2*np.sum(np.log(np.diag(R)))
        r.append(logdet)

    if return_inv:
        invA=fh(np.eye(A.shape[0]))
        r.append(invA)

    return r

def invert_trimat(A, lower=False, right_inv=False, return_logdet=False, return_inv=False):
    """Inversion of triangular matrices.
       Returns lambda function f that multiplies the inverse of A times a vector.

    Args:
      A: Triangular matrix.
      lower: if True A is lower triangular, else A is upper triangular.
      right_inv: If False, f(v)=A^{-1}v; if True f(v)=v' A^{-1}
      return_logdet: If True, it also returns the log determinant of A.
      return_inv: If True, it also returns A^{-1}

    Returns:
      Lambda function that multiplies A^{-1} times vector.
      Log determinant of A
      A^{-1}
    """

    if right_inv:
        fh=lambda x: la.solve_triangular(A.T, x.T, lower=not(lower)).T
    else:
        fh=lambda x: la.solve_triangular(A, x, lower=lower)

    if return_logdet or return_inv:
        r = [fh]
    else:
        r = fh

    if return_logdet:
        logdet=np.sum(np.log(np.diag(A)))
        r.append(logdet)

    if return_inv:
        invA=fh(np.eye(A.shape[0]))
        r.append(invA)

    return r

def softmax(r, axis=-1):
    """
    Returns:
      y = \exp(r)/\sum(\exp(r))
    """
    max_r=np.max(r, axis=axis, keepdims=True)
    r=np.exp(r-max_r)
    r/=np.sum(r, axis=axis, keepdims=True)
    return r

def logsumexp(r, axis=-1):
    """
    Returns:
      y = \log \sum(\exp(r))
    """
    max_r=np.max(r, axis=axis, keepdims=True)
    r=np.exp(r-max_r)
    return np.log(np.sum(r, axis=axis)+1e-20) + np.squeeze(max_r, axis=axis)

def logsigmoid(x):
    """
      Returns:
        y = \log(sigmoid(x))
    """
    e = np.exp(-x)
    f = x < -100
    log_p = -np.log(1+np.exp(-x))
    log_p[f] = x[f]
    return log_p

def neglogsigmoid(x):
    """
      Returns:
        y = -\log(sigmoid(x))
    """
    e = np.exp(-x)
    f = x < -100
    log_p = np.log(1+np.exp(-x))
    log_p[f] = - x[f]
    return log_p

def sigmoid(x):
    """
      Returns:
        y = sigmoid(x)
    """
    e = np.exp(-x)
    f = x < -100
    p = 1/(1+np.exp(-x))
    p[f] = 0
    return p

def fisher_ratio(mu1, Sigma1, mu2, Sigma2):
    """Computes the Fisher ratio between two classes
       from the class means and covariances.
    """
    S=Sigma1+Sigma2
    L=invert_pdmat(S)[0]
    delta=mu1-mu2
    return np.inner(delta, L(delta))

def fisher_ratio_with_precs(mu1, Lambda1, mu2, Lambda2):
    """Computes the Fisher ratio between two classes
       from the class means precisions.
    """

    Sigma1 = invert_pdmat(Lambda1, return_inv=True)[-1]
    Sigma2 = invert_pdmat(Lambda2, return_inv=True)[-1]
    return fisher_ratio(mu1, Sigma1, mu2, Sigma2)

def symmat2vec(A, lower=False, diag_factor=None):
    """Puts a symmetric matrix into a vector.

    Args:
      A: Symmetric matrix.
      lower: If True, it uses the lower triangular part of the matrix.
             If False, it uses the upper triangular part of the matrix.
      diag_factor: It multiplies the diagonal of A by diag_factor.

    Returns:
      Vector with the upper or lower triangular part of A.
    """
    if diag_factor is not None:
        A = np.copy(A)
        A[np.diag_indices(A.shape[0])] *= diag_factor
    if lower:
         return A[np.tril_indices(A.shape[0])]
    return A[np.triu_indices(A.shape[0])]

def vec2symmat(v, lower=False, diag_factor=None):
    """Puts a vector back into a symmetric matrix.

    Args:
      v: Vector with the upper or lower triangular part of A.
      lower: If True, v contains the lower triangular part of the matrix.
             If False, v contains the upper triangular part of the matrix.
      diag_factor: It multiplies the diagonal of A by diag_factor.

    Returns:
      Symmetric matrix.
    """

    dim=int((-1+np.sqrt(1+8*v.shape[0]))/2)
    idx_u=np.triu_indices(dim)
    idx_l=np.tril_indices(dim)
    A=np.zeros((dim,dim), dtype=float_cpu())
    if lower:
        A[idx_l]=v
        A[idx_u]=A.T[idx_u]
    else:
        A[idx_u]=v
        A[idx_l]=A.T[idx_l]
    if diag_factor is not None:
        A[np.diag_indices(A.shape[0])] *= diag_factor
    return A

def trimat2vec(A, lower=False):
    """Puts a triangular matrix into a vector.

    Args:
      A: Triangular matrix.
      lower: If True, it uses the lower triangular part of the matrix.
             If False, it uses the upper triangular part of the matrix.

    Returns:
      Vector with the upper or lower triangular part of A.
    """

    return symmat2vec(A, lower)

def vec2trimat(v, lower=False):
    """Puts a vector back into a triangular matrix.

    Args:
      v: Vector with the upper or lower triangular part of A.
      lower: If True, v contains the lower triangular part of the matrix.
             If False, v contains the upper triangular part of the matrix.

    Returns:
      Triangular matrix.
    """
    dim=int((-1+np.sqrt(1+8*v.shape[0]))/2)
    A=np.zeros((dim,dim), dtype=float_cpu())
    if lower:
        A[np.tril_indices(dim)]=v
        return A
    A[np.triu_indices(dim)]=v
    return A

def fullcov_varfloor(S, F, F_is_chol=False, lower=False):
    """Variance flooring for full covariance matrices.

    Args:
      S: Covariance.
      F: Minimum cov or Cholesqy decomposisition of it
      F_is_chol: If True F is Cholesqy decomposition
      lower: True if cholF is lower triangular, False otherwise

    Returns:
      Floored covariance
    """
    if isinstance(F, np.ndarray):
        if not F_is_chol:
            cholF = la.cholesky(F, lower=False, overwrite_a=False)
        else:
            cholF = F
            if lower:
                cholF = cholF.T
        icholF = invert_trimat(cholF, return_inv=True)[-1]
        T = np.dot(np.dot(icholF.T, S) , icholF)
    else:
        T = S/F

    u, d, _ = la.svd(T, full_matrices=False, overwrite_a=True)
    d[d<1.]=1
    T = np.dot(u*d, u.T)

    if isinstance(F, np.ndarray):
        S = np.dot(cholF.T, np.dot(T, cholF))
    else:
        S = F*T
    return S

def fullcov_varfloor_from_cholS(cholS, cholF, lower=False):
    """Variance flooring for full covariance matrices
       using Cholesky decomposition as input/output

    Args:
      cholS: Cholesqy decomposisition of the covariance.
      cholF: Cholesqy decomposisition of the minimum covariance.
      lower: True if matrices are lower triangular, False otherwise

    Returns:
      Cholesky decomposition of the floored covariance
    """

    if isinstance(cholF, np.ndarray):
        if lower:
            cholS = cholS.T
            cholF = cholF.T
        T = np.dot(cholS, invert_trimat(cholF, return_inv=True)[-1])
    else:
        if lower:
            cholS=cholS.T
        T = cholS/cholF
    T = np.dot(T.T,T)
    u, d, _ = la.svd(T, full_matrices=False, overwrite_a=True)
    d[d<1.]=1
    T = np.dot(u*d, u.T)
    if isinstance(cholF, np.ndarray):
        S = np.dot(cholF.T, np.dot(T, cholF))
    else:
        S = (cholF**2)*T
    return la.cholesky(S, lower)

def int2onehot(class_ids, num_classes=None):
    """Integer to 1-hot vector.

    Args:
      class_ids: Numpy array of integers.
      num_classes: Maximum number of classes.

    Returns:
      1-hot Numpy array.
    """

    if num_classes is None:
        num_classes = np.max(class_ids)+1

    p = np.zeros((len(class_ids), num_classes), dtype=float_cpu())
    p[np.arange(len(class_ids)), class_ids]=1
    return p


import numpy as np

class PCA:
    """:class:`PCA` is a class for dimensionality reduction using PCA in Jina.

    :param n_components: Number of components to keep when projecting with PCA
    :param whiten: Flag variable stating if there projecting with whitening
    """

    def __init__(self, n_components: int, whiten: bool = False):
        self.n_components = n_components
        self.whiten = whiten
        self.e_values = None
        self.w = None

    def fit(self, x_mat: np.ndarray):
        """
        Computes the projection matrix of the PCA algorithm and stores it to self.w

        :param x_mat: Matrix of shape (n_observations, n_features)
        """

        x_mat = x_mat - x_mat.mean(axis=0)

        # covariance matrix (n_features, n_features)
        cov = np.cov(x_mat.T) / x_mat.shape[0]

        # Compute eigenvalues eigenvectors of cov
        e_values, e_vectors = np.linalg.eig(cov)

        # Sort eigenvalues by magnitude (higher to lower)
        idx = e_values.argsort()[::-1]
        e_values = e_values[idx]

        # Sort eigen vectors by eigenvalue magnitude (higher to lower)
        e_vectors = e_vectors[:, idx]

        # Projection matrix contains eigenvectors sorted
        self.w = e_vectors
        self.e_values = e_values

    def transform(self, x_mat: np.ndarray) -> np.ndarray:
        """Projects data from n_features to self.n_components features.

        :param x_mat: Matrix of shape (n_observations, n_features)
        :return: Matrix of shape (n_observations, self.n_components)
        """
        if self.w is not None:
            x_mat_projected = x_mat.dot(self.w[:, : self.n_components])
            if self.whiten:
                return x_mat_projected / np.sqrt(self.e_values[0 : self.n_components])
            else:
                return x_mat_projected

    def fit_transform(self, x_mat: np.ndarray) -> np.ndarray:
        """Fits the PCA and returns a transformed data
        :param x_mat:  Matrix of shape (n_observations, n_features)
        :return: Matrix of shape (n_observations, self.n_components)
        """
        self.fit(x_mat)
        return self.transform(x_mat)


# -*- coding: utf-8 -*-
import numpy as np
import scipy as sp

def sine(t, A=1, f=1, D=0):
    """
    t: time
    A: the amplitude, the peak deviation of the function from zero.
    f: the ordinary frequency, the number of oscillations (cycles) that occur each second of time.
    D: non-zero center amplitude
    """
    sine_ = A * np.sin(2 * np.pi * f * t) + D
    return sine_

def cosine(t, A=1, f=1, D=0):
    """
    t: time
    A: the amplitude, the peak deviation of the function from zero.
    f: the ordinary frequency, the number of oscillations (cycles) that occur each second of time.
    D: non-zero center amplitude
    """
    cos_ = A * np.sin(2 * np.pi * f * t) + D
    return cos_

def square(t, A=1, f=1, D=0):
    """
    t: time
    A: the amplitude, the peak deviation of the function from zero.
    f: the ordinary frequency, the number of oscillations (cycles) that occur each second of time.
    D: non-zero center amplitude
    """
    square_ = A * sp.signal.square(2 * np.pi * f * t) + D
    return square_

def sawtooth(t, A=1, f=1, D=0):
    """
    t: time
    A: the amplitude, the peak deviation of the function from zero.
    f: the ordinary frequency, the number of oscillations (cycles) that occur each second of time.
    D: non-zero center amplitude
    """
    sawtooth_ = A * sp.signal.sawtooth(2 * np.pi * f * t, width=1) + D
    return sawtooth_

def triangle(t, A=1, f=1, D=0):
    """
    t: time
    A: the amplitude, the peak deviation of the function from zero.
    f: the ordinary frequency, the number of oscillations (cycles) that occur each second of time.
    D: non-zero center amplitude
    """
    triangle_ = A * sp.signal.sawtooth(2 * np.pi * f * t, width=0.5) + D
    return triangle_

signal_generators = [sine, cosine, square, sawtooth, triangle]


"""
what makes filters high and low-pass; why is a Sobel filter high-pass and a Gaussian filter low-pass?

Well, you can actually visualize the frequencies that these filters block out by taking a look at their
fourier transforms. The frequency components of any image can be displayed after doing a Fourier Transform (FT).
An FT looks at the components of an image (edges that are high-frequency, and areas of smooth color as low-frequency),
and plots the frequencies that occur as points in spectrum. So, let's treat our filters as small images, and display
them in the frequency domain!

Areas of white or light gray, allow that part of the frequency spectrum through!
Areas of black mean that part of the spectrum is blocked out of the image.

Recall that the low frequencies in the frequency spectrum are at the center of the frequency transform image,
and high frequencies are at the edges. You should see that the Gaussian filter allows only low-pass frequencies through,
which is the center of the frequency transformed image.
The sobel filters block out frequencies of a certain orientation
and a laplace (all edge, regardless of orientation) filter, should block out low-frequencies!

"""

import matplotlib.pyplot as plt
import numpy as np

# Define gaussian, sobel, and laplacian (edge) filters

gaussian = (1 / 9) * np.array([[1, 1, 1],
                               [1, 1, 1],
                               [1, 1, 1]])

sobel_x = np.array([[-1, 0, 1],
                    [-2, 0, 2],
                    [-1, 0, 1]])

sobel_y = np.array([[-1, -2, -1],
                    [0, 0, 0],
                    [1, 2, 1]])

# laplacian, edge filter
laplacian = np.array([[0, 1, 0],
                      [1, -4, 1],
                      [0, 1, 0]])

filters = [gaussian, sobel_x, sobel_y, laplacian]
filter_name = ['gaussian', 'sobel_x', 'sobel_y', 'laplacian']

# perform a fast fourier transform on each filter
# and create a scaled, frequency transform image
f_filters = [np.fft.fft2(x) for x in filters]
f_shift = [np.fft.fftshift(y) for y in f_filters]
frequency_tx = [np.log(np.abs(z) + 1) for z in f_shift]

# display 4 filters
for i in range(len(filters)):
    plt.subplot(2, 2, i + 1)
    plt.imshow(frequency_tx[i], cmap='gray')
    plt.title(filter_name[i])
    plt.xticks([])
    plt.yticks([])

plt.show()


# -*- coding: utf-8 -*-

"""
Author: Saman Moniri (U. Michigan, November 2018)
Course project for ChE 696: On-ramp to Data Science

Project description:
Train a linear regression model using random numbers.
Use trained model to predict the total payment for all the claims in thousands of Swedish Kronor (y) given the total number of claims (x).
The “Auto Insurance in Sweden” dataset is available at:
https://machinelearningmastery.com/implement-simple-linear-regression-scratch-python/

"""
import matplotlib.pyplot as plt
import numpy as np
import sklearn
from sklearn import linear_model
from sklearn.metrics import *
from sklearn.datasets import fetch_mldata
from csv import reader

# Load a CSV file
def load_csv(filename):
    dataset = list()
    with open(filename, 'r') as file:
        csv_reader = reader(file)
        for row in csv_reader:
            if not row:
                continue
            dataset.append(row)
    return dataset

# Use random numbers for training =
xtrain = np.linspace(0,150, 150)
ytrain = 5*(xtrain+3*np.random.random(xtrain.shape[0]))

# reshape input to 2d arrays (code expects it this way)
xtrain = xtrain.reshape(xtrain.shape[0], -1)
ytrain = ytrain.reshape(ytrain.shape[0], -1)

# create the machine learning model object
regr = linear_model.LinearRegression()

# fit the machine learning model object
regr.fit(xtrain, ytrain)

# Use the "Auto Insurance in Sweden" dataset (link below) to predict the total payment for all the claims in thousands of Swedish Kronor (y) given the total number of claims (x)
#https://machinelearningmastery.com/implement-simple-linear-regression-scratch-python/
filename = 'insurance.csv'
dataset = load_csv(filename)
dataset = dataset[1:] # exclude header
xtest = []
ytest = []

for i in range(len(dataset)):
    xtest.append(dataset[i][0]) # x
    ytest.append(dataset[i][1]) # y

xtest = np.array(xtest) # convert to np array
ytest = np.array(ytest) # convert to np array
xtest = xtest.reshape(xtest.shape[0], -1) # reshape to 2d array
ytest = ytest.reshape(ytest.shape[0], -1) # reshape to 2d array
xtest = xtest.astype(float) # change type to float
ytest = ytest.astype(float) # change type to float

# predict values using the fitted model
ypred = regr.predict(xtest)

# the coefficients
print('Coefficients: \n', regr.coef_)
# the mean squared error
print("Mean squared error: %.2f" % mean_squared_error(ytest, ypred))
# variance score
print('Variance score: %.2f' % r2_score(ytest, ypred))

plt.figure()
plt.scatter(xtest[:,0], ytest,  color='black', label="Testing Data")
plt.scatter(xtrain[:,0], ytrain, facecolors="none", edgecolors="blue", label="Training Data")
plt.plot(xtest[:,0], ypred, color='red', linewidth=3, label="Prediction")
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc='best')
plt.show()


import numpy as np
from numpy.linalg import *

def mds(d, dimensions = 2):
    """
    Multidimensional Scaling - Given a matrix of interpoint distances,
    find a set of low dimensional points that have similar interpoint
    distances.
    """
    print('Multidimensional Scaling for scatter plot...')
    (n,n) = d.shape
    E = (-0.5 * d**2)
    # Use mat to get column and row means to act as column and row means.
    Er = np.mat(np.mean(E,1))
    Es = np.mat(np.mean(E,0))
    F = np.array(E - np.transpose(Er) - Es + np.mean(E))
    [U, S, V] = svd(F)
    Y = U * np.sqrt(S)
    return (Y[:,0:dimensions], S)


import math
import numbers
import operator as op

import numpy as np
import scipy.stats as stats

from .random_variables import RV
from .result import (
    Tuple,
    TimeFunction,
    ContinuousTimeFunction,
    DiscreteValued
)
from .results import Results

pi = math.pi
e = math.e
inf = float("inf")

floor = math.floor
ceil = math.ceil

def operation_factory(operation):

    def _op_func(x):
        if isinstance(x, (RV, Tuple, TimeFunction)):
            # recursively call op_fun until x is a scalar
            return x.apply(_op_func)
        elif isinstance(x, Results):
            return x.apply(_op_func)
        else:
            return operation(x)

    return _op_func

sqrt = operation_factory(math.sqrt)
exp = operation_factory(math.exp)
sin = operation_factory(math.sin)
cos = operation_factory(math.cos)
tan = operation_factory(math.tan)
factorial = operation_factory(math.factorial)

def log(value, base=e):
    return operation_factory(lambda x: math.log(x, base))(value)

def mean(x):
    if isinstance(x, numbers.Real):
        raise Exception("Taking the mean with one value is unnecessary.")
    else:
        return sum(x) / len(x)

def cumsum(x):
    return x.cumsum()

def var(x):
    return mean([(i - mean(x)) ** 2 for i in x])

def sd(x):
    return math.sqrt(var(x))

def median(x):
    if isinstance(x, numbers.Real):
        raise Exception("Taking the median of one value is unnecessary.")
    else:
        return np.median(x)

def min_max_diff(x):
    if isinstance(x, numbers.Real):
        raise Exception("Taking the range of one value is unnecessary.")
    else:
        return max(x) - min(x)

def med_abs_dev(x):
    return median(list(abs(i-median(x)) for i in x))

def quantile(q):
    return lambda x: np.percentile(x, q * 100)

def iqr(x):
    if isinstance(x, numbers.Real):
        raise Exception("Taking the iqr of one value is unnecessary.")
    else:
        q75, q25 = np.percentile(x, [75, 25])
        return q75 - q25

def orderstatistics(n):
    if n <= 0:
        raise Exception("Out of bounds. Lowest order is 1.")
    else:
        return lambda x: np.partition(x, n - 1)[n - 1]

def skewness(x):
    if isinstance(x, numbers.Real):
        raise Exception("Finding the skenewss of one value is unnecessary,")
    else:
        return stats.skew(x)

def kurtosis(x):
    if isinstance(x, numbers.Real):
        raise Exception("Finding the kurtosis of one value is unnecessary.")
    else:
        return stats.kurtosis(x)

def moment(k):
    return lambda x: stats.moment(x, k)

def trimmed_mean(alpha):
    return lambda x: stats.trim_mean(x, alpha)

def comparefun(x, compare, value):
    count = 0
    for i in x:
        if compare(i, value):
            count += 1
    return count

def count(func=lambda x: True):
    def _func(x):
        val = 0
        for i in x:
            if func(i):
                val += 1
        return val
    return _func

def count_eq(value):
    def func(x):
        return comparefun(x, op.eq, value)
    return func

def count_neq(value):
    def func(x):
        return comparefun(x, op.ne, value)
    return func

def count_lt(value):
    def func(x):
        return comparefun(x, op.lt, value)
    return func

def count_gt(value):
    def func(x):
        return comparefun(x, op.gt, value)
    return func

def count_geq(value):
    def func(x):
        return comparefun(x, op.ge, value)
    return func

def count_leq(value):
    def func(x):
        return comparefun(x, op.le, value)
    return func

def interarrival_times(continuous_time_function):
    """Given a realization of a continuous-time,
       discrete-state process, returns the interarrival
       times (i.e., the times between each state change).

    Args:
      continuous_time_function: A ContinuousTimeFunction
        object, such as ContinuousTimeMarkovChainResult or
        PoissonProcessResult.
    """
    if not (isinstance(continuous_time_function,
                       ContinuousTimeFunction) and
            isinstance(continuous_time_function,
                       DiscreteValued)):
        raise TypeError(
            "Interarrival times are only defined for "
            "continuous-time, discrete-valued functions."
        )
    return continuous_time_function.get_interarrival_times()

def arrival_times(continuous_time_function):
    """Given a realization of a continuous-time,
       discrete-state process, returns the arrival
       times (i.e., the times when the state changes).

    Args:
      continuous_time_function: A ContinuousTimeFunction
        object, such as ContinuousTimeMarkovChainResult or
        PoissonProcessResult.
    """
    if not (isinstance(continuous_time_function,
                       ContinuousTimeFunction) and
            isinstance(continuous_time_function,
                       DiscreteValued)):
        raise TypeError(
            "Interarrival times are only defined for "
            "continuous-time, discrete-valued functions."
        )
    return continuous_time_function.get_arrival_times()

def states(discrete_valued_function):
    """Given a realization of a discrete-valued function,
       returns an InfiniteVector of the sequence of
       values (or states).

    Args:
      discrete_valued_function: A DiscreteValued object
                                (e.g., MarkovChainResult or
                                       PoissonProcessResult)
    """
    if not isinstance(discrete_valued_function, DiscreteValued):
        raise TypeError(
            "States are only defined for discrete-valued "
            "functions."
        )
    return discrete_valued_function.get_states()


#!/usr/bin/env python
# -*- coding: UTF-8 -*-

__author__ = "Kasra Hosseini"
__license__ = "MIT License"

import numpy as np
from typing import Union

try:
    import pyproj
    pyproj_imported = True
except ImportError:
    pyproj_imported = False

def lonlatdep2xyz_spherical(lons: Union[float, int, np.ndarray, list],
                            lats: Union[float, int, np.ndarray, list],
                            depths: Union[float, int, np.ndarray, list, None]=None,
                            return_one_arr: Union[bool]=True,
                            earth_radius_m: Union[float, int]=6371000):
    """Convert lons/lats/depths to x/y/z

    Parameters
    ----------
    lons : Union[float, int, np.ndarray, list]
    lats : Union[float, int, np.ndarray, list]
    depths : Union[float, int, np.ndarray, list, None], optional
    return_one_arr : Union[bool], optional
    earth_radius_m : Union[float, int], optional
    """
    # co-latitudes:
    colats = 90.0 - lats
    # radii
    r = earth_radius_m - depths

    x = r * np.sin(np.deg2rad(colats)) * np.cos(np.deg2rad(lons))
    y = r * np.sin(np.deg2rad(colats)) * np.sin(np.deg2rad(lons))
    z = r * np.cos(np.deg2rad(colats))

    if return_one_arr:
        return np.vstack([x, y, z]).T
    else:
        return x, y, z

def xyz2lonlatdep_spherical(x: Union[float, int, np.ndarray, list],
                            y: Union[float, int, np.ndarray, list],
                            z: Union[float, int, np.ndarray, list, None]=None,
                            return_one_arr: Union[bool]=True,
                            earth_radius_m: Union[float, int]=6371000):
    """Convert x/y/z/ to lons/lats/depths

    Parameters
    ----------
    x : Union[float, int, np.ndarray, list]
    y : Union[float, int, np.ndarray, list]
    z : Union[float, int, np.ndarray, list, None], optional
    return_one_arr : Union[bool], optional
    earth_radius_m : Union[float, int], optional
    """
    rxy = np.sqrt(x**2 + y**2)
    lons = np.arctan2(y, x)*180./np.pi
    lats = np.arctan2(z, rxy)*180./np.pi
    depths = earth_radius_m - np.sqrt(x**2 + y**2 + z**2)

    if return_one_arr:
        return np.vstack([lons, lats, depths]).T
    else:
        return lons, lats, depths

def lonlatdep2xyz(lons: Union[float, int, np.ndarray, list],
                  lats: Union[float, int, np.ndarray, list],
                  depths: Union[float, int, np.ndarray, list, None]=None,
                  return_one_arr: Union[bool]=True):
    """Convert lons/lats/depths to x/y/z

    Parameters
    ----------
    lons : Union[float, int, np.ndarray, list]
    lats : Union[float, int, np.ndarray, list]
    depths : Union[float, int, np.ndarray, list, None], optional
    return_one_arr : Union[bool], optional
    """

    if not pyproj_imported:
        print(f"[WARNING] pyproj could not be imported.")
        print(f"[WARNING] lonlatdep2xyz_spherical will be used insted.")
        lonlatdep2xyz_spherical(lons, lats, depths, return_one_arr)

    # Define projections
    ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84')
    lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84')

    lons = convert2array(lons)
    lats = convert2array(lats)
    if depths is None:
        depths = np.ones(len(lons))
    else:
        depths = convert2array(depths)

    # trainsform to x, y, z (in meters)
    # -1 * depth as pyproj.transform expects altitude
    x, y, z = pyproj.transform(lla, ecef,
                               lons, lats, -1*depths,
                               radians=False)

    if return_one_arr:
        return np.vstack([x, y, z]).T
    else:
        return x, y, z

def convert2array(myinp):
    """Convert myinp ---> np.ndarray"""
    if isinstance(myinp, np.ndarray):
        return myinp
    elif isinstance(myinp, list):
        return np.array(myinp)
    elif isinstance(myinp, int):
        return np.array([myinp])
    elif isinstance(myinp, float):
        return np.array([myinp])
    else:
        print(f"WARNING: input type cannot be converted: {type(myinp)}")
        return None


# -*- coding: utf-8 -*-
from numpy import exp as npExp
from numpy import nan as npNaN
from numpy import power as npPow
from numpy import dot as npDot
from numpy import empty as npEmpty
from numpy import array as npArray
from pandas import Series
from pandas_ta.utils import get_offset, verify_series

def alma(close, length=None, sigma=None, distribution_offset=None, offset=None, **kwargs):
    """Indicator: Arnaud Legoux Moving Average (ALMA)"""
    # Validate Arguments
    length = int(length) if length and length > 0 else 10
    sigma = float(sigma) if sigma and sigma > 0 else 6.0
    distribution_offset = float(distribution_offset) if distribution_offset and distribution_offset > 0 else 0.85
    close = verify_series(close, length)
    offset = get_offset(offset)

    if close is None:
        return

    # Compute filter weights
    m = distribution_offset * (length - 1)
    s = length / sigma
    filter_index = npArray(range(length))
    weights = npExp(-npPow(filter_index - m, 2) / (2 * npPow(s, 2)))
    norm = weights.sum()

    result = npEmpty(close.shape)
    result[:] = npNaN
    valid_rng = range(length - 1, close.size)
    for j in valid_rng:
        subset = close[j - length + 1:j + 1]
        result[j] = npDot(subset, weights) / norm
    alma = Series(result, index=close.index)

    # Apply offset
    if offset != 0:
        alma = alma.shift(offset)

    # Handle fills
    if "fillna" in kwargs:
        alma.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        alma.fillna(method=kwargs["fill_method"], inplace=True)

    # Name & Category
    alma.name = f"ALMA_{length}_{sigma}_{distribution_offset}"
    alma.category = "overlap"

    return alma

alma.__doc__ = \
"""Arnaud Legoux Moving Average (ALMA)

The ALMA moving average uses the curve of the Normal (Gauss) distribution, which
can be shifted from 0 to 1. This allows regulating the smoothness and high
sensitivity of the indicator. Sigma is another parameter that is responsible for
the shape of the curve coefficients. This moving average reduces lag of the data
in conjunction with smoothing to reduce noise.

Implemented for Pandas TA by rengel8 based on the source provided below.

Sources:
    https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/

Calculation:
    refer to provided source

Args:
    close (pd.Series): Series of 'close's
    length (int): It's period, window size. Default: 10
    sigma (float): Smoothing value. Default 6.0
    distribution_offset (float): Value to offset the distribution min 0
        (smoother), max 1 (more responsive). Default 0.85
    offset (int): How many periods to offset the result. Default: 0

Kwargs:
    fillna (value, optional): pd.DataFrame.fillna(value)
    fill_method (value, optional): Type of fill method

Returns:
    pd.Series: New feature generated.
"""


import numpy as np
from scipy.stats import shapiro
from scipy.stats import anderson
from scipy.stats import normaltest

flutrends = np.loadtxt("goog_flutrends.csv", delimiter=',', usecols=(1,), skiprows=1, converters = {1: lambda s: float(s or 0)}, unpack=True)
N = len(flutrends)
normal_values = np.random.normal(size=N)
zero_values = np.zeros(N)

print "Normal Values Shapiro", shapiro(normal_values)
print "Zeroes Shapiro", shapiro(zero_values)
print "Flu Shapiro", shapiro(flutrends)
print

print "Normal Values Anderson", anderson(normal_values)
print "Zeroes Anderson", anderson(zero_values)
print "Flu Anderson", anderson(flutrends)
print

print "Normal Values normaltest", normaltest(normal_values)
print "Zeroes normaltest", normaltest(zero_values)
print "Flu normaltest", normaltest(flutrends)