# -*- coding: utf-8 -*-
"""
Created on Sun Apr 25 20:15:51 2021

@author: blgnm
"""

import george
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.optimize import minimize
from scipy.optimize import curve_fit
import random
from astropy.stats import biweight_location
import numpy as np
import pandas as pd
from imblearn.over_sampling import SMOTE
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
import sklearn
import matplotlib.pyplot as plt
import pywt
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import cross_validate
from antares_client.search import search
from antares_client._api.models import Locus
from antares_client.search import get_by_ztf_object_id
from tqdm import tqdm
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from imblearn.pipeline import Pipeline as imbpipeline
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
from sklearn.ensemble import RandomForestClassifier
from imblearn.over_sampling import BorderlineSMOTE
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import MinMaxScaler
from sklearn import datasets, metrics, model_selection, svm
from sklearn.model_selection import RepeatedStratifiedKFold
from imblearn.ensemble import BalancedRandomForestClassifier

class ZTFData:
    def __init__(self,ZTF_id = None):
        self.ZTF_id = ZTF_id

    def get_id(self):
        return self.ZTF_id

    def get_raw_data(self):
        for i in self.ZTF_id:
            locus = get_by_ztf_object_id(i)
            return locus.lightcurve

    def get_lightcurve(self):
        """

        Returns
        -------
        Light Curve of all ztf objects stored within ZTFData()

        """
        for i in self.ZTF_id:
            plt.figure(num=None, figsize=(12, 5), dpi=100)
            locus = get_by_ztf_object_id(i)
            lc = locus.lightcurve
            lc['alert_type'] = lc['alert_id'].apply(lambda x: x[:x.index(':')])
            for (pb, at), df in lc.groupby(['ant_passband', 'alert_type']):
                is_candidate = at == 'ztf_candidate'
                plt.errorbar(
                    x=df['ant_mjd'],
                    y=df['ant_mag'] if is_candidate else df['ant_maglim'],
                    yerr=df['ant_magerr'],
                    #  uplims=(at!='ztf_candidate'),
                    label=pb + '  ' + at[4:],
                    color=pb,
                    fmt=('o' if is_candidate else '^') + pb.lower(),
                    alpha=1 if is_candidate else 0.3)
                plt.plot(df['ant_mjd'], df['ant_mag'])
            plt.title(str(i))
            plt.xlabel('MJD')
            plt.ylabel('Magnitude')
            plt.legend()
            plt.gca().invert_yaxis()
            plt.show()

    def Data(self, labels = None):
        """

        Parameters
        ----------
        labels : Pandas Series, optional
            Classification labels, if applicable (I don't remember if that part works tbh). The default is None.

        Returns
        -------
        Pandas data frame of processed event information for all provided ZTF ID's.

        """

        Supernovadf = pd.DataFrame(columns = ["mjd", "band", "magnitude", "error", "event","class"])
            #plt.title(locus.properties['ztf_object_id'])
        loop = tqdm(total = len(self.ZTF_id), position =0, leave = False)
        for i in self.ZTF_id:

            locus = get_by_ztf_object_id(i)
            try:
                Data = locus.lightcurve
            except Exception:
                pass

            Data_frame1 = pd.DataFrame.from_dict(Data[Data['ant_passband']=='g'])
            Data_frame2 = pd.DataFrame.from_dict(Data[Data['ant_passband']=='R'])

            Data_frame1['ant_mag'] = Data_frame1['ant_mag'].replace(np.nan, 0)
            Data_frame2['ant_mag'] = Data_frame2['ant_mag'].replace(np.nan, 0)
            Data_frame1 = Data_frame1[Data_frame1.ant_mag > 0]
            Data_frame2 = Data_frame2[Data_frame2.ant_mag > 0]

            MJD1 = Data_frame1['ant_mjd']
            MJD2 = Data_frame2['ant_mjd']
            MagnitudeG = Data_frame1['ant_mag']
            MagnitudeR = Data_frame2['ant_mag']

            MJD1 = MJD1 - (MJD1.min() - 1)
            MJD2 = MJD2 - (MJD2.min() - 1)

            GBand = pd.DataFrame(columns = ["mjd", "band", "magnitude", "error", "event"])
            GBand["mjd"] = Data_frame1["ant_mjd"]
            GBand["band"] = pd.Series(np.zeros([len(MagnitudeG)]))
            GBand["magnitude"] = MagnitudeG
            GBand['band'] = GBand['band'].replace(np.nan, 0)
            GBand['error'] = Data_frame1["ant_magerr"]

            RBand = pd.DataFrame(columns = ["mjd", "band", "magnitude", "error", "event"])
            RBand["mjd"] = Data_frame2["ant_mjd"]
            RBand["band"] = pd.Series(np.ones([len(MagnitudeR)]))
            RBand["magnitude"] = MagnitudeR
            RBand['band'] = RBand['band'].replace(np.nan, 1)
            RBand['error'] = Data_frame2['ant_magerr']
            num = np.zeros(len(RBand))
            num1 = np.zeros(len(GBand))

            GBand['event'] = num1
            RBand['event'] = num

            GBand['class'] = num1
            RBand['class'] = num

            GBand['event'] = GBand['event'].replace([0], [str(i)])
            RBand['event'] = RBand['event'].replace([0], [str(i)])

            Band = pd.concat([GBand, RBand], axis = 0, ).reset_index(drop=True)
            Supernovadf = pd.concat([Supernovadf, Band], axis = 0).reset_index(drop=True)
            loop.set_description("Fetching Data...".format(len(i)))
            loop.update(1)

        loop.close()

        return(Supernovadf)

    def GaussianRegression(self, data = None, classification = True, DateRange = None, n_samples = 100):
        """

        Parameters
        ----------
        data : Pandas Data Frame, optional
            Pandas Data Frame with info from Data(); if None, it will pull data based off stored ZTF ID's.
            The default is None.
        classification : Boolean, optional
            If you are making a training set to True (I always keep it True personally, not sure if it works otherwise).
            The default is True.
        DateRange : Integer, optional
            How many days you want the classifier to look at. The default is None.
        n_samples : Integer, optional
            The number of samples GP Regression takes from the data. The default is 100.

        Returns
        -------
        Pandas Data Frame
            Pandas Data Frame of GP Regression Data.

        """
        def Multi_Band_GP(x_range, x, y, y_err, dim, n_samples = False, sampling = False):
            """ Considers cross corrolations between multiple bands as dims, prone to holding the order of the bands too rigidly """
            """ Will optimize for 'best' parameters when given no parameters """
            """ x = mjd, y and y_err = measurment, dim and dim_err = wavelength in nm """
            length_scale = 20
            signal_to_noises = (np.abs(y) / np.sqrt(np.power(y_err,2) + (1e-2 * np.max(y))**2))
            scale = np.abs(y[signal_to_noises.argmax()])
            kernel = ((0.5 * scale)**2 * george.kernels.Matern32Kernel([length_scale**2, 6000**2], ndim=2))
            kernel.freeze_parameter('k2:metric:log_M_1_1')
            kernel.freeze_parameter('k1:log_constant') #Fixed Scale
            x_data = np.vstack([x, dim]).T
            gp = george.GP(kernel, mean = biweight_location(y))
            guess_parameters = gp.get_parameter_vector()
            gp.compute(x_data, y_err)
            x_pred = np.linspace(x.min(), x.max(), n_samples)
            x_pred = np.vstack([x, dim]).T
            pred, pred_var = gp.predict(y, x_pred, return_var=True)
            # bounds = [(0, np.log(1000**2))]
            def neg_ln_like(p):
                gp.set_parameter_vector(p)
                return -gp.log_likelihood(y)
            def grad_neg_ln_like(p):
                gp.set_parameter_vector(p)
                return -gp.grad_log_likelihood(y)
            result = minimize(
                    neg_ln_like,
                    gp.get_parameter_vector(),
                    jac=grad_neg_ln_like,
                    # bounds=bounds
                    )
            if result.success:
                    gp.set_parameter_vector(result.x)
            else:
                    gp.set_parameter_vector(guess_parameters)
            gp.set_parameter_vector(result.x)
            # print(kernel.get_parameter_vector(True))
            #print("\nFinal ln-likelihood: {0:.2f}".format(gp.log_likelihood(y)))
            if n_samples != False:
                x_pred = np.vstack([np.array(list(np.linspace(x_range.min(), x_range.max(), n_samples))*np.unique(dim).size),
                                    np.array(np.sort(list(np.unique(dim))*n_samples))]).T
                # x_pred = np.vstack([np.array(list(np.linspace(x_range.min(), x_range.max(), n_samples))*6),
                #                     np.array(np.sort([357, 476, 621, 754, 870, 1004]*n_samples))]).T
                pred, pred_var = gp.predict(y, x_pred, return_var=True)
                output = [x_pred[:,0], pred, np.sqrt(pred_var), x_pred[:,1], []]
                return output
            elif sampling != False:
                x_pred = np.vstack([np.array(sampling[0]),
                                    np.array(sampling[1])]).T
                pred, pred_var = gp.predict(y, x_pred, return_var=True)
                output = [x_pred[:,0], pred, np.sqrt(pred_var), x_pred[:,1], []]
                return output

        def band_to_color(inp):
            labels = [357, 476, 621, 754, 870, 1004]
            # labels = [0,1,2,3,4,5]
            labels_2=['green', 'red', 'goldenrod', 'blue', 'pink', 'grey']
            outlst = []
            for x in inp:
                out = labels.index(int(x))
                out = labels_2[out]
                outlst.append(out)
            return outlst

        def band_to_wvlg(inp):
            labels = [0,1,2,3,4,5]
            labels_2=[357.0, 476.7, 621.5, 754.5, 870.75, 1004.0]
            outlst = []
            for x in inp:
                out = labels.index(int(x))
                out = labels_2[out]
                outlst.append(out)
            return outlst

        def expfun(x, a, b):
            return np.multiply(np.exp(np.multiply(x, b)), a)

        def randomoff(inp, off = 0.25):
            outlist = []
            for i in inp:
                value = random.random()
                outlist += [i+value*off]
            return outlist

        def Spectra_Model():
            return 0

        if data is None:
            sf = self.Data()
        else:
            sf = data
        Gaus = pd.DataFrame()
        pd.options.mode.chained_assignment = None  # default='warn'
        SN_uqlst = sf.event.unique()
        loop = tqdm(total = len(SN_uqlst), position =0, leave = False)

        for i in SN_uqlst:
            SNdf = sf[sf['event']==i]
            SNdf['mjd'] = SNdf['mjd'] - (SNdf['mjd'].min() -1)
            if DateRange is not None:
                SNdf = SNdf[SNdf['mjd'] < DateRange]
            b = SNdf['band'].unique() == np.array([0.0, 1.0])
            if b[0] != True or b[1] != True:
                continue
            mjdrange = np.asarray([min(SNdf['mjd'].tolist()),max(SNdf['mjd'].tolist())])
            D = Multi_Band_GP(x_range = mjdrange, x=SNdf['mjd'].to_numpy(),
                              y=SNdf['magnitude'].to_numpy(), y_err=SNdf['error'].to_numpy(),
                              dim=band_to_wvlg(SNdf['band'].to_numpy()),
                              n_samples= n_samples)
            GaussianFitted = pd.DataFrame()
            GaussianFitted['mjd'] = D[0]
            GaussianFitted['magnitude'] = D[1]
            GaussianFitted['error'] = D[2]
            GaussianFitted['band'] = D[3]
            y = pd.Series(data=np.zeros(1000)).astype(int)
            y = y.replace(0,i)
            GaussianFitted['event'] = y
            if classification == True:
                x = pd.Series(data = np.zeros(1000)).astype(int)
                x = x.replace(0, SNdf['class'].unique()[0])
                GaussianFitted['class'] = x
            Gaus = pd.concat([Gaus, GaussianFitted])
            loop.set_description("Computing GPR...".format(len(i)))
            loop.update(1)
        loop.close()
        return Gaus

    def Gpr_Graph(self, DateRange = None ,n_samples = 100):
            def band_to_color(inp):
                labels = [357, 476, 621, 754, 870, 1004]
                # labels = [0,1,2,3,4,5]
                labels_2=['green', 'red', 'goldenrod', 'blue', 'pink', 'grey']
                outlst = []
                for x in inp:
                    out = labels.index(int(x))
                    out = labels_2[out]
                    outlst.append(out)
                return outlst
            Gaussian = self.GaussianRegression(DateRange = DateRange,n_samples = n_samples)
            for i in Gaussian['event'].unique():
                plt.errorbar(Gaussian[Gaussian['event']==i]['mjd'],Gaussian[Gaussian['event']==i]['magnitude'],Gaussian[Gaussian['event']==i]['error'], c=band_to_color(Gaussian[Gaussian['event']==i]['band']), alpha = 0.2, ls = 'None')

                #plt.errorbar(x = SNdf['mjd'].to_numpy(), y = SNdf['magnitude'].to_numpy(), yerr = SNdf['error'].to_numpy(), ls = 'None')
                plt.xlabel("MJD")
                plt.ylabel("Magnitude")
                plt.title(i)
                plt.gca().invert_yaxis()
                plt.show()
                plt.close()

    def Wavelet(self, Data = None, WaveletType = 'sym2', classification = True, Date = None, length = 150):
        """

        Parameters
        ----------
        Note: This version Processes both bands seperately, see Wavelet2() for multiband processing

        Data : Pandas Data Frame, optional
            Pandas DataFrame processed by Data(). The default is None.
        WaveletType : Str, optional
            Type of Wavelet transformation to be used. The default is 'sym2'.
        classification : Boolean, optional
            If you are making a training set to True (I always keep it True personally, not sure if it works otherwise).
            The default is True.
        Date : Integer, optional
            How many days you want the classifier to look at. The default is None. The default is None.
        length : Integer, optional
            Set maximum event length; all events longer than set length are filtered out. The default is 150.

        Returns
        -------
        Function_Parameters : Pandas DataFrame
            Event Information such as ZTF ID and classification.
        Coefficients : Numpy Array
            List of Wavelet transformation Coefficients.

        """

        from tqdm import tqdm
        Function_Parameters = pd.DataFrame()
        Coefficients = list()

        if Data is None:
            Data = self.Data()
        Gaussian = self.GaussianRegression(data = Data, DateRange = Date)

        Data_uqlst = Data['event'].unique()
        loop = tqdm(total = len(Data['event'].unique()), position =0, leave = False)

        for i in Data_uqlst:

            b = Data[(Data['event']==i)]['band'].unique() == np.array([0.0, 1.0])
            if b[0] != True or b[1] != True:
                continue

            if max(Data[Data['event']==i]['mjd'])-min(Data[Data['event']==i]['mjd']) > length:
                #print(len(Data[Data['event']==i]['mjd']))
                continue
            else:
                GaussianFitted = Gaussian[Gaussian['event']==i]
                Uqe_Bands = GaussianFitted['band'].unique()

                for UBand in Uqe_Bands:
                    if classification == True:
                        Class = GaussianFitted[GaussianFitted['band']==UBand]['class']

                    x = GaussianFitted[GaussianFitted['band']==UBand]['mjd'].astype(float)
                    y = GaussianFitted[GaussianFitted['band']==UBand]['magnitude'].astype(float)
                    y_err = GaussianFitted[GaussianFitted['band']==UBand]['error'].astype(float)
                    signal = y.values.squeeze()

                    ca = np.array(pywt.swt(np.array(signal), WaveletType, level = 2, axis = 0))

                    npoints=len(ca[0, 0, :])
                    coefficients =ca.reshape(2*2, npoints)

                    Features = pd.DataFrame(data = {'band': [UBand], 'event': str(i),
                                                    'delta':y.values.max()-y.values.min(), 'variance':y.var(),
                                                    'duration': max(Data[Data['event']==i]['mjd'])-min(Data[Data['event']==i]['mjd'])})
                    if classification == True:
                        Features['class'] = Class.unique()[0]

                    Coefficients.append(coefficients.flatten())

                    Function_Parameters = pd.concat([Function_Parameters, Features], axis =0 )
                    Function_Parameters = Function_Parameters.reset_index(drop=True)
            loop.set_description("Computing Wavelet Transform...".format(len(i)))
            loop.update(1)
        loop.close()
        Function_Parameters['class'] = Function_Parameters['class'].replace(['SN Ia', 'SN II', 'SN Ib/c', 'SLSN'], [0,1,2,3])
        #Function_Parameters['class'] = Function_Parameters['class'].replace(['SN Ia', 'SN II', 'SN IIn', 'SN IIP', 'SN Ia-91T', 'SLSN-I', 'SLSN-II', 'SN Ic', 'SN Ib', 'SN Ic-BL', 'SN IIb', 'SN Ia-pec', 'SN Ibn', 'SN Ia-91bg'], [0,1,2,3,4,5,6,7,8,9, 10,11,12,13])

        return Function_Parameters, Coefficients

    def Wavelet2(self, Data = None, WaveletType = 'sym2', classification = True, Date = None, length = 150):
        """

        Parameters
        ----------
        Note: This version Processes both bands together, see Wavelet() for seperate band processing

        Data : Pandas Data Frame, optional
            Pandas DataFrame processed by Data(). The default is None.
        WaveletType : Str, optional
            Type of Wavelet transformation to be used. The default is 'sym2'.
        classification : Boolean, optional
            If you are making a training set to True (I always keep it True personally, not sure if it works otherwise).
            The default is True.
        Date : Integer, optional
            How many days you want the classifier to look at. The default is None. The default is None.
        length : Integer, optional
            Set maximum event length; all events longer than set length are filtered out. The default is 150.

        Returns
        -------
        Function_Parameters : Pandas DataFrame
            Event Information such as ZTF ID and classification.
        Coefficients : Numpy Array
            List of Wavelet transformation Coefficients.

        """

        from tqdm import tqdm
        Function_Parameters = pd.DataFrame()
        Coefficients = list()

        if Data is None:
            Data = self.Data()
        Gaussian = self.GaussianRegression(data = Data, DateRange = Date)

        Data_uqlst = Data['event'].unique()
        loop = tqdm(total = len(Data['event'].unique()), position =0, leave = False)

        for i in Data_uqlst:

            b = Data[(Data['event']==i)]['band'].unique() == np.array([0.0, 1.0])
            if b[0] != True or b[1] != True:
                continue

            if max(Data[Data['event']==i]['mjd'])-min(Data[Data['event']==i]['mjd']) > length:
                #print(len(Data[Data['event']==i]['mjd']))
                continue

            GaussianFitted = Gaussian[Gaussian['event']==i]

            if classification == True:
                Class = GaussianFitted['class']

            x = GaussianFitted['mjd'].astype(float)
            y = GaussianFitted['magnitude'].astype(float)
            y_err = GaussianFitted['error'].astype(float)
            signal = y.values.squeeze()
            if len(signal) == 0:
                continue
            from scipy import integrate
            Area = integrate.simpson(y, x)

            ca = np.array(pywt.swt(np.array(signal), WaveletType, level = 2, axis = 0))

            npoints=len(ca[0, 0, :])
            coefficients =ca.reshape(2*2, npoints)

            Features = pd.DataFrame(data = {'event': str(i),
                                            'delta':y.values.max()-y.values.min(), 'variance':y.var(),
                                            'duration': max(Data[Data['event']==i]['mjd'])-min(Data[Data['event']==i]['mjd']),
                                            'area':Area}, index=[0])
            if classification == True:
                Features['class'] = Class.unique()[0]

            Coefficients.append(coefficients.flatten())

            Function_Parameters = pd.concat([Function_Parameters, Features], axis =0 )
            Function_Parameters = Function_Parameters.reset_index(drop=True)
            loop.set_description("Computing Wavelet Transform...".format(len(i)))
            loop.update(1)
        loop.close()
        Function_Parameters['class'] = Function_Parameters['class'].replace(['SN Ia', 'SN II', 'SN Ib/c', 'SLSN'], [0,1,2,3])
        #Function_Parameters['class'] = Function_Parameters['class'].replace(['SN Ia', 'SN II', 'SN IIn', 'SN IIP', 'SN Ia-91T', 'SLSN-I', 'SLSN-II', 'SN Ic', 'SN Ib', 'SN Ic-BL', 'SN IIb', 'SN Ia-pec', 'SN Ibn', 'SN Ia-91bg'], [0,1,2,3,4,5,6,7,8,9, 10,11,12,13])

        return Function_Parameters, Coefficients

    def DimensionalityReduction2(self, Coefficients =None, labels=None, smot = False, n = 20, Trainset = True):
        """

        Parameters
        ----------
        Use this version if you used Wavelet2() (Multiband processing)

        Coefficients : Pandas Data Frame, optional
            Provide your own wavelet coefficients. The default is None.
        labels : Pandas Data Frame, optional
            Provide your own labels. The default is None.
        smot : Boolean, optional
            Choose whether or not to use SMOTE. The default is False.
        n : Integer, optional
            Output Dimension. The default is 20.
        Trainset : Boolean, optional
            Specify if this is the training set or if its unlabeled data. The default is True.

        Returns
        -------
        Pandas Data Frame
            Pandas Data Frame of PCA reduced Wavelet Coefficients.
        Function
            If Trainset = True, returns PCA() to use on unlabeled data.

        """
        if Coefficients is not None:
            labels = labels
            Coefficients = Coefficients
        else:
            labels, Coefficients = self.Wavelet()

        Coefficients = pd.concat([pd.DataFrame(data=labels),pd.DataFrame(data=Coefficients)],axis=1)

        Coeff = Coefficients.iloc[:,6:]

        pca = PCA(n_components = n, whiten = True)
        if smot == True:
            sm = SMOTE()
            Coeff, labels= sm.fit_resample(Coeff, Coefficients['class'].ravel())

        print(Coeff)
        final = pca.fit_transform((Coeff))
        #RBand2, GBand2 = pd.DataFrame(data = {'Rdelta': RBand['delta'], 'Rvariance': RBand['variance']}), pd.DataFrame(data = {'Gdelta':GBand['delta'], 'Gvariance': GBand['variance']})
        if smot == True:
            events =pd.DataFrame(data = {'class': labels}).reset_index(drop=True)
        if smot == False:
            events =pd.DataFrame(data = {'event': Coefficients['event'], 'class': Coefficients['class']}).reset_index(drop=True)
        if Trainset == True:
            return pd.concat([events, pd.DataFrame(final)],axis=1), pca
        if Trainset == False:
            return pd.concat([events, pd.DataFrame(data = Coeff).reset_index(drop=True)],axis=1)

    def DimensionalityReduction(self, Coefficients =None, labels=None, smot = False, n = 20, Trainset = True):
        """

        Parameters
        ----------
        Use this version if you used Wavelet() (One band at a time processing)

        Coefficients : Pandas Data Frame, optional
            Provide your own wavelet coefficients. The default is None.
        labels : Pandas Data Frame, optional
            Provide your own labels. The default is None.
        smot : Boolean, optional
            Choose whether or not to use SMOTE. The default is False.
        n : Integer, optional
            Output Dimension. The default is 20.
        Trainset : Boolean, optional
            Specify if this is the training set or if its unlabeled data. The default is True.

        Returns
        -------
        Pandas Data Frame
            Pandas Data Frame of PCA reduced Wavelet Coefficients.
        Function
            If Trainset = True, returns PCA() to use on unlabeled data.

        """
        if Coefficients is not None:
            labels = labels
            Coefficients = Coefficients
        else:
            labels, Coefficients = self.Wavelet()

        Coefficients = pd.concat([pd.DataFrame(data=labels),pd.DataFrame(data=Coefficients)],axis=1)

        GBand, RBand = Coefficients[Coefficients['band']==357.0].reset_index(drop=True), Coefficients[Coefficients['band']==476.7].reset_index(drop=True)
        print(RBand)
        pca = PCA(n_components = n, whiten = True)
        RBand = pd.concat([RBand.iloc[:,6:].reset_index(drop=True),GBand.iloc[:,6:].reset_index(drop=True)],axis=1, ignore_index=True)
        if smot == True:
            sm = SMOTE()
            RBand, labels= sm.fit_resample(RBand, GBand['class'].ravel())

        final = pca.fit_transform((RBand))
        #RBand2, GBand2 = pd.DataFrame(data = {'Rdelta': RBand['delta'], 'Rvariance': RBand['variance']}), pd.DataFrame(data = {'Gdelta':GBand['delta'], 'Gvariance': GBand['variance']})
        if smot == True:
            events =pd.DataFrame(data = {'class': labels}).reset_index(drop=True)
        if smot == False:
            events =pd.DataFrame(data = {'event': GBand['event'], 'class': GBand['class']}).reset_index(drop=True)
        if Trainset == True:
            return pd.concat([events, pd.DataFrame(final)],axis=1), pca
        if Trainset == False:
            return pd.concat([events, pd.DataFrame(data = RBand).reset_index(drop=True)],axis=1)

    def SupernovaTrainer(self, Train = None, y = None, **kwargs):
        """

        Parameters
        ----------
        Trains for Supernova vs Bogus Classification

        Train : Pandas Data Frame, optional
            Provide your own wavelet coefficients. The default is None.
        y : Pandas Data Frame, optional
            Provide data labels. The default is None.
        **kwargs : Classifier arguments
            Input arguments for classifier.

        Returns
        -------
        Function
            Trained Classifier.

        """
        if Train is None:
            Data = self.DimensionalityReduction()
            Train = Data.iloc[:,2:].reset_index(drop=True)
            y = Data['class'].reset_index(drop=True)
        svc = RandomForestClassifier(random_state=iterations, n_estimators = 30, min_samples_split = 6)

        if kwargs:
            classifier=AdaBoostClassifier(**kwargs)
        else:
            classifier=AdaBoostClassifier(base_estimator=svc,n_estimators=30, learning_rate =4)

        if evaluate == True:
            pipeline = imbpipeline(steps = [['classifier', classifier]])
            stratified_kfold = StratifiedKFold(n_splits=3, shuffle=True)
            print(cross_validate(pipeline, np.array(Train),np.array(y).ravel(),scoring = 'accuracy'))
            y_pred = cross_val_predict(pipeline, np.array(Train),np.array(y), cv = stratified_kfold)
            conf_mat = confusion_matrix(y, y_pred)
            plot_confusion_matrix1(conf_mat, ['SN', 'Bogus'], cmap = 'Blues')

        return classifier.fit(Train, y)

    def SupernovaTypeClassifierTrainer(self, Train, y, evaluate = True , smot = True,
                                       Ada = True, KNN = False,roc = True, Rand = False,
                                       grid = False, n = 1, fold = 3,n_components = 20,
                                       metric = 'accuracy', param_grid = None,**kwargs):
        """

        Parameters
        ----------
        Trains for Supernova Type Classification

        Train : Pandas Data Frame, optional
            Provide your own wavelet coefficients. The default is None.
        y : Pandas Data Frame, optional
            Provide data labels. The default is None.
        evaluate : Boolean, optional
            Choose whether or not to show model performance. The default is True.
        Ada : Boolean, optional
            Choose to use Ada Boosted Random Forrest. The default is True.
        KNN : Boolean, optional
            Choose to use K-nearest neighbors. The default is False.
        **kwargs : TYPE
            DESCRIPTION.

        Raises
        ------
        Exception
            If you set both KNN and Ada to false, raises an error.

        Returns
        -------
        Function
            Trained Classifier.

        """
        if Train is not None:
            TrainingData, u = pd.concat([pd.DataFrame(data=y),pd.DataFrame(data=Train)],axis=1).reset_index(drop=True), y
        #else *** Remember to make this load in default training data
        svc = RandomForestClassifier(n_estimators = 30, min_samples_split = 6)
        TrainingData = TrainingData.sample(frac = 1).reset_index(drop=True)
        if kwargs:
            if Ada ==True:
                classifier = AdaBoostClassifier(**kwargs)
            if KNN == True:
                classifier = KNeighborsClassifier(**kwargs)
            if Rand == True:
                #classifier = RandomForestClassifier(**kwargs)
                classifier = BalancedRandomForestClassifier(**kwargs)

        else:
            classifier=AdaBoostClassifier(base_estimator=svc,n_estimators=30, learning_rate =2)
        #classifier = KNeighborsClassifier(n_neighbors=1500)

        if evaluate == True:

            if smot == True:
                pipeline = imbpipeline(steps = [['scale',MinMaxScaler()],['smote', SMOTE()],['classifier', classifier]])
            if smot == False:
                pipeline = imbpipeline(steps = [['scale',MinMaxScaler()],['classifier', classifier]])
            stratified_kfold = StratifiedKFold(n_splits=fold, shuffle=True)
            repeatstratified_kfold = RepeatedStratifiedKFold(n_splits=fold, n_repeats=n)
            cross = cross_validate(pipeline, np.array(TrainingData.iloc[:,1:]),np.array(TrainingData.iloc[:,0]),scoring = metric, cv = repeatstratified_kfold, n_jobs = -1)
            print(f'The mean {metric} over {fold} fold stratified crossvalidation repeated {n} times is {np.mean(cross["test_score"])}, with a standard deviation of {np.std(cross["test_score"])}')
            y_pred = cross_val_predict(pipeline, np.array(TrainingData.iloc[:,1:]),np.array(TrainingData.iloc[:,0]), cv = stratified_kfold, n_jobs = -1)

            #conf_mat = confusion_matrix(y, y_pred)
            conf_mat = confusion_matrix(TrainingData.iloc[:,0], y_pred)
            disp = ConfusionMatrixDisplay(confusion_matrix=conf_mat)
            disp.plot(cmap = 'Blues')

            if grid == True:
                clf = GridSearchCV(pipeline, param_grid, n_jobs = -1, cv = stratified_kfold, scoring = 'f1_micro', verbose = 1)
                clf.fit(TrainingData.iloc[:,1:], TrainingData.iloc[:,0])

            plot_confusion_matrix1(conf_mat, ['Type 1a','Type 2', 'Type 1b/c', 'SLSN'], cmap = 'Blues')

        Classifier = pipeline.fit(TrainingData.iloc[:,1:], TrainingData.iloc[:,0])

        if grid == False:
            return Classifier
        if grid == True:
            return clf

def plot_confusion_matrix1(cm,
                          target_names,
                          title='Confusion matrix',
                          cmap=None,
                          normalize=True):
    """
    given a sklearn confusion matrix (cm), make a nice plot

    Arguments
    ---------
    cm:           confusion matrix from sklearn.metrics.confusion_matrix

    target_names: given classification classes such as [0, 1, 2]
                  the class names, for example: ['high', 'medium', 'low']

    title:        the text to display at the top of the matrix

    cmap:         the gradient of the values displayed from matplotlib.pyplot.cm
                  see http://matplotlib.org/examples/color/colormaps_reference.html
                  plt.get_cmap('jet') or plt.cm.Blues

    normalize:    If False, plot the raw numbers
                  If True, plot the proportions

    Usage
    -----
    plot_confusion_matrix(cm           = cm,                  # confusion matrix created by
                                                              # sklearn.metrics.confusion_matrix
                          normalize    = True,                # show proportions
                          target_names = y_labels_vals,       # list of names of the classes
                          title        = best_estimator_name) # title of graph

    Citiation
    ---------
    http://scikit-learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html

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

    accuracy = np.trace(cm) / np.sum(cm).astype('float')
    misclass = 1 - accuracy

    if cmap is None:
        cmap = plt.get_cmap('Blues')

    plt.figure(figsize=(8, 6))
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()

    if target_names is not None:
        tick_marks = np.arange(len(target_names))
        plt.xticks(tick_marks, target_names, rotation=45)
        plt.yticks(tick_marks, target_names)

    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    thresh = cm.max() / 1.5 if normalize else cm.max() / 2
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        if normalize:
            plt.text(j, i, "{:0.4f}".format(cm[i, j]),
                     horizontalalignment="center",
                     color="black" if cm[i, j] > thresh else "black")
        else:
            plt.text(j, i, "{:,}".format(cm[i, j]),
                     horizontalalignment="center",
                     color="black" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label\naccuracy={:0.4f}; misclass={:0.4f}'.format(accuracy, misclass))
    plt.show()


import os
from multiprocessing.dummy import Pool as ThreadPool

# Set your opensmile Extracter and path here
exe_opensmile = './opensmile/bin/SMILExtract.exe'
path_config = './opensmile/config/prosody/prosodyShs.conf'

# Set your data path and output path here
data_path = "./wav/"
save_path = './features/'  # output folder

# Extractor set-ups
opensmile_options = '-C ' + path_config

def feature_extract(fn):
    infilename = data_path + fn
    outfilename = save_path + fn[:-4] + ".csv"
    opensmile_call = exe_opensmile + ' ' + opensmile_options + \
        ' -I ' + infilename + ' -csvoutput ' + outfilename + \
        ' -start 60 -end 600'
    print(opensmile_call)
    os.system(opensmile_call)

for root, dirs, files in os.walk(data_path):
    for name in files:
        feature_extract(name)
    # print(files)
    # pool = ThreadPool()
    # pool.map(feature_extract, files)
    # pool.close()
    # pool.join()


# original paper setting: -/77.21/87.85
# add char-cnn 200d: 57.30/77.64/87.75
# 1 layer highway body->subject<->comment: 56/76/86
# 1 layer unshared tanh body->subject<->comment: 57.51/77.18/86.41
import tensorflow as tf

# inpa,inpb (b,m,d) maska,maskb (b,m,1)
def ps_pb_interaction(ps, pb, ps_mask, pb_mask, keep_prob, scope):
    """
    Question Condensing 部分
    :param ps:
    :param pb:
    :param ps_mask:
    :param pb_mask:
    :param keep_prob:
    :param scope:
    :return:
    """
    with tf.variable_scope(scope):
        b, m, n, d = tf.shape(ps)[0], tf.shape(ps)[1], tf.shape(pb)[1], ps.get_shape().as_list()[2]
        attn_mask = tf.expand_dims(ps_mask * tf.reshape(pb_mask, [b, 1, n]), -1)     # (b,m,n,1)   (b,1,n --->b,m,n--->b,m,n,1)

        head = tf.tile(tf.expand_dims(ps, 2), [1, 1, n, 1])                          # (b,m,1,d)
        tail = tf.tile(tf.expand_dims(pb, 1), [1, m, 1, 1])                          # (b,1,n,d)
        parallel = head * tf.reduce_sum(head * tail, -1, True)/(tf.reduce_sum(head * head, -1, True)+1e-5)  # 公式1
        orthogonal = tail - parallel                                                                        # 公式2
        base = parallel if scope == 'parallel' else orthogonal

        interaction = dense(base, d, scope='interaction')    # (b,m,n,d)
        logits = 10.0*tf.tanh((interaction)/10.0) + (1 - attn_mask) * (-1e30)                               # 公式3

        attn_score = tf.nn.softmax(logits, 2) * attn_mask                                                   # 公式4
        attn_result = tf.reduce_sum(attn_score * tail, 2)                           # (b,m,d)               # 公式5
        fusion_gate = dense(tf.concat([ps, attn_result], -1), d, tf.sigmoid, scope='fusion_gate')*ps_mask   # 公式6
        return (fusion_gate*ps + (1-fusion_gate)*attn_result) * ps_mask                                     # 公式7

# inpa,inpb (b,m,d) maska,maskb (b,m,1)
def pq_interaction(ps, qt, ps_mask, qt_mask, keep_prob, scope):
    """
    问答交互部分，返回Satt和Catt
    :param ps:         Srep
    :param qt:         Crep
    :param ps_mask:
    :param qt_mask:
    :param keep_prob:
    :param scope:
    :return:
    """
    with tf.variable_scope(scope):
        b, m, n, d = tf.shape(ps)[0], tf.shape(ps)[1], tf.shape(qt)[1], ps.get_shape().as_list()[2]
        attn_mask = tf.expand_dims(ps_mask*tf.reshape(qt_mask,[b,1,n]), -1)             # (b,m,n,1)

        head = tf.tile(tf.expand_dims(ps, 2), [1,1,n,1])                          # (b,m,1,d)
        tail = tf.tile(tf.expand_dims(qt, 1), [1,m,1,1])                          # (b,1,n,d)

        interaction = dense(tf.concat([head, tail], -1), d, scope='interaction')    # (b,m,n,d)         公式9
        #interaction = tf.reduce_sum(head*tail, -1, True)
        #interaction = tf.reduce_sum(dense(head, d, scope='interaction')*tail, -1, True)

        logits = 5.0*tf.tanh((interaction)/5.0) + (1 - attn_mask) * (-1e30)                           # 公式10

        atta_score = tf.nn.softmax(logits, axis=2) * attn_mask                                             # 公式11左部权重计算
        atta_result = tf.reduce_sum(atta_score * tail, axis=2)                           # (b,m,d)         # 公式11--->S ai

        attb_score = tf.nn.softmax(logits, 1) * attn_mask                                             # 公式12左部权重计算
        attb_result = tf.reduce_sum(attb_score * head, 1)                       # (b,n,d)               公式12--->C ai

        cata = tf.concat([ps, atta_result], -1) * ps_mask   # S att
        catb = tf.concat([qt, attb_result], -1) * qt_mask   # C att
        return cata, catb  # Satt和Catt

def source2token(rep_tensor, rep_mask, keep_prob, scope):
    """

    :param rep_tensor: Satt
    :param rep_mask:
    :param keep_prob:
    :param scope:
    :return:
    """
    with tf.variable_scope(scope):
        ivec = rep_tensor.get_shape().as_list()[2]
        map1 = dense(rep_tensor, ivec, tf.nn.elu, keep_prob, 'map1')*rep_mask  # (b,n,d)  # 公式13
        map2 = dense(rep_tensor, ivec, tf.identity, keep_prob, 'map2')*rep_mask  # (b,n,d)
        map2_masked = map1 + (1-rep_mask) * (-1e30)
        soft = tf.nn.softmax(map2_masked, 1)*rep_mask   # bs,sl,vec
        return tf.reduce_sum(soft * rep_tensor, 1)      # bs, vec  # 公式14

def dense(inp, out_size, activation=tf.identity, keep_prob=1.0, scope=None, need_bias=True):
    with tf.variable_scope(scope):
        inp_shape = [inp.get_shape().as_list()[i] or tf.shape(inp)[i] for i in range(len(inp.get_shape().as_list()))]  # 获取shape列表
        input = tf.nn.dropout(tf.reshape(inp, [-1, inp_shape[-1]]), keep_prob)
        W = tf.get_variable('W', shape=[input.get_shape()[-1],out_size],dtype=tf.float32)
        b = tf.get_variable('b', shape=[out_size], dtype=tf.float32, initializer=tf.zeros_initializer()) if need_bias else 0
        return activation(tf.reshape(tf.matmul(input, W) + b, inp_shape[:-1] + [out_size]))


from gym_compete_rllib import create_env
from ray.tune.registry import ENV_CREATOR, _global_registry

def test_create_env():
    env_creator = _global_registry.get(ENV_CREATOR, "multicomp")
    env_config = {'with_video': False,
                  "SingleAgentToMultiAgent": False,
                  "env_name": "multicomp/YouShallNotPassHumans-v0"}
    env = env_creator(env_config)

    assert env.n_policies == 2
    assert env.observation_space.shape == (380,)
    assert env.action_space.shape == (17,)
    assert env.player_names == ['player_1', 'player_2']

    def episode(env):
        obs = env.reset()
        def check_obs(obs, error_on_empty=True):
            assert isinstance(obs, dict)
            if error_on_empty:
                assert set(obs.keys()) == set(env.player_names), f"{obs.keys()} {env.player_names}"
            assert all([o.shape == env.observation_space.shape for o in obs.values()])
        check_obs(obs)
        while True:
            actions = {p: env.action_space.sample() for p in env.player_names}
            obs, reward, done, info = env.step(actions)
            check_obs(obs, error_on_empty=False)
            if done['__all__']:
                break

    for _ in range(10):
        episode(env)

if __name__ == '__main__':
    test_create_env()


import json, requests, pytest
from pydantic import BaseModel, field_validator
from unittest.mock import Mock, MagicMock

class Location:
    def __init__(self, longitudecls, latitudecls):
        self._longitude = longitudecls
        self._latitude = latitudecls

    def get_weather(self):
        weather_data = requests.get(
            f'https://fcc-weather-api.glitch.me/api/current?lat={self._latitude}&lon={self._longitude}')
        data = json.loads(weather_data.text)
        try:
            if weather_data.status_code != 200:
                raise Exception(f'Error request, status code : {weather_data.status_code}')
            try:
                feels_like_temp = data.get['main']['feels_like']
            except:
                feels_like_temp = 0
            dict_for_weather = {
                'temperature': {
                    'temp': data['main']['temp'],
                    'feels_like': feels_like_temp,
                    'temp_min': data['main']['temp_min'],
                    'temp_max': data['main']['temp_max']
                },
                'pressure': data['main']['pressure'],
                'description': data['weather'][0]['description'],
                'name': data['name']
            }
        except Exception as e:
            return None
        return WeatherPydantic(**dict_for_weather)

class TemperaturePydantic(BaseModel):
    temp: float
    feels_like: float
    temp_min: float
    temp_max: float

    @field_validator('temp')
    def validate_temp(cls, temp: int):
        return round(temp * 1.8 + 32, 3)

class WeatherPydantic(BaseModel):
    temperature: TemperaturePydantic
    pressure: float
    description: str
    name: str

# longitude = int(input('Please enter longitude: '))
# latitude = int(input('Please inter latitude: '))
loc = Location(50, 38)
weather = loc.get_weather()
print(weather)

def test_get_weather(mocker):
    mocker.patch.object(
        requests,
        'get',
        return_value=Mock(
            status_code=200,
            text=json.dumps(

                    {
                        "coord": {
                            "lon": 50,
                            "lat": 28
                        }, "weather": [
                            {
                                "id": 800,
                                "main": "Clear",
                                "description": "clear sky",
                            }
                        ],
                        "base": "stations",
                        "main": {
                             "temp": 33.27,
                             "feels_like": 0.0,
                             "temp_min": 33.27,
                             "temp_max": 33.27,
                             "pressure": 1001,
                             "humidity": 72,
                             "sea_level": 1001,
                             "grnd_level": 1001
                         },
                        "visibility": 10000,
                        "wind": {
                             "speed": 3.25,
                             "deg": 258,
                             "gust": 3.6
                         },
                        "clouds": {
                             "all": 1
                         },
                        "dt": 1691623796,
                        "sys": {
                             "country": "SA",
                             "sunrise": 1691633230,
                             "sunset": 1691681029},
                        "timezone": 12600,
                        "id": 109435,
                        "name": "Jubail",
                        "cod": 200
                    }

            )
        )
    )
    test_loc = Location(50, 28)
    actual = test_loc.get_weather()
    expected = WeatherPydantic(
        temperature=TemperaturePydantic.model_construct(
            temp=round(33.27*1.8 + 32, 3),
            feels_like=0.00,
            temp_min=33.27,
            temp_max=33.27
        ),
        pressure=1001,
        description='clear sky',
        name='Jubail',
    )
    assert actual == expected


import gc
import sys
import wx
from weakref import ref
from testutil import check_collected

foo = 0
success = 0

def test_callafter_leak():
    def func():
        global foo
        foo = 42

    wr = ref(func)
    wx.CallAfter(func)
    del func

    # make sure that func runs
    wx.GetApp().Yield()

    assert wr() is None, gc.get_referrers(gc.get_referrers(wr())[0])
    assert foo == 42

    global success
    success = success + 1

def main():
    a = wx.PySimpleApp()

    N = 100

    for x in xrange(N):
        wx.CallAfter(test_callafter_leak)

    wx.CallAfter(gc.collect)

    for x in xrange(N):
        wx.CallAfter(test_callafter_leak)

    wx.CallAfter(a.ExitMainLoop)
    a.MainLoop()

    global success
    assert success == N*2

if __name__ == '__main__':
    main()


#!/usr/bin/env python

# Demonstrate how to use the vtkBoxWidget to control volume rendering
# within the interior of the widget.

import vtk
from vtk.util.misc import vtkGetDataRoot
VTK_DATA_ROOT = vtkGetDataRoot()

# Load a volume, use the widget to control what's volume
# rendered. Basically the idea is that the vtkBoxWidget provides a box
# which clips the volume rendering.
v16 = vtk.vtkVolume16Reader()
v16.SetDataDimensions(64, 64)
v16.GetOutput().SetOrigin(0.0, 0.0, 0.0)
v16.SetDataByteOrderToLittleEndian()
v16.SetFilePrefix(VTK_DATA_ROOT+ "/Data/headsq/quarter")
v16.SetImageRange(1, 93)
v16.SetDataSpacing(3.2, 3.2, 1.5)

tfun = vtk.vtkPiecewiseFunction()
tfun.AddPoint(70.0, 0.0)
tfun.AddPoint(599.0, 0)
tfun.AddPoint(600.0, 0)
tfun.AddPoint(1195.0, 0)
tfun.AddPoint(1200, .2)
tfun.AddPoint(1300, .3)
tfun.AddPoint(2000, .3)
tfun.AddPoint(4095.0, 1.0)

ctfun = vtk.vtkColorTransferFunction()
ctfun.AddRGBPoint(0.0, 0.5, 0.0, 0.0)
ctfun.AddRGBPoint(600.0, 1.0, 0.5, 0.5)
ctfun.AddRGBPoint(1280.0, 0.9, 0.2, 0.3)
ctfun.AddRGBPoint(1960.0, 0.81, 0.27, 0.1)
ctfun.AddRGBPoint(4095.0, 0.5, 0.5, 0.5)

compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()

volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetInputConnection(v16.GetOutputPort())
volumeMapper.SetVolumeRayCastFunction(compositeFunction)

volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(ctfun)
volumeProperty.SetScalarOpacity(tfun)
volumeProperty.SetInterpolationTypeToLinear()
volumeProperty.ShadeOn()

newvol = vtk.vtkVolume()
newvol.SetMapper(volumeMapper)
newvol.SetProperty(volumeProperty)

outline = vtk.vtkOutlineFilter()
outline.SetInputConnection(v16.GetOutputPort())
outlineMapper = vtk.vtkPolyDataMapper()
outlineMapper.SetInputConnection(outline.GetOutputPort())
outlineActor = vtk.vtkActor()
outlineActor.SetMapper(outlineMapper)

# Create the RenderWindow, Renderer and both Actors
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

# The SetInteractor method is how 3D widgets are associated with the
# render window interactor. Internally, SetInteractor sets up a bunch
# of callbacks using the Command/Observer mechanism (AddObserver()).
boxWidget = vtk.vtkBoxWidget()
boxWidget.SetInteractor(iren)
boxWidget.SetPlaceFactor(1.0)

# Add the actors to the renderer, set the background and size
ren.AddActor(outlineActor)
ren.AddVolume(newvol)

ren.SetBackground(0, 0, 0)
renWin.SetSize(300, 300)

# When interaction starts, the requested frame rate is increased.
def StartInteraction(obj, event):
    global renWin
    renWin.SetDesiredUpdateRate(10)

# When interaction ends, the requested frame rate is decreased to
# normal levels. This causes a full resolution render to occur.
def EndInteraction(obj, event):
    global renWin
    renWin.SetDesiredUpdateRate(0.001)

# The implicit function vtkPlanes is used in conjunction with the
# volume ray cast mapper to limit which portion of the volume is
# volume rendered.
planes = vtk.vtkPlanes()
def ClipVolumeRender(obj, event):
    global planes, volumeMapper
    obj.GetPlanes(planes)
    volumeMapper.SetClippingPlanes(planes)

# Place the interactor initially. The output of the reader is used to
# place the box widget.
boxWidget.SetInput(v16.GetOutput())
boxWidget.PlaceWidget()
boxWidget.InsideOutOn()
boxWidget.AddObserver("StartInteractionEvent", StartInteraction)
boxWidget.AddObserver("InteractionEvent", ClipVolumeRender)
boxWidget.AddObserver("EndInteractionEvent", EndInteraction)

outlineProperty = boxWidget.GetOutlineProperty()
outlineProperty.SetRepresentationToWireframe()
outlineProperty.SetAmbient(1.0)
outlineProperty.SetAmbientColor(1, 1, 1)
outlineProperty.SetLineWidth(3)

selectedOutlineProperty = boxWidget.GetSelectedOutlineProperty()
selectedOutlineProperty.SetRepresentationToWireframe()
selectedOutlineProperty.SetAmbient(1.0)
selectedOutlineProperty.SetAmbientColor(1, 0, 0)
selectedOutlineProperty.SetLineWidth(3)

iren.Initialize()
renWin.Render()
iren.Start()


"""
Name:Hrishikesh Moholkar
file:wordData.py
This file is the main file for
all other working files
"""

from rit_lib import*

class YearCount(struct):
    """
    slots for class:
    year: integer representing particular year
    count:an integer representing count for that year
    return:none
    """
    _slots=((int,"year"),(int,"count"))

class WordTrend(struct):
    """
    slots for class:
    word: string representing word
    trend:an integer representing count for that year
    return:none

    """
    _slots=((str,"word"),(float,"trend"))

def readWordFile(filename):
    """
    this function reads the file and returns dictionary
    containing keys as words and values as list of yearcount objects.
    :param filename: input file
    :return:dictionary
    """
    words=dict()
    list1=[]
    for line in open("data"+ '/' + filename):
        if "," not in line:
          word=line.strip()
          words[word]=""

        else:
          x1= [append(line)]

          if words.get(word)!= "":
             words[word] = words.get(word) + x1;
          else:
            words[word] = x1;
    return (words)

def append(value):
    """
    this helper function returns yearcount object
    and appends to list
    :param value:
    :return:yearcount object
    """
    temp=[]
    temp=value.split(",")
    x=YearCount(int(temp[0]),int(temp[1]))
    return x

def totalOccurrences(word,words):
   """
   this function counts the total occurences of
    a word
   :param word:desired word entered
   :param words:dictionary containing keys
   :return:total number of times that word has appeared in print
   """
   x=words[word]
   count2=0
   if word in words.keys():
       for i in range(0,len(x)):
           count1=x[i].count
           count2=count2+count1
   else:
       print("no key")
   return count2

if __name__ == "__main__" :
    """
    standalone execution
    """
    filename=input("enter word file:")
    word=input("enter word:")
    words=readWordFile(filename)
    #print(words)
    v=totalOccurrences(word,words)
    print("total occurences of",word,":",v)


from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def get_feature_matrix(N = 55):

    #initialize the feature vector with zeros.
    x_vec = np.zeros((N,3))

    x = []
    for i in range (N):
        im = Image.open("images/image_{number}.jpg".format(number=i+1))

        width, height = im.size

        rgb_im = im.convert('RGB')

        red = []
        green = []
        blue = []

        for y in range (height):
            for x in range (width):
                pixel = rgb_im.getpixel((x,y))
                red.append(pixel[0])
                green.append(pixel[1])
                blue.append(pixel[2])
        x_vec[i] = np.mean(red), np.mean(green), np.mean(blue)

    return x_vec;

def get_labels(N=55):
    y = np.zeros((N,1));

    y = np.zeros((N,1))
    #raise NotImplementedError()
    for i in range (0,20):
        y[i] = 1
    for i in range (21, N):
        y[i] = 0
    return y

def sigmoid_func(z):
    sigmoid = 1/(1+np.exp(-z))
    return sigmoid

def gradient(X,y,w):
    grad = []
    grad = np.transpose(np.dot(np.transpose(X), -(y-sigmoid_func(np.dot(X, np.transpose(w))))))/len(X)
    #raise NotImplementedError()
    return grad

def logisticRegression_func(X,y,step_size, K):
    N = X.shape[0]
    d = X.shape[1]
    # Initialize w as 1xd array.
    w = np.zeros((1,d))
    loss = float('inf')
    loss_list = []
    for i in range(K):
       # loss_list.append(gradient(X,y,w))

        cost = (1/N*np.dot(np.transpose(-y),np.log(sigmoid_func(np.dot(X,np.transpose(w)))))-np.dot(np.transpose((1-y)),np.log(1-sigmoid_func(np.dot(X,np.transpose(w))))))
        w = np.subtract(w, step_size*loss_list[i])
        loss_list.append(cost[0])
        #raise NotImplementedError()
    return loss_list, w

""" Predict Output """
def predict_output(X,w):
    y = []

    value = sigmoid_func(np.dot(X, np.transpose(w)))
    for i in range (len(value)):
        if value[i] >= 0.5:
            y.append(1)
        else:
            y.append(0)
    return y

y = get_labels()
X = get_feature_matrix()

# Full Vector
# Let s label : Grass = 1 , Soil = 0, Tiles = 0
assert X.shape == (55,3)
#axes = Visualize_data(X,y)
step_size = 1e-5
num_iter = 3000
e_list, w_opt = logisticRegression_func(X,y,step_size,num_iter)
print ('The optimal weight vector is:', w_opt)
y_hat = predict_output(X,w_opt)

def visualize_error(X, y, step_sizes, best = None, num_iter = 2000):
    plt.figure(figsize=(12, 4))
    fig, axes = plt.subplots(1, 2,figsize=(12, 4))
    for step in step_sizes:
        loss_list, w_opt = logisticRegression_func(X, y, step, num_iter)
        #raise NotImplementedError()
        n = len(loss_list) # Size of list remains the same.
        x_axes = np.linspace(0,n,n,endpoint=False)
        axes[0].plot(x_axes, loss_list, label=step)
    axes[0].set_xlabel('Number of Iterations')
    axes[0].set_ylabel('Loss Function')
    axes[0].legend()
    axes[0].set_title(r'$\bf{Figure\ 4.}$Converge of GD')

    for step in step_sizes:
        ### STUDENT TASK ###
        # Plot Error against Step Size.
        # Now mark the best converge in red. Use value from best as a correct step size.
        loss_list, w_opt = logisticRegression_func(X, y, step, num_iter)
        # YOUR CODE HERE
        #raise NotImplementedError()
        n = len(loss_list) # Size of list remains the same.
        x_axes = np.linspace(0,n,n,endpoint=False)
        if step == best:
            axes[1].plot(x_axes, loss_list, label=step, color="red")
        else:
            axes[1].plot(x_axes, loss_list, label=step, color="blue")

    axes[1].set_xlabel('Number of Iterations')
    axes[1].set_ylabel('Loss Function')
    axes[1].legend()
    axes[1].set_title(r'$\bf{Figure\ 5.}$Converge of GD')
    plt.tight_layout()
    return best, axes

### STUDENT TASK ###
# Change best=None into step size from the list that provides the fastest converge. e.g best=1
res0_1, axes = visualize_error(X/255, y, best=None, step_sizes=[0.1,0.5,1,5,10,16])
# YOUR CODE HERE
#raise NotImplementedError()


import pandas as pd
from sklearn import model_selection
import numpy as np
from sklearn import datasets

def create_k_folds():
    # csv with image id, image location and image label.
    df = pd.read_csv("train.csv")

    # create a new column called kfold and fill it with -1
    df["kfold"] = -1

    # the next step is to randomize the rows of the data
    df = df.sample(frac=1).reset_index(drop=True)

    # initiate the kfold class from model_selection module
    kf = model_selection.KFold(n_splits=5)

    # fill the new kfold column
    for fold, (trn_, val_) in enumerate(kf.split(X=df)):
        df.loc[val_, "kfold"] = fold

    # save the new csv with kfold column
    df.to_csv("train_folds.csv", index=False)

def create_stratified_k_folds():
    # csv with image id, image location and image label.
    df = pd.read_csv("train.csv")

    # create a new column called kfold and fill it with -1
    df["kfold"] = -1

    # the next step is to randomize the rows of the data
    df = df.sample(frac=1).reset_index(drop=True)

    # fetch targets
    y = df.target.values

    # initiate the kfold class from model_selection module
    kf = model_selection.StratifiedKFold(n_splits=5)

    # fill the new kfold column
    for fold, (trn_, val_) in enumerate(kf.split(X=df, y=y)):
        df.loc[val_, "kfold"] = fold

    # save the new csv with kfold column
    df.to_csv("train_folds.csv", index=False)

def create_stratified_k_fold_for_regression(data):
    # create a new column called kfold and fill it with -1
    data["kfold"] = -1

    # the next step is to randomize the rows of the data
    data = data.sample(frac=1).reset_index(drop=True)

    # calculate the number of bins by Sturge's rule
    # I take the floor of the value, you can also just round it.
    num_bins = int(np.floor(1 + np.log2(len(data))))

    # bin tagets
    data.loc[:, "bins"] = pd.cut(data["target"], bins=num_bins, labels=False)

    # initiate the kfold class from model_selection module
    kf = model_selection.StratifiedKFold(n_splits=5)

    # fill the new kfold column note that, instead of targets, we use bins!
    for f, (t_, v_) in enumerate(kf.split(X=data, y=data.bins.values)):
        data.loc[v_, "kfold"] = f

    # drop the bins column
    data = data.drop("bins", axis=1)

    # return data frame with folds
    return data

if __name__ == '__main__':
    # We create a sample dataset with 1500 samples and 100 features and 1 target
    X, y = datasets.make_regression(n_samples=1500, n_features=100, n_targets=1)

    # create a data frame out of our numpy arrays
    df = pd.DataFrame(X, columns=[f"f_{i}" for i in range(X.shape[1])])

    df.loc[:, "target"] = y

    # create folds
    df = create_stratified_k_fold_for_regression(data=df)
    a = 0


import numpy as np

def minimum_bbox(surface_points:np.ndarray):
    '''
    The minimum bounding box of a given point cloud

    Parameters
    ----------
    surface_points : np.ndarray(Ngamma,d)
        The positions of points in a point cloud in 'd' dimensions

    Returns
    ----------
    domain : np.ndarray(d,2)
        The lower and upper bounds along each dimension
    '''
    lower = np.min(surface_points,axis=0)
    upper = np.max(surface_points,axis=0)
    domain = np.stack((lower, upper),axis=1)
    return domain

def enlarged_bbox(surface_points:np.ndarray, percent:float=10.):
    '''
    Calcuate an enlarged bounding box of a given point cloud

    Parameters
    ----------
    surface_points : np.ndarray(Ngamma,d)
        The positions of points in a point cloud in 'd' dimensions
    percent : float
        The percentage to increase the bounding box from the minimum bounding box

    Returns
    ----------
    domain : np.ndarray(d,2)
        The lower and upper bounds along each dimension
    '''
    lower = np.min(surface_points,axis=0)
    upper = np.max(surface_points,axis=0)
    border = percent/100*(upper-lower)/2
    domain = np.stack((lower-border, upper+border),axis=1)
    return domain


from django.urls import path

from payment import views

app_name = 'payment'
urlpatterns = [

    path('canceled/$', views.payment_canceled, name='canceled'),
    path('done/$', views.payment_done, name='done'),
    path('(?P<id>\d+)/process', views.payment_process, name='process')
]


def fight(posseser, intruder):
    id = intruder.int_display()
    pbid = posseser.pos_bid(id)
    pd = posseser.pos_display()
    ibid = intruder.int_bid(pd)
    # print(round(pd,1), round(id,1), round(pbid,1), round(ibid,1), sep='\t\t\t')
    posseser.base_health -= min(pbid,ibid)
    posseser.health = min(posseser.health, posseser.base_health)
    intruder.base_health -= min(pbid,ibid)
    intruder.health = min(intruder.health, intruder.base_health)
    if pbid > ibid:
        return posseser, intruder, pbid, ibid
    else:
        return intruder, posseser, pbid, ibid


"""
Module that can parse chess notation for individual moves. Mostly to debug
things and/or introduce chess states without having to wire up the entire
camera setup on a physical board.

Note that we're using standard Algebraic Notation:

https://en.wikipedia.org/wiki/Algebraic_notation_(chess)

Maybe we move on to FEN https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
to start from boards?

BUGS:
  - Doesn't handle pawn promotions
  - Doesn't handle disambiguations (when two knights can reach the same place)
"""
import re
from enum import Enum
from collections import namedtuple

# Data definitions. Currently don't allow for draws.
Piece = Enum('Piece', 'Pawn Rook Knight Bishop Queen King')
Action = Enum('Action', 'Move Capture CastleKingside CastleQueenside PawnPromotion')
Modifier = Enum('Modifier', 'Check CheckMate')

Col = Enum('Col', 'A B C D E F G H')
Row = Enum('Row', 'One Two Three Four Five Six Seven Eight')

Position = namedtuple('Position', 'row col')
Move = namedtuple('Move', 'piece action position modifiers')
# Black could be None in the case of a white Checkmate
Turn = namedtuple('Turn', 'white black')

LINE_REGEX = re.compile('(?:\d+\.\s+)\s*(\S+)(?:\s+(\S+)\s*)?$')
POSITION_PATTERN = '([a-h])(1|2|3|4|5|6|7|8)'
POSITION_REGEX = re.compile(POSITION_PATTERN)
PIECE_MAP = {
    'B': Piece.Bishop,
    'R': Piece.Rook,
    'Q': Piece.Queen,
    'K': Piece.King,
    'N': Piece.Knight
}
COL_MAP = {'a': Col.A, 'b': Col.B, 'c': Col.C, 'd': Col.D, 'e': Col.E, 'f': Col.F, 'g': Col.G, 'h': Col.H}
ROW_MAP = {
    '1': Row.One,
    '2': Row.Two,
    '3': Row.Three,
    '4': Row.Four,
    '5': Row.Five,
    '6': Row.Six,
    '7': Row.Seven,
    '8': Row.Eight
}
ACTION_MAP = {
    'x': Action.Capture,
    'O-O': Action.CastleKingside,
    'O-O-O': Action.CastleQueenside,
    '=': Action.PawnPromotion
}

def parse_file(filename):
    with open(filename) as f:
        lines = f.readlines()
        return [parse_line(line.rstrip('\n')) for line in lines]

def parse_line(line):
    components = LINE_REGEX.match(line)
    white_move = _parse_move(components.group(1))

    black_move = None
    black_move_spec = components.group(2)
    if black_move_spec:
        black_move = _parse_move(black_move_spec)
    return Turn(white=white_move, black=black_move)

def _parse_move(move):
    if re.match('O-O-O', move):
        return Move(piece=None, action=Action.CastleQueenside, position=None, modifiers=[])
    elif re.match('O-O', move):
        return Move(piece=None, action=Action.CastleKingside, position=None, modifiers=[])

    piece = _get_piece(move)
    action = _get_action(move)
    position = _get_position(move)
    modifiers = _get_modifiers(move)
    return Move(piece=piece, action=action, position=position, modifiers=modifiers)

def _get_piece(move):
    """
    The piece is realatively easy to determine: it's either a pawn, or directly
    determined by its first letter. Gets _a little_ weird for when pawns capture,
    so we default to that if the first character isnt' a recognized one.
    """
    match = re.search('^' + POSITION_PATTERN, move)
    if match:
        return Piece.Pawn
    else:
        return PIECE_MAP.get(move[0], Piece.Pawn)

def _get_action(move):
    for action in ACTION_MAP.iterkeys():
        if re.search(action, move):
            return ACTION_MAP[action]
    return Action.Move

def _get_position(move):
    """
    The position is pretty easily determined by one of the "acceptable letters" followed by
    an acceptable number.
    """
    match = POSITION_REGEX.search(move)
    return Position(col=COL_MAP[match.group(1)], row=ROW_MAP[match.group(2)])

def _get_modifiers(move):
    modifiers = []
    if re.search('\+', move):
        modifiers.append(Modifier.Check)
    elif re.search('#', move):
        modifiers.append(Modifier.CheckMate)
    return modifiers

def test_data():
    return [
           Turn(white=Move(piece=Piece.Pawn,
                           action=Action.Move,
                           position=Position(col=Col.E, row=Row.Four),
                           modifiers=[]),
                black=Move(piece=Piece.Pawn,
                           action=Action.Move,
                           position=Position(col=Col.E, row=Row.Five),
                           modifiers=[])),
            ]


from student import *

# 管理系统类
class Lms(object):

    # 储存学员数据需要的列表
    def __init__(self):
        self.student_list = []

    def bt(self):
        print('学号｜姓名｜性别｜年龄｜联系电话｜身份证号码')

    # 功能检查函数--------------------------------------------------------------
    def inspect(self):
        try:
            print(self.student_list)
        except:
            print('录入功能错误')
        else:
            print('读取学员数据功能测试成功')

    # 系统主页框架--------------------------------------------------------------
    def run(self):
        # 加载学员信息
        self.load_student()

        while True:
            # 显示菜单
            self.show_menu()
            # 输入选项
            menu_num = int(input('\n请输入功能序号：'))
            # 判断功能
            if menu_num == 1:  # 查询
                self.search_student()
            elif menu_num == 2:  # 新增
                self.add_student()
            elif menu_num == 3:  # 遍历
                self.show_student()
            elif menu_num == 0:  # 退出
                self.exit_student()
                break
            elif menu_num == 9:  # 系统检查
                self.inspect()  # 读取信息检测功能
                break

    # print系统菜单--------------------------------------------------------------
    def show_menu(self):  # 系统主页
        print('LMS v1.0'.center(54, '-'))
        print('1、查询学员信息'.center(50, ))
        print('2、新增学员信息'.center(50, ))
        print('3、遍历学员信息'.center(50, ))
        print('0、退出管理系统'.center(50, ))

    # 加载学员信息--------------------------------------------------------------
    def load_student(self):
        try:
            f = open('student.data', 'r')
        except:
            f = open('student.data', 'w')
        else:
            str_data = f.read()
            dick_data = eval(str_data)
            self.student_list = [Student(i['name'], i['id_num'], i['tel'], i['stu_id']) for i in dick_data]
        f.close()

    # 增加功能--------------------------------------------------------------
    def add_student(self):
        global add_sut_id
        id_num = input('请输入身份证号码：')
        # 检查身份证号码位数
        if len(id_num) != 18:
            print('\n***您输入的身份证号码不正确，请重新输入!***\n\n')
            self.add_student()
        else:
            # 检查身份证号码是否已存在
            for i in self.student_list:
                if i.id_num == id_num:
                    print('\n***注意：身份证号存在冲突****\n冲突学员信息：')
                    self.bt()
                    print(i)
                    print('\n已为您返回主菜单\n\n')
                    self.run()
        name = input('请输入学员姓名：')
        tel = input('请输入手机号码：')

        # 调用 student.py模块，生成 学生信息对象，返回给 list
        student = Student(name, id_num, tel)
        self.student_list.append(student)

        # 确认录入信息是否有误：
        for i in self.student_list:
            if i.id_num == id_num:
                self.bt()
                print(i)
                add_sut_id = i.stu_id
                break
        a = input('请检查录入信息\n\n确认无误 Y\n修改录入 r\n返回主菜单 N\n请输入：')
        if a == 'Y' or a == 'y':
            self.save_data()
            print('***学员信息已保存***')
            self.run()
        elif a == 'R' or a == 'r':
            self.del_data(add_sut_id)
            print('请重新录入信息：\n')
            self.add_student()
        elif a == 'N' or a == 'n':
            self.run()

    # 保存数据模块，将学员数据列表，保存的 student.data 文件=---------------
    def save_data(self):
        f = open('student.data', 'w')
        list_data = [i.__dict__ for i in self.student_list]
        str_data = str(list_data)
        print(str_data)
        f.write(str_data)

    # 删除模块 ------------------------------------------
    def del_data(self, value1):
        for i in self.student_list:
            if i.stu_id == value1:
                del i
                break

# _______________________________________________________
#     # 查询功能
#     def search_student(self):  # 1查询功能页面
#         while True:
#             print('1、学号查询')
#             print('2、姓名查询')
#             print('0、退出查询')
#             mo = int(input('请输入查询方式：'))
#             if mo == 1:
#                 self.id_search()
#             elif mo == 2:
#                 self.name_search()
#             elif mo == 0:
#                 self.exit_search()
#                 break
#
#     def student_data(self):  # 启动系统读取全部学员数据文件，存到内存中，如果没有数据文件默认创建空文件，读取后关闭文件；
#         try:
#             f = open('student.data', 'r')
#         except:
#             f = open('student.data', 'w')
#         else:
#             data = f.read()
#             new_list = eval(data)
#             self.student_list = [Student(i['stu_id'], i['name'], i['gender'], i['tel'], i['id_num']) for i in new_list]
#
#     def aa(self):  # 测试学员储存信息函数
#         print(self.student_list)
#
#     # 框架程序入口
#     def run(self):  # 系统主页框架
#         # 欢迎页面
#         print('LMS v1.0'.center(54, '-'))
#         # 加载学员信息
#         # self.load_student()
#
#         while True:
#             # 显示菜单
#             self.show_menu()
#             # 输入选项
#             menu_num = int(input('\n请输入功能序号：'))
#             # 判断功能
#             if menu_num == 1:  # 查询
#                 self.search_student()
#             elif menu_num == 2:  # 新增
#                 self.add_student()
#             elif menu_num == 5:  # 遍历
#                 self.show_student()
#             elif menu_num == 0:  # 退出
#                 # self.exit_student()
#                 self.student_data()
#                 break
#
#     # 系统菜单
#     def show_menu(self):  # 系统主页
#         print('1、查询学员信息'.center(50, ))
#         print('2、新增学员信息'.center(50, ))
#         print('3、遍历学员信息'.center(50, ))
#         print('0、退出管理系统'.center(50, ))
#
#     # 查询功能
#     def search_student(self):  # 1查询功能页面
#         while True:
#             print('1、学号查询')
#             print('2、姓名查询')
#             print('0、退出查询')
#             mo = int(input('请输入查询方式：'))
#             if mo == 1:
#                 self.id_search()
#             elif mo == 2:
#                 self.name_search()
#             elif mo == 0:
#                 self.exit_search()
#                 break
#
#     def id_search(self):  # 1.1学号查询
#         id_student = int(input('请输入查询学员的学号：'))
#         print('学号｜姓名｜性别｜年龄｜联系电话｜身份证号码')
#         for i in self.student_list:
#             if i.id == id_student:
#                 print(i)
#                 break
#         else:
#             print('学号不正确！')
#             self.search_student()
#         num = int(input('1、重新查找\n2、修改学员信息\n3、删除学员信息\n0、返回主菜单'))
#         if num == 1:
#             self.id_search()
#         elif num == 2:
#             self.modify_student()
#         elif num == 3:
#             self.del_student()
#         elif num == 0:
#             self.run()
#
#     def name_search(self):  # 1.2姓名查询
#         name_student = input('请输入查询学员的姓名：')
#         print('学号｜姓名｜性别｜年龄｜联系电话｜身份证号码')
#         for i in self.student_list:
#             if i.name == name_student:
#                 print(i)
#         num = int(input('1、重新查找\n2、修改学员信息\n3、删除学员信息\n0、返回主菜单'))
#         if num == 1:
#             self.name_search()
#         elif num == 2:
#             self.modify_student()
#         elif num == 3:
#             self.del_student()
#         elif num == 0:
#             self.run()
#
#     def exit_modify(self):  # 1.3退出查询
#         self.run()
#
#     def modify_student(self):  # 1.1.1修改信息
#         modify_id = int(input('请输入修改学员学号：'))
#         for i in self.student_list:
#             if i.id == modify_id:
#                 break
#         print('学号｜姓名｜性别｜年龄｜联系电话｜身份证号码')
#         print(i)
#         print('请输入修改信息数字编号：')
#         print('1.姓名；2.性别；3.年龄；4.身份证号码；5.手机号码。')
#         modify_num = int(input('请输入编号：'))
#         new_modify = input('请输入修改内容：')
#         if modify_num == 1:
#             i.id = new_modify
#             print(i)
#         elif modify_num == 2:
#             pass
#         elif modify_num == 3:
#             pass
#         elif modify_num == 4:
#             pass
#         elif modify_num == 5:
#             pass
#
#     def del_student(self):  # 删除学员信息
#         del_id = input('请输入删除学员的学号：')
#         print('学号｜姓名｜性别｜年龄｜联系电话｜身份证号码')
#         for i in self.student_list:
#             if i.id == del_id:
#                 print(i)
#                 break
#         else:
#             print('您输入的学号有误！')
#
#         x = input('输入Y确认删除，输入N返回主菜单')
#         if x == 'Y' or 'y':
#             self.student_list.remove(i)
#             print('学员已删除！')
#         elif x == 'N' or 'n':
#             print('已取消！')
#
#
#
#     # 数据刷新模块
#     def save_data(self):
#         new_list = [i.__dict__ for i in self.student_list]
#         f = open('student.data', 'w')
#         f.write(str(new_list))
#         f.close()
#
#     # 修改功能
#     # 查询功能
#     # 退出功能
#
#
# if __name__ == '__main__':
#     ams = Lms()
#     ams.aa()


'''
started on 2022/06/13
end on 2022/xx/xx
@author zelo2
'''

import torch
import torch.nn as nn

class LightGCN(nn.Module):
    def __init__(self, n_user, n_item, norm_adj, device, args):
        super(LightGCN, self).__init__()
        self.device = device
        self.n_user = n_user
        self.n_item = n_item
        self.norm_adj = norm_adj

        self.embed_size = args.embed_size
        self.batch_size = args.batch_size
        self.layer_num = args.layer_num
        self.reg_value = eval(args.reg)[0]

        self.embeding_dict = self.init_weight()
        self.sp_norm_adj = self.convert_coo_matirix_2_sp_tensor(self.norm_adj).to(self.device)

    def init_weight(self):
        '''Embedding with xavier initialization'''
        initializer = nn.init.xavier_uniform_
        embedding_dict = nn.ParameterDict({
            'user_embed': nn.Parameter(initializer(torch.empty(self.n_user,
                                                               self.embed_size))),
            'item_embed': nn.Parameter(initializer(torch.empty(self.n_item,
                                                               self.embed_size)))
        })
        # self.user_embedding = nn.Embedding(self.n_user, self.embed_size)
        # self.item_embedding = nn.Embedding(self.n_user, self.embed_size)
        # nn.init.xavier_uniform_(self.user_embedding.weight)
        # nn.init.xavier_uniform_(self.item_embedding.weight)

        return embedding_dict

    def convert_coo_matirix_2_sp_tensor(self, X):
        coo = X.tocoo()
        # coo matrix--((data, (row, column)), shape)
        # data:矩阵中的数据， row, column表示这个数据在哪一行哪一列
        i = torch.LongTensor([coo.row, coo.col])  # [row, column]
        v = torch.from_numpy(coo.data).float()  # data
        return torch.sparse.FloatTensor(i, v, coo.shape)

    def sparse_dropout(self, x, rate, noise_shape):
        save_probability = 1 - rate
        # torch.rand: 均匀分布采样[0,1]
        # 因此加上它之后，大于1的概率即为 1 - node_dropout_rate
        save_probability += torch.rand(noise_shape)
        dropout_mask = torch.float(save_probability).type(torch.bool)
        i = x._indices()
        v = x._values()

        i = i[:, dropout_mask]
        v = v[dropout_mask]

        out = torch.sparse.FloatTensor(i, v, x.shape)

        return out * (1. / (1 - rate))  # dropout部分节点，重新正则化。
        # return out

    def forward(self, user, pos_item, neg_item, drop_flag=False):

        A = self.sp_norm_adj
        embedding_matrix = torch.cat([self.embeding_dict['user_embed'], self.embeding_dict['item_embed']]
                                     , 0)  # [M+N, embedding_size]
        embedding_matrix = embedding_matrix.to(self.device)

        all_embeddings = [embedding_matrix]

        for k in range(self.layer_num):

            # Graph Convolution operation without self connection
            embedding_matrix = torch.sparse.mm(A, embedding_matrix)

            # Normalization
            # norm_embeddings = F.normalize(embedding_matrix, p=2, dim=1)  # normalize each row

            all_embeddings += [embedding_matrix]

        all_embeddings = torch.stack(all_embeddings, dim=1)
        all_embeddings = torch.mean(all_embeddings, dim=1)
        user_embeddings = all_embeddings[:self.n_user, :]
        item_embeddings = all_embeddings[self.n_user:, :]

        user_embeddings = user_embeddings[user, :]
        pos_item_embeddings = item_embeddings[pos_item, :]
        neg_item_embeddings = item_embeddings[neg_item, :]

        return user_embeddings, pos_item_embeddings, neg_item_embeddings  # [batch_size, embed_size * layer_num] * 3

    def bpr_loss(self, users, pos_items, neg_items):
        '''
        :param users: user embeddings [batch_size, embed_size * layer_num]
        :param pos_items: positive item embeddings
        :param neg_items: negative item embeddings
        :return: Bayesian Personalized Ranking loss (BPR loss)
        '''
        pos_inner_product = torch.mul(users, pos_items)
        neg_inner_product = torch.mul(users, neg_items)

        pos_inner_product = torch.sum(pos_inner_product, axis=1)  # sum each row [batch_size]
        neg_inner_product = torch.sum(neg_inner_product, axis=1)

        loss_value = nn.LogSigmoid()(pos_inner_product - neg_inner_product)
        loss_value = -1 * torch.mean(loss_value)

        # L2范式：所有元素的平方和 开根号
        l2_value = torch.norm(users, p=2) ** 2 + torch.norm(pos_items, p=2) ** 2 + torch.norm(neg_items, p=2) ** 2
        l2_value /= 2

        # for k in range(self.layer_num):
        #     l2_value += torch.norm(self.weight_dict['W1_layer%d' % k], p=2) ** 2
        #     l2_value += torch.norm(self.weight_dict['b1_layer%d' % k], p=2) ** 2

        # l2_value /= (2 + self.layer_num * 2)

        l2_value = self.reg_value * l2_value / self.batch_size

        return loss_value + l2_value


N = int(input())
trilha = 0
subida = 0

for i in range (N):
    valores = input()
    valores = valores.split()
    M = int(valores[0])
    contador1 = 0
    contador2 = 0
    altura = int(valores[1])

    for j in range(1, M+1):
        alturanova = int(valores[j])

        if alturanova > altura:
            contador1 = alturanova - altura + contador1

        altura = alturanova

    altura = int(valores[M])
    for k in range(M,0,-1):
        alturanova = int(valores[k])

        if alturanova > altura:
            contador2 = alturanova - altura + contador2

        altura = alturanova

    contador1 = min(contador1, contador2)

    if i == 0:
        subida = contador1
        trilha = i+1
    else:
        if contador1<subida:
            subida = contador1
            trilha = i+1

print(trilha)


# 寻找一个能复现bug的小图。
# 如果pattern大小为N，则会先检查所有大小为N的图（共2^(N*(N-1)/2)种），再检查大小为N+1的图……直到找到发生错误
# 由于原程序中输出的东西太多，需要先修改源程序，让其将答案输出至1.out和2.out，其余内容可以输出至stdout（本程序中不会做重定向）
# 使用本程序，需要修改N、bin1和bin2，编译一个正确版本和有bug版本的
# 由于我们的dataloader要求不能存在度数为0的点，所以很多生成的图是不合法的，如果报了“vertex number error!”是正常的

import os

N = 5
bin1 = "../build/bin/gpu_graph"
res1 = "1.out"
bin2 = "../build/bin/gpu_graph_correct"
res2 = "2.out"

while (True):
    print("N = " + str(N))
    print("range = ", range(2 ** int(N * (N - 1) / 2)))
    for i in range(2 ** int(N * (N - 1) / 2)):
        x = i
        e_num = 0
        while (x != 0):
            e_num += x & 1
            x >>= 1
        f = open("graph.out", "w")
        f.write(str(N) + " " + str(e_num) + "\n")
        x = i
        for j in range(1, N):
            for k in range(j + 1, N + 1):
                if (x & 1 == 1):
                    f.write(str(j) + " " + str(k) + "\n")
                x >>= 1
        f.close()
        os.system("srun -N 1 " + bin1 + " Patents graph.out")
        os.system("srun -N 1 " + bin2 + " Patents graph.out")
        if os.path.exists(res1) and os.path.exists(res2) and os.system("diff -w -q " + res1 + " " + res2) != 0:
            break
        print("i = " + str(i) + "  Correct.")
    N += 1


from random import randint

class TokenGenerator:
	def __init__(self, path):
		f = open(path,'r')
		self.list = []
		self.size = 0
		for line in f:
			self.list.append(line.replace("\n",""))
			self.size = self.size+1

	def close(self):
		f.close()

	def get(self):
		word = ""
		for i in range(0,3):
			word = word+self.list[randint(0, self.size-1)]
		return word


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

import numpy as np
import pandas as pd
import time
import gc
import random
import sklearn
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score, GridSearchCV, cross_validate, train_test_split
from sklearn.metrics import accuracy_score, classification_report
from sklearn.svm import SVC
from sklearn.linear_model import LinearRegression
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler, normalize
from sklearn.decomposition import PCA
from sklearn.impute import SimpleImputer
from sklearn import tree
from sklearn.metrics import plot_roc_curve
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.neighbors import KNeighborsClassifier
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import KMeans
from kneed import KneeLocator
import seaborn as sb
from sklearn.metrics import silhouette_score
from sklearn import manifold
from sklearn.mixture import GaussianMixture

class Data():

    def dataAllocation(self, path):
        # Separate out the x_data and y_data and return each
        # args: string path for .csv file
        # return: pandas dataframe, pandas series
        # -------------------------------
        # ADD CODE HERE
        df = pd.read_csv(path)
        xcols = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8']
        ycol = ['y']
        x_data = df[xcols]
        y_data = df[ycol]
#        print(y_data[y_data.y == 1].shape[0])
 #       print(df.shape[0])
        # -------------------------------
        return x_data, y_data.values.ravel()

    def processed_data_Allocation(self, path):
    # Read the processed dataset
    # -------------------------------
        df = pd.read_csv(path)
        xcols = ["age","education","default","housing","loan","contact","month","day_of_week","campaign","previous","poutcome","emp.var.rate","cons.price.idx","cons.conf.idx","euribor3m","nr.employed","job_blue-collar","job_entrepreneur","job_housemaid","job_management","job_retired","job_self-employed","job_services","job_student","job_technician","job_unemployed","marital_married","marital_single"]
        ycol = ['y']
        x_data = df[xcols]
        y_data = df[ycol]

        return x_data, y_data.values.ravel()

    def trainSets(self, x_data, y_data):
        # Split 70% of the data into training and 30% into test sets. Call them x_train, x_test, y_train and y_test.
        # Use the train_test_split method in sklearn with the parameter 'shuffle' set to true and the 'random_state' set to 614.
        # args: pandas dataframe, pandas dataframe
        # return: pandas dataframe, pandas dataframe, pandas series, pandas series
        # -------------------------------
        # ADD CODE HERE
        x_train, x_test, y_train, y_test = train_test_split(
            x_data, y_data, test_size=0.2, shuffle=True, random_state=614)
        # -------------------------------
        return x_train, x_test, y_train, y_test

    def dataPreProcess(self, x_train, x_test):
        # Pre-process the data to standardize it, otherwise the grid search will take much longer.
        # args: pandas dataframe, pandas dataframe
        # return: pandas dataframe, pandas dataframe
        # -------------------------------
        # ADD CODE HERE
        scaler = StandardScaler()
        scaler.fit(x_train)
        scaled_x_train = scaler.transform(x_train)
        scaled_x_test = scaler.transform(x_test)
        # -------------------------------
        return scaled_x_train, scaled_x_test

fig, axs = plt.subplots(2, 3)
##################### Diabetes data #############################
dataset = Data()
data = 'data/pima-indians-diabetes.csv'
x_data, y_data = dataset.dataAllocation(data)
x_train, x_test, y_train, y_test = dataset.trainSets(x_data, y_data)
x_train_scaled, x_test_scaled = dataset.dataPreProcess(x_train, x_test)

# KM with DS1
kmeans_kwargs = {'init': 'random', 'n_init':10, 'max_iter':100, 'random_state':42, 'algorithm':'full',}
start = time.time()
kmeans = KMeans(n_clusters=4, **kmeans_kwargs)
label = kmeans.fit(x_train_scaled).labels_
end = time.time()
print("KM with DS1 time:", end-start)
tsne_transform = manifold.TSNE(n_components=2, perplexity=100, init='pca', random_state=42)
feature2D_DS1 = tsne_transform.fit_transform(x_train_scaled)
axs[0, 0].scatter(feature2D_DS1[:,0], feature2D_DS1[:,1], c=label, cmap=plt.cm.Spectral, s=5)
axs[0, 0].set_title('Clusters for DS1 with KM')

# EM with DS1
em_kwargs = {'covariance_type': 'full', 'n_init':10, 'max_iter':100, 'random_state':42, 'init_params':'kmeans'}
start = time.time()
em = GaussianMixture(n_components=5, **em_kwargs)
label = em.fit(x_train_scaled).predict(x_train_scaled)
end = time.time()
print("EM with DS1 time:", end-start)
tsne_transform = manifold.TSNE(n_components=2, perplexity=100, init='pca', random_state=42)
feature2D_DS1 = tsne_transform.fit_transform(x_train_scaled)
axs[0, 1].scatter(feature2D_DS1[:,0], feature2D_DS1[:,1], c=label, cmap=plt.cm.Spectral, s=5)
axs[0, 1].set_title('Clusters for DS1 with EM')

axs[0, 2].scatter(feature2D_DS1[:,0], feature2D_DS1[:,1], c=y_train, cmap=plt.cm.Spectral, s=5)
axs[0, 2].set_title('Clusters for DS1 - True Label')

dataset = Data()
data = 'data/bank_marketing.csv'
x_data, y_data = dataset.processed_data_Allocation(data)
x_train, x_test, y_train, y_test = dataset.trainSets(x_data, y_data)
x_train_scaled, x_test_scaled = dataset.dataPreProcess(x_train, x_test)

# KM with DS2
kmeans_kwargs = {'init': 'random', 'n_init':10, 'max_iter':100, 'random_state':42, 'algorithm':'full',}
start = time.time()
kmeans = KMeans(n_clusters=6, **kmeans_kwargs)
label = kmeans.fit(x_train_scaled).labels_
end = time.time()
print("KM with DS2 time:", end-start)
tsne_transform = manifold.TSNE(n_components=2, perplexity=100, init='pca', random_state=42)
feature2D_DS2 = tsne_transform.fit_transform(x_train_scaled)
axs[1, 0].scatter(feature2D_DS2[:,0], feature2D_DS2[:,1], c=label, cmap=plt.cm.Spectral, s=5)
axs[1, 0].set_title('Clusters for DS2 with KM')

# EM with DS2
em_kwargs = {'covariance_type': 'full', 'n_init':10, 'max_iter':100, 'random_state':42, 'init_params':'kmeans'}
start = time.time()
em = GaussianMixture(n_components=5, **em_kwargs)
label = em.fit(x_train_scaled).predict(x_train_scaled)
end = time.time()
print("EM with DS2 time:", end-start)
tsne_transform = manifold.TSNE(n_components=2, perplexity=100, init='pca', random_state=42)
feature2D_DS2 = tsne_transform.fit_transform(x_train_scaled)
axs[1, 1].scatter(feature2D_DS2[:,0], feature2D_DS2[:,1], c=label, cmap=plt.cm.Spectral, s=5)
axs[1, 1].set_title('Clusters for DS2 with EM')

axs[1, 2].scatter(feature2D_DS2[:,0], feature2D_DS2[:,1], c=y_train, cmap=plt.cm.Spectral, s=5)
axs[1, 2].set_title('Clusters for DS2 - True Label')

fig.tight_layout()

plt.show()