import numpy as np
import imageio
from skimage.feature import canny
import cv2

DEG = np.pi / 180.0

def rgb2gray(rgb):
    return np.dot(rgb[..., :3], [0.299, 0.587, 0.114]).astype(np.uint8)

def fast_hough_line(img, angle_step=1, lines_are_white=True, value_threshold=5):
    """
    hough line using vectorized numpy operations,
    may take more memory, but takes much less time

    Input:
    img - 2D binary image with nonzeros representing edges
    angle_step - Spacing between angles to use every n-th angle
                 between -90 and 90 degrees. Default step is 1.
    lines_are_white - boolean indicating whether lines to be detected are white
    value_threshold - Pixel values above or below the value_threshold are edges

    Returns:
    accumulator - 2D array of the hough transform accumulator
    theta - array of angles used in computation, in radians.
    rhos - array of rho values. Max size is 2 times the diagonal
           distance of the input image.
    """
    # Rho and Theta ranges
    thetas = np.deg2rad(np.arange(-90.0, 90.0, angle_step)) #can be changed
    #width, height = col.size  #if we use pillow
    width, height = img.shape
    diag_len = int(np.ceil(np.sqrt(width * width + height * height)))   # max_dist
    rhos1 = np.linspace(-diag_len, diag_len, diag_len * 2)

    # Cache some resuable values
    cos_theta = np.cos(thetas)
    sin_theta = np.sin(thetas)
    num_thetas = len(thetas)

    # Hough accumulator array of theta vs rho
    accumulator = np.zeros((2 * diag_len, num_thetas))
    are_edges = img > value_threshold if lines_are_white else img < value_threshold
    #are_edges = cv2.Canny(img,50,150,apertureSize = 3)
    y_idxs, x_idxs = np.nonzero(are_edges)  # (row, col) indexes to edges
    # Vote in the hough accumulator
    xcosthetas = np.dot(x_idxs.reshape((-1,1)), cos_theta.reshape((1,-1)))
    ysinthetas = np.dot(y_idxs.reshape((-1,1)), sin_theta.reshape((1,-1)))
    rhosmat = np.round(xcosthetas + ysinthetas) + diag_len
    rhosmat = rhosmat.astype(np.int16)
    for i in range(num_thetas):
        rhos, counts = np.unique(rhosmat[:,i], return_counts=True)
        accumulator[rhos,i] = counts
    return accumulator, thetas, rhos1, np.arange(0,2 * diag_len)

def hough_peaks(H, num_peaks, thetas, rhos):
    H_values_sorted = np.sort(np.unique(H))[::-1]
    H_values_num_peaks = H_values_sorted[:num_peaks]
    peaks = []
    for pi in H_values_num_peaks:
        indexes = np.argwhere(H == pi)
        for find_indexes in indexes:
            rho = rhos[find_indexes[0]]
            theta = thetas[find_indexes[1]]
            peaks.append([rho, theta])
    return np.array(peaks[0:num_peaks])

def peak_votes(accumulator, thetas, rhos):
    """ Finds the max number of votes in the hough accumulator """
    idx = np.argmax(accumulator)
    rho = rhos[int(idx / accumulator.shape[1])]
    theta = thetas[idx % accumulator.shape[1]]
    return idx, theta, rho

def hough_lines_draw(image, peaks, rhos1):
    x = np.arange(0, image.shape[0]-1)
    H = np.zeros(image.shape)
    for i in range(peaks.shape[0]):
        d = rhos1[int(peaks[i, 0])]
        theta = peaks[i, 1]
        y = ((d - x*np.cos(theta))/np.sin(theta)).astype(int)
        index = np.where(y<=image.shape[1]-1)[0]
        y1 = y[index]
        x1 = x[index]
        index1 = np.where(y1>=0)[0]
        y2 = y1[index1]
        x2 = x1[index1]
        H[x2, y2] = 1
    return H

def show_hough_line(img, accumulator, lines_images, peaks, thetas, rhos, rhos1, save_path=None):
    import matplotlib.pyplot as plt

    fig, ax = plt.subplots(1, 2, figsize=(10, 10))

    ax[0].imshow(img+lines_images, cmap=plt.cm.gray)
    ax[0].set_title('Input image')
    ax[0].axis('image')

    ax[1].imshow(accumulator, cmap='jet',
                   extent=[np.rad2deg(thetas[0]), np.rad2deg(thetas[-1]), rhos1[-1], rhos1[0]])
    for ii in range(len(peaks[:, 0])):
        ax[1].scatter(np.rad2deg(peaks[ii,1]), rhos1[int(peaks[ii, 0])], color='r')
    ax[1].set_aspect('equal', adjustable='box')
    ax[1].set_title('Hough transform')
    ax[1].set_xlabel('Angles (degrees)')
    ax[1].set_ylabel('Distance (pixels)')
    ax[1].axis('image')
    if save_path is not None:
        plt.savefig(save_path, bbox_inches='tight')
    plt.show()

def ComputeGnomon_2(TwiceTheta_Chi, CenterProjection=(45 * DEG, 0 * DEG)):
    data_theta = TwiceTheta_Chi[0] / 2.0
    data_chi = TwiceTheta_Chi[1]
    lat = np.arcsin(np.cos(data_theta * DEG) * np.cos(data_chi * DEG))  # in rads
    longit = np.arctan(
        -np.sin(data_chi * DEG) / np.tan(data_theta * DEG))  # + ones(len(data_chi))*(np.pi)
    centerlat, centerlongit = CenterProjection
    slat0 = np.ones(len(data_chi)) * np.sin(centerlat)
    clat0 = np.ones(len(data_chi)) * np.cos(centerlat)
    longit0 = np.ones(len(data_chi)) * centerlongit
    slat = np.sin(lat)
    clat = np.cos(lat)
    cosanguldist = slat * slat0 + clat * clat0 * np.cos(longit - longit0)
    _gnomonx = clat * np.sin(longit0 - longit) / cosanguldist
    _gnomony = (slat * clat0 - clat * slat0 * np.cos(longit - longit0)) / cosanguldist
    return _gnomonx, _gnomony

def computeGnomonicImage(TwiceTheta,Chi):
    # CenterProjectionAngleTheta = 50#45
    TwiceTheta_Chi = TwiceTheta,Chi
    Xgno,Ygno = ComputeGnomon_2(TwiceTheta_Chi, CenterProjection=(45 * DEG, 0 * DEG))
    pts =(np.array([Xgno,Ygno]).T)
    nbpeaks=len(pts)
    NbptsGno = 300
    maxsize = max(Xgno.max(),Ygno.max(),-Xgno.min(),-Ygno.min())+.0
    xgnomin,xgnomax,ygnomin,ygnomax=(-0.8,0.8,-0.5,0.5)
    xgnomin,xgnomax,ygnomin,ygnomax=(-maxsize,maxsize,-maxsize,maxsize)

    halfdiagonal = np.sqrt(xgnomax**2+ygnomax**2)*NbptsGno
    XGNO = np.array((Xgno-xgnomin)/(xgnomax-xgnomin)*NbptsGno, dtype=int)
    YGNO = np.array((Ygno-ygnomin)/(ygnomax-ygnomin)*NbptsGno, dtype=int)
    imageGNO=np.zeros((NbptsGno+1,NbptsGno+1), dtype=int)
    imageGNO[XGNO,YGNO]=1
    return imageGNO, nbpeaks, halfdiagonal

def InverseGnomon(_gnomonX, _gnomonY):
    """ from x,y in gnomonic projection gives lat and long
    return theta and chi of Q (direction of Q)

    WARNING: assume that center of projection is centerlat, centerlongit = 45 deg, 0
    """
    lat0 = np.ones(len(_gnomonX)) * np.pi / 4
    longit0 = np.zeros(len(_gnomonX))
    Rho = np.sqrt(_gnomonX ** 2 + _gnomonY ** 2) * 1.0
    CC = np.arctan(Rho)

    # the sign should be - !!
    lalat = np.arcsin(np.cos(CC) * np.sin(lat0) + _gnomonY / Rho * np.sin(CC) * np.cos(lat0))
    lonlongit = longit0 + np.arctan2(_gnomonX * np.sin(CC),
        Rho * np.cos(lat0) * np.cos(CC) - _gnomonY * np.sin(lat0) * np.sin(CC))

    Theta = np.arcsin(np.cos(lalat) * np.cos(lonlongit))
    Chi = np.arctan(np.sin(lonlongit) / np.tan(lalat))

    return 2.*np.rad2deg(Theta), np.rad2deg(Chi)

if __name__ == '__main__':
    # ### or load directly the peaks from cor file
    # import LaueTools.IOLaueTools as IOLT
    # filename_ = r"C:\Users\purushot\Desktop\github_version_simple\lauetoolsnn\misc\img\HS261120b_SH2_S5_B_0000.cor"
    # data_theta, data_chi = IOLT.readfile_cor(filename_)[1:3]
    # l_tth = data_theta * 2.
    # l_chi = data_chi
    # img, _, _ = computeGnomonicImage(l_tth, l_chi)

    import matplotlib.pyplot as plt
    from LaueTools import imageprocessing as ImProc
    import LaueTools.dict_LaueTools as dictLT
    import LaueTools.LaueGeometry as Lgeo

    imgpath = 'img/HS261120b_SH2_S5_B_0000.tif'
    img = imageio.imread(imgpath)
    if img.ndim == 3:
        img = rgb2gray(img)

    backgroundimage = ImProc.compute_autobackground_image(img, boxsizefilter=10)
    img = ImProc.computefilteredimage(img, backgroundimage, "sCMOS", usemask=False,
                                                        formulaexpression="A-1.1*B")
    img = canny(img, )
    img = img.astype(int)

    # img2 = np.copy(img)
    # img2[img2==0] = 1000
    # plt.imshow(img2, cmap='gray')

    XX,YY = np.meshgrid(np.arange(img.shape[1]),np.arange(img.shape[0]))
    table = np.vstack((img.ravel(),XX.ravel(),YY.ravel())).T
    ## remove zero values pixels from peak
    keep_ind = np.where(table[:,0]!=0)[0]
    table = np.take(table, keep_ind, axis=0)

    peak_XY = table[:,1:]
    twicetheta, chi = Lgeo.calc_uflab(peak_XY[:,0], peak_XY[:,1], [79.554,979.45,932.54,0.387,0.44],
                                        returnAngles=1,
                                        pixelsize=dictLT.dict_CCD["sCMOS"][1],
                                        kf_direction='Z>0')

    ## check Gnomonic function
    TwiceTheta_Chi = twicetheta, chi
    Xgno,Ygno = ComputeGnomon_2(TwiceTheta_Chi, CenterProjection=(45 * DEG, 0 * DEG))
    twicetheta_back, chi_back = InverseGnomon(Xgno,Ygno)

    assert np.all(np.round(chi_back,4)==np.round(chi,4))
    assert np.all(np.round(twicetheta_back,4)==np.round(twicetheta,4))

    imgGN, _, _ = computeGnomonicImage(twicetheta, chi)

    fig, ax = plt.subplots()
    plt.imshow(imgGN,cmap='gray')
    plt.savefig("prefix.png", bbox_inches='tight',format='png', dpi=1000)

    accumulator, thetas, rhos1, rhos = fast_hough_line(imgGN, angle_step=1,
                                                       lines_are_white=True, value_threshold=0.1)
    peaks = hough_peaks(accumulator, 20, thetas, rhos)
    lines_images = hough_lines_draw(imgGN, peaks, rhos1)

    show_hough_line(imgGN, accumulator, lines_images, peaks, thetas, rhos, rhos1, save_path=None)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Dec  2 15:37:10 2020

Copyright 2020 by Hadrien Montanelli.
"""
# %% Imports.

# Standard library imports:
from math import pi
import matplotlib.pyplot as plt
import numpy as np
import time

# Chebpy imports:
from chebpy.trig import coeffs2vals, diffmat, trigpts, vals2coeffs

# %% First-order differentiation on [-pi, pi].

# Function:
w = 100
f = lambda x: np.cos(w*x)
dfex = lambda x: -w*np.sin(w*x)

# Grid:
n = 4*w
dom = [-pi, pi]
x = trigpts(n, dom)

# Compute coeffs of f:
F = vals2coeffs(f(x))

# Differentiation matrix in coefficient space:
start = time.time()
D = diffmat(n, 1, dom)
end = time.time()
print(f'Time   (setup): {end-start:.5f}s')
plt.figure()
plt.spy(D)

# Differentiate:
start = time.time()
DF = D @ F
end = time.time()
print(f'Time (product): {end-start:.5f}s')

# Convert to value space:
df = coeffs2vals(DF)

# Error:
error = np.max(np.abs(df - dfex(x)))/np.max(np.abs(dfex(x)))
print(f'Error  (L-inf): {error:.2e}')

# %% Second-order differentiation on [-pi, pi].

# Function:
w = 100
f = lambda x: np.cos(w*x)
d2fex = lambda x: -w**2*np.cos(w*x)

# Grid:
n = 4*w
dom = [-pi, pi]
x = trigpts(n, dom)

# Compute coeffs of f:
F = vals2coeffs(f(x))

# Differentiation matrix in coefficient space:
start = time.time()
D2 = diffmat(n, 2, dom)
end = time.time()
print(f'Time   (setup): {end-start:.5f}s')
plt.figure()
plt.spy(D)

# Differentiate:
start = time.time()
D2F = D2 @ F
end = time.time()
print(f'Time (product): {end-start:.5f}s')

# Convert to value space:
d2f = coeffs2vals(D2F)

# Error:
error = np.max(np.abs(d2f - d2fex(x)))/np.max(np.abs(d2fex(x)))
print(f'Error  (L-inf): {error:.2e}')


"""
Math utility functions based on lectures from Prof. Daniel Cremers' Multiple View Geometry course.
"""
import math
import numpy as np
import sympy

def radians(angleDegrees):
    return angleDegrees / 180.0 * np.pi

def rotationMatrixToEuler(R):
    """
    Compute the Euler angles from a rotation matrix

    http://eecs.qmul.ac.uk/~gslabaugh/publications/euler.pdf
    """
    R11, R12, R13, R21, R22, R23, R31, R32, R33 = R.ravel()
    if not (np.isclose(R31, +1) or np.isclose(R31, -1)):
        θ = -np.arcsin(R31)
        ψ = np.arctan2(R32/np.cos(θ), R33/np.cos(θ))
        ϕ = np.arctan2(R21/np.cos(θ), R11/np.cos(θ))
    else:
        ϕ = 0
        if np.isclose(R31, -1):
            θ = np.pi/2
            ψ = ϕ + np.arctan2(R12, R13)
        else:
            θ = -np.pi/2
            ψ = -ϕ + np.arctan2(-R12, -R13)

    return tuple(np.degrees((ψ, θ, ϕ)))

def eulerToRotationMatrix(rXrYrZDegrees, isSymbolic=False):
    rx, ry, rz = rXrYrZDegrees
    wx = col((1, 0, 0))
    wy = col((0, 1, 0))
    wz = col((0, 0, 1))

    if isSymbolic:
        Rx = exp(radians(rx) * skew(wx), isSymbolic=isSymbolic)
        Ry = exp(radians(ry) * skew(wy), isSymbolic=isSymbolic)
        Rz = exp(radians(rz) * skew(wz), isSymbolic=isSymbolic)
    else:
        Rx = exp(np.radians(rx) * skew(wx))
        Ry = exp(np.radians(ry) * skew(wy))
        Rz = exp(np.radians(rz) * skew(wz))
    R = Rz @ Ry @ Rx
    return R

def col(v):
    # create a column vector out of a list / tuple
    return np.array(v).reshape(-1, 1)

def exp(wHat: np.ndarray, isSymbolic=False):
    # exponential mapping of a skew symmetric matrix so(3) onto
    #   the rotation matrix group SO(3), uses Rodrigues' formula
    w = unskew(wHat)
    if isSymbolic:
        wNorm = sympy.sqrt(w[0]**2 + w[1]**2 + w[2]**2)
        I = np.eye(3)
        term1 = (wHat / wNorm) * sympy.sin(wNorm)
        term2 = ((wHat @ wHat) / (wNorm**2)) * (1 - sympy.cos(wNorm))
    else:
        wNorm = np.linalg.norm(w)

        I = np.eye(3)
        if np.isclose(wNorm, 0):
            term1 = 0
        else:
            term1 = (wHat / wNorm) * np.sin(wNorm)
        if np.isclose(wNorm, 0):
            term2 = 0
        else:
            term2 = ((wHat @ wHat) / (wNorm**2)) * (1 - np.cos(wNorm))
    R = I + term1 + term2
    return R

def skew(v):
    # converts vector into a skew symmetric matrix, aka 'hat' operator
    # only works for v of shape (3,1)
    validateShape(v.shape, (3,1))
    a = v[:,0]
    vHat = np.array([
        [    0, -a[2],  a[1]],
        [ a[2],     0, -a[0]],
        [-a[1],  a[0],     0],
    ])
    return vHat

def unskew(vHat):
    validateShape(vHat.shape, (3,3))
    return np.array([vHat[2,1], vHat[0,2], vHat[1,0]])

def validateShape(inputShape, requiredShape):
    for i in range(len(inputShape)):
        if requiredShape[i] is not None and requiredShape[i] != inputShape[i]:
            raise ValueError(f"Expected shape {requiredShape}, got {inputShape}")

def stack(A):
    # stacks the columns of a matrix into a single column
    return col(A.T.ravel())

def unstack(As):
    # unstacks the column vector into a squre matrix
    Nsquared = As.size
    N = int(np.sqrt(Nsquared))
    return As.reshape((N, N)).T

def hom(v):
    if isinstance(v, tuple) or isinstance(v, list):
        v = np.array(v).reshape(-1, len(v))
    elif len(v.shape) == 1:
        return np.append(v, 1)
    # v is Nx2 or Nx3
    vh = np.hstack((v, np.ones((v.shape[0], 1))))
    return vh

def unhom(vHom):
    if len(vHom.shape) == 1:
        v = vHom[:-1] / vHom[-1]
    elif len(vHom.shape) == 2:
        v = vHom[:,:-1] / col(vHom[:,-1])
    else:
        raise ValueError(f"Unexpected input shape for unhom: {vHom.shape}\n{vHom}")
    return v

def normalize(A):
    return A / A.ravel()[-1]

def poseFromRT(R, T):
    world_M_camera = np.eye(4)
    world_M_camera[:3,:3] = R
    if isinstance(T, np.ndarray):
        T = T.ravel()
    world_M_camera[:3,3] = T
    return world_M_camera

def project(A, wMc, wX):
    """
    Inputs:
        A   -- the intrinsic parameter matrix
        wMc -- the camera pose in world
        wX  -- the 3D points in the world

    Outputs:
        xp  -- x' the projected 2D points in the camera
    """
    validateShape(A.shape, (3,3))
    validateShape(wMc.shape, (4,4))
    validateShape(wX.shape, (None,3))

    cMw = np.linalg.inv(wMc)
    X = transform(cMw, wX)
    x = projectStandard(X)
    u = unhom((A @ hom(x).T).T)
    return u

def projectStandard(X):
    """
    Inputs:
        X -- Nx3 points in camera coordinates

    Outputs:
        x -- Nx2 normalized projected 2D points

    Π0            -- standard projection matrix
    """
    validateShape(X.shape, (None,3))

    Π0 = np.array([
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
    ])
    x = unhom((Π0 @ hom(X).T).T)
    return x

def transform(b_M_a, aX):
    """
    Inputs:
        b_M_a -- rigid body transform from coordinates of a to b
        aX -- matrix of Nx3 points in coordinates of a

    Outputs:
        bX -- matrix of Nx3 points in coordinates of b
    """
    validateShape(b_M_a.shape, (4,4))
    validateShape(aX.shape, (None,3))

    bX = unhom((b_M_a @ hom(aX).T).T)
    return bX


# -*- coding: utf-8 -*-
"""
Created on Mon Apr  1 23:29:47 2019

@author:    manma
@project:   Mathematics for Machine Learning.
@purpose:   Week 1 PCA programming assignment
"""
import numpy as np

# GRADED FUNCTION: DO NOT EDIT THIS LINE
def mean_naive(X):
    "Compute the mean for a dataset X nby iterating over the data points"
    # X is of size (D,N) where D is the dimensionality
    # and N the number of data points
    D, N = X.shape
    mean = np.zeros((D, 1))
    # Edit the code; iterate over the dataset and compute the mean vector.
    for d in range(D):
        mean[d] = sum(X[d, :]) / N
    return mean

def cov_naive(X):
    """Compute the covariance for a dataset of size (D,N)
    where D is the dimension and N is the number of data points"""
    D, N = X.shape
    # Edit the code below to compute the covariance matrix
    # by iterating over the dataset.
    covariance = np.zeros((D, D))
    # Update covariance
    for d in range(D):
        d_mean = sum(X[d, :]) / N
        d_diffs = [x - d_mean for x in X[d, :]]
        for j in range(D):
            j_mean = sum(X[j, :]) / N
            j_diffs = [x - j_mean for x in X[j, :]]
            prods = [a * b for (a, b) in zip(d_diffs, j_diffs)]
            cov_dj = sum(prods) / N
            covariance[d, j] = cov_dj
    return covariance

def mean(X):
    """
    Compute the mean for a dataset of size (D,N) where D is the dimension
    and N is the number of data points
    """
    # given a dataset of size (D, N), the mean should be an array of size (D,1)
    # you can use np.mean, but pay close attention to the
    # shape of the mean vector you are returning.
    D, N = X.shape
    # Edit the code to compute a (D,1) array `mean` for the mean of dataset.
    mean = X.mean(axis=1).reshape(D, 1)
    return mean

def cov(X):
    """
    Compute the covariance for a dataset
    """
    # X is of size (D,N)
    # It is possible to vectorize our code for computing the
    # covariance with matrix multiplications,
    # i.e., we do not need to explicitly
    # iterate over the entire dataset as looping in Python tends to be slow
    # We challenge you to give a vectorized implementation without
    # using np.cov, but if you choose to use np.cov,
    # be sure to pass in bias=True.
    D, N = X.shape
    # Edit the code to compute the covariance matrix
    covariance_matrix = np.zeros((D, D))
    mean = X.mean(axis=1).reshape(D, 1)
    U = X - mean
    covariance_matrix = U @ U.T / N
    return covariance_matrix

# GRADED FUNCTION: DO NOT EDIT THIS LINE
def affine_mean(mean, A, b):
    """Compute the mean after affine transformation
    Args:
        x: ndarray, the mean vector
        A, b: affine transformation applied to x
    Returns:
        mean vector after affine transformation
    """
    # Edit the code below to compute the mean vector after
    # affine transformation
    affine_m = np.zeros(mean.shape)  # affine_m has shape (D, 1)
    affine_m = (A @ mean) + b
    return affine_m

def affine_covariance(S, A, b):
    """Compute the covariance matrix after affine transformation
    Args:
        S: ndarray, the covariance matrix
        A, b: affine transformation applied to each element in X
    Returns:
        covariance matrix after the transformation
    """
    # EDIT the code below to compute the covariance matrix
    # after affine transformation
    affine_cov = np.zeros(S.shape)  # affine_cov has shape (D, D)
    affine_cov = A @ S @ A.T
    return affine_cov


import math
import numpy as np

class CSimulation(object):
    option_type_b = {
        'Call': True,
        'Put': False
    }

    step = 0.10
    n = 20000

    s0 = 50
    k = 50
    r = 0.05
    sigma = 0.3
    t = 0.5
    is_call = True

    def __init__(self):
        self.eps = np.random.standard_normal(self.n)
        self.stock_prices = []
        self.option_payoffs = []
        self.gamma = []

    def run(self):
        for i in range(self.n):
            sp = self.s0 * math.exp((self.r - self.sigma**2/2)*self.t + self.sigma*math.sqrt(self.t)*self.eps[i])
            if self.is_call:
                op = math.exp(-self.r*self.t)*max(sp - self.k, 0)
            else:
                op = math.exp(-self.r * self.t) * max(self.k - sp, 0)

            sp1 = sp + self.step
            if self.is_call:
                op1 = math.exp(-self.r*self.t)*max(sp1 - self.k, 0)
            else:
                op1 = math.exp(-self.r*self.t)*max(self.k - sp1, 0)

            g = (op1 - op)/self.step

            self.stock_prices.append(sp)
            self.option_payoffs.append(op)
            self.gamma.append(g)

    def process_results(self):
        pf = np.array(self.option_payoffs)
        self.pf_mean = pf.mean()
        self.pf_std = pf.std()

        gm = np.array(self.gamma)
        self.gm_mean = gm.mean()
        self.gm_std = gm.std()


import pandas as pd
import numpy as np
from scipy.optimize import minimize

df = pd.read_excel('Seasonality.xlsx')
# drops the extra title row
df.drop(df.index[0], axis=0, inplace=True)
# resets the index to start at 0. Could probably just make the datetime the index if you wanted.
df.reset_index(inplace=True, drop=True)

# supply an initial value to alpha
alpha = 0.3

# pulls the actual values into a numpy array
array_of_actual_values = df.Seasonally.values

def full_algorithim(alpha, init_data):
    # values predicted using the single-equation recursive form of Brown’s model
    y = np.empty(len(init_data), float)
    # error values (actual - predicted)
    z = np.empty(len(init_data), float)

    for i in range(0, len(init_data)):
        # sets the first two values in predicted to be the first value in actual
        if i < 2:
            y[i] = init_data[0]
        else:
            y[i] = 2 * init_data[i - 1] - init_data[i - 2] - 2 * (1 - alpha) * z[i - 1] + ((1 - alpha) ** 2) * z[i - 2]

        z[i] = init_data[i] - y[i]

    return np.sqrt(np.mean(np.square(z)))

result = minimize(full_algorithim, alpha, array_of_actual_values, bounds=[(0, 1)])

# there's a tiny amount of variation in the optimal value based on the initial value for alpha
[alpha_optimized] = result.x
print(alpha_optimized)

def algebraic_transformation(df_original, column_name_actual, column_name_predicted, column_name_errors, alpha_opt):
    df_new = df_original

    for i in range(0, len(df_new)):
        if i < 2:
            # sets the first two values in Forecast to be the first value in Seasonally
            df_new.loc[i, column_name_predicted] = df_new.loc[0, column_name_actual]
        else:
            df_new.loc[i, column_name_predicted] = \
                2 * df_new.loc[i - 1, column_name_actual] - df_new.loc[i - 2, column_name_actual] - 2 * (1 - alpha_opt) * df_new.loc[i - 1, column_name_errors] + ((1 - alpha_opt) ** 2 * df_new.loc[i - 2, column_name_errors])

        # calculates the error, y_actual - y_predicted
        df_new.loc[i, column_name_errors] = df_new.loc[i, column_name_actual] - df_new.loc[i, column_name_predicted]

    return df_new

df_changed = algebraic_transformation(df, 'Seasonally', 'Forecast', 'Error', alpha_optimized)

RMSE = np.sqrt(np.mean(np.square(df_changed.Error)))
print(RMSE)

# removes time from date column
df_changed.Date = pd.to_datetime(df.Date).dt.date

with pd.ExcelWriter('Seasonality-with-Forecast-Errors.xlsx', engine='openpyxl', mode='w') as writer:
    df_changed.to_excel(writer, index=False)


# Takes the variables in 'list' and computes a linear fit to
# the data. The function returns the gradient of the fit, as
# well as the residual.

import numpy as np
from scipy import polyfit

def linearRegression( list ) :
    x = np.linspace(1,len(list),len(list))
    # Fit the data to y = mx + c
    linearModel = polyfit( x, list, 1, full=True)
    m = linearModel[0][0]
    res = linearModel[1]
    return m, res


import sympy
import math
x = sympy.Symbol('x')
xn =[2,2.1,2.2,2.3,2.4,2.5]
fxn =[-11.8646,-12.4775,-13.0891,-13.6997,-14.3092,-14.9179]
derivs = []
h = xn[1]-xn[0]

function = -0.666666666662422*x**5 + 7.49999999976717*x**4 - 33.7166666650446*x**3 + 75.7649999978021*x**2 - 91.2657666662708*x + 38.6735999999801
#function =  (math.e**-x)-6*x
def eval(valor):
    return (function.evalf().subs({x:valor}))

def dosPuntos(x0, fx0):
    derivs.append((eval(x0+h)-fx0)/h)

def tresPuntos(x0, fx0):
    derivs.append((x0,(eval(x0+h)-eval(x0-h))/(2*h)))

def cincoPuntos(x0, fx0):
    derivs.append((eval(x0-2*h)-8*eval(x0-h)+8*eval(x0+h)-eval(x0+2*h))/(12*h))

for i in range(0,len(xn)):
    cincoPuntos(xn[i],fxn[i])
for i in derivs:
    print(i)


import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import numpy as np

def tsne_viz(mat, rownames, use_pca=True, learning_rate=1000, n_iter=1000,colors=None, output_filename=None, figheight=40, figwidth=50):
    """2d plot of `mat` using t-SNE, with the points labeled by `rownames`,
        aligned with `colors` (defaults to all black).

        Parameters
        ----------
        mat : 2d np.array
            The matrix to visualize.
        rownames : list of str
            Names of the points to visualize.
        use_pca : A Boolean flag,
            If True PCA will be used to reduce dimensions to 50.
        learning_rate : integer value
            Default is 1000, varies between 100 to 1000.
        n_iter : integer
            Maximum number of iteration for optimizations.
        colors : list of colornames or None (default: None)
            Optional list of colors for rownames. The color names just need to
            be interpretable by matplotlib. If they are supplied, they need to
            have the same length as rownames, or indices if that is not None.
            If `colors=None`, then all the words are displayed in black.
        output_filename : str (default: None)
            If not None, then the output image is written to this location. The
            filename suffix determines the image type. If None, then
            `plt.plot()` is called, with the behavior determined by the
            environment.
        figheight : int (default: 40)
            Height in display units of the output.
        figwidth : int (default: 50)
            Width in display units of the output.
    """
    indices = list(range(len(rownames)))
    # Colors:
    if not colors:
        colors = ['black' for i in indices]
    # Recommended reduction via PCA or similar:
    if use_pca:
        n_components = 50 if mat.shape[1] >= 50 else mat.shape[1]
        dimreduce = PCA(n_components=n_components)
        mat = dimreduce.fit_transform(mat)
    # t-SNE:
    tsne = TSNE(n_components=2, learning_rate=learning_rate, random_state=0, n_iter=n_iter)
    np.set_printoptions(suppress=True)
    tsnemat = tsne.fit_transform(mat)
    # Plot values:
    vocab = np.array(rownames)[indices]
    xvals = tsnemat[indices, 0]
    yvals = tsnemat[indices, 1]
    # Plotting:
    fig, ax = plt.subplots(nrows=1, ncols=1)
    fig.set_figheight(40)
    fig.set_figwidth(50)
    ax.plot(xvals, yvals, marker='', linestyle='')
    # Text labels:
    for word, x, y, color in zip(vocab, xvals, yvals, colors):
        ax.annotate(word, (x, y), fontsize=8, color=color)
    # Output:
    if output_filename:
        plt.savefig(output_filename, bbox_inches='tight')
    else:
        plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 26 10:59:15 2021

@author: yashlad
"""

'''NumpPy coding'''

import numpy as np

nump_array=np.array([[1,2,3],[4,5,6]])

np1=np.array([[7,9],[10,3]])

np2 = np.array([[4,5],[1,3]])

"""numpy array muktiplication"""

mnp1 = np1 @ np2  # muliplying two arrays

# above was row-column multiplication

mnp2 = np1 * np2  # multiplying each element of array

mnp3 = np.dot(np1,np2)  # similar to @ sign

mnp4 = np.multiply(np1,np2)  #similar to * sign

'''addition and subtraction in numpy of array'''

sum1 = np1 + np2

sub1 = np1 - np2

# now using different classes in numpy

sub2 = np.subtract(np1,np2)

np.sum(np1)

broad_nump = np1 + 3   # adding 3 to each element in array

np3 = np.array([[3,4]])

np1 + np3

'''divison'''

D = np.divide([12,40,15], 5)

'or'

d = np.floor_divide([12, 33, 55], 6)

sq = np.math.sqrt(121)

nd = np.random.standard_normal((3,4))

random_array = np.random.randint(1, 50, (2,5))

ze = np.zeros((3,4))

one = np.ones((3,4))

filter_Ar = np.logical_and(random_array>30, random_array<50)
F_Random_Ar = random_array[filter_Ar]


import numpy as np
np.set_printoptions(threshold=3)
np.set_printoptions(suppress=True)
from numpy import genfromtxt

#Notation used coming from: https://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/

def prediction(X_hat_t_1,P_t_1,F_t,B_t,U_t,Q_t):
    X_hat_t=F_t.dot(X_hat_t_1)+(B_t.dot(U_t).reshape(B_t.shape[0],-1) )
    P_t=np.diag(np.diag(F_t.dot(P_t_1).dot(F_t.transpose())))+Q_t
    return X_hat_t,P_t

def update(X_hat_t,P_t,Z_t,R_t,H_t):

    K_prime=P_t.dot(H_t.transpose()).dot( np.linalg.inv ( H_t.dot(P_t).dot(H_t.transpose()) +R_t ) )
    print("K:\n",K_prime)

    X_t=X_hat_t+K_prime.dot(Z_t-H_t.dot(X_hat_t))
    P_t=P_t-K_prime.dot(H_t).dot(P_t)

    return X_t,P_t

acceleration=0
delta_t=1/20#milisecond

groundTruth = genfromtxt('data/groundTruth.csv', delimiter=',',skip_header=1)

#Observations: position_X, position_Y
measurmens = genfromtxt('data/measurmens.csv', delimiter=',',skip_header=1)

#Checking our result with OpenCV
opencvKalmanOutput = genfromtxt('data/kalmanv.csv', delimiter=',',skip_header=1)

#Transition matrix
F_t=np.array([ [1 ,0,delta_t,0] , [0,1,0,delta_t] , [0,0,1,0] , [0,0,0,1] ])

#Initial State cov
P_t= np.identity(4)*0.2

#Process cov
Q_t= np.identity(4)

#Control matrix
B_t=np.array( [ [0] , [0], [0] , [0] ])

#Control vector
U_t=acceleration

#Measurment Matrix
H_t = np.array([ [1, 0, 0, 0], [ 0, 1, 0, 0]])

#Measurment cov
R_t= np.identity(2)*5

# Initial State
X_hat_t = np.array( [[0],[0],[0],[0]] )
print("X_hat_t",X_hat_t.shape)
print("P_t",P_t.shape)
print("F_t",F_t.shape)
print("B_t",B_t.shape)
print("Q_t",Q_t.shape)
print("R_t",R_t.shape)
print("H_t",H_t.shape)

for i in range(measurmens.shape[0]):
    X_hat_t,P_hat_t = prediction(X_hat_t,P_t,F_t,B_t,U_t,Q_t)
    print("Prediction:")
    print("X_hat_t:\n",X_hat_t,"\nP_t:\n",P_t)

    Z_t=measurmens[i].transpose()
    Z_t=Z_t.reshape(Z_t.shape[0],-1)

    print(Z_t.shape)

    X_t,P_t=update(X_hat_t,P_hat_t,Z_t,R_t,H_t)
    print("Update:")
    print("X_t:\n",X_t,"\nP_t:\n",P_t)
    X_hat_t=X_t
    P_hat_t=P_t

    print("=========================================")
    print("Opencv Kalman Output:")
    print("X_t:\n",opencvKalmanOutput[i])


import matplotlib.pyplot as plt
import numpy as np
import cv2
import math as mt

#Constants
colors = ('b' , 'g' ,'r')

#Implementation
src = cv2.imread('images/imagenpdi1.jpg')

hist1 = cv2.calcHist([src],[0],None,[256],[0,256])
hist2 = cv2.calcHist([src],[1],None,[256],[0,256])
hist3 = cv2.calcHist([src],[2],None,[256],[0,256])

fig_size = plt.rcParams["figure.figsize"]
fig_size[0] = 12
fig_size[1] = 9

srcRgb = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)

plt.subplot(221)
plt.imshow(srcRgb)
plt.title('Imagen Original')
plt.ylabel('Vertical pixels')
plt.xlabel('Horizontal pixels')
plt.subplot(222)
plt.plot(hist1, color = colors[0])
plt.title('Histograma Azul')
plt.ylabel('Number of pixels')
plt.xlabel('Intensity')
plt.subplot(223)
plt.plot(hist2, color = colors[1])
plt.title('Histograma Verde')
plt.ylabel('Number of pixels')
plt.xlabel('Intensity')
plt.subplot(224)
plt.plot(hist3, color = colors[2])
plt.title('Histograma Rojo')
plt.ylabel('Number of pixels')
plt.xlabel('Intensity')
plt.suptitle('Imagen inicial y sus histogramas', fontsize=16)

b, g, r = cv2.split(src)

b = np.array(b,dtype = int)
g = np.array(g,dtype = int)
r = np.array(r,dtype = int)

Cdf_acc = 0
for i in range(0,256,1):
    if (i == 0):
        Cdf_acc += int(hist1[i])
        Cdf1 = [Cdf_acc]
    else:
        Cdf_acc += int(hist1[i])
        Cdf1.append(Cdf_acc)
maxcdf = max(Cdf1)
Cdf1[:] = [x/maxcdf for x in Cdf1]

Cdf_acc = 0
for i in range(0,256,1):
    if (i == 0):
        Cdf_acc += int(hist2[i])
        Cdf2 = [Cdf_acc]
    else:
        Cdf_acc += int(hist2[i])
        Cdf2.append(Cdf_acc)
maxcdf = max(Cdf2)
Cdf2[:] = [x/maxcdf for x in Cdf2]

Cdf_acc = 0
for i in range(0,256,1):
    if (i == 0):
        Cdf_acc += int(hist3[i])
        Cdf3 = [Cdf_acc]
    else:
        Cdf_acc += int(hist3[i])
        Cdf3.append(Cdf_acc)
maxcdf = max(Cdf3)
Cdf3[:] = [x/maxcdf for x in Cdf3]

plt.figure()
plt.subplot(221)
plt.plot(Cdf1, color = colors[0])
plt.title('CDF normalizada del canal B')
plt.ylabel('Valor de la CDF')
plt.xlabel('Intensidad del pixel')
plt.subplot(222)
plt.plot(Cdf2, color = colors[1])
plt.title('CDF normalizada del canal G')
plt.ylabel('Valor de la CDF')
plt.xlabel('Intensidad del pixel')
plt.subplot(223)
plt.plot(Cdf3, color = colors[2])
plt.title('CDF normalizada del canal R')
plt.ylabel('Valor de la CDF')
plt.xlabel('Intensidad del pixel')
plt.suptitle('CDF de cada canal', fontsize=16)

width,height,depth = src.shape

for i in range(0,width,1):
    for j in range(0,height,1):
        if Cdf1[b[i,j]]==1:
            b[i,j] = 255
        else:
            b[i,j] = mt.sqrt(2*(70**2)*mt.log(1/(1-Cdf1[b[i,j]])))
            if b[i,j] < 0:
                b[i,j] = 0
            elif b[i,j] > 255:
                b[i,j] = 255
        if Cdf2[g[i,j]]==1:
            g[i,j] = 255
        else:
            g[i,j] = mt.sqrt(2*(70**2)*mt.log(1/(1-Cdf2[g[i,j]])))
            if g[i,j] < 0:
                g[i,j] = 0
            elif g[i,j] > 255:
                g[i,j] = 255
        if Cdf3[r[i,j]]==1:
            r[i,j] = 255
        else:
            r[i,j] = mt.sqrt(2*(70**2)*mt.log(1/(1-Cdf3[r[i,j]])))
            if r[i,j] < 0:
                r[i,j] = 0
            elif r[i,j] > 255:
                r[i,j] = 255

b = np.array(b,dtype = np.uint8)
g = np.array(g,dtype = np.uint8)
r = np.array(r,dtype = np.uint8)

image_final = cv2.merge((b,g,r))
cv2.imwrite('images/proceso2.jpg', image_final)

hist1 = cv2.calcHist([image_final],[0],None,[256],[0,256])
hist2 = cv2.calcHist([image_final],[1],None,[256],[0,256])
hist3 = cv2.calcHist([image_final],[2],None,[256],[0,256])

image_finalRgb = cv2.cvtColor(image_final, cv2.COLOR_BGR2RGB)

plt.figure()
plt.subplot(221)
plt.imshow(image_finalRgb)
plt.title('Imagen Original')
plt.ylabel('Vertical pixels')
plt.xlabel('Horizontal pixels')
plt.subplot(222)
plt.plot(hist1, color = colors[0])
plt.title('Histograma Azul')
plt.ylabel('Number of pixels')
plt.xlabel('Intensity')
plt.subplot(223)
plt.plot(hist2, color = colors[1])
plt.title('Histograma Verde')
plt.ylabel('Number of pixels')
plt.xlabel('Intensity')
plt.subplot(224)
plt.plot(hist3, color = colors[2])
plt.title('Histograma Rojo')
plt.ylabel('Number of pixels')
plt.xlabel('Intensity')
plt.suptitle('Imagen final y sus histogramas', fontsize=16)

plt.show()


"""Hamiltonians for one-dimensional, single-species Bose gases."""

from math import sqrt

import numpy as np
from attr import dataclass
from numpy import pi

from gspits import ExternalPotential, Mesh, State

__all__ = ["HarmonicTrap"]

@dataclass(frozen=True)
class HarmonicTrap(ExternalPotential):
    """One-dimensional harmonic trap external potential.

    :param float freq:
        The trap angular frequency. It must be a non-zero, positive number.
        `NaNs` are not allowed.

    :raises ValueError: If the frequency is negative or zero.
    :raises ValueError: If the frequency is a ``nan``.
    """

    # Trap angular frequency.
    freq: float

    def __attrs_post_init__(self) -> None:
        """Post-initialization checks."""
        # Avoid NaNs.
        if np.isnan(self.freq):
            raise ValueError(
                "'nan' is not a valid value for the trap frequency ('freq')."
            )
        if not self.freq > 0:
            raise ValueError(
                "the frequency must have positive, non-zero values."
            )

        # Make transformations.
        object.__setattr__(self, "freq", float(self.freq))

    @property
    def size(self) -> float:
        """Characteristic size of the trap.

        :rtype: float
        """
        return sqrt(1 / self.freq)

    def gaussian_state(self, mesh: Mesh) -> State:
        """Build a normalized Gaussian state.

        :param Mesh mesh:
            A mesh where the state will be defined.
        :rtype: State
        """
        freq = self.freq
        (x_array,) = mesh.arrays
        wave_func = (freq / pi) ** 0.25 * np.exp(-freq * x_array ** 2 / 2)
        return State(mesh=mesh, wave_func=wave_func)

    def __call__(self, mesh: Mesh) -> np.ndarray:
        """External potential callable interface.

        :param mesh:
            A ``Mesh`` instance representing a domain mesh.
        :rtype: numpy.ndarray
        """
        freq = self.freq
        (x_array,) = mesh.arrays
        return 0.5 * (freq * x_array) ** 2


#sine wave generation function

import numpy as np

def generate_sine_wave_no(N, A, f0, fs, phi):

    '''
    generate sine wave with a given sample number
    N(int): no. of samples
    A(float): amplitude
    f0(float): frequency in Hz
    fs(flaot): sampling frequency in Hz
    phi(float): phase
    '''

    T = 1/fs
    n = np.arange(N)
    s = A*np.sin(2*np.pi*f0*n*T+phi)

    return s

def gaussian(N,FWHM,fd):
    '''

    :param N:
    :param f0:

    :return:
    '''

    temp = np.linspace(0,N,N)
    sigma = FWHM/2.354826

    g = (1 / (sigma * np.sqrt(2 * np.pi))) * np.exp(-(temp - fd) ** 2 / (2 * sigma) ** 2)
    g = g/g.max()

    return g

def numpy_SNR(reference_signal, target_signal):

    signal = np.sum(reference_signal ** 2)
    noise = np.sum((target_signal - reference_signal) ** 2)
    snr = 10 * np.log10(signal / noise)
    return snr


import numpy as np
import pandas as pd
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from scipy.spatial import procrustes
from scipy.linalg import orthogonal_procrustes

x = np.zeros((8, 8), dtype=int)
x[1::2, ::2] = 1
x[::2, 1::2] = 1

y = np.ones((8, 8), dtype=int)
y[1::2, ::2] = 0
y[::2, 1::2] = 0

fig, ax = plt.subplots()
i = ax.imshow(x, cmap=cm.gray, interpolation='none')
fig.colorbar(i)
plt.show()

mtx1, mtx2, mm = procrustes(x, y)

fig, ax = plt.subplots()
i = ax.imshow(y, cmap=cm.gray, interpolation='none')
fig.colorbar(i)
plt.show()

ts_one = np.tile(np.stack([x, y], axis=-1), 12)
ts_two = np.tile(np.stack([y, x], axis=-1), 12)

R, scale = orthogonal_procrustes(ts_one.reshape((64, 24)),
                                 ts_two.reshape((64, 24)))
fig, ax = plt.subplots()
i = ax.imshow(ts_one.reshape((64, 24)) @ R,
              cmap=cm.gray, interpolation='none')
fig.colorbar(i)
plt.show()

def rotate(p, origin=(0, 0), degrees=0):
    """
    Taken from: https://stackoverflow.com/a/58781388
    """
    angle = np.deg2rad(degrees)
    R = np.array([[np.cos(angle), -np.sin(angle)],
                  [np.sin(angle),  np.cos(angle)]])
    o = np.atleast_2d(origin)
    p = np.atleast_2d(p)
    return np.squeeze((R @ (p.T-o.T) + o.T).T)

source = pd.read_csv('data.csv')
jitter = np.random.normal(10, 3, (165, 2))
x_jitter, y_jitter = np.hsplit(jitter, 2)

target = pd.DataFrame({'x': source['x'] + x_jitter.flatten(),
                       'y': source['y'] + y_jitter.flatten()})

origin = (500, 500)
new_points = rotate(target.values, origin=origin, degrees=40)
target['x'], target['y'] = np.hsplit(new_points, 2)

plt.scatter(source['x'], source['y'])
plt.scatter(target['x'], target['y'])
plt.show()

tick_params = {'axis': 'both', 'which': 'both', 'bottom': False, 'top': False,
               'left': False, 'labelleft': False, 'labelbottom': False}

def _plot2D_samples_mat(xs, xt, R, thr=1e-8, **kwargs):
    """ Plot matrix R in 2D with lines for coefficients above threshold thr.
    REPRODUCED FROM POT PACKAGE
    """
    if ('color' not in kwargs) and ('c' not in kwargs):
        kwargs['color'] = 'k'
    mx = R.max()
    for i in range(xs.shape[0]):
        for j in range(xt.shape[0]):
            if R[i, j] / mx > thr:
                plt.plot([xs[i, 0], xt[j, 0]], [xs[i, 1], xt[j, 1]],
                         alpha=R[i, j] / mx, **kwargs)

def _plot_distributions_and_alignment(source, target, R=None, thr=.1, title=None, tick_params=tick_params):
    fig, ax = plt.subplots()
    plt.plot(source['x'], source['y'], 'og', label='Source samples')
    plt.plot(target['x'], target['y'], 'or', label='Target samples')
    plt.legend()

    if R is not None:
        # if R has some negative coeffs, plot them too in red
        if not (R >= 0).all():
            _plot2D_samples_mat(source, target, -R, thr=thr, c=[1, 0.2, 0.2])
            colors = ['blue', 'red']
            lines = [Line2D([0], [0], color=c, linewidth=2) for c in colors]
            labels = ['Positive coeffs', 'Negative coeffs']
            leg = Legend(ax, lines, labels, loc='upper left', fontsize=10)
            ax.add_artist(leg)
            plt.legend()
        # Then plot R positive coeffs above a threshold in blue
        _plot2D_samples_mat(source, target, R, thr=thr, c=[0.2, 0.2, 1])

    plt.rcParams.update(
        {'font.size': 12, 'ytick.labelsize': 14, 'xtick.labelsize': 14, 'axes.titlesize': 14, "axes.labelsize": 12})
    plt.xlabel('Contrast 1', fontsize=14)
    plt.ylabel('Contrast 2', fontsize=14)
    plt.tick_params(**tick_params)
    plt.title(title, fontsize=16)

a, b = source, target

# translate all the data to the origin
mtx1 -= np.mean(a, 0)
mtx2 -= np.mean(b, 0)

norm1 = np.linalg.norm(a)
norm2 = np.linalg.norm(b)

# change scaling of data (in rows) such that trace(mtx*mtx') = 1
a /= norm1
b /= norm2

R, scale = orthogonal_procrustes(a, b)


import numpy as np
import sys
import json
from math import *

def initializeMatrix(file,size):
    A = np.zeros((size, size+1))
     #sys.argv[4] array con los valores iniciales
    xValues= json.loads(sys.argv[4])

    xNewValues = np.zeros(size)
    for i in range (size):
        cont=0
        fileMio=file.readline().replace("\n","").split(" ")
        linea=fileMio
        for j in linea:
            A[i][cont]=float(j)
            cont+=1
    return A,xValues,xNewValues

def newJacobi(xValues,xNewValues,A,size):
    disp = 0
    for i in range (size):
        suma = 0
        for j in range (size):
            var = A[i][j]
            if (i!=j):
                suma += var*xValues[j]
            else:
                aii = var

        var = A[i][size]
        xNewValues[i] = (var - suma)/aii
        disp = max(disp, abs(xNewValues[i]- xValues[i]))

    return disp,xNewValues

def jacobi(xValues,xNewValues,A,size,tol,niter):
    disp = tol+1
    cont = 0
    while (disp > tol and cont < niter):
        for i in range (size):
            xValues[i] = xNewValues[i]
        disp,xNewValues = newJacobi(xValues,xNewValues,A,size)
        print "Iter:",cont
        cont+=1

        print "X vector:",np.array(xNewValues)
        print ("\n")
        print "Error: ",disp
        print ("\n")

    if (disp <= tol):
        bandera= True
    else:
        bandera=False
    return bandera,xValues,xNewValues,A,tol,niter,disp

def main():
    name=sys.argv[1]
    file=open(name)
    size=int(file.readline())
    A,xValues,xNewValues = initializeMatrix(file,size)

    #tolerance=float(input( "how much tolerance? for example if you have n=10, tolerance should be 0.01 and maxIters=10000\n"  ))
    tolerance=float(sys.argv[2])
    #maxIterations=float(input("how many iterations? i.e: 100\n"))
    maxIterations=float(sys.argv[3])
    success,xValues,xNewValues,A,tol,niter,error = jacobi(xValues,xNewValues,A,size, tolerance, maxIterations)
    #print success,xValues,xNewValues,A,tol,niter
    if (success):
        print ("Matrix A")
        print (np.array(A))
        print ("\n")
        print np.array(xValues)
        print ("\n")
        print "Error: ",error
        print ("\n")

    else:
        print "could not reach the solutions in ", maxIterations , " iterations"

main()


#!/usr/bin/env python3

"""Problem 11 from Project Euler: Largest product in a grid

Find the greatet product of n adjacent numbers in a grid in one direction,
up, down, left, right, diagonally.
https://projecteuler.net/problem=11

Usage:
    python3 p0011.py [filename] [number]
"""

import numpy
import sys

from itertools import count, islice
from math import prod
from typing import List, Tuple

def largest_product_in_a_grid(grid: List[List[int]], num: int) -> int:
    """Calculates the largest product of a sequence of num numbers in any
    direction in a given square or rectangular grid of numbers."""
    largest = 0

    for y in range(len(grid)):
        for x in range(len(grid[0])):
            product = lambda dx, dy: grid_product(grid, (x, y), (dx, dy), num)
            largest = max([largest,
                           product(1, 0),      # Horizontal
                           product(0, 1),      # Vertical
                           product(1, 1),      # Diagonal down
                           product(1, -1)])    # Diagonal up

    return largest

def grid_product(grid: List[List[int]], start: Tuple[int], direction: Tuple[int], num: int) -> int:
    """Calculate the product of a sequence of numbers in a grid.

    Args:
        grid: A square or rectangular two-dimensional list of numbers.
        start: The coordinates of the first number in the sequence.
        direction: A vector indicating the direction of the subsequent numbers.
        num: The quantity of numbers to choose from the grid.

    Returns:
        The product of all numbers chosen from the grid or 0 if the movement
        would overflow the grid boundaries.
    """
    x, y = start
    dx, dy = direction

    try:
        # Ensure the sequence doesn't start or end below a zero index
        if x < 0 or y < 0 or x + num * dx < 0 or y + num * dy < 0:
            raise IndexError

        return prod(grid[y + dy * i][x + dx * i] for i in range(num))

    except IndexError:
        return 0

def main(fname: str, num: int):
    """Prints the solution."""
    grid = numpy.loadtxt(fname, int, '#', ' ')
    print(largest_product_in_a_grid(grid, num))

if __name__ == '__main__':
    main(sys.argv[1], int(sys.argv[2]))


# -*- coding: utf-8 -*-
"""
Created on Tue Jul  3 11:33:31 2018

@author: SilverDoe
"""

'''
Interpolation is the process of finding a value between two points on a line or a curve.

Interpolation is guessing data points that fall within the range of the data you have, i.e.
between your existing data points. Extrapolation is guessing data points from beyond the range of your data set.

https://docs.scipy.org/doc/scipy-1.1.0/reference/interpolate.html
'''

'''================ numpy interpolation =======================================

>> While numpy returns an array with discrete datapoints, 'interp1d' returns a function.
   You can use the generated function later in your code as often as you want.

>> Numpy.interp does not handle complex-valued data or ndim>1, while scipy.interp1d does both.
   OTOH, numpy's interpolator is much faster
'''

# numpy interpolation
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 10)
y = np.sin(x)
xvals = np.linspace(0, 2*np.pi, 50)
yinterp = np.interp(xvals, x, y)
plt.plot(x, y, 'o')
plt.plot(xvals, yinterp, '-x')
plt.show()

#=============================== scipy interp1d ===============================
# scipy interp1d
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
x = np.linspace(0, 4, 12)
y = np.cos(x**2/3+4)

plt.plot(x, y,'o')
plt.show()

f1 = interpolate.interp1d(x, y,kind = 'linear')
f2 = interpolate.interp1d(x, y, kind = 'cubic')

xnew = np.linspace(0, 4,30)
plt.plot(x, y, 'o', xnew, f1(xnew), '-', xnew, f2(xnew), '--')
plt.legend(['data', 'linear', 'cubic'], loc = 'best')
# https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html
plt.show()

#====================== UnivariateSpline ======================================

import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
x = np.linspace(0, 4, 12)
y = np.cos(x**2/3+4)
plt.plot(x, y,'o')
plt.show()

spl = interpolate.UnivariateSpline(x, y)
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.UnivariateSpline.html
xs = np.linspace(0, 4, 1000)
plt.plot(xs, spl(xs), 'g', lw = 3)
plt.show()

# example 2 =================

import matplotlib.pyplot as plt
from scipy.interpolate import UnivariateSpline
x = np.linspace(-3, 3, 50)
y = np.exp(-x**2) + 0.1 * np.random.randn(50)
plt.plot(x, y, 'ro', ms = 5)
plt.show()

spl = UnivariateSpline(x, y)
xs = np.linspace(-3, 3, 1000)
plt.plot(xs, spl(xs), 'g', lw = 3)
plt.show()

# manually set smoothing factor
spl.set_smoothing_factor(0.5)
plt.plot(xs, spl(xs), 'b', lw = 3)
plt.show()

# exampe 3 ================


# **************************************************************************** #
#                                                                              #
#                                                         :::      ::::::::    #
#    std.py                                             :+:      :+:    :+:    #
#                                                     +:+ +:+         +:+      #
#    By: ciglesia <ciglesia@student.42.fr>          +#+  +:+       +#+         #
#                                                 +#+#+#+#+#+   +#+            #
#    Created: 2020/11/23 00:09:52 by ciglesia          #+#    #+#              #
#    Updated: 2020/11/23 19:11:46 by ciglesia         ###   ########.fr        #
#                                                                              #
# **************************************************************************** #

import numpy as np
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent.absolute()))
import ex02.variance as v
import ex00.sum as s

def std(x):
    """
    Computes the standard deviation of a non-empty numpy.ndarray, using a
    for-loop.
    Args:
    x: has to be an numpy.ndarray, a vector.
    Returns:
    The standard deviation as a float.
    None if x is an empty numpy.ndarray.
    Raises:
    This function should not raise any Exception.
    """
    if (not s.elements(x)):
        return (None)
    return (np.sqrt(v.variance(x)))

if __name__ == "__main__":
    print("X = np.array([0, 15, -9, 7, 12, 3, -21])\nstd(X)")
    X = np.array([0, 15, -9, 7, 12, 3, -21])
    print(std(X))
    Y = np.array([2, 14, -13, 5, 12, 4, -19])
    print("Y = np.array([2, 14, -13, 5, 12, 4, -19])\nstd(Y)")
    print(std(Y))


#!/usr/bin/env python
# coding: utf-8

# In[1]:
import pandas as pd
import numpy as np

# In[2]:
def pdappend(df,line):
    a_series = pd.Series(line, index = df.columns)
    return df.append(a_series, ignore_index=True)

# In[3]:
head=['theta','sin','cos']
df=pd.DataFrame(columns=head)

# In[4]:
pi=np.pi
dp=pi/100.0
a=np.arange(0,2*pi,dp)

# In[5]:
df['theta']=a
df['sin']=np.sin(df.theta)
df['cos']=np.cos(df.theta)

# In[6]:
def sqit(x,y):
    return (x*x+y*y)

# In[7]:
df['one']=sqit(df['sin'],df['cos'])

# In[8]:
def quake (xin):
    if xin < 0.0 :
        return 0.0
    return xin*xin

# In[9]:
#quake(df.sin)  This does not work

#this does
df.apply(lambda row: quake(row['sin']),axis=1)

# In[10]:
df=pdappend(df,[2*pi,np.sin(2*pi),np.cos(2*pi),1])

# In[11]:
df

# In[12]:
# here we need to point to the directory that contains plotting routines
import sys
sys.path.append("/Users/tkaiser2/bin")
sys.path.append("/home/tkaiser2/bin")

# In[13]:
from plsub import myplot

# In[14]:
try:
    get_ipython().run_line_magic('matplotlib', 'inline')
except:
    pass

# In[15]:
x=np.array(df.theta)
s=np.array(df.sin)
c=np.array(df.cos)

# In[16]:
to_plot=[[x,s,"sin(x)"],[x,c,"cos(x)"]]

# In[17]:
myplot(bl="time",sl="out\nVolts",topl="two plots",width=1,sets=to_plot,doxkcd=True)

def mytan (s,c):
    return s/c

df['tan']=df.apply(lambda row: mytan(row['sin'],row['cos']),axis=1)

print(df)


import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import beta
import seaborn as sns
sns.set(style='white', font='consolas', font_scale=1.2)

def bernoulli_entropy_fig():
    """Simple illustration of entropy for the Bernoulli distribution"""
    x = np.linspace(0.001, 0.999, 100)
    y = -x*np.log2(x) - (1-x)*np.log2(1-x)

    f, ax = plt.subplots(figsize=(6, 5))
    ax.plot(x, y)
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)
    ax.set_xticks([0, 0.5, 1])
    ax.set_yticks([0, 0.5, 1])
    ax.set_xticklabels(['0', '0.5', '1'])
    ax.set_yticklabels(['0', '0.5', '1'])
    ax.set_xlabel("P(X)=1")
    ax.set_ylabel("H(X)")

def beta_distribution():
    """Examples of Beta distribution with varying alpha and beta parameters."""
    x = np.linspace(0, 1, 100)
    f, ax = plt.subplots(figsize=(6, 4))
    rv = beta.pdf(x, 0.5, 0.5)
    ax.plot(x, rv, label='a=0.5, b=0.5')
    rv = beta.pdf(x, 1, 1)
    ax.plot(x, rv, label='a=1, b=1')
    rv = beta.pdf(x, 2, 3)
    ax.plot(x, rv, label='a=2, b=3')
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 3)
    ax.set_title('beta distributions')
    plt.legend()
    f.savefig('../figures/beta_distribution.png')

if __name__ == '__main__':
    beta_distribution()


#!/usr/bin/env python
"""
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
"""
# Definition for a point.
# class Point(object):
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b

class Solution(object):
    def maxPoints(self, points):
        """
        :type points: List[Point]
        :rtype: int
        """
        l = len(points)
        if l < 3:
            return l
        maxpts = 0
        for i in range(l-1): # don't need the last element in initial loop
            overlap = 0
            pi = points[i]
            ptdict = {None: 1} # set some dummy element so that when ptdict is empty it will return at least the initial point of 1 as max
            xi, yi = pi.x, pi.y
            for j in range(i + 1, l):
                pf = points[j]
                xf, yf = pf.x, pf.y
                if xi == xf and yi == yf: # when the point overlap with the current point, increase overlap counter, this will in effect add to all points in ptdict
                    overlap += 1
                    continue
                if xi == xf: # when slope is infinity
                    slope = 'i'
                else:
                    dx, dy = xf - xi, yf - yi
                    gcd = self.getGcd(dx, dy) # use gcd or need to import numpy as np.longdouble which is more time consuming for high accuracy fractions
                    dx //= gcd # reduce the fraction by its greatest common denominator
                    dy //= gcd
                    slope = (dx, dy) # so that the slope can be expressed by two integers
                if slope not in ptdict: # when slope is not already in ptdict, add one, will represent the initial point along this slope
                    ptdict[slope] = 1
                ptdict[slope] += 1
            maxpts = max(maxpts, max(ptdict.values()) + overlap)
        return maxpts

    def getGcd(self, dx, dy): # cleaver way to recursively return greatest common denominator
        if dy == 0: return dx
        else: return self.getGcd(dy, dx % dy)


#! /usr/bin/env python
"""
File: interpolate_exp_cos.py

Copyright (c) 2016 Michael Seaman

License: MIT

Description: Creates a linear interpolation function to evaluate
f = exp(-x^2) * cos(2pi x) for different numbers of interpolation
points q and for x = -.45
"""

import numpy as np
from calculus import discrete_func

def f(x):
    return np.exp(-1 * x**2) * np.cos(2* np.pi * x)

def interpolate(x, given_x_values, given_y_values):
    """
    Returns the linearly approximated value at x of a function who's
    discrete values are given by 'given_y_values' at x values given by
    'given_x_values'. The given values for x must be in increasing order
    and must corespond with the y values.
    """
    k = np.argmax(given_x_values>x) - 1
    slope = (given_y_values[k + 1] - given_y_values[k])/float(given_x_values[k + 1] - given_x_values[k])
    return given_y_values[k] + slope*(x - given_x_values[k])

def interpolate_with_exact(x, f, a, b, n):
    """
    Returns a approximation of f(x) with n interpolation points from
    a to b. Then returns the actual value of f evaluated at x.
    """
    x_list = discrete_func(f, a, b, n)[0]
    y_list = discrete_func(f, a, b, n)[1]
    interpolated_value = interpolate(x, x_list, y_list)
    actual_value = f(x)
    return interpolated_value, actual_value

def test_interpolate_on_given_value():
    """
    Asserts that the interpolation model should perfectly model the
    function when given a value it was trained on - making the term
    (x - given_x_values[k]) go to zero.
    """
    a = -10
    b = 10
    n = 1000
    xL = np.linspace(a, b, n+1)
    yL = np.sin(xL)
    random_index = np.random.randint(n)
    assert interpolate(xL[random_index], xL, yL) == yL[random_index]


import numpy as np
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from pandas.tools import plotting # 高度なプロットを行うツールのインポート
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])

pca = PCA(n_components=2)
pca.fit(X)
v_pca0=pca.components_[0]
v_pca1=pca.components_[1]
X_pca0=[0,1*v_pca0[0]]
Y_pca0=[0,1*v_pca0[1]]
X_pca1=[0,1*v_pca1[0]]
Y_pca1=[0,1*v_pca1[1]]

plt.scatter(X[:,0],X[:,1],c="g",marker = "*")
plt.plot(X_pca0,Y_pca0,c="r",marker = "o")
plt.plot(X_pca1,Y_pca1,c="b",marker = "o")
plt.savefig('k-means/pca_example/pca_data_scatter.jpg')
plt.pause(1)
plt.close()
print(v_pca0[0],v_pca0[1])
Y=np.array([[0,0],[v_pca0[0],v_pca0[1]],[v_pca1[0],v_pca1[1]]])
print(Y)

pcatran_X = pca.transform(X)
pcatran_Y = pca.transform(Y)
print("pcatran_Y={}".format(pcatran_Y))

plt.scatter(pcatran_X[:,0],pcatran_X[:,1],c="g",marker = "*")
plt.scatter(pcatran_Y[:,0],pcatran_Y[:,1],c="r",marker = "o")
plt.plot([pcatran_Y[0,0],pcatran_Y[0,1]],[pcatran_Y[2,0],pcatran_Y[2,1]],c="b")
plt.plot([pcatran_Y[2,0],pcatran_Y[2,1]],[pcatran_Y[0,0],pcatran_Y[0,1]],c="r")  #,marker = "o")
plt.savefig('k-means/pca_example/pca_tran_scatter.jpg')
plt.pause(1)
plt.close()

print("v_pca0={},v_pca1={}".format(v_pca0,v_pca1))
s=2
print("pca.explained_variance_ratio_{}".format(pca.explained_variance_ratio_))
plt.bar([1, 2], pca.explained_variance_ratio_, align = "center",label="pca.explained_variance_ratio_={}".format(pca.explained_variance_ratio_))
plt.title("pca.explained_variance_ratio_")
plt.xlabel("components")
plt.ylabel("contribution")
plt.legend()
plt.savefig('k-means/pca_example/pca2d_contribution_PCA12_plotSn'+str(s)+'.jpg')
plt.pause(1)
plt.close()

print("pca.singular_values_={}".format(pca.singular_values_))

#X = np.array([[-1, -1, -1], [-2, -1,-2], [-3, -2, 1], [1, 1,1], [2, 1,1], [3, 2,1],[-1, -1.5, -1], [-2, -1.5,-2], [-3, -2.5, 1], [1.5, 1,1], [2, 1.5,1], [3, 2,1.5],[-1, 0, -1], [0, -1,-2], [-3, -2, 0], [1, 0,1], [2, 0,1], [0, 2,1],[-1, -0.5, -1], [0, -1.5,-2], [0, -2.5, 1], [1.5, 0,1], [2, 0.5,1], [3, 2,0.5]])
from sklearn.datasets import make_regression

#X, Y, coef = make_regression(random_state=12, n_samples=100, n_features=3, n_informative=2, noise=10.0, bias=-0.0, coef=True)

from sklearn.datasets import make_blobs
X, Y = make_blobs(random_state=8,
                  n_samples=100,
                  n_features=3,
                  cluster_std=4,
                  centers=3)

pca = PCA(n_components=3)
pca.fit(X)
v_pca0=pca.components_[0]
v_pca1=pca.components_[1]
v_pca2=pca.components_[2]
X_pca0=[0,10*v_pca0[0]]
Y_pca0=[0,10*v_pca0[1]]
Z_pca0=[0,10*v_pca0[2]]
X_pca1=[0,10*v_pca1[0]]
Y_pca1=[0,10*v_pca1[1]]
Z_pca1=[0,10*v_pca1[2]]
X_pca2=[0,10*v_pca2[0]]
Y_pca2=[0,10*v_pca2[1]]
Z_pca2=[0,10*v_pca2[2]]

def show_with_angle(angle):
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.view_init(elev = 10., azim = angle)
    ax.plot(X_pca0,Y_pca0,Z_pca0, c='b', marker='o', alpha=0.5, label='1st pricipal')
    ax.plot(X_pca1,Y_pca1,Z_pca1, c='r', marker='o', alpha=0.5, label='2nd principal')
    ax.plot(X_pca2,Y_pca2,Z_pca2, c='g', marker='o', alpha=0.5, label='3rd principal')
    ax.scatter(X[:, 0], X[:, 1], X[:, 2],  c="b", marker='o', alpha=1)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.legend()
    plt.pause(0.01)
    plt.savefig('k-means/pca_example/pca3d/keiba3_PCA3d_angle_'+str(angle)+'.jpg')
    plt.close()

for angle in range(0, 360, 5):
    show_with_angle(angle)

print(v_pca0[0],v_pca0[1],v_pca0[2])
Y=np.array([[0,0,0],[10*v_pca0[0],10*v_pca0[1],10*v_pca0[2]],[10*v_pca1[0],10*v_pca1[1],10*v_pca1[2]],[10*v_pca2[0],10*v_pca2[1],10*v_pca2[2]]])
print(Y)

pcatran_X = pca.transform(X)
print("pcatran_X={}".format(pcatran_X))
pcatran_Y = pca.transform(Y)
print("pcatran_Y={}".format(pcatran_Y))

plt.scatter(pcatran_X[:,0],pcatran_X[:,1],c="g",marker = "*")
plt.scatter(pcatran_Y[:,0],pcatran_Y[:,1],c="r",marker = "o")
plt.plot([pcatran_Y[0,0],pcatran_Y[1,0]],[pcatran_Y[0,1],pcatran_Y[1,1]],c="b",marker = "o")
plt.plot([pcatran_Y[0,0],pcatran_Y[2,0]],[pcatran_Y[0,1],pcatran_Y[2,1]],c="r",marker = "o")
plt.savefig('k-means/pca_example/pca_tran_scatter3.jpg')
plt.pause(1)
plt.close()

def show_with_angle(angle):
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.view_init(elev = 10., azim = angle)
    ax.scatter(pcatran_X[:, 0], pcatran_X[:, 1], pcatran_X[:, 2],  c="b", marker='o', alpha=1)
    ax.set_xlabel('tran_x')
    ax.set_ylabel('tran_y')
    ax.set_zlabel('tran_z')
    ax.legend()
    plt.pause(0.01)
    plt.savefig('k-means/pca_example/tran_pca3d/pca3_PCA3d_angle_'+str(angle)+'.jpg')
    plt.close()

for angle in range(0, 360, 5):
    show_with_angle(angle)

print("v_pca0={},v_pca1={},v_pca2={}".format(v_pca0,v_pca1,v_pca2))
s=3
print("pca.explained_variance_ratio_{}".format(pca.explained_variance_ratio_))
plt.bar([1, 2,3], pca.explained_variance_ratio_, align = "center",label="pca.explained_variance_ratio_={}".format(pca.explained_variance_ratio_))
plt.title("pca.explained_variance_ratio_")
plt.xlabel("components")
plt.ylabel("contribution")
plt.legend()
plt.savefig('k-means/pca_example/pca3d_contribution_PCA12_plotSn'+str(s)+'.jpg')
plt.pause(1)
plt.close()

print("pca.singular_values_={}".format(pca.singular_values_))

s=6
#from sklearn.datasets import make_blobs
X, Y = make_blobs(random_state=8,
                  n_samples=100,
                  n_features=6,
                  cluster_std=4,
                  centers=3)

pca = PCA(n_components=6)
pca.fit(X)
v_pca0=pca.components_[0]
v_pca1=pca.components_[1]
v_pca2=pca.components_[2]

X_pca0=[0,10*v_pca0[0]]
Y_pca0=[0,10*v_pca0[1]]
Z_pca0=[0,10*v_pca0[2]]
X_pca1=[0,10*v_pca1[0]]
Y_pca1=[0,10*v_pca1[1]]
Z_pca1=[0,10*v_pca1[2]]
X_pca2=[0,10*v_pca2[0]]
Y_pca2=[0,10*v_pca2[1]]
Z_pca2=[0,10*v_pca2[2]]

def show_with_angle(angle):
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.view_init(elev = 10., azim = angle)
    ax.plot(X_pca0,Y_pca0,Z_pca0, c='b', marker='o', alpha=0.5, label='1st pricipal')
    ax.plot(X_pca1,Y_pca1,Z_pca1, c='r', marker='o', alpha=0.5, label='2nd principal')
    ax.plot(X_pca2,Y_pca2,Z_pca2, c='g', marker='o', alpha=0.5, label='3rd principal')
    ax.scatter(X[:, 0], X[:, 1], X[:, 2],  c="b", marker='o', alpha=1)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.legend()
    plt.pause(0.01)
    plt.savefig('k-means/pca_example/pca6d/keiba3_PCA3d_angle_'+str(angle)+'.jpg')
    plt.close()

for angle in range(0, 360, 5):
    show_with_angle(angle)

print(v_pca0[0],v_pca0[1],v_pca0[2])

pcatran_X = pca.transform(X)
print("pcatran_X={}".format(pcatran_X))

def show_with_angle(angle):
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.view_init(elev = 10., azim = angle)
    ax.scatter(pcatran_X[:, 0], pcatran_X[:, 1], pcatran_X[:, 2],  c="b", marker='o', alpha=1)
    ax.set_xlabel('tran_x')
    ax.set_ylabel('tran_y')
    ax.set_zlabel('tran_z')
    ax.legend()
    plt.pause(0.01)
    plt.savefig('k-means/pca_example/tran_pca6d/pca3_PCA3d_angle_'+str(angle)+'.jpg')
    plt.close()

for angle in range(0, 360, 5):
    show_with_angle(angle)

print("v_pca0={},v_pca1={},v_pca2={}".format(v_pca0,v_pca1,v_pca2))
s=3
print("pca.explained_variance_ratio_{}".format(pca.explained_variance_ratio_))
plt.bar([1, 2,3,4,5,6], pca.explained_variance_ratio_, align = "center",label="pca.explained_variance_ratio_={}".format(pca.explained_variance_ratio_))
plt.title("pca.explained_variance_ratio_")
plt.xlabel("components")
plt.ylabel("contribution")
plt.legend()
plt.savefig('k-means/pca_example/pca6d_contribution_PCA12_plotSn'+str(s)+'.jpg')
plt.pause(1)
plt.close()

print("pca.singular_values_={}".format(pca.singular_values_))


# Plot 2d sigmoid functions for various values of w1, w2.
# i.e. sigmoid(w1*x1 +%w2*x2)
# Based on https://github.com/probml/pmtk3/blob/master/demos/sigmoidplot2D.m
# Duane Rich

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import proj3d
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from pyprobml_utils import save_fig

def sigmoid(v):
    return 1/(1+np.exp(-v))

def make_lin_sig(w):
    """
    Create linear function passed through a sigmoid for a given parameter vector w.
    """

    def lin_sig(x):
        return sigmoid(w.dot(x))

    return lin_sig

def num_to_string(num):
    """Formats a number as a string"""
    if int(num) == num:
        return str(int(num))
    else:
        return str(num)

def plot_lingsig(ax, w):

    """
    Given an axes, this will plot the linear sigmoid function associated with w on it.
    """

    Y = np.zeros(X1.shape)

    lin_sig = make_lin_sig(np.array(w))

    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = lin_sig(np.array([X1[i, j], X2[i, j]]))

    ax.plot_surface(X1, X2, Y, cmap='jet', vmin=0, vmax=3,rstride=1,cstride=1, linewidth=0)
    ax.set_zticks([0.0, 0.5, 1.0])
    ax.set_xticks([-10, 5, 0, 5, 10])
    ax.set_yticks([-10, 5, 0, 5, 10])
    ax.set_title('W=({0},{1})'.format(num_to_string(w[0]),num_to_string(w[1])))

    return ax

X1, X2 = np.meshgrid(np.linspace(-10, 10, 20),
                     np.linspace(-10, 10, 20))

fig, ax = plt.subplots(figsize=(10,8))

lims = [-5.5, 5.5]

ax.set_ylim(*lims)
ax.set_xlim(*lims)

half_width = 0.075

def det_position(wi):
    # Determine what proportion of the axis limits w is.
    return (wi - lims[0])/(lims[1]-lims[0])

"""Loop over all coefficient values, adding the associated plot to the graph."""
for w_y in [-3.0, 0.0, 3.0]:
    for w_x in [-3.0, 0.0, 3.0]:
        if w_y == w_x == 0:
            w = [w_x, 0.5]
        else:
            w = [w_x, w_y]

        position = [det_position(w[0]), det_position(w[1])]

        """
        These left, bottom, etc... are in reference to the figure (not the axes within it),
        so we need to use fig.tight_layout layer so this closely maps onto the position of
        the main axes.
        """

        left, bottom, width, height = [position[0]-half_width, position[1]-half_width,
                                       2*half_width, 2*half_width]

        curr_ax = fig.add_axes([left, bottom, width, height], projection='3d')
        curr_ax = plot_lingsig(curr_ax, w)

# Add arrows and save
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
edge = (lims[1]-lims[0])*0.05
ax.arrow(0, lims[0]+edge, 0, lims[1]-lims[0]-2*edge,
         linewidth=5)
ax.arrow(lims[0]+edge, 0, lims[1]-lims[0]-2*edge, 0,
         linewidth=5)
save_fig('sigmoidPlot2dColor.pdf')
plt.show()


import numpy as np
from scipy import stats

def one_if_all_non_zero(arr):
	for i in arr:
		if i == 0:
			return 0
	return 1

def Max(arr):
	if len(arr) == 0:
		return 0
	return max(arr)

def Min(arr):
	if len(arr) == 0:
		return 0
	return min(arr)

def first(arr):
	if len(arr) == 0:
		return 0
	return arr[0]

def last(arr):
	if len(arr) == 0:
		return 0
	return arr[-1]

def std(arr):
	if len(arr) == 0:
		return 0
	return np.std(arr)

def signum(num):
	if num >0:
		return 1
	elif num <0:
		return -1
	return 0

def mean(array):
	if len(array) == 0:
		return 0
	return np.average(array)

def median(array):
	if len(array) == 0:
		return 0
	return np.median(array)

def mode(array):
	if len(array) == 0:
		return 0
	return stats.mode(array).mode[0]

def quartile(array):
	arr1 = []
	arr2 = []

	length = len(array)
	arrx = []
	for i in range(length):
		arrx.append(array[i])
	arrx.sort()
	if((len(array)%2) == 1):
		arr1 = array[:length/2]
		arr2 = array[length/2+1:]
	else:
		arr1 = array[:length/2]
		arr2 = array[length/2:]

	return (median(arr1), median(arr2))

def derivative(array_time, array_func):
	prev = ''
	prev_time = ''
	length = len(array_time)
	der = []

	for i in range(length):
		if(array_func[i] != 'NA'):
			if(prev != ''):
				der.append((array_func[i]-prev)/(array_time[i]-prev_time))
			prev = array_func[i]
			prev_time = array_time[i]

	return der


import numpy as np
import matplotlib.pyplot as plt

def LHCSampling(numSamples=int, numDimensions=int, numDivisions=int, dimensionSpans='array', plot=False):
    """
    Implementation of Latin Hypercube Sampling
            The implementation works by dividing each dimensions equally like a square matrix. Then, like the indices of a matrix, indices for each dimension
            are sampled randomly. This indices are then identified in the population matrix from which the actual values are taken. This values are again
            randomised before saving to the output matrix.
    numDivisions    :number of divisions on each dimension spans.
    dimensionSpans  :a numpy array with lower and upper bounds for each dimension eg:np.asarray([dim1_lower, dim1_upper],[dim2_lower, dim2_upper])
                    (should have 2 indices even for 1 diamension, ie, shape = (1,2))
    numSamples      :number of samples needed.
    numDimensions   :number of dimensions to be sampled from.
    plot            :shows(if True) a plot of the samples in the dimension space(limited to 2D)
    LHCsamples      :2d output array with samples of a particular dimension in each row.
    """
    #initialization
    row = []
    for i in range(numDivisions):
        row.append(i)
    Population_indices = np.zeros((numDimensions,numDivisions))   #array of all indices
    sampleIndices = np.zeros((numDimensions, numSamples), dtype=int)  #array of only sampled indices

    for i in range(numDimensions):
        Population_indices[i,:] = np.asarray(row)
    Population_indices_temp = Population_indices
    j = 0

    #sampling of indices
    while True:
        a = np.zeros((numDimensions))
        for i in range(numDimensions):
            a[i] = np.random.choice(Population_indices_temp[i,:], 1, replace=False)   #randomly choosing the indices for each dimension(the replace=False parameter ensures no two same indices are selected)
        if j == 0:
            sampleIndices[:,j] = a
            j+=1
            continue
        else:
            temp = np.zeros((numDimensions))
            flag = 0
            for k in range(len(sampleIndices)):
                if (a[k] in sampleIndices[k,:j]) == True:
                    flag =1
                    break
                else:
                    temp[k] = a[k]
            if flag ==0:
                sampleIndices[:,j]= temp
                j+=1
        if j>=numSamples:
            break
    population = np.zeros((numDimensions,numDivisions))     #array for storing sides of hypercube(divisions of each dimension)
    eachDivision = np.zeros(numDimensions)    #array for storing each division size for each dimension

    for i in range(numDimensions):

        #calculates value of each division for each dimension
        eachDivision[i] = ((dimensionSpans[i,-1] - dimensionSpans[i,0])/numDivisions)
        for j,value in enumerate(np.arange(dimensionSpans[i,0], dimensionSpans[i,-1], eachDivision[i])):
            population[i,j] = value
    LHCsamples = np.zeros((numDimensions,numSamples))  ##array for storing samples collected using LHC
    sampleValues = np.zeros((numDimensions,1))  ##array for storing a single sample

    #generating random samples from the population
    for i in range(numSamples):
        for j in range(numDimensions):
            randomValues = np.random.uniform(low=0, high=eachDivision[j], size=1) #generating a random number for each division for each dimension(randomising sampling between two divisions)
            sampleValues[j,0] = np.take(population[j,:], sampleIndices[j,i]) + randomValues  #adding random value with each division of a dimension
        LHCsamples[:,i] = np.reshape(sampleValues, (numDimensions)) #saving generated random samples for each dimension

    #plotting
    if plot==True:
        plt.scatter(LHCsamples[0,:], LHCsamples[1,:])
        plt.xticks(population[0,:])
        plt.yticks(population[1,:])
        plt.grid()
        plt.show()

    return(LHCsamples)

def QMC_sampling(numSamples, numDimensions, dimensionSpans,sequence='halton', randomize=True, plot=False):
    """
    Implements Quasi-Monte Carlo sampling - reduces the likelihood of clustering (discrepancy)
    dimensionSpans  :a numpy array with lower and upper bounds for each dimension eg:np.asarray([dim1_lower, dim1_upper],[dim2_lower, dim2_upper])
                    (should have 2 indices even for 1 diamension, ie, shape = (1,2))
    numSamples      :number of samples needed.
    numDimensions   :number of dimensions to be sampled from.
    sequence        :the base sequence(halton or hammersley) to be used for sampling.
    randomize       :adds(if True) certain random values to pseudo random samples.
    plot            :shows(if True) a plot of the samples in the dimension space(limited to 2D)
    QMC_samples     :2d output array with samples of a particular dimension in each row.
    """

    #initialization
    QMC_samples = np.zeros((numDimensions, numSamples))

    #QMC sampling based on halton sequences
    if sequence == 'halton':
        primes = np.asarray((2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97))

        for dimension in range(numDimensions):

            #values for scaling the samples
            min_ = np.min(dimensionSpans[dimension,:])
            max_ = np.max(dimensionSpans[dimension,:])
            base = primes[dimension]

            for i in range(1,numSamples+1):

                #generating sequences
                i_th_sample = 0
                binary = np.base_repr(i, base)
                for j,value in enumerate(binary[::-1]):
                    i_th_sample += int(value)/np.power(base,(j+1))

                if randomize==True:
                    U = i_th_sample * (max_ -min_) + min_ + np.random.random(1)
                    if min_ <= U <= max_:
                        QMC_samples[dimension,i-1] = U
                    else:
                        i_th_sample = i_th_sample * (max_ -min_) + min_  #scaling and randomising
                        QMC_samples[dimension,i-1] = i_th_sample

                else:
                    i_th_sample = i_th_sample * (max_ -min_) + min_ #scaling
                    QMC_samples[dimension,i-1] = i_th_sample

    #QMC sampling based on hammersley sequences.
    if sequence == 'hammersley':
        primes = np.asarray((2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97))

        for dimension in range(numDimensions):
            #values for scaling
            min_ = np.min(dimensionSpans[dimension,:])
            max_ = np.max(dimensionSpans[dimension,:])
            base = primes[dimension]
            for i in range(1,numSamples+1):

                #generating sequences
                i_th_sample = 0
                binary = np.base_repr(i, base)
                if dimension == numDimensions-1:
                    i_th_sample = i/numSamples
                else:
                    for j,value in enumerate(binary[::-1]):
                        i_th_sample += int(value)/np.power(base,(j+1))
                if randomize==True:
                    U = i_th_sample * (max_ -min_) + min_ + np.random.random(1) #scaling and randomising
                    if min_ <= U <= max_:
                        QMC_samples[dimension,i-1] = U
                    else:
                        i_th_sample = i_th_sample * (max_ -min_) + min_ #scaling
                        QMC_samples[dimension,i-1] = i_th_sample
                else:
                    i_th_sample = i_th_sample * (max_ -min_) + min_ #scaling
                    QMC_samples[dimension,i-1] = i_th_sample

    #plotting
    if plot==True:
        plt.scatter(QMC_samples[0,:], QMC_samples[1,:])
        plt.grid()
        plt.show()

    return QMC_samples

def tst_train_split(numInputFeatures, filename_or_array, train_test_ratio=0.8, delimiter=',', header_present=True, RandomSeed=True):
    """
    Splits the given dataset into train and test datasets.
    numInputFeatures       :number of input features.
    filename_or_array      :filename or array containing the data
    train_test_ratio       :ratio by which the data has to be split into train and test datasets
    header_present         :specifies whether header is present(True) or not(False)
    RandomSeed             :Sets a random seed value if True
    X_train, X_train       :training data split into input and output
    y_test, y_test         :testing data split into input and output
    """

    if RandomSeed==True:
        np.random.seed(42)

    #start of data reading from file
    if type(filename_or_array) == str:
        raw_data = np.genfromtxt(filename_or_array, delimiter=delimiter, dtype=str)
        m = np.shape(raw_data)[0]  #number of lines in file
        n = np.shape(raw_data)[1]  #number of columns in file

        #changing indices based on the presence of header.
        if header_present == True:
            numTotalData = m-1     #number of total data sets
            firstIndex = 1
            flag = 0
        else:
            numTotalData = m
            firstIndex = 0
            flag = 1

    #taking data from given array
    else:
        m = np.shape(filename_or_array)[0]  #number of lines in file
        n = np.shape(filename_or_array)[1]
        numTotalData = m
        firstIndex = 0
        flag = 1

    numTrainData, numTestData = int(train_test_ratio*numTotalData), int(numTotalData - int(train_test_ratio*numTotalData)) #number of training and test data
    indicesDataSets = (np.linspace(firstIndex,numTotalData-flag,numTotalData)).astype(int) #array with indices of data sets
    np.random.shuffle(indicesDataSets)
    indicesTrainData = indicesDataSets[:numTrainData]   #indices of train data sets
    indicesTestData = indicesDataSets[numTrainData:]   #indices of test data sets
    X_train = (np.take(raw_data[:,:numInputFeatures], indicesTrainData, axis=0)).astype(np.float)   #slicing training input data from dataset
    y_train = (np.take(raw_data[:,numInputFeatures:], indicesTrainData, axis=0)).astype(np.float)   #slicing training output data from dataset
    X_test = (np.take(raw_data[:,:numInputFeatures], indicesTestData, axis=0)).astype(np.float)
    y_test = (np.take(raw_data[:,numInputFeatures:], indicesTestData, axis=0)).astype(np.float)

    return X_train, y_train, X_test, y_test

def read_data(numInputFeatures, filename, delimiter=',', header_present=True):
    """
    Function to read data from file.
    numInputFeatures:number of input features
    filename        :name of the dat file.
    header_present  :specifies whether header is present(True) or not(False)
    X               :array with input features.
    y               :array with output features.
    """
    raw_data = np.genfromtxt(filename, delimiter=delimiter, dtype=str)
    if header_present == True:
        firstIndex = 1
    else:
        firstIndex = 0
    X = (raw_data[firstIndex:,:numInputFeatures]).astype(np.float)
    y = (raw_data[firstIndex:, numInputFeatures:]).astype(np.float)
    return X, y

def shuffle_data(X, y):
    """
    Shuffles the data sets
    X : nd array containing the inputs (eg: X_train)
    y : nd array containing the corresponding outputs (eg: y_train)
    returns
    corresponding shuffled data sets
    """
    data = np.concatenate((X, y),axis=1)
    np.random.shuffle(data)
    n = np.shape(X)[1]  #num_of_column_elements_first_array
    X_shuffled =   data[:,:n] #slicing input data from dataset
    y_shuffled =    data[:,n:] #slicing output data from dataset
    return X_shuffled, y_shuffled

def data_transform_bak(array, array2=None,type='z_score_norm', means=None, stds=None):
    """
    Transforms data in the given array according to the type
    array   :an nd numpy array.
    array2  :an nd numpy array(optional-for multidimensional datasets)
    type    :'z_score_norm' = implements z score normalisation using mean and standard deviation on each column (datasets of each variable) of the given array.
             'min_max_norm' = implements min max scaling on each column (datasets of each variable) of the given array.
             'back_transform_z_score_norm' = returns the original data without z_score transformations.
             'back_transform_min_max_norm' = returns the original data without min_max transformations.
    means   :mean values(or min values) of each variable datasets - used for reverse transformation of data
    stds    :standard deviation values(or max values) of each variable datasets - used for reverse transformation of data

    """
    if array.ndim == 1:
        array = np.reshape(array,(len(array),1))
    if array2 != None:
        if array2.ndim == 1:
            array2 = np.reshape(array2,(len(array2),1))
            assert(np.shape(array)[1]) == np.shape(array2)[1]
    if type== "z_score_norm":
        means =[]
        stds = []
        for i in range(np.shape(array)[1]):
            mean = np.mean(array[:,i])
            std = np.std(array[:,i])
            means.append(mean)
            stds.append(std)
            if mean == 0 and std == 0:
                continue
            for j in range(np.shape(array)[0]):
                array[j,i]= (array[j,i] - mean)/std
            if array2.all() != None:
                for j in range(np.shape(array2)[0]):
                    array2[j,i]= (array2[j,i] - mean)/std

    elif type == "min_max_norm":
        for i in range(np.shape(array)[1]):
            min_ = min(array[:,i])
            max_ = max(array[:,i])
            #print(min_, max_)
            if min_ == 0 and max_ == 0:
                continue
            for j in range(np.shape(array)[0]):
                array[j,i]= (array[j,i] - min_)/(max_ - min_)
            if array2.all() != None:
                for j in range(np.shape(array2)[0]):
                    array2[j,i]= (array2[j,i] - min_)/(max_ - min_)
    elif type == "back_transform_z_score_norm":
        assert(means) != None
        assert(stds) != None
        for i in range(np.shape(array)[1]):
            mean = means[i]
            std = stds[i]
            if mean == 0 and std == 0:
                continue
            for j in range(np.shape(array)[0]):
                array[j,i] = array[j,i] *std + mean
            if array2.all() != None:
                for j in range(np.shape(array2)[0]):
                    array2[j,i] = array2[j,i] *std + mean

    else:
        raise ValueError("undefined method")
    if array2.all() != None:
        return array, array2, means, stds
    else:

        return array, means, stds

def data_transform(array, array2=np.asarray((None)),type='z_score_norm', means=None, stds=None):
    """
    Transforms data in the given array according to the type
    array   :an nd numpy array.
    array2  :an nd numpy array(optional-for multidimensional datasets)
    type    :'z_score_norm' = implements z score normalisation using mean and standard deviation on each column (datasets of each variable) of the given array.
             'min_max_norm' = implements min max scaling on each column (datasets of each variable) of the given array.
             'back_transform_z_score_norm' = returns the original data without z_score transformations.
             'back_transform_min_max_norm' = returns the original data without min_max transformations.
    means   :mean values(or min values) of each variable datasets - used for reverse transformation of data
    stds    :standard deviation values(or max values) of each variable datasets - used for reverse transformation of data

    """
    if array.ndim == 1:
        array = np.reshape(array,(len(array),1))
    if array2.all() != None:
        if array2.ndim == 1:
            array2 = np.reshape(array2,(len(array2),1))
            assert(np.shape(array)[1]) == np.shape(array2)[1]
    if type== "z_score_norm":
        means =[]
        stds = []
        for i in range(np.shape(array)[1]):
            mean = np.mean(array[:,i])
            std = np.std(array[:,i])
            means.append(mean)
            stds.append(std)
            if mean == 0 and std == 0:
                continue
            for j in range(np.shape(array)[0]):
                array[j,i]= (array[j,i] - mean)/std
            if array2.all() != None:
                for j in range(np.shape(array2)[0]):
                    array2[j,i]= (array2[j,i] - mean)/std

    elif type == "min_max_norm":
        for i in range(np.shape(array)[1]):
            min_ = min(array[:,i])
            max_ = max(array[:,i])
            #print(min_, max_)
            if min_ == 0 and max_ == 0:
                continue
            for j in range(np.shape(array)[0]):
                array[j,i]= (array[j,i] - min_)/(max_ - min_)
            if array2.all() != None:
                for j in range(np.shape(array2)[0]):
                    array2[j,i]= (array2[j,i] - min_)/(max_ - min_)
    elif type == "back_transform_z_score_norm":
        assert(means) != None
        assert(stds) != None
        for i in range(np.shape(array)[1]):
            mean = means[i]
            std = stds[i]
            if mean == 0 and std == 0:
                continue
            for j in range(np.shape(array)[0]):
                array[j,i] = array[j,i] *std + mean
            if array2.all() != None:
                for j in range(np.shape(array2)[0]):
                    array2[j,i] = array2[j,i] *std + mean

    else:
        raise ValueError("undefined method")
    if array2.all() != None:
        return array, array2, means, stds
    else:

        return array, means, stds


from numpy.linalg import norm
import numpy as np
import numpy.linalg as la
from time import time

class monitor:
    def __init__(self, algo, loss, x_min, args=()):
        self.x_min = x_min
        self.algo = algo
        self.loss = loss
        self.args = args
        self.f_min = loss(x_min, *args)

    def run(self, *algo_args, **algo_kwargs):
        t0 = time()
        _, x_list = self.algo(*algo_args, **algo_kwargs)
        self.total_time = time() - t0
        self.x_list = x_list
        self.err = [norm(x - self.x_min) for x in x_list]
        self.obj = [self.loss(x, *self.args) - self.f_min for x in x_list]

def grad_i_linreg(i, x, A, b, lbda):
    """Gradient with respect to a sample"""
    a_i = A[i]
    return (a_i.dot(x) - b[i]) * a_i + lbda * x

def grad_linreg(x, A, b, lbda):
    """Full gradient"""
    n = b.size
    g = np.zeros_like(x)
    for i in range(n):
        g += grad_i_linreg(i, x, A, b, lbda)
    return g / n

def loss_linreg(x, A, b, lbda):
    n = b.size
    return norm(A.dot(x) - b) ** 2 / (2. * n) + lbda * norm(x) ** 2 / 2.

def lipschitz_linreg(A, b, lbda):
    n = b.size
    return norm(A, ord=2) ** 2 / n + lbda

def sigmoid(t):
    """Sigmoid function"""
    return 1. / (1. + np.exp(-t))

def grad_i_logreg(i, x, A, b, lbda):
    """Gradient with respect to a sample"""
    a_i = A[i]
    b_i = b[i]
    return - a_i * b_i / (1. + np.exp(b_i * np.dot(a_i, x))) + lbda * x

def grad_logreg(x, A, b, lbda):
    """Full gradient"""
    n = b.size
    u = b * A.dot(x)
    return A.T.dot(b * (sigmoid(u) - 1)) / n +  lbda * x

def loss_logreg(x, A, b, lbda):
    bAx = b * np.dot(A, x)
    return np.mean(np.log(1. + np.exp(- bAx))) + lbda * norm(x) ** 2 / 2.

def lipschitz_logreg(A, b, lbda):
    n = b.size
    return norm(A, ord=2) ** 2 / (4. * n) + lbda

def mu_constant_logreg(A, b, lbda):
    """Return the strong convexity constant"""
    n = b.size
    mu =  min(abs(la.eigvals(np.dot(A,A.T)))) / (4*n) + lbda
    return mu