"""
Example 1 - Single Variable Linear Regression

NOTE: The example and sample data is being taken from the "Machine Learning course by Andrew Ng" in Coursera.

Problem:
  Suppose you are selling your house and you
want to know what a good market price would be. One way to do this is to
first collect information on recent houses sold and make a model of housing
prices.
"""

import matplotlib.pyplot as plt
# initial imports
import numpy as np

plt.ion()

from models.linear_regression import compute_cost, gradient_descent

# ----------------Loading X and y matrix ---------------
print('Loading data ...')

data = np.loadtxt('data/ex1data1.txt', delimiter=',')
X = data[:, 0:-1]
y = data[:, -1:]
m = y.shape[0]

# printing first 5 elements
print(X[0:5])

# ----------------Plotting Data-----------------
fig = plt.figure("data")
axes1 = fig.add_subplot()
axes1.scatter(X, y, marker="x", c='r')

# ---------------Cost and Gradient descent------------
# adding bias units to X

X = np.hstack((np.ones([m, 1]), X))

# Some gradient descent settings
iterations = 1500
alpha = 0.01
theta = np.zeros([X.shape[1], 1])

print('\nTesting the cost function ...')
# compute and display initial cost
J = compute_cost(X, y, theta);
print('With theta = [0 ; 0]\nCost computed = {}'.format(J))
print('Expected cost value (approx) 32.07')

# further testing of the cost function
J = compute_cost(X, y, np.array([[-1], [2]]))
print('\nWith theta = [-1 ; 2]\nCost computed = {}'.format(J))
print('Expected cost value (approx) 54.24')

print('\nRunning Gradient Descent ...')
# run gradient descent
theta, _ = gradient_descent(X, y, theta, alpha, iterations)

# print theta to screen
print('Theta found by gradient descent:')
print(theta)
print('Expected theta values (approx)')
print(' [-3.6303\n  1.1664]')

# ---------------- plotting the linear model---------------------------
plt.plot(X[:, 1:], np.dot(X, theta), lw=1)
plt.show()

# ------------------ plotting the J(theta0,theta1)---------------------
print('Visualizing J(theta_0, theta_1) ...\n')

# Grid over which we will calculate J
theta0_vals = np.linspace(-10, 10, 100)
theta1_vals = np.linspace(-1, 4, 100)

# initialize J_vals to a matrix of 0's
J_vals = np.zeros([theta0_vals.size, theta1_vals.size])

# Fill out J_vals
for i in range(theta0_vals.size):
    for j in range(theta1_vals.size):
        t = np.array([theta0_vals[i], theta1_vals[j]]).reshape(2, 1)
        J_vals[i, j] = compute_cost(X, y, t)

# Because of the way meshgrids work in the surf command, we need to
# transpose J_vals before calling surf, or else the axes will be flipped
J_vals = J_vals.T
theta0_vals, theta1_vals = np.meshgrid(theta0_vals, theta1_vals)

# --------------- Surface plot------------------
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.plot_surface(theta0_vals, theta1_vals, J_vals, rstride=2, cstride=2, lw=0, cmap=cm.jet)
ax.set_xlabel('theta_0')
ax.set_ylabel('theta_1')

# ----------------- Contour plot------------------

fig1 = plt.figure()
ax1 = fig1.add_subplot()
# Plot J_vals as 15 contours spaced logarithmically between 0.01 and 100
ax1.contour(theta0_vals, theta1_vals, J_vals, levels=np.logspace(-2, 3, 20))
ax1.set_xlabel('theta_0')
ax1.set_ylabel('theta_1')

# matplotlib interactive off to view the graph at the end of program
plt.ioff()
plt.show()


import numpy as np

def inc_index(vec,index,h):
    '''
    Auxiliary function for gradient and Hessian computation.
    Args:
        vec (array): numpy array.
        index (int): index.
        h (float):   quantity that vec[index] will be increased.
    Returns:
        vec (array): numpy array vec with vec[index] increased by h.
    '''
    vec[index] +=h
    return vec

def dec_index(vec,index,h=1):
    '''
    Auxiliary function for gradient and Hessian computation.
    Args:
        vec (array): numpy array.
        index (int): index.
        h (float):   quantity that vec[index] will be decreased.
    Returns:
        vec (array): numpy array vec with vec[index] decreased by h.
    '''
    vec[index] -=h
    return vec
def compute_error(x_obj,x_approx):
    '''
    Relative or absolute error between x_obj and x_approx.
    '''
    if np.linalg.norm(x_obj) > np.nextafter(0,1):
        Err=np.linalg.norm(x_obj-x_approx)/np.linalg.norm(x_obj)
    else:
        Err=np.linalg.norm(x_obj-x_approx)
    return Err
def norm_residual(feas_primal, feas_dual):
    '''
    Computes norm of residual for Newtons infeasible initial point method
    '''
    return np.sqrt(np.linalg.norm(feas_primal)**2 +\
                   np.linalg.norm(feas_dual)**2
                   )
def log_barrier_aux_eval_constraints(eval_f_const_inequality):
    '''
    Auxiliary function for evaluation of constraint inequalities in logarithmic barrier
    '''
    #get values that are nonnegative through indexes
    idx_zeros = np.logical_and(eval_f_const_inequality < np.nextafter(0,1),
                               eval_f_const_inequality > -np.nextafter(0,1))
    idx_positive = eval_f_const_inequality > 0
    idx  = np.logical_or(idx_zeros, idx_positive)
    #eval constraint inequality functions
    #next line produces warning if a value of constraint is nonnegative
    eval_f_const_inequality = np.log(-eval_f_const_inequality)
    #assign large value for values positive or equal to 0
    eval_f_const_inequality[idx] = 1e10
    return eval_f_const_inequality
def constraint_inequalities_funcs_eval(x, constraint_inequalities):
    '''
    Auxiliary function for the evaluation of constraint inequalities in logarithmic barrier function
    '''
    const_ineq_funcs_eval = np.array([const(x) for const in \
                                      constraint_inequalities_funcs_generator(constraint_inequalities)])
    return const_ineq_funcs_eval
def logarithmic_barrier(f,x, t_path, constraint_inequalities):
    '''
    Implementation of Logarithmic barrier function.
    '''
    constraint_ineq_funcs_eval = constraint_inequalities_funcs_eval(x,constraint_inequalities)
    log_barrier_const_eval = log_barrier_aux_eval_constraints(constraint_ineq_funcs_eval)
    return t_path*f(x) + np.sum(log_barrier_const_eval)
def constraint_inequalities_funcs_generator(constraint_inequalities):
    '''
    Generator for functional form of inequalities.
    For every example this function produces different fuctions.
    '''
    for k, v in constraint_inequalities.items():
        yield v


__author__ = 'Dmitry Patashov'

import numpy as np
import cv2
import os
from matplotlib import pyplot as plt
from numpy import linalg as LA

# Question 1
def myChessMatrix(n):

    if n != np.uint64(n):
        return None

    size = 2*n
    myMat = np.zeros((size,size))
    myMat[0::2, 1::2] = 1
    myMat[1::2, 0::2] = 1

    return myMat

# Question 2
def countMyChars(myStr):

    if myStr.__class__ != ''.__class__:
        return None

    myLstr = myStr.lower()
    myD = {}
    while myLstr != '':
        myD[myLstr[0]] = myLstr.count(myLstr[0])
        myLstr = myLstr.replace(myLstr[0], '')

    return myD

# Question 3
def myListHist(myList):

    if myList.__class__ != [].__class__:
        return None

    def myListSimplifier(myList, mySimpleList):

        for k in range(len(myList)):
            if myList[k].__class__ == [].__class__:
                myListSimplifier(myList[k], mySimpleList)
            else:
                mySimpleList.append(np.float64(myList[k]))

        return None

    mySimpleList = list()
    myListSimplifier(myList, mySimpleList)

    myValArr = np.asarray(mySimpleList)
    maxVal = np.int64(np.max(myValArr))
    myHist = np.zeros((maxVal + 1))

    for k in range(maxVal + 1):
        myHist[k] = len(myValArr[myValArr == k])

    return myHist

# Question 4
def myKNearest(k, x, myArray):

    if k != np.round(k):
        return None
    elif k <= 0:
        return None

    if myArray.__class__ != np.ndarray:
        return None

    indArr = np.argsort(np.abs(x - myArray))

    return myArray[indArr[0:k]]

# Question 5
def myFastToneReplacement(img, fromA, toB, equalsC):
    if img.__class__ != np.ndarray:
        return None

    myImg = img.copy()
    # ------------------------------------------------------------------
    # D = myImg.shape
    # if len(D) == 2:
    #     for i in range(D[0]):
    #         for j in range(D[1]):
    #             if myImg[i, j] >= fromA and myImg[i, j] <= toB:
    #                 myImg[i, j] = equalsC
    # elif len(D) == 3:
    #     for m in range(D[0]):
    #         for n in range(D[1]):
    #             for k in range(D[2]):
    #                 if myImg[m, n, k] >= fromA and myImg[m, n, k] <= toB:
    #                     myImg[m, n, k] = equalsC
    # else:
    #     return None
    # ------------------------------------------------------------------

    myImg[np.logical_and(myImg>=fromA, myImg<=toB)] = equalsC

    return myImg

# Question 6
def myLRcycles(TrainData, TrainLabel, W, gamma, iterNum):

    if TrainData.__class__ != np.ndarray or TrainLabel.__class__ != np.ndarray or W.__class__ != np.ndarray:
        return None
    if iterNum != np.int64(iterNum) or gamma != np.abs(gamma):
        return None

    def SigmoidF(w, x):
        return 1 / (1 + np.exp(-x.dot(w)))

    def DerivativeCalcF(TrainData, TrainLabel, w):

        return TrainData.transpose().dot(TrainLabel - SigmoidF(w, TrainData))

    for k in range(iterNum):

        W = W + gamma * DerivativeCalcF(TrainData, TrainLabel, W)

    return W

# Question 7
def myGradDescent(signal, time, startLoc, iterNum, stepSize):

    if signal.__class__ != np.ndarray or time.__class__ != np.ndarray:
        return None
    if iterNum != np.int64(iterNum) or stepSize != np.abs(stepSize):
        return None

    xn = startLoc
    indX = np.argmin(np.abs(time - xn))
    df = np.gradient(signal)

    for k in range(iterNum):
        xn = xn - stepSize * df[indX]
        indX = np.argmin(np.abs(time - xn))

    return xn

# Question 8
def myKMeansIter(dataMet, centers):
    if type(dataMet) != np.ndarray or type(centers) != np.ndarray:
        return None
    if len(dataMet.shape) != 2 or len(centers.shape) != 2:
        return None

    dim = dataMet.shape
    labels = np.zeros((dim[0]))
    for i in range(dim[0]):
        labels[i] = np.argmin(np.sqrt(np.sum((centers - dataMet[i])**2, axis=1)))

    nCe = centers.copy()
    for i in range(nCe.shape[0]):
        a2 = labels == i
        a1 = dataMet[a2]
        nCe[i] = np.mean(a1, axis=0)
    return nCe

# Question 9
def myPeakDetect(Signal):

    if Signal.__class__ != np.ndarray:
        return None

    locs = []
    for k in range(1,len(Signal)-1):

        if Signal[k] > Signal[k-1] and Signal[k] > Signal[k+1]:
            locs.append(k)

    return np.asarray(locs)


import numpy as np
import matplotlib.pyplot as plt

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

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

plt.figure(1)
'''
    subplot(nrows, ncols, plot_number)
    分割当前的图片为 nrows * ncols 的矩形阵列，plot-number指当前是第几片，计数从左到右，从上到下
    1，如果都是小于10的横纵，可以连起来写，比如，subplot(223) ， 等效于subplot(2, 2, 3)， 即图片会分成2*2的4块， 当前指明第3块
    2. 默认是 111, 就只有1块
'''
plt.subplot(221)            # 2*2 块，当前是第1块
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
plt.xlabel("aaax")

plt.subplot(2,2,3, facecolor='y')   # 2*2块，当前是第3块
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')

plt.subplot(2,4,4,facecolor='y')   # 2*4块，之前的2块，肯定和221的设计画布有重叠， 所以至少应该从3块开始
plt.plot(range(12))

plt.subplot(2,4,8,  facecolor='r', polar=True)
plt.plot(range(12))
plt.xlabel("ploar-x")

plt.show()

'''
还有其它的关键字参数

facecolor:      背景颜色指定
    The background color of the subplot, which can be any valid color specifier. See matplotlib.colors for more information.
polar:
    A boolean flag indicating whether the subplot plot should be a polar projection. Defaults to False.
projection:
    A string giving the name of a custom projection to be used for the subplot. This projection must have been previously registered. See matplotlib.projections.
'''


# coding: utf-8

# In[1]:

import sympy

# In[2]:

sympy.init_printing()

# In[3]:

from sympy import I,pi,oo

# In[4]:

x = sympy.Symbol("x")

# In[5]:

y = sympy.Symbol("y", real=True)

# In[6]:

y.is_real


import pandas as pd
import numpy as np

datos = pd.read_csv("inel.csv")
experimentales = datos["Delta Energía (J)"]
psinf = datos["pdenergia3"]
pfinal = datos["pfinal"]

print(experimentales)
print(psinf)
print(pfinal)

corr_matrix = np.corrcoef(experimentales, psinf)
corr = corr_matrix[0, 1]
r_sq = corr ** 2
n = 6
k = 3
r_sqa = 1 - ((1 - r_sq) * (n - 1) / (n - k - 1))

print("*Modelo sin fricción*")
print("R^2:", r_sq)
print("R^2 ajustado: ", r_sqa)

corr_matrix = np.corrcoef(experimentales, pfinal)
corr = corr_matrix[0, 1]
r_sq = corr ** 2
n = 6
k = 4
r_sqa = 1 - ((1 - r_sq) * (n - 1) / (n - k - 1))

print("*Modelo con fricción*")
print("R^2:", r_sq)
print("R^2 ajustado: ", r_sqa)


import numpy as np

DIMENSIONS = 2

# Function to implement bayes classifier for Gaussian, Exponential class density
# Prior probability is assumed to be equal unless specified
def bayes_gaussian_exponential(theta_0, theta_1, X_test, p0=0.5, p1=0.5):
    # Density Class 0 parameters - mean and covariance matrix
    mu_0 = theta_0[0]
    sigma_0 = theta_0[1]
    det_sigma_0 = np.linalg.det(sigma_0)
    inv_sigma_0 = np.linalg.inv(sigma_0)

    # Density Class 1 parameters - lambda 1 and lambda 2
    # The features are assumed to be independent for exponential
    lambda_1 = theta_1[0]
    lambda_2 = theta_1[1]

    # Placeholder for output
    Y_pred = np.zeros(len(X_test))

    # Estimate the posterior density and label the output properly
    for idx in range(len(X_test)):
        X = X_test[idx]
        q0 = 1 / (((2 * np.pi) ** DIMENSIONS / 2) * (det_sigma_0 ** 0.5)) * np.exp(
            -0.5 * (X - mu_0) @ inv_sigma_0 @ np.transpose(X - mu_0)) * p0
        X = np.abs(X)
        q1 = lambda_1 * np.exp(-lambda_1 * X[0]) * lambda_2 * np.exp(-lambda_2 * X[1]) * p1

        if q0 >= q1:
            Y_pred[idx] = 0
        else:
            Y_pred[idx] = 1

    return Y_pred


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
import statsmodels.formula.api as sm

""" ========== Simple Linear Regression ========== """

base = pd.read_csv('mt_cars.csv')
base = base.drop(['Unnamed: 0'],axis=1)

X = base.iloc[:,2].values
y = base.iloc[:,0].values

correlation = np.corrcoef(X,y)

X = X.reshape(-1,1)

model = LinearRegression()
model.fit(X,y)
model.intercept_
model.coef_
model.score(X,y) # R²

# Adjusted R²
model_adj = sm.ols (formula = 'mpg ~ disp', data = base) # adjusted model
model_trn = model_adj.fit() # trained model
model_trn.summary()
plt.scatter(X,y) #dispersion graph
plt.plot(X,model.predict(X),color = 'red')

# For disp = 200, mpg = ?

model.predict([[200]])

""" ========== Multiple Linear Regression ========== """

X1 = base.iloc[:,1:4].values
y1 = base.iloc[:,0].values

model1 = LinearRegression()
model1.fit(X1,y1)

# Adjusted R²
model1_adj = sm.ols (formula = 'mpg ~ cyl + disp + hp', data = base) # adjusted model
model1_trn = model1_adj.fit() # trained model
model1_trn.summary()

# For cyl = 4, disp = 200, hp = 100, mpg = ?
condition = np.array([4,200,100]).reshape(1,-1)
model1.predict(condition)


#Takes a field-centric x-y position at height, and converts that into a pixel
#Allows a small outline of the AOE to be created
#Only correct for equiangular fisheye of 180 degree coverage!
#Change if camera changes

#Standard Imports
import math
import numpy as np

def pointPixelEA(tgt,tgt_h,robot,robot_h,robot_heading): #m,m,m,m,m,m,radians; target position, target height, robot position, robot height, robot heading
    focal_length = 214.1528 #pixels #Change this if camera profile changes, will fuck things if not done, keep hardcoded

    #Gives height for later math, eliminate for performace, keep for elevated accuracy
    delta_height = tgt_h - robot_h

    POI_loc = (tgt[0],-1*tgt[1])
    robot_loc = robot

    heading = robot_heading

   #Define Local Functions
    def getPictureRadius(focal_length_z,robot_heading_z,robot_loc_z,POI_loc_z,delta_height_z): #Gives radius in pixels of desired point
        radius = math.sqrt((POI_loc_z[0] - robot_loc_z[0])**2 + (POI_loc_z[1] - robot_loc_z[1])**2 )

        #Find Zenith Angle
        zenith_angle = math.pi/2 - math.atan2(delta_height_z,radius)

        #Corner overlap testing
            #Defines radius on sensor based on focal length and zenith angle, equisolid testing, 180 FOV
        r = 2 * focal_length_z * math.sin(zenith_angle * 0.5)

        return r

    #Finds angle between tgt vector and optical axis
    def findTheta(POI_loc_z,robot_loc_z,robot_heading_z):
        theta = (math.atan2(POI_loc_z[1] - robot_loc_z[1],POI_loc_z[0] - robot_loc_z[0]) + robot_heading_z)%(2*math.pi)
        return theta

    #Converts from polar to cartesian coordinates, outputs x-coordinate
    def polarCartesianX(theta_z,point_radius_z):
        x = point_radius_z * math.cos(theta_z)
        return x

    #Converts from polar to cartesian coordinates, outputs y-coordinate
    def polarCartesianY(theta_z,point_radius_z):
        y = point_radius_z * math.sin(theta_z)
        return y

    #Determines how far out the target pixel is, in pixels.
    point_radius = getPictureRadius(focal_length,heading,robot_loc,POI_loc,delta_height)
    #Outputs theta
    zulu = findTheta(POI_loc,robot_loc,heading)

    #Final Calculation
    pixel_x = polarCartesianX(zulu,point_radius)
    pixel_y = polarCartesianY(zulu,point_radius)

    return np.array([pixel_x,pixel_y]) #Returns revised pixel position

#NOTES:
    '''
    Field is measured with y axis in starting direction of robot from red, with x 90 degrees clockwise
    from that. Robot Angle is measured with y towards front of robot, x 90 degrees clockwise.
    Heading is the differental between each y axis
    '''


import numpy as np
import scipy.io as sio
import matplotlib.pyplot as plt

mat_data = sio.loadmat('D:\hello\ex5data1.mat')
X = mat_data['X']
y = mat_data['y'].ravel()

plt.figure()
plt.plot(X, y, linestyle='', marker='x', color='r')
plt.xlabel('Change in water level (x)')
plt.ylabel('Water flowing out of the dam (y)')

m=len(y)

def cost(t,x,y):

    j = (1.0/(2*m)) * np.sum(np.square(x.dot(t) - y))
    grad = (1.0/m) * x.T.dot(x.dot(t) - y)

    return(j,grad)

# using advanced optimisation
from scipy import optimize as opt
x = np.hstack((np.ones((m, 1)), X))
t = np.zeros((2,1))

t, nfeval ,un = opt.fmin_tnc(func = cost,x0=t,args=(x,y))

ht = t[0] + t[1]*X
plt.plot(X,ht,color='b')
plt.show()

Machine Learning/1.linear regression/advanced opt in linear regression.py


import numpy as np
import random as ra

def f(x, y):
    r1 = np.sqrt(x**2 + (y-4)**2)
    return r1

def g(x, y):
    r2 = np.sqrt((x-4)**2 + y**2)
    return r2

def getProbability(n):
    counter = 0
    darkYellow = 0
    squareArea = 4*4

    while n > counter:
        x = ra.uniform(0, 4)
        y = ra.uniform(0, 4)

        if (f(x, y) <= 4 and g(x, y) <= 4):
            darkYellow += 1
        counter += 1

    probabilityDarkYellow = (darkYellow / n)
    circlesArea = squareArea * probabilityDarkYellow
    probabilityDarkYellow_percentage = round((darkYellow / n)*100,2)

    print(f'Estimated area is: {circlesArea} cm2. Out of {n} times, {darkYellow} coordinates were inside the dark yellow area.')

getProbability(10000)


import numpy as np

# Activation Functions
def identity(input):
    """Compute identity neuron activation """

    return input

def sigmoid(input):
    """Compute sigmoid neuron activation """

    return 1/(1 + np.exp(-input))

def tanh(input):
    """ Compute Tanh neuron activation """

    return np.tanh(input)

def relu(input):
    """ Compute ReLu neuron activation """

    return np.maximum(0, input)

def softmax(input):
    """ Compute softmax neuron activation with numerical stability protection"""

    exps = np.exp(input - np.amax(input, axis=0))
    return exps/np.sum(exps, axis=0)

ACTIVATIONS = {'identity': identity,
               'sigmoid': sigmoid,
               'tanh': tanh,
               'relu': relu,
               'softmax': softmax}

# Activation function derivatives
def derivative_identity(identity_output):
    """Compute derivative of identity function """

    return np.ones(identity_output.shape)

def derivative_sigmoid(sigmoid_output):
    """ Compute derivative of sigmoid function """

    return sigmoid_output*(1 - sigmoid_output)

def derivative_tanh(tanh_output):
    """ Compute derivative of Tanh function """

    return 1 - tanh_output**2

def derivative_relu(relu_output):
    """ Compute derivative of ReLu function """

    relu_output[relu_output <= 0] = 0
    relu_output[relu_output > 0] = 1

    return  relu_output

def derivative_softmax(softmax_output):
    """ Compute softmax neuron activation """
    pass

ACTIVATIONS_DERIVATIVES = {'identity': derivative_identity,
                           'sigmoid': derivative_sigmoid,
                           'tanh': derivative_tanh,
                           'relu': derivative_relu,
                           'softmax': derivative_softmax}

# Cost functions
def mean_square_error(model_output, target):
    """ Compute mean square error """

    if model_output.shape != target.shape:
        raise ValueError('Dimensions of model output and target do not match')

    return np.sum(np.square(target - model_output))/model_output.size/2

def binary_cross_entropy(model_output, target):
    """ Compute binary cross-entropy cost """

    if model_output.shape != target.shape:
        raise ValueError('Dimensions of model output and target do not match')

    # Limit the model output to the interval (0,1) to prevent divide by zero
    eps = np.finfo(model_output.dtype).eps
    model_output = np.clip(model_output, eps, 1- eps)

    return -np.sum(target * np.log(model_output) + (1 - target)*np.log(1 - model_output))/model_output.shape[0]

def cross_entropy(model_output, target):
    """ Compute cross-entropy cost """

    if model_output.shape != target.shape:
        raise ValueError('Dimensions of model output and target do not match')

    # Limit the model output to the interval (0,1) to prevent divide by zero
    eps = np.finfo(model_output.dtype).eps
    model_output = np.clip(model_output, eps, 1- eps)

    return -np.sum(target * np.log(model_output))/model_output.shape[0]

COST_FUNCTIONS = {'mse': mean_square_error, 'binary_cross_entropy': binary_cross_entropy, 'cross_entropy':cross_entropy}
COST_FUNCTION_SELECTION = {'identity': mean_square_error, 'sigmoid': 'binary_cross_entropy', 'softmax': 'cross_entropy'}

# Cost function derivatives
def derivative_mean_square_error(model_output, target):
    """ Compute derivative of mean square error cost function"""

def derivative_cross_entropy(model_output, target):
    """ Compute derivative of cross-entropy cost function"""

    return model_output - target

COST_FUNCTION_DERIVATIVES = {'mse': derivative_mean_square_error, 'cross_entropy': derivative_cross_entropy}

# Regularisation Cost functions
def l2_cost(network, l2_param, targets):

    # get weights
    weights = network.get_weights()[0]

    l2_cost = 0
    for layer_weights in weights:
        l2_cost += 0.5 * l2_param * np.sum(layer_weights**2)/targets.shape[0]

    return l2_cost

# Regularisation Cost function derivatives
def l2_cost_derivative(network, l2_param, targets):

    # get weights
    weights = network.get_weights()[0]

    l2_cost_derivative = 0
    for layer_weights in weights:
        l2_cost_derivative += l2_param * np.sum(layer_weights)/targets.size

    return l2_cost_derivative

REGULARISATION_COST_FUNCTIONS = {'l2': l2_cost}
REGULARISATION_COST_FUNCTION_DERIVATIVES = {'l2': l2_cost_derivative}


#call numpy package
import numpy as np

#input data
x = [77, 50, 99, 60, 90, 82, 93, 75, 86, 99, 55, 79]

#numpy.mean(), sum(), and len()
get_sample_mean = np.sum(x) / (len(x) - 1)

print("Input : ", x)
print("Sample mean of x : ", get_sample_mean)


import numpy as np
import matplotlib.pyplot as plt
from scipy.special import sph_harm
from scipy.special import assoc_laguerre

def get_wave_r1(n,l,m,Zm,r):
        x = r
        y = 0
        z = 0
        X, Z = np.meshgrid(x, z)

        rho = np.linalg.norm((X,y,Z), axis=0) *Zm / n
        Lag = assoc_laguerre(2 * rho, n - l - 1, 2 * l + 1)
        Ylm  = sph_harm(m, l, np.arctan2(y,X), np.arctan2(np.linalg.norm((X,y), axis=0), Z))
        Psi = np.exp(-rho) * np.power((2*rho),l) * Lag * Ylm

        density = np.conjugate(Psi) * Psi
        density = density.real
        return density[0]

def get_wave_r2(n,l,m,r,Zm):
        x = 0
        y = 0
        z = r
        X, Z = np.meshgrid(x, z)

        rho = np.linalg.norm((X,y,Z), axis=0)*Zm  / n
        Lag = assoc_laguerre(2 * rho, n - l - 1, 2 * l + 1)
        Ylm  = sph_harm(m, l, np.arctan2(y,X), np.arctan2(np.linalg.norm((X,y), axis=0), Z))
        Psi = np.exp(-rho) * np.power((2*rho),l) * Lag * Ylm

        density = np.conjugate(Psi) * Psi
        density = density.real
        return density[0]

def get_wave_r3(n,l,m,r,Zm):
        x = 0
        y = r
        z = 0
        X, Z = np.meshgrid(x, z)

        rho = np.linalg.norm((X,y,Z), axis=0)*Zm  / n
        Lag = assoc_laguerre(2 * rho, n - l - 1, 2 * l + 1)
        Ylm  = sph_harm(m, l, np.arctan2(y,X), np.arctan2(np.linalg.norm((X,y), axis=0), Z))
        Psi = np.exp(-rho) * np.power((2*rho),l) * Lag * Ylm

        density = np.conjugate(Psi) * Psi
        density = density.real
        return density[0]

def get_wave_mean(n,l,m,r,Zm):
    n = n
    l = l
    m = m
    Zm = Zm
    wave1 =get_wave_r1(n,l,m,r,Zm)[0]
    wave2 =get_wave_r2(n,l,m,r,Zm)[0]
    wave3 =get_wave_r3(n,l,m,r,Zm)[0]
    mean_wave = (wave1+ wave2 + wave3)/3
    #return mean_wave+wave1+wave2+wave3
    return np.array([mean_wave, wave1, wave2, wave3])

if __name__ == '__main__':


# coding: utf-8

# In[254]:

import pandas as pd
import numpy as np
import os
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# In[255]:

#checking the path directory
print("Previous directory",os.getcwd())
#Now changing the path directory
path=r"C:\Users\Pavan\Desktop\Machine Learning Github\Home Works\HW1"
os.chdir(path)
print("Current directory",os.getcwd())

# Hosuing data set ----Question 1
#
# Run linear regression using Normal Equations and Mean Square Error without using the libraries

# In[256]:

#Loading the DataSet
col_names=["CRIM","ZN","INDUS","CHAS","NOX","RM","AGE","DIS","RAD","TAX","PTRATIO","B","LSTAT","MEDV"]
train_housing=pd.read_table("housing_train.txt",sep="\s+",names=col_names)
train_housing

# In[257]:

y_train=train_housing["MEDV"]
y_train

# In[258]:

del train_housing["MEDV"]
train_housing

# In[259]:

#Using the Normal Equations I am calculating the coefficients of the paremets(w1,w2,w3-----w13)
#Now we have the Data matrix(X) and the labels(Y) now we need to find the coefficients
w_normal_equations=np.linalg.inv(train_housing.T.dot(train_housing)).dot(train_housing.T).dot(y_train)
w_normal_equations

# In[260]:

w=np.reshape(w_normal_equations,(1,13))
w

# In[261]:

##Function for calculating mean squared error using the Normal Equations for the training set
def mean_square_error(y,w,x,n_iterations):
    squared_error=0
    mean_squared_error=0
    for i in range(n_iterations):#For all the data points considerong the (Y-h(x))i.e(y-WX)
        squared_error=squared_error+((y_train[i]-(w.dot(x.iloc[i])))*(y[i]-(w.dot(x.iloc[i]))))
    mean_squared_error=squared_error/n_iterations

    print("Mean Squared Error for the training is:",mean_squared_error)

mean_square_error(y_train,w,train_housing,433)

# In[262]:

#Now we are conisdering the testing data set
test_data=pd.read_table("housing_test.txt",sep="\s+",header=None,names=col_names)
test_data

# In[263]:

y_test=test_data["MEDV"]
y_test

# In[264]:

del test_data["MEDV"]

# In[265]:

x_test=test_data
x_test

# In[266]:

##The mean squared error function is already defined before and I just called that function using the function name
mean_square_error(y_test,w,x_test,74)

#
train error: 24.47
#
test error: 24.29
#
using the Normal Equations

#
Part 2 : Perform everything using the ScikitLearn package

# In[270]:

##Mean squared error using Scikit Learn for the training data
lin_reg = LinearRegression()
lin_reg.fit(train_housing, y_train)# Finding the parameters
lin_reg.intercept_, lin_reg.coef_
train_predictions=lin_reg.predict(train_housing)
print("\n The MSE Error for testing is:",mean_squared_error(y_train,train_predictions))

# In[272]:

##Now calculating the mean sqaured error for the testing dataset
test_predictions=lin_reg.predict(test_data)
print("\n The MSE Error for the testing is:",mean_squared_error(y_test,test_predictions))

#
Training error: 22.08
#
Testing error: 22.63
#
using the scikitlearn package

#
NOW PERFORMING EVERYTHING BY NORMALIZING the Data

# In[273]:

train_housing

# In[274]:

#This gives the total Number of time syou need to learn the inner loop
x=len(train_housing)
x

# In[275]:

#This give sthe total number of times you need to run the for loop
y=len(train_housing.columns)
y

# In[276]:

#Function for Normalization
#X-Number of Rows
#Y- Number of columns
def Normalization(train_housing,x,y):
    for i in range(y):
        z=train_housing.columns[i]
        for j in range(x):
            train_housing[z].iloc[j]=(((train_housing[z].iloc[j]-(min(train_housing[z])))/(max(train_housing[z])-min(train_housing[z]))))

# In[277]:

#This is the Normalized data(Training Data)
Normalization(train_housing,x,y)

# In[278]:

#This is Normalizing the test data
x=len(test_data)
y=len(test_data.columns)
Normalization(x_test,x,y)

# In[279]:

x_test

# In[280]:

train_housing.shape

# In[281]:

y_train.shape

# In[282]:

w_equations=np.linalg.inv(train_housing.T.dot(train_housing)).dot(train_housing.T).dot(y_train)
w_equations

# In[283]:

w_new=w_equations.reshape(1,13)
w_new

# In[284]:

#This is forthe training data
mean_square_error(y_train,w_new,train_housing,433)

# In[285]:

#Now calculating the error for the test data
mean_square_error(y_test,w_new,x_test,74)

#
 Results:
#
 Training Error: 26.33
#
 Testing Error:  32.104

# In[286]:

#by using the scikit learn library
lin_reg = LinearRegression()
lin_reg.fit(train_housing, y_train)# Finding the parameters
lin_reg.intercept_, lin_reg.coef_
train_predictions=lin_reg.predict(train_housing)
print("\n The MSE Error for testing is:",mean_squared_error(y_train,train_predictions))

# In[287]:

##Now calculating the mean sqaured error for the testing dataset
test_predictions=lin_reg.predict(x_test)
print("\n The MSE Error for the testing is:",mean_squared_error(y_test,test_predictions))

#
 By using library:
#
 Training Error: 25.1277
#
 Testing Error:  30.2312


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation
import functions

plt.style.use('seaborn-pastel')

def animateDoublePendulum(file, fps, animate = True, verbose = False, save = False):
	# load data and assign them
	if verbose: print("Load data from file", file)
	settings, data = functions.loadDataFromFile(file)
	m1, m2, l1, l2, g, t_max, dt, sim_mode = settings["m1"], settings["m2"], settings["l1"], settings["l2"], settings["g"], settings["tmax"], settings["dt"], settings["sim"]
	t, q1, q2, p1, p2 = data["t"], data["q1"], data["q2"], data["p1"], data["p2"]
	n = len(t)
	if verbose: print("Loading complete.\nStarting calculation.")
	# calculating the x, y, e_kin, e_pot, e_tot values
	x1 = l1*np.sin(q1)
	x2 = x1 + l2*np.sin(q2)
	y1 = -l1*np.cos(q1)
	y2 = y1 - l2*np.cos(q2)
	E_kin = .5*m1*l1**2*p1**2 + .5*m2*(l1**2*p1**2 + l2**2*p2**2 + 2*p1*p2*l1*l2*np.cos(q1 - q2))
	E_pot = -g*(m1*l1*np.cos(q1) + m2*(l1*np.cos(q1) + l2*np.cos(q2)))
	E_tot = E_kin + E_pot
	if verbose: print("Calculation complete.\nStart plotting.")
	if animate:
		# plot the pendulum
		fig = plt.figure(figsize=(8,8))
		gs = fig.add_gridspec(ncols=2, nrows=2)
		time_template = 'time = %.2fs'

		# prepare realspace plot
		ax = fig.add_subplot(gs[0,0])
		ax.set_xlim(-(l1+l2), l1+l2)
		ax.set_ylim(-(l1+l2), l1+l2)
		ax.set_aspect('equal')
		ax.set_xlabel("X")
		ax.set_ylabel("Y")
		time_text = ax.text(0.05, 0.9, '0 s', transform=ax.transAxes)

		# prepare Energy-time plot
		ax1 = fig.add_subplot(gs[1,0])
		ax1.set_xlim(min(t), max(t))
		ax1.set_ylim(min(min(E_tot), min(E_kin), min(E_pot)), max(max(E_tot), max(E_kin), max(E_pot)))
		ax1.grid()
		ax1.set_xlabel("Time / s")
		ax1.set_ylabel("Energy / arb. units")

		# prepare phasespace plot 1
		ax2 = fig.add_subplot(gs[0,1])
		ax2.set_xlim(min(q1), max(q1))
		ax2.set_ylim(min(p1), max(p1))
		ax2.set_xlabel(r"$\vartheta_1$")
		ax2.set_ylabel(r"$p_1$")

		# prepare phasespace plot 2
		ax3 = fig.add_subplot(gs[1,1])
		ax3.set_xlim(min(q2), max(q2))
		ax3.set_ylim(min(p2), max(p2))
		#ax3.set_xlim(min(min(q1), min(q2)), max(max(q1), max(q2)))
		#ax3.set_ylim(min(min(p1), min(p2)), max(max(p1), max(p2)))
		ax3.set_xlabel(r"$\vartheta_2$")
		ax3.set_ylabel(r"$p_2$")

		# init plots
		## realspace
		line, = ax.plot([0, x1[0], x2[0]], [0, y1[0], y2[0]], 'o-',lw=2)
		## energy time
		E_tot_graph, = ax1.plot([],[])
		E_kin_graph, = ax1.plot([],[])
		E_pot_graph, = ax1.plot([],[])
		## phase space
		point1, = ax2.plot([q1[0]], [p1[0]], '')
		point2, = ax3.plot([q2[0]], [p2[0]], '')

		def animate(i):
			x = [0, x1[i], x2[i]]
			y = [0, y1[i], y2[i]]
			t_list = t[:i]
			E_tot_list = E_tot[:i]
			E_kin_list = E_kin[:i]
			E_pot_list = E_pot[:i]

			q1_list = q1[:i]
			q2_list = q2[:i]
			p1_list = p1[:i]
			p2_list = p2[:i]

			line.set_data(x, y)
			E_tot_graph.set_data(t_list, E_tot_list)
			E_kin_graph.set_data(t_list, E_kin_list)
			E_pot_graph.set_data(t_list, E_pot_list)
			point1.set_data(q1_list, p1_list)
			point2.set_data(q2_list, p2_list)
			time_text.set_text(time_template % (t[i]))
			return line, E_tot_graph, E_kin_graph, E_pot_graph, point1, point2, time_text

		anim = FuncAnimation(fig, animate, frames=np.arange(0, n, max(int(1/fps/dt),1)), interval=1000/fps, blit = True)
		if save:
			if verbose: print("Video saving...")
			anim.save(file + ".mp4", fps=fps)
			if verbose: print("Video saving done.")
		else:
			plt.show()
	else:
		# plot the energies
		fig = plt.figure()

		plt.plot(t, E_kin, label="Kinetic")
		plt.plot(t, E_pot, label="Potentail")
		plt.plot(t, E_tot, label="Total")

		plt.ylim([-50,200])
		plt.legend()
		plt.show()
"""
### >>> BEGIN SETUP <<<
file = "default.txt"
fps = 30
animate_pendulum = True
plot_energies = False
### >>> END SETUP <<<

animateDoublePendulum(file, fps)
"""


#!/usr/bin/nv python
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------
# Filename: wavelets.py
#  Purpose: Signal Analysis
#   Author: Vidal Gonzalez P
#    Email: vidalgonz8@gmail.com
# --------------------------------------------------------------------
"""

        Some useful functions.

"""
import numpy as np

def ormsby(freqs, tvec):
    '''
    Computes ormsby amplitude wavelet.
    '''
    f1, f2, f3, f4 = freqs
    a1 = ((np.pi * f4)**2 / (np.pi * f4 - np.pi * f3)) * np.sinc(f4 * tvec)**2
    a2 = ((np.pi * f3)**2 / (np.pi * f4 - np.pi * f3)) * np.sinc(f3 * tvec)**2
    b1 = ((np.pi * f2)**2 / (np.pi * f2 - np.pi * f1)) * np.sinc(f2 * tvec)**2
    b2 = ((np.pi * f1)**2 / (np.pi * f2 - np.pi * f1)) * np.sinc(f1 * tvec)**2
    return((a1 - a2) - (b1 - b2))

def ricker(fc, tvec):
    '''
    Computes ricker amplitude wavelet
    '''
    return ((1.0 - 2.0 * np.pi**2 * fc**2 * tvec**2) * \
        np.exp(-np.pi**2 * fc**2 * tvec**2))

def main():
    pass

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


import math
import numpy as np
from scipy.spatial.distance import cdist

__all__ = ("naive_gaussian_kernel", "naive_sigmoid_kernel", "naive_laplacian_kernel",
           "naive_linear_kernel", "naive_polynomial_kernel", "naive_matern_kernel",)

def naive_gaussian_kernel(X1, X2, sigma):
    pairwise_dists = cdist(X1, X2, 'sqeuclidean')
    return np.exp(-pairwise_dists / (2 * sigma ** 2))

def naive_laplacian_kernel(X1, X2, sigma):
    pairwise_dists = cdist(X1, X2, 'euclidean')
    return np.exp(-pairwise_dists / sigma)

def naive_linear_kernel(X1, X2, beta, sigma):
    return beta + (1 / sigma ** 2) * X1 @ X2.T

def naive_sigmoid_kernel(X1, X2, alpha, beta):
    out = X1 @ X2.T
    return np.tanh(out * alpha + beta)

def naive_polynomial_kernel(X1, X2, alpha, beta, degree):
    out = X1 @ X2.T
    return np.power(out * alpha + beta, degree)

def naive_matern_kernel(X1, X2, sigma, nu):
    pairwise_dists = cdist(X1 / sigma, X2 / sigma, 'euclidean')

    if nu == 0.5:
        K = np.exp(-pairwise_dists)
    elif nu == 1.5:
        K = pairwise_dists * math.sqrt(3)
        K = (1. + K) * np.exp(-K)
    elif nu == 2.5:
        K = pairwise_dists * math.sqrt(5)
        K = (1. + K + K ** 2 / 3.0) * np.exp(-K)
    elif nu == np.inf:
        K = np.exp(-pairwise_dists ** 2 / 2.0)
    return K


"""
This module illustrates how to solve a system of equations using solve routine
and the linalg module.

Suppose we have the following system of equations:

    3x1 - 2x2 + x3 = 7
    x1 + x2 -2x3 = -4
    -3x1 -2x2 + x3 = 1

We can solve it by the single matrix equation:

    Ax = b
"""
import numpy as np
from numpy import linalg

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

b = np.array([7, -4, 1])

linalg.solve(A, b) # array([ 1., -1., 2.])


import numpy as np

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

print(sigmoid(5))
print(sigmoid(0.8))
a = np.full(5, 0.5)
print(a)
print(round(0.99999999, 3))

# b = [1, 1, 1] - 3
# print(b)
print(sigmoid(5.008))
print(sigmoid(0.843))

x1 = np.array([[1, 1, 1],
               [0, 0, 1],
               [0, 0, 1]])

x2 = np.array([[1, 0, 0],
               [1, 0, 0],
               [1, 1, 1]])

x3 = np.array([[1, 1, 1],
               [1, 0, 0],
               [1, 1, 1]])

d1 = np.array([1, 0, 0])
d2 = np.array([0, 1, 0])
d3 = np.array([0, 0, 1])

X = [x1, x2, x3]
D = [d1, d2, d3]
A = [0.0 for i in range(2)]
Z = [0.0 for i in range(2)]
O = np.full((3, 3), 0.0)
W1 = np.full((9, 2), 1.0)
W2 = np.full((2, 3), 1.0)

print(W1)
print(W1[:, 0])

for i in range(3):
    for k in range(3):
        A[k] = np.dot(X[i], W1[:, k])
        Z[k] = sigmoid(A[k])


import numpy as np
import scipy.stats as scp

def d(S_, K_, r_,sigma_ ,tau_):
    d1_ = 1 / (sigma_ * np.sqrt(tau_)) * ( np.log(S_/K_) + (r_ + sigma_**2/2) * tau_)
    d2_ = d1_ - sigma_ * np.sqrt(tau_)
    return d1_, d2_

def call_option(S_, K_, r_,sigma_ ,tau_ ,d1_,d2_):
    return scp.norm.cdf(d1_) * S_ - scp.norm.cdf(d2_) * K_ * np.exp(-r_ *tau_)

def call_vega(S_, tau_ , d1_):
    return S_ * scp.norm.pdf(d1_) * np.sqrt(tau_)

def Newton_Raphson(S_,K_,r_,tau_, sigma0_ ,price_, epsilon_):
    d1_,d2_ = d(S_, K_, r_,sigma0_ ,tau_)
    g = call_option(S_, K_, r_,sigma0_ ,tau_,d1_,d2_)-price_
    sigma_ = sigma0_ - g/call_vega(S_,tau_, d1_)
    while np.abs(sigma_-sigma0_)/sigma0_ > epsilon_:
        sigma0_ = sigma_
        d1_,d2_ = d(S_, K_, r_,sigma0_ ,tau_)
        g = call_option(S_, K_, r_,sigma0_ ,tau_,d1_,d2_)-price_
        sigma_ = sigma0_ - g/call_vega(S_,tau_, d1_)
    return sigma_


import numpy as np

# core functions
totalreturn = lambda x: (x[-1]/x[0])-1
finalreturn = lambda x: x[-1]
sharpe = lambda x: np.sqrt(12) * (np.mean(x) / np.std(x))
ann_vol = lambda x: np.sqrt(12) * np.std(x)
cagr = lambda x: ((((x[-1]) / x[0])) ** (12.0/(x.count()-1))) - 1
cagr2 = lambda x: ((np.mean(x)+1) ** 12) -1

def max_drawdown(X):
    mdd = 0
    peak = X[0]
    for x in X:
        if x > peak:
            peak = x
        dd = (peak - x)
        if dd > mdd:
            mdd = dd
    return mdd

def avg_max_drawdown(X):
    ldd = []
    mdd = 0
    peak = X[0]
    for x in X:
        if x > peak:
            peak = x
        dd = (peak - x)
        if dd > mdd:
            mdd = dd
            ldd.append(mdd)
    return 0 if len(ldd) == 0 else np.mean(ldd)

def bca_max_drawdown(X):
    mdd = 0
    peak = X[0]
    for x in X:
        if x > peak:
            peak = x
        if peak != 0:
            dd = 1-x/peak
        if dd > mdd:
            mdd = dd
    return mdd


import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

country = "id"
fdir = "../data/"
if country == "it":
    data = np.loadtxt(fdir+"itdata.csv", skiprows=1, delimiter=",", usecols=(1,2,3))[16:,:]
    day_since_ldown = data[:,0] - 16
elif country == "id":
    data = np.loadtxt(fdir+"data.csv", skiprows=1, delimiter=",", usecols=(1,2,4))[32:,:]
    day_since_ldown = data[:,0] - 31

new_case = data[:,1]
new_death = data[:,2]

def fcase(xdays, logyoffset, logygrad1, xchange, logygrad2):
    idxbefore = xdays < xchange
    idxafter = xdays >= xchange
    xbefore = xdays[idxbefore]
    xafter = xdays[idxafter]
    logybefore = logyoffset + logygrad1 * xbefore
    logyoffset2 = logyoffset + (logygrad1 - logygrad2) * xchange
    logyafter = logyoffset2 + logygrad2 * xafter
    y = xdays * 0
    y[idxbefore] = logybefore
    y[idxafter] = logyafter
    return y

p0case = (7.6, 0.19, 8.0, 0.01)
p0death = (4.7, 0.19, 8.0, 0.01)
pcase, pcasevar = curve_fit(fcase, day_since_ldown, np.log(new_case), p0=p0case)
pdeath, pdeathvar = curve_fit(fcase, day_since_ldown, np.log(new_death), p0=p0death)

pcasestd = np.sqrt(np.diag(pcasevar))
pdeathstd = np.sqrt(np.diag(pdeathvar))

dgcase = pcase[1] - pcase[3]
dgdeath = pdeath[1] - pdeath[3]
stddgcase = (pcasestd[1]**2 + pcasestd[3]**2)**.5
stddgdeath = (pdeathstd[1]**2 + pdeathstd[3]**2)**.5

print(pcase, pcasestd)
print(pdeath, pdeathstd)
print(dgcase / stddgcase)
print(dgdeath / stddgdeath)

country_name = {
    "it": "Italia",
    "id": "Indonesia"
}[country]
plt.title("Studi kasus: %s" % country_name)
plt.plot(day_since_ldown, new_case, 'C0o-', alpha=0.3, label="Kasus baru")
plt.plot(day_since_ldown, np.exp(fcase(day_since_ldown, *pcase)), 'C0-')
plt.plot(day_since_ldown, new_death, 'C1o-', alpha=0.3, label="Kematian / hari")
plt.plot(day_since_ldown, np.exp(fcase(day_since_ldown, *pdeath)), 'C1-')
plt.xlabel("Hari setelah social distancing")
plt.ylabel("Jumlah kasus")
plt.gca().set_yscale("log")
plt.legend()
plt.show()


from scipy import integrate
def integrand(z, y, x):
    return x * y**2 + z
x_lower_lim, x_upper_lim = 0.0, 0.5
y_lower_lim, y_upper_lim = lambda x:0.0, lambda x:1.0-2.0*x
z_lower_lim, z_upper_lim = lambda x,y:-1.0, lambda x,y:1.0+2.0*x-y
# int_{x=0}^{0.5} int_{y=0}^{1-2x} int_{z=-1}^{1+2x-y} (x y**2 + z) dz dy dx
integral,error = integrate.tplquad(integrand,
                                   x_lower_lim, x_upper_lim,
                                   y_lower_lim, y_upper_lim,
                                   z_lower_lim, z_upper_lim)
print(integral, error)

example_snippets/multimenus_snippets/Snippets/SciPy/Integration and ODE solvers/Integrate given function object/General purpose triple integration.py


#  BACKPROP MATH UNDERSTANDING
# DW/DX = DW/DY*DY/DX

# USING BASIC CHAIN RULE TO USE BACKPROP

import torch

x = torch.tensor(1.0)
y=torch.tensor(2.0)

w= torch.tensor(1.0,requires_grad=True)

y_hat = w*x
loss = (y_hat-y)**2

loss.backward()

print(w.grad)

# GRAD_DESC WITH AUTOGRAD MANUALLY
import numpy as np
# f = w*x
# f = 2*x

x = np.array([1,2,3,4],dtype='float')
y = np.array([2,4,6,8],dtype='float')

w=0.0 #weights init

# model pred
def forward(x):
    return w*x

# loss = MSE
def loss(y,y_pred):
    return ((y_pred-y)**2).mean()

# then we cal gradients manually using loss
# MSE = 1/n * (w*x-y)**2
# d(mse)/dw = 1/n 2x(w*x - y)

def gradients(x,y,y_pred):
    return np.dot(2*x,y_pred-y).mean()

print(f'prediction before for f(5):{forward(5):.3f}')

n_iters = 20
lr = 1e-2
for epoch in range(n_iters):
    # forward pass
    y_pred = forward(x)
    # loss cal
    l = loss(y,y_pred)
    # gradients update with weights
    dw = gradients(x,y,y_pred)

    # update weights
    w -= lr*dw

    if epoch%3 ==0:
        print(f'after {epoch} epoch\'s weight\'s are {w:.6f} and  loss : {l:.5f}')

print(f'our final prediction\'s is f(5) == {forward(5)}')

# so we saw that with lr==1e-3 it learnt pretty slow but now with lr==1e-2 its almost got it correct
# the same we will do now using autograd of pytorch

print('using AUTOGRAD','-'*20)

import torch
# f = w*x
# f = 2*x

x = torch.tensor([1,2,3,4],dtype=torch.float32)
y = torch.tensor([2,4,6,8],dtype=torch.float32)

w=torch.tensor(0.0,requires_grad=True) #weights init req. grad will calc. gradients automatically

# model pred
def forward(x):
    return w*x

# loss = MSE
def loss(y,y_pred):
    return ((y_pred-y)**2).mean()

# then we cal gradients manually using loss
# MSE = 1/n * (w*x-y)**2
# d(mse)/dw = 1/n 2x(w*x - y)

# def gradients(x,y,y_pred):
#     return np.dot(2*x,y_pred-y).mean()

print(f'prediction before for f(5):{forward(5):.3f}')

n_iters = 30
lr = 1e-2
for epoch in range(n_iters):
    # forward pass
    y_pred = forward(x)
    # loss cal
    l = loss(y,y_pred)
    # gradients update with weights
    # dw = gradients(x,y,y_pred) # instead of this we just propagate it backwards using back. prop

    l.backward()

    # update weights
    with torch.no_grad():
        w -= lr*w.grad

    # we zero the gradients otherwise it adds up and messes things up

    w.grad.zero_()

    if epoch%3 ==0:
        print(f'after {epoch} epoch\'s weight\'s are {w:.6f} and  loss : {l:.5f}')

print(f'our final prediction\'s is f(5) == {forward(5)}')


import numpy as np
import pandas as pd

def median_absolute_deviation(x):
    """
    Returns the median absolute deviation from the window's median
    :param x: Values in the window
    :return: MAD
    """
    return np.median(np.abs(x - np.median(x)))

def hampel(ts, window_size=5, n=3, imputation=False):

    """
    Median absolute deviation (MAD) outlier in Time Series
    :param ts: a pandas Series object representing the timeseries
    :param window_size: total window size will be computed as 2*window_size + 1
    :param n: threshold, default is 3 (Pearson's rule)
    :param imputation: If set to False, then the algorithm will be used for outlier detection.
        If set to True, then the algorithm will also imput the outliers with the rolling median.
    :return: Returns the outlier indices if imputation=False and the corrected timeseries if imputation=True
    """

    if type(ts) != pd.Series:
        raise ValueError("Timeserie object must be of tyme pandas.Series.")

    if type(window_size) != int:
        raise ValueError("Window size must be of type integer.")
    else:
        if window_size <= 0:
            raise ValueError("Window size must be more than 0.")

    if type(n) != int:
        raise ValueError("Window size must be of type integer.")
    else:
        if n < 0:
            raise ValueError("Window size must be equal or more than 0.")

    # Copy the Series object. This will be the cleaned timeserie
    ts_cleaned = ts.copy()

    # Constant scale factor, which depends on the distribution
    # In this case, we assume normal distribution
    k = 1.4826

    rolling_ts = ts_cleaned.rolling(window_size*2, center=True)
    rolling_median = rolling_ts.median().fillna(method='bfill').fillna(method='ffill')
    rolling_sigma = k*(rolling_ts.apply(median_absolute_deviation).fillna(method='bfill').fillna(method='ffill'))

    outlier_indices = list(
        np.array(np.where(np.abs(ts_cleaned - rolling_median) >= (n * rolling_sigma))).flatten())

    if imputation:
        ts_cleaned[outlier_indices] = rolling_median[outlier_indices]
        return ts_cleaned

    return outlier_indices


## NUMERICAL INTEGRATION - MAIN EXECUTION FILE
#### Based on excercise from file *1_aproximacion_a_derivadas_e_integrales*
#### Author: Rob (GitHub: Roberto919)
#### Date: 19 June 2020

'--------------------------------------------------------------------------------'
#############
## Imports ##
#############

## Python libraries
import numpy as np

## Ancillary modules
from numerical_integration_trapeze_functions import *
from numerical_integration_trapeze_parameters import *

'--------------------------------------------------------------------------------'
#################################
## Definition of main function ##
#################################

## Main module's function
def main_function():
    """
    Main module's function
        args:
            -
        returns:
            -
    """

    ## Obtain the first derivative approximation
    print(Tcf(f, a, b, n))

    return

'--------------------------------------------------------------------------------'
#################################
## Excecution of main function ##
#################################

if __name__ == '__main__':

    main_function()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019-04-18 18:12
# @Author  : erwin
import numpy as np
import pandas as pd
from common.util_function import *

data = np.array([[1.22, 2.21, 3.31, 4.41],
                 [4, 5, 6, 8],
                 [2, 3, 5, 9]])
df = pd.DataFrame(data=data, index=['a', 'b', 'c'], columns=['A', 'B', 'C', 'D'])

print_line("round：修改精度")
print_br(df.round(1))

print_line("clip：原数据中小于lower 设为 lower，大于 upper 设为 upper")
print_br(df.clip(2, 4))

print_line("cumsim, cummin, cummax, cumprod：按行/列累计计算")
print_br(df.cumsum(axis=1))
print_br(df.cumsum(axis=0))
# print_br(df.A.cumsum(axis=1))
print_br(df.A.cumsum(axis=0))


import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from scipy.optimize import curve_fit

def moving_average(ydata,point=5):
    """
    moving average

    ydata: original np.array data
    point: average points

    return: moving average data
    data length of calculated data is as same as original.

    ref:畳み込み積分や移動平均を求めるnumpy.convolve関数の使い方
    https://deepage.net/features/numpy-convolve.html

    numpyで移動平均
    https://qiita.com/wrblue_mica34/items/51adf0059b61887075d9
    """

    b =np.ones(point)/point
    y_ma = np.convolve(ydata,b, mode='same')
    #  Mode ‘same’ returns output of length max(M, N). Boundary effects are still visible.

    return y_ma

def cent_of_gravity(x,y,bg=0,printf=False):
    """
    center of gravity method
    fwhm is calculated from variance.
    This method is greatly affected by the background,
    so it is necessary to remove the background appropriately.
    Especially the variance is affected.

    """
    y_rembg = y-bg
    cg = np.sum(x*(y_rembg))/np.sum(y_rembg)

    vpd = y_rembg*(x-cg)*(x-cg)
    # vp2: variance sigma^2
    vp2= np.sum(vpd)/np.sum(y_rembg)
    # vp: standard deviation
    vp = np.sqrt(vp2)

    if printf==True:
        print(f'mu: {cg}, var: {vp2}, var1/2: {vp}')

    return cg, vp2

def fwhm(x,y,bg=0,printf=False):
    """
    full width at half maximum
    fwhm = 2.35*sigma (gauss distribution)
    The data needs to be smoothed.
    """
    # find max index
    ymax_ind = np.argmax(y)
    center_x= x[ymax_ind]
    ymax = y.max()

    yhalf = (ymax-bg)/2
    yhalf_ind = np.where( y-bg > yhalf)[0]
    yhalf_ind_min = yhalf_ind.min()
    yhalf_ind_max = yhalf_ind.max()

    fwhm_s = x[yhalf_ind_min]
    fwhm_l = x[yhalf_ind_max]
    fwhm = np.abs(fwhm_s-fwhm_l)
    # if the difference between the center and small edge is over 2, fwhm value set 'nan'.
    if np.abs(fwhm_l-center_x) > 2*np.abs(center_x-fwhm_s) :
         center_x, fwhm = np.nan, np.nan

    if printf==True:
        print(f'center_x: {center_x}, fwhm: {fwhm}, center_y: {ymax}, half_y: {yhalf}')

    return center_x, fwhm, ymax, yhalf

def r2_cal(ydata, fitdata):
    """
    Coefficient of determination
    """

    residuals =  ydata - fitdata
    rss = np.sum(residuals**2)
    tss = np.sum((ydata-np.mean(ydata))**2)
    r2 = 1 - (rss / tss)

    return r2

def gauss_fit(xdata,ydata, para4_list, printf=False):
    # para4_list = [a,mu,sigma,c]
    try:
        popt, pcov = curve_fit(gauss, xdata,ydata,
        p0=np.array(para4_list), maxfev=10000)

    except RuntimeError as Rte:
#             print('RuntimeError')
        popt = (0, 0, 0, 0)

    if printf==True:
        print(f"initial parameter -> {para4_list}")
        print(f"estimated parameter -> {popt}" )

    return popt

# Gauss distribution
def gauss(x, a = 1, mu = 0, sigma = 1, bg = 0):
    return a *(1/(sigma*np.sqrt(2*np.pi))) *np.exp(-(x - mu)**2 / (2*sigma**2)) + bg

def gauss_pdf(x, a = 1, mu = 0, sigma = 1, bg = 0):
    """using scipy module function
    """
    return a*norm.pdf(x, mu, sigma) + bg

# make simulation data with gauss noise
def simu_data(original_data,sigma):
    data_with_noise=[]
    for iy in original_data:
        data_temp = np.random.normal(loc=iy, scale=sigma, size=1)
        data_with_noise.append(float(data_temp))

    return np.array(data_with_noise)

if __name__ == '__main__':
    # make x data
    # -10～10まで0.05刻みの数値配列作成
    x = np.arange(-10, 10, 0.01)

    # N = 100
    # x = np.linspace(-10.0,10.0,N)

    a = 1
    mu = 0
    sigma = 1
    bg = 0

    y = gauss_pdf(x,a,mu,sigma,bg)
    # plt.plot(x,y)

    yn = simu_data(original_data=y,sigma=0.2)
    ys = moving_average(yn,point=10)

    plt.plot(x,yn,'g')
    plt.plot(x,ys,'b')
    plt.plot(x,y,'r')
    plt.show()

    cent_of_gravity(x,y,bg=0,printf=True)
    cent_of_gravity(x,yn,bg=0,printf=True)
    cent_of_gravity(x,ys,bg=0,printf=True)

    fwhm(x,y,bg=0,printf=True)
    fwhm(x,yn,bg=0,printf=True)
    fwhm(x,ys,bg=0,printf=True)

    para4_list=[1,0,1,0]
    gauss_fit(x,y, para4_list, printf=True)
    gauss_fit(x,yn, para4_list, printf=True)
    gauss_fit(x,ys, para4_list, printf=True)


from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from flask import Flask, render_template,Response, request, url_for
from matplotlib.figure import Figure
import Bisection_Method_Lib
import stringhandling
from sympy import *
import numpy as np
import io
import math

app = Flask(__name__)

@app.route('/')

def home():
    return render_template("index.html")

# @app.route('/GiaiBaiTap')
# def GiaiBaiTap():
#     return render_template("GiaiBaiTapNewTon.html", n = n, sol = sol, err = err,a=a,b=b, pp = pp, f_latex= f_latex, sll = sll,  min_df = min_df, max_df = max_df, min_ddf = min_ddf, max_ddf = max_ddf, f_a = f_a, f_b = f_b)

@app.route('/plot_png')

def plot_png():
    fig = create_figure()
    output = io.BytesIO()
    FigureCanvas(fig).print_png(output)
    return Response(output.getvalue(), mimetype='image/png')
    #Response này có kiểu dữ liệu trả về html không đọc
    # được nên em dẫn link trực tiếp đến hình ảnh
def create_figure():
    global f_input,a,b
    fig = Figure()
    axis = fig.add_subplot(1, 1, 1)
    x = symbols('x')
    t = symbols('t')
    f = lambda x : eval (f_input)
    X = np.linspace(a,b,int((b-a)/3*101))
    Y = [f(x) for x in X]
    axis.plot(X, Y)
    return fig

@app.route('/calc' , methods=['POST' , 'GET'])

def calc():
    global f_input,n,a,b, solArr, errArr,pp, f_latex,n_choose, sllArr, min_df, max_df, min_ddf, max_ddf, f_a , f_b, sol, err, sll,x0
    f_input = request.form['f(x)']
    # f_input = '(x**2 + 3)**math.log(5,3)'
    f_input = str(f_input)
    f_input = stringhandling.stringhandling(f_input)
    n_choose  = str(request.form['n_choose'])
    n = str(request.form['n_input'])
    n = stringhandling.stringhandling(n)
    n = eval(n)
    txt = request.form['ab_input']
    pp = str(request.form['choosen'])
    strs = txt.split (',')
    a , b = eval ( strs [0]) , eval ( strs [1])
    a , b = float(a), float(b)
    x = symbols('x')
    t = symbols('t')
    x_n = symbols('x_n')
    f1 = eval(f_input)
    f_latex = latex(f1)
    f = lambda x : eval (f_input)
    df = lambda x : f(t).diff(t,1).subs(t,x)
    ddf = lambda x: f(t).diff(t,2).subs(t,x)
    f1 = str(f(x_n))
    f1 = eval(f1)
    fx_n_latex = latex(f1)
    if(b - a <=0 ):
        a, b = b ,a
    if(Bisection_Method_Lib.checkCondition(f_input,a,b,pp)):
        if(pp == "chia đôi"):
            solArr , errArr, sllArr = Bisection_Method_Lib.bisection (  f_input, a , b , n, n_choose )
        if(pp == "Newton"):
            solArr , errArr, sllArr,min_df, max_df, min_ddf, max_ddf, f_a , f_b, x0, M,m = Bisection_Method_Lib.Newton(f_input , a , b , n, n_choose )
        if(pp == "Newton cải biên"):
            solArr , errArr, sllArr,min_df, max_df, min_ddf, max_ddf, f_a , f_b, x0, M,m= Bisection_Method_Lib.NewtonExplain(  f_input , a , b , n, n_choose )
        if(pp == "lặp điểm bất động"):
            solArr , errArr, sllArr, df, dY, x0, Y = Bisection_Method_Lib.repeatFixedPoint(  f_input , a , b , n, n_choose )
    if(Bisection_Method_Lib.checkCondition(f_input , a , b , pp) == False):
        return render_template("result1.html", f = f_input,a=a,b=b, pp = pp, f_latex = f_latex)
    sol = str(solArr[-1])
    err = str(errArr[-1])
    sll = sllArr[-1]
    err = stringhandling.handleFloat(err)
    sol = stringhandling.handleFloat(sol)
    x_n = symbols('x_n')
    if(pp == "Newton" or pp == "Newton cải biên"):
        minmax_df = min_df * max_df
        minmax_ddf = min_ddf * max_ddf
        f_ab = f_a * f_b
        max_ddf = "{:.2f}".format(max_ddf)
        min_ddf = "{:.2f}".format(min_ddf)
        max_df = "{:.2f}".format(max_df)
        min_df = "{:.2f}".format(min_df)
        minmax_ddf = "{:.2f}".format(minmax_ddf)
        minmax_df = "{:.2f}".format(minmax_df)
        M = "{:.2f}".format(M)
        m = "{:.2f}".format(m)
        f1 = str(df(x))
        f1 = eval(f1)
        df_latex = latex(f1)
        f1 = str(ddf(x))
        f1 = eval(f1)
        ddf_latex = latex(f1)
        if(pp == "Newton"):
            f1 = str(df(x_n))
            f1 = eval(f1)
            dfx_n_latex = latex(f1)
            return render_template("GiaiBaiTapNewton.html",dfx_n_latex = dfx_n_latex,fx_n_latex = fx_n_latex,  M=M, m=m,x0 = x0, f_ab = f_ab, minmax_ddf = minmax_ddf ,minmax_df=minmax_df,ddf_latex = ddf_latex,df_latex = df_latex, n = n, sol = sol, err = err,a=a,b=b, pp = pp, f_latex= f_latex, sll = sll,  min_df = min_df, max_df = max_df, min_ddf = min_ddf, max_ddf = max_ddf, f_a = f_a, f_b = f_b)
        if(pp == "Newton cải biên"):
            f_x0 = f(x0)
            f_x0 = "{:.2f}".format(f_x0)
            return render_template("GiaiBaiTapNewtonMoRong.html",f_x0 = f_x0,fx_n_latex = fx_n_latex,  M=M, m=m,x0 = x0, f_ab = f_ab, minmax_ddf = minmax_ddf ,minmax_df=minmax_df,ddf_latex = ddf_latex,df_latex = df_latex, n = n, sol = sol, err = err,a=a,b=b, pp = pp, f_latex= f_latex, sll = sll,  min_df = min_df, max_df = max_df, min_ddf = min_ddf, max_ddf = max_ddf, f_a = f_a, f_b = f_b)
    if(pp == "lặp điểm bất động"):
        # x0 = (a+b)/2
        max_f,min_f = max(Y),min(Y)
        if abs(max(dY)) > abs(min(dY)):
            max_df = abs(max(dY))
        if abs(max(dY)) <= abs(min(dY)):
            max_df = abs(min(dY))

        max_f , min_f,x0, max_df =  "{:.2f}".format(max_f), "{:.2f}".format(min_f),  "{:.2f}".format(x0), "{:.2f}".format(max_df)
        f1 = str(df(x))
        f1 = eval(f1)
        df_latex = latex(f1)

        return render_template('LapDiemBatDong.html', x0 = x0,fx_n_latex = fx_n_latex ,df_latex = df_latex, max_df = max_df,  max_f = max_f,min_f=min_f, n = n, sol = sol, err = err,a=a,b=b, pp = pp, f_latex= f_latex, sll = sll)
    return render_template('result.html', n = n, sol = sol, err = err,a=a,b=b, pp = pp, f_latex= f_latex, sll = sll)

@app.route('/table', methods = ['GET', 'POST'])

def table():
    global f_input,n,a,b, solArr, errArr,pp
    return render_template("table.html", f = f_input, a= a, b=b, n=n, solArr = solArr, errArr = errArr)

# from routes import *
# from pyfladesk import init_gui #dùng khi build ứng dụng
if __name__ == '__main__':
    app.run()       #dùng khi build web
    # init_gui(app) #dùng khi muốn build ra ứng dụng


"""Problem 1.

(a) Plot the distributions of samples from both classes.

Author: Lucas David -- <ld492@drexel.edu>
License: MIT (C) 2011

"""
from scipy.integrate import simps

def a_plot_distributions():
    INTERVALS = 100
    dx = (6 + 3.0) / INTERVALS

    P = [0.4, 0.6]
    CLASS_1_GAUSSIAN = (2, 1)
    CLASS_2_UNIFORM = (0, 1)

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

    print('MAP (considering priori probabilities):')

    plt.ylim([0, 1.2])
    x = np.linspace(-3, 6, INTERVALS)
    y = P[0] * mlab.normpdf(x, CLASS_1_GAUSSIAN[0],
                            math.sqrt(CLASS_1_GAUSSIAN[1]))
    lg1, = plt.plot(x, y, label='Class +1', linewidth=2, c='orange')

    start = int(round((0 + 3) / dx))
    end = int(round((1 + 3) / dx))
    c_0_area = simps(y, x)
    c_1_area = simps(y[start:end], x[start:end])
    print('density of gaussian:', c_0_area - c_1_area)

    x = np.linspace(-3, 6, INTERVALS)
    y = np.array([1.0 if CLASS_2_UNIFORM[0] <= e <= CLASS_2_UNIFORM[1]
                  else 0.0 for e in x])
    y = P[1] * y / abs(CLASS_2_UNIFORM[0] - CLASS_2_UNIFORM[1])
    lg2, = plt.plot(x, y, label='Class -1', linewidth=2, c='b')

    # clipping not required, as the uniform dist. is above
    # the gaussian at all times (verified through inspection).
    print('density of uniform:', simps(y, x))

    plt.legend([lg1, lg2], ['Class +1', 'Class -1'])
    plt.grid()
    plt.tight_layout(0)
    plt.savefig('results/map.png')

    plt.clf()

    print('MV (considering equal prob.):')

    plt.ylim([0, 1.2])
    x = np.linspace(-3, 6, INTERVALS)
    y = mlab.normpdf(x, CLASS_1_GAUSSIAN[0],
                     math.sqrt(CLASS_1_GAUSSIAN[1]))
    lg1, = plt.plot(x, y, label='Class +1', linewidth=2, c='orange')

    start = int((0 + 3) / dx)
    end = int((1 + 3) / dx)
    c_0_area = simps(y / 2, x)
    c_1_area = simps(y[start:end] / 2, x[start:end])
    print('density of gaussian:', c_0_area - c_1_area)

    y = np.array([1.0 if CLASS_2_UNIFORM[0] <= e <= CLASS_2_UNIFORM[1]
                  else 0.0 for e in x])
    y = y / abs(CLASS_2_UNIFORM[0] - CLASS_2_UNIFORM[1])
    lg2, = plt.plot(x, y, label='Class -1', linewidth=2, c='b')

    print('density of uniform:', simps(y / 2, x))

    plt.legend([lg1, lg2], ['Class +1', 'Class -1'])
    plt.grid()
    plt.tight_layout(0)
    plt.savefig('results/mv.png')

def main():
    print(__doc__)

    a_plot_distributions()

if __name__ == '__main__':
    main()


import numpy as np

def cart2polar(x, y, center=np.array([0, 0])):
    """
    transforms cartesian coords [x,y] into polar coords [r,phi] in the frame of the lense center

    :param coord: set of coordinates
    :type coord: array of size (n,2)
    :param center: rotation point
    :type center: array of size (2)
    :returns:  array of same size with coords [r,phi]
    :raises: AttributeError, KeyError
    """
    coordShift_x = x - center[0]
    coordShift_y = y - center[1]
    r = np.sqrt(coordShift_x**2+coordShift_y**2)
    phi = np.arctan2(coordShift_y, coordShift_x)
    return r, phi

def polar2cart(r, phi, center):
    """
    transforms polar coords [r,phi] into cartesian coords [x,y] in the frame of the lense center

    :param coord: set of coordinates
    :type coord: array of size (n,2)
    :param center: rotation point
    :type center: array of size (2)
    :returns:  array of same size with coords [x,y]
    :raises: AttributeError, KeyError
    """
    x = r*np.cos(phi)
    y = r*np.sin(phi)
    return x - center[0], y - center[1]

def phi_gamma_ellipticity(phi, gamma):
    """

    :param phi: angel
    :param gamma: ellipticity
    :return:
    """
    e1 = gamma*np.cos(2*phi)
    e2 = gamma*np.sin(2*phi)
    return e1, e2

def ellipticity2phi_gamma(e1, e2):
    """
    :param e1: ellipticity component
    :param e2: ellipticity component
    :return: angle and abs value of ellipticity
    """
    phi = np.arctan2(e2, e1)/2
    gamma = np.sqrt(e1**2+e2**2)
    return phi, gamma

def phi_q2_ellipticity(phi, q):
    """

    :param phi:
    :param q:
    :return:
    """
    e1 = (1.-q)/(1.+q)*np.cos(2*phi)
    e2 = (1.-q)/(1.+q)*np.sin(2*phi)
    return e1, e2

def transform_e1e2(x, y, e1, e2, center_x=0, center_y=0):
    """
    maps the coordinates x, y with eccentricities e1 e2 into a new elliptical coordiante system

    :param x:
    :param y:
    :param e1:
    :param e2:
    :param center_x:
    :param center_y:
    :return:
    """
    x_shift = x - center_x
    y_shift = y - center_y
    x_ = (1-e1) * x_shift - e2 * y_shift
    y_ = -e2 * x_shift + (1 + e1) * y_shift
    det = np.sqrt((1-e1)*(1+e1) + e2**2)
    return x_ / det, y_ / det

def ellipticity2phi_q(e1, e2):
    """
    :param e1:
    :param e2:
    :return:
    """
    phi = np.arctan2(e2, e1)/2
    c = np.sqrt(e1**2+e2**2)
    if c > 0.999:
        c = 0.999
    q = (1-c)/(1+c)
    return phi, q

def phi_q2_ellipticity_bounds(phi, q, bounds=None):
    """

    :param phi:
    :param q:
    :param bounds:
    :return:
    """
    e1, e2 = phi_q2_ellipticity(phi, q)
    if bounds in ['lower', 'upper']:
        e = max(abs(e1), abs(e2))
        if bounds == 'lower':
            e1, e2 = -e, -e
        elif bounds == 'upper':
            e1, e2 = e, e
        else:
            raise ValueError("bounds %s keyword not valid" %bounds)
    return e1, e2


"""
Source:
https://www.dorukhanserg.in/post/implementing-rpca/
https://www.dorukhanserg.in/post/pca-to-rpca/
"""

import numpy as np
import numpy.linalg as la

def soft_thresholding(y: np.ndarray, mu: float):
    """
    Soft thresholding operator as explained in Section 6.5.2 of https://web.stanford.edu/~boyd/papers/pdf/prox_algs.pdf
    Solves the following problem:
    argmin_x (1/2)*||x-y||_F^2 + lmb*||x||_1

    Parameters
    ----------
        y : np.ndarray
            Target vector/matrix
        lmb : float
            Penalty parameter
    Returns
    -------
        x : np.ndarray
            argmin solution
    """
    return np.sign(y) * np.clip(np.abs(y) - mu, a_min=0, a_max=None)

def svd_shrinkage(y: np.ndarray, tau: float):
    """
    SVD shrinakge operator as explained in Theorem 2.1 of https://statweb.stanford.edu/~candes/papers/SVT.pdf
    Solves the following problem:
    argmin_x (1/2)*||x-y||_F^2 + tau*||x||_*

    Parameters
    ----------
        y : np.ndarray
            Target vector/matrix
        tau : float
            Penalty parameter
    Returns
    -------
        x : np.ndarray
            argmin solution

    """
    U, s, Vh = np.linalg.svd(y, full_matrices=False)
    s_t = soft_thresholding(s, tau)
    return U.dot(np.diag(s_t)).dot(Vh)

class RobustPCA:
    """
    Solves robust PCA using Inexact ALM as explained in Algorithm 5 of https://arxiv.org/pdf/1009.5055.pdf
    Parameters
    ----------
        lmb:
            penalty on sparse errors
        mu_0:
            initial lagrangian penalty
        rho:
            learning rate
        tau:
            mu update criterion parameter
        max_iter:
            max number of iterations for the algorithm to run
        tol_rel:
            relative tolerance

    """
    def __init__(self, lmb: float, mu_0: float=1e-5, rho: float=2, tau: float=10,
                max_iter: int=10, tol_rel: float=1e-3):
        assert mu_0 > 0
        assert lmb > 0
        assert rho > 1
        assert tau > 1
        assert max_iter > 0
        assert tol_rel > 0
        self.mu_0_ = mu_0
        self.lmb_ = lmb
        self.rho_ = rho
        self.tau_ = tau
        self.max_iter_ = max_iter
        self.tol_rel_ = tol_rel

    def fit(self, X: np.ndarray):
        """
        Fits robust PCA to X and returns the low-rank and sparse components
        Parameters
        ----------
            X:
                Original data matrix

        Returns
        -------
            L:
                Low rank component of X
            S:
                Sparse error component of X
        """
        assert X.ndim == 2
        mu = self.mu_0_
        Y = X / self._J(X, mu)
        S = np.zeros_like(X)
        S_last = np.empty_like(S)
        for k in range(self.max_iter_):
            # Solve argmin_L ||X - (L + S) + Y/mu||_F^2 + (lmb/mu)*||L||_*
            L = svd_shrinkage(X - S + Y/mu, 1/mu)

            # Solve argmin_S ||X - (L + S) + Y/mu||_F^2 + (lmb/mu)*||S||_1
            S_last = S.copy()
            S = soft_thresholding(X - L + Y/mu, self.lmb_/mu)

            # Update dual variables Y <- Y + mu * (X - S - L)
            Y += mu*(X - S - L)
            r, h = self._get_residuals(X, S, L, S_last, mu)

            # Check stopping cirteria
            tol_r, tol_h = self._update_tols(X, L, S, Y)
            if r < tol_r and h < tol_h:
                break

            # Update mu
            mu = self._update_mu(mu, r, h)

        return L, S

    def _J(self, X: np.ndarray, lmb: float):
        """
        The function J() required for initialization of dual variables as advised in Section 3.1 of
        https://people.eecs.berkeley.edu/~yima/matrix-rank/Files/rpca_algorithms.pdf
        """
        return max(np.linalg.norm(X), np.max(np.abs(X))/lmb)

    @staticmethod
    def _get_residuals(X: np.ndarray, S: np.ndarray, L: np.ndarray, S_last: np.ndarray, mu: float):
        primal_residual = la.norm(X - S - L, ord="fro")
        dual_residual = mu*la.norm(S - S_last, ord="fro")
        return primal_residual, dual_residual

    def _update_mu(self, mu: float, r: float, h: float):
        if r > self.tau_ * h:
            return mu * self.rho_
        elif h > self.tau_ * r:
            return mu / self.rho_
        else:
            return mu

    def _update_tols(self, X, S, L, Y):
        tol_primal = self.tol_rel_ * max(la.norm(X), la.norm(S), la.norm(L))
        tol_dual = self.tol_rel_ * la.norm(Y)
        return tol_primal, tol_dual


##### FIRST ORDER TRANSFER FUNCTION CONTROL SIMULATION WITH MULTISTEP #####

import numpy as np
from sklearn.metrics import mean_squared_error
import pandas as pd
from scipy import signal
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from control import *
from multi_step import *

# Simulate taup * dy/dt = -y + K*u
Kp = 1.0
taup = 1.0

# (1) Transfer Function
num = [Kp]
den = [taup,1]
sys1 = signal.TransferFunction(num,den)
t1,y1 = signal.step(sys1)

# Time definition
ts = 0.1	#sampling time [s]
tf = 20	#simulation time [min]
tf = 60.0*tf      #-----> samples per minute = 60.0/ts
t = np.arange(0.0, tf, ts)
tt = t/60 # set minutes
# tt = t # set seconds

# ODE Integrator
def model3(y,t,u):
    return (-y + Kp * u)/taup

t3 = np.linspace(0,100,100)

tc = np.array([2, 3, 7])
a = np.array([2, 3, 5])

# ctrl = pid(ts, 0.08863, 0.5455, 0.0036)   # control 1_1
ctrl = pid(ts, 1.415, 1.415, 0.0)   # control 1_2c
sp = step_multiple(t, tc, a, ts)
# sp = 1
u = 1
y3_0 = 0

# print("LEN P: ", len(sp))
Y = np.zeros(t.shape)

for k in range(t.size):

    y3 = odeint(model3,y3_0,np.array([0.0, ts]),args=(u,))
    # print("Y3: ",y3)

    yk = y3[1]
    # print("yk: ",yk)
    # print("k: ",k)
    Y[k] = yk
    # print("U BEFORE es: ",u)
    # u = ctrl.solve(sp[k]+0.5*np.random.rand(1),yk) # with noise
    u = ctrl.solve(sp[k],yk)
    # u = ctrl.solve(sp,yk)
    # print("sp: ",sp)
    y3_0 = yk

plt.figure(1)
# plt.plot(t1,y1,'b--',linewidth=3,label='Transfer Fcn')
# plt.plot(t2,y2,'g:',linewidth=2,label='State Space')
plt.plot(tt,Y,'r-',linewidth=1,label='ODE Integrator')
plt.xlabel('Time [s]')
plt.ylabel('Response (y)')
plt.grid()
plt.legend(loc='best')
plt.show()

# # MATLAB response plotting

# df = pd.read_csv (r'control_data\control1_1.csv', header = None)
# y_matlab = df.to_numpy()
# # print(data[0][1]+1)
# print("LEN MATLAB: ",len(y_matlab[0]))
# t_plot_matlab = np.arange(0.0, len(y_matlab[0]), 1)
# # print(t_plot_matlab)

# plt.figure(1)
# # plt.plot(t1,y1,'b--',linewidth=3,label='Transfer Fcn')
# # plt.plot(t2,y2,'g:',linewidth=2,label='State Space')
# plt.plot(tt,Y,'r-',linewidth=1,label='ODE Integrator')
# plt.xlabel('Time [s]')
# plt.ylabel('Response (y)')
# plt.grid()
# plt.legend(loc='best')
# plt.show()
# plt.plot(t_plot_matlab,y_matlab[0],'b-',linewidth=1,label='MATLAB data')
# plt.xlabel('Samples')
# plt.ylabel('Response (y)')
# plt.grid()
# plt.legend(loc='best')
# plt.show()

# RMS_ERROR = np.sqrt(((y_matlab[0]-Y)**2).mean())
# RMS_ERROR_SKLEARN = mean_squared_error(y_matlab[0],Y, squared=False)
# print("My error [%]: ",RMS_ERROR*100)
# print("SKLEARN error [%]: ",RMS_ERROR_SKLEARN*100)


"""
Created on Thu Apr 9
@author: nrw
This plots residuals,
And also takes shelved torque data, adds in torque estimate and residual data
And writes it all to a CSV
"""

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

import plotly.plotly as py
import plotly.offline as po
import plotly.graph_objs as go
from plotly import tools

from sklearn import linear_model
from sklearn.linear_model import Ridge
from sklearn import metrics
import shelve

with shelve.open('calculated_data', 'r') as shelf:
    BigTheta = shelf['BigTheta']
    BigTorque = shelf['BigTorque']
    BigForce = shelf['BigForce']
    BigPosition = shelf['BigPosition']

#path = "~/Documents/projects_Spring2018/howe299r/Experiments/03April2018/WIP/"
IMUCols = ['timeSysCal', 'XYZ','X', 'Y', 'Z']

#===============================================
#### DECLARE CONSTANTS ####
#===============================================

print('number of datapoints', BigTheta.shape)

#### CALCULATE K ####

#===============================================
#### FIT TO ESTIMATE K ####
#===============================================

## Note: For the IMU, orientation.Y is pitch; X is roll; Z is yaw
torq_names = ['x', 'y', 'z']
dim = 1
#torq_1d = BigTorque[:,dim]
torq = BigTorque
theta = BigTheta
print('torq shape', torq.shape)

myX = BigTheta#theta_1Dreshape(-1,1)
myy = torq

regr= Ridge(fit_intercept=True, alpha=1.0, random_state=0, normalize=True)
regr2 = linear_model.LinearRegression()
regr.fit(myX, myy)
regr2.fit(myX, myy)
K = regr.coef_
K2 = regr2.coef_
yPred= regr.predict(myX)
yPred2= regr2.predict(myX)
print('\n======================')
matK = np.linalg.lstsq(BigTorque, BigTheta, rcond=None)[0]
print(matK.shape)
print('Numpy linalg.lstsq() K coefficients:\n', matK)
print('LinReg K Coefficients: \n', K2)
print('Ridge K Coefficients: \n', K)
print('\n======================')

torq_est = np.dot(K2, theta.T).T #n.3
resid = torq - yPred
mse = (resid ** 2).mean(axis=0)
print('resid shape', resid.shape)
print('RMSE Per Torque Dim', np.sqrt(mse))
#print('Variance score (ideal 1): %.2f' % r2_score(thetaY))
print('\n=======  SkLearn Metrics====')
print('\n---- Using LinReg K dot theta. This has worse error as we have no intercept term. ===')
print('Mean Absolute Error: %0.02f'  % metrics.mean_absolute_error(torq, torq_est))
print('Mean Squared Error: %0.02f'  % metrics.mean_squared_error(torq, torq_est)  )
print('Root Mean Squared Error %0.02f' % np.sqrt(metrics.mean_squared_error(torq, torq_est)))

print('\n---- Using sklearn LinearRegression.pred(theta).   ========')
print('Mean Absolute Error: %0.02f:' % metrics.mean_absolute_error(torq, yPred2)),
print('Mean Squared Error: %0.02f' % metrics.mean_squared_error(torq, yPred2)  )
print('Root Mean Squared Error: %0.02f' % np.sqrt(metrics.mean_squared_error(torq, yPred2)))

print('\n---- Using sklearn Ridge.pred(theta).   ========')
print('Mean Absolute Error: %0.02f' % metrics.mean_absolute_error(torq, yPred))
print('Mean Squared Error: %0.02f' % metrics.mean_squared_error(torq, yPred)  )
print('Root Mean Squared Error: %0.02f' % np.sqrt(metrics.mean_squared_error(torq, yPred)))
print('\n --- LinRegr has the best fit ----')

print('\nNote: torques about y axis: Min', myy.min(), '; Max', myy.max(), 'grams * cm')
print('\n======================')

'''
#===============================================
#### PLOT: Residuals (of Y torque_est - torque) vs Torque_est (either Y or X axis)
#===============================================

print(resid)
print(resid.shape)
names = ['X', 'Y', 'Z']
param = 'Torque'
dim = 1

xplot = torq_est[:,dim]
xplot2 = torq[:,dim]
print(xplot.shape)
yplot = resid[:,dim]
print(yplot.shape)

trace0 = go.Scatter( x = xplot, y = yplot, mode = 'markers',
    name = '%s-axis %s estimated'%(names[dim], param))

trace1 = go.Scatter( x = xplot2, y = yplot, mode = 'markers',
name = '%s-axis %s calculated from data'%(names[dim], param))
data = [trace0]

layout = go.Layout(
    title='%s-axis %s: Resid vs Estimate (with 3x3 K, using SkLearn LinReg) (IMU data)' % (names[dim], param),
    yaxis=dict(title= 'resid (g cm)'),
    xaxis=dict(title='%s (g cm)' % param),
    legend=dict(x=.5, y=0.1) )

fig = tools.make_subplots(rows=2, cols=1, subplot_titles=(trace1.name, trace0.name))

fig.append_trace(trace0, 1,1)
fig.append_trace(trace1, 2,1)
fig['layout'].update(title = layout.title)
fig['layout']['xaxis2'].update(title=layout.xaxis['title'])
fig['layout']['yaxis1'].update(title = layout.yaxis['title'])
fig['layout']['yaxis2'].update(title = layout.yaxis['title'])

#fig = go.Figure(data=data, layout=layout)

po.plot(fig)
'''

#===============================================
#### PLOT: Residuals (of Y torque_est - torque) vs Force (Z only)
#===============================================

print(resid.shape)
names = ['X', 'Y', 'Z']
param = 'Torque'
x2param = 'Force'
dim = 0

xplot = torq_est[:,dim]
xplot2 = BigForce[:,2]
yplot = resid[:,dim]

trace0 = go.Scatter( x = xplot, y = yplot, mode = 'markers',
    name = 'resid_torqY vs %s-axis %s estimated'%(names[dim], param))

trace1 = go.Scatter( x = xplot2, y = yplot, mode = 'markers',
name = 'resid_torqY vs Resid vs Z-axis Force, as applied')

#data = [trace0]

overall_title='%s-axis %s: Resid vs Force applied (with 3x3 K, using SkLearn LinReg) (IMU data)' % \
    (names[dim], param) + '
K: ' + np.array_str(K, precision=2) + '
'

yaxistitle= 'resid (g cm)'
xaxistitle= 'force (g)'

layout = go.Layout(
    title = overall_title,
    legend=dict(x=.5, y=0.1) )

fig = tools.make_subplots(rows=2, cols=1, subplot_titles=(trace0.name, trace1.name))

fig.append_trace(trace0, 1,1)
fig.append_trace(trace1, 2,1)

fig['layout'].update(title=overall_title, showlegend=False)
fig['layout']['xaxis1'].update(title='%s torque est (g cm)' % (names[dim]))
fig['layout']['xaxis2'].update(title=xaxistitle)
fig['layout']['yaxis1'].update(title=yaxistitle)
fig['layout']['yaxis2'].update(title=yaxistitle)

#fig = go.Figure(data=data, layout=layout)

#po.plot(fig)

full_data = np.hstack((BigPosition, BigForce, BigTheta, BigTorque))

full_data = np.hstack((full_data, torq_est, resid))
print(torq_est.shape)
print(resid.shape)
np.savetxt("full_calculated_data.csv", full_data, delimiter=",", fmt='%0.02f')

with shelve.open('calculated_data2', 'c') as shelf:
    shelf['torq_est'] = torq_est
    shelf['resid'] = resid
    shelf['K'] = K


# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py:percent
#     text_representation:
#       extension: .py
#       format_name: percent
#       format_version: '1.3'
#       jupytext_version: 1.6.0
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# %%
from pathlib import Path
from functools import partial

from utils import load_polar

import pybem as pb
import numpy as np
import pandas as pd
import proplot as plot
import sympy as sy

# %% [markdown]
# Inputs

# %% [markdown]
# How to compute the Aspect Ratio of the blade.
#
# $$
# AR = R^2 / S
# $$
# where $S$ is the blade area, computed like:
# $$
# S = \int_{R_{min}}^{R} c(r)dr
# $$
#
# We are now going to use `sympy` to compute the area numerically for some special cases to validate our simulator. We assume the chord to vary linearly with `r`.

# %%
r, R, R0 = sy.symbols("r, R, R0")
a, b = sy.symbols("a, b")
c, c0 = sy.symbols("c, c0")

# %% [markdown]
# Set up a generic linear variation

# %%
expr = a + b * r
expr

# %% [markdown]
# Create system of equations to determine the coefficients such that they match initial and final values.

# %%
eq1 = sy.Eq(lhs = expr.subs(r, R), rhs = c) # Tip
eq2 = sy.Eq(lhs = expr.subs(r, R0), rhs = c0) # Hub

# %% [markdown]
# Solve the system and obtain the coefficients

# %%
sol = sy.linsolve([eq1, eq2], (a, b))

a_sol , b_sol = sol.args[0]
print("a =", a_sol)
print("b =", b_sol)

# %% [markdown]
# Create chord variation equation and integrate to obtain blade area.

# %%
chord = a_sol + b_sol * r

area = sy.factor(sy.integrate(chord, (r, R0, R)))
area

# %%
print(sy.pycode(area))

print(sy.pycode(chord))

# %%
PATH_POLARS = Path("../polars")
file_lift = "lift.csv"
file_drag = "drag.csv"
file_propeller = PATH_POLARS / "propeller1_inches.txt"

PITCH_RATIO = 0.9
PITCH = 32.4  # inches for diameter of 36 inches

# %%
INCH_METER = 0.0254
PITCH = INCH_METER * PITCH  # meters

# %%
csv_reader = partial(pd.read_csv, sep=";", index_col=None)
load_polar = partial(
    load_polar,
    path=PATH_POLARS,
    file_lift=file_lift,
    file_drag=file_drag,
    reader=csv_reader,
)

# %%
dimensions_original_df = pd.read_csv(filepath_or_buffer=file_propeller, sep=",")

# Enforce stripped columns
dimensions_original_df.columns = [col.strip() for col in dimensions_original_df.columns]
dimensions_original_df = dimensions_original_df[["radius", "chord"]]

# Convert to international units
dimensions_original_df = dimensions_original_df.mul(INCH_METER)

# Name
dimensions_original_df.index = ["Hub", "S1", "S2", "S3", "S4", "Tip"]

# %% [markdown]
# Create the blade by defining the sections at each stage.

# %%
def generate_sections(coefficient, dimensions_original):

    dimensions_df = dimensions_original.copy()

    # Scale the propeller size and compute theta
    dimensions_df["chord"] *= coefficient

    R = dimensions_df["radius"].max()

    # Compute pitch angle distribution
    for idx, row in dimensions_df.iterrows():

        r = row["radius"]

        # Constant pitch law
        tan_theta = (2.0 * PITCH_RATIO * R) / (2.0 * np.pi * r)
        theta = np.arctan(tan_theta)  # radians
        theta = np.rad2deg(theta)  # degrees

        dimensions_df.loc[idx, "theta"] = theta

    # Define sections
    sections = [
        pb.Section(
            name="Hub",
            r=dimensions_df.loc["Hub", "radius"],
            beta=dimensions_df.loc["Hub", "theta"],
            chord=dimensions_df.loc["Hub", "chord"],
            airfoil=pb.Airfoil(
                polar_cl=load_polar(airfoil_type="765", which="cl"),
                polar_cd=load_polar(airfoil_type="765", which="cd"),
            ),
        ),
        pb.Section(
            name="S1",
            r=dimensions_df.loc["S1", "radius"],
            beta=dimensions_df.loc["S1", "theta"],
            chord=dimensions_df.loc["S1", "chord"],
            airfoil=pb.Airfoil(
                polar_cl=load_polar(airfoil_type="765", which="cl"),
                polar_cd=load_polar(airfoil_type="765", which="cd"),
            ),
        ),
        pb.Section(
            name="S2",
            r=dimensions_df.loc["S2", "radius"],
            beta=dimensions_df.loc["S2", "theta"],
            chord=dimensions_df.loc["S2", "chord"],
            airfoil=pb.Airfoil(
                polar_cl=load_polar(airfoil_type="764", which="cl"),
                polar_cd=load_polar(airfoil_type="764", which="cd"),
            ),
        ),
        pb.Section(
            name="S3",
            r=dimensions_df.loc["S3", "radius"],
            beta=dimensions_df.loc["S3", "theta"],
            chord=dimensions_df.loc["S3", "chord"],
            airfoil=pb.Airfoil(
                polar_cl=load_polar(airfoil_type="763", which="cl"),
                polar_cd=load_polar(airfoil_type="763", which="cd"),
            ),
        ),
        pb.Section(
            name="S4",
            r=dimensions_df.loc["S4", "radius"],
            beta=dimensions_df.loc["S4", "theta"],
            chord=dimensions_df.loc["S4", "chord"],
            airfoil=pb.Airfoil(
                polar_cl=load_polar(airfoil_type="762", which="cl"),
                polar_cd=load_polar(airfoil_type="762", which="cd"),
            ),
        ),
        pb.Section(
            name="Tip",
            r=dimensions_df.loc["Tip", "radius"],
            beta=dimensions_df.loc["Tip", "theta"],
            chord=dimensions_df.loc["Tip", "chord"],
            airfoil=pb.Airfoil(
                polar_cl=load_polar(airfoil_type="761", which="cl"),
                polar_cd=load_polar(airfoil_type="761", which="cd"),
            ),
        ),
    ]

    return sections

# %%
# Define propeller
COEFF_0 = 0.5
COEFF_N = 3
N = 5

results = []
for coeff in np.linspace(start=COEFF_0, stop=COEFF_N, num=N):

    sections = generate_sections(
        coefficient=coeff, dimensions_original=dimensions_original_df
    )

    propeller = pb.Propeller(B=2, sections=sections)

    # Define flow conditions and BEM method

    for J in np.linspace(1e-1, 1.5):

        pi = np.pi

        _lambda = J / pi

        bem = pb.BladeElementMethod(
            _lambda=_lambda, propeller=propeller, tip_loss=True, hub_loss=False
        )

        try:
            # Solve
            bem.solve()
            CT, CQ = bem.integrate_forces()
        except:
            CT = np.nan
            CQ = np.nan

        AR = propeller.aspect_ratio

        # Create experiments non-dimensionless coefficients
        results.append(
            (
                AR,
                J,
                CT * (pi ** 3.0) / 4 / J ** 2.0,
                CQ * (pi ** 4.0) / 4 / J ** 2.0,
                _lambda * CT / CQ,  # efficiency
            )
        )

        del bem

    del propeller

results_df = pd.DataFrame(results, columns=["AR", "J", "CT", "CP", "eta"]).dropna()

# %%
results_df

# %%
_array = [[1, 2], [3, 3]]
fig, axes = plot.subplots(array=_array, share=0)

Rs = results_df["AR"].unique()
for R in Rs:

    mask = results_df["AR"] == AR
    _results_df = results_df.loc[mask].set_index("J").drop("AR", axis=1)

    name = np.round(AR, 2)
    name = str(name)
    ############
    # Thrust
    ############
    ax = axes[0]
    thrust = _results_df["CT"]
    thrust.name = name
    lines = ax.plot(
        thrust,
        cycle="plum",
    )
    ax.format(
        title="Thrust",
        ylabel="$C_T$",
    )

    ############
    # Torque
    ############
    ax = axes[1]
    torque = _results_df["CP"]
    torque.name = name

    ax.plot(
        torque,
        cycle="plum",
    )
    ax.format(
        title="Torque / Power",
        ylabel="$C_P$",
    )

    ############
    # Efficiency
    ############
    ax = axes[-1]
    eta = _results_df["eta"]
    eta.name = name
    ax.plot(eta, cycle="plum")
    ax.format(title="Efficiency", ylabel="$\eta$")

axes[-1].legend(title="Aspect Ratio")

fig.save("Aspect_Ratio.pdf")

# %%

notebooks/Geometry influence - Aspect Ratio.py


"""
Defines a complex polynomial object from coefficients:
f(z) = a_0 + a_1 * z + a_2 * z^2 + ... + a_n * z^n

where for each i, a_i is a complex interval

Author:
Yuan Wang
Princeton University
"""
from interval import interval, inf, imath
from complexinterval import ComplexInterval, _one, _zero, _real
import operator
import numpy as np
import math

class ComplexPolynomial:
	def __init__(self, coeffs = [ComplexInterval()]):
		self.coeffs = coeffs

	def coeffs_copy(self):
		"""
		Return a copy of this complex polynomia's coefficients
		"""
		return self.coeffs[:]

	def derive(self):
		"""
		Returns a polynomial that is the first derivative of
		the current polynomial
		"""
		mycoeffs = self.coeffs
		coeffs = [0] * (len(mycoeffs) - 1)
		for i in range(len(mycoeffs) - 1):
			factor = _real(i + 1)
			coeffs[i] = mycoeffs[i + 1] * factor
		return ComplexPolynomial(coeffs)

	def evaluate(self, z):
		"""
		Evaluates a complex polynomial at z
		"""
		total = _zero()
		coeffs = self.coeffs
		for i in range(len(coeffs)):
			total = total + coeffs[i] * z**i
		return total

	def coeffString(self):
		out = ""
		for i in range(len(self.coeffs)):
			out += '(' + str(min(min(self.coeffs[i].a))) + ' + ' \
			+ str(min(min(self.coeffs[i].b))) + 'i)' + 'z^' + str(i) + ' + '
		return out[:-2]

	def isZero(self):
		"""
		Returns whether or not this polynomial is zero
		"""
		for i in range(len(self.coeffs)):
			if self.coeffs[i].isZero() == False:
				return False
		return True

	def __str__(self):
		"""
		Returns a string representation of the polynomial
		"""

		if (len(self.coeffs) == 0):
			return "f(z) =  0"

		return "f(z) =  " + self.coeffString()

	def __call__(self, z):
		return self.evaluate(z)

	def __add__(self, other):
		coeffs = self.coeffs[:]
		# add coefficientspairwise
		for i in range(min(len(self.coeffs), len(other.coeffs))):
			coeffs[i] = coeffs[i] + other.coeffs[i]

		if (len(other.coeffs) > len(self.coeffs)):
			return ComplexPolynomial(coeffs + other.coeffs[len(other.coeffs):])
		else:
			return ComplexPolynomial(coeffs)

	def __neg__(self):
		coeffs = [-coeff for coeff in self.coeffs]
		return ComplexPolynomial(coeffs)

	def __sub__(self, other):
		return self.__add__(-other)

	def __mul__(self, poly):
		"""
		Multiplies two polynomials.
		"""
		coeffs = []
		if (self.isZero() | poly.isZero()):
			return ComplexPolynomial([_zero()])

		for i in range(len(self.coeffs) + len(poly.coeffs) - 1):
			coeffs.append(_zero())
		P = self.coeffs
		Q = poly.coeffs
		for k in range(len(P)):
			summand = [q_i * P[k] for q_i in Q]
			for j in range(len(Q)):
				coeffs[k + j] = coeffs[k + j] + summand[j]

		return ComplexPolynomial(coeffs)

def main():
	print("Testing Complex Polynomials")
	print("----------------------------")
	xa = interval([1, 2])
	xb = interval([5, 6])
	x = ComplexInterval(xa, xb)

	ya = interval([4, 7])
	yb = interval([2, 3])
	y = ComplexInterval(ya, yb)

	wa = interval([2, 2])
	wb = interval([3, 3])
	w = ComplexInterval(wa, wb)

	za = interval([4, 4])
	zb = interval([5, 5])
	z = ComplexInterval(za, zb)

	a_0_a = interval([1, 1])
	a_0_b = interval([5, 5])
	a_0 = ComplexInterval(a_0_a, a_0_b)

	a_1_a = interval([1, 1])
	a_1_b = interval([5, 5])
	a_1 = ComplexInterval(a_1_a, a_1_b)

	a_2_a = interval([3, 3])
	a_2_b = interval([2, 2])
	a_2 = ComplexInterval(a_2_a, a_2_b)

	a_3_a = interval([7, 7])
	a_3_b = interval([-4, -4])
	a_3 = ComplexInterval(a_3_a, a_3_b)

	a_4_a = interval([-6, -6])
	a_4_b = interval([1, 1])
	a_4 = ComplexInterval(a_4_a, a_4_b)

	a_5 = ComplexInterval(interval([4]), interval([0]))
	a_6 = ComplexInterval(interval([5]), interval([0]))
	a_7 = ComplexInterval(interval([5]), interval([0]))

	coeffs = [a_1, a_2, a_3, a_4]

	print("Testing Complex Constructor")
	print("----------------------------")
	poly_1 = ComplexPolynomial(coeffs)
	print(poly_1)
	poly_2 = ComplexPolynomial([_zero(), a_4])
	print(poly_2)
	print("============================")

	print("Testing Evaluation")
	print("----------------------------")
	print(poly_1.evaluate(w))
	print(poly_1.evaluate(_one()))
	print(poly_1.evaluate(_zero()))

	print("")

	print(poly_2.evaluate(w))
	print(poly_2.evaluate(_one()))
	print(poly_2.evaluate(_zero()))
	print("============================")

	print("Derivation")
	print("----------------------------")
	print(poly_1.derive())

	print("")

	print(poly_2.derive())
	print("============================")

	print("Multiplication")
	print("----------------------------")
	poly_4 = ComplexPolynomial([a_5, a_6])
	poly_5 = ComplexPolynomial([a_7, a_5])

	print(poly_4)
	print(poly_5)
	print(poly_4 * poly_5)
	print(poly_4 * poly_4)

	print("============================")

	print("Addition")
	print("----------------------------")
	print(poly_4 + poly_2)
	print(poly_1 + poly_5)

	print("============================")

	print("Subtraction")
	print("----------------------------")
	print(poly_4 - poly_5)
	print(poly_4 - poly_2)
	print(poly_1 - poly_5)

	print("============================")

if __name__=="__main__":
	main()


import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
from scipy import stats
from utils import sigmoid , cost_function_logistic_regression_J

# pass
Y = np.array([0	,0	,0	,0	,0	,0	,1	,0	,1	,0	,1	,0	,1	,0	,1	,1	,1	,1	,1	,1])
# hours
X1 = np.array([0.50	,0.75	,1.00	,1.25	,1.50	,1.75	,1.75	,2.00	,2.25	,2.50	,2.75	,3.00	,3.25	,3.50	,4.00	,4.25	,4.50	,4.75	,5.00	,5.50])
m = X1.size
X0 = np.ones(m)
X= np.vstack((X0,X1)).T

res = optimize.minimize(cost_function_logistic_regression_J, x0=[0,0] , args=(X,Y))
print(res)
teta0 = res.x[0]
teta1 = res.x[1]

teta_x = teta0 + teta1 *X1
h = sigmoid(teta_x)

plt.scatter(X1, Y)
plt.plot(X1, h)
plt.title('data set and logistic regression using optimize.minimize')
plt.ylabel('pass')
plt.xlabel('hours')
plt.grid()
plt.show()


import numpy as np
from numpy import linalg as la

def rotation_matrix_by_2_vec(a, b):
    unit_vector_a = a / np.linalg.norm(a)
    unit_vector_b = b / np.linalg.norm(b)
    cos_t = np.dot(unit_vector_a, unit_vector_b)
    sin_t = np.sqrt(1-cos_t**2)*np.sign(np.cross(unit_vector_a, unit_vector_b))
    return np.array([[cos_t, -sin_t], [sin_t, cos_t]])

def rotation_matrix_by_angle(t):
    cos_t = np.cos(t)
    sin_t = np.sin(t)
    return np.array([[cos_t, -sin_t], [sin_t, cos_t]])


import numpy as np

def linear_kernel(x, y):
    return np.dot(x, y)

def polynomial_kernel(x, y, d=5):
    return (np.dot(x, y) + 1) ** d

def RBF_kernel(x, y, sigma=1.0):
    return np.exp(-np.linalg.norm((x - y)) ** 2 / (2 * (sigma ** 2)))


import numpy as np
from scipy.optimize import linprog

c1 = np.array([0.3, 0.2]) * -1
c2 = np.array([4.5, 1.5])
A_ub = [
    [-1, 1],
    [1, 1],
    [-1, -1]
]
b_ub = [0, 150, -50]

bounds = ((0, 100), (0, None))

def callback(xk, **kwargs):
    np.set_printoptions(precision=3)
    np.set_printoptions(suppress=True)
    print(kwargs)

res = linprog(c1, A_ub=A_ub, b_ub=b_ub, bounds=bounds, callback=callback)
print(res)
res = linprog(c2, A_ub=A_ub, b_ub=b_ub, bounds=bounds, callback=callback)
print(res)


import numpy as np
import networkx as nx

G = nx.dense_gnm_random_graph(5, 5, seed=12345)

matrix = nx.adjacency_matrix(G).todense()
print(matrix)
# [[0 0 1 0 0]
#  [0 0 1 1 0]
#  [1 1 0 0 1]
#  [0 1 0 0 1]
#  [0 0 1 1 0]]

paths_len_4 = np.linalg.matrix_power(matrix, 4)
print(paths_len_4)
# [[ 3 5  0  0 5]
#  [ 5 9  0  0 9]
#  [ 0 0 13 10 0]
#  [ 0 0 10  8 0]
#  [ 5 9  0  0 9]]


import numpy as np
from scipy import constants

def spectral_radiance(wavelength_nm, temperature: float):
    """
    Estimates the blackbody radiation as a function of wavelength and temperature
    .. math::
        B_{\nu}(T) = \frac{2 h c^2 / \lambda^5}{e^{h c/\lambda kT} - 1}
    where :math:`\nu = c/\lambda`

    Parameters
    ----------
    wavelength_nm: float
        The wavelength in nanometers
    temperature: float
        The temperature in Kelvin

    Returns
    -------
    float:
        The spectral radiance in J * s / (cm^2 nm sr)
    """

    hc = 6.62607015 * 2.99792458  # x 1E -34 (J s) x 1E8 (m/s) = 1E-26 (J m)
    hc2 = hc * 2.99792458  # x 1E -34 (J s) x 1E16 (m/s)^2 = 1E-18 (J m^2 s^{-1})
    hc_by_kt_lambda = 1E6 * hc / 1.380649 / temperature / wavelength_nm
    radiance = 2.0 * hc2 * np.power(wavelength_nm, -5.0)  # 1E-18 (J m^2 s^{-1}) / 1E-45 (m^5) = 1E27 J / (m^3 s)
    radiance *= 1E18 / (np.exp(hc_by_kt_lambda) - 1.0)  # 1E27 J/m^3 s = 1E18 J / (m^2 nm s)
    return radiance

def temperature_at_radiacnce(radiance: float, wavelength_nm: float):
    """
    Estimates the blackbody temperature in Kelvin for a source at a given wavelength in nm and a known spectral radiance
    ..math::
        T(B, \lambda) = \frac{\lambda k}{h c} \{ \ln\left[\frac{hc^2}{\lambda^5 B} + 1\right]\}

    Parameters
    ----------
    radiance: float
        The spectral radiance in W / cm^2 / nm / s / sr
    wavelength_nm: float
        The wavelength in nm

    Returns
    -------
    float:
        The estimated temperature in K
    """
    hc = 6.62607015 * 2.99792458  # x 1E -34 (J s) x 1E8 (m/s) = 1E-26 (J m)
    hc2 = hc * 2.99792458  # x 1E -34 (J s) x 1E16 (m/s)^2 = 1E-18 (J m^2 s^{-1})
    arg = 2.0 * hc2 * np.power(wavelength_nm, -5.0)  # 1E-18 (J m^2 s^{-1}) / 1E-45 (m^5) = 1E27 J / (m^3 s)
    arg /= 1E-14 * radiance  # / 1E27 [J / (m^3 s)] / [J / s cm^2 nm ] = 1E27 / 1E13 = 1E14
    arg += 1.0
    temperature = 1E6 * hc / wavelength_nm / 1.380649  # 1E-26 (J m) / 1E-9 m / 1E-23 J/K
    temperature /= np.log(arg)
    return temperature


import numpy
from sklearn.metrics import confusion_matrix

def load_data():
    train_labels = []
    with open('digitdata/traininglabels', 'rb') as f:
        for i, line in enumerate(f):
            train_labels.append(int(line))
    train_labels = numpy.array(train_labels, dtype=int)

    train_x = numpy.zeros((train_labels.shape[0] * 28 * 28))
    with open('digitdata/trainingimages', 'rb') as f:
        for i, line in enumerate(f):
            for j, char in enumerate(line.strip('\n')):
                if '+' == char:
                    train_x[i * 28 + j] = 1
                if '#' == char:
                    train_x[i * 28 + j] = 2

    train_x = numpy.array(train_x, dtype=int).reshape((train_labels.shape[0], 28 * 28))

    test_labels = []
    with open('digitdata/testlabels', 'rb') as f:
        for i, line in enumerate(f):
            test_labels.append(int(line))
    test_labels = numpy.array(test_labels, dtype=int)

    test_x = numpy.zeros((test_labels.shape[0] * 28 * 28))
    with open('digitdata/testimages', 'rb') as f:
        for i, line in enumerate(f):
            for j, char in enumerate(line.strip('\n')):
                if '+' == char:
                    test_x[i * 28 + j] = 1
                if '#' == char:
                    test_x[i * 28 + j] = 2

    test_x = numpy.array(test_x, dtype=int).reshape((test_labels.shape[0], 28 * 28))

    return train_x, train_labels, test_x, test_labels

class BayesClassifier(object):
    def __init__(self):
        self.bayesmatrix = None

    def fit(self, X, y):
        bayesmatrix = numpy.ones((10, 3, 28 * 28), dtype=numpy.float64)
        for k in xrange(10):
            for i in xrange(3):
                for j in xrange(X.shape[1]):
                    bayesmatrix[k, i, j] = numpy.sum(X[y==k, j]==i)
        numclass = numpy.zeros(10)
        for i in xrange(10):
            numclass[i] = numpy.sum(y==i) + 1
        bayesmatrix += 1
        bayesmatrix /= numclass[:, numpy.newaxis, numpy.newaxis]
        self.bayesmatrix = bayesmatrix

    def predict(self, X):
        labels = []
        for i in xrange(X.shape[0]):
            label = numpy.argmax(numpy.sum(numpy.log(self.bayesmatrix[:, 0, X[i, :]==0]), axis=1) +
                                numpy.sum(numpy.log(self.bayesmatrix[:, 1, X[i, :]==1]), axis=1) +
                                numpy.sum(numpy.log(self.bayesmatrix[:, 2, X[i, :]==2]), axis=1))
            labels.append(label)
        return numpy.array(labels)

if "__main__" == __name__:
    X, y, test_x, test_y = load_data()
    clf = BayesClassifier()
    clf.fit(X, y)
    pr = clf.predict(test_x)
    print "Confusion Matrix"
    print confusion_matrix(test_y, pr)
    print "Accuracy"
    print numpy.sum(pr == test_y) / float(test_y.shape[0])