import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
from sklearn.neighbors import KernelDensity
from sklearn.model_selection import train_test_split
from itertools import cycle

# Problem solved using the links below as refernce
# https://github.com/knathanieltucker/bit-of-data-science-and-scikit-learn/blob/master/notebooks/DensityEstimation.ipynb

def parzen_window(X,y,bw,i,j=None):
    categories = y.unique()

    if j == None:
        X = (X.iloc[:,i]).values.reshape(-1,1)
        X_train, X_test, Y_train, Y_test = train_test_split(X,y, test_size = 0.20, random_state = 0)
        theta = np.linspace(0, max(X_train)+1, 1000).reshape(-1,1)
        estimators = []
        for c in categories:
            m = KernelDensity(kernel='gaussian', bandwidth=bw).fit(X_train[Y_train == c])
            estimators.append(m)

        calc_estimators(estimators, theta, X_test, Y_test, categories,j)

    else:
        X_train, X_test, Y_train, Y_test = train_test_split(X,y, test_size = 0.20, random_state = 0)
        X1_train = (X_train.iloc[:,i]).values.reshape(-1,1)
        X2_train = (X_train.iloc[:,j]).values.reshape(-1,1)
        X1_test = (X_test.iloc[:,i]).values.reshape(-1,1)
        X2_test = (X_test.iloc[:,j]).values.reshape(-1,1)
        Ay, Ax = np.meshgrid(np.linspace(0,max(X1_train)+1,101), np.linspace(0,max(X2_train)+1,101))
        theta = np.vstack([Ay.ravel(), Ax.ravel()]).T
        print(theta.shape)
        xy_test = np.hstack([X1_test,X2_test])
        print(xy_test.shape)

        estimators = []
        for c in categories:
            xy_train = np.hstack([X1_train[Y_train == c],X2_train[Y_train == c]])
            m = KernelDensity(kernel='gaussian', bandwidth=bw).fit(xy_train)
            estimators.append(m)

        calc_estimators(estimators, theta, xy_test, Y_test, categories,j, Ax, Ay)

    return

def calc_estimators(estimators, theta, x_test, y_test,categories,j, Ax=None, Ay=None):

    if j == None:
        cycol = cycle('rgbcmykw')
        test_estimates = []
        for i in range(len(estimators)):
            log_dens = estimators[i].score_samples(theta)
            log_test = estimators[i].score_samples(x_test)
            test_estimates.append(np.exp(log_test))
            color=next(cycol)
            plt.plot(theta, np.exp(log_dens), c = color)

        classify = np.argmax((np.array(test_estimates).T),axis=1)
        category = []
        for c in classify:
            category.append(categories[c])

        print("classify: ", classify)
        print("y_test: ", y_test)
        print("category: ", category)
        print("category==y_test: ", category==y_test)
        plt.show()

    else:
        cycol = cycle(['Reds','Greens','Blues','Yellows','Browns','Oranges'])
        test_estimates = []
        for i in range(len(estimators)):
            log_dens = estimators[i].score_samples(theta)
            log_test = estimators[i].score_samples(x_test)
            f = np.reshape(np.exp(log_dens), Ax.shape)
            test_estimates.append(np.exp(log_test))
            color=next(cycol)
            plt.contour(Ax, Ay, f , cmap = color)

        classify = np.argmax((np.array(test_estimates).T),axis=1)
        category = []
        for c in classify:
            category.append(categories[c])

        print("classify: ", classify)
        print("y_test: ", y_test)
        print("category: ", category)
        print("category==y_test: ", category==y_test)
        plt.show()

    return test_estimates, classify

if __name__ == "__main__":
    Iris = pd.read_csv("iris.csv",header=0)
    X = Iris.iloc[:,0:4]
    y = Iris.iloc[:,4]

    # parzen_window(X,y,.5,2)
    parzen_window(X,y,.5,2,3)

Algorithms for Data Science/Homework 4 /Homework4_Q1.py


'''
SpecialFuncUtil.py

Special mathematical functions, like multivariate gammaln.
'''

from collections import defaultdict
import numpy as np
from scipy.special import gammaln, digamma

LOGPI = np.log(np.pi)
LOGTWO = np.log(2.)
LOGTWOPI = np.log( 2.*np.pi )
EPS = 10*np.finfo(float).eps

MVgCache = defaultdict( lambda: dict())
def MVgammaln(x, D):
  ''' Compute log of the D-dimensional multivariate Gamma func. for input x

      Notes: Caching gives big speedup!
      -------
       caching : 208 sec for 5 iters of CGS on K=50, D=2 problem with N=10000
      no cache : 300 sec
  '''
  try:
    return MVgCache[D][x]
  except KeyError:
    result = gammaln(x+ 0.5*(1 - np.arange(1,D+1)) ).sum() + 0.25*D*(D-1)*LOGPI
    MVgCache[D][x] = result
  return result

def MVdigamma(x, D):
  ''' Compute the first-derivative of the log of the D-dim. Gamma function
  '''
  return digamma(x + 0.5 * (1 - np.arange(1,D+1))).sum()

def logsumexp(logA, axis=None):
  ''' Efficiently compute log(sum(exp(...))) for input matrix "logA"
      Computation is both vectorized and numerically stable.
  '''
  logA = np.asarray(logA)
  logAmax = logA.max(axis=axis)
  if axis is None:
    logA = logA - logAmax
  elif axis==1:
    logA = logA - logAmax[:,np.newaxis]
  elif axis==0:
    logA = logA - logAmax[np.newaxis,:]
  assert np.allclose( logA.max(), 0.0 )
  logA = np.log( np.sum( np.exp(logA), axis=axis )  )
  return logA + logAmax


#==============================================================================
# Photon Diffusion
# Calculates the diffusion of photons in a non-absorbing medium (lanex phosphor) using Fick's laws of diffusion.
#==============================================================================

#Imports
from numpy import *
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.integrate import quad
from scipy.special import erf
import sys
import os

#Import custom modules
from physics import *

sns.set(font_scale=2.0)
sns.set_style("ticks")
sns.set_palette(palette='deep')
sns.set_color_codes(palette='deep')
mpl.rcParams.update({'font.family': 'serif', 'font.serif':'DejaVu Serif'})

#%%
#==============================================================================
# Calculation of the phosphor layer thickness of lanex regular given its areal density:
#==============================================================================

Dcell = 55*10**-6
DPET = 175*10**-6
Dcell2 = 13*10**-6
rhocell = 1.44*10**3
rhoPET = 1.38*10**3
rhophos = 4.48*10**3
sigma = 70*10**-2

Dphos = (sigma - Dcell*rhocell - DPET*rhoPET - Dcell2*rhocell)/rhophos
print(Dphos*10**6)

#%%
#==============================================================================
#  Define functions for photon density and photon current density
#  These functions were derived from Fick's laws of diffusion:
#
#  $$ \frac{\partial n(z,t)}{\partial t} = D \frac{\partial^2 n(z,t)}{\partial z^2}, \: \: \phi (z,t) = -D \frac{\partial n(z,t)}{\partial z}$$
#
#  where n(z,t) is the photon density, D is the diffusion constant $D=\lambda_s c /6$ with $\lambda_s$ corresponding to the mean photon scattering length, and $\phi (z,t)$ is the photon current density. The fluorescence of the lanex phosphor was modeled as the instantaneous generation of light within a infinitely thin segment within a rectangular slab. The slab thickness $L$ is taken to be small compared to the other dimensions so that the problem can be treated one-dimensionally. The initial condition is taken to be
#
#  $$ n(z,0) = \frac{N_0}{A} \delta (z) \: \: \mathrm{with} \: \: n(z,t)=0 \: \: \mathrm{for} \: t<0 $$
#
#  where $N_0$ is the number of photons generated and $A$ is the cross-sectional area of the slab. In other words, at $t=0$, $N_0$ photons are generated and modeled as a dirac delta function at $z=0$. Fick's laws are then solved with absorbing boundary conditions at the edges of the lanex:
#
#  $$ n(d,t)=0, \: n(-l,t)=0$$
#
#  where $z=d$ is the location of the CCD and $z=-l$ is the location of the top edge of the phosphor. This yields
#
#  $$ n(z,t) = \frac{N_0}{2 A \sqrt{\pi D t}} \sum\limits_{m=-\infty}^\infty \left[ e^{-(z-2mL)^2/4Dt} - e^{-(z+2mL-2d)^2/4Dt} \right] $$
#
#  The photon current density then follows by differentiation with respect to $z$.
#==============================================================================

N0 = 10**6 #Number of photons emitted at t=0
lambdas = 2.85*10**-6 #Diffusion length in m
D = lambdas*c/6 #Diffusion constant
A = 100*10**-6*100*10**-6 #Area of segment in m^2
L = 81*10**-6 #Depth of lanex in m
l = 10.0*10**-6 #Distance from top lanex edge to segment in m
d = L-l #Distance from bottom lanex edge to segment

def n(z,t):
    '''Returns the photon density at position z and time t'''
    n0 = N0/(2*A*sqrt(pi*D*t))
    Sum = 0
    maxm = 10
    for m in range(-maxm,maxm+1):
        Sum += exp(-(z-2*m*(l+d))**2/(4*D*t))-exp(-(z+2*m*(l+d)-2*d)**2/(4*D*t))
    return n0*Sum

def particlecurrent(t):
    '''Returns the particle current (photons per second per meter^2) at the boundary z=d at time t'''
    Sum = 0
    maxm = 10
    for m in range(-maxm,maxm+1):
        am = d-2*m*L
        Sum += am*exp(-am**2/(4*D*t))
    return N0/(A*sqrt(4*pi*D*t**3))*Sum

#%%
#==============================================================================
# Plot photon density
# The function $n(z,t)$ is calculated from 1 fs to 10 ps and plotted below.
# The boundary conditions are visibly satisfied and the function approaches a
# dirac delta function for short times. It then spreads out with the total number
# of photons decreasing as they're absorbed at the boundaries.
#==============================================================================

narray = []
zarray = np.linspace(-l,d,1000)
time = [1,10,10**2,10**3,10**4]
time = np.multiply(time,10**-15) #convert to s

for i in range(len(time)):
    narray.append([])
    for z in zarray:
        narray[i].append(n(z,time[i])*10**-6)

zarray = np.multiply(zarray,10**6)

plt.subplots(figsize=(12,6))

color = ['r','g','b','c','m','y','k']
legend = []
for i in range(5):
    legend.append(str(int(time[i]*10**15))+' fs')
    plt.plot(zarray,narray[i],color=color[i],linewidth=2,label=legend[i])
plt.xlim(np.min(zarray),np.max(zarray))
plt.ylim(1.0*10**6,np.max(narray[0]))
plt.xlabel('Position (um)')
plt.ylabel('Photon Density (m^-3)')
#plt.semilogy()
plt.legend(loc=1)

#%%
#==============================================================================
# Plot photon current density
# Photon current density is then calculated at $z=d$ and plotted below as a function of time
#==============================================================================

particlecurrentarray = []
tarray = []
for t in linspace(10**-15,50*10**-12,1000):
    tarray.append(t*10**12)
    particlecurrentarray.append(particlecurrent(t))

plt.subplots(figsize=(12,6))

plt.plot(tarray,particlecurrentarray,linewidth=2)
plt.xlim(np.min(tarray),np.max(tarray))
plt.ylim(0)
plt.xlabel('time (ps)')
plt.ylabel('Photon Current at $z=d$ $(s^{-1} \cdot m^{-2})$')
#plt.semilogy()
plt.legend(loc=4)

#%%
#==============================================================================
# Integrate photon current density
# The photon current density at $z=d$ is then integrated over large times and
# multiplied by the area $A$ to determine the total number of photons absorbed
# by the CCD. This is done numerically and analytically with the function
# defined below. A plot of the fraction of photons absorbed is plotted as a
# function of time to ensure that the integral converges.
#==============================================================================

Nabs = A*quad(particlecurrent,0,400*10**-12)[0] #Total number of photons absorbed at the boundary z=d
print(Nabs/N0)

def F(t,maxm,distance):
    Sum1 = 0
    Sum2 = 0
    for m in range(-maxm,1):
        am = distance-2*m*L
        Sum1 += 1 - erf(am/sqrt(4*D*t))
    for m in range(1,maxm+1):
        am = distance-2*m*L
        Sum2 += 1 + erf(am/sqrt(4*D*t))
    return (Sum1 - Sum2)

FractionAbsArray = []
FractionAbsArrayAnalytic = []
tarray = []
for t in linspace(10**-12,50*10**-12,10000):
    tarray.append(t*10**12)
    #FractionAbsArray.append(A*quad(particlecurrent,0,t)[0]/N0)
    FractionAbsArrayAnalytic.append(F(t,100,d))

plt.subplots(figsize=(12,6))

plt.plot(tarray,FractionAbsArrayAnalytic,linewidth=2)
plt.xlim(np.min(tarray),np.max(tarray))
plt.ylim(0,1.0)
plt.xlim(0,50)
plt.xlabel('time (ps)')
plt.ylabel('Fraction Absorbed at $z=d$')
#plt.semilogy()
plt.legend(loc=4)

#%%
#==============================================================================
# Calculate number of photons absorbed as a function of d
# A function is defined to calculate the total number of photons absorbed at $z=d$ after all time as a function of $d$. The results are then plotted and found to be linear. The rather unpleasant expression defined above evidently can be approximated as (or is exactly equal to)
#
# $$N_{abs}(d) = N_0 (1 - d/L) $$
#==============================================================================

FractionAbsArrayAnalytic = []
distancearray = []

#Find the fraction of photons absorbed at z=d for various values of d ranging from 0 to L - 1 um (to avoid division by zero errors)
for distance in linspace(0,L-10**-6,100):
    Integrationtime = 10**-12
    TargetError = 10**-3
    Error = 1.0
    FractionAbsAnalytic=0
    while Error>TargetError:
        Error = abs(FractionAbsAnalytic-F(Integrationtime,100,distance))/F(Integrationtime,100,distance)
        FractionAbsAnalytic = F(Integrationtime,100,distance)
        Integrationtime *= 2
    FractionAbsArrayAnalytic.append(FractionAbsAnalytic)
    distancearray.append(distance*10**6)

plt.subplots(figsize=(12,6))

plt.plot(distancearray,FractionAbsArrayAnalytic,linewidth=2)
#plt.xlim(np.min(tarray),np.max(tarray))
#plt.ylim(0,1.0)
#plt.xlim(0,50)
plt.xlabel('Segment Distance (um)')
plt.ylabel('Fraction Absorbed by CCD')
#plt.semilogy()


# This is a ported version of a MATLAB example from the signal processing
# toolbox that showed some difference at one time between Matplotlib's and
# MATLAB's scaling of the PSD.  This differs from psd_demo3.py in that
# this uses a complex signal, so we can see that complex PSD's work properly
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab

fs = 1000
t = np.linspace(0, 0.3, 301)
A = np.array([2, 8]).reshape(-1, 1)
f = np.array([150, 140]).reshape(-1, 1)
xn = (A * np.exp(2j * np.pi * f * t)).sum(axis=0) + 5 * np.random.randn(*t.shape)

yticks = np.arange(-50, 30, 10)
xticks = np.arange(-500,550,100)
plt.subplots_adjust(hspace=0.45, wspace=0.3)
ax = plt.subplot(1, 2, 1)

plt.psd(xn, NFFT=301, Fs=fs, window=mlab.window_none, pad_to=1024,
    scale_by_freq=True)
plt.title('Periodogram')
plt.yticks(yticks)
plt.xticks(xticks)
plt.grid(True)
plt.xlim(-500, 500)

plt.subplot(1, 2, 2, sharex=ax, sharey=ax)
plt.psd(xn, NFFT=150, Fs=fs, window=mlab.window_none, noverlap=75, pad_to=512,
    scale_by_freq=True)
plt.title('Welch')
plt.xticks(xticks)
plt.yticks(yticks)
plt.ylabel('')
plt.grid(True)
plt.xlim(-500, 500)

plt.show()


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

import numpy as np
import sktensor as skt

def rmse(Y1,Y2):
    return np.sqrt(np.linalg.norm(Y1-Y2)**2/Y2.size)

class Kernel(object):
    def __init__(self,name,param=None, normalize=False):
        assert name in ['rbf','linear','poly'], 'kernel not implemented'
        if name == 'rbf':
            self.f = lambda x,y: np.exp(-1*param * np.linalg.norm(x-y)**2)
            self.param = param
            self.name = name

        if name == 'linear':
            self.f = np.dot
            self.param = param
            self.name = name

        if name == 'poly':
            self.f = lambda x,y: (param[1] + x.T.dot(y))**param[0]
            self.param = param
            self.name = name
        self.normalize = normalize

    def __call__(self,x,y):
        if self.normalize:
            z = np.sqrt(self.f(x,x)*self.f(y,y))
        else:
            z = 1
        return self.f(x,y) / z

    def __str__(self):
        return self.name + ' (param=%s, norm=%s)' % (str(self.param), str(self.normalize))

    def gram_matrix(self,X,X_test=None):
        if isinstance(X,skt.dtensor):
            X = X.unfold(0)
        if X_test is None:
            n = X.shape[0]
            K = np.zeros([n,n])
            for i in range(n):
                for j in range(i,n):
                    tmp = self(X[i,:],X[j,:])
                    K[i,j] = tmp
                    K[j,i] = tmp
        else:
            if isinstance(X_test,skt.dtensor):
                X_test = X_test.unfold(0)
            K = np.zeros([X_test.shape[0], X.shape[0]])
            for i in range(X_test.shape[0]):
                for j in range(X.shape[0]):
                    K[i,j] = self(X_test[i,:],X[j,:])
        return K

def rbf_kernel(gamma):
    return lambda x,y: np.exp(-1*gamma * np.linalg.norm(x-y)**2)


# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import numpy as np
import pandas as pd
from fclib.evaluation.evaluation_utils import MAPE, sMAPE, pinball_loss

y = np.array([1, 2, 3])
yhat = np.array([1.1, 2.2, 3.3])
TOLERANCE = 1e-5

def test_MAPE():
    assert abs(MAPE(yhat, y) - 0.1) < TOLERANCE

def test_sMAPE():
    assert abs(sMAPE(yhat, y) - 0.04761904) < TOLERANCE

def test_pinball_loss():
    df = pd.DataFrame({"yhat": yhat, "y": y})
    assert all(abs(pinball_loss(df.yhat, df.y, 0.5) - pd.Series([0.05, 0.1, 0.15])) < TOLERANCE)


import unittest
import sympy as sp
import numpy as np

import sys
import os
sys.path.append('.')

import stats.methods as methods
from stats.utils import *

class TestBasicSearch(unittest.TestCase):

    def setUp(self):
        self.num_vals = 20          # number of source values

    def test_quadratic(self):
        sym_x, sym_y = sp.symbols('x y')
        sym_a, sym_b, sym_c = sp.symbols('a b c')
        sym_expr = sp.sympify('a*(x**2) + b*x + c')
        sym_expr_delta = sp.sympify('y - (a*(x**2) + b*x + c)')

        min_x = 1
        max_x = 20

        real_a = 2            # real 'a' value of source distribution
        real_b = 3            # real 'b' value of source distiribution
        real_c = 5            # real 'c' value of source distiribution

        # real X values without errors
        x = np.linspace(min_x, max_x,
                        self.num_vals, dtype=np.float)

        # real Y values without errors
        y = np.vectorize(
            sp.lambdify(
                sym_x, sym_expr.subs(
                    {sym_a: real_a,
                     sym_b: real_b,
                     sym_c: real_c}
                ),
                'numpy'
            )
        )(x)

        third_len = self.num_vals // 3

        # get base values as half-distant pairs of values
        base_values_dist = {
            sym_x: (x[0], x[third_len], x[third_len * 2]),
            sym_y: (y[0], y[third_len], y[third_len * 2])
        }

        # find params with basic method
        basic_a, basic_b, basic_c = methods.search_basic(
            delta_expression=sym_expr_delta,
            parameters=(sym_a, sym_b, sym_c),
            values=base_values_dist
        )

        self.assertAlmostEqual(real_a, basic_a, places=5)
        self.assertAlmostEqual(real_b, basic_b, places=5)
        self.assertAlmostEqual(real_c, basic_c, places=5)


#!/usr/bin/env python

"""
This example shows how to work with coordinate transformations, curvilinear
coordinates and a little bit with differential geometry.

It takes polar, cylindrical, spherical, rotating disk coordinates and others
and calculates all kinds of interesting properties, like Jacobian, metric
tensor, Laplace operator, ...
"""

from sympy import var, sin, cos, pprint, Matrix, eye, trigsimp, Eq, \
    Function, simplify, sinh, cosh, expand, symbols

def laplace(f, g_inv, g_det, X):
    """
    Calculates Laplace(f), using the inverse metric g_inv, the determinant of
    the metric g_det, all in variables X.
    """
    r = 0
    for i in range(len(X)):
        for j in range(len(X)):
            r += g_inv[i, j]*f.diff(X[i]).diff(X[j])
    for sigma in range(len(X)):
        for alpha in range(len(X)):
            r += g_det.diff(X[sigma]) * g_inv[sigma, alpha] * \
                f.diff(X[alpha]) / (2*g_det)
    return r

def transform(name, X, Y, *, g_correct=None, recursive=False):
    """
    Transforms from cartesian coordinates X to any curvilinear coordinates Y.

    It printing useful information, like Jacobian, metric tensor, determinant
    of metric, Laplace operator in the new coordinates, ...

    g_correct ... if not None, it will be taken as the metric --- this is
                  useful if sympy's trigsimp() is not powerful enough to
                  simplify the metric so that it is usable for later
                  calculation. Leave it as None, only if the metric that
                  transform() prints is not simplified, you can help it by
                  specifying the correct one.

    recursive ... apply recursive trigonometric simplification (use only when
                  needed, as it is an expensive operation)
    """
    print("_"*80)
    print("Transformation:", name)
    for x, y in zip(X, Y):
        pprint(Eq(y, x))
    J = X.jacobian(Y)
    print("Jacobian:")
    pprint(J)
    g = J.T*eye(J.shape[0])*J

    g = g.applyfunc(expand)
    print("metric tensor g_{ij}:")
    pprint(g)
    if g_correct is not None:
        g = g_correct
        print("metric tensor g_{ij} specified by hand:")
        pprint(g)
    print("inverse metric tensor g^{ij}:")
    g_inv = g.inv(method="ADJ")
    g_inv = g_inv.applyfunc(simplify)
    pprint(g_inv)
    print("det g_{ij}:")
    g_det = g.det()
    pprint(g_det)
    f = Function("f")(*list(Y))
    print("Laplace:")
    pprint(laplace(f, g_inv, g_det, Y))

def main():
    mu, nu, rho, theta, phi, sigma, tau, a, t, x, y, z, w = symbols(
        "mu, nu, rho, theta, phi, sigma, tau, a, t, x, y, z, w")

    transform("polar", Matrix([rho*cos(phi), rho*sin(phi)]), [rho, phi])

    transform("cylindrical", Matrix([rho*cos(phi), rho*sin(phi), z]),
              [rho, phi, z])

    transform("spherical",
              Matrix([rho*sin(theta)*cos(phi), rho*sin(theta)*sin(phi),
                      rho*cos(theta)]),
              [rho, theta, phi],
              recursive=True
              )

    transform("rotating disk",
              Matrix([t,
                      x*cos(w*t) - y*sin(w*t),
                      x*sin(w*t) + y*cos(w*t),
                      z]),
              [t, x, y, z])

    transform("parabolic",
              Matrix([sigma*tau, (tau**2 - sigma**2) / 2]),
              [sigma, tau])

    transform("bipolar",
            Matrix([a*sinh(tau)/(cosh(tau)-cos(sigma)),
                a*sin(sigma)/(cosh(tau)-cos(sigma))]),
            [sigma, tau]
            )

    transform("elliptic",
              Matrix([a*cosh(mu)*cos(nu), a*sinh(mu)*sin(nu)]),
              [mu, nu]
              )

if __name__ == "__main__":
    main()


import numpy as np

def second_differences(xs, *, direction):
    """Compute second differences. Returns three numpy arrays: the first
    and second differences, as well as a truncated version of the input
    array so that the positions at each index match up.
    """
    xs = np.array(xs)
    if direction == 'forward':
        trunc_xs = xs[:-2]
        dxs = xs[1:] - xs[:-1]
        d2xs = dxs[1:] - dxs[:-1]
        return trunc_xs, dxs[:-1], d2xs
    elif direction == 'central':
        trunc_xs = xs[1:-1]
        dxs = (xs[2:] - xs[:-2]) / 2
        d2xs = xs[2:] - 2*xs[1:-1] + xs[:-2]
        return trunc_xs, dxs, d2xs
    else:
        raise NotImplementedError('direction must be forward or central')

def accelerate(xs, **kwargs):
    iterations = kwargs.pop('iterations', 1)
    direction = kwargs.setdefault('direction', 'forward')
    strength = kwargs.setdefault('strength', 1)

    if not isinstance(iterations, int) or iterations < 1:
        raise TypeError('The number of iterations must be a positive integer.')

    if iterations > 1:
        return accelerate(
            accelerate(xs, **kwargs), iterations=iterations-1, **kwargs
        )

    xs, dxs, d2xs = second_differences(xs, direction=direction)
    correction = np.where(
        (dxs == 0) & (d2xs == 0),
        0,
        np.divide(dxs ** 2, d2xs)
    )
    return xs - strength * correction


# implementation of linear kalman filter using 2D constant acceleration model

# state matrix:             2D x-y position, velocity and acceleration in x and y axis (6 x 1)
# input matrix:             --None--
# measurement matrix:       2D x-y position and imu acceleration in x and y axis (4 x 1)

import math
import matplotlib.pyplot as plt
import numpy as np
from scipy.sparse.linalg import expm
from scipy.linalg import sqrtm

# initalize global variables
dt = 0.01  # seconds
N = int(input('Enter number of samples : '))  # number of samples
qc = 0.1  # process noise magnitude

z_noise = 1  # measurement noise magnitude

# prior mean
x_0 = np.array([[0.0],  # x position
                [0.0],  # y position
                [0.0],  # x velocity
                [0.0],  # y velocity
                [0.0],  # x acceleration
                [0.0]  # y acceleration
                ])

# prior covariance
p_0 = np.array([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                [0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
                [0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
                [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]])

# a matrix - continuous time motion model
a = np.array([[0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
              [0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])

a = expm(dt * a)
gamma = np.array([[0.0], [0.0], [0.0], [0.0], [1.0], [1.0]])

# q matrix - continuous time process noise covariance
q = qc * gamma @ np.transpose(gamma)
q_euler = dt * q

# h matrix - measurement model
h = np.array([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
              [0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]])

# r matrix - measurement noise covariance
r = np.array([[0.010, 0.0, 0.0, 0.0],
              [0.0, 0.015, 0.0, 0.0],
              [0.0, 0.0, 0.1, 0.0],
              [0.0, 0.0, 0.0, 0.1]])**2

# main program
def main():
    show_final = int(input('Display final result? (No/Yes = 0/1) : '))
    show_animation = int(
        input('Show animation of filter working? (No/Yes = 0/1) : '))
    if show_animation == 1:
        show_ellipse = int(
            input('Display covariance ellipses in animation? (No/Yes = 0/1) : '))
    else:
        show_ellipse = 0
    x_est = x_0
    p_est = p_0
    x_true_cat = np.array([x_0[0, 0], x_0[1, 0]])
    x_est_cat = np.array([x_0[0, 0], x_0[1, 0]])
    z_cat = np.array([x_0[0, 0], x_0[1, 0]])
    for i in range(N):
        z, x_true = gen_measurement(i)
        if i == (N - 1) and show_final == 1:
            show_final_flag = 1
        else:
            show_final_flag = 0
        postpross(x_true, x_true_cat, x_est, p_est,
                  x_est_cat, z_cat, z, show_animation, show_ellipse, show_final_flag)
        x_est, p_est = kalman_filter(x_est, p_est, z)
        x_true_cat = np.vstack((x_true_cat, np.transpose(x_true[0:2])))
        z_cat = np.vstack((z_cat, np.transpose(z[0:2])))
        x_est_cat = np.vstack((x_est_cat, np.transpose(x_est[0:2])))
    print('KF Over')

# generate ground truth position x_true and noisy position z
def gen_measurement(i):
    x_true = np.array([[i], [i], [0.0], [0.0]])
    z = x_true + z_noise * np.random.randn(4, 1)
    return z, x_true

# linear kalman filter prediction step
def linear_prediction(a, x_hat, p_hat, q):
    x_pred = a @ x_hat
    p_pred = a @ p_hat @ np.transpose(a) + q
    return x_pred, p_pred

# linear kalman filter update step
def linear_update(x_hat, p_hat, y, h, r):
    s = h @ p_hat @ np.transpose(h) + r
    k = p_hat @ np.transpose(h) @ np.linalg.pinv(s)
    v = y - h @ x_hat

    x_upd = x_hat + k @ v
    p_upd = p_hat - k @ s @ np.transpose(k)
    return x_upd, p_upd

# linear kalman filter
def kalman_filter(x, p, z):
    x_pred, p_pred = linear_prediction(a, x, p, q_euler)
    x_upd, p_upd = linear_update(x_pred, p_pred, z, h, r)
    return x_upd, p_upd

# postprocessing
def plot_ellipse(x_est, p_est):
    phi = np.linspace(0, 2 * math.pi, 100)
    p_ellipse = np.array(
        [[p_est[0, 0], p_est[0, 1]], [p_est[1, 0], p_est[1, 1]]])
    x0 = 3 * sqrtm(p_ellipse)
    xy_1 = np.array([])
    xy_2 = np.array([])
    for i in range(100):
        arr = np.array([[math.sin(phi[i])], [math.cos(phi[i])]])
        arr = x0 @ arr
        xy_1 = np.hstack([xy_1, arr[0]])
        xy_2 = np.hstack([xy_2, arr[1]])
    plt.plot(xy_1 + x_est[0], xy_2 + x_est[1], 'r')
    plt.pause(0.00001)

def plot_final(x_true_cat, x_est_cat, z_cat):
    fig = plt.figure()
    f = fig.add_subplot(111)
    f.plot(x_true_cat[0:, 0], x_true_cat[0:, 1], 'r', label='True Position')
    f.plot(x_est_cat[0:, 0], x_est_cat[0:, 1], 'b', label='Estimated Position')
    f.plot(z_cat[0:, 0], z_cat[0:, 1], '+g', label='Noisy Measurements')
    f.set_xlabel('x [m]')
    f.set_ylabel('y [m]')
    f.set_title('Linear Kalman Filter - Constant Acceleration Model')
    f.legend(loc='upper left', shadow=True, fontsize='large')
    plt.grid(True)
    plt.show()

def plot_animation(x_true, x_est, z):
    plt.plot(x_true[0], x_true[1], '.r')
    plt.plot(x_est[0], x_est[1], '.b')
    plt.plot(z[0], z[1], '+g')
    plt.grid(True)
    plt.pause(0.001)

def postpross(x_true, x_true_cat, x_est, p_est, x_est_cat, z_cat, z, show_animation, show_ellipse, show_final_flag):
    if show_animation == 1:
        plot_animation(x_true, x_est, z)
        if show_ellipse == 1:
            plot_ellipse(x_est[0:2], p_est)
    if show_final_flag == 1:
        plot_final(x_true_cat, x_est_cat, z_cat)

main()


import pandas as pd
import numpy as np

class topsis():

    def __init__(self,input,weights,impacts):

        self.input_file=input
        self.w=weights
        self.imp=impacts

    def result(self):
        try:
            df=pd.read_csv(self.input_file)
        except:
            err=['Error: File '+str(self.input_file)+' Not Found']
            print(err)
            exit()

        if any(True for char in self.w if char in '@^! #%$&)(+*-="'):
            err=['Error: Weights are not separated by a comma']
            print(err)
            exit()
        else:
            weight = self.w.split(",")

        if any(True for char in self.imp if char in '@^! #%$&)(*="'):
            err=['Error: Impacts are not given correctly']
            print(err)
            exit()
        else:
            impacts = self.imp.split(",")

        for imp in impacts:
            if(imp=='+' or imp=='-'):
                continue
            else:
                print("Impacts must be either positive or negative!")
                exit()

        data= df.drop(df.columns[[0]], axis = 1)

        if len(weight)!=len(impacts) or len(impacts)!=data.shape[1] or len(weight)!=data.shape[1]:
            err=['Error: Wrong number of inputs in weight/impacts']
            print(err)
            exit()

        if(df.shape[1]<3):
            err=['Error: The number of columns in the given input file are not equal to or more than 3']
            print(err)
            exit()

        if data.applymap(np.isreal).all(1).sum() != data.shape[0]:
            err=['Error: Non-numeric column values occur']
            print(err)
            exit()

        for col in data.columns:
            data[col] = data[col]/np.sqrt(np.sum(np.square(data[col])))

        for i,col in enumerate(data.columns):
            data[col]=data[col]*int(weight[i])

        best=[]
        worst=[]
        j=0

        for i in impacts:
            if(i =="+"):
                best.append(data.iloc[:,[j]].max()[0])
                worst.append(data.iloc[:,[j]].min()[0])
                j=j+1
            elif (i=="-"):
                best.append(data.iloc[:,[j]].min()[0])
                worst.append(data.iloc[:,[j]].max()[0])
                j=j+1
            else:
                error =["Error: The 'impacts' input is wrong."]
                print(error)
                exit()

        ideal_best = np.array(best)
        ideal_worst = np.array(worst)

        def Euclidean(ideal,row):
            return np.sqrt(np.sum(np.square(ideal-row)))

        Splus = np.array([Euclidean(ideal_best,row) for row in data.values ])
        Sminus = np.array([Euclidean(ideal_worst,row) for row in data.values ])

        PScore = Sminus/(Sminus+Splus)
        data['Topsis Score'] = PScore
        df['Topsis Score']= PScore

        data["Rank"] = data["Topsis Score"].rank(ascending=False)
        df["Rank"] = data["Rank"]

        return df


import numpy as np
from scipy.special import logsumexp

from prml.nn.function import Function

class LogSoftmax(Function):
    def _forward(self, x):
        self.output = x - logsumexp(x, axis=-1, keepdims=True)
        return self.output

    def _backward(self, delta, x):
        softmax = np.exp(self.output)
        dx = delta - softmax * delta.sum(axis=-1, keepdims=True)
        return dx

def log_softmax(x):
    return LogSoftmax().forward(x)


"""
Procrustes analysis with Python
https://en.wikipedia.org/wiki/Procrustes_analysis
"""

# Get [proper] multi-dimensional array support
import numpy as np

# Ordinary Procrustes Analysis (alignment to reference)
def opa(a, b):

	# Compute centroid (ori_avg/ori_len)
	aT = a.mean(0)
	bT = b.mean(0)

	# Translate point cloud around own origin (0)
	A = a - aT
	B = b - bT

	# Compute quadratic mean of point cloud
	aS = np.sum(A * A)**.5
	bS = np.sum(B * B)**.5

	# Get scale invariant unit vector (ori/ori_rms=0_to_1_rmsd_norm_coords)
	A /= aS
	B /= bS

	# Compute the covariance matrix from escalar product of sets
	C = np.dot(B.T, A)

	# Decompose point cloud into orthonormal bases (U, V being U transposed as in 'np.fliplr(np.rot90(U))') and singular values (S/_)
	U, _, V = np.linalg.svd(C)

	# Compute optimal rotation matrix from unitary matrices (left U and transposed right V singular vectors)
	aR = np.dot(U, V)

	# Enforce clockwise rotation matrix by disabling svd 'best-fit' reflections (the UV matrix R determinant should always be +1)
	if np.linalg.det(aR) < 0:

		# Flip sign on second row
		V[1] *= -1

		# Rebuild rotation matrix (no need to rerun if condition skipped)
		aR = np.dot(U, V)

	# Get scale multiplier factor so we can zoom in mutable shape into reference (rotation is already computed so we can leave the norm space)
	aS = aS / bS

	# Compute translation distance from mutable shape to reference (aT - bT_fitted_to_a_space)
	aT = aT - (bT.dot(aR) * aS)

	# Rotate mutable B unto fixed A (svd helps but the method for optimal rotation matrix U is Kabsch's)
	B_ = B.dot(aR)

	# Compute Procrustes distance from RMSD (as per Kabsch 'A-BR' instead of dummy 'A-B')
	aD = (np.sum((A - B_)**2) / len(a))**.5

	# Output full rst transformation tuple and Kabsch RMSD
	return aR, aS, aT, aD

# Generalized Procrustes Analysis (mean shape)
def gpa(v, n=-1):

	# Compute unknown mean shape prototype or fit everything to nth shape
	p = avg(v) if n < 0 else v[n]

	# Get shape collection length
	l = len(v)

	# Initialize storage arrays (one per shape)
	r, s, t, d = np.ndarray((4, l), object)

	# Get procrustes components for every shape against the reference (first one)
	for i in range(l):
		r[i], s[i], t[i], d[i] = opa(p, v[i])

	# Return per-shape transforms collection (including average shape and disparity)
	return r, s, t, d

# Average shape from n point clouds
def avg(v):

	# Make a shape collection copy (we don't want to overwrite the original data) while making sure is a well-formatted one (numpy)
	v = np.copy(v)

	# Get shape collection length
	l = len(v)

	# Initialize storage arrays (one per shape) with type-agnostic lists for flexible assignment
	R, S, T = [list(np.zeros(l)) for _ in range(3)]

	# Avg 1/2 (sum): Iterate every possible match between shapes
	for i, j in np.ndindex(l, l):

		# Compute transform components for every permutation
		r, s, t, _ = opa(v[i], v[j])

		# Add up [A]ngle (scalar) from all [R]otations (matrix) carried against every other shape
		R[j] += np.arccos(min(1, max(-1, np.trace(r[:1])))) * np.sign(r[1][0])

		# Get combined scale and translation values for every shape
		S[j] += s
		T[j] += t

	# Avg 2/2 (div): Apply average transformations to shapes
	for i in range(l):

		# Average rotation 'theta' angle for every shape and rebuild rotation matrix
		a = R[i] / l
		r = [np.cos(a), -np.sin(a)], [np.sin(a), np.cos(a)]

		# Transform shape collection (so we can compute the prototype average from it)
		v[i] = v[i].dot(r) * (S[i] / l) + (T[i] / l)

	# Return components and shape prototype (useful as virtual reference) from 'procrustes mean' (shapes are optimally fitted so this is a safe estimation)
	return v.mean(0)


# --------------------------------
# Name: Roberto Sanchez
# Date: October 14, 2017
# Assignment 03 - Part 3
# --------------------------------
import numpy as np
import matplotlib.pyplot as plt
def CalcPoisson(rounds):
    probability = 1/216
    lamda = probability * rounds
    PoissonNum = []
    e = 2.718281

    for x in range (17):
        lamda2 = np.power(lamda,x)
        e2 = np.power(e,lamda)
        factorial = np.math.factorial(x)
        Poisson = (int)(lamda2*rounds/factorial*e2)
        for i in range(Poisson):
            PoissonNum.append(x)
    #This prints the graph
    b = range(-1,16)
    h1, bin_edges = np.histogram(PoissonNum, bins = b)
    b1 = bin_edges[0:16]

    #plot
    plt.stem(b1, h1/rounds)
    plt.title("Probability Mass Function")
    plt.ylabel("Probability of success")
    plt.xlabel("Number of successes in n = 1000 trials")

    #show graph
    plt.show()
CalcPoisson(1000)


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from scipy.spatial import Voronoi
import math
# https://stackoverflow.com/questions/48253800/shading-a-map-according-to-data-for-a-set-of-coordinates

def generate_voronoi_diagram(width, height, sparse_locations, sparse_data):
    '''
    sparse_locations should be list of centers with associated measurement locations (so for example one row could be [10,24])
    sparse_data should be measurements at sensor locations
    '''
    arr = np.zeros((width, height))
    imgx,imgy = width, height
    num_cells=np.shape(sparse_locations)[0]

    nx = sparse_locations[:,0]
    ny = sparse_locations[:,1]
    nr = list(range(num_cells))
    ng = nr
    nb = nr

    for y in range(imgy):
        for x in range(imgx):
            dmin = math.hypot(imgx-1, imgy-1)
            j = -1
            for i in range(num_cells):
                d = math.hypot(nx[i]-x, ny[i]-y)
                if d < dmin:
                    dmin = d
                    j = i
            arr[x, y] = sparse_data[j]

    plt.imshow(arr)
    plt.show()

    return arr

def generate_weighted_voronoi_diagram(width, height, sparse_locations, sparse_data):
    '''
    sparse_locations should be list of centers with associated measurement locations (so for example one row could be [10,24])
    sparse_data should be measurements at sensor locations
    '''
    arr = np.zeros((width, height))
    imgx,imgy = width, height
    num_cells=np.shape(sparse_locations)[0]

    nx = sparse_locations[:,0]
    ny = sparse_locations[:,1]
    nr = list(range(num_cells))
    ng = nr
    nb = nr

    weighted_sparse_data = sparse_data/np.max(sparse_data)

    for y in range(imgy):
        for x in range(imgx):
            dmin = math.hypot(imgx-1, imgy-1)
            j = -1
            for i in range(num_cells):
                d = math.hypot(nx[i]-x, ny[i]-y)
                if d < weighted_sparse_data[i]*dmin:
                    dmin = d
                    j = i
            arr[x, y] = sparse_data[j]

    plt.imshow(arr)
    plt.show()

    return arr

if __name__ == '__main__':
    # get random points
    np.random.seed(1234)

    # Using other (slower method)
    sparse_locations = np.random.randint(256,size=(15,2)) # 15 sensors
    sparse_data = np.random.uniform(low=0.0, high=1.0, size=(15,))

    input_array = generate_voronoi_diagram(256,256,sparse_locations,sparse_data)
    input_array = generate_weighted_voronoi_diagram(256,256,sparse_locations,sparse_data)


from numpy import *
from sigmoid import sigmoid

def computeCost(theta, X, y):
	# Computes the cost of using theta as the parameter
	# for logistic regression.

    m = X.shape[0] # number of training examples
    J = 0

    for i in range(m):
        val = dot(X[i,:], theta)
        J += -y[i]*log(sigmoid(val))-(1-y[i])*log(1-sigmoid(val))

    J /= m

	# =============================================================

    return J


'''
The np.random module and Bernoulli trials
100xp
You can think of a Bernoulli trial as a flip of a possibly biased coin. Specifically, each coin flip has a probability p
 of landing heads (success) and probability 1−p
 of landing tails (failure). In this exercise, you will write a function to perform n Bernoulli trials, perform_bernoulli_trials(n, p), which returns the number of successes out of n Bernoulli trials, each of which has probability p of success. To perform each Bernoulli trial, use the np.random.random() function, which returns a random number between zero and one.

Instructions
-Define a function with signature perform_bernoulli_trials(n, p).
    -Initialize to zero a variable n_success the counter of Trues, which are Bernoulli trial successes.
    -Write a for loop where you perform a Bernoulli trial in each iteration and increment the number of success if the result is True. Perform n iterations by looping over range(n).
    -To perform a Bernoulli trial, choose a random number between zero and one using np.random.random(). If the number you chose is less than p, increment n_success (use the += 1 operator to achieve this).
    -The function returns the number of successes n_success.
'''
import numpy as np

def perform_bernoulli_trials(n, p):
    """Perform n Bernoulli trials with success probability p
    and return number of successes."""
    # Initialize number of successes: n_success
    n_success = 0

    # Perform trials
    for i in range(n):
        # Choose random number between zero and one: random_number
        random_number = np.random.random()

        # If less than p, it's a success so add one to n_success
        if random_number < p:
            n_success += 1

    return n_success

print(perform_bernoulli_trials(10000, 0.65))


###________________________ 2nd-Order-Free-Response ________________________###

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

matplotlib.rcParams.update({'font.size': 22})

##__________ Functions for dumping characteristic cases __________##
def undumped(wn, x0, x_dot0, t):
    return x0 * np.cos(wn * t) + x_dot0 / wn * np.sin(wn * t)

def underdumped(xi, wn, x0, x_dot0, t):

    wd = wn * np.sqrt(1 - xi**2)

    x = (
        np.exp(-xi*wn*t) *
        (
            x0 * np.cos(wd * t) +
            (xi*wn*x0 + x_dot0) / wd * np.sin(wd * t)
        )
    )
    return x

def critically_dumped(wn, x0, x_dot0, t):
    return np.exp(-wn*t) * (x0 * (1 + wn * t) + x_dot0 * t)

def overdumped(xi, wn, x0, x_dot0, t):
    a = xi * wn + wn * np.sqrt(xi**2 - 1)
    b = xi * wn - wn * np.sqrt(xi**2 - 1)

    x = (
        (a * x0 + x_dot0) / (a - b) * np.exp(-b*t) -
        (b * x0 + x_dot0) / (a - b) * np.exp(-a*t)
        )
    return x

##__________ 2nd order free response __________##
def plot_2order_free_resp(xi, wn, x0, x_dot0):

    t = np.linspace(0, 10, 1000)

    # Calculate selected
    if np.isclose(xi, 0):
        x = undumped(wn, x0, x_dot0, t)
    elif np.isclose(xi, 1):
        x = critically_dumped(wn, x0, x_dot0, t)
    elif 0 < xi < 1:
        x = underdumped(xi, wn, x0, x_dot0, t)
    else:
        x = overdumped(xi, wn, x0, x_dot0, t)

    # Plot selected
    plt.figure(figsize=(15, 8))
    plt.plot(t, x, ls='-', lw=2, c='#b30000', label=f"$\\xi={xi:.2f}$")

    # Critical dumping
    x = critically_dumped(wn, x0, x_dot0, t)
    plt.plot(t, x, ls='--', lw=4, alpha=0.7, c='#02818a', label="$\\xi=1.00$")

    # No dumping
    x = undumped(wn, x0, x_dot0, t)

    # Formatting
    plt.title("$\omega_n$ = {}, $x_0$ = {}, $\\dotx_0$ = {}".format(wn, x0, x_dot0))
    plt.plot(t, x, ls='-', lw=4, alpha=0.5, c='#0570b0', label="$\\xi=0.00$")

    plt.ylim(-1, 1)
    plt.xlim(0,10)
    plt.grid()
    plt.xlabel('t')
    plt.ylabel('x')
    plt.legend(loc='upper right')

for xii in [1.5, 1.85, 2.5]:
# for xii in [0.00, 1.00, 2.50]:
    for wnn in [1, 3, 5]:
        for x00 in [-1, -0.5, 0]:
            for x_dot00 in [1.5, 3.6, 4.5]:
                plot_2order_free_resp(xii, wnn, x00, x_dot00)


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec  # for unequal plot boxes
import scipy.optimize

# define fitting function
def GaussPolyBase(f, a, b, c, P, fp, fw):
    return a + b*f + c*f*f + P*np.exp(-0.5*((f-fp)/fw)**2)

# read in spectrum from data file
# f=frequency, s=signal, ds=s uncertainty
f, s, ds = np.loadtxt("Spectrum.txt", skiprows=4, unpack=True)

# initial guesses for fitting parameters
a0, b0, c0 = 60., -3., 0.
P0, fp0, fw0 = 80., 11., 2.

# fit data using SciPy's Levenberg-Marquart method
nlfit, nlpcov = scipy.optimize.curve_fit(GaussPolyBase,
                f, s, p0=[a0, b0, c0, P0, fp0, fw0], sigma=ds)

# unpack fitting parameters
a, b, c, P, fp, fw = nlfit
# unpack uncertainties in fitting parameters from diagonal
# of covariance matrix
da, db, dc, dP, dfp, dfw = \
          [np.sqrt(nlpcov[j,j]) for j in range(nlfit.size)]

# create fitting function from fitted parameters
f_fit = np.linspace(0.0, 25., 128)
s_fit = GaussPolyBase(f_fit, a, b, c, P, fp, fw)

# Calculate residuals and reduced chi squared
resids = s - GaussPolyBase(f, a, b, c, P, fp, fw)
redchisqr = ((resids/ds)**2).sum()/float(f.size-6)

# Create figure window to plot data
fig = plt.figure(1, figsize=(8,8))
gs = gridspec.GridSpec(2, 1, height_ratios=[6, 2])

# Top plot: data and fit
ax1 = fig.add_subplot(gs[0])
ax1.plot(f_fit, s_fit)
ax1.errorbar(f, s, yerr=ds, fmt='or', ecolor='black')
ax1.set_xlabel('frequency (THz)')
ax1.set_ylabel('absorption (arb units)')
ax1.text(0.7, 0.95, 'a = {0:0.1f}$\pm${1:0.1f}'
         .format(a, da), transform = ax1.transAxes)
ax1.text(0.7, 0.90, 'b = {0:0.2f}$\pm${1:0.2f}'
         .format(b, db), transform = ax1.transAxes)
ax1.text(0.7, 0.85, 'c = {0:0.2f}$\pm${1:0.2f}'
         .format(c, dc), transform = ax1.transAxes)
ax1.text(0.7, 0.80, 'P = {0:0.1f}$\pm${1:0.1f}'
         .format(P, dP), transform = ax1.transAxes)
ax1.text(0.7, 0.75, 'fp = {0:0.1f}$\pm${1:0.1f}'
         .format(fp, dfp), transform = ax1.transAxes)
ax1.text(0.7, 0.70, 'fw = {0:0.1f}$\pm${1:0.1f}'
         .format(fw, dfw), transform = ax1.transAxes)
ax1.text(0.7, 0.60, '$\chi_r^2$ = {0:0.2f}'
         .format(redchisqr),transform = ax1.transAxes)
ax1.set_title('$s(f) = a + bf + cf^2 + P\, e^{-(f-f_p)^2/2f_w^2}$')

# Bottom plot: residuals
ax2 = fig.add_subplot(gs[1])
ax2.errorbar(f, resids, yerr = ds, ecolor="black", fmt="ro")
ax2.axhline(color="gray", zorder=-1)
ax2.set_xlabel('frequency (THz)')
ax2.set_ylabel('residuals')
ax2.set_ylim(-20, 20)
ax2.set_yticks((-20, 0, 20))

plt.show()
plt.savefig("FitSpectrum.pdf")


__author__ = 'dixon'
from scipy.stats import norm
import scipy.stats as st
import numpy as np
import pandas as pd
from math import *

def bsformula( callput, S0, K, r, T, sigma, q=0.):
    """
    :param callput: Indicates if the option is a Call or Put option
    :param S0: Stock price
    :param K: Strike price
    :param r: Risk-free rate
    :param T: Time to expiration
    :param sigma: Volatility
    :param q: Dividend rate
    :return: Value of the option, its Delta, its Vega
    """
    d1=(log(float(S0)/K)+((r-q)+sigma*sigma/2.)*T)/(sigma*sqrt(T))
    d2=d1-sigma*sqrt(T)
    if callput==1:
        optionValue=S0*exp(-q*T)*norm.cdf(d1)-K*exp(-r*T)*norm.cdf(d2)
        delta=norm.cdf(d1)
    elif callput==-1:
        optionValue=K*exp(-r*T)*norm.cdf(-d2)-S0*exp(-q*T)*norm.cdf(-d1)
        delta=-norm.cdf(-d1)

    vega=S0*sqrt(T)*norm.pdf(d1)
    return optionValue,delta,vega

#Density derivative
def dpdf(x):
    v = 1
    return -x*np.exp(-x**2/(2.0*v**2))/(v**3*np.sqrt(2.0*np.pi))

def generalizedGreeks(cp, s, k, t, v, rfInt, divInt):
        """ Price an option using the Black-Scholes model.
        cp: +1/-1 for call/put
        s: initial stock price
        k: strike price
        t: expiration time
        v: volatility
        rfInt: deterministic risk-free rate integrated between 0 and t
        divInt: deterministic dividend integrated between 0 and t
        """

        d1 = (np.log(s/k)+(rfInt-divInt+0.5*v*v*t))/(v*np.sqrt(t))
        d2 = d1 - v*np.sqrt(t)

        Nd1 = st.norm.cdf(cp*d1)
        Nd2 = st.norm.cdf(cp*d2)

        discountFactor = np.exp(-rfInt)
        forwardFactor = np.exp(-divInt)
        avgDiv = divInt/t
        avgRf = rfInt/t

        optprice = (cp*s*forwardFactor*Nd1) - (cp*k*discountFactor*Nd2)

        delta = cp*Nd1
        vega  = s*np.sqrt(t)*st.norm.pdf(d1)
        delta_k = -s*forwardFactor*Nd1/(v*np.sqrt(t)*k) - cp*discountFactor*Nd2 + k*discountFactor*Nd2/(v*np.sqrt(t)*k)

        gamma_k = s*forwardFactor/((v*np.sqrt(t)*k)**2)*(Nd1*v*np.sqrt(t) + cp*dpdf(cp*d1)) - k*discountFactor/((v*np.sqrt(t)*k)**2)*(Nd2*v*np.sqrt(t) + cp*dpdf(cp*d2)) +  2.0*discountFactor*Nd2/(v*np.sqrt(t)*k)

        dd1_dt = (avgRf-avgDiv+0.5*v*v)/(v*np.sqrt(t)) - 0.5*(np.log(s/k)+(rfInt-divInt+0.5*v*v*t))/(v*v*t**(3/2))
        dd2_dt = dd1_dt - 0.5*v/np.sqrt(t)
        delta_T = avgRf*cp*k*discountFactor*Nd2 - avgDiv*cp*s*forwardFactor*Nd1 + s*forwardFactor*Nd1*dd1_dt- k*discountFactor*Nd2*dd2_dt

        return optprice, delta, vega, delta_k, gamma_k, delta_T

#Change of variable for constant discount and dividend short rate
def changeOfVariable_BS(s, t, q, r):

  factorPrice = np.exp( - q*t )

  divSpread = (q-r)*t

  factorStrike = np.exp( divSpread )
  adjustedStrike = np.multiply(s, factorStrike)
  return adjustedStrike, factorPrice

def bs_price(cp, s, k, rf, t, v, div):
        """ Price an option using the Black-Scholes model.
        cp: +1/-1 for call/put
        s: initial stock price
        k: strike price
        t: expiration time
        v: volatility
        rf: risk-free rate
        div: dividend
        """

        d1 = (np.log(s/k)+(rf-div+0.5*v*v)*t)/(v*np.sqrt(t))
        d2 = d1 - v*np.sqrt(t)

        optprice = (cp*s*np.exp(-div*t)*st.norm.cdf(cp*d1)) - (cp*k*np.exp(-rf*t)*st.norm.cdf(cp*d2))

        return optprice

def bissectionMethod(S0, r, q, implied_vol0, maturity, Strike, refPrice, epsilon, optionType):
    calibratedSigma = implied_vol0
    #Call black-scholes price function for initial value
    priceBS = bs_price(optionType , S0, Strike, r, maturity, calibratedSigma, q)
    sigmaUp = 2.0
    sigmaInf = epsilon
    lossSerie = []

    priceMax = bs_price(optionType ,S0, Strike, r, maturity, sigmaUp, q)
    if priceMax < refPrice:
        return priceMax, sigmaUp, pd.Series(lossSerie)

    priceMin = bs_price(optionType ,S0, Strike, r, maturity, sigmaInf, q)
    if priceMin > refPrice:
        return priceMin, sigmaInf, pd.Series(lossSerie)

    #Stop the optimization when the error is less than epsilon
    while(abs(priceBS - refPrice) > epsilon):
        #Update the upper bound or the lower bound
        #by comparing calibrated price and the target price
        if priceBS < refPrice :
            sigmaInf = calibratedSigma
        else :
            sigmaUp = calibratedSigma
        #Update calibratedSigma
        calibratedSigma = (sigmaUp + sigmaInf) / 2
        #Update calibrated price
        priceBS = bs_price(optionType ,S0, Strike, r, maturity, calibratedSigma, q)
        #Record the calibration error for this step
        lossSerie.append(abs(priceBS - refPrice))

    return priceBS, calibratedSigma, pd.Series(lossSerie)

def vectorizedImpliedVolatilityCalibration(S0,
                                           bootstrap,
                                           maturity,
                                           strike,
                                           optionType,
                                           marketPrice):
    epsilon = 1e-6
    discountRate = bootstrap.discountIntegral(maturity) / maturity
    dividendRate = bootstrap.dividendIntegral(maturity) / maturity
    data = np.vstack([np.array(maturity),  np.array(strike), np.array(optionType),
                      np.array(marketPrice), np.array(discountRate), np.array(dividendRate)]).T
    dataSet = pd.DataFrame(data, columns = ["Maturity", "Strike", "OptionType", "Price", "r", "q"])

    calibFunction = lambda x : bissectionMethod(S0, x["r"], x["q"], 0.2,
                                                x["Maturity"],
                                                x["Strike"],
                                                x["Price"],
                                                epsilon,
                                                x["OptionType"])[1]
    impVol = dataSet.apply(calibFunction, axis=1)

    return np.ravel(impVol)


"""

Path Planning with 4 point Beizer curve

author: Atsushi Sakai(@Atsushi_twi)

"""

import scipy.special
import numpy as np
import matplotlib.pyplot as plt
import math

show_animation = True

def calc_4point_bezier_path(sx, sy, syaw, ex, ey, eyaw, offset):
    D = math.sqrt((sx - ex)**2 + (sy - ey)**2) / offset
    cp = np.array(
        [[sx, sy],
         [sx + D * math.cos(syaw), sy + D * math.sin(syaw)],
         [ex - D * math.cos(eyaw), ey - D * math.sin(eyaw)],
         [ex, ey]])

    traj = []
    for t in np.linspace(0, 1, 100):
        traj.append(bezier(3, t, cp))
    P = np.array(traj)

    return P, cp

def bernstein(n, i, t):
    return scipy.special.comb(n, i) * t**i * (1 - t)**(n - i)

def bezier(n, t, q):
    p = np.zeros(2)
    for i in range(n + 1):
        p += bernstein(n, i, t) * q[i]
    return p

def plot_arrow(x, y, yaw, length=1.0, width=0.5, fc="r", ec="k"):
    u"""
    Plot arrow
    """

    if not isinstance(x, float):
        for (ix, iy, iyaw) in zip(x, y, yaw):
            plot_arrow(ix, iy, iyaw)
    else:
        plt.arrow(x, y, length * math.cos(yaw), length * math.sin(yaw),
                  fc=fc, ec=ec, head_width=width, head_length=width)
        plt.plot(x, y)

def main():
    start_x = 10.0  # [m]
    start_y = 1.0  # [m]
    start_yaw = math.radians(180.0)  # [rad]

    end_x = -0.0  # [m]
    end_y = -3.0  # [m]
    end_yaw = math.radians(-45.0)  # [rad]
    offset = 3.0

    P, cp = calc_4point_bezier_path(
        start_x, start_y, start_yaw, end_x, end_y, end_yaw, offset)

    assert P.T[0][0] == start_x, "path is invalid"
    assert P.T[1][0] == start_y, "path is invalid"
    assert P.T[0][-1] == end_x, "path is invalid"
    assert P.T[1][-1] == end_y, "path is invalid"

    if show_animation:
        plt.plot(P.T[0], P.T[1], label="Bezier Path")
        plt.plot(cp.T[0], cp.T[1], '--o', label="Control Points")
        plot_arrow(start_x, start_y, start_yaw)
        plot_arrow(end_x, end_y, end_yaw)
        plt.legend()
        plt.axis("equal")
        plt.grid(True)
        plt.show()

def main2():
    start_x = 10.0  # [m]
    start_y = 1.0  # [m]
    start_yaw = math.radians(180.0)  # [rad]

    end_x = -0.0  # [m]
    end_y = -3.0  # [m]
    end_yaw = math.radians(-45.0)  # [rad]
    offset = 3.0

    for offset in np.arange(1.0, 5.0, 1.0):
        P, cp = calc_4point_bezier_path(
            start_x, start_y, start_yaw, end_x, end_y, end_yaw, offset)
        assert P.T[0][0] == start_x, "path is invalid"
        assert P.T[1][0] == start_y, "path is invalid"
        assert P.T[0][-1] == end_x, "path is invalid"
        assert P.T[1][-1] == end_y, "path is invalid"

        if show_animation:
            plt.plot(P.T[0], P.T[1], label="Offset=" + str(offset))

    if show_animation:
        plot_arrow(start_x, start_y, start_yaw)
        plot_arrow(end_x, end_y, end_yaw)
        plt.legend()
        plt.axis("equal")
        plt.grid(True)
        plt.show()

if __name__ == '__main__':
    main()
    #  main2()


from .ArrayUtils import *
import numpy as np
import math

def generateDistanceMatrix(width, height):
    """
	Generates a matrix specifying the distance of each point in a window to its centre.
	"""

    # Determine the coordinates of the exact centre of the window
    originX = width / 2
    originY = height / 2

    # Generate the distance matrix
    distances = zerosFactory((height, width), dtype=np.float)
    for index, val in np.ndenumerate(distances):
        y, x = index
        distances[(y, x)] = math.sqrt(
            math.pow(x - originX, 2) + math.pow(y - originY, 2)
        )

    return distances


"""
    Computation to machine precision of the ground state energy (per site)
of 1D Transverse Field Ising Model (TFIM) for various values of the parameter g.
"""
import numpy as np
import scipy.integrate as integrate

def E0_sum(N, g):
    ks = np.linspace(-(N-1)/2, (N-1)/2, num=N) / N * 2 * np.pi
    epsilon_ks = 2 * np.sqrt(g**2 - 2 * g * np.cos(ks) + 1)
    E0 = - 0.5 * epsilon_ks.sum() / N
    return E0

def E0_integrate(g):
    f = lambda k: -1. / (2. * np.pi) * np.sqrt(g**2 - 2 * g * np.cos(k) + 1)
    E0, error = integrate.quadrature(f, -np.pi, np.pi, tol=1e-16, rtol=1e-16, maxiter=2000)
    return E0, error

if __name__ == "__main__":
    gs = np.array([0.80, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20])
    E0s_sum = np.empty(gs.size)
    for i in range(gs.size):
        g = gs[i]
        print("g =", g)
        upper = 10 if g == 1.00 else 8
        for exponent in range(2, upper):
            E0 = E0_sum(10 ** exponent, g)
            print("N = 10^%d, \t\tE0 = %.15f" % (exponent, E0))
            if exponent == upper - 1:
                E0s_sum[i] = E0
        #print("E0_integrate = %.15f" % E0_integrate(g)[0])

    filename = "datas/E0_sum.npz"
    np.savez(filename, gs=gs, E0s=E0s_sum)


import numpy as np

def verifyValue(value):
    if np.isinf(value) or np.isnan(value):
        return False
    return True

def minimum(signals):
    features = []
    for signal in signals:
        features.append(np.min(signal))
    return np.array(features)

def maximum(signals):
    features = []
    for signal in signals:
        features.append(np.max(signal))
    return np.array(features)

def mean(signals):
    features = []
    for signal in signals:
        features.append(np.mean(signal))
    return np.array(features)

def std(signals):
    features = []
    for signal in signals:
        features.append(np.std(signal))
    return np.array(features)

def variance(signals):
    features = []
    for signal in signals:
        features.append(np.var(signal))
    return np.array(features)

def median(signals):
    features = []
    for signal in signals:
        features.append(np.median(signal))
    return np.array(features)

def skewness(signals):
    features = []
    for signal in signals:
        std = np.std(signal)
        if std == 0:
            return 0
        mean = np.mean(signal)
        median = np.median(signal)
        skewness_value = (3*(mean-median))/std
        if verifyValue(skewness_value):
            features.append(skewness_value)
        features.append(0)
    return np.array(features)

def energy(signals):
    features = []
    for signal in signals:
        features.append(np.sum(np.array(signal)**2))
    return np.array(features)

def entropy(signals):
    features = []
    for signal in signals:
        entropy_value = 0
        for i in range(len(signal)):
            if verifyValue(np.log2(signal[i]**2)):
                entropy_value += (signal[i]**2)*(np.log2(signal[i]**2))
        if verifyValue(entropy_value):
            features.append(entropy_value)
        features.append(0)
    return np.array(features)

def relative_energy(signals):
    features = []
    energies = []
    for signal in signals:
        energies.append(np.sum(np.array(signal)**2))
    total_energy = np.sum(energies)
    for energy_value in energies:
        if total_energy == 0:
            features.append(0)
        else:
            features.append(energy_value/total_energy)
    return np.array(features)


import numpy as np

def softmax(X):
    """ Softmax function """
    return np.exp(X) / np.sum(np.exp(X), axis=0)

def main():
    """ Main """
    scores = np.array([1.0, 2.0, 3.0])
    print softmax(scores)

    scores = np.array([[1, 2, 3, 6],
                      [2, 4, 5, 6],
                      [3, 8, 7, 6]])
    print softmax(scores)

if __name__ == "__main__":
    main()


import math
import matplotlib.pyplot as plt
import time
from abc import ABC, abstractmethod
from scipy import integrate
import numpy as np

from numericalODE import RK4, Euler, CalcError
from functions import fun_exp, lot_volt_f, lot_volt_g, to_1dim, exact

#warunki początkowe
t = 0.0
t_stop = 80.0

dt = 0.1
dt_e = 0.1

y = 1.0
y0 = [30,4]
func = fun_exp

params = {
    'a': 0.2,   # współczynnik nardzin ofiar
    'b': 0.04,   # czestotliwosc umierania ofiar
    'c': 0.04,   # przyrost drapieżników
    'd': 0.5    # umieranie drapieżnikow
    }
# tuple - do Scipy
params_ =[v for _, v in params.items()]
params_= tuple(params_)

# obliczenia
euler_1 = Euler(fun_exp, y, t, t_stop, dt)
rk4_1 = RK4(fun_exp, y, t, t_stop, dt)

# Lotki-Volterry, ukad równań różniczkowych
Ye_2dim, Te_2dim = euler_1.solve_system(f=lot_volt_f, g=lot_volt_g, u=y0, params=params)
Yrk_2dim, Trk_2dim = rk4_1.solve_system(f=lot_volt_f, g=lot_volt_g, u=y0, params=params)
preyRK, predRK = to_1dim(Yrk_2dim)
preyE, predE = to_1dim(Ye_2dim)

# wizualizacja
plt.figure(figsize=(15,8))
plt.plot(Te_2dim, Ye_2dim, label="E")
plt.plot(Trk_2dim, Yrk_2dim, label="RK")
plt.xlabel("czas")
plt.ylabel("liczba zwierząt")
plt.legend()
plt.show()

# równanie różniczkowe
t_stop = 40
euler_2 = Euler(fun_exp, y, t, t_stop, dt)
rk4_2 = RK4(fun_exp, y, t, t_stop, dt)

Ye, Te = euler_2.solve()
Yrk, Trk = rk4_2.solve()
exact_rk = exact(dt,t_stop,y)

#wizualizacja
plt.figure(figsize=(16,10))
plt.plot(Te,Ye, color="red", label=f"Euler dt: {dt_e}")
plt.plot(Trk,exact_rk, label="exact")
plt.xlabel("czas",fontsize=13)
plt.ylabel("y",fontsize=13)
plt.legend()
plt.show()


"""Run PCA.
"""

import numpy as np
from sklearn.decomposition import KernelPCA, PCA

from ml.config import pcaConf

def run_pca(data: np.ndarray, components=pcaConf.components):
    """Running normal PCA.
    """

    mat_PCA = PCA(n_components=components)
    X = mat_PCA.fit_transform(data)

    return X

def run_kernel_pca(data: np.ndarray, components=pcaConf.components):
    """Running kernel PCA.

    Sklearn KernelPCA may fits better for material data, which contain no linear
    features.
    """

    mat_kernelPCA = KernelPCA(n_components=components)
    X = mat_kernelPCA.fit_transform(data)

    return X


# Copyright 2021 Christian Schneider Pedersen <cspe18@student.aau.dk>, Helene Bach Vistisen, Julian Teule, Mikkel Filt Bengtson, Victor Büttner <beer@0x23.dk>
#
# SPDX-License-Identifier: Beerware OR MIT
import math
from typing import List
import numpy as np
from numpy.typing import ArrayLike

def gen_bits(nbits: int) -> List[int]:
    """
    example:
    >>> gen_bits(2)
    [0, 1, 3, 2]
    """
    if nbits == 1:
        return [0, 1]
    previous = gen_bits(nbits - 1)
    reverse = reversed(previous)
    # prefix bytes with 1, e.g. 01 becomes 101
    reverse = map(lambda v: (1 << (nbits - 1)) | v, reverse)
    return previous + list(reverse)

class GrayEncoder:

    def __init__(self, M: int) -> None:
        nbits = math.log2(M)
        assert nbits.is_integer(), f"M should be a power of 2, {M} is not"
        self.lookup_encode = np.array(gen_bits(int(nbits)))

        self.lookup_decode = np.empty(len(self.lookup_encode))
        for i, element in enumerate(self.lookup_encode):
            self.lookup_decode[element] = i

    def encode(self, a: ArrayLike) -> ArrayLike:
        return self.lookup_encode[a]

    def decode(self, a: ArrayLike) -> ArrayLike:
        return self.lookup_decode[a]


import numpy as np

'''
Numpy features:
* Transpose array:
  my_array = numpy.array([[1,2,3],
                          [4,5,6]])
  numpy.transpose(my_array)
  [[1 4]
   [2 5]
   [3 6]]
* Flatten array:
  my_array = numpy.array([[1,2,3],
                          [4,5,6]])
  my_array.flatten()
  [1 2 3 4 5 6]
'''
def main():
    # Input N rows x M cols array
    rows, cols = map(int, input().split())
    matrix = [list(map(int, input().split())) for _ in range(rows)]
    nparr = np.array(matrix)

    # print(f'\nOriginal:\n{nparr}')
    # print(f'\nTransposed:\n{np.transpose(nparr)}')
    # print(f'\nFlattened:\n{nparr.flatten()}')

    # Per challenge specs:
    print(f'{np.transpose(nparr)}')
    print(f'{nparr.flatten()}')

if __name__ == '__main__':
    main()


import numpy as np

def cal_similarity(v1, v2, similarity='cos'):
    """
    计算余弦相似度
    :param v1: 第一个向量
    :param v2: 第二个向量
    :return: 余弦相似度
    """

    if similarity == 'cos':
        cos = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
        return cos
    elif similarity == 'Euclidean':
        Euclidean = np.linalg.norm(v2 - v1)
        return Euclidean
    else:
        raise ValueError('mode should be cos or Euclidean')

def cal_similarities(v, v_list, similarity='cos', modify=False):
    '''

    :param v: array,向量
    :param v_list: iter,向量迭代器
    :param similarity: str,'cos' or 'Euclidean',相似度计算方法
    :param modify: bool,是否进行余弦修正
    :return:
    '''
    similarity_all = []
    if modify:
        texts_vec_use = np.array([i for i in v_list if type(i) == np.ndarray])
        texts_vec_mean = texts_vec_use.mean(axis=0)
        for i in v_list:
            # 出现nan则相似度记为-999
            if type(v) != np.ndarray or type(i) != np.ndarray:
                similarity_one = -999.0
            else:
                similarity_one = cal_similarity(v1=v - texts_vec_mean,
                                                v2=i - texts_vec_mean,
                                                similarity=similarity)
            similarity_all.append(similarity_one)
    else:
        for i in v_list:
            # 出现nan则相似度记为-999
            if type(v) != np.ndarray or type(i) != np.ndarray:
                similarity_one = -999.0
            else:
                similarity_one = cal_similarity(v1=v, v2=i, similarity=similarity)
            similarity_all.append(similarity_one)
    return similarity_all

if __name__ == '__main__':
    x = np.array([1, 2])
    y = np.array([1, 1])
    print('cos:', cal_similarity(x, y, similarity='cos'))
    print('Euclidean:', cal_similarity(x, y, similarity='Euclidean'))


# Project Euler 11 - Largest product in a grid
# GitHub: urtuba

import numpy as np

def load_2d_array(filename: str) -> np.ndarray:
    '''
    Reads a txt file into 2d numpy integer array.

    :param filename: name of the txt file.
    :return: 2d numpy array
    '''
    with open(filename, 'r') as file:
        array_2d = np.loadtxt(filename, dtype=np.int32, ndmin=2)
    return array_2d

def largest_product_of_quarts(array_2d: np.ndarray) -> int:
    '''
    Returns largest product of four adjacent integers in the given 2D array.
    Adjacency can occur horizontally, vertically or diagonally.

    :param array_2d: 2d array, n x n.
    :return: largest product of 4 adjacent numbers
    '''

    # hidden helper functions
    def _max_quart_product_of_rows(array_2d: np.ndarray) -> int:
        dim = len(array_2d)
        maximum = 0
        for row in array_2d:
            for i in range(dim-3):
                temp = np.product(row[i:i+4])
                if maximum < temp: maximum = temp
        return maximum

    def _max_quart_product_of_cols(array_2d: np.ndarray) -> int:
        dim = len(array_2d)
        maximum = 0
        for col in array_2d.transpose():
            for i in range(dim-3):
                temp = np.product(col[i:i+4])
                if maximum < temp: maximum = temp
        return maximum

    def _max_quart_product_of_diags(array_2d: np.ndarray) -> int:
        dim = len(array_2d)
        diags = [array_2d.diagonal(i) for i in range(-dim+1, dim)]
        diags.extend([array_2d[:,::-1].diagonal(i) for i in range(-dim+1, dim)])
        diags = list(filter(lambda n: len(n) > 3, diags))

        maximum = 0
        for diag_line in diags:
            diag_len = len(diag_line)
            for i in range(diag_len-3):
                temp = np.product(diag_line[i:i+4])
                if maximum < temp: maximum = temp
        return maximum

    # actual function body
    rows_max = _max_quart_product_of_rows(array_2d)
    cols_max = _max_quart_product_of_cols(array_2d)
    diags_max = _max_quart_product_of_diags(array_2d)
    return max(rows_max, cols_max, diags_max)

if __name__ == '__main__':
    matrix = load_2d_array('s011-input.txt')
    result = largest_product_of_quarts(matrix)
    print (result)


import numpy as np

def describe_policy_matrix(matrix, env):
    for state, action in enumerate(matrix):
        if action == -1:
            print('Terminal State ', state, ' : No Action')
        else:
            value = env.action_to_value_mapping[action]
            if value > 0:
                string = 'Subtract '+str(abs(value))+' from current value'
            else:
                string = 'Add '+str(abs(value))+' to current value'
            print('State ', state, ' : Action : ', string)

def get_return(state_list, gamma):
    """
    :param state_list: a list of tuples (observation, action, reward)
    :param gamma: the discount factor
    :return: the return value for that state_list
    """
    return_value = 0
    counter = 0
    for visit in state_list:
        reward = visit[2]
        return_value += reward * np.power(gamma, counter)
        counter += 1
    return return_value

def update_policy(episode_list, policy_matrix, state_action_matrix):
    """
    Updates the policy in a greedy way, selecting actions which have the highest
    utility for each state visited in the episode_list
    :param episode_list: the tuples of states visited as (observation, action, reward)
    :param policy_matrix: the policy matrix
    :param state_action_matrix: the Q matrix
    :return:
    """
    for visit in episode_list:
        state = visit[0][0]
        if policy_matrix[state] != -1:
            # if its not the terminal state
            policy_matrix[state] = np.argmax(state_action_matrix[:, state])
    return policy_matrix

def has_converged(old_matrix, new_matrix):
    if abs(np.sum(new_matrix-old_matrix)) < 0.1:
        return True
    return False


from functools import partial
from typing import Optional

import numpy as np

# found module but no type hints or library stubs
from scipy.special import binom  # type: ignore

def fdiff_coef(d: float, window: int) -> np.ndarray:
    """Returns sequence of coefficients in fracdiff operator.

    Parameters
    ----------
    d : float
        Order of differentiation.
    window : int
        Number of terms.

    Returns
    -------
    coef : numpy.array, shape (window,)
        Coefficients in fracdiff operator.

    Examples
    --------
    >>> fdiff_coef(0.5, 4)
    array([ 1.    , -0.5   , -0.125 , -0.0625])
    >>> fdiff_coef(1.0, 4)
    array([ 1., -1.,  0., -0.])
    >>> fdiff_coef(1.5, 4)
    array([ 1.    , -1.5   ,  0.375 ,  0.0625])
    """
    return (-1) ** np.arange(window) * binom(d, np.arange(window))

def fdiff(
    a: np.ndarray,
    n: float = 1.0,
    axis: int = -1,
    prepend: Optional[np.ndarray] = None,
    append: Optional[np.ndarray] = None,
    window: int = 10,
    mode: str = "same",
) -> np.ndarray:
    """Calculate the `n`-th differentiation along the given axis.

    Extention of ``numpy.diff`` to fractional differentiation.

    Parameters
    ----------
    a : array_like
        The input array.
    n : float, default=1.0
        The order of differentiation.
        If ``n`` is an integer, returns the same output with ``numpy.diff``.
    axis : int, default=-1
        The axis along which differentiation is performed, default is the last axis.
    prepend : array_like, optional
        Values to prepend to ``a`` along axis prior to performing the differentiation.
        Scalar values are expanded to arrays with length 1 in the direction of axis and
        the shape of the input array in along all other axes.
        Otherwise the dimension and shape must match ``a`` except along axis.
    append : array_like, optional
        Values to append.
    window : int, default=10
        Number of observations to compute each element in the output.
    mode : {"same", "valid"}, default="same"
        "same" (default) :
            At the beginning of the time series,
            return elements where at least one coefficient of fracdiff is used.
            Output size along ``axis`` is :math:`L_{\\mathrm{in}}`
            where :math:`L_{\\mathrm{in}}` is the length of ``a`` along ``axis``
            (plus the lengths of ``append`` and ``prepend``).
            Boundary effects may be seen at the at the beginning of a time-series.
        "valid" :
            Return elements where all coefficients of fracdiff are used.
            Output size along ``axis`` is
            :math:`L_{\\mathrm{in}} - \\mathrm{window} + 1` where
            where :math:`L_{\\mathrm{in}}` is the length of ``a`` along ``axis``
            (plus the lengths of ``append`` and ``prepend``).
            Boundary effects are not seen.

    Returns
    -------
    fdiff : numpy.ndarray
        The fractional differentiation.
        The shape of the output is the same as ``a`` except along ``axis``.

    Examples
    --------
    This returns the same result with ``numpy.diff`` for integer `n`.

    >>> from fracdiff import fdiff
    >>> a = np.array([1, 2, 4, 7, 0])
    >>> (np.diff(a) == fdiff(a)).all()
    True
    >>> (np.diff(a, 2) == fdiff(a, 2)).all()
    True

    This returns fractional differentiation for noninteger `n`.

    >>> fdiff(a, 0.5, window=3)
    array([ 1.   ,  1.5  ,  2.875,  4.75 , -4.   ])

    Mode "valid" returns elements for which all coefficients are convoluted.

    >>> fdiff(a, 0.5, window=3, mode="valid")
    array([ 2.875,  4.75 , -4.   ])
    >>> fdiff(a, 0.5, window=3, mode="valid", prepend=[1, 1])
    array([ 0.375,  1.375,  2.875,  4.75 , -4.   ])

    Differentiation along desired axis.

    >>> a = np.array([[  1,  3,  6, 10, 15],
    ...               [  0,  5,  6,  8, 11]])
    >>> fdiff(a, 0.5, window=3)
    array([[1.   , 2.5  , 4.375, 6.625, 9.25 ],
           [0.   , 5.   , 3.5  , 4.375, 6.25 ]])
    >>> fdiff(a, 0.5, window=3, axis=0)
    array([[ 1. ,  3. ,  6. , 10. , 15. ],
           [-0.5,  3.5,  3. ,  3. ,  3.5]])
    """
    if mode == "full":
        mode = "same"
        raise DeprecationWarning("mode 'full' was renamed to 'same'.")

    if isinstance(n, int) or n.is_integer():
        prepend = np._NoValue if prepend is None else prepend  # type: ignore
        append = np._NoValue if append is None else append  # type: ignore
        return np.diff(a, n=int(n), axis=axis, prepend=prepend, append=append)

    if a.ndim == 0:
        raise ValueError("diff requires input that is at least one dimensional")

    a = np.asanyarray(a)
    # Mypy complains:
    # fracdiff/fdiff.py:135: error: Module has no attribute "normalize_axis_index"
    axis = np.core.multiarray.normalize_axis_index(axis, a.ndim)  # type: ignore
    dtype = a.dtype if np.issubdtype(a.dtype, np.floating) else np.float64

    combined = []
    if prepend is not None:
        prepend = np.asanyarray(prepend)
        if prepend.ndim == 0:
            shape = list(a.shape)
            shape[axis] = 1
            prepend = np.broadcast_to(prepend, tuple(shape))
        combined.append(prepend)

    combined.append(a)

    if append is not None:
        append = np.asanyarray(append)
        if append.ndim == 0:
            shape = list(a.shape)
            shape[axis] = 1
            append = np.broadcast_to(append, tuple(shape))
        combined.append(append)

    if len(combined) > 1:
        a = np.concatenate(combined, axis)

    if mode == "valid":
        D = partial(np.convolve, fdiff_coef(n, window).astype(dtype), mode="valid")
        a = np.apply_along_axis(D, axis, a)
    elif mode == "same":
        # Convolve with the mode 'full' and cut last
        D = partial(np.convolve, fdiff_coef(n, window).astype(dtype), mode="full")
        s = tuple(
            slice(a.shape[axis]) if i == axis else slice(None) for i in range(a.ndim)
        )
        a = np.apply_along_axis(D, axis, a)
        a = a[s]
    else:
        raise ValueError("Invalid mode: {}".format(mode))

    return a


import math
import numpy as np

class Activation:
    def __init__(self, name: str, phi, dPhi):
        """
        Utility class used for manage name,function and its derivative for all activation function
        :param name: Name of activation function, shown in the title of chats
        :param phi: pointer to activation function
        :param dPhi: pointer to derivative of activation function
        """
        self.name = name
        self.phi = phi
        self.dPhi = dPhi

def linear(x): return x

def d_linear(x): return 1

def relu(x): return max(0, x)

def LReLU(x): return x if x >= 0 else 0.01 * x

def d_LReLU(x): return 1 if x >= 0 else 0.01

def d_relu(x): return 0 if x < 0 else 1

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

def d_sigmoid(x):
    s = sigmoid(x)
    return s * (1 - s)

def tanH(x): return np.tanh(x)

def d_tanH(x): return 1 - math.pow(np.tanh(x), 2)

# Dictionary of activation function used in the grid search configuration
actF = {
    "linear": Activation("linear", linear, d_linear),
    "relu": Activation("ReLu", relu, d_relu),
    "sig": Activation("Sigmoid", sigmoid, d_sigmoid),
    "tan": Activation("tanH", tanH, d_tanH),
    "lRelu": Activation("LReLu", LReLU, d_LReLU),

}


# -*- coding: utf-8 -*-
"""
Created on Tue Dec  7 20:49:22 2021

@author: Oliver

"""
import numpy as np
import sympy as sp
import math
import matplotlib.pyplot as plt
w_0=250
E=200000
I=300000000
delta_x =125 # mm
L = 3000 #mm

y = np.linspace(0,3000,24000)
def theta_x(x):
    return w_0/(120*E*I*L) *(-5*x**4 +6*L**2*x**2 - L**4)

dydx = theta_x(0)

"E*I*dthetadx = M(x)"
"dMdx = V(x)"
"dVdx = -w(x)"

def calculate_dx (a, b, n):
    return (b-a)/float(n)

def rect_rule (f, a, b, n):
    total = 0.0
    dx = calculate_dx(a, b, n)
    for k in range (0, n):
        total = total + f((a + (k*dx)))
    return dx*total
print(rect_rule(theta_x, 0, 1.5, 24))

deflection_values = []

for i in y:
    deflection_values.append(rect_rule(theta_x,0,i,24))
plt.title("THIS IS THE GRAPH")
plt.plot(y,deflection_values)
plt.show()

# DERIVATIVES NOW
z = sp.Symbol('z')
x = sp.Symbol('x')
f = sp.Function('f')(x)
f = w_0/(120*E*I*L) *(-5*x**4 +6*L**2*x**2 - L**4)
M_x = sp.diff(f)/(E*I)
v = M_x.evalf(subs = {x:1.5})

print(f'The Moment at midpoint is: {v}')
V_x = sp.diff(M_x)
w_x = sp.diff(V_x)
for i in y:
    if i==3:
        print(0)
        break
    print(w_x.evalf(subs = {x:i}))

print(f'Moment is given by the following equation: {M_x}')
print(f'Shear is given by the following equation: {V_x}')
print(f'Load is given by the following equation: {V_x}')

# NEXT QUESTION
# SPHERICAL TANK HAS A CIRCULAR ORIFICE IN ITS BOTTOM THROUGH
# WHICH THE LIQUID FLOWS OUT
# inputs

# functions that returns dy/dx
# i.e. the equation we want to solve: dy/dx = - y
def model(y,x):
    C=0.55
    r_ori = 0.3
    A=(r_ori/2)**2*math.pi
    g=9.81
    r=1.5
    dydx = -(C*A*(2*g*y)**0.5)/(2*math.pi*r*y-math.pi*y**2)
    return dydx

# initial conditions
x0 = 0
y0 = 2.75
# total solution interval
x_final = 100
# step size
h = 0.1
# ------------------------------------------------------

# ------------------------------------------------------
# Euler method

# number of steps
n_step = math.ceil(x_final/h)

# Definition of arrays to store the solution
y_eul = np.zeros(n_step+1)
x_eul = np.zeros(n_step+1)

# Initialize first element of solution arrays
# with initial condition
y_eul[0] = y0
x_eul[0] = x0

# Populate the x array
for i in range(n_step):
    x_eul[i+1]  = x_eul[i]  + h

# Apply Euler method n_step times
for i in range(n_step):
    # compute the slope using the differential equation
    slope = model(y_eul[i],x_eul[i])
    # use the Euler method
    y_eul[i+1] = y_eul[i] + h * slope
    if y_eul[i+1] < 0:
        break
    # print( x_eul[i+1], y_eul[i+1])
# ------------------------------------------------------

# ------------------------------------------------------
# plot results
plt.plot(x_eul, y_eul , 'b.-',)
plt.xlabel('time (s)')
plt.ylabel('y(x)')
plt.show()
# ------------------------------------------------------

# FINAL QUESTION OF THE TUTORIAL

ff,zz,EE,II,LL,zz = sp.symbols('ff,zz,EE,II,LL,zz')

z = 30 #HEIGHT AT THE END WHICH IS EQUAL TO L
f=60
E=1.25*10**8
I=0.05
L=30

g = ff*(LL-zz)**2/(2*EE*II)

Integral_1 = sp.integrate(g,zz)
Integral_2 = sp.integrate(Integral_1,zz)
print(Integral_1)
print(Integral_1.subs([(zz,z),(ff,f),(EE,E),(II,I),(LL,L)]))
print(Integral_2)
print(Integral_2.subs([(zz,z),(ff,f),(EE,E),(II,I),(LL,L)]))


"""Tools for maximum likelihood estimation associated with Lomb-Scargle"""
import numpy as np

def design_matrix(t, frequency, dy=None, bias=True, nterms=1):
    """Compute the Lomb-Scargle design matrix at the given frequency

    This is the matrix X such that the periodic model at the given frequency
    can be expressed :math:`\\hat{y} = X \\theta`.

    Parameters
    ----------
    t : array_like, shape=(n_times,)
        times at which to compute the design matrix
    frequency : float
        frequency for the design matrix
    dy : float or array_like (optional)
        data uncertainties: should be broadcastable with `t`
    bias : bool (default=True)
        If true, include a bias column in the matrix
    nterms : int (default=1)
        Number of Fourier terms to include in the model

    Returns
    -------
    X : ndarray, shape=(n_times, n_parameters)
        The design matrix, where n_parameters = bool(bias) + 2 * nterms
    """
    t = np.asarray(t)
    assert t.ndim == 1
    assert np.isscalar(frequency)

    if nterms == 0 and not bias:
        raise ValueError("cannot have nterms=0 and no bias")

    if bias:
        cols = [np.ones_like(t)]
    else:
        cols = []

    for i in range(1, nterms + 1):
        cols.append(np.sin(2 * np.pi * i * frequency * t))
        cols.append(np.cos(2 * np.pi * i * frequency * t))
    XT = np.vstack(cols)

    if dy is not None:
        XT /= dy

    return np.transpose(XT)

def periodic_fit(t, y, dy, frequency, t_fit,
                 center_data=True, fit_bias=True, nterms=1):
    """Compute the Lomb-Scargle model fit at a given frequency

    Parameters
    ----------
    t, y, dy : float or array_like
        The times, observations, and uncertainties to fit
    frequency : float
        The frequency at which to compute the model
    t_fit : float or array_like
        The times at which the fit should be computed
    center_data : bool (default=True)
        If True, center the input data before applying the fit
    fit_bias : bool (default=True)
        If True, include the bias as part of the model
    nterms : int (default=1)
        The number of Fourier terms to include in the fit

    Returns
    -------
    y_fit : ndarray
        The model fit evaluated at each value of t_fit
    """
    if dy is None:
        dy = 1

    t, y, dy = np.broadcast_arrays(t, y, dy)
    t_fit = np.asarray(t_fit)
    assert t.ndim == 1
    assert t_fit.ndim == 1
    assert np.isscalar(frequency)

    if center_data:
        w = dy ** -2.0
        y_mean = np.dot(y, w) / w.sum()
        y = (y - y_mean)
    else:
        y_mean = 0

    X = design_matrix(t, frequency, dy=dy, bias=fit_bias, nterms=nterms)
    theta_MLE = np.linalg.solve(np.dot(X.T, X),
                                np.dot(X.T, y / dy))

    X_fit = design_matrix(t_fit, frequency, bias=fit_bias, nterms=nterms)

    return y_mean + np.dot(X_fit, theta_MLE)


import numpy as np
from pydrake.autodiffutils import AutoDiffXd

from pydrake.solvers.mathematicalprogram import MathematicalProgram

def cos(theta):
  return AutoDiffXd.cos(theta)
def sin(theta):
  return AutoDiffXd.sin(theta)

def landing_constraint(vars):
  '''
  Impose a constraint such that if the ball is released at final state xf,
  it will land a distance d from the base of the robot
  '''
  l = 1
  g = 9.81
  constraint_eval = np.zeros((3,), dtype=AutoDiffXd)
  q = vars[:3]
  qdot = vars[3:6]
  t_land = vars[-1]
  pos = np.array([[-l*sin(q[0]) - l*sin(q[0] + q[1]) - l*sin(q[0] + q[1] + q[2])],
                  [-l*cos(q[0]) - l*cos(q[0] + q[1]) - l*cos(q[0] + q[1] + q[2])]])
  vel = np.array([[-l*qdot[2]*cos(q[0] + q[1] + q[2]) + qdot[0]*(-l*cos(q[0]) - l*cos(q[0] + q[1]) - l*cos(q[0] + q[1] + q[2])) + qdot[1]*(-l*cos(q[0] + q[1]) - l*cos(q[0] + q[1] + q[2]))],
                  [l*qdot[2]*sin(q[0] + q[1] + q[2]) + qdot[0]*(l*sin(q[0]) + l*sin(q[0] + q[1]) + l*sin(q[0] + q[1] + q[2])) + qdot[1]*(l*sin(q[0] + q[1]) + l*sin(q[0] + q[1] + q[2]))]])

  # TODO: Express the landing constraint as a function of q, qdot, and t_land
  # constraint_eval[0]: Eq (15)
  # constraint_eval[1]: Eq (16)
  # constraint_eval[2]: Eq (18)

  return constraint_eval

def AddFinalLandingPositionConstraint(prog, xf, d, t_land):

  # TODO: Add the landing distance equality constraint as a system of inequality constraints
  # using prog.AddConstraint(landing_constraint, lb, ub, vars)

  # TODO: Add a constraint that t_land is positive
  pass


import numpy as np

class MSE():
    def calc(self, yHat, y):
        # return ((yHat - y) ** 2) / 2
        return np.sum((yHat - y) ** 2) / y.size


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

# load the data
df = pd.read_csv('data.csv', header=None)
X = df[0]
Y = df[1]

# plot the data to see what it looks like
plt.scatter(X, Y)
plt.show()

# calculate values which are used more than once
Xsum = X.sum()
Xmean = X.mean()
Ymean = Y.mean()

# calculate the common denominator
denominator = X.dot(X) - Xmean * Xsum

# finally calculate the weights
W = ( X.dot(Y) - Ymean*Xsum ) / denominator
b = ( Ymean * X.dot(X) - Xmean * X.dot(Y) ) / denominator

print('Weights are: W = {}, b = {}'.format(W, b))

# calculate the predicted Y
Yhat = W*X + b

# let's plot everything together to make sure it worked
plt.scatter(X, Y)
plt.plot(X, Yhat)
plt.show()

# determine how good the model is by computing the r-squared
d1 = Y - Yhat
d2 = Y - Y.mean()
r2 = 1 - d1.dot(d1) / d2.dot(d2)

print('R2 is: {}'.format(r2))


import math
import numpy as np

def softmax(word_importance_dict : dict) -> dict:
    """
    Computes softmax value of word_importance_dict values.

    :param word_importance_dict: describe about parameter p1

    :return: replaces raw values of word_importance_dict with
    softmax values
    """
    normalized_sum = np.sum(np.exp(list(word_importance_dict.values())))
    softmax_word_importance = {}
    for word in word_importance_dict:
        softmax_word_importance[word] = (math.e**word_importance_dict[word])/normalized_sum
    return softmax_word_importance


import scipy as sc
import scipy.sparse as sparse
import scipy.sparse.linalg
import numpy as np
import pylab as pl
import matplotlib.pyplot as plt
import time

t=time.time()
# Number of internal points
N = 512

# Calculate Spatial Step-Size
h = 1/(N+1.0)

# Create Temporal Step-Size, TFinal, Number of Time-Steps
k = h/2
TFinal = 0.2
NumOfTimeSteps = int(TFinal/k)

# Create grid-points on x axis
x = np.linspace(0,1,N+2)
x = x[1:-1]

# Initial Conditions
u = np.transpose(np.mat(10*np.sin(2*np.pi*x)))

# Second-Derivative Matrix
data = np.ones((3, N))
data[1] = -2*data[1]
diags = [-1,0,1]
L = sparse.spdiags(data,diags,N,N)/(h**2)

# Identity Matrix
I = sparse.identity(N)

# Data for each time-step
data = []

for i in range(NumOfTimeSteps):
    # Solve the System: (I - k/2*L) u_new = (I + k/2*L)*u_old
    A = (I -k/2*L)
    b = ( I + k/2*L )*u
    u = np.transpose(np.mat( sparse.linalg.spsolve(A,b)))
    data.append(u)

print(time.time()-t)
plt.clf()
plt.imshow(np.squeeze(np.asarray(data))) #transforme le format matrix en format array pour imshow
plt.xlabel('x')
plt.ylabel('t (temps)')
plt.colorbar()

#http://jkwiens.com/2010/01/02/finite-difference-heat-equation-using-numpy/


from math import sqrt, floor
from numpy import var
from scipy.stats import ttest_ind
from statsmodels.stats.power import tt_ind_solve_power
from oeda.log import warn, error
from oeda.analysis import Analysis
from numpy import mean

class TwoSampleTest(Analysis):

    def run(self, data, knobs):

        if len(data) < 2:
            error("Cannot run " + self.name + " on less than two samples.")
            return False

        if len(data) > 2:
            warn("Cannot run " + self.name + " on more than two samples.")
            warn("Comparing only the first two samples.")

        self.y1 = [d for d in data[0]]
        self.y2 = [d for d in data[1]]

        return True

class Ttest(TwoSampleTest):

    name = "t-test"

    def __init__(self, stage_ids, y_key, alpha=0.05):
        super(self.__class__, self).__init__(stage_ids, y_key)
        self.alpha = alpha

    def run(self, data, knobs):

        if not super(self.__class__, self).run(data, knobs):
            error("Aborting analysis.")
            return

        statistic, pvalue = ttest_ind(self.y1, self.y2, equal_var=False)

        different_averages = bool(pvalue <= self.alpha)

        result = dict()
        result["statistic"] = statistic
        result["pvalue"] = pvalue
        result["alpha"] = self.alpha
        result["different_averages"] = different_averages

        result["mean_diff"] = mean(self.y1) - mean(self.y2)

        # calculating cohen's d effect size ():
        pooled_std = sqrt((var(self.y1) + var(self.y2)) / 2)
        result["effect_size"] = result["mean_diff"] / pooled_std

        return result

class TtestPower(TwoSampleTest):

    name = "t-test-power"

    def __init__(self, stage_ids, y_key, effect_size, alpha=0.05, alternative='two-sided'):
        super(self.__class__, self).__init__(stage_ids, y_key)
        self.alpha = alpha
        self.effect_size = effect_size
        self.alternative = alternative

    def run(self, data, knobs):

        if not super(self.__class__, self).run(data, knobs):
            error("Aborting analysis.")
            return

        # pooled_std = sqrt((var(self.y1) + var(self.y2)) / 2)
        # effect_size = self.mean_diff / pooled_std

        sample_size = len(self.y1)

        power = tt_ind_solve_power(effect_size=self.effect_size, nobs1=sample_size, alpha=self.alpha, alternative=self.alternative)

        result = dict()
        result["effect_size"] = self.effect_size
        result["sample_size"] = sample_size
        result["alpha"] = self.alpha
        result["power"] = power
        # result["mean_diff"] = self.mean_diff
        # result["pooled_std"] = pooled_std

        return result

class TtestSampleSizeEstimation(TwoSampleTest):

    name = "t-test-sample-estimation"

    def __init__(self, stage_ids, y_key, effect_size, mean_diff, alpha=0.05, power=0.8, alternative='two-sided'):
        super(self.__class__, self).__init__(stage_ids, y_key)
        self.alpha = alpha
        self.power = power
        self.effect_size = effect_size
        self.mean_diff = mean_diff
        self.alternative = alternative

    def run(self, data, knobs):

        if not super(self.__class__, self).run(data, knobs):
            error("Aborting analysis.")
            return

        if not self.effect_size:
            if not self.mean_diff:
                raise Exception("You cannot leave both mean_diff and effect_size paramaters empty")
            pooled_std = sqrt((var(self.y1) + var(self.y2)) / 2)
            effect_size = self.mean_diff / pooled_std
        else:
            effect_size = self.effect_size

        sample_size = tt_ind_solve_power(effect_size=effect_size, nobs1=None, alpha=self.alpha, power=self.power, alternative=self.alternative)

        result = dict()
        result["effect_size"] = effect_size
        result["sample_size"] = floor(sample_size)
        result["alpha"] = self.alpha
        result["power"] = self.power
        # result["mean_diff"] = self.mean_diff
        # result["pooled_std"] = pooled_std

        return result


# Create a boolean numpy array: the element of the array should be True if the corresponding baseball player's BMI is below 21.' \
# You can use the < operator for this. Name the array light.
# Print the array light
# Print out the numpy array with the BMIs of all baseball players whose BMI is below 21. Use light
# inside square bracket to do a selection on the bmi array.
# height and weight are available as a regular lists

# Import numpy
import numpy as np

# Calculate the BMI: bmi
np_height_m = np.array(height_in) * 0.0254
np_weight_kg = np.array(weight_lb) * 0.453592
bmi = np_weight_kg / np_height_m ** 2

# Create the light array
light = bmi < 21

# Print out light
print(light)

# Print out BMIs of all baseball players whose BMI is below 21
print(bmi[light])

01-introduction to python for data science/04-numpy/lightweight-baseball-player.py


"""a little helper module
"""
__author__ = "Reed Essick <reedessick@kicp.uchicago.edu>"

#-------------------------------------------------

import numpy as np

#-------------------------------------------------

DEFAULT_ALPHA = 0.1

#-------------------------------------------------

def tukey(N, alpha=DEFAULT_ALPHA):
    """
    generate a tukey window
    The Tukey window, also known as the tapered cosine window, can be regarded as a cosine lobe of width \alpha * N / 2
        that is convolved with a rectangle window of width (1 - \alpha / 2). At \alpha = 1 it becomes rectangular, and
        at \alpha = 0 it becomes a Hann window.

    """
    # Special cases
    if alpha <= 0:
        return np.ones(N) #rectangular window
    elif alpha >= 1:
        return np.hanning(N)

    # Normal case
    x = np.linspace(0, 1, N)
    w = np.ones(x.shape)

    # first condition 0 <= x < alpha/2
    first_condition = x<alpha/2
    w[first_condition] = 0.5 * (1 + np.cos(2*np.pi/alpha * (x[first_condition] - alpha/2) ))

    # second condition already taken care of

    # third condition 1 - alpha / 2 <= x <= 1
    third_condition = x>=(1 - alpha/2)
    w[third_condition] = 0.5 * (1 + np.cos(2*np.pi/alpha * (x[third_condition] - 1 + alpha/2)))

    return w

def lowpass(f, fo, m):
    """return 1./(1+(f/fo)**m)
    """
    return 1./(1+(f/fo)**m)

def highpass(f, fo, m):
    """return (f/fo)**m/(1+(f/fo)**m)
    """
    return 1. - lowpass(f, fo, m)


"""Determine the bhattacharyya distance beetween the given dictionaries."""
import numpy as np
from math import sqrt
from typing import Dict
from .distances_utils import sort

def bhattacharyya_coefficient(a: Dict, b: Dict) -> float:
    """Determine the Bhattacharyya coefficient beetween the given dictionaries.

    Parameters
    ----------------------------
    a: Dict,
        First dictionary to consider.
    b: Dict,
        Second dictionary to consider.

    Returns
    ----------------------------
    Return the Bhattacharyya coefficient beetween the given dictionaries.
    """
    total = 0
    big, small = sort(a, b)
    big_get = big.__getitem__
    for k, small_value in small.items():
        try:
            total += sqrt(big_get(k) * small_value)
        except KeyError:
            pass
    return total

def bhattacharyya(a: Dict, b: Dict) -> float:
    """Determine the Bhattacharyya distance beetween the given dictionaries.

    Parameters
    ----------------------------
    a: Dict,
        First dictionary to consider.
    b: Dict,
        Second dictionary to consider.

    Returns
    ----------------------------
    Return the Bhattacharyya distance beetween the given dictionaries.
    """
    distance = -np.log(bhattacharyya_coefficient(a, b))
    if np.isinf(distance):
        return 0
    return distance


import numpy as np

data_path = "data/problem_03.txt"
# data_path = "data/problem_03_test.txt"

data = np.loadtxt(data_path, dtype="S")
input_width = len(data[0])
data = data.view(dtype=np.uint8).reshape(-1, input_width) == ord("1")

# part 1
exponents = 2 ** np.arange(data.shape[1])[::-1].reshape(-1, 1)
gamma = (np.sum(data, axis=0) > len(data) * 0.5).astype(np.int32)
power_consumption = ((1 - gamma) @ exponents) * (gamma @ exponents)
print(f"Part 1 solution: {power_consumption[0]}\n")

# part 2
o2_data = data[:]
co2_data = data[:]

o2_candidates = np.arange(len(data))
co2_candidates = np.arange(len(data))

for col_index in range(data.shape[1]):
    o2_gamma = int(np.sum(data[o2_candidates, col_index]) >= len(o2_candidates) * 0.5)
    co2_gamma = int(np.sum(data[co2_candidates, col_index]) < len(co2_candidates) * 0.5)

    o2_candidates = o2_candidates[data[o2_candidates, col_index] == o2_gamma]
    co2_candidates = co2_candidates[data[co2_candidates, col_index] == co2_gamma]

    if len(o2_candidates) == 1:
        o2_value = data[o2_candidates[0]]
    if len(co2_candidates) == 1:
        co2_value = data[co2_candidates[0]]

o2_value = (o2_value @ exponents)[0]
co2_value = (co2_value @ exponents)[0]
print(f"o2_value: {o2_value}")
print(f"co2_value: {co2_value}")
print(f"Part 2 solution: {o2_value * co2_value}\n")