import json
import os
from pathlib import Path

import pandas as pd
from typing import Dict
import matplotlib
import matplotlib.pyplot as plt

from drl.experiment.config import Config

class Analyzer:

    def __init__(self, config: Config, session_id):
        self.__config = config
        self.__session_id = session_id
        pass

    def play_analysis(self, path_to_experiment) -> Dict:

        # path = self.__config.get_app_experiments_path(train_mode=False)
        path = os.path.join(path_to_experiment, 'log.csv')

        df = pd.read_csv(path)

        analysis = {}
        analysis['number_of_episodes'] = df['episode'].max() + 1
        analysis['average_number_of_steps'] = df.groupby('episode').count()['step'].mean()
        analysis['average_reward_per_step'] = df.groupby('episode').mean()['reward'].mean()
        analysis['average_reward'] = df.groupby('episode').max()['reward_total'].sum()

        """

        :return:
            number_of_episodes
            average_number_of_steps
            average_reward
            average_number_of_actions
        """
        return analysis

    def compare_train_config(self, path_to_experiments):

        for path_to_experiment in path_to_experiments:
            path = os.path.join(path_to_experiment, 'config.json')

            with open(path, 'r') as fp:
                cfg = json.load(fp)

            print(path_to_experiment)
            print(json.dumps(cfg, indent=4, sort_keys=True))

        pass

    def compare_train_epoch_cols(self, path_to_experiments, compare_col, plot=False):
        max_x = 0

        for path_to_experiment in path_to_experiments:
            path = os.path.join(path_to_experiment, 'epoch-log.csv')

            df = pd.read_csv(path, index_col=0)
            if df.shape[0] > max_x:
                max_x = df.shape[0]

        df_main = pd.DataFrame(list(range(max_x)))

        for path_to_experiment in path_to_experiments:
            path = os.path.join(path_to_experiment, 'epoch-log.csv')

            df_tmp = pd.read_csv(path, index_col=0)

            df_tmp = df_tmp[[compare_col]]

            df_tmp.columns = [(path_to_experiment.rsplit('/', 1)[1])]

            df_main = df_main.join(df_tmp)

        df_main = df_main[df_main.columns.difference([0])]

        ax = df_main.plot()

        ax.set_xlabel('epoch')
        ax.set_ylabel(compare_col)

        from matplotlib import pyplot
        fig = ax.get_figure()

        path = os.path.join(self.__config.get_app_analysis_path(), self.__session_id)
        Path(path).mkdir(parents=True, exist_ok=True)

        path = os.path.join(path, compare_col +'.png' )

        if plot:
            plt.show()
            return None
        else:
            matplotlib.use('Agg')
            fig.savefig(path)
            return path

    def compare_train_epoch_score(self, path_to_experiment, plot=False):

        path = os.path.join(path_to_experiment, 'epoch-log.csv')

        df_tmp = pd.read_csv(path, index_col=0)

        df_tmp = df_tmp[['avg_score', 'avg_val_score']]

        ax = df_tmp.plot()

        ax.set_xlabel('epoch')
        ax.set_ylabel('score')

        from matplotlib import pyplot
        fig = ax.get_figure()

        path = os.path.join(self.__config.get_app_analysis_path(), self.__session_id)
        Path(path).mkdir(parents=True, exist_ok=True)

        path = os.path.join(path, 'score.png' )

        if plot:
            plt.show()
            return None
        else:
            matplotlib.use('Agg')
            fig.savefig(path)
            return path

    def log_analysis(self, analysis: Dict):
        for key in analysis.keys():
            print("{}: {}".format(key, analysis[key]))


import numpy as np
import os

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import matplotlib.pyplot as plt

with open(os.path.join(os.getcwd(), 'clean', 'clean-antivirus-features.txt')) as f:
    all_features = f.readlines()

cosine_sim_scores = []

tfidf_vectorizer = TfidfVectorizer()
with open(os.path.join(os.getcwd(), 'requirement','antivirus-requirements.txt')) as f:
    for generated_feature in f.readlines()[:500]:
        appended_features = [generated_feature] + all_features
        tfidf_matrix = tfidf_vectorizer.fit_transform(appended_features)
        cosine_sim_scores.append(np.mean(cosine_similarity(tfidf_matrix[0:1], tfidf_matrix)))

X = np.arange(len(cosine_sim_scores))

# fig,ax = plt.subplots(1)

plt.figure(figsize=(8,4))
plt.bar(X, cosine_sim_scores, width=0.3, color='#4286f4')
plt.xlabel("generated requirement id")
plt.ylabel("cosine similarity td-idf score")
# plt.gca().axes.get_xaxis().set_visible(False)

cosine_sim_scores.sort()

plt.axhline(y=cosine_sim_scores[400], color='r', linestyle='-', linewidth=0.5)
plt.tight_layout()
plt.show()

print('Finished!')


import numpy as np
from gym.envs.box2d import LunarLander
from gym.envs.box2d.lunar_lander import ContactDetector, VIEWPORT_W, SCALE, VIEWPORT_H, INITIAL_RANDOM, LANDER_POLY, \
    LEG_AWAY, LEG_W, LEG_H, LEG_DOWN, LEG_SPRING_TORQUE
from gym.vector.utils import spaces

import Box2D
from Box2D.b2 import (edgeShape, circleShape, fixtureDef, polygonShape, revoluteJointDef, contactListener)

INITIAL_RANDOM = INITIAL_RANDOM

class LunarLanderRandomInit(LunarLander):
    smooth_random = True

    def reset(self):
        self._destroy()
        self.world.contactListener_keepref = ContactDetector(self)
        self.world.contactListener = self.world.contactListener_keepref
        self.game_over = False
        self.prev_shaping = None

        W = VIEWPORT_W / SCALE
        H = VIEWPORT_H / SCALE

        # terrain
        CHUNKS = 11
        height = self.np_random.uniform(0, H / 2, size=(CHUNKS + 1,))
        chunk_x = [W / (CHUNKS - 1) * i for i in range(CHUNKS)]
        self.helipad_x1 = chunk_x[CHUNKS // 2 - 1]
        self.helipad_x2 = chunk_x[CHUNKS // 2 + 1]
        self.helipad_y = H / 4
        height[CHUNKS // 2 - 2] = self.helipad_y
        height[CHUNKS // 2 - 1] = self.helipad_y
        height[CHUNKS // 2 + 0] = self.helipad_y
        height[CHUNKS // 2 + 1] = self.helipad_y
        height[CHUNKS // 2 + 2] = self.helipad_y
        smooth_y = [0.33 * (height[i - 1] + height[i + 0] + height[i + 1]) for i in range(CHUNKS)]

        self.moon = self.world.CreateStaticBody(shapes=edgeShape(vertices=[(0, 0), (W, 0)]))
        self.sky_polys = []
        for i in range(CHUNKS - 1):
            p1 = (chunk_x[i], smooth_y[i])
            p2 = (chunk_x[i + 1], smooth_y[i + 1])
            self.moon.CreateEdgeFixture(
                vertices=[p1, p2],
                density=0,
                friction=0.1)
            self.sky_polys.append([p1, p2, (p2[0], H), (p1[0], H)])

        self.moon.color1 = (0.0, 0.0, 0.0)
        self.moon.color2 = (0.0, 0.0, 0.0)

        if self.smooth_random:
            initial_x = np.clip(self.np_random.normal(loc=W / 2., scale=W / 3.),
                                a_min=0., a_max=W)
            initial_y = np.clip(self.np_random.normal(loc=H - (H - self.helipad_y) / 3., scale=self.helipad_y / 3.),
                                a_min=self.helipad_y, a_max=H)
            initial_angle = self.np_random.normal(loc=0., scale=np.pi / 3.)
        else:
            initial_x = self.np_random.uniform(0., W)
            initial_y = self.np_random.uniform(self.helipad_y, H)
            initial_angle = self.np_random.uniform(-np.pi / 2, np.pi / 2)

        self.lander = self.world.CreateDynamicBody(
            position=(initial_x, initial_y),
            angle=initial_angle,
            fixtures=fixtureDef(
                shape=polygonShape(vertices=[(x / SCALE, y / SCALE) for x, y in LANDER_POLY]),
                density=5.0,
                friction=0.1,
                categoryBits=0x0010,
                maskBits=0x001,  # collide only with ground
                restitution=0.0)  # 0.99 bouncy
        )
        self.lander.color1 = (0.5, 0.4, 0.9)
        self.lander.color2 = (0.3, 0.3, 0.5)
        self.lander.ApplyForceToCenter((
            self.np_random.uniform(-INITIAL_RANDOM, INITIAL_RANDOM),
            self.np_random.uniform(-INITIAL_RANDOM, INITIAL_RANDOM)
        ), True)

        self.legs = []
        for i in [-1, +1]:
            leg = self.world.CreateDynamicBody(
                position=(initial_x - i * LEG_AWAY / SCALE, initial_y),
                angle=(i * 0.05 + initial_angle),
                fixtures=fixtureDef(
                    shape=polygonShape(box=(LEG_W / SCALE, LEG_H / SCALE)),
                    density=1.0,
                    restitution=0.0,
                    categoryBits=0x0020,
                    maskBits=0x001)
            )
            leg.ground_contact = False
            leg.color1 = (0.5, 0.4, 0.9)
            leg.color2 = (0.3, 0.3, 0.5)
            rjd = revoluteJointDef(
                bodyA=self.lander,
                bodyB=leg,
                localAnchorA=(0, 0),
                localAnchorB=(i * LEG_AWAY / SCALE, LEG_DOWN / SCALE),
                enableMotor=True,
                enableLimit=True,
                maxMotorTorque=LEG_SPRING_TORQUE,
                motorSpeed=+0.3 * i  # low enough not to jump back into the sky
            )
            if i == -1:
                rjd.lowerAngle = +0.9 - 0.5  # The most esoteric numbers here, angled legs have freedom to travel within
                rjd.upperAngle = +0.9
            else:
                rjd.lowerAngle = -0.9
                rjd.upperAngle = -0.9 + 0.5
            leg.joint = self.world.CreateJoint(rjd)
            self.legs.append(leg)

        self.drawlist = [self.lander] + self.legs

        return self.step(np.array([0, 0]) if self.continuous else 0)[0]

class LunarLanderContinuousRandomInit(LunarLanderRandomInit):
    continuous = True

class LunarLanderNoRewardShaping(LunarLander):

    def step(self, action):
        prev_shaping = self.prev_shaping
        state, reward, done, d = super().step(action)
        shaping = self.prev_shaping
        if prev_shaping is not None:
            reward += prev_shaping - shaping
        return state, reward, done, d

class LunarLanderContinuousNoRewardShaping(LunarLanderNoRewardShaping):
    continuous = True

class LunarLanderRewardShapingAugmented(LunarLander):

    def __init__(self):
        super().__init__()
        self.observation_space = spaces.Box(-np.inf, np.inf, shape=(9,), dtype=np.float32)

    def step(self, action):
        state, reward, done, d = super().step(action)
        state = np.append(state, [self.prev_shaping * 1e-2], axis=-1)
        return state, reward, done, d

class LunarLanderContinuousRewardShapingAugmented(LunarLanderRewardShapingAugmented):
    continuous = True

class LunarLanderRandomInitRewardShapingAugmented(LunarLanderRandomInit, LunarLanderRewardShapingAugmented):
    def reset(self):
        return LunarLanderRandomInit.reset(self)

    def step(self, action):
        return super().step(action)

class LunarLanderRandomInitNoRewardShaping(LunarLanderRandomInit, LunarLanderNoRewardShaping):
    def reset(self):
        return LunarLanderRandomInit.reset(self)

    def step(self, action):
        return super().step(action)

class LunarLanderContinuousRandomInitNoRewardShaping(LunarLanderRandomInitNoRewardShaping):
    continuous = True

class LunarLanderContinuousRandomInitRewardShapingAugmented(LunarLanderRandomInitRewardShapingAugmented):
    continuous = True


# 1000이하ㅏ의 소수를 나열하기

counter = 0             # 나눗셈 카운트
ptr = 0                 # 이미 찾은 소수의 갯수
prime = [None] * 500    # 소수를 저장하는 배열

prime[ptr] = 2          # 2는 소수이기 때문에 초기값으로 설정
ptr += 1

for n in range(3, 1001, 2): #홀수만을 대상으로 설정
    for i in range(1, ptr): #이미 찾은 소수로 나눔
        counter += 1
        if n % prime[i] == 0:   #나누어 떨어지면 소수가 아님
            break
    else:
        prime[ptr] = n  # 소수로 배열에 등록
        ptr += 1

for i in range(ptr):
    print(prime[i])

print(f'나눗셈 횟수 {counter}')


import h5py
import os
import argparse

import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.gridspec as gridspec
import matplotlib.cm as cm
from matplotlib import rcParams

import numpy as np
import scipy as sp
from scipy import optimize
from scipy.constants import pi, c, mu_0
import scipy.fftpack as fft

rcParams.update({'figure.autolayout': True})
rcParams.update({"font.size": 9})

# parser = argparse.ArgumentParser()
# parser.add_argument("location")
# args = parser.parse_args()

core_radius = 125e-6
T = 293.0

# sim_location = os.path.join("C:\\PhD\\Experiments\\HISOL\\SPM to soliton regime\\simulation", args.location)
# os.chdir(sim_location)

# try:
#     sim_location = os.path.join("C:\\Users\\Setaou\\Documents\\PhD\\Experiments\\HISOL\\SPM to soliton regime\\simulation\\spectrogram", args.location + "\\ionONshockON")
#     os.chdir(sim_location)
# except:
#     print("No such dir? Wrong dir?")

# try:
#     gas = args.location[:2]
#     pressure_mbar = int(((args.location).split(gas))[1].split("mbar")[0])
#     τfwhm_fs = int(((args.location).split("mbar"))[1].split("fs")[0])
# except:
#     print("File names are not in the appropriate notation, soz...")

def chrng(x):
    return (2*pi*c)/x

def ρ(p, T, p0=1.0, T0=273.0):
  ρ = (p/p0)*(T0/T)
  return ρ

def n_gas(λ, gas, p, T):
    if gas == "Ar":
        B = [20332.29e-8, 34458.31e-8]
        C = [206.12e-6, 8.066e-3]
    elif gas == "Kr":
        B = [26102.88e-8, 56946.82e-8]
        C = [2.01e-6, 10.043e-3]
    χ = B[0]*(λ*1e6)**2/((λ*1e6)**2 - C[0]) + B[1]*(λ*1e6)**2/((λ*1e6)**2 - C[1])
    ngas = sp.sqrt(1.0 + ρ(p, T)*χ)
    return ngas

def χ3(gas, p, T):
    if gas == "Ar":
        χ3 = 4.0*23.5*3.43e-28
    elif gas == "Kr":
        χ3 = 4.0*64.0*3.43e-28
    χ3gas = ρ(p, T)*χ3
    return χ3gas

def β_capillary(ω, gas, p, core_radius, T):
    β = ω/c*sp.sqrt(n_gas(chrng(ω), gas, p, T)**2 - ((2.4048**2)*(c**2)/((core_radius**2)*ω**2)))
    return β

def β2(ω, gas, p, core_radius, T):
    h = 1e13
    return (β_capillary(ω+h, gas, p, core_radius, T)- 2*β_capillary(ω, gas, p, core_radius, T) + β_capillary(ω-h, gas, p, core_radius, T))/(h**2)

def λzd(ω, β2, gas, p, core_radius, T):
    return chrng(sp.optimize.brentq(β2, chrng(200e-9), chrng(2000e-9), args=(gas, p, core_radius, T)))*1e9

def τ0(τfwhm):
    return τfwhm/(2*sp.log(1 + sp.sqrt(2)))

def L_dis(p, τfwhm, λpump, gas, core_radius, T):
    return τ0(τfwhm)**2/abs(β2(chrng(λpump), gas, p, core_radius, T))

def P_peak(E, τfwhm):
    return 0.88*E/τfwhm

def γ(gas, p, core_radius, λpump, T):
    return (3/4)*(chrng(λpump)*mu_0*χ3(gas, p, T))/(0.48*sp.pi*core_radius**2*n_gas(λpump, gas, p, T)**2)

def L_nl(gas, p, E, τfwhm, core_radius, λpump, T):
    return 1/(γ(gas, p, core_radius, λpump, T)*P_peak(E, τfwhm))

def Nsol(gas, p, E, τfwhm, λpump, core_radius, T):
    return sp.sqrt(L_dis(p, τfwhm, λpump, gas, core_radius, T)/L_nl(gas, p, E, τfwhm, core_radius, λpump, T))

def field_envelope(E):
    Eω = sp.fft(E)
    Eω[len(E)//2+1:] = 0.0
    Et = 2.0*sp.ifft(Eω)
    return Et

def browse_sims():
    files = os.listdir()
    sim_filenames = []
    energies = []
    for file in files:
        if file[:2] == gas:
            sim_filenames.append(file)
            energy = float((file.split("E="))[1].split("e-")[0])
            energy_mag = int((file.split("e-"))[1].split("_0000")[0])
            energies.append(energy*10**(-energy_mag))
    N = len(sim_filenames)
    return sim_filenames, N, energies

def load_sim(filename):
    sim = h5py.File(filename, "r")
    #z = np.array(sim["Z"])
    ω = np.array(sim["W"])
    ω_pivot = len(ω)
    t = np.array(sim["T"])
    E = np.array(sim["E"])
    steps = E.shape[0]
    modes = E.shape[1]
    Et = np.zeros((steps, modes, len(t)))
    for step in range(0, steps):
        for mode in range(0, modes):
            Et[step, mode, :] = abs(field_envelope(E[step][mode][:]))**2
    Eω = np.zeros((steps, modes, ω_pivot))
    for step in range(0, steps):
        for mode in range(0, modes):
            Eω[step, mode, :] = sp.real(abs(sp.fft(E[step][mode][:])[:ω_pivot])**2)
    energy_in = np.array(sim["input_energies"])[0]
    energy_out = np.array(sim["stats_energy_m"])[-1,0]
    energy = np.array([energy_in, energy_out])
    pressure = sim["gas_pressure"][()]
    τfwhm = np.array(sim["input_fwhms"])[0]
    sim.close()
    #return z, ω, t, Eω, Et, energy, pressure, τfwhm, modes
    return ω, t, Eω, Et, energy, pressure, τfwhm, modes

def load_sim_prop(filename):
    sim = h5py.File(filename, "r")
    z = np.array(sim["Z"])
    ω = np.array(sim["W"])
    ω_pivot = len(ω)
    t = np.array(sim["T"])
    E = np.array(sim["E"])
    steps = E.shape[0]
    modes = E.shape[1]
    Et = np.zeros((steps, modes, len(t)), dtype=np.cdouble)
    for step in range(0, steps):
        for mode in range(0, modes):
            Et[step, mode, :] = field_envelope(E[step][mode][:])
    Eω = np.zeros((steps, modes, ω_pivot), dtype=np.cdouble)
    for step in range(0, steps):
        for mode in range(0, modes):
            Eω[step, mode, :] = sp.fft(E[step][mode][:])[:ω_pivot]
    stats = {}
    pressure = sim["gas_pressure"][()]
    stats["pressure"] = pressure
    energy_out = np.array(sim["stats_energy"])[-1]
    stats["output energy"] = energy_out
    energy_in = np.array(sim["input_energies"])[0]
    stats["input energy"] = energy_in
    ne = np.array(sim["stats_peak_Ne"])
    stats["free electron density"] = ne
    z_solver = np.array(sim["stats_z"])
    stats["z"] = z_solver
    stats["neutral gas density"] = sim["gas_N0"][()]
    #stats["t_fwhm_compression"] = sim["stats_fwhm_t"][-1]
    sim.close()
    return z, ω, t, Eω, Et, modes, stats
    # return z, ω, t, Et, modes, stats

def plot_zprop_with_ion(t_compression_ratio=16, ω_compression_ratio=1):
    sim_filenames, N, energies = browse_sims()
    z, ω, t, Eω, Et, modes, stats = load_sim_prop(sim_filenames[0])
    time = t[::t_compression_ratio]
    afreq = ω[::ω_compression_ratio]
    Etime = np.zeros((len(z), modes, len(t)//t_compression_ratio))
    Espec = np.zeros((len(z), modes, len(t)//(2*ω_compression_ratio) + 1))
    Espec_full = np.zeros((len(t)//(2*ω_compression_ratio) + 1))
    wl = chrng(afreq)*1e9
    wl[0] = 6e5
    modes_to_plot = int(input("How many modes do you want to plot? "))
    Eplot = float(input("What input energy do you want to plot? "))
    idx_plot = np.abs(np.asarray(energies) - Eplot).argmin()
    _, _, _, Eω, Et, _, stats = load_sim_prop(sim_filenames[idx_plot])
    for mode in range(0, modes_to_plot):
        Etime[:, mode, :] = Et[:,mode,::t_compression_ratio]/Et[:,mode,::t_compression_ratio].max()
        Espec[:, mode, :] = Eω[:,mode,::ω_compression_ratio]/Eω[:,0,::ω_compression_ratio].max()
    #Espec_full = 10*np.log10(np.sum(Espec, axis=0))
    Espec = 10*np.log10(Espec)
    #Nsim = Nsol(gas, pressure, energies[:idx_lim,0], τfwhm, 800e-9, core_radius, T)
    fig = plt.figure(dpi=300)
    gs = gridspec.GridSpec(1, 3, width_ratios=[2, 2, 1], wspace=0.1, hspace=0.1, left=0.11, right=0.92, bottom=0.15, top=0.98)
    plt.rcParams.update({"font.size": 9})
    for mode in range(0, modes+1):
        if mode < modes:
            if mode == 0:
                ax = fig.add_subplot(gs[0])
                #plt.title("Propagation simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE1" + str(mode+1))
                #plt.pcolormesh(wl, Nsim, Espec[:idx_lim,mode,:], vmin=-30)
                ax.pcolormesh(afreq*1e-15, z, Espec[:, mode, :], vmin=-30, rasterized=True)
                ax.set_xlim(chrng(2500e-9)*1e-15, chrng(270e-9)*1e-15)
                ax.set_xlabel("Angular frequency [PHz]")
                #plt.ylabel("Soliton order")
                ax.set_ylabel("Propagation distance [m]")
                #plt.axvline(x=λzd(afreq, β2, gas, pressure, core_radius, T), color="white", linestyle="--")
            # else:
            #     plt.figure(dpi=250)
            #     plt.title("Energy scan spectrum simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE1" + str(mode+1))
            #     plt.pcolormesh(wl, energies[:,0]*1e6, Espec[:,mode,:], vmin=-30)
            #     plt.xlim(200, 1600)
            #     plt.xlabel("Wavelength [nm]")
            #     plt.ylabel("Soliton order")
        # else:
        #     plt.figure(dpi=250)
        #     plt.title("Energy scan spectrum simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, " + str(modes_to_plot) + " modes")
        #     plt.pcolormesh(wl, z, Espec_full, vmin=-30)
        #     plt.xlim(200, 1600)
        #     plt.xlabel("Wavelength [nm]")
            # plt.ylabel("Soliton order")
    bx = fig.add_subplot(gs[1])
    # plt.title("Energy scan time simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE11")
    bx.pcolormesh(time*1e15, z, Etime[:, 0, :], rasterized=True)
    bx.set_xlim(-15, 50)
    bx.set_yticks([], [])
    bx.set_xlabel("Time [fs]")
    cx = fig.add_subplot(gs[2])
    cx.plot(stats["free electron density"]/stats["neutral gas density"]*100, stats["z"], color=cm.viridis(0), linewidth=1.0)
    #plt.set_yticks([], [])
    cx.set_xlabel("Ionization fraction [%]")
    cx.set_yticks([], [])
    cx.set_ylim(0, 3)
    #cx.set_xlim(0, 4)
#     # plt.ylabel("Soliton order")
#     # x = np.linspace(0, energies[:idx_lim,0].max()*1e6, 200)
#     # straight_line_x = 0.64*x
#     # marker_colour = cm.viridis(0)
#     # plt.figure(dpi=250)
#     # plt.title("Energy scan energy simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE11")
#     # plt.plot(energies[:idx_lim,0]*1e6, energies[:idx_lim,1]*1e6, "o", markersize=3, color=marker_colour, label="Output energy")
#     # plt.plot(x, straight_line_x, "--k", linewidth=1.0, label="Linear output")
#     # plt.xlabel("Input energy [μJ]")
#     # plt.ylabel("Output energy [μJ]")
#     # plt.legend()

def plot_zprop(filename, t_compression_ratio=16, ω_compression_ratio=1):
    z, ω, t, Eω, Et, modes, stats = load_sim_prop(filename)
    fig = plt.figure(dpi=300)
    gs = gridspec.GridSpec(1, 2, width_ratios=[1, 1], wspace=0.1, hspace=0.1, left=0.11, right=0.92, bottom=0.15, top=0.98)
    plt.rcParams.update({"font.size": 9})
    ax = fig.add_subplot(gs[0])
    #plt.title("Propagation simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE1" + str(mode+1))
    #plt.pcolormesh(wl, Nsim, Espec[:idx_lim,mode,:], vmin=-30)
    ax.pcolormesh(ω[::ω_compression_ratio]*1e-15, z, 10*np.log10(abs(Eω[:, 0, ::ω_compression_ratio])**2/abs(Eω[:, 0, ::ω_compression_ratio].max())**2), vmin=-30, rasterized=True)
    ax.set_xlim(0.1, 6)
    ax.set_xlabel("Angular frequency (rad/fs)")
    #plt.ylabel("Soliton order")
    ax.set_ylabel("Propagation distance (m)")
    ax.axvline(x=chrng(λzd(ω, β2, "Ar", 467e-3, core_radius, T)*1e-9)*1e-15, color="white", linestyle="--")
    bx = fig.add_subplot(gs[1])
    # plt.title("Energy scan time simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE11")
    bx.pcolormesh(t[::t_compression_ratio]*1e15, z, abs(Et[:, 0, ::t_compression_ratio])**2, vmin=-30, rasterized=True)
    bx.set_xlim(-70, 150)
    bx.set_xticks([-50, 0, 50, 100, 150])
    bx.set_yticks([], [])
    bx.set_xlabel("Time (fs)")

def plot_escan(t_compression_ratio=16, ω_compression_ratio=1):
    sim_filenames, N, _ = browse_sims()
    ω, t, Eω, Et, energy, pressure, τfwhm, modes = load_sim(sim_filenames[0])
    time = t[::t_compression_ratio]
    afreq = ω[::ω_compression_ratio]
    Etime = np.zeros((N, modes, len(t)//t_compression_ratio))
    Espec = np.zeros((N, modes, len(t)//(2*ω_compression_ratio) + 1))
    Espec_full = np.zeros((N, len(t)//(2*ω_compression_ratio) + 1))
    energies = np.zeros((N, len(energy)))
    wl = chrng(afreq)*1e9
    wl[0] = 6e5
    modes_to_plot = int(input("How many modes do you want to plot? "))
    Elim = float(input("Up to what input energy do you want to plot? "))
    for idx, file in enumerate(sim_filenames):
        _, _, Eω, Et, energy, _, _, _ = load_sim(file)
        for mode in range(0, modes_to_plot):
            energies[idx] = energy
            Etime[idx,mode,:] = Et[-1,mode,::t_compression_ratio]/Et[-1,mode,::t_compression_ratio].max()
            Espec[idx,mode,:] = Eω[-1,mode,::ω_compression_ratio]/Eω[-1,0,::ω_compression_ratio].max()
        Espec_full[idx,:] = 10*np.log10(np.sum(Espec[idx], axis=0))
    Espec = 10*np.log10(Espec)
    idx_lim = np.abs(energies[:,0] - Elim).argmin()
    Nsim = Nsol(gas, pressure, energies[:idx_lim,0], τfwhm, 800e-9, core_radius, T)
    for mode in range(0, modes+1):
        if mode < modes:
            if mode == 0:
                plt.figure(dpi=200)
                plt.title("Energy scan spectrum simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE1" + str(mode+1))
                #plt.pcolormesh(wl, Nsim, Espec[:idx_lim,mode,:], vmin=-30)
                plt.pcolormesh(wl, energies[:idx_lim,0]*1e6, Espec[:idx_lim,mode,:], vmin=-30)
                plt.xlim(120, 1600)
                plt.xlabel("Wavelength [nm]")
                #plt.ylabel("Soliton order")
                plt.ylabel("Input energy [μJ]")
                plt.axvline(x=λzd(afreq, β2, gas, pressure, core_radius, T), color="white", linestyle="--")
            # else:
            #     plt.figure(dpi=250)
            #     plt.title("Energy scan spectrum simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE1" + str(mode+1))
            #     plt.pcolormesh(wl, energies[:,0]*1e6, Espec[:,mode,:], vmin=-30)
            #     plt.xlim(200, 1600)
            #     plt.xlabel("Wavelength [nm]")
            #     plt.ylabel("Soliton order")
        else:
            plt.figure(dpi=200)
            plt.title("Energy scan spectrum simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, " + str(modes_to_plot) + " modes")
            plt.pcolormesh(wl, energies[:idx_lim,0]*1e6, Espec_full[:idx_lim,:], vmin=-30)
            # plt.pcolormesh(wl, Nsim, Espec_full[:idx_lim,:], vmin=-30)
            plt.xlim(120, 1600)
            plt.xlabel("Wavelength [nm]")
            # plt.ylabel("Soliton order")
            plt.ylabel("Input energy [μJ]")
    plt.figure(dpi=200)
    plt.title("Energy scan time simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE11")
    # plt.pcolormesh(time*1e15, Nsim, Etime[:idx_lim,0,:])
    plt.pcolormesh(time*1e15, energies[:idx_lim,0]*1e6, Etime[:idx_lim,0,:])
    plt.xlim(-25, 50)
    plt.xlabel("Time [fs]")
    # plt.ylabel("Soliton order")
    plt.ylabel("Input energy [μJ]")
    x = np.linspace(0, energies[:idx_lim,0].max()*1e6, 200)
    straight_line_x = 0.64*x
    marker_colour = cm.viridis(0)
    plt.figure(dpi=200)
    plt.title("Energy scan energy simulation: " + str(τfwhm_fs) + " fs pulses, " + str(pressure_mbar) + " mbar Ar, mode HE11")
    plt.plot(energies[:idx_lim,0]*1e6, energies[:idx_lim,1]*1e6, "o", markersize=3, color=marker_colour, label="Output energy")
    plt.plot(x, straight_line_x, "--k", linewidth=1.0, label="Linear output")
    plt.xlabel("Input energy [μJ]")
    plt.ylabel("Output energy [μJ]")
    plt.legend()

def plot_1spec(filename):
    # sim_filenames, N, energies = browse_sims()
    # Eplot = float(input("What input energy do you want to plot? "))
    # idx_plot = np.abs(np.asarray(energies) - Eplot).argmin()
    # ω, t, Eω, Et, _, pressure, _, _ = load_sim(sim_filenames[idx_plot])
    ω, t, Eω, Et, _, pressure, _, _ = load_sim(filename)
    wl = chrng(ω)*1e9
    wl[0] = 6e5
    plt.figure(dpi=200)
    colour = cm.viridis(0)
    plt.plot(ω*1e-15, Eω[-1, 0, :]/Eω[-1, 0, :].max(0), color=colour, label=str(int(Eplot*1e6))+ " μJ")
    plt.axvline(x=chrng(λzd(ω, β2, gas, pressure, core_radius, T)*1e-9)*1e-15, color="black", linestyle="--")
    plt.xlim(0, 10)
    plt.xlabel("Angular frequency [PHz]")
    plt.ylim(0, 1.1)
    plt.ylabel("SPD [a.u.]")
    plt.legend()
    plt.figure(dpi=200)
    plt.plot(wl, (Eω[-1, 0, :]*ω**2/c)/(Eω[-1, 0, :]*ω**2/c).max(0), color=colour, label=str(int(Eplot*1e6))+ " μJ")
    plt.axvline(x=λzd(ω, β2, gas, pressure, core_radius, T), color="black", linestyle="--")
    plt.xlim(120, 2500)
    plt.xlabel("Wavelength [nm]")
    plt.ylim(0, 1.1)
    plt.ylabel("SPD [a.u.]")
    plt.legend()

def plot_filtered2(filename, λ0IR, ΔλIR, λ0VIS, ΔλVIS, supergauss_power, plot_filtered=True):
    def gauss_filter(x, x0, σ, supergauss_power):
        return sp.exp(-0.5*((x-x0)/σ)**supergauss_power)
    def chΔλ(Δλ, λ0):
        return (c/λ0**2)*Δλ
    z, ω, t, Eω, Et, _, _ = load_sim_prop(filename)
    # stats: "pressure", "output energy", "input energy", "free electron density", "z", "neutral gas density"
    # # wl = chrng(ω)*1e9
    # # wl[0] = 6e5
    Nt = len(t)
    T = Nt//2-1
    Nz = len(z)
    Nw = len(ω)
    gaussIR = np.zeros(Nt)
    gaussIR[T:] = gauss_filter(ω, chrng(λ0IR), chΔλ(ΔλIR, λ0IR), supergauss_power)
    gaussVIS = np.zeros(Nt)
    gaussVIS[T:] = gauss_filter(ω, chrng(λ0VIS), chΔλ(ΔλVIS, λ0VIS), supergauss_power)
    filteredEωIR = np.zeros((Nz, Nt), dtype=np.cdouble)
    filteredEωIRprop = np.zeros((Nz, Nw))
    filteredEtIR = np.zeros((Nz, Nt))
    ###### here this array if of real values only, because otherwise the printing complains; if I need phase I need to change it
    filteredEωVIS = np.zeros((Nz, Nt), dtype=np.cdouble)
    filteredEωVISprop = np.zeros((Nz, Nw))
    filteredEtVIS = np.zeros((Nz, Nt))
    for step in range(0, len(z)):
        filteredEωIR[step, T:] = gaussIR[T:]*Eω[step, 0, :]
        filteredEωIRprop[step, :] = abs(filteredEωIR[step, T:]/filteredEωIR[0, T:].max())**2
        filteredEtIR[step, :] = abs(2.0*sp.ifft(filteredEωIR[step, :]))**2
        filteredEωVIS[step, T:] = gaussVIS[T:]*Eω[step, 0, :]
        filteredEωVISprop[step, :] = abs(filteredEωVIS[step, T:]/filteredEωVIS[0, T:].max())**2
        filteredEtVIS[step, :] = abs(2.0*sp.ifft(filteredEωVIS[step, :]))**2
    colour = cm.viridis(0)
    colourIR = cm.viridis(100)
    colourVIS = cm.viridis(200)
    colourUV = cm.viridis(300)
    if plot_filtered == True:
        filteredEωIR = gaussIR[T:]*(Eω[-1, 0, :]/Eω[-1, 0, :].max())
        filteredEωVIS = gaussVIS[T:]*(Eω[-1, 0, :]/Eω[-1, 0, :].max())
        plt.figure(dpi=200)
        plt.plot(ω*1e-15, abs((Eω[-1, 0, :]))**2/(abs(Eω[-1, 0, :])**2).max(), color=colour, label="Full time")
        #plt.plot(ω*1e-15, abs(filteredEωIR)**2, color=colourIR, linestyle="--", label="Filtered IR")
        #plt.plot(ω*1e-15, abs(filteredEωVIS)**2, color=colourVIS, linestyle="--", label="Filtered VIS")
        plt.xlabel("Ang. frequency (rad/fs)")
        plt.ylabel("SPD (a.u.)")
        plt.axvline(x=2.35, color="black", linestyle="--")
        plt.xlim(0.1, 7)
    else:
        plt.figure(dpi=200)
        plt.plot(t*1e15, 1e-9*abs(Et[-1, 0, :])**2, color=colour, label="Full time")
        plt.plot(t*1e15, filteredEtIR[-1, :]*1e-9, color=colourIR, label="Filtered IR")
        plt.plot(t*1e15, filteredEtVIS[-1, :]*1e-9, color=colourVIS, label="Filtered VIS")
        plt.xlim(-30, 50)
        plt.xlabel("Time (fs)")
        plt.ylabel("Power (GW)")
        plt.legend()
    plt.show()

def plot_filtered(filename, λ0IR, ΔλIR, λ0VIS, ΔλVIS, λ0UV, ΔλUV, supergauss_power, plot_filtered=True):
    def gauss_filter(x, x0, σ, supergauss_power):
        return sp.exp(-0.5*((x-x0)/σ)**supergauss_power)
    def chΔλ(Δλ, λ0):
        return (c/λ0**2)*Δλ
    z, ω, t, Eω, Et, _, _ = load_sim_prop(filename)
    # stats: "pressure", "output energy", "input energy", "free electron density", "z", "neutral gas density"
    # # wl = chrng(ω)*1e9
    # # wl[0] = 6e5
    Nt = len(t)
    T = Nt//2-1
    Nz = len(z)
    Nw = len(ω)
    gaussIR = np.zeros(Nt)
    gaussIR[T:] = gauss_filter(ω, chrng(λ0IR), chΔλ(ΔλIR, λ0IR), supergauss_power)
    gaussVIS = np.zeros(Nt)
    gaussVIS[T:] = gauss_filter(ω, chrng(λ0VIS), chΔλ(ΔλVIS, λ0VIS), supergauss_power)
    gaussUV = np.zeros(Nt)
    gaussUV[T:] = gauss_filter(ω, chrng(λ0UV), chΔλ(ΔλUV, λ0UV), supergauss_power)
    filteredEωIR = np.zeros((Nz, Nt), dtype=np.cdouble)
    filteredEωIRprop = np.zeros((Nz, Nw))
    filteredEtIR = np.zeros((Nz, Nt))
    ###### here this array if of real values only, because otherwise the printing complains; if I need phase I need to change it
    filteredEωVIS = np.zeros((Nz, Nt), dtype=np.cdouble)
    filteredEωVISprop = np.zeros((Nz, Nw))
    filteredEtVIS = np.zeros((Nz, Nt))
    filteredEωUV = np.zeros((Nz, Nt), dtype=np.cdouble)
    filteredEωUVprop = np.zeros((Nz, Nw))
    filteredEtUV = np.zeros((Nz, Nt))
    maxIR = np.zeros((Nz))
    maxUV = np.zeros((Nz))
    energyIR = np.zeros((Nz))
    energyUV = np.zeros((Nz))
    for step in range(0, len(z)):
        filteredEωIR[step, T:] = gaussIR[T:]*Eω[step, 0, :]
        filteredEωIRprop[step, :] = abs(filteredEωIR[step, T:]/filteredEωIR[0, T:].max())**2
        maxIRidx = np.where(filteredEωIR[step, T:] == filteredEωIR[step, T:].max())
        maxIR[step] = ω[maxIRidx[0]]
        filteredEtIR[step, :] = abs(sp.ifft(filteredEωIR[step, :]))**2
        energyIR[step] = np.trapz(filteredEtIR[step, :], t)
        filteredEωVIS[step, T:] = gaussVIS[T:]*Eω[step, 0, :]
        filteredEωVISprop[step, :] = abs(filteredEωVIS[step, T:]/filteredEωVIS[0, T:].max())**2
        filteredEtVIS[step, :] = abs(2.0*sp.ifft(filteredEωVIS[step, :]))**2
        filteredEωUV[step, T:] = gaussUV[T:]*Eω[step, 0, :]
        filteredEωUVprop[step, :] = abs(filteredEωUV[step, T:]/filteredEωIR[0, T:].max())**2
        maxUVidx = np.where(filteredEωUV[step, T:] == filteredEωUV[step, T:].max())
        maxUV[step] = ω[maxUVidx[0]]
        filteredEtUV[step, :] = abs(2.0*sp.ifft(filteredEωUV[step, :]))**2
        energyUV[step] = np.trapz(filteredEtUV[step, :], t)
    colour = cm.viridis(0)
    colourIR = cm.viridis(100)
    colourVIS = cm.viridis(200)
    colourUV = cm.viridis(300)
    if plot_filtered == True:
        filteredEωIR = gaussIR[T:]*(Eω[-1, 0, :]/Eω[-1, 0, :].max())
        filteredEωVIS = gaussVIS[T:]*(Eω[-1, 0, :]/Eω[-1, 0, :].max())
        filteredEωUV = gaussUV[T:]*(Eω[-1, 0, :]/Eω[-1, 0, :].max())
        plt.figure(dpi=200)
        plt.plot(ω*1e-15, Eω[-1, 0, :]/Eω[-1, 0, :].max(), color=colour, label="Full time")
        plt.plot(ω*1e-15, filteredEωIR, color=colourIR, linestyle="--", label="Filtered IR")
        plt.plot(ω*1e-15, filteredEωVIS, color=colourVIS, linestyle="--", label="Filtered VIS")
        plt.plot(ω*1e-15, filteredEωUV, color=colourUV, linestyle="--", label="Filtered UV")
        plt.axvline(x=λzd(ω, β2, "Ar", 467e-3, core_radius, T), color="black", linestyle="--")
        plt.xlim(0.1, 8)
        plt.ylim(0, 1.1)
        plt.legend()
    else:
        plt.figure(dpi=200)
        plt.plot(chrng(ω)*1e9, Eω[-1, 0, :]/Eω[-1, 0, :].max(), color=colour)
        plt.axvline(x=λzd(ω, β2, "Ar", 467e-3, core_radius, T), color="black", linestyle="--")
        # plt.figure(dpi=200)
        # plt.subplot(1,2,1)
        # plt.plot(z, chrng(maxIR)*1e9, "ro", label="IR")
        # plt.plot(z, chrng(maxUV)*1e9, "ko", label="UV")
        # plt.legend()
        # plt.subplot(1,2,2)
        # plt.plot(z, energyIR*1e6, "ro", label="IR")
        # plt.plot(z, energyUV*1e6, "ko", label="UV")
        # plt.legend()
        # plt.figure(dpi=200)
        # plt.subplot(2,3,1)
        # plt.title("Filtered IR - spectrum")
        # filteredEωIRproplog = 10*np.log10(filteredEωIRprop)
        # filteredEωIRproplog[np.isinf(filteredEωIRproplog)] = -30
        # plt.pcolormesh(ω*1e-15, z, filteredEωIRproplog, vmin=-30, rasterized=True)
        # plt.xlim(0.1, 7)
        # plt.xlabel("Ang. frequency (rad/fs)")
        # plt.ylabel("Propagation distance (m)")
        # #plt.figure(dpi=200)
        # plt.subplot(2,3,4)
        # plt.title("Filtered IR - time")
        # plt.pcolormesh(t*1e15, z, filteredEtIR, rasterized=True)
        # plt.xlim(-25, 150)
        # plt.xlabel("Time (fs)")
        # plt.ylabel("Propagation distance (m)")
        # #plt.figure(dpi=200)
        # plt.subplot(2,3,2)
        # plt.title("Filtered VIS - spectrum")
        # filteredEωVISproplog = 10*np.log10(filteredEωVISprop)
        # filteredEωVISproplog[np.isinf(filteredEωVISproplog)] = -30
        # plt.pcolormesh(ω*1e-15, z, filteredEωVISproplog, vmin=-30, rasterized=True)
        # plt.xlim(0.1, 7)
        # plt.xlabel("Ang. frequency (rad/fs)")
        # plt.ylabel("Propagation distance (m)")
        # #plt.figure(dpi=200)
        # plt.subplot(2,3,5)
        # plt.title("Filtered VIS - time")
        # plt.pcolormesh(t*1e15, z, filteredEtVIS, rasterized=True)
        # plt.xlim(-25, 150)
        # plt.xlabel("Time [fs]")
        # plt.ylabel("Propagation distance (m)")
        # #plt.figure(dpi=200)
        # plt.subplot(2,3,3)
        # plt.title("Filtered UV - spectrum")
        # filteredEωUVproplog = 10*np.log10(filteredEωUVprop)
        # filteredEωUVproplog[np.isinf(filteredEωUVproplog)] = -30
        # plt.pcolormesh(ω*1e-15, z, filteredEωUVproplog, vmin=-30, vmax=0, rasterized=True)
        # plt.xlim(0.1, 7)
        # plt.xlabel("Ang. frequency (rad/fs)")
        # plt.ylabel("Propagation distance (m)")
        # plt.colorbar()
        # #plt.figure(dpi=200)
        # plt.subplot(2,3,6)
        # plt.title("Filtered UV - time")
        # plt.pcolormesh(t*1e15, z, filteredEtUV, rasterized=True)
        # plt.xlim(-25, 150)
        # plt.xlabel("Time (fs)")
        # plt.ylabel("Propagation distance (m)")
        # plt.colorbar()
    plt.show()

#plot_1spec()
#plot_filtered("Ar467mbar10fs170uJ.h5", 1250e-9, 5000e-9, 550e-9, 1100e-9, 200e-9, 650e-9, 10, False)
plot_filtered2("Ar467mbar_i0000000017_E=3.50854271e-05_0000.h5", 1320e-9, 5000e-9, 570e-9, 1100e-9, 30, True)
#plot_escan(8, 4)
#plot_zprop("collision.h5", 1, 4)

plt.show()


# -*- coding: utf-8 -*-
"""
Created on Wed Apr  6 11:42:29 2022

@author: Fede
"""
from sklearn import tree, metrics
from sklearn.metrics import accuracy_score, precision_score, confusion_matrix
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sn
import joblib

# Cargo datos
df = pd.read_excel(r"C:\Users\fede_\OneDrive\Escritorio\clientes robo advisor2.xlsx")
df_datos = df.drop(["Resultado del perfil"], axis=1)
df_target = df["Resultado del perfil"]

# Invoco a la librería train_test_split para partir el dataset
X_train, X_test, Y_train, Y_test = train_test_split(df_datos, df_target,test_size=0.3, random_state=0)
print(X_train)

# Selecciono el algoritmo para clasificar los datos
clf = tree.DecisionTreeClassifier(max_depth=9, random_state=42)

# Procedo a entrenarlo
clf.fit(X_train, Y_train)

# Obtengo las predicciones
y_pred = clf.predict(X_test)

# Grafico
plt.figure(figsize=(15,10))
tree.plot_tree(clf)
plt.title("Arbol de decisión")
plt.savefig("Arbol de decisión.png")
plt.show()

# Matriz de confusion
matriz = confusion_matrix(Y_test, y_pred)
print('\n- Matriz de Confusión -')
sn.heatmap(matriz, annot=True)

# Metricas
print("Acuracy:", accuracy_score(Y_test, y_pred))
print("Precision:", precision_score(Y_test, y_pred,average='weighted'))
print("Recall" , metrics.recall_score(Y_test,y_pred,average='weighted'))
print(metrics.classification_report(Y_test, y_pred))
plt.show()

#Guardo el modelo
joblib.dump(clf, "arbol_roboAdvisor.pkl")


import csv
import os

# The data we neeed to retrieve

# Assign a variable for the file to load and the path
file_to_load = os.path.join("Resources","election_results.csv")

# Assign filename variable for indirect path to the write file
file_to_save = os.path.join("analysis", "election_analysis.txt")

# Create a vote counter
total_votes = 0

# Create list of the candidate's names
candidate_options = []

# Create dictionary to hold count for each option
candidate_votes = {}

# We Have a Winner! - Create variables for winning candidate along with vote count and % of total
winner = ""
winning_count = 0
winning_per = 0

# Open the results file in read mode
with open(file_to_load) as election_data:

#   #To Do: analysis and all the fun stuff
    file_reader = csv.reader(election_data)

    # Print the Header row
    headers = next(file_reader)

    #Print each row in CSV file
    for row in file_reader:
        # Add to the total vote count

        total_votes += 1

        # Print the candidate's name from 3rd column
        candidate_name = row[2]

        # # Add canidate names found to the list
        # candidate_options.append(candidate_name)

        # Only add name to list if it is not already found on list
        if candidate_name not in candidate_options:
            candidate_options.append(candidate_name)

            # Set the candidate's vote count to 0
            candidate_votes[candidate_name] = 0

         # Add a vote to candidate count.
        candidate_votes[candidate_name] += 1

# Save Results to a txt file
with open(file_to_save, "w") as txt_file:
        # Create election results vari
    election_results = (
        f"\nElection Results\n"
        f"-----------------------\n"
        f"Total Votes Cast: {total_votes}\n"
        f"-----------------------\n")

    print(election_results, end ="")

    # After printing in terminal save to txt file
    txt_file.write(election_results)

        # # Results for each candidate
        #     winning_candidate_summary = (
        #     f"-------------------------\n"
        #     f"Winner: {winner}\n"
        #     f"Winning Vote Count: {winning_count:,}\n"
        #     f"Winning Percentage: {winning_per:.1f}%\n"
        #     f"-------------------------\n")
        # #  print(winning_candidate_summary)

        # #  # # Save the final vote count to txt
        # #  txt_file.write(election_results)
        # #  # txt_file.write(candidate_results)
        # #  txt_file.write(winning_candidate_summary)

# with open(file_to_save, "w") as txt_file:
    # Calculate the % of votes for each candidate using a loop to count
    # 1 Iterate through the list
    for candidate_name in candidate_votes:
        # Get Vote Count
        votes = candidate_votes[candidate_name]

        # Calculate the percentage
        vote_percentage = float(votes) / float(total_votes) * 100

        candidate_results = (
            f"{candidate_name}: {vote_percentage:.1f}% ({votes:,})\n")

        # Print each candidate, their voter count, and percentage to the terminal.
        print(candidate_results)

        #  Save the candidate results to our text file.
        txt_file.write(candidate_results)
         # # Save the final vote count to txt
        # txt_file.write(election_results)
        # #      # txt_file.write(candidate_results)
        # # txt_file.write(winning_candidate_summary)

        # print(f"{candidate_name}: {vote_percentage:.1f}%  ({votes:,})\n")

        # Determin winner and winning count
        # check if the votes are greater than the winning count
        if (votes > winning_count) and (vote_percentage > winning_per):
            # If True set winning count equal to votes and vote % = winning %
            winning_count = votes
            winning_per = vote_percentage

            # Set winner to candidate name
            winner = candidate_name
    # candidate_results = (f"{candidate_name}: received {vote_percentage:.1f}% of the toal votes cast.")

    # Output winner's info
    winner_summary =(
        f"-----------------------\n"
        f"And the winner is: {winner}!\n"
        f"Who received {winning_count} votes\n"
        f"{winning_count} votes is {winning_per:.1f}% of the total cast\n"
        f"------------------------\n")
    print(winner_summary)
    # Save this summary to txt file
    txt_file.write(winner_summary)

        # # Print the candidate's name and the % of total vote each received

    # #Print the total votes
    # print(candidate_votes)

        # # Print each row of the ED file
        # for row in file_reader:
        #     print(row)

    # # Opening output file in write mode
    # with open(file_to_save, "w") as txt_file:

    # # # Write some test data into file
    # # txt_file.write(""Hello World")

    #     # Writing county names to file
    #     txt_file.write("Counties in the Election\n------------------------\n")
    #     txt_file.write("Arapahoe\n")
    #     txt_file.write("Denver\n")
    #     txt_file.write("Jefferson")

    # # # Close output file
    # # txt_file.close()

    # #1 The total number of votes cast
    # #2 A complete list of canidates who recieved votes
    # #3 The percentage of votes each canidate won
    # #4 The total number of votes each canidate won
    # #5 The winner of the elction based on the popular vote

    # # Close the file
    # # election_data.close()


# http://www.labri.fr/perso/nrougier/teaching/numpy.100/

import numpy as np

Z = np.zeros((10, 10), [('x', float), ('y', float)])
Z['x'], Z['y'] = np.meshgrid(np.linspace(0, 1, 10),
                             np.linspace(0, 1, 10))
#
# l = globals().copy()
# for v in l:
#     print ("'" + v + "'" + ": instance_of_class_name(\"" + type(l[v]).__name__ + "\"),")


import rclpy
from rclpy.node import Node
from std_msgs.msg import String
import os
import speech_recognition as sr
from gtts import gTTS
import threading
from dexhand_llm_control.openai_session import OpenAISession
import json

class LLMControlNode(Node):
    def __init__(self):
        super().__init__('llm_control')

        # Retreive the OpenAI key from the environment
        openai_key = os.environ.get('OPENAI_API_KEY')
        if openai_key is None:
            self.get_logger().error('OPENAI_API_KEY environment variable not set. Cannot continue.')
            exit(1)
        self.openai_session = OpenAISession(openai_key, self.get_logger())

        # Default publishers for hand
        self.extension_publisher = self.create_publisher(String, 'dexhand_finger_extension', 10)
        self.gesture_publisher = self.create_publisher(String, 'dexhand_gesture', 10)

        # Set up speech recognition
        self.recognizer = sr.Recognizer()

        # List the microphones - see if we can find a Respeaker
        self.microphone_index = 0  # Default to built in microphone
        for index, name in enumerate(sr.Microphone.list_microphone_names()):
            self.get_logger().debug("Microphone with name \"{1}\" found for `Microphone(device_index={0})`".format(index, name))
            if (name.lower().find("respeaker") != -1):
                self.microphone_index = index
                self.get_logger().info("Respeaker detected - Using microphone with name \"{1}\" for `Microphone(device_index={0})`".format(index, name))
                break

        self.get_logger().info("Using microphone with index {0} named {1}".format(self.microphone_index, sr.Microphone.list_microphone_names()[self.microphone_index]))
        self.microphone = sr.Microphone(device_index=self.microphone_index)
        self.recognizer.energy_threshold = 4000
        with self.microphone as source:
            self.recognizer.adjust_for_ambient_noise(self.microphone)

        # Start audio processing loop in a thread
        self.audio_thread = threading.Thread(target=self.message_processing_loop)
        self.audio_thread.start()

    # Basic wrapper for Google Text to Speech. Takes a string, speaks it, and then deletes the file.
    def textToSpeech(self, text):
        tts = gTTS(text=text, lang='en')
        tts.save("speech.mp3")
        os.system("mpg123 speech.mp3")
        os.remove("speech.mp3")

    # Takes the JSON response from OpenAI and formats it into a command for the hand
    def formatROSMessages(self, jsonmessage):

        # Publish a dexhand_gesture message to return to base pose
        msg = String()
        msg.data = "reset"
        self.gesture_publisher.publish(msg)

        # Is this a gesture or a finger message?
        if "gesture" in jsonmessage:
            msg = String()
            msg.data = jsonmessage["gesture"]
            self.gesture_publisher.publish(msg)

            self._logger.debug("Published dexhand_gesture message: {0}".format(msg.data))
        else:
            # Convert each finger to a dexhand_finger_extension message and publish it
            for finger, value in jsonmessage.items():
                msg = String()
                msg.data = "{0}:{1}".format(finger, value)
                self.extension_publisher.publish(msg)

                self._logger.debug("Published dexhand_finger_extension message: {0}".format(msg.data))

    # This is our main message processor that records audio from the user and
    # attempts to process it with OpenAI. It runs in a thread.
    def message_processing_loop(self):
        while rclpy.ok():
            with self.microphone as source:
                self.get_logger().info('Ready for audio input')
                audio = self.recognizer.listen(source)

                try:
                    # for testing purposes, we're just using the default API key
                    # to use another API key, use `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")`
                    # instead of `r.recognize_google(audio)`
                    query = self.recognizer.recognize_google(audio)

                    # We have a few special commands that we handle here without needing AI

                    # Reset the hand
                    if query == "reset hand":
                        self.get_logger().info('Resetting hand')
                        msg = String()
                        msg.data = "reset"
                        self.gesture_publisher.publish(msg)
                        continue

                    # Reset the context
                    if query == "reset context":
                        self.get_logger().info('Resetting context')
                        self.openai_session.resetContext()
                        msg = String()
                        msg.data = "reset"
                        self.gesture_publisher.publish(msg)

                        continue

                    # Send the query to OpenAI
                    jsonmessage,textmessage = self.openai_session.processPrompt(query)

                    # If the we received a jsonmessage, we format that into a command and send it to the hand
                    if jsonmessage is not None:
                        self.get_logger().info('Sending to DexHand: "%s"' % jsonmessage)
                        self.formatROSMessages(json.loads(jsonmessage))

                    # If we received a text message, we just speak it
                    if textmessage is not None:
                        self.get_logger().info('Speaking to user: "%s"' % textmessage)
                        self.textToSpeech(textmessage)

                except sr.UnknownValueError:
                    print("Google Speech Recognition could not understand audio")
                    #self.textToSpeech("I'm sorry, I didn't understand that. Try again.")

                except sr.RequestError as e:
                    print("Could not request results from Google Speech Recognition service; {0}".format(e))
                    self.textToSpeech("I'm sorry, there is an error with Google Speech Recognition.")

def main(args=None):
    rclpy.init(args=args)
    dexhand_node = LLMControlNode()
    rclpy.spin(dexhand_node)
    dexhand_node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()


#!/usr/bin/env python3

# ChimeraCheck is designed to screen CDS of annotated transcripts for evidence of a shitty assembly.
# It looks for coverage anomalies.

# Additional software necessary to run this:
# (1) bwa
# (2) GATK
# (3) bedtools

# The input required includes:
# (1) a fasta file of the contigs to annotate
# (2) a fasta file of the nt sequences of previously annotated coding sequences

from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
import matplotlib.pyplot as plt
import pandas as pd
import argparse
import sys, os, shutil
import subprocess
from Bio import SeqIO
from Bio.Seq import Seq

# Set up and extract the command line options.
parser = argparse.ArgumentParser(description='SE version 12/11/19')
parser.add_argument("-i","--input",
                    type=argparse.FileType('r'),
                    help="Fasta file of contigs to check. Use only CODING SEQUENCES.")
parser.add_argument("-r","--reads",
                    type=argparse.FileType('r'),
                    help="Fastq file of UNPAIRED reads.")
parser.add_argument("-b","--bwa",
                    nargs='?',
                    type=str,
                    default="bwa",
                    help="Path to bwa executable. Default assumes it is in your PATH.")
parser.add_argument("-s","--samtools",
                    nargs='?',
                    type=str,
                    default="samtools",
                    help="Path to samtools executable. Default assumes it is in your PATH.")
parser.add_argument("-bt","--bedtools",
                    nargs='?',
                    type=str,
                    default="bedtools",
                    help="Path to bedtools executable. Default assumes it is in your PATH.")
parser.add_argument("-p","--picard",
                    nargs='?',
                    type=str,
                    default="picard ",
                    help="Picard command. Something like: java -jar /PATH/TO/PICARD/picard.jar")
parser.add_argument("-g","--gatk",
                    nargs='?',
                    type=str,
                    default="java -jar /home/sellsworth/scripts/GenomeAnalysisTK-3.8-1-0-gf15c1c3ef/GenomeAnalysisTK.jar ",
                    help="GATK command. Some like: java -jar /PATH/TO/GATK/GenomeAnalysisTK.jar")
parser.add_argument("-m","--mismatches",
                    nargs='?',
                    type=int,
                    default=0,
                    help="Number of allowable mismatches to keep in alignment. The default is 0.")
parser.add_argument("-ts","--tooShort",
                    nargs='?',
                    type=int,
                    default=150,
                    help="Minimum length of clipped reads. Default is 150.")
parser.add_argument("-mq","--mapQuality",
                    nargs='?',
                    type=int,
                    default=0,
                    help="Minimum mapping quality. Default is 0. Note that reads with multiple mappings get assigned a quality of 0 by bwa.")
parser.add_argument("-min","--minRead",
                    nargs='?',
                    type=int,
                    default=150,
                    help="Minimum read length. Default is 150.")
parser.add_argument("-max","--maxRead",
                    nargs='?',
                    type=int,
                    default=1000,
                    help="Maximum read length. Default is 1000.")
parser.add_argument("-X","--foldCoverage",
                    nargs='?',
                    type=float,
                    default=20.0,
                    help="Maximum allowed fold coverage differential. Default is 20.")
parser.add_argument("-mer","--merSize",
                    nargs='?',
                    type=int,
                    default=100,
                    help="Mer size for sequence comparisons. Default is 100.")
parser.add_argument("-win","--window",
                    nargs='?',
                    type=int,
                    default=151,
                    help="Window size for coverage comparisons. Default is 151.")
parser.add_argument("-pdf","--pdfprint",
                    nargs='?',
                    type=str,
                    default="Y",
                    help="Use a Y or a N to indicate if you want to print pdfs of the good and bad coverage sequences. N will only print bad coverage sequences")
args = parser.parse_args()

columns =20

print("*"*int(columns))

# Check the input fasta file and output the number of detected sequences.
totalContigs = 0
for seq in SeqIO.parse(args.input,format="fasta") :
    totalContigs += 1
print("Total number of input contigs = " + str(totalContigs))
print("Maximum allowed mismatches per read retained in the alignment = " + str(args.mismatches))

print("*"*int(columns))

# Run the alignment
grepNM = "grep -E 'NM:i:[0-" + str(args.mismatches) + "][[:space:]]|^@'"
name = args.input.name.split(".")[0]
print("Generating bwa alignment: " + name + ".bam")
# Build the bwa index
command = args.bwa + " index " + args.input.name
subprocess.call(command,shell=True)
# Generate the initial sam alignment
command = args.bwa + " mem -M -t 8 -R \'@RG\\tID:" + args.input.name + "\\tSM:" + args.reads.name + "' " + args.input.name + " " + args.reads.name + " | " + grepNM  + " > tmp1.sam"
subprocess.call(command,shell=True)
# Create a sorted bam file
command = args.picard + " SortSam INPUT=tmp1.sam OUTPUT=tmp2.bam SORT_ORDER=coordinate"
subprocess.call(command,shell=True)
command = args.picard + " BuildBamIndex INPUT=tmp2.bam"
subprocess.call(command,shell=True)
# Remove overclipped reads
command = args.picard + "CreateSequenceDictionary REFERENCE=" + args.input.name + " OUTPUT=" + args.input.name.split(".")[0] + ".dict"
subprocess.call(command,shell=True)
command = args.samtools + " faidx " + args.input.name
subprocess.call(command,shell=True)
command = args.gatk + "-T PrintReads -R " + args.input.name + " -I tmp2.bam  -rf OverclippedRead --filter_is_too_short_value " + str(args.tooShort) + " --do_not_require_softclips_both_ends -rf MappingQuality -mmq " + str(args.mapQuality) + " -rf ReadLength -minRead " + str(args.minRead) + " -maxRead " + str(args.maxRead) + " -o " + name + ".bam"
subprocess.call(command,shell=True)
# Calculate coverage
# command = args.bedtools + " genomecov -d -ibam " + name + ".bam > coverage.txt"
# subprocess.call(command,shell=True)
subprocess.call("rm tmp*[bs]a[im]",shell=True)
# Generate Bed file
for seq_record in SeqIO.parse(args.input.name, "fasta"):
	count = 0
	for i in range(1,len(seq_record.seq)):
		if count < len(seq_record.seq):
			n= open("Test.bed",'a+')
			n.write(seq_record.id+'\t'+str(i)+'\t'+str(i+args.window)+'\n')
			n.close()
			count = i+args.window
# Calculate coverage
command = args.bedtools + ' coverage -a Test.bed -b '+name + '.bam -f 1 > coverage.txt'
subprocess.call(command,shell=True)
#

# Read in the coverage data
print("*"*int(columns))
print("Importing coverage information.")
X = pd.read_csv("coverage.txt",sep='\t',names=['transcript','pos1','pos2','cov','basecov','window','percent'])
print("Identified coverage data for " + str(len(set(X['transcript']))) + " transcripts.")
T = list(set(X['transcript']))

reportFile = open("report.txt","w")
goodFasta = open("good.fasta","w")
badcovFasta = open("badcov.fasta","w")
zeroBad = []
# Check for any sites with no coverage
for i in T :
    zeros = list(X[X['transcript'] == i]['cov']).count(0)
    if zeros :
        zeroBad.append(i)
        reportFile.write("BADZERO: " + i + " has " + str(zeros) + " sites with no coverage.\n")
reportFile.write("\n\n")
# Remove the contigs with zero coverage sites from the master list
T = [x for x in T if x not in zeroBad]
print("Removed " + str(len(zeroBad)) + " contigs for sites with zero coverage.")

# Check for bad coverage
covBad = []
for i in T :
    x = float(max(list(X[X['transcript'] == i]['cov'])))/float(min(list(X[X['transcript'] == i]['cov'])))
    if x > args.foldCoverage :
        covBad.append(i)
        reportFile.write("BADCOV: " + i + " has a " + str(round(x)) + "-fold coverage differential.\n")
    else :
        reportFile.write("GOOD: " + i + " has a " + str(round(x)) + "-fold coverage differential.\n")
print("Identified " + str(len(covBad)) + " contigs with >" + str(round(args.foldCoverage)) + "-fold coverage differentials.")

T = [x for x in T if x not in covBad]

# Function to generate mers for a single sequence (character string)
def MerSplit(merSize, seq) :
    mers = []
    if len(seq) < merSize :
        print("Sequence length (" + str(len(seq)) + ") is less than mer size (" + str(merSize) + ").")
        sys.exit()
    for i in range(0,len(seq)-merSize+1) :
        mers.append(seq[i:i+merSize])
    return mers

# Function to identify exactly matching regions between two sequences
# The return value will be a list of three-element lists, where the first element is a list of the starting and ending positions
# in seqence 1, the second is a list for sequence 2, and the third is the actual sequence match.
def ExactMatches(merSize,seq1,seq2) :
    if len(seq1) < merSize or len(seq2) < merSize :
        print("Sequence length is less than mer size (" + str(merSize) + ").")
        sys.exit()
    matches = []
    seq1mers = MerSplit(merSize,seq1)
    seq2mers = MerSplit(merSize,seq2)
    i = 0
    while i < len(seq1mers) :
        if seq1mers[i] in seq2mers :
            match1 = [i,i+merSize]                # get seq1 coordinates for initial match
            seq = seq1mers[i]                     # get initial match sequence
            j = seq2mers.index(seq1mers[i])       # get seq2 coordinates for initial match
            match2 = [j,j+merSize]
            i += 1
            j += 1
            while i < len(seq1mers) and j < len(seq2mers) and seq1mers[i] == seq2mers[j] :    # extend match while 2 sequences agree
                match1[1] += 1
                match2[1] += 1
                seq += seq1mers[i][-1]
                i += 1
                j += 1
            match1[1] += -1                       # to correct for overstepping by one
            match2[1] += -1
            matches.append([match1,match2,seq])
        else :
            i += 1
            continue
    return matches

# Create a dictionary of all of the contigs.
seqFile = open(args.input.name,"r")
S = {}
for seq in SeqIO.parse(seqFile,"fasta") :
    #create fasta file for good and bad coverage sequences
    if seq.id in T:
    	goodFasta.write('>'+str(seq.id)+'\n'+str(seq.seq)+'\n')
    if seq.id in covBad:
    	badcovFasta.write('>'+str(seq.id)+'\n'+str(seq.seq)+'\n')
    S[seq.description] = str(seq.seq)
seqFile.close()

reportFile.write("\n\n")

# Generate coverage plots and exact matches for bad-coverage contigs
print("Generating coverage plots for " + str(len(covBad)) + " contigs with >" + str(round(args.foldCoverage)) + "-fold coverage differentials.")
for i in covBad :
    matches = {}
    for j in T :
        match = ExactMatches(args.merSize,S[i],S[j])
        if match :
            matches[j] = match
    if len(matches.keys()) == 0 :
        reportFile.write("No GOOD matches identified for " + i +".\n")
        x = list(X[X['transcript'] == i]['pos1'])
        y = list(X[X['transcript'] == i]['cov'])
        plt.figure(figsize=(12,4))
        plt.title(i)
        plt.ylabel('Coverage')
        plt.xlabel('CDS position')
        plt.plot(x,y,'b-',linewidth=2)
        plt.xlim(x[0],x[-1])
        plt.savefig('badcov_'+i+".pdf")
        plt.close()
        continue

    x = list(X[X['transcript'] == i]['pos1'])
    y = list(X[X['transcript'] == i]['cov'])

    plt.figure(figsize=(12,4+4))
    plt.subplot(2,1,1)
    plt.title(i)
    plt.ylabel('Coverage')
    plt.xlabel('CDS position')
    plt.plot(x,y,'b-',linewidth=2)
    plt.xlim(x[0],x[-1])

    if not len(matches.keys()) :
        continue
    else :
        plt.subplot(2,1,2)
        plt.xlim(x[0],x[-1])
        plt.xlabel('CDS position')
        plt.ylim(0,len(matches.keys())+1)
        pos = 1
        for m in matches.keys() :
            plt.text(0.1*x[-1],pos+0.25,m)
            for n in range(0,len(matches[m])) :
                a = [matches[m][n][0][0],matches[m][n][0][1]]
                plt.hlines(pos,a[0],a[1],"r",linewidth=3)
                plt.vlines(a[0],pos+0.1,pos-0.1)
                plt.vlines(a[1],pos+0.1,pos-0.1)
            pos += 1
    plt.savefig('badcov_'+i+".pdf")
    plt.close()
if args.pdfprint == 'Y':
	for i in T:
		x = list(X[X['transcript'] == i]['pos1'])
		y = list(X[X['transcript'] == i]['cov'])
		plt.figure(figsize=(12,4))
		plt.title(i)
		plt.ylabel('Coverage')
		plt.xlabel('CDS position')
		plt.plot(x,y,'b-',linewidth=2)
		plt.xlim(x[0],x[-1])
		plt.savefig('good_'+i+".pdf")
		plt.close()
reportFile.close()
goodFasta.close()
badcovFasta.close()
print("*"*int(columns))


from __future__ import absolute_import, division, print_function

import numpy as np

import torch
import torch.nn as nn
import torchvision.models as models
import torch.utils.model_zoo as model_zoo
import torch.nn.functional as F
from collections import OrderedDict
from config.conf import LocalConf
from pytorch_model_summary import summary

class ResNetMultiImageInput(models.ResNet):
    """Constructs a resnet model with varying number of input images.
    Adapted from https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py
    """
    def __init__(self, block, layers, num_classes=1000, num_input_images=1):
        super(ResNetMultiImageInput, self).__init__(block, layers)
        self.inplanes = 64
        self.conv1 = nn.Conv2d(
            num_input_images * 3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

def resnet_multiimage_input(num_layers, pretrained=False, num_input_images=1):
    """Constructs a ResNet model.
    Args:
        num_layers (int): Number of resnet layers. Must be 18 or 50
        pretrained (bool): If True, returns a model pre-trained on ImageNet
        num_input_images (int): Number of frames stacked as input
    """
    assert num_layers in [18, 50], "Can only run with 18 or 50 layer resnet"
    blocks = {18: [2, 2, 2, 2], 50: [3, 4, 6, 3]}[num_layers]
    block_type = {18: models.resnet.BasicBlock, 50: models.resnet.Bottleneck}[num_layers]
    model = ResNetMultiImageInput(block_type, blocks, num_input_images=num_input_images)

    if pretrained:
        loaded = model_zoo.load_url(models.resnet.model_urls['resnet{}'.format(num_layers)])
        loaded['conv1.weight'] = torch.cat(
            [loaded['conv1.weight']] * num_input_images, 1) / num_input_images
        model.load_state_dict(loaded)
    return model

class ResnetPoseEncoder(nn.Module):
    """
        Pytorch module for a resnet encoder
    """
    def __init__(self, num_layers, pretrained, num_input_images=1):
        super(ResnetPoseEncoder, self).__init__()

        self.num_ch_enc = np.array([64, 64, 128, 256, 512])

        resnets = {
                   18: models.resnet18,
                   34: models.resnet34,
                   50: models.resnet50,
                   101: models.resnet101,
                   152: models.resnet152
                  }

        if num_layers not in resnets:
            raise ValueError("{} is not a valid number of resnet layers".format(num_layers))

        self.encoder = resnet_multiimage_input(num_layers, pretrained, num_input_images)

        if num_layers > 34:
            self.num_ch_enc[1:] *= 4

    def forward(self, input_image):
        self.features = []
        x = (input_image - 0.45) / 0.225
        x = self.encoder.conv1(x)
        x = self.encoder.bn1(x)
        self.features.append(self.encoder.relu(x))
        self.features.append(self.encoder.layer1(self.encoder.maxpool(self.features[-1])))
        self.features.append(self.encoder.layer2(self.features[-1]))
        self.features.append(self.encoder.layer3(self.features[-1]))
        self.features.append(self.encoder.layer4(self.features[-1]))

        return self.features

class PoseDecoder(nn.Module):
    def __init__(self, num_ch_enc, num_input_features, num_frames_to_predict_for=None, stride=1, num_ep=0):
        super(PoseDecoder, self).__init__()

        self.num_ch_enc = num_ch_enc
        self.num_input_features = num_input_features
        self.num_ep = num_ep

        if num_frames_to_predict_for is None:
            num_frames_to_predict_for = num_input_features - 1
        self.num_frames_to_predict_for = num_frames_to_predict_for

        self.convs = OrderedDict()

        self.convs[("squeeze")] = nn.Conv2d(self.num_ch_enc[-1], 256, 1)

        if self.num_ep > 0:
            self.convs["epconv"] = nn.Sequential(
            nn.Conv2d(2, 16, kernel_size=1, stride=1, padding=0, bias=True),
            nn.ELU(inplace=True),
            nn.Conv2d(16, self.num_ep, kernel_size=1, stride=1, padding=0, bias=True),
            nn.ELU(inplace=True)
            )

        self.convs[("pose", 0)] = nn.Conv2d(num_input_features * 256 + num_ep, 256, 3, stride, 1)
        self.convs[("pose", 1)] = nn.Conv2d(256, 256, 3, stride, 1)
        self.convs[("pose", 2)] = nn.Conv2d(256, 6 * num_frames_to_predict_for, 1)

        self.relu = nn.ReLU()

        self.net = nn.ModuleList(list(self.convs.values()))

    def forward(self, input_features, input_grids=None):
        last_features = [f[-1] for f in input_features]

        cat_features = [self.relu(self.convs["squeeze"](f)) for f in last_features]
        cat_features = torch.cat(cat_features, 1)

        if self.num_ep > 0:
            grids_ep = self.convs["epconv"](input_grids)
            dgrid = F.interpolate(grids_ep, size=(cat_features.shape[2], cat_features.shape[3]), align_corners=True, mode='bilinear')
            cat_features = torch.cat([cat_features, dgrid], dim=1)

        out = cat_features
        for i in range(3):
            out = self.convs[("pose", i)](out)
            if i != 2:
                out = self.relu(out)

        out = out.mean(3).mean(2)

        out = 0.01 * out.view(-1, self.num_frames_to_predict_for, 1, 6)

        axisangle = out[..., :3]
        translation = out[..., 3:]

        return axisangle, translation

if __name__=='__main__':
    conf = LocalConf().conf
    get = lambda x: conf.get(x)

    option = 1  # 1 means PoseEncoder, 2 means PoseDecoder

    if option == 1:
        # for pose_encoder
        model=ResnetPoseEncoder(num_layers=get('model').get('num_resnet_layers'), pretrained=True, num_input_images=2)
        architecture = summary(model, torch.rand(1, 3, *get('im_sz')), max_depth=4, show_parent_layers=True,
                               print_summary=True)

        # Convert to onnx in order to visualize in Netron
        # Input to the model
        x = torch.randn(1, 3, *get('im_sz'), requires_grad=True)
        torch_out = model(x)

        # Export the model
        torch.onnx.export(model,  # model being run
                          x,  # model input (or a tuple for multiple inputs)
                          "resnet_pose_encoder.onnx",  # where to save the model (can be a file or file-like object)
                          export_params=True,  # store the trained parameter weights inside the model file
                          opset_version=10,  # the ONNX version to export the model to
                          do_constant_folding=True,  # whether to execute constant folding for optimization
                          input_names=['input'],  # the model's input names
                          output_names=['output'],  # the model's output names
                          dynamic_axes={'input': {0: 'batch_size'},  # variable length axes
                                        'output': {0: 'batch_size'}})

    else:
        #for pose_decoder
        model=PoseDecoder(num_layers=get('model').get('num_resnet_layers'), pretrained=True)
        architecture = summary(model, torch.rand(1, 3, *get('im_sz')), max_depth=4, show_parent_layers=True,
                               print_summary=True)


import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import pandas as pd
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
import plotly.express as px

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.DARKLY])

app.layout = dbc.Container([
	dbc.Row(
		dbc.Col([
			html.Div(
				dbc.RadioItems(
					options = [
						{'label':'tsne only', 'value':1},
						{'label':'tsne + pca', 'value':2}
					],
					value = 1,
					id = 'radio',
					className = 'btn-group',
					labelClassName = 'btn btn-secondary',
					labelCheckedClassName = 'active',
				),
				className = 'radio-group',
				style = {'text-align':'center'}
			),
			dcc.Graph(id="scatter-plot"),
			html.Div(["PCA n_components: ", html.Div(id='display3')]),
			dcc.Slider(
				id='pca_comp',
				min=0, max=47, step=1,
				marks={a*10:str(a*10) for a in range(5)},
				value=20
			),
			html.Div(["Perplexity: ", html.Div(id='display')]),
			dcc.Slider(
				id='perplexity',
				min=0, max=100, step=1,
				marks={a*10:str(a*10) for a in range(11)},
				value=1
			),
			html.Div(["No of iteratons: ", html.Div(id='display2')]),
			dcc.Slider(
				id='iters',
				min=250, max=5000, step=50,
				marks={a*250:str(a*250) for a in range(4,21)},
				value=300
			),
		],
		width=12
		)
	)
])

df = pd.read_csv('../data/model_vus_preprocd.csv')
y=[]
for i in df.index:
	if pd.notna(df.loc[i,'gene']):
		y.append('Important Gene Mutation')
		continue
	if df.loc[i,'outcome'] == 0:
		y.append('No Mutation')
	else:
		y.append('VUS')
df = df.drop(['Sno','outcome','gene','Syndrome', 'gene name if VUS','Ethnicity  0-delhi NCR, west UP, haryana  1-eastern UP, Bihar 2- pahari 3-rajasthan 4-punjab 5-miscellanous'], axis=1)

@app.callback(
	Output("scatter-plot", "figure"),
	[Input("perplexity", "value"), Input('iters', 'value'), Input('pca_comp', 'value'), Input('radio', 'value')]
)
def update_bar_chart(slider_val, itersval, pcacomps, radio):
	pca_res = df
	if radio == 2:
		pca = PCA(n_components=pcacomps)
		pca_res = pca.fit_transform(df)
	tsne = TSNE(n_components=2, verbose=0, perplexity=slider_val, n_iter=itersval)
	tsne_results = tsne.fit_transform(pca_res)
	df['tsne-2d-one'] = tsne_results[:,0]
	df['tsne-2d-two'] = tsne_results[:,1]
	fig = px.scatter(df, x="tsne-2d-one", y="tsne-2d-two", template='plotly_dark', color=y)
	fig.layout.height=700
	return fig

@app.callback(
	Output('display', 'children'),
	[Input('perplexity', 'value')]
)
def update_display(val):
	return val

@app.callback(
	Output('display2', 'children'),
	[Input('iters', 'value')]
)
def update_display2(val):
	return val

app.run_server(debug=True)


#coding : utf8
#Author : taosenlin
#Time : 2020/5/25 14:22

from selenium import webdriver
import unittest
import time

class Testbaidu(unittest.TestCase):

    def setUp(self,url = 'https://www.baidu.com'):
        self.driver = webdriver.Chrome("E:\chromedriver.exe")
        self.url = url

    def tearDown(self):
        self.driver.quit()

    def test_baidu(self):
        # url = 'https://www.baidu.com'
        driver = self.driver
        driver.get(self.url)
        driver.find_element_by_id('kw').clear()
        driver.find_element_by_id('kw').send_keys('unittest')
        driver.find_element_by_id('su').click()
        time.sleep(3)
        title = driver.title
        self.assertEqual(title,'unittest_百度搜索')

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


import os
import time
import yaml
from pathlib import Path
from pkg_resources import packaging

import torch
import torch.cuda.nccl as nccl
import torch.distributed as dist
from torch.distributed.fsdp import StateDictType
from torch.distributed.fsdp.sharded_grad_scaler import ShardedGradScaler
from tqdm import tqdm
from transformers import LlamaTokenizer

def set_tokenizer_params(tokenizer: LlamaTokenizer):
    tokenizer.pad_token_id = 0
    tokenizer.padding_side = "left"

# Converting Bytes to Megabytes
def byte2mb(x):
    return int(x / 2**20)

def train(model, train_dataloader, tokenizer, optimizer, lr_scheduler, gradient_accumulation_steps, train_config, fsdp_config=None, local_rank=None, rank=None):
    """
    Trains the model on the given dataloader

    Args:
        model: The model to be trained
        train_dataloader: The dataloader containing the training data
        optimizer: The optimizer used for training
        lr_scheduler: The learning rate scheduler
        gradient_accumulation_steps: The number of steps to accumulate gradients before performing a backward/update operation
        num_epochs: The number of epochs to train for
        local_rank: The rank of the current node in a distributed setting
        train_config: The training configuration
        eval_dataloader: The dataloader containing the eval data
        tokenizer: tokenizer used in the eval for decoding the predicitons

    Returns: results dictionary containing average training and validation perplexity and loss
    """
    # Create a gradient scaler for fp16
    train_prep = []
    train_loss = []
    val_prep = []
    val_loss =[]
    epoch_times = []
    checkpoint_times = []
    results = {}
    best_val_loss = float("inf")
    for epoch in range(train_config.num_epochs):
        epoch_start_time = time.perf_counter()
        model.train()
        total_loss = 0.0
        total_length = len(train_dataloader)//gradient_accumulation_steps
        pbar = tqdm(colour="green", desc=f"Training Epoch: {epoch+1}", total=total_length, dynamic_ncols=True)
        for step, batch in enumerate(train_dataloader):
            for key in batch.keys():
                batch[key] = batch[key].to('cuda')
                loss = model(**batch).loss
                loss = loss / gradient_accumulation_steps
                total_loss += loss.detach().float()
                # regular backpropagation when fp16 is not used
                loss.backward()
                if (step + 1) % gradient_accumulation_steps == 0 or step == len(train_dataloader) - 1:
                    optimizer.step()
                    optimizer.zero_grad()
                    pbar.update(1)

                pbar.set_description(f"Training Epoch: {epoch+1}/{train_config.num_epochs}, step {step}/{len(train_dataloader)} completed (loss: {loss.detach().float()})")

        epoch_end_time = time.perf_counter()-epoch_start_time
        epoch_times.append(epoch_end_time)
        # Reducing total_loss across all devices if there's more than one CUDA device
        train_epoch_loss = total_loss / len(train_dataloader)
        train_perplexity = torch.exp(train_epoch_loss)

        train_prep.append(train_perplexity)
        train_loss.append(train_epoch_loss)

        # Update the learning rate as needed
        lr_scheduler.step()

        print(f"Epoch {epoch+1}: train_perplexity={train_perplexity:.4f}, train_epoch_loss={train_epoch_loss:.4f}, epoch time {epoch_end_time}s")
    avg_epoch_time = sum(epoch_times)/ len(epoch_times)
    avg_checkpoint_time = sum(checkpoint_times)/ len(checkpoint_times) if len(checkpoint_times) > 0 else 0
    avg_train_prep = sum(train_prep)/len(train_prep)
    avg_train_loss = sum(train_loss)/len(train_loss)

    results['avg_train_prep'] = avg_train_prep
    results['avg_train_loss'] = avg_train_loss
    results["avg_epoch_time"] = avg_epoch_time
    results["avg_checkpoint_time"] = avg_checkpoint_time

    #saving the training params including fsdp setting for reference.
    if train_config.enable_fsdp and not train_config.use_peft:
        save_train_params(train_config, fsdp_config, rank)

    return results

def freeze_transformer_layers(model, num_layer):
   for i, layer in enumerate(model.model.layers):
        if i < num_layer:
            for param in layer.parameters():
                param.requires_grad = False

def check_frozen_layers_peft_model(model):
     for i, layer in enumerate(model.model.layers):
            for name, param in layer.named_parameters():
                print(f"Layer {i}, parameter {name}: requires_grad = {param.requires_grad}")

def setup():
    """Initialize the process group for distributed training"""
    dist.init_process_group("nccl")

def setup_environ_flags(rank):
    """Set environment flags for debugging purposes"""
    os.environ["TORCH_SHOW_CPP_STACKTRACES"] = str(1)
    os.environ["NCCL_ASYNC_ERROR_HANDLING"] = str(1)
    # os.environ["TORCH_DISTRIBUTED_DEBUG"] = "DETAIL"
    # This flag will help with CUDA memory fragmentations that can lead into OOM in some cases.
    # Note this is only availble in PyTorch Nighlies (as of July 30 2023)
    # os.environ['PYTORCH_CUDA_ALLOC_CONF']='expandable_segments:True'
    if rank == 0:
        print(f"--> Running with torch dist debug set to detail")

def cleanup():
    """Clean up the process group after training"""
    dist.destroy_process_group()

def clear_gpu_cache(rank=None):
    """Clear the GPU cache for all ranks"""
    if rank == 0:
        print(f"Clearing GPU cache for all ranks")
    torch.cuda.empty_cache()

def get_parameter_dtypes(model):
    """Get the data types of model parameters"""
    parameter_dtypes = {}
    for name, parameter in model.named_parameters():
        parameter_dtypes[name] = parameter.dtype
    return parameter_dtypes

def print_model_size(model, config, rank: int = 0) -> None:
    """
    Print model name, the number of trainable parameters and initialization time.

    Args:
        model: The PyTorch model.
        model_name (str): Name of the model.
        init_time_start (float): Initialization start time.
        init_time_end (float): Initialization end time.
        rank (int, optional): Current process's rank. Defaults to 0.
    """
    if rank == 0:
        print(f"--> Model {config.model_name}")
        total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
        print(f"\n--> {config.model_name} has {total_params / 1e6} Million params\n")

def save_train_params(train_config, fsdp_config, rank):
    """
    This function saves the train_config and FSDP config into a train_params.yaml.
    This will be used by converter script in the inference folder to fetch the HF model name or path.
    It also would be hepful as a log for future references.
    """
    # Convert the train_config and fsdp_config objects to dictionaries,
    # converting all values to strings to ensure they can be serialized into a YAML file
    train_config_dict = {k: str(v) for k, v in vars(train_config).items() if not k.startswith('__')}
    fsdp_config_dict = {k: str(v) for k, v in vars(fsdp_config).items() if not k.startswith('__')}
    # Merge the two dictionaries into one
    train_params_dict = {**train_config_dict, **fsdp_config_dict}
    # Construct the folder name (follwoing FSDP checkpointing style) using properties of the train_config object
    folder_name = (
    train_config.dist_checkpoint_root_folder
    + "/"
    + train_config.dist_checkpoint_folder
    + "-"
    + train_config.model_name
    )

    save_dir = Path.cwd() / folder_name
    # If the directory does not exist, create it
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    # Convert the dictionary to a YAML string
    config_yaml = yaml.dump(train_params_dict, indent=4)
    file_name = os.path.join(save_dir,'train_params.yaml')

    # Check if there's a directory with the same name as the file
    if os.path.isdir(file_name):
        print(f"Error: {file_name} is a directory, not a file.")
    else:
        # Write the YAML string to the file
        with open(file_name, 'w') as f:
            f.write(config_yaml)
        if rank==0:
            print(f"training params are saved in {file_name}")


#Author : Koralp Catalsakal

#Import modules
import nltk
nltk.download('punkt')
import flask
import io

from nltk.stem.lancaster import LancasterStemmer
lancaster_stemmer = LancasterStemmer()

import numpy as np
import tensorflow as tf
import pandas as pd
#import tflearn
import json
import random
from pandas.io.json import json_normalize

from keras.preprocessing.sequence import pad_sequences
from sklearn.preprocessing import OneHotEncoder
from tensorflow.keras.utils import to_categorical

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM,Dense,Input,Embedding

MAX_SEQ_LENGTH = 10
global json_df,vocab,label_dict

#Tokenization of patterns
def tokenize(data,stemmer):
    flat_json_df = json_normalize(data['intents'])

    all_words = []
    for pattern in flat_json_df['patterns']:
        for pat in pattern:
            all_words.extend(nltk.word_tokenize(pat))

    all_words = [lancaster_stemmer.stem(w.lower()) for w in all_words]
    all_words = set(all_words)
    return all_words,flat_json_df

# Create vocabulary from the corpus
def create_vocabulary(corpus):
    vocabulary_dict = {}
    NB_OF_WORDS = len(corpus)
    for idx,word in enumerate(corpus):
        vocabulary_dict[word] = idx+2
    vocabulary_dict['unk'] = 1
    return vocabulary_dict

def numerate_text(vocabulary,text):
    numerized_text = []
    for t in text:
        output_vec = []
        token = nltk.word_tokenize(t)
        for inner_t in token:
            stemmed = lancaster_stemmer.stem(inner_t.lower())
            if stemmed in vocabulary.keys():
                output_vec.append(vocabulary[stemmed])
            else:
                output_vec.append(vocabulary['unk'])
        numerized_text.append(output_vec)
    return numerized_text

def numerate_string(vocabulary,str):
    numerized_str = []
    token = nltk.word_tokenize(str)
    for inner_t in token:
        stemmed = lancaster_stemmer.stem(inner_t.lower())
        if stemmed in vocabulary.keys():
            numerized_str.append(vocabulary[stemmed])
        else:
            numerized_str.append(vocabulary['unk'])
    numerized_str = [numerized_str]
    return numerized_str

def prepare_labels(dataframe):

    class_dict = {}
    #One-hot encode output
    onehot_encoder = OneHotEncoder(sparse=False)
    onehot_encoded = onehot_encoder.fit_transform(np.asarray(dataframe['tag']).reshape(-1,1))

    all_labels = []
    for i in dataframe.index:
        for l in range(len(dataframe.iloc[i]['patterns'])):
            all_labels.append(onehot_encoded[i])
        class_dict[np.argwhere(onehot_encoded[i] == 1)[0][0]] =  dataframe.iloc[i]['tag']

    return np.array(all_labels,dtype = 'float32'),class_dict

def trainChatNN(X,y,vocabulary_length):
    X_reshaped = X.reshape(X.shape[0],1,X.shape[1])

    input_dim = X_reshaped.shape[1:3]
    output_classes = y.shape[1]
    ##TRAINING NETWORK NOW##
    model = Sequential()

    model.add(Input(input_dim[1]))
    model.add(Embedding(vocabulary_length + 1,input_dim[1]//2,mask_zero =  True))
    model.add(LSTM(input_dim[1]*3, activation = 'relu' , return_sequences = False))
    model.add(Dense(input_dim[1]*2, activation = 'relu'))
    model.add(Dense(output_classes,activation ='softmax'))

    model.compile(loss='categorical_crossentropy',
                  optimizer=tf.keras.optimizers.Adam(1e-4),
                  metrics=['accuracy'])

    model.summary()

    early_stop = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3000)

    history = model.fit(X,y, epochs=3000,verbose = 1,callbacks = [early_stop])
    model.save('chatbot.h5')
    return model

def loadChatbot(filename):
    loaded_model = tf.keras.models.load_model(filename)
    return loaded_model

def predictStringInput(model,str):
        numerical = numerate_string(vocab,str)
        padded = pad_sequences(numerical, maxlen=MAX_SEQ_LENGTH)
        padded = padded.reshape(1,padded.size)
        prediction = model.predict(padded)
        predicted_class = np.argmax(prediction)
        predicted_tag = label_dict[predicted_class]
        print('Input is: {0} - Predicted tag: {1} - Confidence : {2:.2f}'.format(str,predicted_tag, np.max(prediction)))
        responses = json_df['responses'][json_df['tag'] == predicted_tag]
        total_responses = len(responses.iloc[0])
        randidx = np.random.randint(0,total_responses)
        print('Response is: {0}'.format(responses.iloc[0][randidx]))
        return responses.iloc[0][randidx]

def interactiveLoop(model,vocabulary,dataframe,label_dictionary):
    print('Hello there! Wanna say something to me ?')
    user_in = ''
    while(True and user_in != 'Exit'):
        user_in = input()
        predictStringInput(model,user_in,vocabulary,dataframe,label_dictionary)
"""
        numerical = numerate_string(vocabulary,user_in)
        padded = pad_sequences(numerical, maxlen=MAX_SEQ_LENGTH)
        prediction = model.predict(padded)
        predicted_class = np.argmax(prediction)
        predicted_tag = label_dictionary[predicted_class]
        responses = dataframe['responses'][dataframe['tag'] == predicted_tag]
        print(responses)
        total_responses = len(responses.iloc[0])
        randidx = np.random.randint(0,total_responses-1)
        print(responses.iloc[0][randidx])
"""

#Load data
with open('intents.json') as file:
        data = json.load(file)

#Tokenize all words and apply stemming operation
all_words,json_df = tokenize(data,lancaster_stemmer)

#Gather all tags
tags = sorted(json_df['tag'])

#Create vocabulary from stemmed words(Not an embedding, just a vocabulary!)
vocab = create_vocabulary(all_words)

#Convert character arrays to numerical values, w.r.t our vocabulary
numerized = json_df['patterns'].apply(lambda x : numerate_text(vocab,x))

#Create the target label dataset
labels,label_dict = prepare_labels(json_df)

#Pad sequences to MAX_SEQ_LENGTH
padded = []
for n in numerized:
    padded.extend(list(pad_sequences(n, maxlen=MAX_SEQ_LENGTH)))
padded = np.array(padded,dtype = 'float32')

#chatbot = trainChatNN(padded,labels,len(vocab))
chatbot = loadChatbot('chatbot.h5')

user_in = input()
predictStringInput(chatbot,user_in)
#interactiveLoop(chatbot,vocab,json_df,label_dict)


from rest_framework import serializers
from .models import *
from lyka_products.serializers import ProductRetriveSerializer, ColorSerializer, VariationsSerializer
from lyka_address.serializers import CustomerAddressRetriveSerializer, SellerStoreAddressRetriveSerializer
from lyka_payment.serializers import CouponSerializer
import uuid
from lyka_seller.serializers import SellerBusinessNameSerializer

class OrderCredentialsSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderCredentials
        fields = "__all__"

class OrderItemsSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItems
        fields = "__all__"

class OrderSerializer(serializers.ModelSerializer):
    order_id = serializers.UUIDField(read_only=True)
    class Meta:
        model = Order
        fields = ["order_id"]

    def create(self, validated_data):
        o_id = uuid.uuid1()
        order = Order.objects.create(order_id=o_id)
        return order

class OrderGroupSerializer(serializers.ModelSerializer):
    order_list_id = serializers.UUIDField(read_only=True)
    class Meta:
        model = OrderGroup
        fields = ["order_list_id"]

    def create(self, validated_data):
        o_l_id = uuid.uuid1()
        order = OrderGroup.objects.create(order_list_id=o_l_id)
        return order

class OrderItemsRetriveSerializer(serializers.ModelSerializer):
    product = ProductRetriveSerializer()
    product_color = ColorSerializer()
    product_variant = VariationsSerializer()
    class Meta:
        model = OrderItems
        fields = "__all__"

class OrderRetriveSerializer(serializers.ModelSerializer):
    item = OrderItemsRetriveSerializer()
    shipping_address = CustomerAddressRetriveSerializer()
    seller = SellerBusinessNameSerializer()
    class Meta:
        model = Order
        fields = "__all__"

class OrderDetailsRetriveSerializer(serializers.ModelSerializer):
    item = OrderItemsRetriveSerializer()
    shipping_address = CustomerAddressRetriveSerializer()
    billing_address = CustomerAddressRetriveSerializer()
    credentials = OrderCredentialsSerializer()
    pickup_address = SellerStoreAddressRetriveSerializer()
    applied_coupon = CouponSerializer()
    class Meta:
        model = Order
        fields = "__all__"

class OrderGroupPriceSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderGroup
        fields = ["total_price", "total_selling_price", "additional_charges", "coupon_discount", "discount", "total_shipping_charge"]

class OrderItemsPriceSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItems
        fields = ["product_price", "selling_price", "coupon_discount", "discount", "additional_charges"]

class OrderPriceSerializer(serializers.ModelSerializer):
    item = OrderItemsPriceSerializer()
    class Meta:
        model = Order
        fields = ["item", "shipping_charge"]


from automaton import automata

class gramatica:
    def __init__(self, parts:list) -> None:
        self.name = parts.pop(0)
        tmp = parts.pop(0).split(";")
        self.Vn = tmp[0].split(",")
        self.Vt = tmp[1].split(",")
        self.Sn = tmp[2]
        self.glc = False
        self.Pr = []
        while len(parts) > 0:
            prod = parts.pop(0).split("->")
            prod[0] = prod[0].strip()
            prod[1] = prod[1].strip()
            self.Pr.append(prod)
            self.isGlc(prod)
        self.auto:automata = None

    def isGlc(self,prod):
        left = prod[0].split()
        numL = 0
        for e in left:
            for nt in self.Vn:
                if e == nt:
                    numL += 1
        right = prod[1].split()
        rNt = 0
        for e in right:
            for nt in self.Vn:
                if e == nt:
                    rNt += 1
        rT = 0
        for e in right:
            for t in self.Vt:
                if e == t:
                    rT += 1
        if numL == 1:
            if rNt > 1 or rT > 1:
                self.glc = True

    def showGrammar(self):
        print("\n------------------------------------------\n")
        print("Nombre de gramatica =",self.name)
        str = "{"
        for nt in self.Vn:
            str += nt+","
        str = str.removesuffix(",")
        str += "}"
        print("No Terminales =",str)
        str = "{"
        for t in self.Vt:
            str += t+","
        str = str.removesuffix(",")
        str += "}"
        print("Terminales =",str)
        print("No terminal inicial =",self.Sn)
        print("Producciones =\n")
        groups = []
        for prod in self.Pr:
            for g in groups:
                if g[0] == prod[0]:
                    g.append(prod[1])
                    break
            else:
                group = [prod[0],prod[1]]
                groups.append(group)
        for g in groups:
            if len(g) > 2:
                str = g.pop(0) + " -> "
                str += g.pop(0)
                for rule in g:
                    str += f" | {rule}"
                print(str)
            else:
                print(g[0],"->",g[1])
        print("\n------------------------------------------")


import json

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods

from Defect_Management_backend.models import Requirement, Iteration

# 新增需求接口
@csrf_exempt
@require_http_methods(['POST'])
def requirement_add(request):
    response = {}
    try:
        form = json.loads(request.body)['form']
        pid = json.loads(request.body)['pid']  # 项目ID
        iteration_title = Iteration.objects.filter(id=form['iteration']).values('title')
        Requirement.objects.create(title=form['title'], priority=form['priority'], iteration=iteration_title, iterationId=form['iteration'],
                                   handler=form['handler'], start=form['start'], end=form['end'],
                                   desc=form['desc'], pid=pid)
        response['respCode'] = '000000'
        response['respMsg'] = 'success'
    except Exception as e:
        response['respCode'] = '999999'
        response['respMsg'] = str(e)
    return JsonResponse(response)

# 查询接口
@csrf_exempt
@require_http_methods(['GET'])
def requirement_info(request):
    response = {}
    try:
        pid = request.GET.get('pid')  # 项目ID
        rid = request.GET.get('rid')  # 需求ID
        iteration_id = request.GET.get('iterationId')    # 迭代ID
        if pid:
            info = Requirement.objects.filter(pid=pid).values()
        elif rid:
            info = Requirement.objects.filter(id=rid).values()
        else:
            info = Requirement.objects.filter(iterationId=iteration_id).values()
        response['respCode'] = '000000'
        response['respMsg'] = 'success'
        response['list'] = list(info)
    except Exception as e:
        response['respCode'] = '000000'
        response['respMsg'] = str(e)
    return JsonResponse(response)

# 修改接口
@csrf_exempt
@require_http_methods(['POST'])
def requirement_edit(request):
    response = {}
    try:
        rid = json.loads(request.body)['rid']
        form = json.loads(request.body)['form']
        iteration_title = Iteration.objects.filter(id=form['iteration']).values('title')
        Requirement.objects.filter(id=rid).update(title=form['title'], priority=form['priority'],
                                                  iterationId=form['iteration'], iteration=iteration_title,
                                                  handler=form['handler'], start=form['start'], end=form['end'],
                                                  desc=form['desc'])
        response['respCode'] = '000000'
        response['respMsg'] = 'success'
    except Exception as e:
        response['respCode'] = '999999'
        response['respMsg'] = str(e)
    return JsonResponse(response)

# 删除接口
@csrf_exempt
@require_http_methods(['GET'])
def requirement_del(request):
    response = {}
    try:
        rid = request.GET.get('rid')  # 需求ID
        Requirement.objects.filter(id=rid).delete()
        response['respCode'] = '000000'
        response['respMsg'] = 'success'
    except Exception as e:
        response['respCode'] = '000000'
        response['respMsg'] = str(e)
    return JsonResponse(response)

# 修改状态接口
@csrf_exempt
@require_http_methods(['POST'])
def requirement_update_state(request):
    response = {}
    try:
        rid = json.loads(request.body)['rid']
        state = json.loads(request.body)['newState']
        Requirement.objects.filter(id=rid).update(state=state)
        response['respCode'] = '000000'
        response['respMsg'] = 'success'
    except Exception as e:
        response['respCode'] = '999999'
        response['respMsg'] = str(e)
    return JsonResponse(response)