import numpy as np
import matplotlib.pyplot as plt

# y = w1 * x1 + w2 * x2 + b

n = 30
epoch = 5
np.random.seed(0)
# x = np.random.uniform(0, 5, n)
x = np.random.rand(n,2)
x.shape

#x = np.reshape( np.arange(60), (30,2))
#x.shape

d = np.random.uniform(0, 5, n)
d.shape

#d = 2 * x[:,0]

w = np.random.rand(1,2)
b = np.random.uniform(0.001, 0.002, 1)

alpha = 0.9

#fig1 = plt.figure()
#ax1 = fig1.add_subplot(111)
#ax1.plot(x, d, 'ro')

epdist = np.zeros((epoch,2))
wdata = np.zeros((epoch,2))
bdata = np.zeros((epoch,1))

for j in range(0,epoch):
        print(j)
        for i in range(0,n):
                y = x[i,:].dot(w.T) + b
                e = d[i] - y
                dw = alpha * e * x[i,:] # (1,2)
                db = alpha * e
                w += dw
                b += db
                # print(w, b)
        wdata[j,:] = w
        bdata[j,:] = b
        d1 = x.dot(w.T) + b
        dist = d1 - y
        dist1 = np.mean(abs(dist)) # MAE
        epdist[j,0] = j ; epdist[j,1] = dist1 # Matrix for epoch # and MAE

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(epdist[:,0], epdist[:,1])
ax.set_xlabel('Number of Epoch')
ax.set_ylabel('Mean Absolute Error')
ax.set_title('Trend of MAE')

# Regression visualization
import seaborn as sns; sns.set(color_codes=True)
ax = sns.regplot(x=x[:,0], y=d)

# Result visualizaion
y_pred = np.zeros((epoch, n))
for j in range(0, epoch):
    y_pred[j] = x.dot(wdata[j, :].T) + bdata[j]

import pandas as pd

num = np.repeat(np.arange(epoch), n)
x1 = np.tile(x[:,0],epoch)
y1 = np.concatenate(y_pred)
df = pd.DataFrame({'epoch':num ,'x':x1, 'y':y1})

sns.lmplot("x", "y", data=df, hue='epoch', fit_reg=True)

'''
#fig1 = plt.figure()
#ax1 = fig1.add_subplot(111)
for j in range(0, epoch):
    y_pred[j] = x.dot(wdata[j,:].T) + bdata[j]

    #plt.plot(x, d, 'ro')
    #plt.plot(x[:,0], y_pred[j])

    fit = np.polyfit(x[:, 0], y_pred[j], 1)
    fit_fn = np.poly1d(fit)

    ax1.plot(x[:,0], y_pred[j], 'yo', x, fit_fn(x), '--k')

#colormap = plt.cm.gist_ncar
#colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))]

fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.set_color_cycle(['red', 'green', 'blue', 'yellow'])
ax1.plot(x, d, 'ro')

for j in range(0, epoch):
    y_pred[j] = x.dot(wdata[j, :].T) + bdata[j]
    # plt.plot(x, d, 'ro')
    # plt.plot(x[:,0], y_pred[j])

    fit = np.polyfit(x[:, 0], y_pred[j], 1)
    fit_fn = np.poly1d(fit)

    ax1.plot(x[:,0], y_pred[j])
'''


# Do not import any additional 3rd party external libraries as they will not
# be available to AutoLab and are not needed (or allowed)

import numpy as np
import os

# The following Criterion class will be used again as the basis for a number
# of loss functions (which are in the form of classes so that they can be
# exchanged easily (it's how PyTorch and other ML libraries do it))

class Criterion(object):
    """
    Interface for loss functions.
    """

    # Nothing needs done to this class, it's used by the following Criterion classes

    def __init__(self):
        self.logits = None
        self.labels = None
        self.loss = None

    def __call__(self, x, y):
        return self.forward(x, y)

    def forward(self, x, y):
        raise NotImplemented

    def derivative(self):
        raise NotImplemented

class SoftmaxCrossEntropy(Criterion):
    """
    Softmax loss
    """

    def __init__(self):
        super(SoftmaxCrossEntropy, self).__init__()

    def softmax(x):
        x = x - x.max(axis=1, keepdims=True)
        exp_scores = np.exp(x)
        p = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
        return p

    def forward(self, x, y):
        """
        Argument:
            x (np.array): (batch size, 10)
            y (np.array): (batch size, 10)
        Return:
            out (np.array): (batch size, )
        """
        self.logits = x
        self.labels = y

        m = y.shape[0]
        # get unnormalized probabilities
        p = SoftmaxCrossEntropy.softmax(x)

        # alternate way of computing loss
        #log_likelihood = np.dot(-y, (np.log(p)).T)
        #loss = log_likelihood.diagonal()

        loss = np.sum(np.multiply(-y, np.log(p)), axis=1)
        return loss

    def derivative(self):
        """
        Return:
            out (np.array): (batch size, 10)
        """
        x = self.logits
        y = self.labels
        p = SoftmaxCrossEntropy.softmax(x)

        return (p - y)


# =================================================
# minso.jeong@daum.net
# 20. 이미지 Contour 응용 3
# Reference : samsjang@naver.com
# =================================================
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

# =====================* arrangement *============================
# 01. Aspect Ratic (종횡비)
# x, y, w, h = cv2.boundingRect(cnt), aspect_ratio = float(w)/h
# 02. Extent (Contour 넓이와 Contour 외접 직사각형의 넓이비)
# area = cv2.contoourArea(cnt), x, y, w, h = cv2.boundingRect(cnt)
# rect_area = w*h, extent = float(area)/rect_area
# 03. Solidity (Contour 넓이와 이 Contour의 Convex Hull 넓이의 비)
# area = cv2.contourArea(cnt), hull = cv2.convexHull(cnt)
# hull_area = cv2.contourArea(hull), solidity = float(area)/hull_area
# 04. Equivalent Diameter (Contour의 넓이와 동일한 넓이를 가진 원의 지름)
# area = cv2.contourArea(cont), equivalent_diameter = np.sqrt(4*area/np.pi)
# 05. Orientation (Contour의 최적 타원의 기울어진 각도)
# (x, y), (MajorAxis, MinorAxis), angle = cv2.fitEllipse(cnt)
# 06. Mask & Pixel Points (객체를 구성하는 모든 점들)
# mask = np.zeros(imgray.shape, np.uint8)
# cv2.drawContours(mask, [cnt], 0, 255, -1), pixels = cv2.findNonZero(mask)
# 07. Mean Color / Mean Intensity (평균 색상)
# mean_value = cv2.mean(img, mask=mask)
# ================================================================

# A. Image Features
def convex():
	img = cv.imread('../Images/22.korea.jpg')
	gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
	ret, thr = cv.threshold(gray_img, 127, 255, 0)
	_, contours, _ = cv.findContours(thr, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

	cnt = contours[30]

	mmt = cv.moments(cnt)
	cx = int(mmt['m10']/mmt['m00'])
	cy = int(mmt['m01']/mmt['m00'])

	x, y, w, h = cv.boundingRect(cnt)
	korea_rect_area = w*h
	korea_area = cv.contourArea(cnt)
	hull = cv.convexHull(cnt)
	hull_area = cv.contourArea(hull)
	ellipse = cv.fitEllipse(cnt)

	aspect_ratio = w/h
	extent = korea_area/korea_rect_area
	solidity = korea_area/hull_area

	print("KOREA aspect_ratio :\t%.3f" %aspect_ratio)
	print("KOREA Extent :\t%.3f" %extent)
	print("KOREA Solidity :\t%.3f" %solidity)
	print("KOREA Orientation : :\t%.3f" %ellipse[2])

	equivalent_diameter = np.sqrt(4*korea_area/np.pi)
	korea_radius = int(equivalent_diameter/2)

	cv.circle(img, (cx, cy), 3, (0, 0, 255), -1)
	cv.circle(img, (cx, cy), korea_radius, (0, 0, 255), 2)
	cv.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
	cv.ellipse(img, ellipse, (50, 50, 50), 2)

	cv.imshow('KOREA Features', img)
	cv.waitKey(0)
	cv.destroyAllWindows()
#convex()

# B: Extreme Points
# =====================* arrangement *============================
# leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
# rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
# topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
# bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])
# ================================================================


import matplotlib.pyplot as plt
import Nio, sys, argparse
import numpy as np
from scipy import signal
from pprint import pprint

def SpectralVariance(y):
    c = np.fft.rfft(signal.detrend(y), norm="ortho") # Ortho means normalized by sqrt N
    return abs(c)**2.0

parser = argparse.ArgumentParser()
parser.add_argument('--input-dir', dest='input_dir')
parser.add_argument('--output-dir', dest='output_dir')
parser.add_argument('--casenames', dest='casenames')
parser.add_argument('--legends')
parser.add_argument('--data-file', dest='data_file')
parser.add_argument('--varname', dest='varname')

args = parser.parse_args()

pprint(args)

casenames = args.casenames.split(",")
legends   = args.legends.split(",")

print("Going to compare these models:")
pprint(casenames)

tss = []
sps = []

for i in range(len(casenames)):

    f = Nio.open_file("%s/%s/%s.nc" % (args.input_dir, casenames[i], args.data_file), "r")

    ts = f.variables[args.varname][:]
    ts /= np.std(ts)

    sp = SpectralVariance(ts)

    tss.append(ts)
    sps.append(sp)

    f.close()

N = len(tss[0])
freq = np.fft.rfftfreq(N, d=1.0/12.0)
time = np.arange(N) / 12
nyears = N / 12.0
period = 1.0 / freq

marked_periods   = np.array([0.5, 1, 2, 3, 4, 5, 10, 20, 30, 40])

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

ax[0].set_title("%s indices (%d years)" % (args.varname, nyears, ))
ax[0].set_xlabel("Time [years]")
ax[0].plot([time[0], time[-1]], [0, 0], "-", color="#cccccc", linewidth=2)

for i in range(len(casenames)):
    ax[0].plot(time, tss[i], linewidth=2, label=casenames[i])

ax[0].legend()

ax[1].set_title("Spectrum Analysis")
ax[1].set_xlabel("Period [years]")

for i in range(len(casenames)):
    ax[1].loglog(period[1:], sps[i][1:], linewidth=2, label=legends[i])
    #ax[1].plot(period[1:], sps[i][1:], linewidth=2, label=casenames[i])

ax[1].legend()

ax[1].set_xticks(marked_periods)
ax[1].set_xticklabels([("%.1f" if v<1 else "%d") % (v,) for v in marked_periods])

fig.savefig("%s/mc_climate_indices_%s.png" % (args.output_dir, args.varname), dpi=200)

#plt.show()


import numpy as np
import matplotlib.pyplot as plt

def signal(t, freq_1=4.0, freq_2=7.0):
    return np.sin(freq_1*2*np.pi*t) + np.sin(freq_2*2*np.pi*t)

state = np.random.RandomState(12345)
sample_size = 2**7
sample_t = np.linspace(0, 4, sample_size, dtype=np.float64)
sample_y = signal(sample_t) + state.standard_normal(sample_size)
sample_d = 4. / (sample_size - 1) # Spacing for linspace array
true_signal = signal(sample_t)

from numpy import fft

fig1, ax1 = plt.subplots()
ax1.plot(sample_t, sample_y, "k.", label="Noisy signal")
ax1.plot(sample_t, true_signal, "k--", label="True signal")

ax1.set_title("Sample signal with noise")
ax1.set_xlabel("Time")
ax1.set_ylabel("Amplitude")
ax1.legend()

spectrum = fft.fft(sample_y)

freq = fft.fftfreq(sample_size, sample_d)
pos_freq_i = np.arange(1, sample_size//2, dtype=int)

psd = np.abs(spectrum[pos_freq_i])**2 + np.abs(spectrum[-pos_freq_i])**2

fig2, ax2 = plt.subplots()
ax2.plot(freq[pos_freq_i], psd)
ax2.set_title("PSD of the noisy signal")
ax2.set_xlabel("Frequency")
ax2.set_ylabel("Density")

filtered = pos_freq_i[psd > 1e4]

new_spec = np.zeros_like(spectrum)
new_spec[filtered] = spectrum[filtered]
new_spec[-filtered] = spectrum[-filtered]

new_sample = np.real(fft.ifft(new_spec))

fig3, ax3 = plt.subplots()
ax3.plot(sample_t, true_signal, color="#8c8c8c", linewidth=1.5, label="True signal")
ax3.plot(sample_t, new_sample, "k--", label="Filtered signal")
ax3.legend()
ax3.set_title("Plot comparing filtered signal and true signal")
ax3.set_xlabel("Time")
ax3.set_ylabel("Amplitude")

plt.show()


import math
import matplotlib.pyplot as plt
import numpy as np
import time, os, sys

sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../../software/models/'))

import dftModel as DF
import utilFunctions as UF

(fs, x) = UF.wavread('../../../sounds/oboe-A4.wav')
M = 512
N = 512
start = int(.8*fs)
x1 = x[start:start+M]
xw = x1 * np.hamming(M)

plt.figure(1, figsize=(9.5, 6))
plt.subplot(311)
plt.plot(np.arange(start, (start+M), 1.0)/fs, xw, 'b', lw=1.5)
plt.axis([start/fs, (start+M)/fs, min(xw), max(xw)])
plt.title('x (oboe-A4.wav), M = 512')
mX, pX = DF.dftAnal(x1, np.hamming(N), N)

plt.subplot(312)
plt.plot((fs/2.0)*np.arange(mX.size)/float(mX.size), mX, 'r', lw=1.5)
plt.axis([0,fs/4.0,-85,max(mX)])
plt.title('mX, N = 512')

M = 512
N = 2048
start = int(.8*fs)
x1 = x[start:start+M]
xw = x1 * np.hamming(M)
mX, pX = DF.dftAnal(x1, np.hamming(M), N)

plt.subplot(313)
plt.plot((fs/2.0)*np.arange(mX.size)/float(mX.size), mX, 'r', lw=1.5)
plt.axis([0,fs/4.0,-85,max(mX)])
plt.title('mX, N = 2048')

plt.tight_layout()
plt.savefig('fft-size.png')
plt.show()


# coding: utf-8

# # SIR version 01.01

# ## El modelo epidémico de SIR

# Una descripción matemática simple de la propagación de una enfermedad en una población es el llamado modelo SIR, que divide la población (fija) de N individuos en tres "compartimentos" que pueden variar en función del tiempo, t:
#
# - S( t) son aquellos susceptibles pero aún no infectados con la enfermedad;
# - I( t) es la cantidad de individuos infecciosos;
# - R( t) son aquellos individuos que se han recuperado de la enfermedad y ahora tienen inmunidad contra ella.
#
# El modelo SIR describe el cambio en la población de cada uno de estos compartimentos en términos de dos parámetros, $\beta$ y $\gamma$.
#
# $\beta$ describe la tasa de contacto efectiva de la enfermedad: un individuo infectado entra en contacto con otros $\beta \cdot N$ individuos por unidad de tiempo (de los cuales la fracción que es susceptible a contraer la enfermedad es $S/N$) $\gamma$ es la tasa de recuperación media: es decir, $\frac{1}{\gamma}$ es el período de tiempo promedio durante el cual un individuo infectado puede transmitirlo.
# Además hemos incluido el caso de decesos, los que representamos con el factor $\mu$.

# Las ecuaciones diferenciales que describen este modelo fueron derivadas primero por Kermack y McKendrick [Proc.R.Soc.A,115,772(1927)]:
#
# $$\frac{dS}{dt}=−\beta \cdot \frac{S \cdot I}{N}$$
#
# $$ \frac{dI}{dt} =\beta \cdot \frac{S\cdot I}{N}−\gamma \cdot I - \mu \cdot I$$
#
# $$\frac{dR}{dt} = \gamma \cdot I $$
#
# $$\frac{dr}{dt} = \mu \cdot I $$
#

# El siguiente código de Python integra estas ecuaciones para una enfermedad caracterizada por los parámetros β = 0.2, 1/γ = 10 [dias] en una población de N = 1000 (quizás 'gripe en una escuela).
#
# El modelo se inicia con una sola persona infectada el día 0: I( 0 ) = 1.
#
# Las curvas trazadas de S(t), I(t) y R(t) están diseñados para ver los resultados obtenidos.

# In[37]:

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt

# In[10]:

# Una cuadrícula de puntos de tiempo (en días).
t = np.linspace(0, 160, 160)

# In[15]:

# Las ecuaciones diferenciales del modelo SIR.
def deriv(y, t, N, beta, gamma, mu):
    S, I, R, r = y
    dSdt = -beta * S * I / N
    dIdt = beta * S * I / N - gamma * I - mu * I
    dRdt = gamma * I
    drdt = mu * I
    return dSdt, dIdt, dRdt, drdt

# In[16]:

# Población total, N.
N = 10000
# Número inicial de individuos infectados, recuperados y fallecidos, I0, R0 y r0.
I0, R0, r0 = 1, 0, 0
# Todos los demás, S0, son susceptibles a la infección inicialmente.
S0 = N - I0 - R0 - r0

# In[36]:

# beta: tasa media de contacto,
# gamma (en 1/dias): tasa media de recuperación.
# mu: tasa media de decesos    # 0.28
beta, gamma, mu = 0.335, 1./14, 0.006

# In[ ]:

# Vector de condiciones iniciales
y0 = S0, I0, R0, r0

# In[18]:

# Integra las ecuaciones SIR sobre la cuadrícula de tiempo, t.
ret = odeint(deriv, y0, t, args=(N, beta, gamma, mu))
S, I, R, r = ret.T

# In[35]:

# Grafico los datos en tres curvas separadas para S(t), I(t) y R(t)
with plt.style.context('seaborn'):
    plt.plot(t, S, 'b', alpha=0.5, lw=2, label='Susceptibles')
    plt.plot(t, I, 'r', alpha=0.5, lw=2, label='Infectados')
    plt.plot(t, R, 'g', alpha=0.5, lw=2, label='Recuperados con inmunidad')
    plt.plot(t, r, 'k', alpha=0.5, lw=2, label='Decesos')
    plt.xlabel('Tiempo [días]')
    plt.ylabel('Número ('+str(N)+'%)')
    plt.ylim(-N/20,N*1.1)
    plt.xlim(0, 120)
    plt.grid(b=True, which='major', c='w', lw=2, ls='-')
    plt.legend(loc= 'upper left', prop={'size': 16})
    plt.show()


# from the jupyter notebook provided by the class

import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import DataLoader, Dataset, TensorDataset
import torchvision.datasets as ds
import pylab as plt

def load_mnist(datadir='./data_cache'):
    train_ds = ds.MNIST(root=datadir, train=True,
                           download=True, transform=None)
    test_ds = ds.MNIST(root=datadir, train=False,
                          download=True, transform=None)

    def to_xy(dataset):
        X = np.array(dataset.data) / 255.0  # [0, 1]
        Y = np.array(dataset.targets)
        return X, Y

    X_tr, Y_tr = to_xy(train_ds)
    X_te, Y_te = to_xy(test_ds)
    return X_tr, Y_tr, X_te, Y_te

X_tr, Y_tr, X_te, Y_te = load_mnist()

i = np.random.choice(len(X_tr))
plt.imshow(X_tr[i], cmap='gray')
plt.title(f'digit: {Y_tr[i]}')

print('original X_tr:', X_tr.shape)

# select 500 random examples
n = 500
I = np.random.choice(len(X_tr), n, replace=False)
X = X_tr[I]
Y = (Y_tr[I] % 2) * 2.0 - 1 # odd/even --> +1/-1
X = X.reshape(-1,  28*28) # flatten

print('reshaped X:', X.shape)
print('reshaped Y:', Y.shape)

# problem 3 part 2

def dLdbeta(X,Y,beta):
    if len(X.shape)==1:
        return np.multiply(np.dot(X.T,X), beta) - np.multiply(X.T,Y)
    else:
        return np.matmul(np.matmul(X.T,X), beta) - np.matmul(X.T,Y)

# this sgd uses all samples with minibatches of size 1. may want to add minibatches to this for better tradeoff between convergence and computational efficiency
def sgd(X, Y, learning_rate=0.01, n_epochs=50):

    beta = np.random.randn(784, )  # start with random beta

    epoch = 0

    while epoch < n_epochs:

        inds = np.arange(len(X))
        np.random.shuffle(inds) # shuffle the inds
        for i in inds:
            beta = beta-learning_rate*dLdbeta(X[i],Y[i],beta)
        epoch += 1
        learning_rate = learning_rate / 1.02 # gradually reducing the learning rate

    return beta

def gd(X, Y, learning_rate=0.0001, n_epochs=50):

    beta = np.random.randn(784, )  # start with random beta

    epoch = 0

    while epoch < n_epochs:

        beta = beta-learning_rate*dLdbeta(X,Y,beta)
        epoch += 1
        learning_rate = learning_rate / 1.02 # gradually reducing the learning rate

    return beta

# running SGD
print("SGD resutls")
beta_sgd = sgd(X,Y)

# double check:
train_error = np.linalg.norm(np.matmul(X,beta_sgd)-Y)**2/Y.shape[0]
print(f"train error: {train_error}")
print(f"train acc: {100*np.sum(np.round(np.matmul(X,beta_sgd))==Y)/Y.shape[0]}%")

# get the 'test error'
test_error = np.linalg.norm(np.matmul(X_te.reshape(-1,  28*28),beta_sgd)-Y_te)**2/Y_te.shape[0]
print(f"test error: {test_error}")
print(f"test acc: {100*np.sum(np.round(np.matmul(X_te.reshape(-1,  28*28),beta_sgd))==Y_te)/Y_te.shape[0]}%")

# running GD
print("GD resutls")
beta_gd = gd(X,Y)

# double check:
train_error = np.linalg.norm(np.matmul(X,beta_gd)-Y)**2/Y.shape[0]
print(f"train error: {train_error}")
print(f"train acc: {100*np.sum(np.round(np.matmul(X,beta_gd))==Y)/Y.shape[0]}%")

# get the 'test error'
test_error = np.linalg.norm(np.matmul(X_te.reshape(-1,  28*28),beta_gd)-Y_te)**2/Y_te.shape[0]
print(f"test error: {test_error}")
print(f"test acc: {100*np.sum(np.round(np.matmul(X_te.reshape(-1,  28*28),beta_gd))==Y_te)/Y_te.shape[0]}%")


import numpy
import matplotlib.pyplot as plt
#
"""
Fixed Parameters
================

SB_SIGMA - Stefan-Boltzman constant in W/(m**2 K**4)
PI       - delicious old pi
"""
SB_SIGMA = 5.7E-8
PI = 3.141592653589793

"""
Sun's Parameters
----------------
F_SOL - Temperature of the sun (K)
R_SOL - Radius of the sun (m)
"""
T_SOL = 5800
R_SOL = 6.96000E8

"""
Earth's Parameters
------------------
R - distance of Earth from sun (m)
"""
R = 1.5E11

"""
C_AT - heat capacity: atmosphere only
C_OS - heat capacity: ocean surface 50m (real ca. 70m)
C_OU - heat capacity: upper ocean layer 250m (real ca. 360m)
C_OD - heat capacity: ocean 3900m, 70% of Earth surface

Note: Heat capacity is given in J/(K*m^2) to simplify calculations.

The specific heat capacity of air (Cp) is ~1000 J/(kg*K) or, given the density
of air (ro) of 1 kg/m^3, the volumetric heat capacity Cv of ~1000 J/(K*m^3).
[ Cv=Cp*ro=1000 J/(K*m^3) ].

In ro*Cp*dT/dt=dQ/dx, Q is heat flow in W/m^2 or J/(s*m^2), which is given by
f_net. To get dT, we need to divide heat flow by a unit of length. In this exercise,
volumetric heat capacity (c=ro*cp) is already multiplied by 10000 (m), i.e. the
average thickness of the troposphere, and therefore skip the division of the heat
flow by length.

Example:
C_AT= ro*Cp*H where H is the height of the troposphere (~10km).
"""
C_AT = 1.0E7
C_OS = 2.0E8
C_OU = 1.0E9
C_OD = 1.6E10

"""
ALBEDO_0  - albedo mean constant
TRANSM_0  - transmissivity mean constant
"""
ALBEDO_0 = 0.3
TRANSM_0 = 0.64262

"""
Tasks for You!
==============

1) Calculate the sun's output F_SOL and radiative flux PHI_SOL
"""
F_SOL   = SB_SIGMA * T_SOL**4
PHI_SOL = F_SOL * 4 * PI * R_SOL**2
print("F_SOL:", F_SOL)
print("PHI_SOL:", PHI_SOL)

"""
2) Calculate F_SW_IN_0, the mean incoming shorwave radiation per area on Earth in W/m^2, i.e. the solar constant.
"""
E_0 = PHI_SOL / (4 * PI * R**2)  # solar constant
F_SW_IN_0 = E_0 / 4
print("E_0:", E_0)
print("F_SW_IN_0:", F_SW_IN_0)

"""
3) Calculate the predicted temperature on Earth T_EARTH assuming no atmosphere
"""
T_EARTH = ( ( E_0 * (1 - ALBEDO_0) ) / (4 * SB_SIGMA) )**(1/4)
print("T_EARTH:", T_EARTH)

"""
You'll notice that the temperature of task 3 deviates somewhat from the actual temperature on Earth.
What we need is to consider greenhouse gas related transmissivity.

4) Let temperature evolve over time!
Initialise temperature and let it evolve over time until it reaches equilibrium.
Make sure to include albedo and transmissivity in your calculations.

HINT: To calculate temperature change for a specific time step based on net incoming radiation,
remember dT (change in temperature) = dQ (change in heat/energy) / C (heat capacity), incoming
radiation is measured in W/m^2 (J/(s*m^2)) and heat capacity is given in J/(K*m^2) here.

Note: When calculating the radiation emitted by Earth, a multiplication by the factor of 0.95 is
necessary to take into consideration the emissive propertiesof the Earth's surface.

4-a: Initialise temperature at 300K and let it evolve using a heat capacity of the atmosphere only.
4-b: Change the initial temperature, run your code again and see what happens. Does this make sense?
4-c: Pick a different heat capacity and see what happens. Does this make sense?
"""

# Simulation Parameters
i_dt  = 10                                # time step size in days
nt    = 50                                # number of time steps
dt    = 60*60*24*float(i_dt)              # time step size in SI units (s)
ck    = C_AT                              # selection of heat capacity
#
# Initialisation
temp = [0.0]*nt                           # initialise temperature array
temp[0]=300                               # initial temperature
#
# run simulation
for i in range(0,nt-1):
    #
    # radiative fluxes
    f_sw_in  = F_SW_IN_0
    f_sw_out = ALBEDO_0 * f_sw_in
    f_lw_out = 0.95 * SB_SIGMA * temp[i]**4
    f_net    = f_sw_in - f_sw_out - f_lw_out * TRANSM_0
    #
    # temperature for next time step
    temp[i+1] = temp[i] + dt*(1/ck) * f_net
#    print(temp[i])
#
# plotting everything
x = [0.0]*nt
y = temp
#
for i in range (1,nt):
    x[i] = x[i-1]+i_dt
#
# create plot
plt.figure(0)                          # number your figures
plt.plot(x, y)                         # create a simple x-y plot
plt.title('temperature evolution')     # set a title
plt.xlabel('days')                     # label the x axis
plt.ylabel('temperature (K)')          # label the y axis
#plt.axis([0, nt, 280, 300])            # give x and y bounds
plt.show()


import bionetwork
import numpy
import matplotlib.pyplot as plt
import torch
import activationFunctions
from scipy.optimize import minimize

plt.rcParams["figure.figsize"] = (4,4)

leak = 0.01

x = numpy.linspace(-5, 5, 2001)
delta = (max(x)-min(x))/len(x)

functionType = 'leakyRelu' #MML leakyRelu  sigmoid
if functionType == 'MML':
    activation = activationFunctions.MMLactivation
    deltaActivation = activationFunctions.MMLDeltaActivation
    oneStepDeltaActivationFactor = activationFunctions.MMLoneStepDeltaActivationFactor
    invActivation = activationFunctions.MMLInvActivation
elif functionType == 'leakyRelu':
    activation = activationFunctions.leakyReLUActivation
    deltaActivation = activationFunctions.leakyReLUDeltaActivation
    oneStepDeltaActivationFactor = activationFunctions.leakyReLUoneStepDeltaActivationFactor
    invActivation = activationFunctions.leakyReLUInvActivation
elif functionType == 'sigmoid':
    activation = activationFunctions.sigmoidActivation
    deltaActivation = activationFunctions.sigmoidDeltaActivation
    oneStepDeltaActivationFactor = activationFunctions.sigmoidOneStepDeltaActivationFactor
    invActivation = activationFunctions.sigmoidInvActivation

y = activation(x.copy(), leak)
yd = deltaActivation(x.copy(), leak)

yNum = (y[1:len(y)]-y[0:(len(y)-1)])/delta

#plt.plot(x, yd)
#plt.plot(x[1:len(y)], yNum, 'o')
# plt.legend(['Analytical', 'Numerical'], frameon=False)
# plt.xlabel('X')
# plt.ylabel('dY/dX')
# plt.title('Derivative check')

plt.rcParams["figure.figsize"] = (8,6)
plt.figure()
ax1=plt.subplot(2, 3, 1)
plt.plot(x, y)
plt.title('activation function')

ax1=plt.subplot(2, 3, 2)
plt.plot(x, yd)
plt.plot(x[1:len(y)], yNum, 'o')
plt.legend(['Analytical', 'Numerical'], frameon=False)
plt.xlabel('X')
plt.ylabel('dY/dX')
plt.title('Derivative check')

# ax1=plt.subplot(2, 2, 3)
# plt.plot(yNum, yd[1:(len(y))], 'o')
# plt.title('Deviations numerical vs analytical')

ax1=plt.subplot(2, 3, 3)
plt.plot(x[0:len(y)-1], yNum-yd[1:len(y)], 'o')
plt.title('Deviations numerical vs analytical')
plt.tight_layout()

ax1=plt.subplot(2, 3, 4)
xInv = invActivation(y, leak)
plt.plot(xInv, x, 'o')
plt.xlabel('inv(y)')
plt.ylabel('x')
plt.title('check inverse')

ax1=plt.subplot(2, 3, 5)
ydOnestep = oneStepDeltaActivationFactor(torch.tensor(y), leak)
plt.plot(y, ydOnestep)
plt.xlabel('y')
plt.ylabel('onestep(y)=deltaActivation(inv(y))')
plt.title('one step')

ax1=plt.subplot(2, 3, 6)
plt.plot(yd, ydOnestep, 'o')
plt.xlabel('onestep(y)')
plt.ylabel('delta(x)')
plt.title('check onestep')

#%%
# plt.figure()
# plt.rcParams["figure.figsize"] = (4,4)

# leak = 0.01

# MM = lambda km, x: 1/((km/x) + 1)
# x = numpy.linspace(0.00001, 5, 201)
# y = bionetwork.activation(x.copy(), leak)
# res = minimize(lambda km: sum((MM(km, x)-y)**2), 1)
# optimalMM = MM(res.x[0], x)
# print('MM', res.fun)

# tanh = lambda k, x: numpy.tanh(k*x)
# res = minimize(lambda k: sum((tanh(k, x)-y)**2), 1)
# optimalTanh = tanh(res.x[0], x)
# print('tanh', res.fun)

# sigmoid = lambda k, x: 1/(1 + numpy.exp(-x*k[0] + k[1]))
# res = minimize(lambda k: sum((sigmoid(k, x)-y)**2), numpy.array([1, 0]))
# optimalSigmoid = sigmoid(res.x, x)
# print('Sigmoid', res.fun)

# plt.figure()
# plt.plot(x, y, color='black')
# plt.plot(x, optimalMM)
# plt.plot(x, optimalTanh)
# plt.plot(x, optimalSigmoid)
# plt.ylim([0, 1])
# plt.legend(['MML', 'MM', 'tanh', 'sigmoid'], frameon=False)

#%%
plt.figure()
plt.rcParams["figure.figsize"] = (4,4)

leak = 0.01

MM = lambda km, x: numpy.where(x>0, 1/((km/x) + 1), 0)
x = numpy.linspace(-0.5, 10, 201)
y = MM(2, x.copy())

MML = lambda x: activationFunctions.MMLactivation(x.copy(), leak)
res = minimize(lambda k: sum((MML(k[0]*x+k[1])-y)**2), numpy.array([1, 0]))
k = res.x
optimalMML = MML(k[0]*x+k[1])
print('MML', res.fun)

# tanh = lambda k, x: numpy.tanh(k[0]*x + k[1])
# res = minimize(lambda k: sum((tanh(k, x)-y)**2), numpy.array([1, 0]))
# optimalTanh = tanh(res.x, x)
# print('tanh', res.fun)

relu = lambda x: activationFunctions.leakyReLUActivation(x.copy(), leak)
res = minimize(lambda k: sum((relu(k[0]*x+k[1])-y)**2), numpy.array([1, 0]))
k = res.x
optimalReLU = relu(k[0]*x+k[1])
print('Relu', res.fun)

sigmoid = lambda x: activationFunctions.sigmoidActivation(x.copy(), leak)
res = minimize(lambda k: sum((sigmoid(x*k[0] + k[1])-y)**2), numpy.array([1, 0]))
k = res.x
optimalSigmoid = sigmoid(k[0]*x+k[1])
print('Sigmoid', res.fun)

plt.figure()
plt.plot(x, y, color='black')
plt.plot(x, optimalMML)
plt.plot(x, optimalReLU)
#plt.plot(x, optimalTanh)
plt.plot(x, optimalSigmoid)
plt.ylim([0, 1])
plt.legend(['MM', 'MML', 'ReLU', 'sigmoid'], frameon=False)
plt.title('Fit to a MM')
plt.xlabel('x')
plt.ylabel('y')


from numpy import ndarray, diag, array, dot, cos, sin, tanh
from numpy.linalg import inv

from dsorlib import State

def rot_matrix_from_B_to_U(yaw):
    """
    Auxiliary function to compute the rotation matrix in the 2D plane for velocities
    expressed in the body frame to velocities expressed in the inertial frame
    :param yaw:
    :return:
    """
    return array([[cos(yaw), -sin(yaw)],
                  [sin(yaw), cos(yaw)]])

class AUVOuterLoop:
    """
    Class responsible for implementing the outer loop that given a reference coordinate [x, y],
    generates a desired surge speed and heading rate for the the inner loops of the vehicle to follow

    The work in this section is heavily inspired by the work of F. Vanni and A. Pascoal in 'Cooperative
    Path-Following of Underactuated Autonomous Marine Vehicles with Logic-based Communications'
    """

    def __init__(self,
                 K: ndarray = array([1.0, 1.0]),
                 delta: float = -1.0):
        """
        Constructor for the AUV outer-loop
        :param K: A gain vector of size 2, with elements > 0
        :param delta: The size of the ball of the error allowed < 0
        """

        # Save the Tuning gains for the importance given to the tracking error in [X, Y]
        self.K: ndarray = diag(K).reshape((2, 2))

        # Save the gamma parameter (which defines the ball of the allowed error)
        self.delta: float = float(delta)

        # Save the delta vector
        self.delta_vec = array([self.delta, 0.0])

        # Matrix delta matrix
        self.delta_matrix = array([[1.0, 0.0],
                                   [0.0, -self.delta]])

        # The inverted delta_matrix
        self.inv_delta_matrix = inv(self.delta_matrix)

    def __call__(self,
                 state: State,
                 desired_pos: ndarray,
                 desired_vel: ndarray,
                 v_disturbances: ndarray = array([0.0, 0.0])):

        # Compute the rotation matrix from the inertial frame to the body frame
        bRu = rot_matrix_from_B_to_U(state.eta_2[2]).transpose()

        # Compute the error in the inertial frame [x, y] - [x_des, y_des]
        error_I: ndarray = state.eta_1[0:2] - desired_pos

        # Convert the error to the body frame
        error_B = dot(bRu, error_I)

        # Get the sway velocity from the state vector
        v_sway = state.v_1[1]

        # Compute the feedback law
        u_d = dot(self.inv_delta_matrix, -dot(self.K, tanh(error_B - self.delta_vec)) - array([0.0, v_sway]) - v_disturbances + dot(bRu, desired_vel))

        # Return the (desired surge speed, desired yaw rate)
        return u_d[0], u_d[1]


import math
import numpy as np
import depthai as dai

class HostSpatialsCalc:
    # We need device object to get calibration data
    def __init__(self, device):
        calibData = device.readCalibration()
        # Required information for calculating spatial coordinates on the host
        self.monoHFOV = np.deg2rad(calibData.getFov(dai.CameraBoardSocket.LEFT))

        # Values
        self.DELTA = 5
        self.THRESH_LOW = 200 # 20cm
        self.THRESH_HIGH = 30000 # 30m

    def setLowerThreshold(self, threshold_low):
        self.THRESH_LOW = threshold_low
    def setUpperThreshold(self, threshold_low):
        self.THRESH_HIGH = threshold_low
    def setDeltaRoi(self, delta):
        self.DELTA = delta

    def _check_input(self, roi, frame): # Check if input is ROI or point. If point, convert to ROI
        if len(roi) == 4: return roi
        if len(roi) != 2: raise ValueError("You have to pass either ROI (4 values) or point (2 values)!")
        # Limit the point so ROI won't be outside the frame
        self.DELTA = 5 # Take 10x10 depth pixels around point for depth averaging
        x = min(max(roi[0], self.DELTA), frame.shape[1] - self.DELTA)
        y = min(max(roi[1], self.DELTA), frame.shape[0] - self.DELTA)
        return (x-self.DELTA,y-self.DELTA,x+self.DELTA,y+self.DELTA)

    def _calc_angle(self, frame, offset):
        return math.atan(math.tan(self.monoHFOV / 2.0) * offset / (frame.shape[1] / 2.0))

    # roi has to be list of ints
    def calc_spatials(self, depthFrame, roi, averaging_method=np.mean):
        roi = self._check_input(roi, depthFrame) # If point was passed, convert it to ROI
        xmin, ymin, xmax, ymax = roi

        # Calculate the average depth in the ROI.
        depthROI = depthFrame[ymin:ymax, xmin:xmax]
        inRange = (self.THRESH_LOW <= depthROI) & (depthROI <= self.THRESH_HIGH)

        averageDepth = averaging_method(depthROI[inRange])

        centroid = { # Get centroid of the ROI
            'x': int((xmax + xmin) / 2),
            'y': int((ymax + ymin) / 2)
        }

        mid = int(depthFrame.shape[0] / 2) # middle of the depth img
        bb_x_pos = centroid['x'] - mid
        bb_y_pos = centroid['y'] - mid

        angle_x = self._calc_angle(depthFrame, bb_x_pos)
        angle_y = self._calc_angle(depthFrame, bb_y_pos)

        spatials = {
            'z': averageDepth,
            'x': averageDepth * math.tan(angle_x),
            'y': -averageDepth * math.tan(angle_y)
        }
        return spatials, centroid


# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numba as nb
# From https://scipython.com/book/chapter-7-matplotlib/problems/p72/the-julia-set/
# Image width and height; parameters for the plot
im_width, im_height = 500, 500
c = complex(-0.1, 0.65) #-0.8,.156 also beautiful
zabs_max = 10
nit_max = 1000
xmin, xmax = -1.5, 1.5
xwidth = xmax - xmin
ymin, ymax = -1.5, 1.5
yheight = ymax - ymin

@nb.jit(nopython=True)
def JuliaSet(im_width=im_width,im_height=im_height,
                    nit_max=nit_max,zabs_max=zabs_max):
    julia = np.zeros((im_width, im_height))
    for ix in range(im_width):
        for iy in range(im_height):
            nit = 0
            # Map pixel position to a point in the complex plane
            z = complex(ix / im_width * xwidth + xmin,
                        iy / im_height * yheight + ymin)
            # Do the iterations
            while abs(z) <= zabs_max and nit < nit_max:
                z = z**2 + c
                nit += 1
            shade = 1-np.sqrt(nit / nit_max)
            ratio = nit / nit_max
            julia[ix,iy] = ratio
    return julia
julia = JuliaSet()
fig, ax = plt.subplots(figsize=(8,8))
ax.imshow(julia, interpolation='nearest', cmap=cm.cool)
ax.axis('equal')
#ax.set_axis_off()
# Set the tick labels to the coordinates of z0 in the complex plane
xtick_labels = np.linspace(xmin, xmax, int(xwidth // 0.5))
ax.set_xticks([(x-xmin) / xwidth * im_width for x in xtick_labels])
ax.set_xticklabels(['{:.1f}'.format(xtick) for xtick in xtick_labels])
ytick_labels = np.linspace(ymin, ymax, int(yheight // 0.5))
ax.set_yticks([(y-ymin) / yheight * im_height for y in ytick_labels])
ax.set_yticklabels(['{:.1f}'.format(ytick) for ytick in ytick_labels])
ax.set_title(r"The Julia Set for $f(z)=z^2+c$, where $c = −0.1+0.65j$")
plt.show()
#plt.savefig('JuliaSet.png')


import scipy
import pandas as pd

def corr( df, alpha = 0.05 ):
	"""
	Uses dataframe df and returns 3 dataframes:
	* corr_r: Pearson's correlation coefficient.
	* corr_p: p-value for correlation coefficient
	* corr_b: if p-value survives a Bonferoni correction (using level of signitifance alpha).
	"""
	variables = df.columns #or use all
	corr_r = {}
	corr_p = {}
	corr_b = {} #survives Bonferoni

	variablesNo = len(variables)
	#not counting correlation of the variable with itself, count only half of correlations (they are symmetrical)
	Bonferoni = 2 * alpha/float((variablesNo-1)*(variablesNo-1))

	for variable in variables:
	    corr_r[variable] = []
	    corr_p[variable] = []
	    corr_b[variable] = []
	    for column in df.columns:
		if variable == column:
		    corr_r[variable].append(1)
		    corr_p[variable].append(0)
		    corr_b[variable].append( True )
		else:
		    corrdf = df[[variable, column]].dropna(how='any')
		    r, p = scipy.stats.pearsonr(corrdf[variable], corrdf[column])
		    corr_r[variable].append(r)
		    corr_p[variable].append(p)
		    corr_b[variable].append( p < Bonferoni )
	corr_r = pd.DataFrame(corr_r, index=df.columns).sort_index()
	corr_p = pd.DataFrame(corr_p, index=df.columns).sort_index()
	corr_b = pd.DataFrame(corr_b, index=df.columns).sort_index()
	return corr_r, corr_p, corr_b


"""Preprocessing"""

import numpy as np
from subfunc.showdata import *

# ============================================================
# ============================================================
def pca(x, num_comp=None, params=None, zerotolerance = 1e-7):
    """Apply PCA whitening to data.
    Args:
        x: data. 2D ndarray [num_comp, num_data]
        num_comp: number of components
        params: (option) dictionary of PCA parameters {'mean':?, 'W':?, 'A':?}. If given, apply this to the data
        zerotolerance: (option)
    Returns:
        x: whitened data
        parms: parameters of PCA
            mean: subtracted mean
            W: whitening matrix
            A: mixing matrix
    """
    print("PCA...")

    # Dimension
    if num_comp is None:
        num_comp = x.shape[0]
    print("    num_comp={0:d}".format(num_comp))

    # From learned parameters --------------------------------
    if params is not None:
        # Use previously-trained model
        print("    use learned value")
        data_pca = x - params['mean']
        x = np.dot(params['W'], data_pca)

    # Learn from data ----------------------------------------
    else:
        # Zero mean
        xmean = np.mean(x, 1).reshape([-1, 1])
        x = x - xmean

        # Eigenvalue decomposition
        xcov = np.cov(x)
        d, V = np.linalg.eigh(xcov)  # Ascending order
        # Convert to descending order
        d = d[::-1]
        V = V[:, ::-1]

        zeroeigval = np.sum((d[:num_comp] / d[0]) < zerotolerance)
        if zeroeigval > 0: # Do not allow zero eigenval
            raise ValueError

        # Calculate contribution ratio
        contratio = np.sum(d[:num_comp]) / np.sum(d)
        print("    contribution ratio={0:f}".format(contratio))

        # Construct whitening and dewhitening matrices
        dsqrt = np.sqrt(d[:num_comp])
        dsqrtinv = 1 / dsqrt
        V = V[:, :num_comp]
        # Whitening
        W = np.dot(np.diag(dsqrtinv), V.transpose())  # whitening matrix
        A = np.dot(V, np.diag(dsqrt))  # de-whitening matrix
        x = np.dot(W, x)

        params = {'mean': xmean, 'W': W, 'A': A}

        # Check
        datacov = np.cov(x)

    return x, params


import numpy as np
import matplotlib.pyplot as plt

def cart2pol(x, y):
    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)
    return(rho, phi)

def pol2cart(rho, phi):
    x = rho * np.cos(phi)
    y = rho * np.sin(phi)
    return(x, y)

def sum2(x, y):
	return tuple(map(sum, zip(x,y)))

def sum3(x, y, z):
	return tuple(map(sum, zip(x,y, z)))

################################
#initial conditions

x_0 = 10
y_0 = 0
v_int = 1/10

r_0 = [(x_0, y_0)]
v_0 = [(0, v_int)]

r = r_0
v = v_0

h = x_0*v_int
p = h**2
E_0 = .5*v_int**2-1/x_0
a = -1/(2*E_0)
e = (1-p/a)**.5
P = 2*np.pi*a**(3/2)
t = P/1000

##############################################
#Runge-Kutta
x_0 = 10
y_0 = -50
v_int = 1/10

r_0 = [(x_0, 0)]
v_0 = [(0, v_int)]

r = r_0
v = v_0

# r_n1
# v_n1

#

for i in range(0,int(P*100)):
	v_n = np.asarray(v[len(v)-1])  #this is v_n
	r_n = np.asarray(r[len(r)-1])  #this is r_n

	r_mag = (r_n[0]**2+r_n[1]**2)**.5  #magnitude of r_n, used to calculate a_n
	a_n = np.asarray((-r_n[0]/r_mag**3,-r_n[1]/r_mag**3))  #this is a_n

	#r_n1 (the midpoint estimate, used for calculating a_n1)
	r_n1 = np.asarray(sum3(r_n, .5*t*v_n, 1/8*t**2*a_n))
	r_n1_mag = (r_n1[0]**2+r_n1[1]**2)**.5
	a_n1 = np.asarray((-r_n1[0]/r_n1_mag**3,-r_n1[1]/r_n1_mag**3))

	r_add = sum3(r_n, t*v_n, sum2(t**2/6*a_n,t**2/6*2*a_n1))

	r_n2 = sum3(r_n, t*v_n, .5*t**2*a_n1)
	r_n2_mag = (r_n2[0]**2+r_n2[1]**2)**.5
	a_n2 = np.asarray((-r_n2[0]/r_n2_mag**3,-r_n2[1]/r_n2_mag**3))
	v_add = sum2(v_n, sum3(t/6*a_n, t/6*4*a_n1, t/6*a_n2))

	r.append(r_add)
	v.append(v_add)

r = np.asarray(r)
l = []

for i in r:
	l.append(cart2pol(i[0],i[1]))

x_val = [x[0] for x in l]
y_val = [x[1] for x in l]

#Graphing

fig1, ax3 = plt.subplots()
ax3=fig1.add_subplot(111, projection='polar')
ax3.plot(y_val,x_val)
# ax3.plot(theta_comp, r_comp, 'o', markerfacecolor='none', markeredgecolor='r')
ax3.set_rmax(.5)
ax3.set_rticks([3, 6, 9, 12])  # less radial ticks
ax3.set_rlabel_position(-22.5)  # get radial labels away from plotted line
ax3.grid(True)
ax3.set_title("Runge-Kutta", va='bottom')
plt.show()


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy
from sklearn import linear_model # Le modèle linéaire
from sklearn import datasets
from sklearn.metrics import mean_squared_error, r2_score # Métriques d'évaluation
import seaborn as sns

def linearReg():
    datasource = pd.read_excel(r'./data/slr04.xls')
    datasource = datasource.rename(columns={
        "X": "Males",
        "Y": "Females",
    })
    print(datasource)

    X_train = np.expand_dims(datasource['Males'], axis=1)
    Y_train = datasource['Females']

    print(X_train)
    print(Y_train)

    #sns.set(rc={'figure.figsize': (10, 3)})
    #sns.scatterplot(X_train[:, 0], Y_train)

    regr = linear_model.LinearRegression()
    regr_fit = regr.fit(X_train, Y_train, sample_weight=None)

    print(f'Intercept: \t{regr.intercept_}')
    print(f'Coefficients: \t{regr.coef_}')

    #plt.figure(figsize=(10,7))
    #plt.scatter(X_train, Y_train)
    #plt.plot([0,10], regr.predict([[0], [10]]), color='red')
    #plt.show()
    Y_pred = regr.predict(X_train)

    mse = mean_squared_error(Y_train, Y_pred)
    score = r2_score(Y_train, Y_pred) * 100

    print("MSE : {:3.2f}".format(mse))
    print('Score R2: {:2.1f}%'.format(score))

    return {
        "mse": mse,
        "score": score
    }


import numpy as np
import scipy as sp

#mic_position=[[x,y,z],[x,y,z]]
#source_position=[[x,y,z],[x,y,z] ]
#freqs=[f1,f2,f3...]
def obtain_steering_vector(mic_position,source_position,freqs,SOUND_SPEED=340,useAmp=False):
    mic_num=np.shape(mic_position)[0]
    source_num=np.shape(source_position)[0]

    #mic_position
    #m,x
    #s, x
    #m,s,x
    source_position=np.expand_dims(source_position,axis=0)
    mic_position=np.expand_dims(mic_position,axis=1)
    #m,s
    distance=np.sqrt(np.sum(np.square(source_position-mic_position),axis=2))
    delay=distance/SOUND_SPEED
    #s,freq,m
    phase_delay=np.einsum('k,ms->skm',-2.j*np.pi*freqs,delay)
    #s,f,m
    steering_vector=np.exp(phase_delay)
    if useAmp==True:
        #m,s
        ampRatio=np.divide(1.,distance)
        steering_vector=np.einsum('ms,skm->skm',ampRatio,steering_vector)
    #大きさを1で正規化する
    #skm
    norm=np.sqrt(np.sum(steering_vector*np.conjugate(steering_vector),axis=2,keepdims=True))
    steering_vector=np.divide(steering_vector,norm)

    return(steering_vector)

def obtain_steering_vector_test():
    fftSize=1024
    fftMax=int(fftSize/2+1)
    print(fftMax)
    sampling_rate=16000
    max_freq=sampling_rate/2

    freqs=np.array(range(fftMax),dtype=np.float)/np.array(fftMax,dtype=np.float)*max_freq

    mic_position=np.array([[0.,0.,0.],[0.05,0.05,0.03],[0.04,0.04,0.02]])
    source_position=np.array([[1.,0.,0.],[0.,1.,0.]])

    #s,k,m
    steeringVector=obtain_steering_vector(mic_position,source_position,freqs,useAmp=True)

    print(np.shape(steeringVector))


import numpy as np
from scipy.fftpack import fft,fft2,fftshift,ifft2,ifftshift
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.gridspec import GridSpec
import tkinter

class WaveSimulation(object):

    @staticmethod
    def make_spectrum(signal, t=None):
        n = len(signal)
        if len(t) != n:
            t = np.array([i for i in range(len(n))])
        dt = np.mean(np.diff(t))
        # fs = np.linspace(-n//2,n//2,n) / dt
        ft = (t - t[n // 2]) / dt / np.max(t)
        F = np.fft.ifftshift(np.fft.fft(signal))
        Freq_content = np.abs(F)
        fig = plt.figure()
        ax1 = fig.add_subplot(211)
        ax1.plot(t, signal)
        ax1.set_xlabel('time')
        ax1.set_ylabel('f_{signal}')
        ax2 = fig.add_subplot(212)
        ax2.plot(ft, Freq_content)
        ax2.set_xlabel('frequency')
        ax2.set_ylabel(r'$|\mathcal{F}_{signal}|$')
        plt.show()

    @staticmethod
    def rect(x):
        return np.where(np.abs(x) <= 0.5, 1, 0)

    @staticmethod
    def python_angular_spectrum_prop(E_in,x,y,z_prop,wavelen):
        #E_in - this is your 2D complex field that you wish to propagate
        #z_prop = ...   this is the distance by which you wish to propagate
        dx = x[1]-x[0]
        dy = y[1]-y[0]
        wavenum = 2 * np.pi / wavelen
        wavenum_sq=wavenum**2
        kx = np.fft.fftfreq(E_in.shape[0], dx / (2 * np.pi))
        ky = np.fft.fftfreq(E_in.shape[1], dy / (2 * np.pi))
        # this is just for broadcasting, the "indexing" argument prevents NumPy
        # from doing a transpose (default meshgrid behaviour)
        kx, ky = np.meshgrid(kx, ky, indexing='ij', sparse=True)
        kz_sq = kx**2 + ky**2
        # we zero out anything for which this is not true, see many textbooks on
        # optics for an explanation
        mask = wavenum_sq > kz_sq
        g = np.zeros((len(kx), len(ky.T)), dtype=np.complex_)
        g[mask]=np.exp(1j * np.sqrt(wavenum_sq - kz_sq[mask]) * z_prop)
        res = np.fft.ifft2(g * np.fft.fft2(E_in))  # this is the result
        return res

    @staticmethod
    def volume_angular_spectrum_prop(E_in, x, y, z_prop, wavelen, normalized):
        """
         DESCRIPTION:
         volume_angular_spectrum_prop is an extension
         to angular_spectrum_prop from Fourier Optic by Goddman
         %% USAGE:% speckles3d = volume_angular_spectrum_prop(E_in, x, y, 3e2, 632e-6, true)
         % speckles3d = volume_angular_spectrum_prop(E_in, x, y, [0:0.01: 1].*3e2, 632e-6, true)
         %% INPUTS:%
          E_in - Feildtopropagate, notice that it should be the same  size of x, y
          x, y - 1Darrays in mm units
        z_prop - scaler / 1Darray in mm units of the z, axial location to propagate the feild
         wl - scaler, the wave length in mm
          normalized - bool.whether to normalize achaxial section of the 2D feild
          \%% OUTPUTS:% Intensity3d - 3D array of Intensity of the EM field.
        """
        s_z = len(z_prop) #;
        kx, ky, s_x, s_y = WaveSimulation.transverse_fourier_coordinates(x, y) #;
        alpha = ((kx / (2 * np.pi))* wavelen).astype(np.complex) #; % unitless normalized fourier coordinates
        beta = ((ky / (2 * np.pi))* wavelen).astype(np.complex) #; % unitless normalized fourier coordinates
        [Alpha, Beta] = np.meshgrid(alpha, beta,) # ;
        mu = ((2 * np.pi) / wavelen)* np.sqrt((Alpha** 2 + Beta**2) - 1) #;
        convolved_fourier = fftshift(fft2(E_in))#;
        Intensity3d = np.zeros((s_x, s_y, s_z))#;
        # angular    spectrum    of    propogation    distance    z
        for z_counter in range(s_z):
            z_pos = z_prop[z_counter] #;
            angs_prop_z = np.exp(1* mu* z_pos)#;
            E_out = ifft2(ifftshift(convolved_fourier* angs_prop_z))#;
            Iout = np.abs(E_out)** 2#;
            if normalized:
                Iout = Iout/ max(Iout[:])#; % Normalized
            Intensity3d[:,:, z_counter]=Iout

        return Intensity3d

    @staticmethod
    def transverse_fourier_coordinates(x, y):
        s_x = len(x) #;
        s_y = len(y) #;
        temp1 = np.arange(-s_x / 2,s_x / 2 ) / s_x  #;  [-0.5 0.5]     unitless
        temp2 = np.arange(-s_y / 2,s_y / 2 ) / s_y  #; % [-0.5 0.5]    unitless
        kx = temp1* (s_x * 2 * np.pi / (np.max(x) - np.min(x)))  #; % fourier    coordinates in 2    pi / mm
        ky = temp2* (s_y * 2 * np.pi / (np.max(y) - np.min(y)))  #;
        return kx, ky, s_x, s_y

    # Initialize work in mm
    def __init__(self,n=2**8,nz=2**8,*args,**kwargs):
        self.n=n
        self.nz=nz
        if len(args)>2:
            self.wav_length = args[0]  # ; % wave    length in mm
            self.NA = args[1]
            self.scatter_angle =args[2] # % % determined      by      the      material %
        else:
            self.wav_length = 2e-3  # ; % wave    length in mm
            self.NA = 0.2  # ;
            self.scatter_angle = 2 / 180 * np.pi  # % % determined      by      the      material

        self.min_focal_units = kwargs.pop('zmin', 0)
        self.max_focal_units = kwargs.pop('zmax', 1)
        self.length_x = kwargs.pop('length_x', 1)
        self.length_y = kwargs.pop('length_y', 1)
        self.x, self.y = np.arange(n)/self.n, np.arange(n)/self.n
        self.x=(self.x-np.mean(self.x))*self.length_x
        self.y = (self.y - np.mean(self.y))*self.length_y
        self.XX, self.YY = np.meshgrid(self.x, self.y)

    def creat_gaussian_beam(self, beam_width=1):
        self.RHO = np.sqrt((self.XX - np.mean(self.XX)) ** 2 + (self.YY - np.mean(self.YY)) ** 2)
        self.E0 = np.exp(-self.RHO ** 2 / beam_width)

    def diffuser(self):
        dx = self.length_x / self.n
        max_angle = ((self.wav_length / dx)) / 2

        T_diff = np.exp(1j * 2 * np.pi * np.random.rand(self.n))
        T_K = fftshift(fft2(T_diff))
        T_K = T_K * ((self.RHO / np.max(self.XX[:]) * max_angle) < self.scatter_angle)  # ; % determine    scattering    angle
        T_diff = ifft2(fftshift(T_K))
        # ; % convert    to    thin    phase    plate(meaning    takeing    only    the    phase    under    fft and not the    intensity)
        self.T_diff = np.exp(1j* np.angle(T_diff))

    def lens_phase(self,focal_length=5,**kwargs):
        nargout = kwargs.pop('nargout', 1)
        z_pos=np.linspace(self.min_focal_units,self.max_focal_units,self.nz)
        z = z_pos*focal_length
        # Lens    Phase
        #phase_of_lens = focal_length*np.ones(self.n) - np.sqrt(focal_length **2 * np.ones(self.n) - (self.XX** 2) - (self.YY**2))
        phase_of_lens = focal_length*1 - np.sqrt(focal_length **2 - (self.XX** 2) - (self.YY**2)+0j)
        phase_of_lens = phase_of_lens* (2 * np.pi / self.wav_length)
        A_lens = np.exp(-1j * phase_of_lens)
        A_lens = A_lens* (self.RHO < (np.max(self.XX[:]) *(self.NA)))
        if nargout>1:
            return A_lens,z
        else:
            return A_lens

def main():
    grid=WaveSimulation(2**8,2**8,length_x=1,length_y=1)
    normalized = 0
    grid.creat_gaussian_beam(0.05)
    A_lens,z=grid.lens_phase(focal_length=10,nargout=2)
    E_until_lens=grid.E0*A_lens
    fig1=plt.figure(1)
    plt.imshow(np.abs(E_until_lens))
    speckle3D = WaveSimulation.volume_angular_spectrum_prop(E_until_lens, grid.x, grid.y, z, grid.wav_length, normalized)
    ims=[]

    for depth in range(grid.nz-1):
        im = plt.imshow(speckle3D[:,:,depth], animated=True)
        ims.append([im])
    plt.rcParams['animation.ffmpeg_path'] = 'C:\\FFmpeg\\bin\\ffmpeg.exe'
    FFwriter = animation.FFMpegWriter(fps=10, extra_args=['-vcodec', 'libx264'])

    anim = animation.ArtistAnimation(fig1, ims, interval=200, blit=True,
                                    repeat_delay=100)
    anim.save('plswork.mp4', writer=FFwriter)
    plt.show()
    print(speckle3D.shape)
    plt.figure()
    plt.imshow(speckle3D[:,:, grid.nz // 2],interpolation='bicubic')
    plt.axis('off')
    plt.figure()
    plt.imshow(np.squeeze(speckle3D[:, grid.n // 2,:].T),interpolation='bicubic')
    plt.axis('off')
    plt.show()
    #return speckle3D

def animated_propagtion():
    grid = WaveSimulation(2 ** 8, 2 ** 8, length_x=10, length_y=10, zmin=-4,zmax=10)
    normalized = 0
    grid.creat_gaussian_beam(1)
    A_lens, z = grid.lens_phase(focal_length=100, nargout=2)
    E_until_lens = grid.E0 * A_lens
    fig1 = plt.figure(1)
    ims = []
    intersity3d = np.empty((grid.n, grid.n, grid.nz))
    for depth in range(grid.nz):
        feild2d = WaveSimulation.python_angular_spectrum_prop(E_until_lens, grid.x, grid.y, z[depth], 500e-6)
        intersity3d[:, :, depth] = (np.abs(feild2d) ** 2)
        im = plt.imshow(np.abs(feild2d) ** 2, animated=True)
        ims.append([im])
    plt.rcParams['animation.ffmpeg_path'] = 'C:\\FFmpeg\\bin\\ffmpeg.exe'
    FFwriter = animation.FFMpegWriter(fps=10, extra_args=['-vcodec', 'libx264'])

    anim = animation.ArtistAnimation(fig1, ims, interval=200, blit=True,
                                     repeat_delay=100)
    anim.save('now.mp4', writer=FFwriter)

def make_intersity3d(grid,feild,z):
    intersity3d = np.empty((grid.n, grid.n, grid.nz))
    for depth in range(grid.nz):
        feild2d = WaveSimulation.python_angular_spectrum_prop(feild, grid.x, grid.y, z[depth], 500e-6)
        intersity3d[:, :, depth] = (np.abs(feild2d) ** 2)
    return intersity3d

def fig1():
    grid = WaveSimulation(2 ** 8, 2 ** 8, length_x=1, length_y=1,zmin=0,zmax=2)
    grid.creat_gaussian_beam(0.05)
    A_lens, z = grid.lens_phase(focal_length=20, nargout=2)
    E_until_lens = grid.E0 * A_lens
    plt.imshow(np.abs(E_until_lens))
    plt.imshow(np.angle(E_until_lens))
    plt.show()
    intersity3d=make_intersity3d(grid,E_until_lens,z)
    print(np.argmax)
    fig1_1 = plt.figure(1)
    ax1=fig1_1.add_subplot(111) # First row, first column
    ax1.imshow((intersity3d[:,:,grid.nz//2])**(1/1.5))
    ax1.set_title("XY",fontsize=30)
    plt.axis('off')
    plt.show()
    fig1_2 = plt.figure(2)
    ax2=fig1_2.add_subplot(111) # First row, second column
    ax2.imshow((intersity3d[grid.n // 2-1, :, :].T)**1.5)
    ax2.set_title("XZ",fontsize=30)
    plt.axis('off')
    plt.show()

def fig2():
    grid = WaveSimulation(2 ** 8, 2 ** 8, length_x=1, length_y=1,zmin=0,zmax=2)
    grid.creat_gaussian_beam(0.05)
    A_lens, z = grid.lens_phase(focal_length=20, nargout=2)
    E_until_lens = grid.E0 * A_lens
    plt.imshow(np.abs(E_until_lens))
    plt.imshow(np.angle(E_until_lens))
    plt.show()
    intersity3d=make_intersity3d(grid,E_until_lens,z)
    print(np.argmax)
    fig2 = plt.figure(2)
    gs=GridSpec(4,4) # 4 rows, 4 columns
    gs.tight_layout(fig2, rect=[None, None, None, None])
    ax1=fig2.add_subplot(gs[0:2,0:2]) # First row, first column
    ax1.imshow(intersity3d[:,:,grid.nz//2])
    ax1.set_title("XY")
    plt.axis('off')
    ax2=fig2.add_subplot(gs[0:2,2:4]) # First row, second column
    ax2.imshow((intersity3d[grid.n // 2-1, :, :].T)**3)
    ax2.set_title("XZ")
    plt.axis('off')
    ax3=fig2.add_subplot(gs[2,0]) # First row, third column
    plt.axis('off')
    ax4=fig2.add_subplot(gs[2,1]) # Second row, span all columns
    plt.axis('off')
    ax5 = fig2.add_subplot(gs[2, 2])  # First row, third column
    plt.axis('off')
    ax6 = fig2.add_subplot(gs[2, 3])  # Second row, span all columns
    plt.axis('off')
    ax7 = fig2.add_subplot(gs[3, 0])  # First row, third column
    plt.axis('off')
    ax8 = fig2.add_subplot(gs[3, 1])  # Second row, span all columns
    plt.axis('off')
    ax9 = fig2.add_subplot(gs[3, 2])  # First row, third column
    plt.axis('off')
    ax10 = fig2.add_subplot(gs[3, 3])  # Second row, span all columns
    plt.axis('off')
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    """""
    speckle3D = main()
    window = tkinter.Tk()
    # to rename the title of the window
    window.title("z axus")
    # pack is used to show the object in the window
    label = tkinter.Label(window, text="Welcome to DataCamp's Tutorial on Tkinter!").pack()
    window.mainloop()
    w=tkinter.Label(window, from_=0, to=42)
    """""
    #main()
    fig1()
    #animated_propagtion()

def make3DGaussianKernel(shape,sigma):
    if len(shape)==0:
        raise ValueError('shape is empty,should be at list given one shape')
    else:
        nx=shape[0]
        if len(shape)==2:
            ny=shape[1]
            nz = shape[2]
        if len(shape)==1:
            ny = nx
            nz = shape[1]
        else:
            ny = nx
            nz = ny

    if len(sigma)==0:
        sigma=[1,1,1]
    else:
        if len(sigma)==1:
            sigma.extend([sigma[0], sigma[0]])
        if len(shape)==2:
            sigma.insert(1,sigma[0])
    x = np.arange(0,nx)
    x = x - np.mean(x)
    y = np.arange(0, ny)
    y = y - np.mean(y)
    z = np.arange(0, nz)
    z = z - np.mean(z)
    n1, n2, n3 = np.meshgrid(x, y, z)
    gaussKER = np.exp(-n1**2/ sigma[0]  -n2**2/ sigma[1] -n3**2/ sigma[2])
    gaussKER = gaussKER/ np.sum(gaussKER)
    return gaussKER


import numpy as np
import scipy.stats as st
import sys

if sys.argv != 2:
    print("usage: python3 stats.py file_name")

with open(sys.argv[1]) as f:
    lines = f.read().split("\n")
    data_arrays = {}
    for line in lines:
        s = line.split("\t")
        if len(s) == 3 and "ok" not in line and "FAIL" not in line: # ignore meta info
            exp_name = s[0].strip()
            time = s[2]
            time = time.replace("ns/op", "")
            time = float(time.strip()) # want milliseconds, not nanoseconds
            if exp_name in data_arrays.keys():
                data_arrays[exp_name].append(time)
            else:
                data_arrays[exp_name] = [time]

for exp in data_arrays.keys():
    data = np.array(data_arrays[exp])
    avg = "{:.2f}".format(np.average(data)/1000000)
    median = "{:.2f}".format(np.median(data)/1000000)
    ci =  "{:.2f}".format((2*np.std(data)/pow(len(data), 0.5))/1000000)
    ci_div_avg = ((2*np.std(data)/pow(len(data), 0.5))/1000000)/(np.average(data)/1000000)

    print(exp, "\n")
    print("\taverage: ", avg, "\tmedian: ", median, "\tconfidence interval", ci, "\t ci/avg", ci_div_avg, "\n")
    #print(exp, "\t\t", avg, "\t", median, "\t", stdev, "%\n")


import numpy as np

class sigmoid:
    @staticmethod
    def forward(x):
        return 1.0 / (1.0 + np.exp(- x))

    @staticmethod
    def backward(x, top_diff):
        output = sigmoid.forward(x)
        return (1.0 - output) * output * top_diff

class tanh:
    @staticmethod
    def forward(x):
        return np.tanh(x)

    @staticmethod
    def backward(x, top_diff):
        output = tanh.forward(x)
        return (1.0 - np.square(output)) * top_diff

class softmax:
    @staticmethod
    def predict(x):
        exp_scores = np.exp(x)
        return exp_scores / np.sum(exp_scores, axis=1, keepdims=True)

    @staticmethod
    def loss(x, y):
        num_examples = x.shape[0]
        prob = softmax.predict(x)
        logprob = -np.log(prob[range(num_examples), y])
        data_loss = np.sum(logprob)
        return 1. / num_examples * data_loss

    @staticmethod
    def diff(x, y):
        num_examples = x.shape[0]
        prob = softmax.predict(x)
        prob[range(num_examples), y] -= 1
        return prob


import numpy as np

# From lecture slides - CSE573

def get_homography_matrix(pts1, pts2):
    """Returns a 3*3 homograpy matrix that maps pts1 to pts2. CAlculates the
    homography matrix by using the using the eigen value of the smallest eigen vector
    of set of equations formed by given points or Direct Linear Transform.

    Arguments:
        pts1 {np.ndarray} -- List of points for which homography is computed
        pts2 {np.ndarray} -- List of points using which homography is computed

    Returns:
        np.ndarray -- A matrix mapping pts1 to pts2
    """

    eqn_list = []
    # Form set of equations from the given points
    for (x1, y1), (x2, y2) in zip(pts1, pts2):
        row1 = [x1, y1, 1, 0, 0, 0, -x1*x2, -y1*x2, -x2]
        row2 = [0, 0, 0, x1, y1, 1, -x1*y2, -y1*y2, -y2]
        eqn_list.append(row1)
        eqn_list.append(row2)

    # Solve for A.h = 0 i.e., h = eigen value corresponding to smallest eigen value of A'A
    A = np.array(eqn_list)
    eig_values, eig_vectors = np.linalg.eig(np.dot(A.T, A))
    h_index = eig_values.argmin()
    h = eig_vectors[:, h_index]

    # Convert h to a unit vector
    h = h / np.linalg.norm(h)
    h /= h[-1]
    h = h.reshape(3, 3)
    return h


from sympy.core.symbol import symbols
from sympy.solvers.solveset import nonlinsolve
import json
import sys

symbol_dict = json.loads(sys.argv[1])
unknown_list = json.loads(sys.argv[2])
precision = int(sys.argv[3])

for unknown in unknown_list:
    symbol_dict[unknown] = symbols(unknown)

momentum_equation = (symbol_dict["m"]*symbol_dict["v"]) - symbol_dict["p"]
kinetic_energy_equation = (symbol_dict["m"]*symbol_dict["v"]**2)/2 - symbol_dict["e"]

solution = nonlinsolve([momentum_equation, kinetic_energy_equation], unknown_list)

solution_pp = {}

for i,v in enumerate((unknown_list)):
    solution_pp[v] = round(float(list(solution)[0][i]), precision)

print(json.dumps(solution_pp))

# Test: python3 src/lib/python/solve_object_properties.py '{"m1i":1,"m1f":1,"v1i":1,"m2i":2,"m2f":2,"v2i":0,"re":1, "re_positive": true}' '["v1f","v2f"]'


import numpy as np
import matplotlib.pyplot as plt

import MyFFT as F

PI = np.pi

N = 2**8 # 2の累乗のデータ数
fs = 100 # サンプリング周波数
T = 1/fs # サンプリング周期
PI = np.pi
f1 = 10; f2 = 20; f3 = 30 # sin波に使う周波数
A1 = 1; A2 = 0.5; A3 = 0.8 #sin波に使う振幅
t = np.arange(0, N*T, T) # sin波の時間 N*T秒

#サンプルのsin波形
x = A1*np.sin(2*PI*f1*t)+A2*np.sin(2*PI*f2*t)+A3*np.sin(2*PI*f3*t)

testF = F.my_fft(x)
amp = 2*np.abs(testF)/N # プロットの振幅
freq = np.linspace(0, fs, N) # プロットの周波数

plt.plot(freq[:int(N/2)+1], amp[:int(N/2)+1])
plt.show()


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

def main():

    print("Solving the nuclear decay equation")

    t12 = float(input("Half life = "))

    c = math.log(2) / t12

    st = float(input("Start of time interval = "))

    et = float(input("End of time interval = "))

    h = float(input("Step size = "))            # distance between grid points

    t = np.arange(start=st, stop=et, step=h, dtype=float)  # time array

    n = t.size

    A = sp.lil_matrix((n, n))               # Coefficient matrix

    A.setdiag(-1/(2 * h), -1)                   # Building the diagonals
    A.setdiag(c, 0)
    A.setdiag(1/(2 * h), 1)

    A[0, 0] = 1                                 # Building the 0th row
    A[0, 1] = 0

    A[n - 1, n - 2] = -1 / h                        # Building the nth row
    A[n - 1, n - 1] = 1 / h + c

    A = A.tocsr()

    b = sp.lil_matrix((n, 1))               # RHS vector

    b[0, 0] = float(input("Initial mass = "))

    y = sp.linalg.spsolve(A, b)                 # Solving the system

    plt.plot(t, y, label="dm/dt = - (ln|2| / half-life) * m")          # Plotting the system
    plt.title("Decay Equation")
    plt.xlabel("time")
    plt.ylabel("mass")
    plt.legend()
    plt.show()

main()


from scipy import integrate
def integrand(x0, x1, x2):
    return x2 * x1**2 + x0
x2_lim = (0.0, 0.5)
x1_lim = lambda x2:(0.0, 1.0-2.0*x2)
x0_lim = lambda x1,x2:(-1.0, 1.0+2.0*x2-x1)
# int_{x2=0}^{0.5} int_{x1=0}^{1-2x2} int_{x0=-1}^{1+2x2-x1} (x2 x1**2 + x0) dx0 dx1 dx2
integral,error = integrate.nquad(integrand, [x0_lim, x1_lim, x2_lim])
print(integral, error)

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


#%%
"""
Created on July 12 2021
Ho-Lee Model, Simulation of the Model + Computation of ZCBs, P(0,t)

This code is purely educational and comes from "Financial Engineering" course by L.A. Grzelak
The course is based on the book “Mathematical Modeling and Computation
in Finance: With Exercises and Python and MATLAB Computer Codes”,
by C.W. Oosterlee and L.A. Grzelak, World Scientific Publishing Europe Ltd, 2019.
@author: Lech A. Grzelak
"""

import numpy as np
import matplotlib.pyplot as plt

def f0T(t,P0T):
    # time-step needed for differentiation
    dt = 0.01
    expr = - (np.log(P0T(t+dt))-np.log(P0T(t-dt)))/(2*dt)
    return expr

def GeneratePathsHoLeeEuler(NoOfPaths,NoOfSteps,T,P0T,sigma):

    # Initial interest rate is a forward rate at time t->0
    r0 = f0T(0.01,P0T)
    theta = lambda t: (f0T(t+dt,P0T)-f0T(t-dt,P0T))/(2.0*dt) + sigma**2.0*t

    Z = np.random.normal(0.0,1.0,[NoOfPaths,NoOfSteps])
    W = np.zeros([NoOfPaths, NoOfSteps+1])
    R = np.zeros([NoOfPaths, NoOfSteps+1])
    M = np.zeros([NoOfPaths, NoOfSteps+1])
    M[:,0]= 1.0
    R[:,0]=r0
    time = np.zeros([NoOfSteps+1])

    dt = T / float(NoOfSteps)
    for i in range(0,NoOfSteps):
        # making sure that samples from normal have mean 0 and variance 1
        if NoOfPaths > 1:
            Z[:,i] = (Z[:,i] - np.mean(Z[:,i])) / np.std(Z[:,i])
        W[:,i+1] = W[:,i] + np.power(dt, 0.5)*Z[:,i]
        R[:,i+1] = R[:,i] + theta(time[i]) * dt + sigma* (W[:,i+1]-W[:,i])
        M[:,i+1] = M[:,i] * np.exp((R[:,i+1]+R[:,i])*0.5*dt)
        time[i+1] = time[i] +dt

    # Outputs
    paths = {"time":time,"R":R,"M":M}
    return paths

def mainCalculation():
    NoOfPaths = 25000
    NoOfSteps = 500

    sigma = 0.007

    # We define a ZCB curve (obtained from the market)
    P0T = lambda T: np.exp(-0.1*T)

    # In this experiment we compare ZCB from the Market and Monte Carlo
    "Monte Carlo part"
    T = 40
    paths= GeneratePathsHoLeeEuler(NoOfPaths,NoOfSteps,T,P0T,sigma)
    M = paths["M"]
    ti = paths["time"]

    # Here we compare the price of an option on a ZCB from Monte Carlo and Analytical expression
    P_t = np.zeros([NoOfSteps+1])
    for i in range(0,NoOfSteps+1):
        P_t[i] = np.mean(1.0/M[:,i])

    plt.figure(1)
    plt.grid()
    plt.xlabel('T')
    plt.ylabel('P(0,T)')
    plt.plot(ti,P0T(ti))
    plt.plot(ti,P_t,'--r')
    plt.legend(['P(0,t) market','P(0,t) Monte Carlo'])
    plt.title('ZCBs from Ho-Lee Model')

mainCalculation()

Lecture 03-The HJM Framework/Materials/Ho-Lee-ZCBs.py


from __future__ import absolute_import
from __future__ import print_function
import autograd.numpy as np
from autograd import value_and_grad
from scipy.optimize import minimize

def rosenbrock(x):
    return 100*(x[1] - x[0]**2)**2 + (1 - x[0])**2

# Build a function that also returns gradients using autograd.
rosenbrock_with_grad = value_and_grad(rosenbrock)

# Optimize using conjugate gradients.
result = minimize(rosenbrock_with_grad, x0=np.array([0.0, 0.0]), jac=True, method='CG')
print("Found minimum at {0}".format(result.x))


"""
Simple linear regression, as seen in the previous recipe, is excellent for
producing simple models of a relationship between one response variable and one
predictor variable. Unfortunately, it is far more common to have a single
response variable that depends on many predictor variables. Moreover, we might
not know which variables from a collection make good predictor variables. For
this task, we need multilinear regression.

This module illustrates how to use multilinear regression to explore the
relationship between a response variable and several predictor variables.
"""
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt

from numpy.random import default_rng

rng = default_rng(12345)
p_vars = pd.DataFrame({
    "const": np.ones((100,)),
    "X1": rng.uniform(0, 15, size=100),
    "X2": rng.uniform(0, 25, size=100),
    "X3": rng.uniform(5, 25, size=100)
})

residuals = rng.normal(0.0, 12.0, size=100)
Y = -10.0 + 5.0 * p_vars["X1"] - 2.0 * p_vars["X2"] + residuals

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharey=True, tight_layout=True)
ax1.scatter(p_vars["X1"], Y)
ax2.scatter(p_vars["X2"], Y)
ax3.scatter(p_vars["X3"], Y)

ax1.set_title("Y against X1")
ax1.set_xlabel("X1")
ax1.set_ylabel("Y")
ax2.set_title("Y against X2")
ax2.set_xlabel("X2")
ax3.set_title("Y against X3")
ax3.set_xlabel("X3")

plt.show()

model = sm.OLS(Y, p_vars).fit()
second_model = sm.OLS(Y, p_vars.loc[:, "const":"X2"]).fit()

print(model.summary())
print(second_model.summary())

import numpy,from numpy,import statsmodels


import numpy as np

# create a n.n matrix
def createSquareMatrix(n):
    matrix = np.random.random((n, n))
    return matrix

# Calculate det() of a matrix
def determinant_recursive(matrix_numpy, total=0):
    # convert numpy array to list
    # np.array([[1, 2], [3, 4]]) => [[1, 2], [3, 4]]
    if type(matrix_numpy) is not list:
        matrix = matrix_numpy.tolist()

    # Store indices in list for row referencing
    indices = list(range(len(matrix)))
    print("i:", indices)
    # 2x2 matrix
    if len(matrix) == 2 and len(matrix[0]) == 2:
        val = matrix[0][0] * matrix[1][1] - matrix[1][0] * matrix[0][1]
        return val

    # submatrix for focus column (fc)
    for fc in indices:  # for each focus column, ...
        # find the submatrix ...
        s_matrix = matrix.copy()  # make a copy
        s_matrix = s_matrix[1:]  # remove the first row
        height = len(s_matrix)
        print("s_m:", s_matrix)
        print("h:", height)

        for i in range(height):
            # for each remaining row of submatrix ...
            # remove the focus column elements
            s_matrix[i] = s_matrix[i][0:fc] + s_matrix[i][fc + 1:]

        sign = (-1) ** (fc % 2)
        # pass submatrix recursively
        sub_det = determinant_recursive(s_matrix)
        # total all returns from recursion
        total += sign * matrix[0][fc] * sub_det

    return total

# Calculate inverse()
def inversion_matrix(matrix_np):
    AM = matrix_np.tolist()
    n = len(AM)
    IM = np.eye(n)

    indices = list(range(n))  # to allow flexible row referencing
    for fd in range(n):  # fd stands for focus diagonal
        fdScaler = 1.0 / AM[fd][fd]
        # FIRST: scale fd row with fd inverse.
        for j in range(n):  # Use j to indicate column looping.
            AM[fd][j] *= fdScaler
            IM[fd][j] *= fdScaler

            # SECOND: operate on all rows except fd row.
        for i in indices[0:fd] + indices[fd + 1:]:  # *** skip row with fd in it.
            crScaler = AM[i][fd]  # cr stands for "current row".
            for j in range(n):  # cr - crScaler * fdRow, but one element at a time.
                AM[i][j] = AM[i][j] - crScaler * AM[fd][j]
                IM[i][j] = IM[i][j] - crScaler * IM[fd][j]

    return np.multiply(matrix_np, IM)

# Main
print()


import numpy as np
from skfuzzy import cmeans

from config import NAN, FCMParam

class FCMeansEstimator:
    def __init__(self, c, m, data):
        self.c = c
        self.m = m
        self.data = data
        self.complete_rows, self.incomplete_rows = self.__extract_rows()

    # Extract complete and incomplete rows
    def __extract_rows(self):
        rows, columns = len(self.data), len(self.data[0])
        complete_rows, incomplete_rows = [], []
        for i in range(rows):
            for j in range(columns):
                if self.data[i][j] == NAN:
                    incomplete_rows.append(i)
                    break
                complete_rows.append(i)

        return np.array(complete_rows), np.array(incomplete_rows)

    # Estimate the missing values
    def estimate_missing_values(self):
        estimated_data = []
        complete_data = np.array([self.data[x] for x in self.complete_rows])
        centers, _, _, _, _, _, _ = cmeans(data=complete_data.transpose(), c=self.c, m=self.m, error=FCMParam.ERROR,
                                           maxiter=FCMParam.MAX_ITR, init=None)

        # Calculate distance between two points based on euclidean distance
        def calculate_distance(data_1, data_2):
            return np.linalg.norm(data_1 - data_2)

        # Calculate the membership value for given point
        def calculate_membership(dist_matrix, distance, m):
            numerator = np.power(distance, -2 / (1 - m))
            denominator = np.array([np.power(x, -2 / (1 - m)) for x in dist_matrix]).sum()
            return numerator / denominator

        for i in self.incomplete_rows:
            estimated = 0
            dist, membership_value = [], []
            miss_ind = np.where(self.data[i] == NAN)[0][0]

            for center in centers:
                dist.append(calculate_distance(data_1=np.delete(np.array(center), miss_ind),
                                               data_2=np.delete(np.array(self.data[i]), miss_ind)))

            for d in dist:
                membership_value.append(calculate_membership(dist, d, self.m))

            for k in range(self.c):
                estimated += centers[k][miss_ind] * membership_value[k]

            estimated_data.append(estimated)

        return np.array(estimated_data)


import numpy as np
import theano
from theano.tests import unittest_tools as utt
from pymc3.math import LogDet, logdet, probit, invprobit
from .helpers import SeededTest

def test_probit():
    p = np.array([0.01, 0.25, 0.5, 0.75, 0.99])
    np.testing.assert_allclose(invprobit(probit(p)).eval(), p, atol=1e-5)

class TestLogDet(SeededTest):
    def setup_method(self):
        super(TestLogDet, self).setup_method()
        utt.seed_rng()
        self.op_class = LogDet
        self.op = logdet

    def validate(self, input_mat):
        x = theano.tensor.matrix()
        f = theano.function([x], self.op(x))
        out = f(input_mat)
        svd_diag = np.linalg.svd(input_mat, compute_uv=False)
        numpy_out = np.sum(np.log(np.abs(svd_diag)))

        # Compare the result computed to the expected value.
        utt.assert_allclose(numpy_out, out)

        # Test gradient:
        utt.verify_grad(self.op, [input_mat])

    def test_basic(self):
        # Calls validate with different params
        test_case_1 = np.random.randn(3, 3) / np.sqrt(3)
        test_case_2 = np.random.randn(10, 10) / np.sqrt(10)
        self.validate(test_case_1.astype(theano.config.floatX))
        self.validate(test_case_2.astype(theano.config.floatX))

import numpy,import theano,from theano,from pymc3


from math import floor

import numpy as np

def absolute(a: float, size: int, clip: bool = False) -> int:
    res = a * size
    if clip:
        res = np.clip(res, 0, size)
    return int(res)

def relative(a: int, size: int) -> float:
    return a / size

def interval(a: float, size: float):
    parts = int(1.0 / size)
    return min(floor(a * parts), parts - 1)
    # return min(floor(a / size), parts - 1)

if __name__ == '__main__':
    s = .1
    for x in [
        0.,
        .099,
        .1,
        .265,
        .485,
        .8999999,
        .9,
        .999999999,
        .999999999999999999999999999999999999999999999999999,

        1.
    ]:
        val = interval(x, s)
        print(x, ' -> ', val)


"""
This module is for functions which perform measurements.
"""

import numpy as np

def calculate_distance(rA, rB, dimensions="xyz"):
    """Calculate the distance between two points.

    Parameters
    ----------
    rA, rB : np.ndarray
        The coordinates of each point.
    dimensions : str (optional)
        The distance projection on the specified dimensions. Default: "xyz"

    Returns
    -------
    distance : float
        The distance between the two points.

    Examples
    --------
    >>> r1 = np.array([0, 0, 0])
    >>> r2 = np.array([0, 0.1, 0])
    >>> calculate_distance(r1, r2)
    0.1
    """
    # This function calculates the distance between two points given as numpy arrays.
    if isinstance(rA, np.ndarray) is False or isinstance(rB, np.ndarray) is False:
        raise TypeError("rA and rB must be numpy arrays")

    dist_vec = rA - rB

    for i, d in enumerate("xyz"):
        if d not in dimensions:
            dist_vec[0][i] = 0

    distance = np.linalg.norm(dist_vec)

    if distance == 0.0:
        raise Exception("Two atoms are located in the same point in space")

    return distance

def calculate_angle(rA, rB, rC, degrees=False):
    # Calculate the angle between three points. Answer is given in radians by default, but can be given in degrees
    # by setting degrees=True
    AB = rB - rA
    BC = rB - rC
    theta = np.arccos(np.dot(AB, BC) / (np.linalg.norm(AB) * np.linalg.norm(BC)))

    if degrees:
        return np.degrees(theta)
    else:
        return theta

# Conversions between radians and degrees
def RAD2DEG(rad):
    return rad * 57.295779513082325

def DEG2RAD(deg):
    return deg * 0.017453292519943

def calculate_volume(a, b, c, alpha, beta, gamma):
    """Calculate the volume of a unit cell.

    Parameters
    ----------
    a : float
        Unit cell length in Angstroms
    b : float
        Unit cell length in Angstroms
    c : float
        Unit cell length in Angstroms
    alpha : float
        Unit cell angle in degrees
    beta : float
        Unit cell angle in degrees
    gamma : float
        Unit cell angle in degrees

    Returns
    -------
    volume : float
        the volume of the unit cell in cubic Angstrom
    """

    c_x = c * np.cos(DEG2RAD(beta))
    c_y = (
        c
        * (np.cos(DEG2RAD(alpha)) - np.cos(DEG2RAD(beta)) * np.cos(DEG2RAD(gamma)))
        / np.sin(DEG2RAD(gamma))
    )
    c_z = np.sqrt(c * c - c_x * c_x - c_y * c_y)
    return a * b * c_z * np.sin(DEG2RAD(gamma))

def calculate_rotation(vk):
    z = np.array([0, 0, 1])
    axis = np.cross(vk, z)
    theta = np.arccos(np.dot(z, vk))
    return axis, theta


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

# # Linear Regression With Gradient Descent
# Linear Regression is the art of finding relationship between two or more variables and it is a kind of supervised learning problem which uses continous value dataset. Linear regression is useful in finding the best fit line which descibes how different features are related to each other.
# For more info: [Linear Regression](https://en.wikipedia.org/wiki/Linear_regression)
#

# The code in this notebook will not use any libraries except numpy for mathematical calculations and matplotlib for graph plotting and pandas for handling data. This will give a better understanding of how machine learning algorithms works under the hood.

# ## Dataset
# The dataset consists of two columns
# * Number of study hours
# * Test Scores

# In[3]:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt, rcParams as rc
rc["figure.figsize"] = 10,6

# ## Error function
# Error function is used to calculate the cost or the error on each iteration. Here we use Mean Squared Error algorithm for calculating the error.
#         $RMSE = \frac{1}{2n}\Sigma_{i=1}^{n}{({h_i -Y_i})^2}$
#

# In[4]:

def error_function(features,labels,m,c):
    m_derived = np.sum((m*features + c - labels)*features)/len(labels)
    c_derived = np.sum((m*features + c)-labels)/len(labels)
    error = np.sum(np.square(m*features+c - labels))/(2*len(labels))
    return [m_derived,c_derived,error]

# ## Gradient Descent
# Gradient descent is a very important parameter learning algorithm which is used to decide the value of parameters for which the cost function is minimum. The below function will perform a single step of gradient descent.

# ![gradient_descent%20.png](attachment:gradient_descent%20.png)

#
#

# In[5]:

def  step_gradient_descent(features,labels,learning_rate,c,m):
    [derived_m,derived_c,error] = error_function(features.values.reshape(100,1),labels.values.reshape(100,1),m,c)
    m = m - learning_rate*derived_m
    c = c - learning_rate*derived_c
    return [c,m,error]

# This function repeats the gradient descent step multiple times to minimize the cost function J(Q).

# In[6]:

def gradient_descent_runner(features,labels,learning_rate,initial_c,initial_m,num_iterations):
    m= initial_m
    c=initial_c
    error_list=[]
    for a in range(num_iterations):
        [c,m,error] = step_gradient_descent(features,labels,learning_rate,c,m)
        error_list.append(error)
    return [c,m,error,error_list]

# ## Start
# Here we decide the following parameters for our linear regression Model.
# * Learning rate
# * initial value for out parameters
# * number of iterations for the gradient descent
#

# In[7]:

def run():
    points = pd.read_csv('data.csv',delimiter=',',header = None,names=['study hours','test scores']).sort_values(by=['study hours'])
    learning_rate=0.000001
    initial_c = 4
    initial_m = 5
    num_iterations = 1000
    [c,m,error,error_list]=gradient_descent_runner(points['study hours'],points['test scores'],learning_rate,initial_c,initial_m,num_iterations)
    plt.title("study hours v/s test scores")
    plt.scatter(points['study hours'],points['test scores'])
    plt.plot(points['study hours'],m*points['study hours']+c)
    plt.xlabel('study hours')
    plt.ylabel('test scores')
    plt.show()
    print("cost function is {}".format(error))
    plt.title("Cost Function Convergence graph")
    plt.plot(list(range(num_iterations)),error_list)
    plt.xlabel("No. of iterations")
    plt.ylabel("Cost Function")

run()

# # Graphs
# ## Study hours and test Scores
# The graph shows how the test scores of students are affected by the number of study hours. The best fit line shows how well the learning algorithm performed.
#
# ## No. of Iterations V/S Cost Function
# A good way according to me to check whether the algorithm is working fine is by plotting a graph between Cost function. If the cost function is decreasing, it means that the learning algorithm is working fine. You can even check the effect of learning rate on gradient descent by fine tuning it yourself.

# In[ ]:


#!/usr/bin/env python

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

x, y = syp.symbols('x y')

fxy = x**2 + y**2
plane = 4*(x-2) + 4*(y-2)

syp.plotting.plot3d(fxy,plane)

#expr_1 = x**2 + y**2
#x_range_1 = (x, -5, 5)
#y_range_1 = (y, -5, 5)
#
#expr_2 = -x**2 + -y**2
#x_range_2 = (x, -5, 5)
#y_range_2 = (y, -5, 5)
#
#p1 = syp.plotting.plot3d(
#    (expr_1, x_range_1, y_range_1),
#    (expr_2, x_range_2, y_range_2)
#)

# x, y, z = syp.symbols('x y z')
#
# curve_1 = x
# curve_2 = x**2
# curve_3 = x**3
#
# x_range = (x, -10, 10)
#
# syp.plot(curve_1, curve_2, curve_3, x_range, show = False)

#my_function = x**2 + y**2 - 50

#curve_1 = syp.plot3d(my_function)

#plot3d(my_function)

# x = symbols('x')
# p1 = plot(x*x)
# p2 = plot(x)
# p1.extend(p2)

#  ########################
#  # Straight matplot lib
#  ########################
#  from mpl_toolkits.mplot3d import Axes3D
#  import matplotlib.pyplot as plt
#  from matplotlib import cm
#  from matplotlib.ticker import LinearLocator, FormatStrFormatter
#  import numpy as np
#
#  fig = plt.figure()
#  ax = fig.gca(projection='3d')
#
#  # Make data.
#  X = np.arange(-5, 5, 0.05)
#  Y = np.arange(-5, 5, 0.05)
#
#  X, Y = np.meshgrid(X, Y)
#  f = X**2 + Y**2
#
#  # Plot the surface.
#  surf = ax.plot_surface(X, Y, f, cmap=cm.coolwarm,
#                         linewidth=0, antialiased=False)
#
#  plane = 4*(X-2) + 4*(Y-2)
#  surf = ax.plot_surface(X, Y, plane, cmap=cm.coolwarm,
#                         linewidth=0, antialiased=False)
#
#  # Customize the z axis.
#  #ax.set_zlim(-1.01, 1.01)
#  #ax.zaxis.set_major_locator(LinearLocator(10))
#  #ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
#
#  ## Add a color bar which maps values to colors.
#  fig.colorbar(surf, shrink=0.5, aspect=5)
#
#  plt.show()


"""
Solve OT problem
"""

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

class EarthMovers2D:

    dimension = '2D'

    def __init__(self, n: int):
        self.n = n  # number of samples
        self.p = None
        self._set_positions()
        # Cost matrix
        self.M = None
        # OT matrix
        self.T = None
        # sample are uniform
        self.a = []
        self.b = []

    def _set_positions(self):
        # source position
        self.xs = np.random.random_sample((self.n, 2))
        # target position
        self.xt = np.random.random_sample((self.n, 2))

    def _compute_loss_matrix(self):
        """Return loss matrix"""
        self.M = (ot.dist(self.xs, self.xt,
                          metric='sqeuclidean'))**(self.p / 2)

    def get_ot_matrix(self):
        """Return optimal transport matrix"""
        self._compute_loss_matrix()
        return ot.emd(self.a, self.b, self.M)

    def get_wasserstein_distance(self) -> float:
        """Return Wasserstein_distance"""
        return np.sum(self.T * self.M)

    def compute_ot(self):
        """Solve OT problem"""
        self.T = self.get_ot_matrix()

    def get_distances(self):
        """Return a 1D-array of the distances"""
        return np.extract(self.T / self.T.max() > 1e-8, self.M)

    def create_figure(self, suptitle: str):
        """Create empty figure"""
        fig, ax = plt.subplots()
        ax.set_xlabel('$x$')
        ax.set_ylabel('$y$')
        ax.set_aspect('equal', 'datalim')  # x and y scales are equal
        fig.suptitle(suptitle)
        return ax

    def plot_ot(self, p=1., plot_points=True):
        """A 2D plot of the OT problem"""
        self.p = p
        xs = self.xs
        xt = self.xt
        ax = self.create_figure(suptitle='Source and target distributions')

        self.compute_ot()

        max_distance = self.get_distances().max()
        # inspired by plot2D_samples_mat()
        mx = self.T.max()
        for i in range(self.n):
            for j in range(self.n):
                if self.T[i, j] / mx > 1e-8:
                    color_scale = 1 - self.M[i, j] / max_distance
                    c = [color_scale, color_scale, color_scale]
                    ax.plot([xs[i, 0], xt[j, 0]], [xs[i, 1], xt[j, 1]], c=c)
        if plot_points:
            ax.plot(xs[:, 0], xs[:, 1], 'ob', label='Source samples')
            ax.plot(xt[:, 0], xt[:, 1], 'or', label='Target samples')
            ax.legend(loc=0)
        wd = self.get_wasserstein_distance()
        ax.set_title(f"$p = {self.p}$ - Wasserstein distance: {wd:f}",
                     fontsize=10)

    def plot_distance_histogram(self, p=1., bins=10):
        """Plot an histogram of distance"""
        self.p = p
        self.compute_ot()
        distances = self.get_distances()
        fig, ax = plt.subplots()
        plt.hist(distances, bins=bins)
        ax.set_xlabel("Distance")
        ax.set_ylabel("Number of matchings")
        fig.suptitle("Histogram of distance", fontsize=14)
        ax.set_title(f"{self.dimension} - $p = {self.p}$")

class EarthMovers1D(EarthMovers2D):

    dimension = '1D'

    def _set_positions(self):
        # source and target positions
        self.xs = np.empty((self.n, 2))
        self.xt = np.empty((self.n, 2))
        # source
        self.xs[:, 0] = np.random.random_sample((self.n, ))
        self.xs[:, 1] = 0.
        # target
        self.xt[:, 0] = np.random.random_sample((self.n, ))
        self.xt[:, 1] = 1.

    def _compute_loss_matrix(self):
        """Return loss matrix"""
        self.M = (ot.dist(self.xs, self.xt, metric='sqeuclidean')
                  - 1)**(self.p / 2)

if __name__ == '__main__':
    em = EarthMovers2D(500)
    em.plot_ot(p=1., plot_points=False)

    em1D = EarthMovers1D(50)
    em1D.plot_ot(p=1.00001)

    em1000 = EarthMovers2D(1000)
    em1000.plot_distance_histogram(bins=20)

    plt.show()


import numpy as np
import scipy.linalg as la
from auxiliary import *

A = np.array([
    [ 0 ,  3  ,  2  ,  1 ],
    [ 1 , 1j  , 1j  , 1j ],
    [ 2 ,  2  , 2j  , 2j ],
    [ 3 ,  3  ,  3  , 3j ],
], dtype=complex)

U, s, Vt = la.svd(A, lapack_driver='gesvd')

mprintC('amat', A)
mprintC('uCorrect',  U)
vprint('sCorrect',  s)
mprintC('vtCorrect', Vt)

m, n = np.shape(A)
ns   = min([m, n])

S = np.zeros((m, n))
for i in range(ns):
    S[i,i] = s[i]
USVt = np.dot(U, np.dot(S, Vt))

print 'A    =\n', A
print 'USVt =\n', USVt
print np.allclose(A, USVt)


import numpy as np
from numpy import linalg as la
from scipy.linalg import block_diag
from scipy.stats import ortho_group

############### PURPOSE #################
# SBD is a simple and efficient algorithm for finding a (often finest) simultaneous block diagonalization of an arbitrary number of symmetric matrices.
# The algorithm works by finding the eigendecomposition of a single matrix, which is a random linear combination of all the matrices to be simultaneously block diagonalized.
# The current algorithm is inspired by the results presented in K. Murota et al. Jpn. J. Ind. Appl. Math 27, 125–160 (2010).
# For an efficient algorithm that also guarantees the optimal SBD, see https://github.com/y-z-zhang/net-sync-sym.
# There, you can also find concrete examples on how the SBD algorithm can be applied to analyze cluster synchronization patterns in complex networks.

############### USEAGE #################
# [P,BlockSizes] = sbd(A,threshold)
# A --- list containing the set of matrices to be simultaneously block diagonalized
# threshold --- real number, matrix entries below threshold are considered zero
# P --- orthogonal transformation matrix that performs SBD on A
# BlockSizes --- array listing the size of each common block

############### REFERENCE #################
# Y. Zhang, V. Latora, and A. E. Motter,
# Unified treatment of synchronization patterns in generalized networks with higher-order, multilayer, and temporal interactions,
# Commun. Phys. 4, 195 (2021).

def sbd(A,threshold):
	n = len(A[0])	# size of the matrices to be simultaneously block diagonalized
	m = len(A)		# number of matrices to be simultaneously block diagonalized
	BlockSizes = []	# initialize the array that lists the size of each common block

    # B is a random self-adjoint matrix generated by matrices from A (and their conjugate transposes)
	B = np.zeros((n,n))
	for p in range(m):
		B = B + np.random.normal()*(A[p]+A[p].transpose())

    # find the eigenvalues and eigenvectors of B
	D, V = la.eigh(B)

    # C is a matrix used to sort the column vectors of V (i.e., the base vectors)
    # such that the base vectors corresponding to the same common block are next to each other
	C = np.zeros((n,n))
	for p in range(m):
		C = C + np.random.normal()*(A[p]+A[p].transpose())
	C = V.transpose()@C@V
	#for p in range(m):
	#	C = C + np.random.normal()*V.transpose()@A[p]@V

    # arrays used to track which base vectors have been sorted
	remaining_basis = list(range(n))
	sorted_basis = []

    # the sorting process: find C_ij's that are nonzero and group the base vectors v_i and v_j together
	while len(remaining_basis) > 0:
		current_block = [remaining_basis[0]]
		current_block_size = 1
		if len(remaining_basis) > 1:
			for idx in remaining_basis[1:]:
				if np.abs(C[remaining_basis[0],idx]) > threshold:
					current_block.append(idx)
					current_block_size = current_block_size + 1

		for idx in current_block:
			sorted_basis.append(idx)
			remaining_basis.remove(idx)

		# do the following in case there are zero entries inside the block
		current_block_extra = []
		if len(remaining_basis) > 0:
			for idx in remaining_basis:
				for ind in current_block:
					if np.abs(C[ind,idx]) > threshold:
						current_block_extra.append(idx)
						current_block_size = current_block_size + 1
						break

		for idx in current_block_extra:
			sorted_basis.append(idx)
			remaining_basis.remove(idx)

		BlockSizes.append(current_block_size)

    # the sorted base vectors give the final orthogonal/unitary transformation matrix that performs SBD on A
	P = V[:,sorted_basis]

	return P, BlockSizes

## uncomment below for an example use of the algorithm
#n = 10	# size of the matrices to be simultaneously block diagonalized
## A1 and A2 are random matrices that share a predefined block structure
#A1 = block_diag(np.random.rand(3,3),np.random.rand(2,2),np.random.rand(4,4),np.random.rand(1,1))
#A2 = block_diag(np.random.rand(3,3),np.random.rand(2,2),np.random.rand(4,4),np.random.rand(1,1))
## transform A1 and A2 using a random orthogonal matrix Q
#Q = ortho_group.rvs(dim=n)
#A1 = Q.T@A1@Q
#A2 = Q.T@A2@Q
#A = [A1,A2]
## use the SBD algorithm to uncover the common block structure
#sbd(A,1e-5)


from numpy import eye, float64

def laplacian(N, dtype = float64):
	"""
	Create a del2 laplacian matrix of dimension N.

	E.g. for N = 4:

	.. math::

		\begin{matrix}
		 2 & -1 &  0 &  0 \\\\
		-1 &  2 & -1 &  0 \\\\
		 0 & -1 &  2 & -1 \\\\
		 0 &  0 & -1 &  2 \\\\
		\end{matrix}

	Used for numerical differentiation.

	In many cases, :ref: scipy.ndimage.filters.laplace, which calculates the derivative of a vector,
	is faster (but might be slightly different at boundaries).

	Note that this is not the graph theory laplacian matrix.
	"""
	return 2 * eye(N, k = 0, dtype = dtype) + \
			 - eye(N, k = -1, dtype = dtype) + \
			 - eye(N, k = 1, dtype = dtype)

"""
	NOTE: if you add something, write a test!
"""


import numpy

def rcosFn(*args):
    ''' [X, Y] = rcosFn(WIDTH, POSITION, VALUES)

        Return a lookup table (suitable for use by INTERP1)
        containing a "raised cosine" soft threshold function:

        Y =  VALUES(1) + (VALUES(2)-VALUES(1)) *
             cos^2( PI/2 * (X - POSITION + WIDTH)/WIDTH )

        WIDTH is the width of the region over which the transition occurs
        (default = 1). POSITION is the location of the center of the
        threshold (default = 0).  VALUES (default = [0,1]) specifies the
        values to the left and right of the transition.  '''

    if len(args) > 0:
        width = args[0]
    else:
        width = 1

    if len(args) > 1:
        position = args[1]
    else:
        position = 0

    if len(args) > 2:
        values = args[2]
    else:
        values = (0,1)

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

    sz = 256   # arbitrary!

    X = numpy.pi * numpy.array(range(-sz-1,2)) / (2*sz)

    Y = values[0] + (values[1]-values[0]) * numpy.cos(X)**2;

    # make sure end values are repeated, for extrapolation...
    Y[0] = Y[1]
    Y[sz+2] = Y[sz+1]

    X = position + (2*width/numpy.pi) * (X + numpy.pi/4)

    return (X,Y)


import numpy as np
from scipy.signal import hamming
import numpy as np

def STFT(x, wlen, h, nfft, fs):
    ########################################################
    #              Short-Time Fourier Transform            %
    #               with MATLAB Implementation             %
    #                  For Python                          %
    # Copier: Nelson Yalta                       11/03/15  %
    ########################################################
    # function: [stft, f, t] = stft(x, wlen, h, nfft, fs)
    # x - signal in the time domain
    # wlen - length of the hamming window
    # h - hop size
    # nfft - number of FFT points
    # fs - sampling frequency, Hz
    # f - frequency vector, Hz
    # t - time vector, s
    # stft - STFT matrix (only unique points, time across columns, freq across rows)
    # represent x as column-vector if it is not

    if (len(x.shape) > 1) and (x.shape[1] > 1):
            x = x.transpose()

    # length of the signal
    xlen = x.shape[0]

    # form a periodic hamming window
    win = hamming(wlen, False)
    # form the stft matrix
    rown = int(np.ceil((1.0+nfft)/2))
    coln = int(np.fix((xlen-wlen)/h) + 1)
    short_tft = np.zeros((rown,coln)).astype('complex64')

    # initialize the indexes
    indx = 0
    col = 0

    # perform STFT
    while (indx + wlen <= xlen):
        # windowing

        xw =x[indx:indx+wlen]*win

        # FFT
        X = np.fft.fft(xw,nfft)

        # update the stft matrix
        short_tft[:,col] = X[0:rown]

        # update the indexes
        indx +=  h
        col += 1

    # calculate the time and frequency vectors

    t = np.linspace(wlen/2,wlen/2+(coln-1)*h,coln)/fs
    f = np.arange(0,rown,dtype= np.float32)*fs/nfft

    return short_tft, f, t

def single_spectrogram(inseq,fs,wlen,h,imag=False):
    """
        imag: Return Imaginary Data of the STFT on True
    """
    NFFT = int(2**(np.ceil(np.log2(wlen))))
    K = np.sum(hamming(wlen, False))/wlen
    raw_data = inseq.astype('float32')
    raw_data = raw_data/np.amax(np.absolute(raw_data))
    stft_data,_,_ = STFT(raw_data,wlen,h,NFFT,fs)
    s = np.absolute(stft_data)/wlen/K;
    if np.fmod(NFFT,2):
        s[1:,:] *=2
    else:
        s[1:-2] *=2
    real_data = np.transpose(20*np.log10(s + 10**-6)).astype(np.float32)
    if imag:
        imag_data = np.angle(stft_data).astype(np.float32)
        return real_data,imag_data
    return real_data

def multi_spectrogram(inseq,fs,wlen,h):
    """
        inseq: audio data sequence in [# Channels, # Samples]
    """
    CHANNELS=inseq.shape[0]
    for ch in range(0,CHANNELS):
        spect_data = single_spectrogram(inseq[ch,:], fs, wlen, h)
        if ch==0:
            real_data = np.zeros(( spect_data.shape[0], CHANNELS,
                spect_data.shape[1]))
        real_data[:,ch,:] = spect_data
    return real_data


from __future__ import print_function
import numpy as np
import tensorflow as tf

from edward.stats import multinomial
from scipy.special import gammaln

sess = tf.Session()

def multinomial_logpmf(x, n, p):
    """
    log pmf of multinomial. SciPy doesn't have it.

    Parameters
    ----------
    x: np.array
        vector of length K, where x[i] is the number of outcomes
        in the ith bucket
    n: int
        number of outcomes equal to sum x[i]
    p: np.array
        vector of probabilities summing to 1
    """
    return gammaln(n + 1.0) - \
           np.sum(gammaln(x + 1.0)) + \
           np.sum(x * np.log(p))

def multinomial_logpmf_vec(x, n, p):
    """Vectorized version of multinomial_logpmf."""
    if len(x.shape) == 1:
        return multinomial_logpmf(x, n, p)
    else:
        n_minibatch = x.shape[0]
        return np.array([multinomial_logpmf(x[i, :], n, p)
                         for i in range(n_minibatch)])

def _assert_eq(val_ed, val_true):
    with sess.as_default():
        # NOTE: since Tensorflow has no special functions, the values here are
        # only an approximation
        assert np.allclose(val_ed.eval(), val_true, atol=1e-4)

def _test_logpmf(x, n, p):
    xtf = tf.constant(x)
    val_true = multinomial_logpmf_vec(x, n, p)
    _assert_eq(multinomial.logpmf(xtf, n, p),
               val_true)
    _assert_eq(multinomial.logpmf(xtf, n, tf.constant(p, dtype=tf.float32)),
               val_true)
    _assert_eq(multinomial.logpmf(xtf, n, p),
               val_true)
    _assert_eq(multinomial.logpmf(xtf, n, tf.constant(p, dtype=tf.float32)),
               val_true)

def test_logpmf_int_1d():
    _test_logpmf(np.array([0, 1]), 1, np.array([0.5, 0.5]))
    _test_logpmf(np.array([1, 0]), 1, np.array([0.75, 0.25]))

def test_logpmf_float_1d():
    _test_logpmf(np.array([0.0, 1.0]), 1, np.array([0.5, 0.5]))
    _test_logpmf(np.array([1.0, 0.0]), 1, np.array([0.75, 0.25]))

def test_logpmf_int_2d():
    _test_logpmf(np.array([[0, 1],[1, 0]]), 1, np.array([0.5, 0.5]))
    _test_logpmf(np.array([[1, 0],[0, 1]]), 1, np.array([0.75, 0.25]))

def test_logpmf_float_2d():
    _test_logpmf(np.array([[0.0, 1.0],[1.0, 0.0]]), 1, np.array([0.5, 0.5]))
    _test_logpmf(np.array([[1.0, 0.0],[0.0, 1.0]]), 1, np.array([0.75, 0.25]))