import os
import pandas as pd
import spacy
from sklearn.feature_extraction.text import CountVectorizer
import datetime
import numpy as np

from processing import get_annee_scolaire

if __name__ == "__main__":

    #print("files", os.listdir("data_processed"))

    ##########################
    # Chargement des données
    ##########################

    path_g = os.path.join("data_processed", "greves.pk")
    g = pd.read_pickle(path_g)
    g["ind"] = g.ind.map(lambda x: 1 if x == "GREVE" else 0)
    g = g[["taux_grevistes", "nos", "ind", "greves_manquantes"]]

    path_m = os.path.join("data_processed", "menus.pk")
    m = pd.read_pickle(path_m)

    path_fe = os.path.join("data_processed", "frequentation_effectif.pk")
    fe = pd.read_pickle(path_fe)

    path_ferie = os.path.join("data_processed", "feries.pk")
    feries = pd.read_pickle(path_ferie)

    path_vacs = os.path.join("data_processed", "vacances.pk")
    vacances = pd.read_pickle(path_vacs)

    path_epidemies = os.path.join("data_processed", "epidemies.pk")
    epidemies = pd.read_pickle(path_epidemies)

    path_religions = os.path.join("data_processed", "religions.pk")
    religions = pd.read_pickle(path_religions)

    ##########################
    # Join sur les dates des différentes BDD
    ##########################

    df = fe.groupby("date")[["prevision", "reel", "effectif"]].sum().join(g).join(m).join(feries).join(vacances).join(epidemies).join(religions)

    ##########################
    # Remplacement des valeurs manquantes
    ##########################

    for col in df.isnull().sum()[df.isnull().sum()>0].index.drop("menu"):
        df[col] = df[col].fillna(0)
    df["menu"] = df["menu"].map(lambda x: x if type(x) == list else [])

    ####################################
    # Ajout des jours, mois semaines, année scolaire, repas noel
    ####################################
    dic_jour = {0: "Lundi", 1: "Mardi", 2: "Mercredi", 3: "Jeudi", 4: "Vendredi", 5: "Samedi", 6: "Dimanche"}
    dic_mois = {1: "Janvier", 2: "Fevrier", 3: "Mars", 4: "Avril", 5: "Mai", 6: "Juin", 7: "Juillet", 8: "Aout",
                9: "Septembre", 10: "Octobre", 11: "Novembre", 12: "Decembre"}

    df["jour"] = df.index.weekday
    df["jour"] = df["jour"].apply(lambda x: dic_jour[x])
    df["semaine"] = df.index.week
    df["mois"] = df.index.month
    df["mois"] = df["mois"].apply(lambda x: dic_mois[x])
    df["annee_scolaire"] = df.index.to_series().map(get_annee_scolaire)

    date_repas_noel = ["2012-12-20", "2013-12-19", "2014-12-18", "2015-12-17", "2016-12-15",
                       "2017-12-21", "2018-12-20"]
    l_noel = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in date_repas_noel]

    df_noel = pd.DataFrame(l_noel, columns=["date"])
    df_noel["repas_noel"] = 1
    df = df.join(df_noel.set_index("date"))
    df["repas_noel"] = df["repas_noel"].fillna(0)

    ####################################
    # Ajout du gaspillage
    ####################################

    assert df.isnull().sum().sum() == 0

    df["gaspillage_volume"] = df["prevision"] - df["reel"]
    df["gaspillage_pourcentage"] = 100 * (df["prevision"] - df["reel"]) / df["prevision"]

    ####################################
    # Ajout des variables liées au menu
    ####################################

    nlp = spacy.load("fr_core_news_sm")
    corpus = df['menu'].apply(lambda x: "".join([i + " " for i in x]))
    corpus = corpus.dropna()

    # stop_word
    liste = ['04', '10', '17', '18225', '2015', '2016', '220gr', '268', '29', '500', '500g', '5kg', '850''500', '500g',
             '5kg', '850', 'ab', 'an', 'au', 'aux', 'avec', 'baut', 'bbc', 'de', 'des', 'du', 'en', 'et', 'gr', 'kg',
             'la', 'le', 'les', 'ou', 'par', 's17', 'sa', 'sans', 'ses', 'son']

    # Create CountVectorizer object
    vectorizer = CountVectorizer(strip_accents='ascii', stop_words=liste, lowercase=True, ngram_range=(1, 1))

    # Generate matrix of word vectors
    bow_matrix = vectorizer.fit_transform(corpus)

    # Convert bow_matrix into a DataFrame
    bow_df = pd.DataFrame(bow_matrix.toarray())

    # Map the column names to vocabulary
    bow_df.columns = vectorizer.get_feature_names()
    bow_df.index = df.index

    # feature porc
    l_porc = ["carbonara", "carbonata", "cassoulet", "chipo", "chipolatas", "choucroute",
              "cordon", "croziflette", "francfort", "jambon", "knacks", "lardons", "porc", "rosette",
              "saucisse", "saucisses", "tartiflette"]

    df["porc"] = sum([bow_df[alim] for alim in l_porc])
    df['porc'] = df['porc'] > 0
    df['porc'] = df['porc'].astype('int')

    # feature viande
    l_viande = ["roti", "agneau", "blanquette", "boeuf", "boudin", "boulettes",
                "bourguignon", "bourguignonne", "canard", "carne", "chapon", "colombo",
                "couscous", "dinde", "escalope", "farci", "foie", "kebab", "lapin", "merguez",
                "mouton", "napolitaines", "nuggets", "paupiette", "pintade",
                "poulet", "steak", "stogonoff", "strogonoff", "tagine", "tajine",
                "veau", "viande", "volaile", "volaille", "carbonara", "carbonata", "cassoulet", "chipo", "chipolatas",
                "choucroute",  "cordon", "croziflette", "francfort", "jambon", "knacks", "lardons", "porc", "rosette",
                "saucisse", "saucisses", "tartiflette", "parmentier"]

    df["viande"] = sum([bow_df[alim] for alim in l_viande])
    df['viande'] = df['viande'] > 0
    df['viande'] = df['viande'].astype('int')

    df = df.reset_index().rename(columns = {"index":"date"})

    l_index = ["2018-01-22", "2017-10-09", "2017-05-09", "2016-10-18", "2016-04-25", "2015-05-26", "2014-11-24",
             "2014-05-26", "2014-03-31", "2014-01-20", "2012-01-16", "2012-01-30", "2012-07-02", "2012-10-01",
             "2011-01-17", "2011-01-31", "2011-09-13", "2015-06-22", "2015-01-19", "2014-06-30", "2012-06-18",
             "2011-06-20"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "viande"] = 1

    # traitement particulier des lasagnes napolitaines pour éviter les confusions avec les lasagnes de poisson
    l_index = ["2016-02-22", "2016-02-04", "2015-11-23", "2015-11-17", "2015-10-05",
             "2015-05-04", "2015-01-26", "2014-12-15", "2013-09-23", "2012-10-09", "2012-05-21", "2012-02-27",
             "2011-11-03", "2011-09-05", "2011-05-09", "2012-12-10", "2013-12-02", "2014-05-12", "2016-05-09"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "viande"] = 1

    # traitement particulier de certains termes qui peuvent être utilisés pour du poisson ou de la viande sautés, chili, pot au feu, bolognaise, courgette farcie,ravioli
    l_index = ["2016-01-28", "2016-03-17", "2016-03-07", "2015-09-15", "2012-12-06", "2012-05-03", "2012-02-09",
             "2011-11-03",
             "2011-09-13", "2011-06-07", "2011-04-04", "2014-06-12", "2012-11-12", "2015-06-22"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "viande"] = 1

    # traitement particulier pour parmentier végétale, steack de soja
    l_index = ["2019-11-25", "2014-06-20"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "viande"] = 0

    # feature poisson
    l_poisson = ["poissons", "sardines", "perray", "thon", "calamar", "lieu", "colin", "crabe", "crevette", "crustace",
                 "dorade", "maquereau", "poisson", "rillette", "sardine", "saumon"]

    df["poisson"] = sum([bow_df[alim] for alim in l_poisson])
    df['poisson'] = df['poisson'] > 0
    df['poisson'] = df['poisson'].astype('int')
    df['poisson'][(df['viande'] == 1) & (df['poisson'] == 1)] = np.zeros(
        len(df['poisson'][(df['viande'] == 1) & (df['poisson'] == 1)]))

    # traitement particulier parmentier poisson #nuggets de poisson,steack de soja et sale au thon, carbo de saumon
    l_index = ["2019-05-17", "2019-05-17", "2019-02-01", "2018-11-23", "2018-10-19", "2018-09-14", "2018-06-05",
             "2018-03-27", "2018-01-16", "2017-12-01", "2017-09-22", "2017-05-05", "2016-05-03", "2016-02-26",
             "2016-01-15", "2015-11-20", "2015-09-22", "2015-09-08", "2015-06-05", "2014-09-08", "2014-03-25",
             "2014-02-18", "2014-01-24", "2013-12-10", "2013-11-29", "2013-10-01", "2012-12-14", "2012-10-19",
             "2012-09-21", "2012-03-16", "2012-01-20", "2011-09-09", "2011-03-18", "2019-03-08"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "viande"] = 0
        df.loc[df[df["date"] == i].index, "poisson"] = 1

    # traitement particulier paella de la mer, filet
    l_index = ['2011-01-10', '2012-01-09', '2011-01-07', "2012-01-06"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "poisson"] = 1

    # 2 menus : végé et viande, on considère que c'est un menu végé
    l_index = ["2015-11-13", "2015-09-11"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "poisson"] = 0
        df.loc[df[df["date"] == i].index, "viande"] = 0

    # 2 menus : poisson et viande, on considère que c'est un menu poisson
    l_index = ["2015-11-20", "2015-10-16", "2015-10-02", "2015-09-25", "2015-09-18", "2015-09-04", "2015-06-25",
             "2015-06-11"]
    index = [datetime.datetime.strptime(x, '%Y-%m-%d') for x in l_index]

    for i in index:
        df.loc[df[df["date"] == i].index, "poisson"] = 1
        df.loc[df[df["date"] == i].index, "viande"] = 0

    # menu inconnu, mais probablement avec viande d'après le modèle
    df.loc[df[df["date"] == datetime.datetime.strptime("2015-10-15", "%Y-%m-%d")].index, "viande"] = 1

    # feature bio
    df['bio'] = bow_df["bio"]

    # set date as index
    df = df.set_index("date")

    ###############################################################
    # Ajout des 4 premiers et 4 derniers jours de l'année scolaire (grosse incertitude)
    #############################################################

    ind = []
    temp = []
    subset = df.copy()

    #print("subset", subset["annee_scolaire"].unique()[1:])

    for i in range(1, 5):

        for annee in subset["annee_scolaire"].unique()[1:]:
            temp.append(min(subset[(subset.index.year == min(subset[subset["annee_scolaire"] == annee].index.year)) & (
                        subset["annee_scolaire"] == annee)].index))
            df.loc[temp, "4_premiers_jours"] = 1
            ind.append(temp)

            subset.drop(temp, inplace=True)
            temp = []

    for i in range(1, 5):

        for annee in subset["annee_scolaire"].unique()[:-1]:
            temp.append(max(subset[(subset.index.year == max(subset[subset["annee_scolaire"] == annee].index.year)) & (
                        subset["annee_scolaire"] == annee)].index))
            df.loc[temp, "4_derniers_jours"] = 1
            ind.append(temp)

            subset.drop(temp, inplace=True)
            temp = []
    df["4_derniers_jours"].fillna(0, inplace=True)
    df["4_premiers_jours"].fillna(0, inplace=True)

    ####################################
    # Tests (longueur et valeurs manquantes)
    ####################################

    assert len(df) == 1188

    df.to_pickle("data_processed/global.pk")
    df.to_excel("data_processed/global.xlsx")


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

# # ACDC Challenge
#
# In this notebook we will try to obatain the best model for classiying CVD with the use of radiomics data.
#
# We will create a pipeline to work through the data and compare the experiments

# In[1]:

### import the packages and libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score
from sklearn.preprocessing import LabelEncoder, MinMaxScaler
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import f1_score, accuracy_score, confusion_matrix, classification_report, precision_score
from sklearn.svm import LinearSVC, SVC
from sklearn.feature_selection import SelectKBest, f_classif, chi2, RFECV, RFE
from sklearn.model_selection import GridSearchCV
from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from mlxtend.plotting import plot_sequential_feature_selection as plot_sfs
from sklearn.pipeline import Pipeline
from skopt import BayesSearchCV
from skopt.space import Real, Integer
# from sklearn.multiclass import OneVsRestClassifier, OneVsOneClassifier
import seaborn as sns

# ## Machine Learning Pipeline
#
# 1. Dataset
# 2. Feature Engineering/Selection
# 4. ML Algorithms
# 5. Testing on the Data

# ### 1. Dataset
#
# We will load the training and test dataset, which contain the extracted radiomics of 100 and 50 patients, respectively. It will also contain the clinical data (only height and weight available) and the class of the patient (each of the 4 diseases or normal state). We will create a function to prepare the datasets.

# In[2]:

train_df = pd.read_csv('Extracted_radiomics\ACDC_(Radiomics+Clinical)_Training.csv')
print(train_df.shape)
test_df = pd.read_csv('Extracted_radiomics\ACDC_(Radiomics+Clinical)_Testing.csv')
print(test_df.shape)

# We know from prior knowledge that both the train and test dataset are equally balanced.

# We also know that there are features that are not numeric and are just the product of the of the radiomics library that will not be needed for our model. We show them and we are going to eliminate them.

# In[3]:

train_df = train_df.loc[:,~ train_df.columns.str.startswith('diagnostics')]
test_df = test_df.loc[:,~ test_df.columns.str.startswith('diagnostics')]
print(train_df.shape)
print(test_df.shape)

# In[67]:

y_train = train_df['class']
y_test = test_df['class']

# In[70]:

ED_train_df = train_df.filter(regex='ED')
ES_train_df = train_df.filter(regex='ES')

ED_test_df = test_df.filter(regex='ED')
ES_test_df = test_df.filter(regex='ES')

# In[50]:

# ED_train_df = pd.concat([ED_train_df, class_df_train], axis=1)
# ES_train_df = pd.concat([ES_train_df, class_df_train], axis=1)

# ED_test_df = pd.concat([ED_test_df, class_df_test], axis=1)
# ES_test_df = pd.concat([ES_test_df, class_df_test], axis=1)

# In[72]:

rad_train = pd.concat([ED_train_df, ES_train_df], axis = 1)
rad_test = pd.concat([ED_test_df, ES_test_df], axis = 1)

# In[73]:

med_info_train = train_df.iloc[:,-3:-1]
med_info_test = test_df.iloc[:,-3:-1]

# In[74]:

all_data_train = pd.concat([rad_train, med_info_train], axis=1)
all_data_test = pd.concat([rad_test, med_info_test], axis=1)

# ### 2. Feature Engineering/Selection

# ##### Feature Engineering
# * MinMaxScaler for all the features
# * Encoding Class values

# In[11]:

# def prepare_traindata(train_df, test_df, clinical=True):
#     clin = -3

#     if clinical == True:
#         clin = -1

#     X_train,y_train = train_df.iloc[:,:clin], train_df['class'] #Training/Val dataset
#     X_test, y_test = test_df.iloc[:,:clin], test_df['class']  #Test dataset

#     #tools scaling and labelling
#     scaler = MinMaxScaler()
#     encoder = LabelEncoder()

#     X_train = scaler.fit_transform(X_train)
#     X_test = scaler.transform(X_test)

#     y_train= encoder.fit_transform(y_train)
#     y_test = encoder.fit_transform(y_test)

#     return X_train, X_test, y_train,y_test

# In[12]:

#X_train, X_test, y_train,y_test = prepare_traindata(train_df, test_df)

# In[13]:

#X_train.shape

# ##### Feature Selection
#
# For this section we aim to apply several techiniques for feature selection and compare the performance with each proposed model/learning algorithm of the section 3

# Set of Techniques we are going to use:
# 1. <u> K-Best </u>: This method is a **filter method**, which select features according the K-Highest Score of an statistical Test. For this one we are going to use both **Anova-Test** and **Chi-Suared-Test**.
#
# 2. <u> Sequential Forward Feature Elimination </u>: automatically select a subset of features that is most relevant to the problem. The goal of feature selection is two-fold: We want to improve the computational efficiency and reduce the generalization error of the model by removing irrelevant features or noise. http://rasbt.github.io/mlxtend/user_guide/feature_selection/SequentialFeatureSelector/#example-1-a-simple-sequential-forward-selection-example

# In[60]:

def GridSearch_fun(clf, grid, X_train, y_train, X_test):
    gscv = GridSearchCV(clf, grid, scoring='accuracy', cv= StratifiedKFold(4), return_train_score=True)

#     print(gscv.get_params().keys())

    gscv.fit(X_train, y_train)

    #print(gscv.best_parameters)
    #print(gscv.best_score_)

    y_pred = gscv.predict(X_test)

    return y_pred, gscv.best_params_

# #### Models

# This fucniton works, will need to be checked later becuase for the other methods we are using pipeline so is nested, so we need to adapt the param grids, we might want to do the same for this technique to work on the models for every technique

# In[61]:

## Creating Functions to test these techniques

#K-Best

def K_Best_testing(model, X_train,y_train, X_test, y_test, parameter_grid, score_function= f_classif):
    '''Function to test the number of features using the Method K-Best'''
    '''score_function defautl Anova Test'''

    trial_set = np.arange(1,X_train.shape[1], step=1)
    test_accuracy= []
    parameters = []
    y_pred = []

    for x in trial_set:
        selector = SelectKBest(score_function, k=x)

        selector.fit(X_train, y_train)

        # Get columns to keep and create new dataframe with those only

        X_train_tr = selector.transform(X_train)
        X_test_tr = selector.transform(X_test)

        #Splitting the data with the corresponding features

        y_test_pred, best_parameters = GridSearch_fun(model, parameter_grid, X_train_tr, y_train, X_test_tr)

        test_acc = accuracy_score(y_test, y_test_pred)

        y_pred.append(y_test_pred)
        test_accuracy.append(test_acc)
        parameters.append(best_parameters)

    best_nfeatures=test_accuracy.index(max(test_accuracy))+1
    best_model = parameters[best_nfeatures]

    print("Nº of Features Recommended :",  test_accuracy.index(max(test_accuracy))+1, "with a Test acc of :", max(test_accuracy))
    print("Best Model: \n", best_model )

    plt.figure(figsize=(8,6))
    #plt.plot(trial_set, train_accuracy, label='Train accuracy', c='blue')
    plt.plot(trial_set, test_accuracy, label='test accuracy', c='yellow')
    plt.legend()
    plt.title('Trial Set - Accuracy')
    plt.xlabel('Nº of Features')
    plt.ylabel('Accuracy')

    plt.show()

    selector = SelectKBest(score_function, k=best_nfeatures)
    selector.fit(X_train, y_train)

    # Get columns to keep and create new dataframe with those only

    cols = selector.get_support(indices=True)
    features_df_new = train_df.iloc[:,cols]
    K_best = list(features_df_new.columns)  ### Saving the name of the features

    y_test_pred = y_pred[best_nfeatures]

    cm = confusion_matrix(y_test, y_test_pred)

    cm_normalized = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
    plt.figure(figsize=(8,4))
    plt.imshow(cm_normalized, interpolation='nearest', cmap=plt.cm.Blues)
    plt.title("Confusion Matrix")
    sns.heatmap()

    class_list = ['DCM', 'HCM', 'MINF', 'NOR', 'RV']

    tick_marks = np.arange(len(class_list))
    plt.xticks(tick_marks, class_list, rotation=45)
    plt.yticks(tick_marks, class_list)
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()

    # f1_value = f1_score(y_val, y_val_pred, average='weighted')
    # f1_value

    print(classification_report(y_test, y_test_pred,target_names=class_list))

    return K_best

def KBest_GS(X_train, y_train, X_test, y_test, model, param_grid, df ):

    selector = SelectKBest()

    ### Pipeline

    ### we would need to adapt the "NUMBER OF FEATURES PARAMETER OF THE GRID"

    pipe = Pipeline([('selector', selector),
                 ('model', model)])

    featss = np.array(range(3,X_train.shape[1]))

    dict_1 = {'selector__score_func': [f_classif, chi2],
              'selector__k':featss}   #### para pruebas

    dict_1.update(param_grid)

    gs = GridSearchCV(estimator=pipe,
                  param_grid=dict_1,
                  scoring='accuracy',
                  n_jobs=1,
                  cv=StratifiedKFold(4, shuffle=True, random_state=42),
                  iid=True,
                  refit=True,
                     verbose=3)

    print(pipe.get_params().keys())

    gs = gs.fit(X_train, y_train)

    print("Best Model", gs.best_params_)

    print('Best score:', gs.best_score_)

    y_test_pred = gs.predict(X_test)

    test_acc = accuracy_score(y_test,y_test_pred)

    print("\n Test Accuracy with best estimator: ", test_acc)

    cm = confusion_matrix(y_test, y_test_pred)

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

    plt.figure(figsize=(8,4))

    plt.imshow(cm_normalized, interpolation='nearest', cmap=plt.cm.Blues)
    plt.title("Confusion Matrix")
    plt.colorbar()
    plt.tight_layout()

    class_list = ['DCM', 'HCM', 'MINF', 'NOR', 'RV']

    tick_marks = np.arange(len(class_list))
    plt.xticks(tick_marks, class_list, rotation=45)
    plt.yticks(tick_marks, class_list)
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()

    print(classification_report(y_test, y_test_pred,target_names=class_list))

    cols = gs.best_estimator_.steps[0][1].get_support(indices=True)
    features_df_new = df.iloc[:,cols]
    K_best = list(features_df_new.columns)

    print(K_best)

    return gs

# ---
#
# #### Sequential Foward Selection

# In[64]:

def SFS_GS(X_train, y_train, X_test, y_test, model, param_grid):

    #Setting up the SFS
    sfs1 = SFS(estimator=model,
           k_features=X_train.shape[1],
           forward=True,
           floating=False,
           scoring='accuracy',
           cv=StratifiedKFold(4, shuffle=True, random_state=42))

    ### Pipeline

    ### we would need to adapt the "NUMBER OF FEATURES PARAMETER OF THE GRID"

    pipe = Pipeline([('sfs', sfs1),
                 ('model', model)])

    #dict_1 = {'sfs__k_features':list(range(1,X_train.shape[1]))}   #### para pruebas

    dict_1 = {'sfs__k_features':[5,10,15]}  #Testing

    dict_1.update(param_grid)

    gs = GridSearchCV(estimator=pipe,
                  param_grid=dict_1,
                  scoring='accuracy',
                  n_jobs=1,
                  cv=StratifiedKFold(4, shuffle=True, random_state=42),
                  verbose=3,
                  refit=True)

    print(pipe.get_params().keys())

    gs = gs.fit(X_train, y_train)

#     print(gs.best_estimator_.steps)

    print("Best Model", gs.best_params_)

#     print('Best score:', gs.best_score_)

    y_test_pred = gs.predict(X_test)

    test_acc = accuracy_score(y_test,y_test_pred)

    print("\n Test Accuracy with best estimator: ", test_acc)

    cm = confusion_matrix(y_test, y_test_pred)

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

    plt.figure(figsize=(8,4))

    plt.imshow(cm_normalized, interpolation='nearest', cmap=plt.cm.Blues)
    plt.title("Confusion Matrix")
    plt.colorbar()
    plt.tight_layout()

    class_list = ['DCM', 'HCM', 'MINF', 'NOR', 'RV']

    tick_marks = np.arange(len(class_list))
    plt.xticks(tick_marks, class_list, rotation=45)
    plt.yticks(tick_marks, class_list)
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()

    print(classification_report(y_test, y_test_pred,target_names=class_list))

    feats = gs.best_estimator_.steps[0][1].k_feature_idx_

    feats_2= np.asanyarray(feats)

    print(train_df.iloc[:,feats_2].columns)

    return gs, pipe

# In[65]:

#Features from Irm
#train_prueba = train_df.iloc[:,[288,421,411,26,416,585,674,162,774, -1]]
#test_prueba = test_df.iloc[:,[288,421,411,26,416,585,674,162,774, -1]]

# In[24]:

#X_train1, X_train2,y_train1, y_train2 = train_test_split(X_train, y_train, shuffle=True, stratify=y_train, random_state=42)

# In[66]:

def processing(X_train,y_train, X_test, y_test):
    #tools scaling and labelling
    scaler = MinMaxScaler()
    encoder = LabelEncoder()

    X_train = scaler.fit_transform(X_train)
    X_test = scaler.transform(X_test)

    y_train = encoder.fit_transform(y_train)
    y_test = encoder.fit_transform(y_test)

    return X_train, y_train, X_test, y_test

#ED Alone
X_train_ED, y_train, X_test_ED, y_test = processing(ED_train_df, y_train, ED_test_df, y_test)

#ES Alon

X_train_ES, y_train, X_test_ES, y_test = processing(ES_train_df, y_train, ES_test_df, y_test)

#Radiomics

X_train_rad, y_train, X_test_rad, y_test = processing(rad_train, y_train, rad_test, y_test)

#All data

X_train_all, y_train, X_test_all, y_test = processing(all_data_train, y_train, all_data_test, y_test)

# ### 3. ML Algorithms
#
# Let's test some algorithms with the feature selection techniques

# In[77]:

#Support Vector Classifier

model_SVC = SVC(gamma = 'scale', max_iter= 5000, random_state=42)

param_grid_SVC =  {'model__kernel':('linear', 'rbf'),
                   'model__C':[5, 10]}

# param_grid_SVC_nested =  { 'sfs__estimator__kernel': ['linear', 'rbf', 'poly']},
#                           {'degree':[1,5,10]},{
#                    'sfs__estimator__C':[5]}

param_grid_SVC_nested_2 =  { 'selector__estimator__kernel': ['linear', 'rbf'],
                   'selector__estimator__C':[15]}

param_grid_SVC_test_2 =  {
                   'estimator__model__C':[0.5, 1,5,10]}

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

#Random Forest

# Number of trees in random forest
n_estimators = [10, 100,1000]
# Number of features to consider at every split
max_features = ['auto', 'sqrt']
# Maximum number of levels in tree
max_depth = [2,4,6,8,10]
max_depth.append(None)
# Minimum number of samples required to split a node
min_samples_split = [2, 5]
# Minimum number of samples required at each leaf node
min_samples_leaf = [1, 2, 4]
# Method of selecting samples for training each tree
bootstrap = [True, False]
# Create the random grid

# param_grid_RF = {'n_estimators': n_estimators,
#                'max_features': max_features,
#                'max_depth': max_depth,
#                'min_samples_split': min_samples_split,
#                'min_samples_leaf': min_samples_leaf,
#                'bootstrap': bootstrap}

param_grid_RF = {'model__n_estimators': n_estimators,
               'model__max_features': max_features,
               'model__max_depth': max_depth,
               'model__min_samples_split': min_samples_split,
               'model__min_samples_leaf': min_samples_leaf,
               'model__bootstrap': bootstrap}

param_grid_RF_2 = {'estimator__n_estimators': n_estimators,
               'estimator__bootstrap': bootstrap}

model_RF = RandomForestClassifier(random_state=42)

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

# Logistic Regression

param_grid_LR_nested = {'model__penalty': ['l1','l2'],
               'model__C': [0.1,1,10,100, 200]}

param_grid_LR = {'penalty': ['l1','l2'],
               'C': [0.1,1,10,100, 200]}

model_LR = LogisticRegression( multi_class='auto', random_state=42)

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

### Gradient Boosting

# parameters_GRB = {
#     "loss":["deviance"],
#     "learning_rate": [0.01, 0.025, 0.05, 0.075, 0.1, 0.15, 0.2],
#     "min_samples_split": np.linspace(0.1, 0.5, 12),
#     "min_samples_leaf": np.linspace(0.1, 0.5, 12),
#     "max_depth":[3,5,8],
#     "max_features":["log2","sqrt"],
#     "criterion": ["friedman_mse",  "mae"],
#     "subsample":[0.5, 0.618, 0.8, 0.85, 0.9, 0.95, 1.0],
#     "n_estimators":[10]
#     }

# param_grid_GRB_nested = {
#     "model__loss":["deviance"],
#     "model__learning_rate": [0.01, 0.025, 0.05, 0.075, 0.1, 0.15, 0.2],
#     "model__min_samples_split": np.linspace(0.1, 0.5, 12),
#     "model__min_samples_leaf": np.linspace(0.1, 0.5, 12),
#     "model__max_depth":[3,5,8],
#     "model__max_features":["log2","sqrt"],
#     "model__criterion": ["friedman_mse",  "mae"],
#     "model__subsample":[0.5, 0.618, 0.8, 0.85, 0.9, 0.95, 1.0],
#     "model__n_estimators":[10]
#     }

# model_GRB = GradientBoostingClassifier(random_state=42)

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

### Adaboost

#...

# In[37]:

# In[39]:

#gs = KBest_GS(X_train_ED, y_train, X_test_ED, y_test, model_SVC, param_grid_SVC)
#gs = KBest_GS(X_train_ED, y_train, X_test_ED, y_test, model_RF, param_grid_RF)

# In[148]:

#gs, pipe = SFS_GS(X_train, y_train, X_test, y_test, model_SVC, param_grid_SVC_nested)


from math import pi, log, sqrt
import pandas as pd
import numpy as np
from math import pi, log, exp
import matplotlib as mpl; mpl.use("Qt5Agg")
import matplotlib.pyplot as plt

plt.rcParams.update({'font.size': 16})

def collectCoeffsSimple(pressure, temperature):

    # pressure in GPa
    # temperature in degK
    # Cottrell et al 2009

    coeffs = {
        'alpha': 0,
          'beta': 0,
          'chi': 0,
          'delta': 0,
          'epsilon': 0
    }

    if 0 <= pressure <= 3:
        coeffs['alpha'] = 1.11
        coeffs['beta'] = -1.18
        coeffs['chi'] = -0.85
        coeffs['delta'] = 1680
        coeffs['epsilon'] = 487

    elif 3 < pressure:
        coeffs['alpha'] = 1.05
        coeffs['beta'] = -1.10
        coeffs['chi'] = -0.84
        coeffs['delta'] = 3588
        coeffs['epsilon'] = -102

    return coeffs

def partition(pressure, temperature, deltaIW):
    nbo_t = 2.6
    coeffs = collectCoeffsSimple(pressure=pressure, temperature=temperature)
    alpha = coeffs['alpha']
    beta = coeffs['beta']
    chi = coeffs['chi']
    delta = coeffs['delta']
    epsilon = coeffs['epsilon']
    logD = alpha + (beta * deltaIW) + (chi * nbo_t) + (delta * (1/temperature)) + (epsilon * (pressure/temperature))
    D = 10**logD
    return D

def adiabat(current_depth, current_temperature, depth_increment, depth, gravity, thermal_expansion, heat_capacity,
            depth_gradient, adiabat_gradient):
    current_depth += depth_increment
    # dT/dh = (alpha * g * T) / c_p
    current_temperature += ((thermal_expansion * gravity * current_temperature) / heat_capacity) * depth_increment
    adiabat_gradient.append(current_temperature)
    depth_gradient.append(current_depth / 1000)
    if current_depth < depth:  # recursion!
        return adiabat(current_depth, current_temperature, depth_increment, depth, gravity, thermal_expansion,
                       heat_capacity, depth_gradient, adiabat_gradient)
    else:
        return depth_gradient, adiabat_gradient

def hydrostatic(current_depth, depth_increment, depth, gravity, density_melt, current_pressure, depth_gradient,
                pressure_gradient):
    current_depth += depth_increment
    # dP/dh = rho * g
    current_pressure += (density_melt * gravity) * depth_increment
    pressure_gradient.append(current_pressure * (10**(-9)))  # gPa
    depth_gradient.append(current_depth / 1000)
    if current_depth < depth:
        return hydrostatic(current_depth, depth_increment, depth, gravity, density_melt, current_pressure, depth_gradient,
                pressure_gradient)
    else:
        return depth_gradient, pressure_gradient

earth_magma_ocean_depth = 520 * 1000
earth_magma_ocean_depth_increment = 260 * 10
earth_surface_gravity = 9.8

vesta_magma_ocean_depth = 262.8 * 1000
vesta_magma_ocean_depth_increment = 400
vesta_surface_gravity = 0.25

silicate_density = 3750
metal_density = 7800
w_diffusivity = 10**-8
thermal_expansivity = 6 * 10**(-5)
heat_capacity = 10**3

earth_z_eq_eta_35_actual = 23.93 / 1000
earth_z_eq_eta_10_actual = 62.97 / 1000

earth_adiabatic_depths, earth_adiabatic = adiabat(
    current_depth=0 / 1000,  # begin at surface
    current_temperature=2000,  # degrees K
    depth_increment=earth_magma_ocean_depth_increment,  # 10 km interval
    depth=earth_magma_ocean_depth,  # to depth of 250 km
    gravity=earth_surface_gravity,  # m/s^2, Vesta
    thermal_expansion=thermal_expansivity,
    heat_capacity=heat_capacity,
    depth_gradient=[0],  # returns this list at index=0
    adiabat_gradient=[2000],  # returns this list at index=1
)

earth_hydrostatic_depths, earth_hydrostat = hydrostatic(
    current_depth=0 / 1000,
    depth_increment=earth_magma_ocean_depth_increment,
    depth=earth_magma_ocean_depth,
    gravity=earth_surface_gravity,
    current_pressure=0,
    density_melt=silicate_density,
    depth_gradient=[0],
    pressure_gradient=[0],
)

vesta_adiabatic_depths, vesta_adiabatic = adiabat(
    current_depth=0 / 1000,  # begin at surface
    current_temperature=2000,  # degrees K
    depth_increment=vesta_magma_ocean_depth_increment,  # 10 km interval
    depth=vesta_magma_ocean_depth,  # to depth of 250 km
    gravity=vesta_surface_gravity,  # m/s^2, Vesta
    thermal_expansion=thermal_expansivity,
    heat_capacity=heat_capacity,
    depth_gradient=[0],  # returns this list at index=0
    adiabat_gradient=[2000],  # returns this list at index=1
)

vesta_hydrostatic_depths, vesta_hydrostat = hydrostatic(
    current_depth=0 / 1000,
    depth_increment=vesta_magma_ocean_depth_increment,
    depth=vesta_magma_ocean_depth,
    gravity=vesta_surface_gravity,
    current_pressure=0,
    density_melt=silicate_density,
    depth_gradient=[0],
    pressure_gradient=[0],
)

cottrell_model_vesta = []
cottrell_model_earth = []
fO2_list = [-0.8, -1.10, -2.25, -2.45]
for i in fO2_list:
    temp_d_vesta = []
    temp_d_earth = []
    for index, t in enumerate(vesta_hydrostatic_depths):
        pressure = vesta_hydrostat[index]
        temperature = vesta_adiabatic[index]
        d = partition(pressure=pressure, temperature=temperature, deltaIW=i)
        temp_d_vesta.append(d)
    for index, t in enumerate(earth_hydrostatic_depths):
        pressure = earth_hydrostat[index]
        temperature = earth_adiabatic[index]
        d = partition(pressure=pressure, temperature=temperature, deltaIW=i)
        temp_d_earth.append(d)
    cottrell_model_vesta.append(temp_d_vesta)
    cottrell_model_earth.append(temp_d_earth)

print(vesta_adiabatic[-1], earth_adiabatic[-1], vesta_hydrostat[-1], earth_hydrostat[-1])

# adiabatic/hydrostatic gradient figure
fig1 = plt.figure()
ax1_0 = fig1.add_subplot(111)
ax1_1 = fig1.add_subplot(211)
ax1_2 = fig1.add_subplot(212)
ax1_1.plot(vesta_adiabatic_depths, vesta_adiabatic, linewidth=2.0, color='black', label='Vesta')
ax1_2.plot(earth_adiabatic_depths, earth_adiabatic, linewidth=2.0, color='black', label='Earth')
# Turn off axis lines and ticks of the big subplot
ax1_0.spines['top'].set_color('none')
ax1_0.spines['bottom'].set_color('none')
ax1_0.spines['left'].set_color('none')
ax1_0.spines['right'].set_color('none')
ax1_0.tick_params(labelcolor='w', top='off', bottom='off', left='off', right='off')
ax1_0.xaxis.labelpad = 20
ax1_0.yaxis.labelpad = 20
ax1_0.set_xlabel("Depth (km)")
ax1_0.set_ylabel("Temperature ($\degree$K)")
ax1_0.set_title("Adiabatic Temperature Profile for Vestian and Earth Magma Ocean")
ax1_1.grid()
ax1_2.grid()
ax1_1.legend(loc='upper left')
ax1_2.legend(loc='upper left')
ax1_1.set_xlim(0, max(vesta_adiabatic_depths))
ax1_2.set_xlim(0, max(earth_adiabatic_depths))

fig4 = plt.figure()
ax4_0 = fig4.add_subplot(111)
ax4_1 = fig4.add_subplot(211)
ax4_2 = fig4.add_subplot(212)
ax4_1.plot(vesta_hydrostatic_depths, vesta_hydrostat, linewidth=2.0, color='black', label='Vesta')
ax4_2.plot(earth_hydrostatic_depths, earth_hydrostat, linewidth=2.0, color='black', label='Earth')
# Turn off axis lines and ticks of the big subplot
ax4_0.spines['top'].set_color('none')
ax4_0.spines['bottom'].set_color('none')
ax4_0.spines['left'].set_color('none')
ax4_0.spines['right'].set_color('none')
ax4_0.tick_params(labelcolor='w', top='off', bottom='off', left='off', right='off')
ax4_0.xaxis.labelpad = 20
ax4_0.yaxis.labelpad = 20
ax4_0.set_xlabel("Depth (km)")
ax4_0.set_ylabel("Pressure (GPa)")
ax4_0.set_title("Hydrostatic Pressure Profile for Vestian and Earth Magma Ocean")
ax4_1.grid()
ax4_2.grid()
ax4_1.legend(loc='upper left')
ax4_2.legend(loc='upper left')
ax4_1.set_xlim(0, max(vesta_hydrostatic_depths))
ax4_2.set_xlim(0, max(earth_hydrostatic_depths))

# cottrell partition models for Vesta
fig2 = plt.figure()
ax2_0 = fig2.add_subplot(111)
ax2_1 = fig2.add_subplot(211)
ax2_2 = fig2.add_subplot(212)
# Turn off axis lines and ticks of the big subplot
ax2_0.spines['top'].set_color('none')
ax2_0.spines['bottom'].set_color('none')
ax2_0.spines['left'].set_color('none')
ax2_0.spines['right'].set_color('none')
ax2_0.tick_params(labelcolor='w', top='off', bottom='off', left='off', right='off')
ax2_0.xaxis.labelpad = 20
ax2_0.yaxis.labelpad = 20
ax2_0.set_xlabel("Depth (km)")
ax2_0.set_ylabel("D")
ax2_0.set_title("Predicted Partition Coefficients for a Vestian Magma Ocean")
ax2_1.plot(vesta_hydrostatic_depths, cottrell_model_vesta[0], color='black')
ax2_1.plot(vesta_hydrostatic_depths, cottrell_model_vesta[1], color='black')
ax2_1.fill_between(vesta_hydrostatic_depths, cottrell_model_vesta[0], cottrell_model_vesta[1], color='red', alpha=0.4,
                   label="Vesta Oxidizing Model")
ax2_1.grid()
ax2_1.legend(loc='upper right')
ax2_2.plot(vesta_hydrostatic_depths, cottrell_model_vesta[2], color='black')
ax2_2.plot(vesta_hydrostatic_depths, cottrell_model_vesta[3], color='black')
ax2_2.fill_between(vesta_hydrostatic_depths, cottrell_model_vesta[2], cottrell_model_vesta[3], color='red', alpha=0.4,
                   label="Vesta Reducing Model")
ax2_2.grid()
ax2_2.legend(loc='upper right')

# cottrell partition models for Earth
fig3 = plt.figure()
ax3_0 = fig3.add_subplot(111)
ax3_1 = fig3.add_subplot(211)
ax3_2 = fig3.add_subplot(212)
# Turn off axis lines and ticks of the big subplot
ax3_0.spines['top'].set_color('none')
ax3_0.spines['bottom'].set_color('none')
ax3_0.spines['left'].set_color('none')
ax3_0.spines['right'].set_color('none')
ax3_0.tick_params(labelcolor='w', top='off', bottom='off', left='off', right='off')
ax3_0.xaxis.labelpad = 20
ax3_0.yaxis.labelpad = 20
ax3_0.set_xlabel("Depth (km)")
ax3_0.set_ylabel("D")
ax3_0.set_title("Predicted Partition Coefficients for an Earth Magma Ocean")
ax3_1.plot(earth_hydrostatic_depths, cottrell_model_earth[0], color='black')
ax3_1.plot(earth_hydrostatic_depths, cottrell_model_earth[1], color='black')
ax3_1.fill_between(earth_hydrostatic_depths, cottrell_model_earth[0], cottrell_model_earth[1], color='red', alpha=0.5,
                   label="Earth Oxidizing Model")
ax3_1.axvline(earth_z_eq_eta_10_actual, linewidth=2.0, linestyle="--", color='black', label="z$_{eq}$ ($\eta$=10$^{-1.0}$)")
ax3_1.axvline(earth_z_eq_eta_35_actual, linewidth=2.0, linestyle="--", color='red', label="z$_{eq}$ ($\eta$=10$^{-3.5}$)")
ax3_2.axvline(earth_z_eq_eta_10_actual, linewidth=2.0, linestyle="--", color='black', label="z$_{eq}$ ($\eta$=10$^{-1.0}$)")
ax3_2.axvline(earth_z_eq_eta_35_actual, linewidth=2.0, linestyle="--", color='red', label="z$_{eq}$ ($\eta$=10$^{-3.5}$)")
ax3_1.grid()
ax3_1.legend(loc='upper right')
ax3_2.plot(earth_hydrostatic_depths, cottrell_model_earth[2], color='black')
ax3_2.plot(earth_hydrostatic_depths, cottrell_model_earth[3], color='black')
ax3_2.fill_between(earth_hydrostatic_depths, cottrell_model_earth[2], cottrell_model_earth[3], color='red', alpha=0.5,
                   label="Earth Reducing Model")
ax3_2.grid()
ax3_2.legend(loc='upper right')

plt.show()


import streamlit as st
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import MinMaxScaler
import pickle
import os

st.title('Telco Churn Prediction')
st.sidebar.header('Choose According to your Criteria')

project_dir = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(project_dir, 'Customer_Churn_Prediction.png')
st.image(image_path, use_column_width=True)

def user_input_features():
    services_options = ['No internet service', 'Use internet services but no additional service', '1 Service', '2 Service', '3 Service', '4 Service', '5 Service', '6 Service']
    multiple_lines_options = ['No phone services', 'Use phone services but no multiple lines', 'Use phone services and use multiple lines']
    internet_services_options = ['DSL', 'Fiber optic', 'No']
    contract_options = ['Month-to-month', 'One year', 'Two year']
    payment_method_options = ['Bank transfer', 'Credit card', 'Electronic check', 'Mailed check']

    tenure_months = st.sidebar.number_input('⌛ Tenure Months', int(np.arange(1, 73)[0]), int(np.arange(1, 73)[-1]))
    monthly_charges = st.sidebar.number_input('💸 Monthly Charges', float(np.arange(18.25, 119.75)[0]), float(np.arange(18.25, 119.75)[-1]))
    multiple_lines = st.sidebar.selectbox('☎ Multiple Lines', multiple_lines_options)
    services = st.sidebar.selectbox('📑 Service Types', services_options)
    internet_services = st.sidebar.selectbox('🛜 Internet Service Types', internet_services_options)
    contract = st.sidebar.selectbox('🗓 Contract Types', contract_options)
    payment_method = st.sidebar.selectbox('💳 Payment Method', payment_method_options)

    data = {'Tenure': tenure_months,
            'MonthlyCharges': monthly_charges,
            'Services': services,
            'MultipleLinesService': multiple_lines,
            'InternetService': internet_services,
            'Contract': contract,
            'PaymentMethod': payment_method
            }

    features = pd.DataFrame(data, index=[0])
    return features

input_df = user_input_features()

csv_file_path = os.path.join(project_dir, 'Customer_Churn_Prediction.csv')
churn_raw = pd.read_csv(csv_file_path)
churn = churn_raw.drop(columns=['Churn'])
df = pd.concat([input_df, churn], axis=0)
df_test = df[:1]

df['Services'] = df['Services'].astype(str)
df['MultipleLinesService'] = df['MultipleLinesService'].astype(str)

label_encode_columns = ['Services', 'MultipleLinesService']
label_encoder = LabelEncoder()
for column in label_encode_columns:
    df[column] = label_encoder.fit_transform(df[column])

one_hot_encode_columns = ['InternetService', 'Contract', 'PaymentMethod']
df_encoded = pd.get_dummies(df, columns=one_hot_encode_columns)

model_path = os.path.join(project_dir, 'Customer_Churn_Prediction.sav')
loaded_model_dict = pickle.load(open(model_path, 'rb'))
loaded_model = loaded_model_dict['model']

st.subheader('Churn Prediction and Confidence Score')

if st.button('Predict'):
    prediction = loaded_model.predict(df_encoded)
    prediction_proba = loaded_model.predict_proba(df_encoded)[:, 1]

    prob = prediction_proba[0]
    churn_prediction = 'Churn' if prob > 0.5 else 'Not Churn'
    confidence_not_churn = 1 - prob
    confidence_score = prob

    background_color = 'red' if churn_prediction == 'Churn' else 'green'
    font_size = '20px'

    styled_prediction_churn = f"
Customer will Churn with a confidence level of {confidence_score:.2%}.
"
    styled_prediction_not_churn = f"
Customer will Not Churn with a confidence level of {confidence_not_churn:.2%}.
"

    if churn_prediction == 'Churn':
        st.markdown(styled_prediction_churn, unsafe_allow_html=True)
    else:
        st.markdown(styled_prediction_not_churn, unsafe_allow_html=True)


from email.message import EmailMessage
import ssl
import smtplib

smtp_server = "smtp-relay.sendinblue.com"
port = 587
sender_email = 'proyectoceiabd@gmail.com'
email_receiver = 'adrian.correa.cordero@gmail.com'
em = EmailMessage()
em['From'] = 'proyectoceiabd@gmail.com'
em['To'] = 'adrian.correa.cordero@gmail.com'
em['Subject'] = "Alerta CEIABD"
em.set_content("La ruido ha sobrepasado el umbral definido")

# Create a secure SSL context
context = ssl.create_default_context()

# Try to log in to server and send email
with smtplib.SMTP(smtp_server, port) as server:
    server.ehlo()
    server.starttls(context=context) # Secure the connection
    server.ehlo()
    server.login(sender_email, 'C6GqRdTX8ZE5cU4g')
    server.sendmail(sender_email, email_receiver, em.as_string())
print('Correo enviado')


import linecache
import sys

from converttomachinecode1 import *
from decode1 import *
from error_handling import *
from execute0 import *
from fetch0 import *
from memoryaccess1 import *
from registerupdate1 import *

def unpipelined_func():
    assign_labelled_instruction()  # Labelled instruction has been stored in list
    globalss.assign_register()  # a 32 length array nas been assigned for register
    a = error_handling()  # checking for error
    if a == 1:
        print('not passed')  # if error exist
        sys.exit()
    print('passed')  # no error
    convert_to_machinecode()  # Phase 1 portion ...A machinecode.txt file has been created
    globalss.assign_memory()  # 1000 size array has been assigned for memory
    globalss.assign_stack()  # 1000 size array has been assigned for stack

    file2 = open('machinecode.txt', 'r')
    i = 1
    CLOCK = 0
    each = str(linecache.getline('machinecode.txt', i))  # Execution will be done now
    while each != '':
        print((each))
        global reg
        each = each.split()
        if (len(each) == 1):
            globalss.PC_execution = globalss.PC_execution + 4
            i = int(globalss.PC_execution / 4) + 1
            each = (linecache.getline('machinecode.txt', i))
            continue
        lii = fetch(each)
        CLOCK = CLOCK + 1
        # print("Instruction fetched!!")
        # We will update the reg[] list after the execution of every step

        reg = decode(lii)  # now exact instruction name will be appended #reg[rd,rs1,rs2,imm,type]
        CLOCK = CLOCK + 1
        # print("Instruction Decoded!!")
        reg = determine_exact_instruction(lii,
                                          reg)  # now exact instruction name will be appended #reg[rd,rs1,rs2,imm,type,oriname]

        reg = execute(reg)  # execution result will be appended in the reg list
        CLOCK = CLOCK + 1
        # print("Instruction executed!!")

        reg = memoryaccess(reg)  # a new value has been appended. We will use this value in regsiter update
        CLOCK = CLOCK + 1
        # print("Memory accessed")                 # reg[rd,rs1,rs2,imm,type,oriname,execute_result,memoryaccessreult]

        registerupdate(reg)
        CLOCK = CLOCK + 1
        # print("Writeback done!!")

        print(reg)  # It is printing the contents of a instruction
        i = int(globalss.PC_execution / 4) + 1  # It contains the line number of next instruction to be executed
        print(i)
        each = (linecache.getline('machinecode.txt', i))  # each will contain  the next instruction
        reg.clear()  # reg list is cleared
        globalss.register[0] = 0  # register x0 is updated to value zero.Because it is constant
    file2.close()
    print("Number of cycles: ", CLOCK)  # Run this to print clock cycles
    # print(globalss.memory_array)           #Run this to print the memory
    print(register)  # Run this to print the register

if __name__ == '__main__':
    unpipelined_func()


# -*- coding: utf-8 -*-
import pytz
import re
import six

from dateutil import rrule

from five import grok

from zope import schema
from zope.interface import Interface, invariant, Invalid, Attribute
from zope.component import getAllUtilitiesRegisteredFor as getallutils
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm

from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
from plone.directives import form
from plone.dexterity.interfaces import IDexterityFTI
from plone.dexterity.utils import schemaNameToPortalType as getname

from z3c.form.browser.checkbox import CheckBoxFieldWidget
from z3c.form.browser.radio import RadioFieldWidget
from z3c.form import widget

from libres.modules.rasterizer import VALID_RASTER
from seantis.plonetools.schemafields import Email
from seantis.reservation import _, utils
from seantis.reservation.mail_templates import templates
from seantis.reservation.utils import _languagelist

class ISeantisReservationSpecific(Interface):
    pass

days = SimpleVocabulary(
    [
        SimpleTerm(value=rrule.MO, title=_(u'Mo')),
        SimpleTerm(value=rrule.TU, title=_(u'Tu')),
        SimpleTerm(value=rrule.WE, title=_(u'We')),
        SimpleTerm(value=rrule.TH, title=_(u'Th')),
        SimpleTerm(value=rrule.FR, title=_(u'Fr')),
        SimpleTerm(value=rrule.SA, title=_(u'Sa')),
        SimpleTerm(value=rrule.SU, title=_(u'Su')),
    ]
)

recurrence = SimpleVocabulary(
    [
        SimpleTerm(value=False, title=_(u'Once')),
        SimpleTerm(value=True, title=_(u'Daily')),
    ]
)

calendar_views = SimpleVocabulary(
    [
        SimpleTerm(value='month', title=_(u'Monthly View')),
        SimpleTerm(value='agendaWeek', title=_(u'Weekly View')),
        SimpleTerm(value='agendaDay', title=_(u'Daily View'))
    ]
)

default_views = ['month', 'agendaWeek', 'agendaDay']
default_selected_view = 'agendaWeek'

calendar_dates = SimpleVocabulary(
    [
        SimpleTerm(value='current', title=_(u'Always show the current date')),
        SimpleTerm(value='specific', title=_(u'Always show a specific date'))
    ]
)

# plone.app.vocabularies should have that, but it won't work on travis
# -> no harm loading our own...
common_timezones = SimpleVocabulary(
    [SimpleTerm(value=tz, title=tz) for tz in pytz.common_timezones]
)

def select_at_least_one(values):
    if not values:
        raise Invalid(
            _(u'Select at least one value')
        )
    return True

@grok.provider(IContextSourceBinder)
def form_interfaces(context):
    """ Used as a source for a vocabulary this function returns a vocabulary
    of interfaces which may be used as sub-forms in a resource object.

    """
    dutils = getallutils(IDexterityFTI)
    behaviors = set((
        'seantis.reservation.interfaces.IReservationFormSet',
        'seantis.reservation.interfaces.IReservationManagerFormSet'
    ))
    interfaces = [
        (
            u.title, u.lookupSchema()
        ) for u in dutils if behaviors & set(u.behaviors)
    ]

    def get_term(item):
        return SimpleTerm(title=item[0], value=getname(item[1].__name__))

    return SimpleVocabulary(map(get_term, interfaces))

@grok.provider(IContextSourceBinder)
def plone_languages(context):
    def get_term(item):
        return SimpleTerm(title=item[1]['native'], value=item[0])

    terms = sorted(map(get_term, _languagelist.items()), key=lambda t: t.title)

    return SimpleVocabulary(terms)

class IOverview(Interface):
    """ Views implementing this interface may use the OverviewletManager to
    display an overview of a list of resources.

    The OverviewletManager displays viewlets which work with a list of
    resources in a folderish view. Those resources are not required to actually
    be stored in that folder. They just need to be defined using this
    interface.

    The result may be something like this, with the part on the right side
    being the work of the overview:

    Resources Overivew

                                ╔═══════════════╗
        » Resource One          ║ ░ ░ ░ ░ ░ ░ ░ ║
        » Resource Two          ║   calendar    ║
                                ║ ░ ░ ░ ░ ░ ░ ░ ║
                                ╚═══════════════╝

                                » Monthly Report
                                » Compare Resources
    """

    def resource_map(self):
        """ Returns a dictionary mapping items to resources. Or in the case
        of a simple resource list, the list of uuids of those resources.

        Simple
        ------
        If you deal with a folderish view which only displays a list of
        resources you can simply return a list of uuids (or any other
        iterable except strings):

        [uuid1, uuid2, uuid3]

        The uuids may be UUID objects or strings.

        -> See Listing view in seantis.reservation.resource

        Grouped
        -------
        If you deal with a folderish view which shows parents of groups of
        resources you should return something like this:

        group1 -> [uuid1, uuid2]
        group2 -> [uuid3]

        This will highlight group1 if a day containing uuid1 or uuid2 is
        hovered over in the calendar. It will also highlight the days for which
        there's an allocation in any of the resources when a group is hovered
        over.

        -> See Directory View in seantis.dir.facility.directory

        Note
        ----
        For the highlighting to work the id of the element in the browser
        must be the uuid in the simple and the group key in the grouped
        example.

        """

# not really where I want this code to be, but the code needs some reorganizing
# because of circular imports and the like
class OverviewletManager(grok.ViewletManager):
    """ Manages the viewlets shown in the overview. """
    grok.context(Interface)
    grok.name('seantis.reservation.overviewletmanager')
    grok.layer(ISeantisReservationSpecific)

    @utils.cached_property
    def uuidmap(self):
        """ Returns a dictionary mapping resource uuids to item ids. """

        if not IOverview.providedBy(self.view):
            return {}

        rmap = self.view.resource_map()
        assert not isinstance(rmap, six.string_types)

        def transform_uuid(target):
            if utils.is_uuid(target):
                return utils.string_uuid(target)
            else:
                return target

        if not isinstance(rmap, dict):
            return dict(([transform_uuid(uuid)] * 2) for uuid in rmap)

        # overlay.js needs the map the other way around, which is mostly a
        # historical artifact, but it also makes more sense for the developer
        # using IOverview to define a group -> resources relationship
        uuidmap = {}
        for key, resources in rmap.items():
            assert isinstance(resources, (list, tuple, set))

            for resource in resources:
                uuidmap.setdefault(transform_uuid(resource), []).append(key)

        return uuidmap

    @property
    def resource_uuids(self):
        if not self.uuidmap:
            return []

        return self.uuidmap.keys()

class IReservationFormSet(Interface):
    """ Marks interface as usable for sub-forms in a resource object. """

class IReservationManagerFormSet(IReservationFormSet):
    """ Same as IReservationFormSet but only available to managers. """

class IResourceAllocationDefaults(form.Schema):

    quota = schema.Int(
        title=_(u'Quota'),
        description=_(
            u'Number of times an allocation may be reserved at the same time. '
            u'e.g. 3 spots in a daycare center, 2 available cars, '
            u'1 meeting room. '
        ),
        default=1
    )

    reservation_quota_limit = schema.Int(
        title=_(u'Reservation Quota Limit'),
        description=_(
            u'The maximum quota a single reservation may occupy at once. '
            u'There is no limit if set to zero.'
        ),
        default=1
    )

    approve_manually = schema.Bool(
        title=_(u'Manually approve reservation requests'),
        description=_(
            u'If checked a reservation manager must decide if a reservation '
            u'can be approved. Until then users are added to a waitinglist. '
            u'Reservations are automatically approved if this is not checked. '
        ),
        default=False
    )

    partly_available = schema.Bool(
        title=_(u'Partly available'),
        description=_(
            u'If the allocation is partly available users may reserve '
            u'only a part of it (e.g. half of it). If not the allocation '
            u'Must be reserved as a whole or not at all'
        ),
        default=False
    )

    raster = schema.Choice(
        title=_(u'Raster'),
        description=_(
            u'Defines the minimum length of any given reservation as well '
            u'as the alignment of the start / end of the allocation. E.g. a '
            u'raster of 30 minutes means that the allocation can only start '
            u'at xx:00 and xx:30 respectively'
        ),
        values=VALID_RASTER,
        default=15
    )

    @invariant
    def isValidQuota(Allocation):
        if not (1 <= Allocation.quota and Allocation.quota <= 1000):
            raise Invalid(_(u'Quota must be between 1 and 1000'))

    @invariant
    def isValidQuotaLimit(Allocation):
        if Allocation.reservation_quota_limit < 0:
            raise Invalid(
                _(u'Reservation quota limit must zero or a positive number')
            )

class IResourceBase(IResourceAllocationDefaults):
    """ A resource displaying a calendar. """

    title = schema.TextLine(
        title=_(u'Name')
    )

    description = schema.Text(
        title=_(u'Description'),
        required=False
    )

    first_hour = schema.Int(
        title=_(u'First hour of the day'),
        description=_(
            u'Everything before this hour is not shown in the '
            u'calendar, making the calendar display more compact. '
            u'Should be set to an hour before which there cannot '
            u'be any reservations.'
        ),
        default=7
    )

    last_hour = schema.Int(
        title=_(u'Last hour of the day'),
        description=_(
            u'Everything after this hour is not shown in the '
            u'calendar, making the calendar display more compact. '
            u'Should be set to an hour after which there cannot '
            u'be any reservations.'
        ),
        default=23
    )

    available_views = schema.List(
        title=_(u'Available Views'),
        description=_(u'Views available to the user on the calendar.'),
        value_type=schema.Choice(
            source=calendar_views
        ),
        default=default_views,
        constraint=select_at_least_one
    )

    form.widget(available_views=CheckBoxFieldWidget)

    selected_view = schema.Choice(
        title=_(u'Selected View'),
        description=_(u'Selected view when opening the calendar.'),
        source=calendar_views,
        default=default_selected_view
    )

    form.widget(selected_view=RadioFieldWidget)

    selected_date = schema.Choice(
        title=_(u'Selected Date'),
        description=_(u'Calendar date shown when opening the calendar.'),
        source=calendar_dates,
        default='current'
    )

    form.widget(selected_date=RadioFieldWidget)

    specific_date = schema.Date(
        title=_(u'Specific Date'),
        required=False
    )

    form.fieldset(
        'defaults',
        label=_(u'Default Allocation Values'),
        fields=(
            'quota', 'partly_available', 'raster', 'approve_manually',
            'reservation_quota_limit'
        )
    )

    form.widget(thank_you_text=WysiwygFieldWidget)
    thank_you_text = schema.Text(
        title=_(u"Thank you text"),
        description=_(
            u"Shown to the user when the reservation has been completed. "
            u"A good place to inform the user general information about the "
            u"reservation he just completed."
        ),
        required=False
    )

    formsets = schema.List(
        title=_(u'Formsets'),
        description=_(
            u'Subforms that need to be filled out to make a reservation. '
            u'Forms can currently only be created by a site-administrator.'
        ),
        value_type=schema.Choice(
            source=form_interfaces,
        ),
        required=False
    )

    form.widget(formsets=CheckBoxFieldWidget)

    @invariant
    def isValidFirstLastHour(Resource):
        in_valid_range = lambda h: 0 <= h and h <= 24
        first_hour, last_hour = Resource.first_hour, Resource.last_hour

        if not in_valid_range(first_hour):
            raise Invalid(_(u'Invalid first hour'))

        if not in_valid_range(last_hour):
            raise Invalid(_(u'Invalid last hour'))

        if last_hour <= first_hour:
            raise Invalid(
                _(u'First hour must be smaller than last hour')
            )

    @invariant
    def isValidCalendarDate(Resource):
        if Resource.selected_date == 'specific' and not Resource.specific_date:
            raise Invalid(
                _(u"You chose to 'Always show a specific date' but you did "
                  u"not specify a specific date")
            )

    @invariant
    def isValidSelectedView(Resource):
        if Resource.selected_view not in Resource.available_views:
            raise Invalid(
                _(u'The selected view must be one of the available views.')
            )

class IResource(IResourceBase):
    pass

class IAllocation(IResourceAllocationDefaults):
    """ An reservable time-slot within a calendar. """

    id = schema.Int(
        title=_(u'Id'),
        default=-1,
        required=False,
    )

    group = schema.Text(
        title=_(u'Recurrence'),
        default=u'',
        required=False
    )

    timeframes = schema.Text(
        title=_(u'Timeframes'),
        default=u'',
        required=False
    )

    start_time = schema.Time(
        title=_(u'Start'),
        description=_(
            u'Allocations may start every 5 minutes if the allocation '
            u'is not partly available. If it is partly available the start '
            u'time may be every x minute where x equals the given raster.'
        )
    )

    end_time = schema.Time(
        title=_(u'End'),
        description=_(
            u'Allocations may end every 5 minutes if the allocation '
            u'is not partly available. If it is partly available the start '
            u'time may be every x minute where x equals the given raster. '
            u'The minimum length of an allocation is also either 5 minutes '
            u'or whatever the value of the raster is.'
        )
    )

    whole_day = schema.Bool(
        title=_(u'Whole Day'),
        description=_(
            u'The allocation spans the whole day.'
        ),
        required=False,
        default=False
    )

    recurring = schema.Choice(
        title=_(u'Recurrence'),
        vocabulary=recurrence,
        default=False
    )

    day = schema.Date(
        title=_(u'Day'),
    )

    recurrence_start = schema.Date(
        title=_(u'From'),
    )

    recurrence_end = schema.Date(
        title=_(u'Until')
    )

    days = schema.List(
        title=_(u'Days'),
        value_type=schema.Choice(vocabulary=days),
        required=False
    )

    separately = schema.Bool(
        title=_(u'Separately reservable'),
        description=_(
            u'If checked parts of the recurrance may be reserved. '
            u'If not checked the recurrance must be reserved as a whole.'
        ),
        required=False,
        default=False
    )

    @invariant
    def isValidRange(Allocation):
        start, end = utils.get_date_range(
            Allocation.day,
            Allocation.start_time, Allocation.end_time
        )

        if not Allocation.whole_day and abs((end - start).seconds // 60) < 5:
            raise Invalid(_(u'The allocation must be at least 5 minutes long'))

    @invariant
    def isValidOption(Allocation):
        if Allocation.recurring:
            if Allocation.partly_available and not Allocation.separately:
                raise Invalid(_(
                    u'Partly available allocations can only be reserved '
                    u'separately'
                ))

class ITimeframe(form.Schema):
    """ A timespan which is either visible or hidden. """

    title = schema.TextLine(
        title=_(u'Name')
    )

    start = schema.Date(
        title=_(u'Start')
    )

    end = schema.Date(
        title=_(u'End')
    )

    @invariant
    def isValidDateRange(Timeframe):
        if Timeframe.start > Timeframe.end:
            raise Invalid(_(u'End date before start date'))

template_variables = _(
    u'May contain the following template variables:
'
    u'%(resource)s - title of the resource
'
    u'%(dates)s - list of dates reserved
'
    u'%(quota)s - reservation quota
'
    u'%(reservation_mail)s - email of reservee
'
    u'%(data)s - formdata associated with the reservation
'
    u'%(reservation_link)s - link to the reservation view
'
    u'%(approval_link)s - link to the approval view
'
    u'%(denial_link)s - link to the denial view
'
    u'%(cancel_link)s - link to the cancel view'
)

template_revoke_variables = template_variables + _(
    u'%(reason)s - reason for revocation
'
)

template_time_changed_variables = template_revoke_variables + _(
    u'%(old_time)s - old start/end time
'
    u'%(new_time)s - new start/end time
'
)

reservations_template_variables = _(
    u'May contain the following template variable:
'
    u'%(reservations)s - list of reservations'
)

class IEmailTemplate(form.Schema):
    """ An email template used for custom email messages """

    language = schema.Choice(
        title=_(u'Language'),
        source=plone_languages
    )

    reservation_made_subject = schema.TextLine(
        title=_(u'Email Subject for Reservation Autoapproved'),
        description=_(u'Sent to managers when a reservation is '
                      u'automatically approved. '
                      u'May contain the template variables listed below.'),
        default=templates['reservation_made'].get_subject('en')
    )

    reservation_made_content = schema.Text(
        title=_(u'Email Text for Reservation Autoapproved'),
        description=template_variables,
        default=templates['reservation_made'].get_body('en')
    )

    reservation_pending_subject = schema.TextLine(
        title=_(u'Email Subject for Reservation Pending'),
        description=_(
            u'Sent to managers when a new pending reservation is made. '
            u'May contain the template variables listed below.'
        ),
        default=templates['reservation_pending'].get_subject('en')
    )

    reservation_pending_content = schema.Text(
        title=_(u'Email Text for Reservation Pending'),
        description=template_variables,
        default=templates['reservation_pending'].get_body('en')
    )

    reservation_received_subject = schema.TextLine(
        title=_(u'Email Subject for Received Reservations'),
        description=_(
            u'Sent to users when a new reservation is made wheter they '
            u'still need to be approved or not. By default it cointains the '
            u'reservations made with an indication of the approval status. '
            u'May contain the template variables listed below.'
        ),
        default=templates['reservation_received'].get_subject('en')
    )

    reservation_received_content = schema.Text(
        title=_(u'Email Text for Received Reservations'),
        description=reservations_template_variables,
        default=templates['reservation_received'].get_body('en')
    )

    reservation_approved_subject = schema.TextLine(
        title=_(u'Email Subject for Approved Reservations'),
        description=_(u'Sent to users when a reservation is approved. '
                      u'May contain the template variables listed below.'),
        default=templates['reservation_approved'].get_subject('en')
    )

    reservation_approved_content = schema.Text(
        title=_(u'Email Text for Approved Reservations'),
        description=template_variables,
        default=templates['reservation_approved'].get_body('en')
    )

    reservation_denied_subject = schema.TextLine(
        title=_(u'Email Subject for Denied Reservations'),
        description=_(u'Sent to users when a reservation is denied. '
                      u'May contain the template variables listed below.'),
        default=templates['reservation_denied'].get_subject('en')
    )

    reservation_denied_content = schema.Text(
        title=_(u'Email Text for Denied Reservations'),
        description=template_variables,
        default=templates['reservation_denied'].get_body('en')
    )

    reservation_revoked_subject = schema.TextLine(
        title=_(u'Email Subject for Revoked Reservations'),
        description=_(u'Sent to users when a reservation is revoked. '
                      u'May contain the template variables listed below.'),
        default=templates['reservation_revoked'].get_subject('en')
    )

    reservation_revoked_content = schema.Text(
        title=_(u'Email Text for Revoked Reservations'),
        description=template_revoke_variables,
        default=templates['reservation_revoked'].get_body('en')
    )

    reservation_time_changed_subject = schema.TextLine(
        title=_(u'Email Subject for Changed Reservations'),
        description=_(u'Sent to users when the time of a reservation '
                      u'is changed. May contain the template variables '
                      u'listed below.'),
        default=templates['reservation_time_changed'].get_subject('en')
    )

    reservation_time_changed_content = schema.Text(
        title=_(u'Email Text for Changed Reservations'),
        description=template_time_changed_variables,
        default=templates['reservation_time_changed'].get_body('en')
    )

    @invariant
    def validate_templates(email):
        # go through the *_content attributes
        content_attributes = (
            (k, v) for k, v in IEmailTemplate._v_attrs.items()
            if k.endswith('_content')
        )

        # gather all the %(xxx)s tags
        form_tags = re.compile(r'%\(([a-z_]+)\)')

        # try to fill those with dummy variables
        for key, attr in content_attributes:
            tags = form_tags.findall(attr.getDoc())
            test_data = zip(tags, (str(i) for i in range(0, len(tags))))

            try:
                getattr(email, key) % dict(test_data)

            # if anything fails, it would also in the email sending process
            # which is the last thing we want to fail
            except KeyError as e:
                raise Invalid(
                    _(
                        u"Invalid template variable '${name}' in '${field}'",
                        mapping={
                            'name': e.message,
                            'field': attr.title
                        }
                    )
                )

def get_default_language(adapter):
    return utils.get_current_site_language()

DefaultLanguage = widget.ComputedWidgetAttribute(
    get_default_language, field=IEmailTemplate['language']
)

class IReservation(Interface):
    """ A reservation of an allocation (may be pending or approved). """

    id = schema.Int(
        title=_(u'Id'),
        default=-1,
        required=False
    )

    day = schema.Date(
        title=_(u'Day'),
        required=False
    )

    start_time = schema.Time(
        title=_(u'Start'),
        required=False
    )

    end_time = schema.Time(
        title=_(u'End'),
        required=False
    )

    quota = schema.Int(
        title=_(u'Number of Reservations'),
        required=False,
        default=1
    )

    email = Email(
        title=_(u'Email'),
        required=True
    )

class IReservationTargetForm(Interface):
    """ Describes a form with a hidden reservation-token and an optional
    reservation-id field.
    """

    token = schema.Text(
        title=_(u'Token'),
        required=False
    )

    id = schema.Text(
        title=_(u'Id'),
        required=False,
        default=None
    )

class IReservationTargetEmailForm(IReservationTargetForm):

    email = Email(
        title=_(u'Email'),
        required=True
    )

class IReservationEditTimeForm(IReservationTargetForm):

    start_time = schema.Time(
        title=_(u'Start'),
        required=True
    )

    end_time = schema.Time(
        title=_(u'End'),
        required=True
    )

    send_email = schema.Bool(
        title=_(u"Send Email"),
        description=_(
            u"Send an email to the reservee informing him of the change"
        ),
        default=True
    )

    reason = schema.Text(
        title=_(u'Reason'),
        description=_(
            u"Optional reason for the change. Sent to the reservee. "
            u"e.g. 'Your reservation has to be adjusted because the meeting "
            "room has been flooded.'"
        ),
        required=False
    )

class IGroupReservation(Interface):
    """ A reservation of an allocation group. """

    group = schema.Text(
        title=_(u'Recurrence'),
        required=False
    )

    quota = schema.Int(
        title=_(u'Number of Reservations'),
        required=False,
        default=1
    )

    email = Email(
        title=_(u'Email'),
        required=True
    )

class ISelectionReservation(Interface):
    """ A reservation of a selected number of allocations. """

    # hidden
    ids = schema.TextLine(
        title=_(u'Ids'),
        required=False
    )

    start_time = schema.Time(
        title=_(u'Start'),
        required=False
    )

    end_time = schema.Time(
        title=_(u'End'),
        required=False
    )

    quota = schema.Int(
        title=_(u'Number of Reservations'),
        required=False,
        default=1
    )

    email = Email(
        title=_(u'Email'),
        required=True
    )

class IRevokeReservation(IReservationTargetForm):
    """ For the reservation revocation form. """

    send_email = schema.Bool(
        title=_(u"Send Email"),
        description=_(
            u"Send an email to the reservee informing him of the revocation"
        ),
        default=True
    )

    reason = schema.Text(
        title=_(u'Reason'),
        description=_(
            u"Optional reason for the revocation. Sent to the reservee. "
            u"e.g. 'Your reservation has to be cancelled because the lecturer "
            u"is ill'."
        ),
        required=False
    )

class IResourceViewedEvent(Interface):
    """ Event triggered when a seantis.reservation resource is viewed. Pretty
    useful if you need a hook which is guaranteed to be triggered on a plone
    site where seantis.reservation is active.

    """

    context = Attribute("The IResourceBase context object")

class IReservationsBaseEvent(Interface):
    """ Base Interface for reservation events (not actually fired). """

    reservations = Attribute(
        "The reservation records associated with the event"
    )
    language = Attribute(
        "The language of the site or current request"
    )

class IReservationsApprovedEvent(IReservationsBaseEvent):
    """ Event triggered when a reservation is approved. """

class IReservationsDeniedEvent(IReservationsBaseEvent):
    """ Event triggered when a reservation is denied. """

class IReservationsRevokedEvent(IReservationsBaseEvent):
    """ Event triggered when a reservation is revoked. """

    reason = Attribute("""
        Optional reason for the revocation given by manager. The reason is
        given in the language of the one writing it as the language of the
        reservee is unknown at this point. In the future we might have to
        store said language on the reservation.
    """)

class IReservationsConfirmedEvent(Interface):
    """ Event triggered when the user confirms a list of reservations
    (i.e. submits them).

    Note how this is not a IReservationBaseEvent because it contains
    _multiple_ reservations, not just one.

    """
    reservations = Attribute("The list of reservations the user confirmed")
    language = Attribute("language of the site or current request")

class IReservationTimeChangedEvent(Interface):
    """ Event triggered when a reservation's start/end time is changed. See
    seantis.reservation.db.Scheduler.change_reservation_time.

    """
    reservation = Attribute("The reservation after the change")
    old_time = Attribute("A tuple of start/end representing the old time")
    new_time = Attribute("A tuple of start/end representing the new time")
    send_email = Attribute("True if the reservee should be informed")
    reason = Attribute("Optional reason for the change")


from django.shortcuts import render ,get_object_or_404
from django.http import HttpResponse ,HttpResponseRedirect
from .models import Citie,Categorie,Area,Offer,Bathroom,Bedroom,Property,Mail
from .forms import SearchForm , ContactForm ,SubscribeForm
from django.core.mail import send_mail
from django.contrib.auth.decorators import login_required
from cart.cart import Cart

def properties(request):
    properties=Property.objects.all
    a=""
    b=""
    c=0
    d=0
    e=""
    context={'properties':properties}
    if request.method=='POST':
        form=SearchForm(request.POST)
        if form.is_valid():
            a=str(form.cleaned_data['City'])
            b=str(form.cleaned_data['Categorie'])
            c=str(form.cleaned_data['Bathrooms'])
            d=str(form.cleaned_data['Bedrooms'])
            e=str(form.cleaned_data['Area'])
            context={'properties':properties,'form':form,'a':a,'b':b,'c':c,'d':d,'e':e}
    else:
        form=SearchForm()
    return render(request,'dealer/properties.html',context)

def home(request):
    properties=Property.objects.all
    return render(request,'dealer/index.html',{'properties':properties})

def gallery(request):
   photos = Photo.objects.all()
   return render(request, 'gallery.html', {'photos': photos})

def contact(request):
    properties=Property.objects.all
    context={'properties':properties}
    subject="Hello"
    if request.method=="POST":
        form=ContactForm(request.POST)
        if form.is_valid():
            subject = form.cleaned_data['subject']
            message = form.cleaned_data['message']
            sender = 'hassanbaras5@gmail.com'
            recipients = [form.cleaned_data['sender']]
            fail_silently=False
            send_mail(subject, message, sender, recipients, fail_silently)
            context={'properties':properties,'form':form,'subject':subject}
    else:
        form=ContactForm()
    return render(request,'dealer/contact.html',context)

def aboutus(request):
    properties=Property.objects.all
    return render(request,'dealer/about.html',{'properties':properties})

def news(request):
    properties=Property.objects.all
    return render(request,'dealer/news.html',{'properties':properties})

def lahore(request):
    properties=Property.objects.all
    return render(request,'dealer/lahore.html',{'properties':properties})

def karachi(request):
    properties=Property.objects.all
    return render(request,'dealer/karachi.html',{'properties':properties})

def islamabad(request):
    properties=Property.objects.all
    return render(request,'dealer/islamabad.html',{'properties':properties})

def detail(request,property_id):
    property_detail=get_object_or_404(Property,pk=property_id)
    return render(request,'dealer/property.html',{'property_detail':property_detail})

def cart(request):
    properties=Property.objects.all
    return render(request,'dealer/cart.html',{'properties':properties})

def login(request):
    properties=Property.objects.all
    return render(request,'dealer/login.html',{'properties':properties})

@login_required(login_url="/accounts/login")
def cart_add(request, id):
    cart = Cart(request)
    product = Property.objects.get(id=id)
    cart.add(product=product)
    return HttpResponseRedirect("/")

@login_required(login_url="/accounts/login")
def item_clear(request, id):
    cart = Cart(request)
    product = Property.objects.get(id=id)
    cart.remove(product)
    return redirect("cart")

@login_required(login_url="/accounts/login")
def item_increment(request, id):
    cart = Cart(request)
    product = Property.objects.get(id=id)
    cart.add(product=product)
    return redirect("cart")

@login_required(login_url="/accounts/login")
def item_decrement(request, id):
    cart = Cart(request)
    product = Property.objects.get(id=id)
    cart.decrement(product=product)
    return redirect("cart")

@login_required(login_url="/accounts/login")
def cart_clear(request):
    cart = Cart(request)
    cart.clear()
    return redirect("cart")

@login_required(login_url="/accounts/login")
def cart(request):
    properties=Property.objects.all
    return render(request, 'dealer/cart.html',{'properties':properties})


import torch

import numpy as np
import torch.nn.functional as F

from geoopt import linalg

class SPDSW:
    """
        Class for computing SPDSW distance and embedding

        Parameters
        ----------
        shape_X : int
            dim projections
        num_projections : int
            Number of projections
        num_ts : int
            Number of timestamps for quantiles, default 20
        device : str
            Device for computations, default None
        dtype : type
            Data type, default torch.float
        random_state : int
            Seed, default 123456
        sampling : str
            Sampling type
                - "spdsw": symetric matrices + geodesic projection
                - "logsw": unit norm matrices + geodesic projection
                - "sw": unit norm matrices + euclidean projection
            Default "spdsw"
        """

    def __init__(
        self,
        shape_X,
        num_projections,
        num_ts=20,
        device=None,
        dtype=torch.float,
        random_state=123456,
        sampling="spdsw",
    ):

        if device is None:
            device = "cuda" if torch.cuda.is_available() else "cpu"

        if sampling not in ["spdsw", "logsw", "sw", "aispdsw"]:
            raise Exception(
                "'sampling' should be in ['spdsw', 'logsw', 'sw', 'aispdsw']"
            )

        self.generate_projections(
            shape_X, num_projections, num_ts,
            device, dtype, random_state, sampling
        )

        self.sampling = sampling

    def generate_projections(self, shape_X, num_projections, num_ts,
                             device, dtype, random_state, sampling):
        """
        Generate projections for sampling

        Parameters
        ----------
        shape_X : int
            dim projections
        num_projections : int
            Number of projections
        device : str
            Device for computations
        dtype : type
            Data type
        random_state : int
            Seed
        sampling : str
            Sampling type
                - "spdsw": symetric matrices + geodesic projection
                - "logsw": unit norm matrices + geodesic projection
                - "sw": unit norm matrices + euclidean projection
        """

        rng = np.random.default_rng(random_state)

        if sampling == "spdsw":

            # Random projection directions, shape (d-1, num_projections)
            theta = rng.normal(size=(num_projections, shape_X))
            theta = F.normalize(
                torch.from_numpy(theta), p=2, dim=-1
            ).type(dtype).to(device)

            D = theta[:, None] * torch.eye(
                theta.shape[-1],
                device=device,
                dtype=dtype
            )

            # Random orthogonal matrices
            Z = rng.normal(size=(num_projections, shape_X, shape_X))
            Z = torch.tensor(
                Z,
                dtype=dtype,
                device=device
            )
            Q, R = torch.linalg.qr(Z)
            lambd = torch.diagonal(R, dim1=-2, dim2=-1)
            lambd = lambd / torch.abs(lambd)
            P = lambd[:, None] * Q

            self.A = torch.matmul(
                P,
                torch.matmul(D, torch.transpose(P, -2, -1))
            )

        elif sampling in ["logsw", "sw"]:

            self.A = torch.tensor(
                rng.normal(size=(num_projections, shape_X, shape_X)),
                dtype=dtype,
                device=device
            )

            self.A /= torch.norm(self.A, dim=(1, 2), keepdim=True)

        elif sampling == "aispdsw":
            # Random projection directions, shape (d-1, num_projections)
            theta = rng.normal(size=(num_projections, shape_X))
            theta = F.normalize(
                torch.from_numpy(theta), p=2, dim=-1
            ).type(dtype).to(device)
            theta_sorted, sorter = torch.sort(theta, descending=False)

            perm_matrix = F.one_hot(sorter).type(dtype)
            D_sorted = theta_sorted[:, None] * torch.eye(
                theta.shape[-1],
                dtype=dtype,
                device=device
            )

            # Random orthogonal matrices
            Z = rng.normal(size=(num_projections, shape_X, shape_X))
            Z = torch.tensor(
                Z,
                dtype=dtype,
                device=device
            )
            Q, R = torch.linalg.qr(Z)
            lambd = torch.diagonal(R, dim1=-2, dim2=-1)
            lambd = lambd / torch.abs(lambd)
            P = lambd[:, None] * Q

            self.P = torch.matmul(P, torch.transpose(perm_matrix, -2, -1))
            self.A = D_sorted

        self.ts = torch.linspace(0, 1, num_ts, dtype=dtype, device=device)

    def emd1D(self, u_values, v_values, u_weights=None, v_weights=None, p=1):
        n = u_values.shape[-1]
        m = v_values.shape[-1]

        device = u_values.device
        dtype = u_values.dtype

        if u_weights is None:
            u_weights = torch.full((n,), 1/n, dtype=dtype, device=device)

        if v_weights is None:
            v_weights = torch.full((m,), 1/m, dtype=dtype, device=device)

        # Sort
        u_values, u_sorter = torch.sort(u_values, -1)
        v_values, v_sorter = torch.sort(v_values, -1)

        u_weights = u_weights[..., u_sorter]
        v_weights = v_weights[..., v_sorter]

        # Compute CDF
        u_cdf = torch.cumsum(u_weights, -1)
        v_cdf = torch.cumsum(v_weights, -1)

        cdf_axis, _ = torch.sort(torch.cat((u_cdf, v_cdf), -1), -1)

        u_index = torch.searchsorted(u_cdf, cdf_axis)
        v_index = torch.searchsorted(v_cdf, cdf_axis)

        u_icdf = torch.gather(u_values, -1, u_index.clip(0, n-1))
        v_icdf = torch.gather(v_values, -1, v_index.clip(0, m-1))

        cdf_axis = torch.nn.functional.pad(cdf_axis, (1, 0))
        delta = cdf_axis[..., 1:] - cdf_axis[..., :-1]

        if p == 1:
            return torch.sum(delta * torch.abs(u_icdf - v_icdf), axis=-1)
        if p == 2:
            return torch.sum(delta * torch.square(u_icdf - v_icdf), axis=-1)

        return torch.sum(
            delta * torch.pow(torch.abs(u_icdf - v_icdf), p),
            axis=-1
        )

    def spdsw(self, Xs, Xt, u_weights=None, v_weights=None, p=2):
        """
            Parameters:
            Xs: ndarray, shape (n_batch, d, d)
                Samples in the source domain
            Xt: ndarray, shape (m_batch, d, d)
                Samples in the target domain
            device: str
            p: float
                Power of SW. Need to be >= 1.
        """
        n, _, _ = Xs.shape
        m, _, _ = Xt.shape

        n_proj, d, _ = self.A.shape

        if self.sampling in ["spdsw", "logsw"]:
            # Busemann Coordinates
            log_Xs = linalg.sym_logm(Xs)
            log_Xt = linalg.sym_logm(Xt)

            prod_Xs = (self.A[None] * log_Xs[:, None]).reshape(n, n_proj, -1)
            prod_Xt = (self.A[None] * log_Xt[:, None]).reshape(m, n_proj, -1)

        elif self.sampling in ["sw"]:
            # Euclidean Coordinates
            prod_Xs = (self.A[None] * Xs[:, None]).reshape(n, n_proj, -1)
            prod_Xt = (self.A[None] * Xt[:, None]).reshape(m, n_proj, -1)

        elif self.sampling in ["aispdsw"]:
            Xs2 = torch.matmul(
                torch.matmul(
                    torch.transpose(self.P, -2, -1)[:, None],
                    Xs[None]
                ),
                self.P[:, None]
            )
            Xt2 = torch.matmul(
                torch.matmul(
                    torch.transpose(self.P, -2, -1)[:, None],
                    Xt[None]
                ),
                self.P[:, None]
            )

            LD, pivots = torch.linalg.ldl_factor(Xs2)
            P, L, D_Xs = torch.lu_unpack(LD, pivots)

            LD, pivots = torch.linalg.ldl_factor(Xt2)
            P, L, D_Xt = torch.lu_unpack(LD, pivots)

            log_Xs = torch.transpose(linalg.sym_logm(D_Xs), 0, 1)
            log_Xt = torch.transpose(linalg.sym_logm(D_Xt), 0, 1)

            prod_Xs = (self.A[None]*log_Xs).reshape(n, n_proj, -1)
            prod_Xt = (self.A[None]*log_Xt).reshape(m, n_proj, -1)

        Xps = prod_Xs.sum(-1)
        Xpt = prod_Xt.sum(-1)

        return torch.mean(
            self.emd1D(Xps.T, Xpt.T, u_weights, v_weights, p)
        )

    def get_quantiles(self, x, ts, weights=None):
        """
            Inputs:
            - x: 1D values, size: n_projs * n_batch
            - ts: points at which to evaluate the quantile
        """
        n_projs, n_batch = x.shape

        if weights is None:
            X_weights = torch.full(
                (n_batch,), 1/n_batch, dtype=x.dtype, device=x.device
            )
            X_values, X_sorter = torch.sort(x, -1)
            X_weights = X_weights[..., X_sorter]

        X_cdf = torch.cumsum(X_weights, -1)

        X_index = torch.searchsorted(X_cdf, ts.repeat(n_projs, 1))
        X_icdf = torch.gather(X_values, -1, X_index.clip(0, n_batch-1))

        return X_icdf

    def get_features(self, x, weights=None, p=2):
        """
            Inputs:
            - x: ndarray, shape (n_batch, d, d)
                Samples of SPD
            - weights: weight of each sample, if None, uniform weights
            - p
        """
        num_unifs = len(self.ts)
        n_proj, d, _ = self.A.shape
        n, _, _ = x.shape

        if self.sampling in ["spdsw", "logsw"]:
            log_x = linalg.sym_logm(x)
            Xp = (self.A[None] * log_x[:, None]).reshape(n, n_proj, -1).sum(-1)
        elif self.sampling == "sw":
            Xp = (self.A[None] * x[:, None]).reshape(n, n_proj, -1).sum(-1)
        elif self.sampling == "aispdsw":
            x2 = torch.matmul(
                torch.matmul(
                    torch.transpose(self.P, -2, -1)[:, None],
                    x[None]
                ),
                self.P[:, None]
            )
            LD, pivots = torch.linalg.ldl_factor(x2)
            P, L, D_x = torch.lu_unpack(LD, pivots)
            log_x = torch.transpose(linalg.sym_logm(D_x), 0, 1)
            Xp = (self.A[None]*log_x).reshape(n, n_proj, -1).sum(-1)

        q_Xp = self.get_quantiles(Xp.T, self.ts, weights)

        return q_Xp / ((n_proj * num_unifs) ** (1 / p))


import numpy as np
from keras.preprocessing import sequence
from sklearn.preprocessing import LabelEncoder

def preprocess_dataset(dataset, w2v_model):
    x = np.array([[w2v_model.word2idx(token) for token in row[0][::-1]] for row in dataset])
    x = sequence.pad_sequences(x, maxlen=99, value=-1)
    x = sequence.pad_sequences(x, maxlen=100, value=-1)

    label_encoder = LabelEncoder()
    label_encoder.fit(['O', 'B', 'I'])

    y = [label_encoder.transform(row[1]) for row in dataset]
    y = sequence.pad_sequences(y, maxlen=100, padding='post', truncating='post', value=-1)
    y = np.array([np.eye(4)[elem] for elem in y])

    return x, y, label_encoder

def reverse_preprocessing_y(y, label_encoder):
    y_iob = [[label_encoder.inverse_transform(np.where(token == 1)[0][0]) for token in row
              if np.where(token == 1)[0][0] != 3] for row in y]

    return iob_2_conditions(y_iob)

def iob_2_conditions(y_iob):
    y_indexes = []
    for row in y_iob:
        conds = []
        cond = []
        for index, elem in enumerate(row):
            if elem == 'B':
                if len(cond) > 0:
                    conds.append(cond)
                cond = [index + 1]
            elif elem == 'I':
                cond.append(index + 1)
            else:
                if len(cond) > 0:
                    conds.append(cond)
                cond = []
        y_indexes.append(conds)
    return y_indexes


import xlrd
import xlwt
import pysnooper
import datetime
import numpy

@pysnooper.snoop()
def re_order(fil_name):
    """
    Get the input excel file information
    """
    excel_rd = xlrd.open_workbook(fil_name)
    excel_tb = excel_rd.sheet_by_index(0)
    nrows = excel_tb.nrows  # Get the number of origin rows
    ncols = excel_tb.ncols  # Get the number of origin cols

    """
    Create the new excel for output
    """
    excel_wt = xlwt.Workbook()
    table_wt = excel_wt.add_sheet('first', cell_overwrite_ok=True)

    num = int(nrows / 2) # Get the middle rows
    while(1):
        test_data = excel_tb.col(3)[num].value

        """
        Checking the middle
        Ensure it's empty
        """
        if test_data is not '':
            num -= 1
        else:
            mark_num = num + 1
            break

    """
    Traversing the origin excel file util the middle row
    """
    for i_row in range(nrows):
        for i_col in range(ncols):
            if i_row < mark_num:
                table_wt.write(i_row, i_col, excel_tb.row(i_row)[i_col].value)
            else:   # When Traver to the middle row change to the second
                table_wt.write(i_row - mark_num, i_col+5, excel_tb.row(i_row)[i_col].value)

    today = datetime.date.today()
    now = today.strftime('%m%d')
    name = "{0}.xls".format(now)
    excel_wt.save(name)

    return name

if __name__ == '__main__':
    re_order('0517.xls')