#importing
import csv
import pandas as pd
import statistics
import plotly.figure_factory as ff
import plotly.graph_objects as go

dataFrames = pd.read_csv("StudentsPerformance.csv")

mathscoreList = dataFrames["math score"].to_list()
readingscoreList = dataFrames["reading score"].to_list()
writingscoreList = dataFrames["writing score"].to_list()

#Mean
mathscoreMean = statistics.mean(mathscoreList)
readingscoreMean = statistics.mean(readingscoreList)
writingscoreMean = statistics.mean(writingscoreList)

#Median
mathscoreMedian = statistics.median(mathscoreList)
readingscoreMedian = statistics.median(readingscoreList)
writingscoreMedian = statistics.median(writingscoreList)

#Mode
mathscoreMode = statistics.mode(mathscoreList)
readingscoreMode = statistics.mode(readingscoreList)
writingscoreMode = statistics.mode(writingscoreList)

#Printing Mean, Median and Mode
print("Mean, Median and Mode of Math score is {}, {} and {} respectively".format(mathscoreMean, mathscoreMedian, mathscoreMode))
print("Mean, Median and Mode of Reading score is {}, {} and {} respectively".format(readingscoreMean, readingscoreMedian, readingscoreMode))
print("Mean, Median and Mode of Writing score is {}, {} and {} respectively".format(writingscoreMean, writingscoreMedian, writingscoreMode))

#Standard Deviation
mathscorestdDeviation = statistics.stdev(mathscoreList)
readingscorestdDeviation = statistics.stdev(readingscoreList)
writingscorestdDeviation = statistics.stdev(writingscoreList)

#Printing standard deviation
print("Standard Deviation of Math score is {}".format(mathscorestdDeviation))
print("Standard Deviation of Reading score is {}".format(readingscorestdDeviation))
print("Standard Deviation of Writing score is {}".format(writingscorestdDeviation))

#1, 2 and 3 Standard Deviations for Math score
mathscore1stdDeviationStart, mathscore1stdDeviationEnd = mathscoreMean - mathscorestdDeviation, mathscoreMean + mathscorestdDeviation
mathscore2stdDeviationStart, mathscore2stdDeviationEnd = mathscoreMean - (2 * mathscorestdDeviation), mathscoreMean + (2 * mathscorestdDeviation)
mathscore3stdDeviationStart, mathscore3stdDeviationEnd = mathscoreMean - (3 * mathscorestdDeviation), mathscoreMean + (3 * mathscorestdDeviation)

#1, 2 and 3 Standard Deviations for Reading score
readingscore1stdDeviationStart, readingscore1stdDeviationEnd = readingscoreMean - readingscorestdDeviation, readingscoreMean + readingscorestdDeviation
readingscore2stdDeviationStart, readingscore2stdDeviationEnd = readingscoreMean - (2 * readingscorestdDeviation), readingscoreMean + (2 * readingscorestdDeviation)
readingscore3stdDeviationStart, readingscore3stdDeviationEnd = readingscoreMean - (3 * readingscorestdDeviation), readingscoreMean + (3 * readingscorestdDeviation)

#1, 2 and 3 Standard Deviations for Writing score
writingscore1stdDeviationStart, writingscore1stdDeviationEnd = writingscoreMean - writingscorestdDeviation, writingscoreMean + writingscorestdDeviation
writingscore2stdDeviationStart, writingscore2stdDeviationEnd = writingscoreMean - (2 * writingscorestdDeviation), writingscoreMean + (2 * writingscorestdDeviation)
writingscore3stdDeviationStart, writingscore3stdDeviationEnd = writingscoreMean - (3 * writingscorestdDeviation), writingscoreMean + (3 * writingscorestdDeviation)

#Plotting the graph for Math score
figure = ff.create_distplot([mathscoreList], ["Math Results"], show_hist = False)
figure.add_trace(go.Scatter(x = [mathscoreMean, mathscoreMean], y = [0, 0.17], mode = "lines", name = "MEAN"))

figure.add_trace(go.Scatter(x = [mathscore1stdDeviationStart, mathscore1stdDeviationStart], y = [0, 0.17], mode = "lines", name = "START OF STANDARD DEVIATION 1"))
figure.add_trace(go.Scatter(x = [mathscore1stdDeviationEnd, mathscore1stdDeviationEnd], y = [0, 0.17], mode = "lines", name = "END OF STANDARD DEVIATION 1"))

figure.add_trace(go.Scatter(x = [mathscore2stdDeviationStart, mathscore2stdDeviationStart], y = [0, 0.17], mode = "lines", name = "START OF STANDARD DEVIATION 2"))
figure.add_trace(go.Scatter(x = [mathscore2stdDeviationEnd, mathscore2stdDeviationEnd], y = [0, 0.17], mode = "lines", name = "END OF STANDARD DEVIATION 2"))

figure.add_trace(go.Scatter(x = [mathscore3stdDeviationStart, mathscore3stdDeviationStart], y = [0, 0.17], mode = "lines", name = "START OF STANDARD DEVIATION 3"))
figure.add_trace(go.Scatter(x = [mathscore3stdDeviationEnd, mathscore3stdDeviationEnd], y = [0, 0.17], mode = "lines", name = "END OF STANDARD DEVIATION 3"))

figure.show()

#Printing the findings for Math score
DataWithinMath1stdDeviation = [result for result in mathscoreList if result > mathscore1stdDeviationStart and result < mathscore1stdDeviationEnd]
DataWithinMath2stdDeviation = [result for result in mathscoreList if result > mathscore2stdDeviationStart and result < mathscore2stdDeviationEnd]
DataWithinMath3stdDeviation = [result for result in mathscoreList if result > mathscore3stdDeviationStart and result < mathscore3stdDeviationEnd]

#Printing the findings for Reading score
DataWithinReading1stdDeviation = [result for result in readingscoreList if result > readingscore1stdDeviationStart and result < readingscore1stdDeviationEnd]
DataWithinReading2stdDeviation = [result for result in readingscoreList if result > readingscore2stdDeviationStart and result < readingscore2stdDeviationEnd]
DataWithinReading3stdDeviation= [result for result in readingscoreList if result > readingscore3stdDeviationStart and result < readingscore3stdDeviationEnd]

#Printing the findings for Writing score
DataWithinWriting1stdDeviation = [result for result in writingscoreList if result > writingscore1stdDeviationStart and result < writingscore1stdDeviationEnd]
DataWithinWriting2stdDeviation = [result for result in writingscoreList if result > writingscore2stdDeviationStart and result < writingscore2stdDeviationEnd]
DataWithinWriting3stdDeviation = [result for result in writingscoreList if result > writingscore3stdDeviationStart and result < writingscore3stdDeviationEnd]

#Math score
print("{} values of data lies within 1 standard Deviation(Math score)".format(len(DataWithinMath1stdDeviation)))
print("{}% of data lies within 1 standard Deviation(Math score)".format(len(DataWithinMath1stdDeviation)*100/len(mathscoreList)))

print("{} values of data lies within 2 standard Deviation(Math score)".format(len(DataWithinMath2stdDeviation)))
print("{}% of data lies within 2 standard Deviation(Math score)".format(len(DataWithinMath2stdDeviation)*100/len(mathscoreList)))

print("{} values of data lies within 3 standard Deviation(Math score)".format(len(DataWithinMath3stdDeviation)))
print("{}% of data lies within 3 standard Deviation(Math score)".format(len(DataWithinMath3stdDeviation)*100/len(mathscoreList)))

#Reading Score
print("{} values of data lies within 1 standard Deviation(Reading score)".format(len(DataWithinReading1stdDeviation)))
print("{}% of data lies within 1 standard Deviation(Reading score)".format(len(DataWithinReading1stdDeviation)*100/len(readingscoreList)))

print("{} values of data lies within 2 standard Deviation(Reading score)".format(len(DataWithinReading2stdDeviation)))
print("{}% of data lies within 2 standard Deviation(Reading score)".format(len(DataWithinReading2stdDeviation)*100/len(readingscoreList)))

print("{} values of data lies within 3 standard Deviation(Reading score)".format(len(DataWithinReading3stdDeviation)))
print("{}% of data lies within 3 standard Deviation(Reading score)".format(len(DataWithinReading3stdDeviation)*100/len(readingscoreList)))

#Writing Score
print("{} values of data lies within 1 standard Deviation(Writing score)".format(len(DataWithinWriting1stdDeviation)))
print("{}% of data lies within 1 standard Deviation(Writing score)".format(len(DataWithinWriting1stdDeviation)*100/len(writingscoreList)))

print("{} values of data lies within 2 standard Deviation(Writing score)".format(len(DataWithinWriting2stdDeviation)))
print("{}% of data lies within 2 standard Deviation(Writing score)".format(len(DataWithinWriting2stdDeviation)*100/len(writingscoreList)))

print("{} values of data lies within 3 standard Deviation(Writing score)".format(len(DataWithinWriting3stdDeviation)))
print("{}% of data lies within 3 standard Deviation(Writing score)".format(len(DataWithinWriting3stdDeviation)*100/len(writingscoreList)))


"""quantize bert model"""
import sys
import os
os.environ['CURL_CA_BUNDLE'] = ''
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
import onnx
import numpy as np
from onnx_bridge import OnnxBridge
from quantize import get_quantized_model
from dataset import prepare_dataset_text

def measure_cos_err(lhs, rhs):
    """measure cos error"""
    assert lhs.shape == rhs.shape, 'shapes are  not the same!'
    return lhs / np.linalg.norm(lhs) @ rhs / np.linalg.norm(rhs)

def bert_compare_function(orig_output, quant_output, inputs):
    """compare function for bert"""
    size = np.sum(inputs[1])
    return measure_cos_err(orig_output[0].flatten()[:size], quant_output[0].flatten()[:size])

def main():
    """ main """
    base_onnx = sys.argv[1]
    new_model_path = os.path.join(sys.argv[2])
    distortion = float(sys.argv[3])
    dataset_path = sys.argv[4]
    model = OnnxBridge(base_onnx)
    dims = model.get_inputs()
    size_input = dims[1][1]
    dataset_calibration = prepare_dataset_text(dataset_path, size_input)

    quant_model = get_quantized_model(
        base_onnx,
        dataset_calibration,
        distortion=distortion,
        compare_function=bert_compare_function)
    onnx.save(quant_model.m, new_model_path)

main()


from typing import (
    List,
)
from lintcode import (
    Interval,
)

"""
Definition of Interval:
class Interval(object):
    def __init__(self, start, end):
        self.start = start
        self.end = end
"""

class Solution:
    """
    @param intervals: an array of meeting time intervals
    @return: the minimum number of conference rooms required
    """
    def min_meeting_rooms(self, intervals: List[Interval]) -> int:
        # Write your code here
        start = sorted([i.start for i in intervals])
        end = sorted([i.end for i in intervals])

        #count of ongoing meetings and max will be stored in res
        res,ongoing =0,0

        #two pointers which points to start of both start and end lists
        s,e =0,0

        while s<len(intervals):
            if start[s] < end[e]:
                ongoing+=1
                s+=1
            else:
                ongoing -=1
                e+=1
            res = max(res,ongoing)
        return res


# ENTRADA DE DATOS: la mayoría del código que escribas tiene como fin solucionar un problema del usuario (publicar un muro, realizar un examen en línea, subir una imágen, solicitar un taxi, crear un evento, etc). En Python se utiliza la función input() para detener la ejecución del programa hasat que el usuario agregue información.
nombre = input('Cuál es tu nombre: \r\n ')
print(f'Hola {nombre}')

# Leer datos que serán numeros
edad = int(input('Cuál es tu edad? '))  #convertir la string a número

if edad >= 18:
    print('Puedes votar')
else:
    print('Aun no puedes votar')

# Mezclar con operadores
numero = int(input('Agrega un número y te diré si es par o impar: \r\n'))
if numero % 2 == 0:
    print('Es un número par')
else:
    print('Es un número impar')

# DESAFIO: realizar un exámen con 3 preguntas que tu desees, el usuario deberá responder "SI" o "NO" y al final otorgarle una calificación (la calificación se logra con una variable que inicia en 0 y por cada respuesta correcta incrementa en 1)

respuesta1 = (input('Debés responder con SI o NO: París está en Francia? \r\n')).upper()
respuesta2 = (input('Debés responder con SI o NO: Se habla francés como idioma oficial en otro país además de Francia? \r\n')).upper()
respuesta3 = (input('Debés responder con SI o NO: Limita Francia con Alemania? \r\n')).upper()

nota = 0

if respuesta1 == 'SI':
        nota+=1

if respuesta2 == 'SI':
        nota+=1

if respuesta3 == 'NO':
        nota+=1

print(f'Tu nota es un : {nota}')


import numpy as np
import pandas as pd
from fractions import Fraction
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
from simulation.sources import Source

def latex(fraction: Fraction) -> str:
    """
    Convert a fraction.Fraction, in multiples of pi, to a nice
    latex representation
    """
    fraction = str(fraction)
    if '/' in fraction:
        l = fraction.split('/')
        l[0] = l[0].replace('1', '')
        if '-' in l[0]:
            fraction = '-\\' + 'frac{' + l[0][1:] + '\pi}{' + l[1] + '}'
        else:
            fraction = '\\' + 'frac{' + l[0] + '\pi}{' + l[1] + '}'
    elif fraction == '1':
        fraction = '\pi'
    elif fraction == '-1':
        fraction = '-\pi'
    elif fraction == '0':
        pass
    else:
        fraction += '\pi'
    return '${}$'.format(fraction)

def get_pi_ticks(between=(-np.pi, np.pi), step=np.pi / 4):
    """
    Get the positions and labels (string, latexed) for an axis
    in multiples of pi
    """
    start, stop = between
    ticks = np.array(list(np.arange(start, stop, step)) + [stop])
    labels = [latex(Fraction(number).limit_denominator()) for number in ticks / np.pi]
    return ticks, labels

def add_pi_ticks(ax, between=(-np.pi, np.pi), step=np.pi / 4, axis='x'):
    ticks, labels = get_pi_ticks(between=between, step=step)
    if axis == 'x':
        ax.set_xticks(ticks)
        ax.set_xticklabels(labels)
    elif axis == 'y':
        ax.set_yticks(ticks)
        ax.set_yticklabels(labels)
    elif axis == 'both':
        ax.set_xticks(ticks)
        ax.set_xticklabels(labels)
        ax.set_yticks(ticks)
        ax.set_yticklabels(labels)

def plot_wpb_dist(params: np.array,
                  title: str=None,
                  add_kde: bool=False,
                  y_max: float=None,
                  save_as: str=None,
                  ax=None,
                  legend=True):

    cols = {'w': '#1f77b4', 'p': '#ff7f0e', 'b': '#2ca02c'}

    if ax is None:
        fig, ax = plt.subplots()

    stds = np.std(params, axis=0)
    means = np.mean(params, axis=0)

    for i, typ in enumerate(['w', 'p', 'b']):
        ax.hist(params[:, i],
                 label='${}$ = {:.2f} $\pm$ {:.2f}'.format(typ, means[i], stds[i]),
                 bins=100,
                 alpha=0.6,
                 density=True,
                 color=cols[typ])

    if add_kde:
        y_w = gaussian_kde(params[:, 0])
        y_p = gaussian_kde(params[:, 1])
        y_b = gaussian_kde(params[:, 2])
        x = np.linspace(0, 1, 250)
        ax.plot(x, y_w, color=cols['w'])
        ax.plot(x, y_p, color=cols['p'])
        ax.plot(x, y_b, color=cols['b'])

    if legend:
        plt.legend()

    plt.xlim(0, 1)

    if y_max is not None:
        plt.ylim(0, 40)

    plt.title(title)

    if save_as is not None:
        if '.' in save_as:
            plt.savefig(save_as[:save_as.index('.')] + '.pdf')
        else:
            plt.savefig(save_as + '.pdf')

    plt.show()

def plot_paths(paths: pd.DataFrame, source: Source, ax=None):

    max_x, min_x = paths['x'].max(), paths['x'].min()
    max_y, min_y = paths['y'].max(), paths['y'].min()
    x_diff = max_x - min_x
    y_diff = max_y - min_y

    max_x += 0.05 * x_diff
    min_x -= 0.05 * x_diff
    max_y += 0.05 * y_diff
    min_y -= 0.05 * y_diff

    step = (max_x - min_x) / 500

    x_space = np.arange(min_x, max_x, step)
    y_space = np.arange(min_y, max_y, step)
    X, Y = np.meshgrid(x_space, y_space)

    Rs = (X - source.position[0]) ** 2 + (Y - source.position[1]) ** 2
    Z = np.exp(- Rs)

    if ax is None:
        fig, ax = plt.subplots()

    ax.imshow(Z, extent=[min_x, max_x, min_y, max_y], origin='lower')
    ax.set_aspect('equal')

    for id, path in paths.groupby('trackID'):
        ax.plot(path['x'], path['y'], linewidth=0.5)

    if ax is None:
        plt.show()

def plot_AD_param_dist(dist: np.ndarray, priors: list=None):
    """
    Plot the output distibution of the attractant dynamics parameters

    Parameters
    ----------
    dist        The output MCMC trails (from AttractantInferer().infer())
    priors      A list of the prior distributions (from AttractantInferer().priors)

    """

    fig, axes = plt.subplots(nrows=1, ncols=7, figsize=(12, 5), sharex='col')
    cols = plt.rcParams['axes.prop_cycle'].by_key()['color']

    names = ['$q$ [mol min$^{-1}$]', '$D$ [$\mu m^{2}$ min$^{-1}$]', 'τ [min]', '$R_0$ [mol $\mu m^{-2}$]',
             '$\kappa_d$ [mol $\mu m^{-2}$]', '$m$ [$\mu m^{2}$ mol$^{-1}$]', '$b_0$ [unitless]']

    for j in range(7):
        axes[j].set_title(names[j])
        axes[j].set_yticks([])
        axes[j].hist(dist[:, j], bins=50, color=cols[j], alpha=0.6, density=True)
        if priors is not None:
            priors[j].plot(ax=axes[j], color=cols[j])

    plt.tight_layout()
    plt.show()


class Solution:
    """link to the problem: https://leetcode.com/problems/binary-search/"""
    @staticmethod
    def v1_search(nums: list[int], target: int) -> int:
        """
        Time complexity: O(logN) 230ms beats 51.43%
        Space complexity: 0(1) 17.72mb beats 92.00%
        """
        left, right = 0, len(nums) - 1

        while left <= right:
            mid = left + (right - left) // 2

            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1
            else:
                return mid
        return -1


import numpy as np
from numpy.fft import fft2, ifft2, ifftshift
from scipy.signal import convolve2d
import matplotlib.pyplot as plt
from PIL import Image

def pad(h, shape_x):
	shape_h = np.shape(h)
	offset = 1
	hpad = np.zeros(shape_x, dtype=np.float32)
	i1, j1 = np.int32((shape_x[0] - shape_h[0])/2)+offset, np.int32((shape_x[1] - shape_h[1])/2)+offset
	i2, j2 = i1 + shape_h[0], j1 + shape_h[1]
	hpad[i1:i2, j1:j2] = h
	return hpad

def shrinkage(z, beta):
	c1, c2 = z -beta,  z + beta
	z_out = np.clip(c1,0,np.inf) + np.clip(z+beta,-np.inf,0)
	return z_out

# def crop(img, M, N):
# 	# M < N
# 	i1, i2 = np.int32(0.5*(N-M)), np.int32(0.5*(M+N))
# 	return img[i1:i2, i1:i2]

def crop(h, shape_crop):
	shape_h = np.shape(h)
	i1, j1 = np.int32((shape_h[0] - shape_crop[0])/2), np.int32((shape_h[1] - shape_crop[1])/2)
	i2, j2 = np.int32((shape_h[0] + shape_crop[0])/2), np.int32((shape_h[1] + shape_crop[1])/2)
	return h[i1:i2, j1:j2]

def gauss_kernel(size, sigma):
	ax = np.linspace(-(size-1)*0.5, size*0.5, size)
	xx, yy = np.meshgrid(ax, ax)

	kernel = np.exp( -(xx**2 + yy**2)/(2*(sigma**2)) )
	kernel = kernel/np.sum(kernel.ravel())
	return kernel

def disk(size, r):
	ax = np.linspace(-(size-1)*0.5, size*0.5)
	xx, yy = np.meshgrid(ax, ax)

	kernel = np.asarray((xx**2 + yy**2) < r**2, dtype=np.float32)
	kernel = kernel/np.sum(kernel.ravel())
	return kernel

def D(U):
	Dux1 = np.diff(U,n = 1,axis =1)
	Dux = np.zeros(np.shape(U))
	Dux[:,0:-1] = Dux1.copy()
	Dux[:,-1] = U[:,0] - U[:,-1]

	Duy1 = np.diff(U, n=1, axis=0)
	Duy = np.zeros(np.shape(U))
	Duy[0:-1,:] = Duy1.copy()
	Duy[-1,:] = U[0,:] - U[-1,:]

	return Dux, Duy

def Mask(Dx, Dy, tau_s =0.1, tau_r =0.1):
	g = (1/25)*np.ones([5,5], dtype=np.float32)

	Dxy = np.sqrt(Dx**2 + Dy**2)
	a, b = convolve2d(Dx,g,mode='same'), convolve2d(Dy,g,mode='same')
	c = convolve2d(Dxy,g,mode='same')
	R = np.sqrt(a**2 + b**2)/(c +0.5)
	M = np.max(R-tau_r, 0)
	Dx1, Dy1 = Dx*np.max(M*Dxy-tau_s,0), Dy*np.max(M*Dxy-tau_s,0)
	return  Dx1, Dy1, M

def k_ifft(x_rec, y, lambda_l2, lambda_l1, M=25):
	# M = kernel size
	# Solves ||Delta(x)*k - Delta(y)||^2 + \lambda_s*||k||^2
	# Then passes through a TV denoiser
	N = np.shape(x_rec)[0]
	Dx_1, Dx_2 = D(x_rec)
	Dx_1, Dx_2, _ = Mask(Dx_1, Dx_2)
	Dy_1, Dy_2 = D(y)
	Dy_1, Dy_2, _ = Mask(Dy_1, Dy_2)

	num = np.conj(fft2(Dx_1))*fft2(Dy_1) + np.conj(fft2(Dx_2))*fft2(Dy_2)
	den = np.abs(fft2(Dx_1))**2 + np.abs(fft2(Dx_2))**2 + lambda_l2
	k0 = np.real(ifftshift(ifft2(num/den)))
	k0 = np.clip(crop(k0,M,N),0,np.inf)
	k0 = k0/np.sum(np.ravel(k0))

	return k0

def rgb_to_bayer(x):
	H, W, _ = np.shape(x)
	x_bayer = np.zeros([2*H, 2*W])
	x_r, x_g, x_b =  x[:,:,0], x[:,:,1], x[:,:,2]

	x_bayer[0::2,0::2] = x_r
	x_bayer[0::2,1::2] = x_g
	x_bayer[1::2,0::2] = x_g
	x_bayer[1::2,1::2] = x_b

	return x_bayer

def rggb_to_rgb(x_list, switch_rgb):
	H, W = np.shape(x_list[0])
	x_rgb = np.zeros([H, W, 3])

	x_rgb[:,:,0] = x_list[0]
	x_rgb[:,:,1] = (x_list[1]+x_list[2])*0.5
	x_rgb[:,:,2] = x_list[3]

	if switch_rgb:
		x_rgb = np.flip(x_rgb,2)
	return x_rgb

def psf2otf(kernel, size):
	psf = np.zeros(size,dtype=np.float32)
	centre =  np.shape(kernel)[0]//2 + 1

	psf[:centre, :centre] = kernel[(centre-1):,(centre-1):]
	psf[:centre, -(centre-1):] = kernel[(centre-1):, :(centre-1)]
	psf[-(centre-1):, :centre] = kernel[:(centre-1), (centre-1):]
	psf[-(centre-1):, -(centre-1):] = kernel[:(centre-1),:(centre-1)]

	otf = fft2(psf, size)
	return psf, otf


import numpy as np
import matplotlib.pyplot as plt
import os
class Plots(object):
    def __init__(self, masses, time, polynomial, correctedtime, fracinterp,  massfrac, c, egy, IMF):
        """
        This module contains all of the plotting functions
        """
        self.masses = masses
        self.time = time
        self.logmasses = np.log(masses)
        self.logtime = np.log(time)
        self.tnew = np.linspace(np.log(self.time[0]),np.log(self.time[-1]),1000)
        self.polynomial = polynomial
        self.deriv = polynomial.deriv()
        self.correctedtime = correctedtime
        self.fracinterp = fracinterp
        self.massfrac = massfrac
        self.c = c
        self.egy = egy
        self.xinterp = np.linspace(self.correctedtime[0], self.correctedtime[-1], 10000)
        self.IMF = IMF

    # For plotting mass vs time (raw data)
    def masstimeplot(self):
        """
        Plots the raw mass v time data
        """
        fig = plt.figure(1)
        ax = fig.add_subplot(1,2,1)
        ax.plot(self.masses, (self.time))
        ax.set_xlabel(r'$M/\mathrm{M}_\odot$')
        ax.set_ylabel(r'Time to Supernova (s)')
        ax.set_title(r'Time to supernova for early stars of varying mass')

        ax2 = fig.add_subplot(1,2,2)
        ax2.plot(np.log(self.masses), np.log(self.time))
        ax2.set_xlabel(r'$M/\mathrm{M}_\odot$')
        ax2.set_ylabel(r'Time to Supernova (s)')
        ax2.set_title(r'Log Log plot')
        fig.tight_layout()
        plt.show()
        fig.savefig(os.path.expanduser('~/python/project/outputfiles/masstimeplot.pdf'), bbox_inches = 'tight')

###########################################################################

    # Plotting the interpolation functions
    def interpolationfunctionplot(self):
        """
        Plots the interpolated mass v time function
        """
        fig = plt.figure(1)

        ax = fig.add_subplot(1,2,1)
        ax.plot(self.time,self.masses, 'o',  np.exp(self.tnew), np.exp(self.polynomial(self.tnew)), '-')
        ax.set_ylabel(r'$M/\mathrm{M}_\odot$')
        ax.set_xlabel(r'Time to Supernova (s)')
        ax.set_title(r'Interpolated function')

        ax2 = fig.add_subplot(1,2,2)
        ax2.plot(self.logtime,self.logmasses, 'o', self.tnew, self.polynomial(self.tnew), '-')
        ax2.set_ylabel(r'ln $M/\mathrm{M}_\odot$')
        ax2.set_xlabel(r'ln Time to Supernova (s)')
        ax2.set_title(r'Interpolated function (log)')

        y = np.exp(self.tnew) #regular data
        x = np.exp(self.polynomial(self.tnew))

        dx = x[1:] - x[:-1]
        dy = y[1:] - y[:-1]
        ax = 0.5*(x[1:] + x[:-1]) #average
        ay = 0.5*(y[1:] + y[:-1])
        n = dy*ax/(dx*ay)  #y=x**n, n is local gradient dt/dm

        fig = plt.figure(2)

        a1 = fig.add_subplot(1,1,1)
        a1.plot(ax,n, '-')
        a1.set_title('Evolution of n with increasing mass')
        a1.set_xlabel('$M/\mathrm{M}_\odot$')
        a1.set_ylabel('n')
        fig.tight_layout()
        plt.show()
        fig.savefig(os.path.expanduser('~/python/project/outputfiles/interpfunc.pdf'), bbox_inches = 'tight')
############################################################################

    # this plots the interpolated function with the correct mass and times
    def correctedtimeplot(self):
        """
        Plots mass v the adjusted time fixed by the root finding fixtime function
        """
        fig = plt.figure(1)

        ax = fig.add_subplot(1,1,1)
        ax.plot(self.correctedtime,self.masses, 'o',  np.exp(self.tnew), np.exp(self.polynomial(self.tnew)), '-') # plots original data with interpolation function data once its been raised to exponential to return it to original form
        ax.set_ylabel('$M/\mathrm{M}_\odot$')
        ax.set_xlabel('Time to Supernova (s)')
        ax.set_title('Interpolated function and corrected times')
        fig.tight_layout()
        plt.show()
        fig.savefig(os.path.expanduser('~/python/project/outputfiles/correctedtime.pdf'), bbox_inches = 'tight')
#############################################################################
    # plot of the mass fractions over time
    def massfracplot(self):
        """
        Plots the mass fractions (ejecta mass over initial mass) of each star
        """
        fig = plt.figure()
        ax = fig.add_subplot(1,1,1)
        ax.plot(self.correctedtime, self.massfrac, 'o', self.xinterp, self.fracinterp(self.xinterp), '-')
        ax.set_ylabel('Mass ejection Fraction')
        ax.set_xlabel('Time to Supernova (s)')
        ax.set_title('Mass ejection fraction for corrected times')
        fig.tight_layout()
        plt.show()
        fig.savefig(os.path.expanduser('~/python/project/outputfiles/massfrac.pdf'), bbox_inches='tight')

######################################################

    # this plots the big function we are integrating to obtain yield solutions
    def functiontointegrateplot(self):
        """
        Plots the main mass function which is integrated to obtain ejecta
        """
        m = lambda t: np.exp(self.polynomial(np.log(t)))
        g = lambda t: self.IMF(m(t))*self.c*self.deriv(np.log(t))*self.fracinterp(t)/t*m(t)
        fig = plt.figure()
        ax = fig.add_subplot(1,1,1)
        ax.plot(self.correctedtime, g(self.correctedtime), '-')
        ax.set_xlabel('Time (s)')
        ax.set_ylabel('Mass ejection')
        ax.set_title('Plot of mass ejection to be integrated')
        fig.tight_layout()
        plt.show()
        fig.savefig(os.path.expanduser('~/python/project/outputfiles/integrationfunction.pdf'), bbox_inches = 'tight')

#######################################################
    # plots the explosion energy as a function of mass
    def egymassplot(self):
        """
        Plots the supernova explosion energy as calculated by Heger and Mueller
        """
        fig = plt.figure()
        ax = fig.add_subplot(1,1,1)
        ax.plot(self.masses, self.egy, '.')
        ax.set_xlabel('Initial Mass (Solar Masses)')
        ax.set_ylabel('Explosion Energy (B)')
        ax.set_title('Supernova Explosion energy')
        fig.tight_layout()
        plt.show()
        fig.savefig(os.path.expanduser('~/python/project/outputfiles/explosionenergy.pdf'), bbox_inches = 'tight')


from __future__ import absolute_import

from orchestrator.plugins.common.factory.maja_l1_image_reader_provider import L1ImageReaderProvider
from orchestrator.common.logger.maja_logging import configure_logger
from orchestrator.plugins.common.factory.plugin_activate import register_all

from orchestrator.launcher.app_handler import AppHandler
import orchestrator.plugins.common.factory.product_utils as product_utils
import orchestrator.common.constants as constants
from orchestrator.cots.otb.otb_file_utils import otb_copy_image_to_file
from orchestrator.cots.otb.otb_app_handler import OtbAppHandler
import orchestrator.common.file_utils as file_utils
from orchestrator.common.dem.dem_base import DEMBase
from orchestrator.common.directory_manager import DirectoryManager
from orchestrator.common.earth_explorer.gipp_l2_comm_earth_explorer_xml_file_handler import \
    GippL2COMMEarthExplorerXMLFileHandler
import orchestrator.common.gipp_utils as gipp_utils
import argparse, sys, os
LOGGER = configure_logger(__name__)

argParser = argparse.ArgumentParser()
required_arguments = argParser.add_argument_group('required arguments')
required_arguments.add_argument('-i', '--input_dir', required=True,
                                    help='Path to input folder')
required_arguments.add_argument('-o', '--output_dir', required=True,
                                    help='Path to output directory')
required_arguments.add_argument('-t', '--tile_id', required=False,
                                    help='Tile id of the L1 product')
args = argParser.parse_args(sys.argv[1:])

register_all()
app_handler = AppHandler()
app_handler._workingDirectory = args.output_dir
app_handler._directory_manager = DirectoryManager(working_dir=args.output_dir)
OtbAppHandler.set_ram_to_use(8048)

# Get the thread value
os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = str(app_handler.get_nb_threads())

l1product = product_utils.get_input_l1_image_product(args.input_dir, args.tile_id)
LOGGER.debug(l1product.Satellite)

# Read and load L2COM
gip_l2comm_filename = gipp_utils.get_gipp_filename_with_mission(args.input_dir, "GIP_L2COMM", l1product.Satellite)
LOGGER.debug("L2COMM filename : " + gip_l2comm_filename)
l_gippl2commhandler = GippL2COMMEarthExplorerXMLFileHandler(gip_l2comm_filename)

# Read and initialize DEM
dem_filename = gipp_utils.get_gipp_filename_with_mission(args.input_dir, "AUX_REFDE2", l1product.UniqueSatellite)
LOGGER.debug("DEM filename : " + dem_filename)
dem = DEMBase()
dem_working = app_handler.get_directory_manager().get_temporary_directory("DTMRead_",do_always_remove=False)
dem.initialize(dem_filename, dem_working, True)

# Read L1 product
l1_reader = L1ImageReaderProvider.create(l1product.PluginName, l1product, app_handler, l_gippl2commhandler, dem,
                             constants.ReadL1Mode.READ_L1_MODE_FOR_ALGORITHMS)

LOGGER.info(app_handler.get_system_infos())
print(app_handler.get_working_directory())

LOGGER.info("L1 Reader Done ...")
#Copy files to the output directory
if l1_reader.has_value("IPEDGSubOutput") and l1_reader.get_value("IPEDGSubOutput"):
    otb_copy_image_to_file(l1_reader.get_value("IPEDGSubOutput"),os.path.join(args.output_dir, "IPEDGSubOutput.tif"))

if l1_reader.has_value("SOL1Image") and l1_reader.get_value("SOL1Image"):
    otb_copy_image_to_file(l1_reader.get_value("SOL1Image"), os.path.join(args.output_dir,"SOL1Image.tif"))

if l1_reader.has_value("SOL2Image") and l1_reader.get_value("SOL2Image"):
    otb_copy_image_to_file(l1_reader.get_value("SOL2Image"), os.path.join(args.output_dir,"SOL2Image.tif"))

if l1_reader.has_value("DTMVIEImage") and l1_reader.get_value("DTMVIEImage"):
    otb_copy_image_to_file(l1_reader.get_value("DTMVIEImage"), os.path.join(args.output_dir,"DTMVieImage.tif"))

if l1_reader.has_value("IPTOASubOutput") and l1_reader.get_value("IPTOASubOutput"):
    otb_copy_image_to_file(l1_reader.get_value("IPTOASubOutput"), os.path.join(args.output_dir,"IPTOASubOutput.tif"))

if l1_reader.has_value("IPSATSubOutput") and l1_reader.get_value("IPSATSubOutput"):
    otb_copy_image_to_file(l1_reader.get_value("IPSATSubOutput"), os.path.join(args.output_dir,"IPSATSubOutput.tif"))

if l1_reader.has_value("L1TOACirrusImage") and l1_reader.get_value("L1TOACirrusImage"):
    otb_copy_image_to_file(l1_reader.get_value("L1TOACirrusImage"), os.path.join(args.output_dir, "L1TOACirrusImage.tif"))

if l1_reader.has_value("CLAImage") and l1_reader.get_value("CLAImage"):
    otb_copy_image_to_file(l1_reader.get_value("CLAImage"), os.path.join(args.output_dir,"CLAImage.tif"))

if l1_reader.has_value("ShadowVIEImage") and l1_reader.get_value("ShadowVIEImage"):
    otb_copy_image_to_file(l1_reader.get_value("ShadowVIEImage"), os.path.join(args.output_dir,"ShadowVIEImage.tif"))

LOGGER.info("L1 PIX Begin ...")
if l1_reader.has_value("L1PIXImageList") and l1_reader.get_value("L1PIXImageList"):
    for i in range(0,len(l1_reader.get_value("L1PIXImageList"))):
        otb_copy_image_to_file(l1_reader.get_value("L1PIXImageList")[i],
                               os.path.join(args.output_dir,"L1PIXImageList_R"+str(i+1)+".tif"))

LOGGER.info("L1 PIX Done ...")

if l1_reader.has_value("L2TOAImageList") and l1_reader.get_value("L2TOAImageList"):
    for i in range(0,len(l1_reader.get_value("L2TOAImageList"))):
        otb_copy_image_to_file(l1_reader.get_value("L2TOAImageList")[i],
                               os.path.join(args.output_dir,"L2TOAImageList_R"+str(i+1)+".tif"))

if l1_reader.has_value("L2EDGOutputList") and l1_reader.get_value("L2EDGOutputList"):
    for i in range(0,len(l1_reader.get_value("L2EDGOutputList"))):
        otb_copy_image_to_file(l1_reader.get_value("L2EDGOutputList")[i],
                               os.path.join(args.output_dir,"L2EDGOutputList_R"+str(i+1)+".tif"))

if l1_reader.has_value("L2SATImageList") and l1_reader.get_value("L2SATImageList"):
    LOGGER.debug(l1_reader.get_value("L2SATImageList"))
    for i in range(0,len(l1_reader.get_value("L2SATImageList"))):
        if l1_reader.get_value("L2SATImageList")[i]:
            otb_copy_image_to_file(l1_reader.get_value("L2SATImageList")[i],
                                   os.path.join(args.output_dir,"L2SATMaskList_R"+str(i+1)+".tif"))

if l1_reader.has_value("L2PIXImageList") and l1_reader.get_value("L2PIXImageList"):
    for i in range(0,len(l1_reader.get_value("L2PIXImageList"))):
        otb_copy_image_to_file(l1_reader.get_value("L2PIXImageList")[i],
                               os.path.join(args.output_dir,"L2PIXImageList_R"+str(i+1)+".tif"))

if l1_reader.has_value("L2DFPImageList") and l1_reader.get_value("L2DFPImageList"):
    for i in range(0,len(l1_reader.get_value("L2DFPImageList"))):
        otb_copy_image_to_file(l1_reader.get_value("L2DFPImageList")[i],
                               os.path.join(args.output_dir,"L2DFPImageList_R"+str(i+1)+".tif"))

if l1_reader.has_value("L1CLDImageList") and l1_reader.get_value("L1CLDImageList"):
    for i in range(0,len(l1_reader.get_value("L1CLDImageList"))):
        otb_copy_image_to_file(l1_reader.get_value("L1CLDImageList")[i],
                               os.path.join(args.output_dir,"L1CLDImageList_R"+str(i+1)+".tif"))

if l1_reader.has_value("AngleZoneMaskList") and l1_reader.get_value("AngleZoneMaskList"):
    for i in range(0, len(l1_reader.get_value("AngleZoneMaskList"))):
        otb_copy_image_to_file(l1_reader.get_value("AngleZoneMaskList")[i],
                               os.path.join(args.output_dir,"AngleZoneMaskList_R"+str(i+1)+".tif"))

if l1_reader.has_value("L1TOAImageList") and l1_reader.get_value("L1TOAImageList"):
    for i in range(0, len(l1_reader.get_value("L1TOAImageList"))):
        LOGGER.debug("toa image list test: " + str(l1_reader.get_value("L1TOAImageList")[i]) )
        otb_copy_image_to_file(l1_reader.get_value("L1TOAImageList")[i],
                               os.path.join(args.output_dir,"L1TOAImageList_R"+str(i+1)+".tif"))
# Log system infos

#app_handler.get_directory_manager().clean(True)


from vkbottle.bot import Blueprint
from random import randint, choice

from config import http_client

bp = Blueprint("OtherCommands")
bp.labeler.vbml_ignore_case = True

@bp.on.message(text="рандом <number:int> <number_two:int>")
async def bones(_, number, number_two):

    if number > number_two:
        return "📠 Введите числа так, чтобы первое число не было больше второго."

    return f"📠 Ваше рандомное число: {randint(number, number_two):,}"

@bp.on.message(text=["время", "дата"])
async def time_get(_):

    now = await http_client.request_text("https://isdayoff.ru/now", "get")
    return f"📆 {now}"

@bp.on.message(text="монетка")
async def coin(_):

    return f"✊ Вам выпало: {choice(['решка', 'орёл'])}"

@bp.on.message(text="год <year:int>")
async def isleap(_, year: int):

    result = "високосный" if year % 4 == 0 else "не високосный"
    return f"📙 Год {year} {result}"


import os, os.path
from modules import data_quality as dq, file_check as fc

def __get_file_list() -> list:
    gen = os.walk('./unprocessed')
    return list(gen)[0][2]

def process_file(file: str):
    file_check = fc.FileCheck(filename=file)
    if file_check.is_valid():
        file_check.load_csv(location='unprocessed')
        if file_check.df_status:
            quality = dq.Quality(file_check.df)
            quality.separate_invalid_rows(invalid_folder=file_check.invalid_folder)
            quality.clean_fields()
            quality.validate_phone_number()
            quality.write_processed_csv(file_check.processed_folder, file_check.filename)
            print(f"All checks were successfully ran on file {file_check.filename}")
        else:
            print(f"File {file_check.filename} cannot be loaded into pandas DataFrame")
    else:
        if file_check.extension == 'csv':
            target = file_check.move_invalid_file()
            print(f"File has been moved to {target} as it is invalid.")

if __name__ == "__main__":
    file_list = __get_file_list()
    for file in file_list:
        process_file(file)


# -*- coding: utf-8 -*-
from django import forms

from .models import Post
from django.core.exceptions import ValidationError
import bleach
from django.conf import settings

class PostForm(forms.ModelForm):

    class Meta:
        model = Post
        fields = ('post_title', 'post_content','tags')

        exclude = ('poster',)
        error_messages = {
            'post_title': {
                'max_length': "لطفا عنوان کوتاه تری انتخاب نمایید",
                'required':"لطفا عنوان را وارد نمایید",
            },
            'tags': {
                'max_length': "لطفا تگ کوتاه تری انتخاب نمایید",
                'required': "لطفا حداقل یک تگ (برچسب) وارد نمایید",
            },
        }

    def clean_tags(self):
        data = self.cleaned_data['tags']
        #Check date is not in past.
        if data.__len__() < 1:
            raise ValidationError('لطفا حداقل یک تگ وارد کنید.')
        # if data.__len__() < 3:
        #     raise ValidationError('تگ انتخاب شده میبایست حداقل 3 حرف باشد.')
        return data

    def clean_post_title(self):
        data = self.cleaned_data['post_title']
        #Check date is not in past.
        if data.__len__() < 1:
            raise ValidationError('لطفا عنوان سئوال را وارد نمایید')
        if data.__len__() < 10:
            raise ValidationError('عنوان سئوال شما می بایست به اندازه کافی طولانی باشد')
        return data

    def clean_post_content(self):
        data = self.cleaned_data['post_content']
        # myfield = self.cleaned_data.get('myfield', '')
        cleaned_text = bleach.clean(data,
                                    settings.BLEACH_VALID_TAGS,
                                    settings.BLEACH_VALID_ATTRS,
                                    settings.BLEACH_VALID_STYLES)
        return cleaned_text #sanitize html

class RegisterNewUser(forms.Form):
    phone_number = forms.CharField(error_messages={'required': 'شماره تلفن همراه خود را وارد نمایید'}, required=False)
    authentication_code = forms.CharField(error_messages={'required': 'شماره کد ارسال شده به شماره همراه شما را وارد نمایید'}, required=False)
    username = forms.CharField(error_messages={'required': 'لطفا یک نام کاربری وارد نمایید'}, required=False)

    def clean_phone_number(self):
        data = self.cleaned_data['phone_number']
        if data.__len__() < 1:
            raise ValidationError('لطفا حداقل یک تگ وارد کنید.')
        # Remember to always return the cleaned data.
        return data


#https://github.com/eriklindernoren/PyTorch-GAN/blob/master/implementations/gan/gan.py

import argparse
import os
import numpy as np
import math

import torchvision.transforms as transforms
from torchvision.utils import save_image

from torch.utils.data import DataLoader

from torchvision import datasets
from torch.autograd import Variable

import torch.nn as nn
import torch.nn.functional as F
import torch

os.makedirs("images", exist_ok=True)

parser = argparse.ArgumentParser()
parser.add_argument("--n_epochs", type=int, default=200, help="number of epochs of training")
parser.add_argument("--batch_size", type=int, default=64, help="size of the batches")
parser.add_argument("--lr", type=float, default=0.0002, help="adam: learning rate") #Check Values
parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient") #Check Values
parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient") #Check Values
parser.add_argument("--n_cpu", type=int, default=8, help="number of cpu threads to use during batch generation") #Depends on Machine
parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space")
parser.add_argument("--img_size", type=int, default=128, help="size of each image dimension") #E.g. a 64x64 image would be 64 -> assumes square images
parser.add_argument("--channels", type=int, default=1, help="number of image channels")
parser.add_argument("--sample_interval", type=int, default=400, help="interval betwen image samples")
opt = parser.parse_args()
print(opt)

img_shape = (opt.channels, opt.img_size, opt.img_size)

cuda = True if torch.cuda.is_available() else False

#DataLoader helper
from torch.utils.data import Dataset
from PIL import Image
class ElbowFacesDataset(Dataset):
    """Human Faces dataset."""

    def __init__(self, npz_imgs):
        """
        Args:
            npz_imgs (string): npz file with all the images (created in gan.ipynb)
        """
        self.imgs = npz_imgs

    def __len__(self):
        return len(self.imgs)

    def __getitem__(self, idx):
        if torch.is_tensor(idx):
            idx = idx.tolist()
        image = self.imgs[idx]
        return image

# Preparing dataloader for training

def prepData():
    dir_data  = "ImagesforResearch/Elbow"

    img_dim = opt.img_size
    # setting image shape to 64x64
    img_shape = (img_dim,img_dim, 3)

    # listing out all file names
    nm_imgs   = np.sort(os.listdir(dir_data))
    print(nm_imgs)

    X_train = []
    for file in nm_imgs:
        try:
            img = Image.open(dir_data+'/'+file)
            img = img.resize((img_dim,img_dim))
            img = np.asarray(img)/255
            X_train.append(img)
        except:
            print("something went wrong")

    X_train = np.array(X_train)
    transpose_imgs = np.transpose( # imp step to convert image size from (7312, 32,32,3) to (7312, 3,32,32)
    np.float32(X_train), # imp step to convert double -> float (by default numpy input uses double as data type)
    (0, 3,1,2) # tuple to describe how to rearrange the dimensions
    )
    return transpose_imgs

class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()

        def block(in_feat, out_feat, normalize=True):
            layers = [nn.Linear(in_feat, out_feat)]
            if normalize:
                layers.append(nn.BatchNorm1d(out_feat, 0.8))
            layers.append(nn.LeakyReLU(0.2, inplace=True))
            return layers

        self.model = nn.Sequential(
            *block(opt.latent_dim, 128, normalize=False),
            *block(128, 256),
            *block(256, 512),
            *block(512, 1024),
            nn.Linear(1024, int(np.prod(img_shape))),
            nn.Tanh()
        )

    def forward(self, z):
        img = self.model(z)
        img = img.view(img.size(0), *img_shape)
        return img

class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(int(np.prod(img_shape)), 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(256, 1),
            nn.Sigmoid(), #outputs final probability as a sigmoid activation function
        )

    def forward(self, img):
        img_flat = img.view(img.size(0), -1)
        validity = self.model(img_flat)

        return validity

# Loss function
adversarial_loss = torch.nn.BCELoss() #uses Binary Cross Entropy Closs (could use BCEwithLogits loss) which combines softmax and BCE

# Initialize generator and discriminator
generator = Generator()
discriminator = Discriminator()

if cuda:
    generator.cuda()
    discriminator.cuda()
    adversarial_loss.cuda()

# Configure data loader
#Replace with our dataset
os.makedirs("../../data/mnist", exist_ok=True)
dataloader = torch.utils.data.DataLoader(dataset = ElbowFacesDataset(prepData()),
    batch_size=opt.batch_size,
    shuffle=True,
)

# Optimizers
optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))

Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor

# ----------
#  Training
# ----------

dataloader = next(iter(dataloader)) #Added

for epoch in range(opt.n_epochs):
    for i, imgs in enumerate(dataloader):

        # Adversarial ground truths
        valid = Variable(Tensor(imgs.size(0), 1).fill_(1.0), requires_grad=False)
        fake = Variable(Tensor(imgs.size(0), 1).fill_(0.0), requires_grad=False)

        # Configure input
        real_imgs = Variable(imgs.type(Tensor))

        # -----------------
        #  Train Generator
        # -----------------

        optimizer_G.zero_grad()

        # Sample noise (from a normal dist) as generator input
        z = Variable(Tensor(np.random.normal(0, 1, (imgs.shape[0], opt.latent_dim))))

        # Generate a batch of images
        gen_imgs = generator(z)

        # Loss measures generator's ability to fool the discriminator
        g_loss = adversarial_loss(discriminator(gen_imgs), valid)

        g_loss.backward()
        optimizer_G.step()

        # ---------------------
        #  Train Discriminator
        # ---------------------

        optimizer_D.zero_grad()

        # Measure discriminator's ability to classify real from generated samples
        real_loss = adversarial_loss(discriminator(real_imgs), valid)
        fake_loss = adversarial_loss(discriminator(gen_imgs.detach()), fake)
        d_loss = (real_loss + fake_loss) / 2

        d_loss.backward()
        optimizer_D.step()

        print(
            "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]"
            % (epoch, opt.n_epochs, i, len(dataloader), d_loss.item(), g_loss.item())
        )

        batches_done = epoch * len(dataloader) + i
        if batches_done % opt.sample_interval == 0:
            save_image(gen_imgs.data[:25], "images/%d.png" % batches_done, nrow=5, normalize=True)


import sys

def sum_recursive(x):
    if x == 0:
        return 0
    else:
        return sum_recursive(x - 1) + x

def sum_iterative(x):
    numSum = 0
    for i in range(x):
        numSum += i + 1
    return numSum

y = sum_iterative(int(sys.argv[1]))
z = sum_recursive(int(sys.argv[1]))
print("The SUM value calculated by recursive is ", end="")
print(str(z), end="")
print(" and by iterative is ", end="")
print(str(y), end="")
print(".")

#print("The SUM value calculated by recursive is " + str(z) + " and by iterative is " + str(y) + ".")


import numpy as np
import pandas as pd
import rasterio
import rasterio.mask
import fiona
from sklearn.metrics import balanced_accuracy_score
from sklearn.metrics import f1_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
import time

### Get dataframe for HDI

hdi_path = 'data/shdi/SHDI Complete 4.0 (1).csv'
df = pd.read_csv(hdi_path, usecols=['iso_code', 'year', 'level', 'GDLCODE', 'shdi'], low_memory=False)
# get HDI for Nigeria at subnational level for year 2018
df = df.loc[
        (df['iso_code'] == 'NGA') &
        (df['year'] == 2018) &
        (df['level'] == 'Subnat')]
df.drop(columns=['iso_code', 'year', 'level'], inplace=True)
df['shdi'] = df['shdi'].astype(float)
df.set_index('GDLCODE', inplace=True)
df_hdi = df

### Get level 1 admin units (federal states) shapefile

shapefile_path = 'data/shapefiles/GDL Shapefiles V4.shp'
shapes_NGA = {}

with fiona.open(shapefile_path) as shapefile:
    for feature in shapefile:
        if feature['properties']['country'] == 'Nigeria':
            shapes_NGA[feature['properties']['GDLcode']] = feature['geometry']

### Set threshold and compute balanced accuracy for each federal state
# https://rasterio.readthedocs.io/en/latest/topics/masking-by-shapefile.html
# https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html

dfs = {}

thresholds = np.arange(9)
gdl_codes = df_hdi.index.to_numpy()
print(gdl_codes)

for threshold in thresholds:
    bal_accuracy = {}
    f1 = {}
    precision = {}
    recall = {}

    start_time = time.time()
    for region, shape in shapes_NGA.items():

        # get truth
        with rasterio.open('data/grid3/NGA - population - v1.2 - mastergrid.tif') as dataset:
            truth = rasterio.mask.mask(dataset, [shape], all_touched=False, nodata=255)[0]
            truth = truth.flatten()
            truth = truth[truth != 255]

        # get prediction
        with rasterio.open('data/metrics/pipeline-counts.tif') as dataset:
            counts = rasterio.mask.mask(dataset, [shape], all_touched=False, nodata=255)[0]
            counts = counts.flatten()
            counts = counts[counts != 255]
            prediction = np.zeros(counts.size, dtype=np.uint8)
            prediction[counts > threshold] = 1

        bal_accuracy[region] = balanced_accuracy_score(truth, prediction)
        f1[region] = f1_score(truth, prediction)
        precision[region] = precision_score(truth, prediction)
        recall[region] = recall_score(truth, prediction)

    # make dataframe
    df_score = pd.DataFrame(index=bal_accuracy.keys())
    df_score['balanced_accuracy'], df_score['f1_score'], df_score['precision'], df_score['recall'] = [
        bal_accuracy.values(), f1.values(), precision.values(), recall.values()]
    df_score.index.rename('GDLCODE', inplace=True)
    df = df_hdi.join(df_score)

    dfs[threshold] = df
    print(f'threshold {threshold} taken: {time.time()-start_time} seconds')

# make dataframe with multiindex
data = np.vstack([df.to_numpy() for df in dfs.values()])
index = pd.MultiIndex.from_arrays([np.repeat(thresholds, gdl_codes.size), np.tile(gdl_codes,thresholds.size)])
final_df = pd.DataFrame(data=data, index=index)

final_df.to_csv('data/results/hdi-threshold-metrics.csv', sep=',')


import numpy as np
import argparse
import re
import math
import torch
import torch.distributions as tdist
import matplotlib.pyplot as plt

import activations as actv

from sympy.solvers import solve , nsolve
from sympy import Symbol
from sympy import sin, limit
from scipy import stats

class RnnArgs:
  def __init__(self, activation = (lambda x : torch.sign(x)) , num_samples=1024, input_size=1024, sim_time=20,tied_weights=False, SigmaW=1.0, SigmaU=1.0, \
               SigmaB=1.0, mu = 0.0, C0=0.5, Q0=1.0, LambdaIn= None, plot=False, desc=None, offsets=[]):
    self.input_size = input_size
    self.output_size = input_size
    self.num_samples = num_samples
    self.sim_time = sim_time
    self.tied_weights = tied_weights
    self.Mu = float(mu)
    self.SigmaW = float(SigmaW)
    self.SigmaU = float(SigmaU)
    self.SigmaB = float(SigmaB)
    self.Q0 = float(Q0)
    self.C0 = float(C0)
    if (LambdaIn==None):
      LambdaIn= (lambda x : seq_input_step( x, T=sim_time))
    self.In = LambdaIn(self)
    self.plot = plot
    self.act = activation
    self.offsets = offsets
    if (desc==None):
      self.desc = "Mu=%.2f, W=%.2f, U=%.2f, B=%.2f" % (self.Mu,self.SigmaW, self.SigmaU,self.SigmaB)
    else:
      self.desc = desc
    pass

  def label(self):
    return self.desc

  def present(self,rng=5.0):
    x = torch.linspace(-rng,rng,1000)
    y=self.act(x)
    plt.plot(x.numpy(),y.numpy())
    plt.plot(x.numpy(),x.numpy())
    plt.grid()
    plt.show()

def parse():
  parser = argparse.ArgumentParser(description='Calculate Covariance Matrix and match with Simulation')

  parser.add_argument('-n','--num', dest='num_samples', default=1024, \
                      type=int, help='Number of samples to simulate or use for calculation (default: 1024)')

  parser.add_argument('-M','--input_size', dest='input_size', default=1024, \
                      type=int, help='Length of inputs (default: 1024)')

  parser.add_argument('-N','--output_size', dest='output_size', default=1024, \
                      type=int, help='Length of output (default: 1024)')

  parser.add_argument('-T','--time', dest='sim_time', default=100, \
                      type=int, help='Length of time to simulate (default: 100)')

  parser.add_argument('-t','--tied_weights', dest='tied_weights', default=False,
                      action='store_true', help='Use tied weights (Simulation only, default: untied)')

  parser.add_argument('-s','--sim', dest='simulate', default=False,
                      action='store_true', help='Run calculation')

  parser.add_argument('-c','--calc', dest='calculate', default=False,
                      action='store_true', help='Run simulation')

  parser.add_argument('-p','--params', dest='params', default='0,1,1,1', \
                      type=str, help="mu,Sigma_w,Sigma_u,Sigma_b default: 0,1,1,1")

  parser.add_argument('-I','--initial', dest='initial', default='1,1', \
                      type=str, help="format: Q[0],C[0] default: 1,1")

  inputs= {
    'Step' : (lambda x : seq_input_step( x, T=10)),
    'Short Step' : (lambda x : seq_input_step( x, T=2 )),
    'Long Step' : (lambda x : seq_input_step( x, T=50)),
    'Same' : (lambda x : seq_input_step( x, T=0)),
    'Reverse' : (lambda x : seq_input_reverse_step( x, T=10)),

  }

  parser.add_argument('-x','--input_sequence', dest='input_seq', default='Step', \
                      type=str, help="Options: %s (default: 'Step')" % [key for (key,val) in inputs.items()])

  args = parser.parse_args()

  if (args):
    args.input_size = args.output_size
    if (args.input_size != args.output_size):
      print("Input dimnesion must be equal to ouput dimension")
      return None
    params = re.split(',',args.params)
    args.Mu = float(params[0])
    args.SigmaW = float(params[1])
    args.SigmaU = float(params[2])
    args.SigmaB = float(params[3])
    args.params=None

    initials = re.split(',',args.initial)
    args.Q0 = float(initials[0])
    args.C0 = float(initials[1])
    args.initial = None
    args.In = inputs[args.input_seq](args)

  return args

def normalize(v):
  return (v / v.norm())
  pass

def angle(a,b):
  return torch.sum(a*b)/(a.norm()*b.norm())
  pass

def Edot(a,b):
  return torch.sum(a*b)
  pass

class seq_input:
  def gen(self,t):
    pass

  def normGen(self,t):
    return normalize(self.gen(t))
##torch.Tensor.numpy()
  def cov(self,t, N=100):
    cov12 = 0
    cov11 = 0
    for n in range(N):
      cov12 += angle(self.gen(t),self.gen(t)) ##  self.normGen(t).mm(self.normGen(t))
      a = self.normGen(t)
      cov11 += np.dot(np.transpose(a),a)
    cov11 = cov11 / N
    cov12 = cov12 / N

    return np.matrix([[cov11, cov12],[cov12,cov11]])
    pass

  def cosine(self,t, n=100): ##off diagonal
    cov12 = 0
    for n in range(n):
      cov12 += angle(self.gen(t),self.gen(t)) ##  self.normGen(t).mm(self.normGen(t))
    cov12 = cov12 / n
    if (cov12 > 1.00):
      cov12 = 0.99
    return cov12
    pass

class seq_input_step(seq_input):
  def __init__(self, args, R=1.0, T=10, sigma = 1.0):
    self.R = R
    self.start = T
    self.sigma = sigma
    size= args.sim_time - T
    self.input_size= args.input_size
    self.values = np.random.normal(0, sigma, (size, self.input_size))
    self.dist = tdist.Normal(torch.tensor([0.0]), torch.tensor([sigma]))
    self.values = self.dist.sample([size, self.input_size])

  def gen(self,t):
    if (t < self.start):
      return self.dist.sample([self.input_size])
    else:
      return self.values[t - self.start]

class seq_input_reverse_step(seq_input):
  def __init__(self, args, R=1.0, T=10, sigma = 1.0):
    self.R = R
    self.start = T
    self.sigma = sigma
    size= T
    self.input_size= args.input_size
    self.values = np.random.normal(0, sigma, (size, self.input_size))
    self.dist = tdist.Normal(torch.tensor([0.0]), torch.tensor([sigma]))
    self.values = self.dist.sample([size, self.input_size])

  def gen(self,t):
    if (t < self.start):
      return self.values[t]
    else:
      return self.dist.sample([self.input_size])

def sim(args):

  samples = args.num_samples
  num_nets = int(np.sqrt(samples))
  tests_per_net = int(samples/num_nets)

  N = args.output_size
  iW = tdist.Normal(torch.tensor([0.0]), torch.tensor([args.SigmaW/np.sqrt(N)]))
  W = iW.sample([N,N])

  iU = tdist.Normal(torch.tensor([0.0]), torch.tensor([args.SigmaU/np.sqrt(N)]))
  iB = tdist.Normal(torch.tensor([args.Mu]), torch.tensor([args.SigmaB]))

  n = num_nets
  m = tests_per_net
  U = iU.sample([n,N,N]).repeat(m,1,1,1).reshape([n*m,N,N])
  W = iW.sample([n,N,N]).repeat(m,1,1,1).reshape([n*m,N,N])
  B = iB.sample([n,N]).repeat(m,1,1,1).reshape([n*m,N,1])

  s = torch.zeros([n*m,N,1])

  Z = torch.zeros(n*m,N,1)

  T = args.sim_time
  Q = np.ones(T)
  Qu = np.zeros(T)
  C = np.ones(T)
  Cu = np.zeros(T)
  Zdiag = np.zeros(T)
  Xi = np.zeros(T)

  for t in  range(T): ## range(args.sim_time):
    for k in range(n*m):
      Z[k] = args.In.gen(t).reshape(N,1)

    if (not args.tied_weights):
        W = iW.sample([n,N,N]).repeat(m,1,1,1).reshape([n*m,N,N])

    u = W.bmm(s) + U.bmm(Z) + B
    s = args.act(u)

    Es = torch.zeros([N,1])
    Eu = torch.zeros([N,1])

    for a_sample in range(samples):
      g = np.random.randint(0,num_nets)
      i = np.random.randint(0,tests_per_net)*num_nets + g
      j = np.random.randint(0,tests_per_net)*num_nets + g
      Q[t]+= Edot(s[i],s[i])
      C[t]+= Edot(s[i],s[j])
      Qu[t]+= Edot(u[i],u[i])
      Cu[t]+= Edot(u[i],u[j])
      Es= Es + s[i]
      Eu= Eu + u[i]
      Zdiag[t]+= angle(Z[i],Z[j])

    normalizor= samples*N
    Es = Es/(samples)
    Eu = Eu/(samples)
    Q[t] = Q[t]/(normalizor) - Edot(Es,Es)/N
    C[t] = C[t]/(normalizor)  - Edot(Es,Es)/N
    C[t] = C[t]/Q[t]
    Qu[t] = Qu[t]/(normalizor) - Edot(Eu,Eu)/N
    Cu[t] = Cu[t]/(normalizor) - Edot(Eu,Eu)/N
    Cu[t] = Cu[t]/Qu[t]
    Zdiag[t] =Zdiag[t]/samples

    if (t>1):
      Xi[t] = C[t]/C[t-1]
  if (args.plot):
    plt.plot(range(T),C,label="C")
    ##plt.plot(range(T),Q,label="Q")
    plt.plot(range(T),Zdiag,label="Z (diag)")
    ##plt.plot(range(T),Qu,label="Qu")
    plt.plot(range(T),Cu,label="Cu")
    #plt.plot(range(T),Xi,label="Xi")

    plt.legend()
    plt.show()
  return { 'Q': Q, 'C': C, 'Qu': Qu, 'Cu': Cu, 'Xi': Xi, 'Zdiag' : Zdiag}

def compute_Xi(mu, qu, cu, ww):
  muu = mu**2
  tmp = 1 + (muu)/qu+(2*mu/np.sqrt(qu))*cu
  tmp = tmp/(1-cu*cu)
  tmp = -(1/2) * tmp * (muu/qu)
  tmp = np.exp(tmp)
  tmp = (2*ww/(np.pi))*tmp
  return tmp

def calc(args):
  ##print("Calculation not supported yet")
  T = args.sim_time
  Q = np.ones(T)*args.Q0
  Qu = np.zeros(T)
  C = np.ones(T)*args.C0
  Cu = np.zeros(T)
  CholskeyC = np.zeros(T)
  Xi = np.zeros(T)

  Zdiag = np.zeros(T)
  ww = args.SigmaW**2
  uu = args.SigmaU**2
  bb = args.SigmaB**2
  mu = args.Mu

  n = args.num_samples ##num samples for convariance measurement

  stable_point = False

  for t in range(1,T):
    Zdiag[t] = args.In.cosine(t,n)# sigma Z off diagonal
    Qu[t] = ww*Q[t-1]+uu+bb
    Cu[t]= (ww*Q[t-1]*C[t-1] + uu*Zdiag[t] + bb)/Qu[t]
    Xi[t] = compute_Xi(mu,Qu[t],Cu[t],ww)

    if (stable_point):
      Q[t] = 1-math.erf(mu/(np.sqrt(2)*Qu[t]))
      C[t] = C[t-1]*Xi
    else:

      if Cu[t] >= 1.0:
        Cu[t] = 0.99

      diag = Qu[t]
      off_diag = Qu[t]*Cu[t]

      Cov= [[diag,off_diag],[off_diag,diag]]
      U = tdist.Normal(torch.tensor([mu]), torch.tensor([Qu[t]]))
      u = U.sample([n]).sign()
      Eu = torch.mean(u)
      Q[t] = torch.mean(u*u) - Eu**2

      U1 = tdist.MultivariateNormal(torch.tensor([mu,mu]), torch.tensor(Cov))

      Us = U1.sample([n])
      u1 = Us[:,0]
      u2 = Us[:,1]
      ## no cholskey decomposition
      C[t] = torch.mean(u1.sign()*u2.sign())- Eu**2
      C[t] = C[t]/Q[t]

      Uc = tdist.MultivariateNormal(torch.tensor([0.0,0.0]), torch.eye(2)).sample([n])
      u1 = Uc[:,0]
      u2 = Uc[:,1]
      ch1 = np.sqrt(Qu[t])*u1+mu
      ch2 = np.sqrt(Qu[t])*(Cu[t] * u1 + np.sqrt(1-Cu[t]*Cu[t])*u2)  + mu
      CholskeyC[t] = torch.mean(ch1.sign()*ch2.sign()) - Eu**2
      CholskeyC[t] = CholskeyC[t]/Q[t]

  if (args.plot):
    plt.plot(range(T),C,label="C")
    ##plt.plot(range(T),Q,label="Q")
    plt.plot(range(T),Zdiag,label="Z (diag)")
    ##plt.plot(range(T),Qu,label="Qu")
    plt.plot(range(T),Cu,label="Cu")
    #plt.plot(range(T),Xi,label="Xi")
    #plt.plot(range(T),CholskeyC,label="Cholskey C")
    plt.legend()
    plt.show()

  return { 'Q': Q, 'C': C, 'Qu': Qu, 'Cu': Cu, 'Xi': Xi, 'Zdiag' : Zdiag}

def get_ff_qstar(args):
  ww = args.SigmaW**2
  bb = args.SigmaB**2
  mu = args.Mu
  n = args.num_samples ##num samples for convariance measurement
  N = args.output_size

  q = 0.5
  for i in range(N):

    Qu = ww*q+bb
    U = tdist.Normal(torch.tensor([mu]), torch.tensor([np.sqrt(Qu)]))
    u = args.act(U.sample([n]))
    Eu = torch.mean(u)
    q = torch.mean(u*u) - Eu**2

  return q

def get_ff_star(args):
  ww = args.SigmaW**2
  bb = args.SigmaB**2
  mu = args.Mu
  n = args.num_samples ##num samples for convariance measurement
  N = args.output_size

  Qstar = get_ff_qstar(args)
  c=0.5
  for i in range(N):
    Qu = ww*Qstar+bb
    Cu= (ww*Qstar*c + bb)/Qu
    ##print("Qu = %.02f, Cu = %.02f" % (Qu,Cu))
    U = tdist.Normal(torch.tensor([mu]), torch.tensor([np.sqrt(Qu)]))
    u = args.act(U.sample([n]))
    Eu = torch.mean(u)

    Uc = tdist.MultivariateNormal(torch.tensor([0.0,0.0]), torch.eye(2)).sample([n])
    u1 = Uc[:,0]
    u2 = Uc[:,1]
    ch1 = np.sqrt(Qu)*u1+mu
    ch2 = np.sqrt(Qu)*(Cu * u1 + np.sqrt(1.0-Cu*Cu)*u2) + mu
    tmp = torch.mean(args.act(ch1) * args.act(ch2) ) - Eu**2
    c = tmp/Qstar
    if (c>=1.0):
      return 1.0,Qstar
    elif (c<=0.0):
      return 0.0,Qstar
  return c,Qstar

def get_chi_star(args,Cstar,Qstar,eps =0.01):
  ww = args.SigmaW**2
  bb = args.SigmaB**2
  mu = args.Mu
  n = args.num_samples ##num samples for convariance measurement
  N = args.output_size
  M = np.zeros(N)
  mx = min(Cstar+eps,1.0)
  mn = max(Cstar-eps,0.0)
  Cv= torch.linspace(mn,mx,N)
  for i in range(N):
    c= Cv[i]
    Qu = ww*Qstar+bb
    Cu= (ww*Qstar*c + bb)/Qu
    ##print("Qu = %.02f, Cu = %.02f" % (Qu,Cu))
    U = tdist.Normal(torch.tensor([mu]), torch.tensor([np.sqrt(Qu)]))
    u = args.act(U.sample([n]))
    Eu = torch.mean(u)

    Uc = tdist.MultivariateNormal(torch.tensor([0.0,0.0]), torch.eye(2)).sample([n])
    u1 = Uc[:,0]
    u2 = Uc[:,1]
    ch1 = np.sqrt(Qu)*u1+mu
    ch2 = np.sqrt(Qu)*(Cu * u1 + np.sqrt(1.0-Cu*Cu)*u2) + mu
    tmp = torch.mean(args.act(ch1) * args.act(ch2) ) - Eu**2
    mc = tmp/Qstar
    if (mc>=1.0):
      mc= 1.0
    M[i] = mc

  slope, intercept, r_value, p_value, std_err = stats.linregress(Cv,M)

  return slope

def get_qstar(args):
  ww = args.SigmaW**2
  uu = args.SigmaU**2
  bb = args.SigmaB**2
  mu = args.Mu

  n = args.num_samples ##num samples for convariance measurement
  N = args.output_size

  Q = np.linspace(0,50,N)

  Mq = np.zeros(N)
  for i in range(N):
    q = Q[i]
    Qu = ww*q+uu+bb
    U = tdist.Normal(torch.tensor([mu]), torch.tensor([np.sqrt(Qu)]))
    u = args.act(U.sample([n]))
    Eu = torch.mean(u)
    Mq[i] = torch.mean(u*u) - Eu**2

  argmin = np.argmin(np.abs(Mq - Q))
  Qstar1 = Q[argmin]

  if (args.plot):
    max_plot= N if (argmin*2 > N) else argmin*2
    plt.plot(Q[0:argmin*2],Mq[0:argmin*2],label="Mapping")
    plt.plot(Q[0:argmin*2],Q[0:argmin*2],label="Q=Q line")
    plt.title("Q Mapping")
    plt.legend()
    plt.show()

  delta=1.0
  if (delta < Qstar1):
    delta = Qstar1
  Q = np.linspace(Qstar1-delta,Qstar1+delta,N)

  Mq = np.zeros(N)
  for i in range(N):
    q = Q[i]
    Qu = ww*q+uu+bb
    U = tdist.Normal(torch.tensor([mu]), torch.tensor([np.sqrt(Qu)]))
    u = args.act(U.sample([n]))
    Eu = torch.mean(u)
    Mq[i] = torch.mean(u*u) - Eu**2

  argmin = np.argmin(np.abs(Mq - Q))
  Qstar = Q[argmin]

  return Qstar

def draw_map(args, C = None):
  ww = args.SigmaW**2
  uu = args.SigmaU**2
  bb = args.SigmaB**2
  mu = args.Mu

  n = args.num_samples ##num samples for convariance measurement

  if not type(C) is np.ndarray:
    C = np.linspace(0,1,args.output_size)

  N = len(C)
  M = np.zeros(N)

  Qstar = get_qstar(args)
  Z = 1

  for i in range(N):
    c = C[i]
    Qu = ww*Qstar+uu+bb
    Cu= (ww*Qstar*c + uu*Z + bb)/Qu

    U = tdist.Normal(torch.tensor([mu]), torch.tensor([np.sqrt(Qu)]))
    u = args.act(U.sample([n]))
    Eu = torch.mean(u)

    Uc = tdist.MultivariateNormal(torch.tensor([0.0,0.0]), torch.eye(2)).sample([n])
    u1 = Uc[:,0]
    u2 = Uc[:,1]
    ch1 = np.sqrt(Qu)*u1+mu
    ch2 = np.sqrt(Qu)*(Cu * u1 + np.sqrt(1-Cu*Cu)*u2) + mu
    M[i] = torch.mean(args.act(ch1) * args.act(ch2) ) - Eu**2
    M[i] = M[i]/Qstar

  if (args.plot):
    plt.plot(C,M,label="Mapping")
    plt.plot(C,C,label="C=C line")
    plt.title("C Mapping")
    plt.legend()
    plt.show()

  argmin = np.argmin(np.abs(C[0:(len(C)-1)] - M[0:(len(C)-1)]))
  Cstar = M[argmin]
  return {'C': C, 'Qstar': Qstar, 'M': M, 'Cstar': Cstar}

def plot_convergence(simC, calC):
  T = len(simC)
  simC_star=  simC[T-1]
  calC_star= calC[T-1]

  simCdiff= np.abs(simC- simC_star)
  calCdiff= np.abs(calC- calC_star)

  plt.plot(range(T),simCdiff,label="simulation convergence")
  plt.plot(range(T),calCdiff,label="calculation convergence")
  plt.yscale = "log"
  plt.legend()
  plt.show()

def plot_graph(results):
  T = len(results['C'])
  plt.plot(range(T),results['C'],label="C")
  plt.plot(range(T),results['Q'],label="Q")
  plt.plot(range(T),results['Qu'],label="Qu")
  plt.plot(range(T),results['Zdiag'],label="Z (diag)")
  plt.plot(range(T),results['Cu'],label="Cu")
  plt.legend()
  plt.show()

def compare(results):
  keys=list(results.keys())
  T = len(results[keys[0]])
  for key in keys:
    plt.plot(range(T),results[key],label=key)
  plt.legend()
  plt.gcf().set_size_inches(10, 10)
  plt.show()

def noisy_sign(x):
  return actv.noisy_sign(x)

def sr_sign(x):
  return actv.sr_sign(x)

def cast_int2(x):
  return actv.cast_int2(x)

def cast_intn(x,n):
  return actv.cast_intn(x,n)

def cast_even_intn(x,n):
  return actv.cast_even_intn(x,n)

def report(arguments, samples= 1024*256):
    for args in arguments:
        tmp = args.num_samples
        args.num_samples = samples
        c,q = get_ff_star(args)
        chi = get_chi_star(args,c,q)
        args.num_samples = tmp
        print("%s:, C = %.02f, Q = %.02f, chi = %.02f" % (args.desc,c,q,chi))

def get_cu(C,args,q):
    ww = args.SigmaW**2
    bb = args.SigmaB**2
    uu = args.SigmaU**2
    return (q*C*(ww)+bb+uu)/(ww*q+bb+uu)

def get_qu(args):
    ww = args.SigmaW**2
    bb = args.SigmaB**2
    uu = args.SigmaU**2
    q= get_qstar(args)
    Qu = ww*q+uu+bb
    return Qu

def main():
  np.set_printoptions(precision=2)
  args = parse()
  if (args==None):
    return
  if args.simulate:
    sQ,sC,sQu,sCu,sXi = sim(args)
  if args.calculate:
    cQ,cC,cQu,cCu,cXi = calc(args)
    plot_convergence(args,sC,cC)

  pass

if __name__ == "__main__":
  main()

##runfile('C:/Users/Yaniv/Downloads/np_calc.py', "-T 50 -c -p 0.5,1.3,1,1 -I 1,1")


from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from jsonDict.jsonDictionary import input_json
from PageObjects.HomepageObj import Homepage
from PageObjects.WeatherDetailspageObj import WeatherDetails
from TemperatureViaAPI.APITemperature import ApiTemp
import json
import statistics

class TestWeatherReporting:
    def __init__(self):
        self.driver = webdriver.Chrome(ChromeDriverManager().install())
        self.driver.get("https://weather.com/")

    def getWeatherInfoViaUI(self):
        hp = Homepage(self.driver)
        wd = WeatherDetails(self.driver)
        hp.searchCity("Delhi")
        return wd.getCurrentTemp()

    def getWeatherInfoViaAPI(self):
        apiObj = ApiTemp()
        temperatures = apiObj.getJsonCitiesTemp()
        return temperatures

    def calculateVariance(self, samples, UISample):
        jsonDict = json.loads(input_json)
        variance = jsonDict.get("variance")
        for sample in samples:
            data_sample = [UISample, sample]
            print(data_sample)
            if statistics.variance(data_sample) <= variance:
                print(f"calculated variance is {statistics.variance(data_sample)} : pass")
            else:
                print(f"calculated variance is {statistics.variance(data_sample)} :exceed variance range")

test = TestWeatherReporting()
temperatureFromUI = test.getWeatherInfoViaUI()
temperatureFromAPI = test.getWeatherInfoViaAPI()
print("Temperature from UI:",temperatureFromUI)
print("Temperature from API for the cities in json", temperatureFromAPI)
test.calculateVariance(temperatureFromAPI, temperatureFromUI)


import os
import re
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

class QuestionsParser():
    def __init__(self, url_list):
        self.url_list = url_list

    def parse_questions(self, number_of_questions_per_difficulty_level):
        url_list = self.url_list
        all_questions_lists = []
        all_questions_urls_list = []
        os.environ['PATH'] = "/Users/ashutoshkumar/seleniumdrivers"
        options = Options()
        options.headless = True
        driver = webdriver.Chrome(options=options)
        for url in url_list:
            print("Getting questions from", url)
            driver.get(url)
            d = {}
            self.__parse_questions_for_url(driver, d)
            questions_list = self.__get_questions_list(d, number_of_questions_per_difficulty_level, all_questions_urls_list)
            all_questions_lists.extend(questions_list)
            time.sleep(3)
        driver.close()
        return all_questions_lists

    def __parse_questions_for_url(self, driver, d):
        problems_table = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((webdriver.common.by.By.CSS_SELECTOR, "table.problems")))
        for row in problems_table.find_elements(webdriver.common.by.By.TAG_NAME, "tr"):
            try: # parse questions details
                problem_details = row.find_element(webdriver.common.by.By.TAG_NAME, "td")
                problem_url = problem_details.find_element(webdriver.common.by.By.TAG_NAME, "a").get_attribute("href")
                problem_name_and_tag = row.find_element(webdriver.common.by.By.CSS_SELECTOR, "td:nth-of-type(2)").text
                posn = problem_name_and_tag.index("\n")
                problem_name = problem_name_and_tag[:posn]
                problem_tag = problem_name_and_tag[posn+1:]
                tmp_d = {}
                tmp_d["problem_code"] = problem_details.text
                tmp_d["problem_url"] = problem_url
                tmp_d["problem_name"] = problem_name
                tmp_d["problem_tag"] = problem_tag
                match_obj = re.search("[A-Z]+",problem_details.text)
                code = match_obj.group()
                if d.get(code, -1) == -1:
                    d[code] = [tmp_d]
                else:
                    d[code].append(tmp_d)
            except Exception as e:
                pass
        try:
            pagination = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((webdriver.common.by.By.CSS_SELECTOR, "div.pagination")))
            last_anchor_tag = pagination.find_elements(webdriver.common.by.By.TAG_NAME, "a")[-1]
            if last_anchor_tag.text == "→":
                last_anchor_tag.click()
                time.sleep(3)
                print("moving to next page...")
                self.__parse_questions_for_url(driver, d)
        except Exception as ex:
            pass

    def __get_questions_list(self, question_dict, num_of_questions_per_difficulty, all_questions_urls_list):
        all_questions_arr = []
        for difficulty in question_dict:
            questions_arr = []
            for question in question_dict[difficulty]:
                question_tags = question['problem_tag']
                question_url = question['problem_url']
                match_obj = re.search('\*+', question_tags)
                if not match_obj and question_url not in all_questions_urls_list:
                    questions_arr.append(question)
                    all_questions_urls_list.append(question_url) # to remove duplicates
                    if len(questions_arr) >= 10:
                        break
            all_questions_arr.extend(questions_arr)
        return all_questions_arr


from comparator.interval import Constraint
from comparator.ota import State, Timedword

class Letter(object):
    """
        The definition of letter. A letter is a pair (location, region).
        "location" for indicating the location
        "constraint" for the region
    """

    def __init__(self, location, constraint):
        self.location = location
        if isinstance(constraint, str):
            constraint = Constraint(constraint)
        self.constraint = constraint

    def __eq__(self, letter):
        if self.location == letter.location and self.constraint == letter.constraint:
            return True
        else:
            return False

    def __hash__(self):
        return hash(("LETTER", self.location, self.constraint))

    def to_state(self, i):
        """
            Transform a letter to a state.
        """
        location = self.location
        if self.constraint.isPoint():
            v = self.constraint.min_value + '.0'
        else:
            v = self.constraint.min_value + '.' + str(i + 1)
        return State(location, v)

    def show(self):
        return self.location.get_flagname() + ',' + self.constraint.show()

    def __str__(self):
        return self.show()

    def __repr__(self):
        return self.show()

class Letterword(object):
    """
        The definition of letterword.
        lw for the letterword list itself
        prelw for the pre letterword object.
    """

    def __init__(self, lw, prelw=None, action="DELAY"):
        self.lw = lw or []
        self.prelw = prelw
        self.action = action

    def __eq__(self, letterword):
        if self.lw == letterword.lw:
            return True
        else:
            return False

    def __hash__(self):
        return hash(("LETTERWORD", self.lw, self.prelw, self.action))

    def show(self):
        return self.lw  # , self.action

    def __str__(self):
        return self.show()

    def __repr__(self):
        return self.show()

class Element(object):
    """
        The definition of the element in OTA observation table.
    """

    def __init__(self, tws=[], value=[], suffixes_resets=[]):
        self.tws = tws or []
        self.value = value or []
        self.suffixes_resets = suffixes_resets or []

    def __eq__(self, element):
        if self.tws == element.tws and self.value == element.value:
            return True
        else:
            return False

    def get_tws_e(self, e):
        tws_e = [tw for tw in self.tws]
        if len(e) == 0:
            return tws_e
        else:
            for tw in e:
                tws_e.append(tw)
            return tws_e

    def row(self):
        return self.value

    def whichstate(self):
        state_name = ""
        for v in self.value:
            state_name = state_name + str(v)
        return state_name

    def show(self):
        return [tw.show() for tw in self.tws], self.value, self.suffixes_resets

def ota_inclusion(max_time_value, A, B):
    """
        Determine whether L(B) is a subset of L(A).
    """
    A_init_name = A.initstate_name
    B_init_name = B.initstate_name
    L1 = A.findlocationbyname(A_init_name)
    Q1 = B.findlocationbyname(B_init_name)
    w0 = [{Letter(L1, "[0,0]"), Letter(Q1, "[0,0]")}]
    to_explore = [Letterword(w0, None, '')]
    explored = []
    while True:
        if len(to_explore) == 0:
            return True, None
        w = to_explore[0]
        del to_explore[0]
        if is_bad_letterword(w.lw, A, B):
            return False, w
        while explored_dominated(explored, w):
            if len(to_explore) == 0:
                return True, None
            w = to_explore[0]
            del to_explore[0]
            if is_bad_letterword(w.lw, A, B):
                return False, w
        wsucc, next = compute_wsucc(w, max_time_value, A, B)
        for nw in next:
            if nw not in to_explore:
                to_explore.append(nw)
        if w not in explored:
            explored.append(w)

def is_bad_letterword(letterword, A, B):
    """
        Determine whether a letterword is bad in case of L(B) is a subset of L(A)
    """
    if len(letterword) == 1:
        letter1, letter2 = list(letterword[0])
    elif len(letterword) == 2:
        letter1, letter2 = list(letterword[0])[0], list(letterword[1])[0]
    else:
        raise NotImplementedError()
    location1 = letter1.location
    location2 = letter2.location
    if location1.flag == B.locations[0].flag:
        if location1.name in B.accept_names and location2.name not in A.accept_names:
            return True
        else:
            return False
    else:
        if location2.name in B.accept_names and location1.name not in A.accept_names:
            return True
        else:
            return False

def explored_dominated(explored, w):
    if len(explored) == 0:
        return False
    for v in explored:
        if letterword_dominated(v, w):
            return True
    return False

def letterword_dominated(lw1, lw2):
    """
        To determine whether letterword lw1 is dominated by letterword lw2 (lw1 <= lw2)
    """
    index = 0
    flag = 0
    for letters1 in lw1.lw:
        for i in range(index, len(lw2.lw)):
            if letters1.issubset(lw2.lw[i]):
                index = i + 1
                flag = flag + 1
                break
            else:
                pass
    if flag == len(lw1.lw):
        return True
    else:
        return False

def compute_wsucc(letterword, max_time_value, A, B):
    """
        Compute the Succ of letterword.
    """
    # First compute all possible time delay
    results = []
    last_region = Constraint('(' + str(max_time_value) + ',' + '+' + ')')
    if len(letterword.lw) == 1:
        result = letterword.lw[0]
        while any(letter.constraint != last_region for letter in result):
            results.append(Letterword([result], letterword))
            new_result = set()
            for letter in result:
                new_letter = Letter(letter.location, next_region(letter.constraint, max_time_value))
                new_result.add(new_letter)
            result = new_result
        current_lw = Letterword([result], letterword)
        if current_lw not in results:
            results.append(current_lw)
    elif len(letterword.lw) == 2:
        if len(letterword.lw[0]) != 1 and len(letterword.lw[1]) != 1:
            raise NotImplementedError()
        result = letterword.lw
        while list(result[0])[0].constraint != last_region or list(result[1])[0].constraint != last_region:
            results.append(Letterword(result, letterword))
            new_result = []
            l1, l2 = list(result[0])[0], list(result[1])[0]
            if l1.constraint.isPoint():
                new_result.append({Letter(l1.location, next_region(l1.constraint, max_time_value))})
                new_result.append({l2})
            else:
                new_result.append({Letter(l2.location, next_region(l2.constraint, max_time_value))})
                new_result.append({l1})
            result = new_result
        current_lw = Letterword(result, letterword)
        if current_lw not in results:
            results.append(current_lw)
            new_result = Letterword([current_lw.lw[1], current_lw.lw[0]], letterword)
            if new_result not in results:
                results.append(new_result)
    else:
        raise NotImplementedError()

    # Next, perform the immediate 'a' transition
    next = []
    for letterword in results:
        next_ws = immediate_asucc(letterword, A, B)
        for next_w in next_ws:
            if next_w not in next:
                next.append(next_w)
    return results, next

def next_region(region, max_time_value):
    """
        Returns r_0^1 for r_0, r_1 for r_0^1, etc.
    """
    if region.isPoint():
        if int(region.max_value) == max_time_value:
            return Constraint('(' + region.max_value + ',' + '+' + ')')
        else:
            return Constraint('(' + region.max_value + ',' + str(int(region.max_value) + 1) + ')')
    else:
        if region.max_value == '+':
            return Constraint('(' + region.min_value + ',' + '+' + ')')
        else:
            return Constraint('[' + region.max_value + ',' + region.max_value + ']')

def immediate_asucc(letterword, A, B):
    """
        Perform the immediate 'a' action in case of L(B) is a subset of L(A).
    """
    results = []
    if len(letterword.lw) == 1:
        letter1, letter2 = list(letterword.lw[0])
        for action in B.sigma:
            if letter1.location.flag == A.locations[0].flag:
                B_letter = immediate_letter_asucc(letter2, action, B)
                A_letter = immediate_letter_asucc(letter1, action, A)
            else:
                B_letter = immediate_letter_asucc(letter1, action, B)
                A_letter = immediate_letter_asucc(letter2, action, A)
            if B_letter is not None and A_letter is not None:
                B_ispoint = B_letter.constraint.isPoint()
                A_ispoint = A_letter.constraint.isPoint()
                if A_ispoint == True and B_ispoint == True:
                    w = [{A_letter, B_letter}]
                elif A_ispoint == True and B_ispoint == False:
                    w = [{A_letter}, {B_letter}]
                elif A_ispoint == False and B_ispoint == True:
                    w = [{B_letter}, {A_letter}]
                else:
                    w = [{A_letter, B_letter}]
                current_lw = Letterword(w, letterword, action)
                if current_lw not in results:
                    results.append(current_lw)
    elif len(letterword.lw) == 2:
        letter1, letter2 = list(letterword.lw[0])[0], list(letterword.lw[1])[0]
        for action in B.sigma:
            if letter1.location.flag == A.locations[0].flag:
                B_letter = immediate_letter_asucc(letter2, action, B)
                A_letter = immediate_letter_asucc(letter1, action, A)
                if B_letter is not None and A_letter is not None:
                    B_ispoint = B_letter.constraint.isPoint()
                    A_ispoint = A_letter.constraint.isPoint()
                    if A_ispoint == True and B_ispoint == True:
                        w = [{A_letter, B_letter}]
                    elif A_ispoint == True and B_ispoint == False:
                        w = [{A_letter}, {B_letter}]
                    elif A_ispoint == False and B_ispoint == True:
                        w = [{B_letter}, {A_letter}]
                    else:
                        w = [{A_letter}, {B_letter}]
                    current_lw = Letterword(w, letterword, action)
                    if current_lw not in results:
                        results.append(current_lw)
            else:
                B_letter = immediate_letter_asucc(letter1, action, B)
                A_letter = immediate_letter_asucc(letter2, action, A)
                if B_letter is not None and A_letter is not None:
                    B_ispoint = B_letter.constraint.isPoint()
                    A_ispoint = A_letter.constraint.isPoint()
                    if A_ispoint == True and B_ispoint == True:
                        w = [{A_letter, B_letter}]
                    elif A_ispoint == True and B_ispoint == False:
                        w = [{A_letter}, {B_letter}]
                    elif A_ispoint == False and B_ispoint == True:
                        w = [{B_letter}, {A_letter}]
                    else:
                        w = [{B_letter}, {A_letter}]
                    current_lw = Letterword(w, letterword, action)
                    if current_lw not in results:
                        results.append(current_lw)
    else:
        raise NotImplementedError()
    return results

def immediate_letter_asucc(letter, action, ota):
    location_name = letter.location.name
    region = letter.constraint
    for tran in ota.trans:
        if tran.source == location_name and action == tran.label and region.issubset(tran.constraints[0]):
            succ_location_name = tran.target
            succ_location = ota.findlocationbyname(succ_location_name)
            if tran.reset:
                region = Constraint("[0,0]")
            if succ_location is not None:
                return Letter(succ_location, region)
    return None

def findDelayTimedwords(letterword, flag, sigma):
    """
        Given a path, return the delay timedword.
    """
    path = findpath(letterword)
    delay_timedwords = []
    current_clock_valuation = 0
    delay_time = 0
    for letterword in path:
        if len(letterword.lw) == 1:
            letter1, letter2 = list(letterword.lw[0])
        elif len(letterword.lw) == 2:
            letter1, letter2 = list(letterword.lw[0])[0], list(letterword.lw[1])[0]
        else:
            raise NotImplementedError()
        if letter1.location.flag == flag:
            temp_region = letter1.constraint
        else:
            temp_region = letter2.constraint
        if letterword.action == "DELAY":
            delay_time = minnum_in_region(temp_region) - current_clock_valuation
            current_clock_valuation = minnum_in_region(temp_region)
        elif letterword.action in sigma:
            new_timedword = Timedword(letterword.action, delay_time)
            delay_timedwords.append(new_timedword)
            current_clock_valuation = minnum_in_region(temp_region)
        elif letterword.action == '':
            pass
        else:
            raise NotImplementedError()
    return delay_timedwords

def findpath(letterword):
    """
        When get a letterword, find the path ends in the letterword.
    """
    current_lw = letterword
    path = [current_lw]
    while current_lw.prelw is not None:
        path.insert(0, current_lw.prelw)
        current_lw = current_lw.prelw
    return path

def minnum_in_region(constraint):
    """
        Return the minimal number in the region. For [5,9], return 5; for (4,10), return 4.1 .
    """
    if constraint.closed_min:
        return int(constraint.min_value)
    else:
        return float(constraint.min_value + '.1')

def equivalence_query_normal(max_time_value, teacher, hypothesis, prev_ctx=None):
    """Normal teacher
    """
    if prev_ctx is not None:
        for ctx in prev_ctx:
            teacher_res = teacher.is_accepted_delay(ctx.tws)
            hypothesis_res = hypothesis.is_accepted_delay(ctx.tws)
            if teacher_res != hypothesis_res and hypothesis_res != -2:
                return False, ctx

    flag_pos, w_pos = ota_inclusion(max_time_value, hypothesis, teacher)
    if not flag_pos:
        dtw_pos = findDelayTimedwords(w_pos, 's', teacher.sigma)
        ctx_pos = Element(dtw_pos, [])
        return False, ctx_pos
    else:
        flag_neg, w_neg = ota_inclusion(max_time_value, teacher, hypothesis)
        if not flag_neg:
            dtw_neg = findDelayTimedwords(w_neg, 's', teacher.sigma)
            ctx_neg = Element(dtw_neg, [])
            return False, ctx_neg
        else:
            return True, None


# Contadores
total_compra = 0
menor_valor = 19 * 1000
menor_nome = ''
valormaisde1000 = 0
# Condição
condicaowhile_principal = True

print('='*15, 'Bem-vindo ao menu da loja', '='*15)

while condicaowhile_principal:
    nome_produto = str(input('Digite o nome o produto: ')).strip().lower()
    valor_produto = float(input('Digite o valor do produto R$: '))
    total_compra += valor_produto
    print('=-' * 30)
    if valor_produto < menor_valor:
        menor_valor = valor_produto
        menor_nome = nome_produto
    if valor_produto >= 1000:
        valormaisde1000 += 1
    while True:
        novo_produto = str(input('Você quer adicionar novos produtos?')).strip().lower()
        print('=-' * 30)
        if novo_produto == 'sim' or novo_produto == 's':
            break
        elif novo_produto == 'n' or novo_produto == 'não' or novo_produto == 'nao':
            condicaowhile_principal = False
            break

print(f'''{total_compra:.2f} foi valor final dos produto(s)
{valormaisde1000} produto(s) com o valor maior que R$1000
{menor_nome.capitalize()} é o produto mais barato, no valor de {menor_valor}''')


#Reverse the dictionary

translations = {
   'apple': ['malum', 'pomum', 'popula'],
   'fruit': ['baca', 'bacca', 'popum'],
   'punishment': ['malum', 'multa']
}
print(translations)

rev_dict = {}
for key, val in translations.items():
   rev_dict[tuple(val)] = key
print("Reversed dictionary: ", rev_dict)