# Librerias
import numpy as nump
import pandas as pand
import seaborn as seans
import re
from sys import exit
from matplotlib import pyplot as plot
from matplotlib import style
from sklearn import linear_model
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC, LinearSVC
from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV, cross_val_score
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_score, recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import roc_curve
from sklearn.metrics  import roc_auc_score

#Recogemos los ficheros
test_df = pand.read_csv("PracticaIndividual/test.csv")
train_df = pand.read_csv("PracticaIndividual/train.csv")

#Mostramos la información
#train_df.info()

#Describe las variables
#print(train_df.describe())

#Describe las variables
#print(train_df.head(20))

#Se realiza la suma y se ordenan los valores de forma descendente cuando son "Null"
total = train_df.isnull().sum().sort_values(ascending=False)

#Sacamos los porcentajes
percent_1 = train_df.isnull().sum()/train_df.isnull().count()*100
#redondeamos el porcentaje que vamos a mostrar
percent_2 = (round(percent_1, 1)).sort_values(ascending=False)

#mostramos los valores que tienen campos con tipo Null en dos  columnas(La suma de Null por columna y % sobre el global de filas)
missing_data = pand.concat([total, percent_2], axis=1, keys=['Total', '%'])

#Muestra la suma de valores NULL y el porcentaje sobre el Total
#print(missing_data.head(11))

#nos muestra todas las cabeceras del fichero
#print(train_df.columns.values)

#dataNew = [train_df, test_df]
dataNew =  pand.concat(objs=[train_df, test_df], axis=0).reset_index(drop=True)

#Cambiar los valores de Sexo a Int
sex = {"male": 3, "female": 0}
data = [train_df, test_df]

for dataset in data:
    dataset['Sex'] = dataset['Sex'].map(sex)

#Agregamos al DataSet el sexo por la clase del pasajero para diferenciarlos

data = [train_df, test_df]
for dataset in data:
    dataset['Sex_Class']= dataset['Sex']+ dataset['Pclass']

#print(dataset['Sex_Class'].describe())

#MOSTRAR LAS MEDIAS AGRUPANDO POR EL GRUPO SEXCLASS
#print(dataset.groupby('Sex_Class').mean())

#Mostrar la relación entre la Edad y el Sexo
#AS = seans.factorplot(y="Age", x="Sex_Class", data = dataset, kind="box")
#PA = seans.factorplot(data = dataNew , x = 'Sex_Class' , y = 'Age', kind = 'box')

#Relación entre Pclass y edad
'''
facet = seans.FacetGrid(dataNew, hue="Sex_Class", aspect=4)
facet.map(seans.kdeplot,'Age',shade= True)
facet.set(xlim=(0, train_df['Age'].max()))
facet.add_legend()
plot.show()
'''

#Corrección v2 de la EDAD

def AgeImpute(df):
    Age = df[0]
    Sex_Class = df[1]

    if pand.isnull(Age):
        if Sex_Class == 1: return 41
        elif Sex_Class == 2: return 24
        elif Sex_Class == 3: return 23
        elif Sex_Class == 4: return 40
        elif Sex_Class == 5: return 30
        else: return 24
    else:
        return Age

# Edad corregida
train_df['Age'] = train_df[['Age' , 'Sex_Class']].apply(AgeImpute, axis = 1)
test_df['Age'] = test_df[['Age' , 'Sex_Class']].apply(AgeImpute, axis = 1)

#Trabajaremos ahora para sustituir los valores Null de la variable EDAD (V1)
'''
data = [train_df, test_df]

for dataset in data:
    mean = train_df["Age"].mean()
    std = test_df["Age"].std()
    is_null = dataset["Age"].isnull().sum()
    # calcula números aleatorios entre la media, std y is_null
    rand_age = nump.random.randint(mean - std, mean + std, size = is_null)
    # llena los valores de NaN en la columna de Edad con los valores aleatorios generados
    age_slice = dataset["Age"].copy()
    age_slice[nump.isnan(age_slice)] = rand_age
    dataset["Age"] = age_slice
    dataset["Age"] = train_df["Age"].astype(int)
print(train_df["Age"].isnull().sum())
'''
print(train_df.info())
print(test_df.info())

#Trabajaremos ahora para sustituir los valores Null de la variable Embarked
#print(train_df['Embarked'].describe())
common_value = 'S'
data = [train_df, test_df]

for dataset in data:
    dataset['Embarked'] = dataset['Embarked'].fillna(common_value)

#Nos deshacemos de cabina y lo volvemos un valor numerico(Cubierta-Deck) a partir de Primera letra del campo Cabin
deck = {"A": 1, "B": 2, "C": 3, "D": 4, "E": 5, "F": 6, "G": 7, "U": 8}
data = [train_df, test_df]

for dataset in data:
    dataset['Cabin'] = dataset['Cabin'].fillna("U0")
    dataset['Deck'] = dataset['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group())
    dataset['Deck'] = dataset['Deck'].map(deck)
    dataset['Deck'] = dataset['Deck'].fillna(0)
    dataset['Deck'] = dataset['Deck'].astype(int)

# Nos desacemos de la variable cabina al trabajar con el nuevo campo "Cubierta"
train_df = train_df.drop(['Cabin'], axis=1)
test_df = test_df.drop(['Cabin'], axis=1)

#Eliminamos el numero de pasajero solo en el fichero de entrenamiento
train_df = train_df.drop (['PassengerId'], axis = 1)

#observamos un conteo de la información del campo número de ticket
#print(train_df['Ticket'].describe())

#Eliminamos el numero de ticket
train_df = train_df.drop(['Ticket'], axis=1)
test_df = test_df.drop(['Ticket'], axis=1)

#Generaremos una suma de "familiares" en vez de trabajar por separado con ellas
#y otra variable 1,0 que nos permita saber si alguien está solo
data = [train_df, test_df]
for dataset in data:
    dataset['relatives'] = dataset['SibSp'] + dataset['Parch']
    dataset.loc[dataset['relatives'] > 0, 'not_alone'] = 0
    dataset.loc[dataset['relatives'] == 0, 'not_alone'] = 1
    dataset['not_alone'] = dataset['not_alone'].astype(int)
train_df['not_alone'].value_counts()

#Convertimos la tarifa pagada en un numero entero
data = [train_df, test_df]

for dataset in data:
    dataset['Fare'] = dataset['Fare'].fillna(0)
    dataset['Fare'] = dataset['Fare'].astype(int)

#Convertimos la variable de sexto en un valor numerico
sex = {3: 0, 0: 1}
data = [train_df, test_df]

for dataset in data:
    dataset['Sex'] = dataset['Sex'].map(sex)

#Convertimos la variable de sexto en un valor numerico
data = [train_df, test_df]
abrev = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}

for dataset in data:
    # Exportar titulos
    dataset['Title'] = dataset.Name.str.extract(' ([A-Za-z]+)\.', expand=False)
    # Los titulos más comunes los unificamos en un grupo númerico
    dataset['Title'] = dataset['Title'].replace(['Lady', 'Countess','Capt', 'Col','Don', 'Dr',\
                                            'Major', 'Rev', 'Sir', 'Jonkheer', 'Dona'], 'Rare')
    dataset['Title'] = dataset['Title'].replace('Mlle', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Ms', 'Miss')
    dataset['Title'] = dataset['Title'].replace('Mme', 'Mrs')
    # Convertir a valor numérico
    dataset['Title'] = dataset['Title'].map(abrev)
    # Los que no tengan ningún titulo recogen el valor 0
    dataset['Title'] = dataset['Title'].fillna(0)
train_df = train_df.drop(['Name'], axis=1)
test_df = test_df.drop(['Name'], axis=1)

#Convertimos la puerta de embarque en un número entero
ports = {"S": 0, "C": 1, "Q": 2}
data = [train_df, test_df]

for dataset in data:
    dataset['Embarked'] = dataset['Embarked'].map(ports)

#Convertimos a Int la edad y hacemos grupos de edad de un tamaño similar
data = [train_df, test_df]
total = train_df.isnull().sum().sort_values(ascending=False)
print(test_df.info())
print(total)
test_df.head()

for dataset in data:
    dataset['Age'] = dataset['Age'].astype(int)
    dataset.loc[ dataset['Age'] <= 16, 'Age'] = 0
    dataset.loc[(dataset['Age'] > 16) & (dataset['Age'] <= 20), 'Age'] = 1
    dataset.loc[(dataset['Age'] > 20) & (dataset['Age'] <= 24), 'Age'] = 2
    dataset.loc[(dataset['Age'] > 24) & (dataset['Age'] <= 28), 'Age'] = 3
    dataset.loc[(dataset['Age'] > 28) & (dataset['Age'] <= 32), 'Age'] = 4
    dataset.loc[(dataset['Age'] > 32) & (dataset['Age'] <= 37), 'Age'] = 5
    dataset.loc[(dataset['Age'] > 37) & (dataset['Age'] <= 45), 'Age'] = 6
    dataset.loc[ dataset['Age'] > 45, 'Age'] = 7

#contamos los grupos de edad según franjas de edad de un rango total(101 a 122)
#print(train_df['Age'].value_counts())

#Buscamos que nos ayude la funcion qcut a formar lo grupos aproximados
#print(pand.qcut(train_df['Fare'], q=4))

#Agrupamos el precio que han pagado por el ticket cada persona
data = [train_df, test_df]

for dataset in data:
    dataset.loc[ dataset['Fare'] <= 7.91, 'Fare'] = 0
    dataset.loc[(dataset['Fare'] > 7.91) & (dataset['Fare'] <= 14.454), 'Fare'] = 1
    dataset.loc[(dataset['Fare'] > 14.454) & (dataset['Fare'] <= 31), 'Fare']   = 2
    dataset.loc[ dataset['Fare'] > 31, 'Fare'] = 3
    dataset['Fare'] = dataset['Fare'].astype(int)

#print(train_df['Fare'].value_counts())

#Agregamos al DataSet la edad por la clase del pasajero para diferenciarlos
data = [train_df, test_df]
for dataset in data:
    dataset['Age_Class']= dataset['Age']* dataset['Pclass']

#Generemos otro subgrupo en el DataSet que contenga el precio que paga cada persona
for dataset in data:
    dataset['Fare_Per_Person'] = dataset['Fare']/(dataset['relatives']+1)
    dataset['Fare_Per_Person'] = dataset['Fare_Per_Person'].astype(int)

#Mostrar la info tratada
#print(train_df.head(20))
#train_df.info()

#####VISUALIZACIÓN PARA ANÁLISIS DE DATOS#####

#visualización de datos con la libreria Seaborn
#print(seans.barplot(x='Pclass', y='Survived', data=train_df))

#Visualización relación clase y grupo de edad
#grid = seans.FacetGrid(train_df, col='Survived', row='Pclass', size=2.2, aspect=1.6)
#grid.map(plot.hist, 'Age', alpha=.5, bins=20)
#grid.add_legend();

#Mostramos los datos de los supervivientes por sexo
'''
survived = 'survived'
not_survived = 'not survived'
fig, axes = plot.subplots(nrows=1, ncols=2,figsize=(10, 4))
women = train_df[train_df['Sex']==0]
men = train_df[train_df['Sex']==1]
ax = seans.distplot(women[women['Survived']==1].Age.dropna(), bins=18, label = survived, ax = axes[0], kde =False)
ax = seans.distplot(women[women['Survived']==0].Age.dropna(), bins=40, label = not_survived, ax = axes[0], kde =False)
ax.legend()
ax.set_title('Female')
ax = seans.distplot(men[men['Survived']==1].Age.dropna(), bins=18, label = survived, ax = axes[1], kde = False)
ax = seans.distplot(men[men['Survived']==0].Age.dropna(), bins=40, label = not_survived, ax = axes[1], kde = False)
ax.legend()
_ = ax.set_title('Male')
'''

#Mostramos visualmente los datos de superviviencia embarcando en cada puerto
'''
FacetGrid = seans.FacetGrid(train_df, row='Embarked', size=4.5, aspect=1.6)
FacetGrid.map(seans.pointplot, 'Pclass', 'Survived', 'Sex', palette=None,  order=None, hue_order=None )
FacetGrid.add_legend()
'''

#Comprobamos la correlación entre el número de familiares
#axes = seans.factorplot('relatives','Survived',data=train_df, aspect = 2.5, )

#Mostrar los nulos y otra información sobre el DATASET Tratado
'''
print('Datos despues de tratarlos:')
print(pand.isnull(train_df).sum())
print(pand.isnull(test_df).sum())
print(train_df.shape)
print(test_df.shape)
print(test_df.head())
print(train_df.head())
'''

####BORRAMOS ATRIBUTOS PARA MEJORAR NUESTRO MODELO#####
# Estos atributos tiene poca importancia en la probabilidad de supervivencia
train_df  = train_df.drop("not_alone", axis=1)
test_df  = test_df.drop("not_alone", axis=1)
train_df  = train_df.drop("Parch", axis=1)
test_df  = test_df.drop("Parch", axis=1)

##### APLICACIÓN ALGORITMOS Y ENTRENAMIENTO #####

#Separamos la columna superviviente en otra matriz de datos y la de test sin el ID de Pasajero
X_train = train_df.drop("Survived", axis=1)
Y_train = train_df["Survived"]
X_test  = test_df.drop("PassengerId", axis=1).copy()

#Información de las variables
#print(train_df.info())
#print(test_df.info())

#Algoritmo Stochastic Gradient Descent (SGD)
sgd = linear_model.SGDClassifier(max_iter=5, tol=None)
sgd.fit(X_train, Y_train)
Y_pred = sgd.predict(X_test)

sgd.score(X_train, Y_train)

acc_sgd = round(sgd.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Stochastic Gradient Descent (SGD):',acc_sgd)

#Algoritmo Random Forest
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)

Y_prediction = random_forest.predict(X_test)

random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Random Forest:',acc_random_forest)

#Algoritmo Regresión Logistica
logreg = LogisticRegression()
logreg.fit(X_train, Y_train)

Y_pred = logreg.predict(X_test)

acc_log = round(logreg.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Regresión Logistica:',acc_log)

#Algoritmo K Nearest Neighbor KNN
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(X_train, Y_train)
Y_pred = knn.predict(X_test)
acc_knn = round(knn.score(X_train, Y_train) * 100, 2)
#print('Algoritmo K Nearest Neighbor KNN:',acc_log)

#### Algoritmo Gaussian Naive Bayes
gaussian = GaussianNB()
gaussian.fit(X_train, Y_train)
Y_pred = gaussian.predict(X_test)
acc_gaussian = round(gaussian.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Gaussian Naive Bayes:',acc_gaussian)

#Algoritmo Perceptron
perceptron = Perceptron(max_iter=5)
perceptron.fit(X_train, Y_train)

Y_pred = perceptron.predict(X_test)

acc_perceptron = round(perceptron.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Perceptron:',acc_perceptron)

#Algoritmo Linear Support Vector Machine(Algoritmo maquinas de Soporte Lineal):
linear_svc = LinearSVC()
linear_svc.fit(X_train, Y_train)

Y_pred = linear_svc.predict(X_test)

acc_linear_svc = round(linear_svc.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Linear Support Vector Machine:',acc_linear_svc)

#Support Vector Machines (Algoritmo maquinas de Soporte Lineal)
svc = SVC()
svc.fit(X_train, Y_train)
Y_pred = svc.predict(X_test)
acc_svc = round(svc.score(X_train, Y_train) * 100, 2)
#print('Precisión Soporte de Vectores:',acc_svc)

#Algoritmo Decision Tree
decision_tree = DecisionTreeClassifier()
decision_tree.fit(X_train, Y_train)
Y_pred = decision_tree.predict(X_test)
acc_decision_tree = round(decision_tree.score(X_train, Y_train) * 100, 2)
#print('Algoritmo Decision Tree:',acc_decision_tree)

#Mostramos cual de los algoritmos es el más fiable en una matriz de datos

results = pand.DataFrame({
    'Model': ['Support Vector Machines', 'Linear Support Vector Machines', 'KNN', 'Regresión Logistica',
              'Random Forest', 'Naive Bayes', 'Perceptron',
              'Stochastic Gradient Decent',
              'Decision Tree'],
    'Score': [acc_linear_svc, acc_linear_svc, acc_knn, acc_log,
              acc_random_forest, acc_gaussian, acc_perceptron,
              acc_sgd, acc_decision_tree]})
result_df = results.sort_values(by='Score', ascending=False)
result_df = result_df.set_index('Score')
print(result_df.head(9))

#Afinar el algoritmo Random Forest porque es de los que mejor tasa de acierto tiene

rf = RandomForestClassifier(n_estimators=100)
scores = cross_val_score(rf, X_train, Y_train, cv=10, scoring = "accuracy")
#print("Scores:", scores)
#print("Mean:", scores.mean())
#print("Standard Deviation:", scores.std())

#Mostrar la importancia de cara atributo sobre la probabilidad de sobrevivir
#importances = pand.DataFrame({'feature':X_train.columns,'importance':nump.round(random_forest.feature_importances_,3)})
#importances = importances.sort_values('importance',ascending=False).set_index('feature')
#print(importances.head(15))

#Visualizar graficamente la importancia de los atributos del Dataset
#importances.plot.bar()

#####AFINAR EL MODELO#####

param_grid = { "criterion" : ["gini", "entropy"], "min_samples_leaf" : [1, 5, 10, 25, 50, 70], "min_samples_split" : [2, 4, 10, 12, 16, 18, 25, 35], "n_estimators": [100, 400, 700, 1000, 1500]}
rf = RandomForestClassifier(n_estimators=100, max_features='auto', oob_score=True, random_state=1, n_jobs=-1)
clf = GridSearchCV(estimator=rf, param_grid=param_grid, n_jobs=-1)
#clf.fit(X_train, Y_train)
#print(clf.bestparams)

#Nuevos parametros de Random Forest
random_forest = RandomForestClassifier(criterion = "gini",
                                       min_samples_leaf = 1,
                                       min_samples_split = 10,
                                       n_estimators=100,
                                       max_features='auto',
                                       oob_score=True,
                                       random_state=1,
                                       n_jobs=-1)

random_forest.fit(X_train, Y_train)
Y_prediction = random_forest.predict(X_test)

random_forest.score(X_train, Y_train)
#print("oob score:", round(random_forest.oob_score_, 4)*100, "%")

#####CALCULAR PRECICIÓN UTILIZANDO LOS MODELOS#####

#Matriz de Precisión
predictions = cross_val_predict(random_forest, X_train, Y_train, cv=3)
#print(confusion_matrix(Y_train, predictions))

#Precisión del modelo
#print("Precision:", precision_score(Y_train, predictions))
#print("Recall:",recall_score(Y_train, predictions))

#Puntuación F
print("Preción F",f1_score(Y_train, predictions))

#Visualizar curva de PRECISIÓN

y_scores = random_forest.predict_proba(X_train)
y_scores = y_scores[:,1]
'''
precision, recall, threshold = precision_recall_curve(Y_train, y_scores)
def plot_precision_and_recall(precision, recall, threshold):
    plot.plot(threshold, precision[:-1], "r-", label="precision", linewidth=5)
    plot.plot(threshold, recall[:-1], "b", label="recall", linewidth=5)
    plot.xlabel("threshold", fontsize=19)
    plot.legend(loc="upper right", fontsize=19)
    plot.ylim([0, 1])

plot.figure(figsize=(14, 7))
plot_precision_and_recall(precision, recall, threshold)
#plot.show()
'''

#Otra opción de visualizar la precisión
'''
def plot_precision_vs_recall(precision, recall):
    plot.plot(recall, precision, "g--", linewidth=2.5)
    plot.ylabel("recall", fontsize=19)
    plot.xlabel("precision", fontsize=19)
    plot.axis([0, 1.5, 0, 1.5])

plot.figure(figsize=(14, 7))
plot_precision_vs_recall(precision, recall)
plot.show()
'''

#Curva ROC AUC
#calcular la tasa de verdaderos positivos y la tasa de falsos positivos
'''
false_positive_rate, true_positive_rate, thresholds = roc_curve(Y_train, y_scores)
#plotting entre cada uno de ellos
def plot_roc_curve(false_positive_rate, true_positive_rate, label=None):
    plot.plot(false_positive_rate, true_positive_rate, linewidth=2, label=label)
    plot.plot([0, 1], [0, 1], 'r', linewidth=4)
    plot.axis([0, 1, 0, 1])
    plot.xlabel('False Positive Rate (FPR)', fontsize=16)
    plot.ylabel('True Positive Rate (TPR)', fontsize=16)

plot.figure(figsize=(14, 7))
plot_roc_curve(false_positive_rate, true_positive_rate)
plot.show()
'''

#Puntuación de ROC AUC
r_a_score = roc_auc_score (Y_train, y_scores)
print ("ROC-AUC-Score:", r_a_score)

#GENERAR EL NUEVO FICHERO DE PREDICCION

#Crear un DataFrame con las identificaciones de los pasajeros y nuestra predicción sobre si sobrevivieron o no.
submission = pand.DataFrame({'PassengerId':test_df['PassengerId'],'Survived':Y_prediction})

filename = 'PracticaIndividual/gender_submission.csv'

submission.to_csv(filename,index=False)

print('Saved file: ' + filename)

#EXPORTACIÓN DEL DATASET FINAL EN OTRO FICHERO CSV
#train_df.to_csv(r'PracticaIndividual/export_TRAIN_DEFINITIVO.csv', index = False, header=True)
#test_df.to_csv(r'PracticaIndividual/export_TEST_DEFINITIVO.csv', index = False, header=True)


#!/usr/bin/env python3

import rospy

import pyrealsense2 as rs
import numpy as np
import cv2

from modules.Trajectory import Trajectory
from modules import modern_robotics as mr
from modules.MotorController import MotorController

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

import v4_6dof.msg as msg

import sys, os

# Configure depth and color streams
pipeline = rs.pipeline()
config = rs.config()

# Get device product line for setting a supporting resolution
pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)
device = pipeline_profile.get_device()
device_product_line = str(device.get_info(rs.camera_info.product_line))
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

# Start streaming
profile = pipeline.start(config)
depth_sensor = profile.get_device().first_depth_sensor()
depth_scale = depth_sensor.get_depth_scale() # 0.0010000000474974513
max_depth = 6
max_depth_scaled = max_depth/depth_scale

# getting transf matrix from camera to robot origin
rot_camera_to_90 = mr.RollPitchYawToRot(0,0,np.pi/4)
transf_camera_to_90 = mr.RpToTrans(rot_camera_to_90, [0,0,0])
transf_90_to_base = np.array([[0, 0,1, 0.07274],\
                              [0,-1,0, 0.06474],\
                              [1, 0,0, -0.0175],\
                              [0, 0,0,       1]])
transf_camera_to_base = transf_90_to_base @ transf_camera_to_90

# initializing globals
trajectories = []
old_trajectories = []
depth_background = np.array([])
betas_depth_to_dia = np.load("/home/justin/catkin_ws/src/v4_6dof/scripts/constants/betas.npy")

mc = MotorController()
rospy.init_node('talker', anonymous=True)

# testing realsense filters comparing to mine
decimate = rs.decimation_filter(2)
hole_filling = rs.hole_filling_filter()
spatial = rs.spatial_filter()
temporal = rs.temporal_filter()

try:

    mc.anglePublish([0, -np.pi/2, np.pi/2, 0, -np.pi/2, 0], 0.4, True)

    # trying to find a ping pong ball now
    for i in range(0,50):
        depth_cleaned = np.load("frames/depth_frame_"+str(i)+".npy")
        depth_cleaned_3d = np.dstack((depth_cleaned,depth_cleaned,depth_cleaned))

        # create an canny edge picture
        # values tuned in tests/realsense/tune_cleaning
        sigma = 0.38
        v = np.median(depth_cleaned)
        lower = int(max(0, (1.0 - sigma) * v))
        upper = int(min(255, (1.0 + sigma) * v))
        depth_canny = cv2.Canny(depth_cleaned, lower, upper)
        depth_canny_3d = np.dstack((depth_canny,depth_canny,depth_canny))

        contours, hierarchy = cv2.findContours(depth_canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        # sift thru all the contours to find anything that looks like a ping pong ball
        for c in contours:
            try:
                # rectangle, not circle; slow shutter speed/motion blur elongates the circle into oval, need the shorter height
                (x,y), (width, height), angle = cv2.minAreaRect(c)
                diameter = min(width, height)
                depth = depth_frame.get_distance(int(x),int(y))
            except: continue

            # removing weird edge cases
            if x*y*diameter <= 0: continue

            # if contour area smaller than this number, it is most likely noise
            contour_area = cv2.contourArea(c)
            if (contour_area < 50): continue

            # checking area of contour to area of ellipse
            ellipse_area = np.pi*(diameter/2)*(diameter/2)
            if (contour_area/ellipse_area) < 0.5: continue

            # if depth/diameter relationship does not follow the trend in tests/realsense/depth_diameter_eq-polyfit, then continue
            calculated_diameter = betas_depth_to_dia[0] + betas_depth_to_dia[1]*depth + betas_depth_to_dia[2]*(depth*depth)
            if ((diameter-calculated_diameter)/calculated_diameter) > 0.15: continue

            # grabbing from original depth image, without the cleanup
            # if there was a way to grab from the cleaned array, I would do it
            point = rs.rs2_deproject_pixel_to_point(depth_intrin, [x,y], depth)
            if (point[0]*point[1]*point[2] == 0): continue

            # transf matrix established at the top
            point = transf_camera_to_base @ np.r_[point,1]

            # go thru all trajectories and see if this point fits in the projected path
            added = False
            for t in trajectories:
                success = t.append(current_time, point)
                if success: added = True

            # if the point was not in the projected path, then create a new trajectory
            if not added:
                trajectories.append(Trajectory(current_time, point))

            # paint circles onto canny and cleaned
            cv2.circle(depth_canny_3d, (int(x),int(y)), 3, (0,0,255), 1)
            cv2.circle(depth_cleaned_3d, (int(x),int(y)), int(diameter/2), (0,255,0),2)

        # show images
        images = np.hstack((depth_canny_3d, depth_cleaned_3d))
        cv2.namedWindow('Main', cv2.WINDOW_AUTOSIZE)
        cv2.imshow('Main', images)

        # move thru all registered trajectories
        for traj in trajectories:
            # if the trajectory is developed (5 points), perform a check to see if robot can move there
            if (traj.developed):
                reachable, intersection_point, time_until_intersection = traj.checkSphereIntersection([0,0.180212,0], 0.278515)
                if reachable:
                    print(f"point: {intersection_point} time: {time_until_intersection} reachable")
                    intersection_transf = mr.RpToTrans(np.identity(3), intersection_point)
                    mc.transfMatrixJointPublish(intersection_transf, time_until_intersection)
                    old_trajectories.append(traj)
                else:
                    print(f"point: {intersection_point} not reachable")
                trajectories.remove(traj)

            # if total time is longer than 2 seconds, kill the trajectory
            if (current_time - traj.init_time) >= 2:
                trajectories.remove(traj)

        key = cv2.waitKey(1)
        if key & 0xFF == ord('q') or key == 27:
            cv2.destroyAllWindows()
            # for t in old_trajectories:
            #     for i in range(len(t.points)):
            #         ax.scatter(t.points[i][0], t.points[i][1], t.points[i][2])
            #         plt.pause(0.01)
            # cv2.waitKey()
            break

finally:
    # Stop streaming
    pipeline.stop()


import logging
from logging import Logger, FileHandler, Formatter
from pathlib import Path
from typing import Dict, List, Sequence

import aqt.qt
from anki.notes import NoteId, Note
from aqt import mw

init_py_file: Path = Path(__file__)
addon_dir: Path = init_py_file.parent
addon_name: str = addon_dir.name

logger: Logger = logging.getLogger(addon_name)
logger.setLevel(logging.DEBUG)

log_file: Path = Path(addon_dir, addon_name + '.log')
handler: FileHandler = FileHandler(log_file)
handler.setLevel(logging.DEBUG)
handler.setFormatter(Formatter('%(asctime)s %(levelname)s %(message)s'))
logger.addHandler(handler)

V1_TEXT_FIELD = 'v1_text'
ING_TEXT_FIELD = 'ing_text'
S_TEXT_FIELD = 's_text'

def fill():
    logger.info('Start')
    file: Path = Path(addon_dir, 'verbs.csv')

    with open(file, newline='') as csv_file:
        import csv
        reader = csv.reader(csv_file, delimiter=',')
        verbs: Dict[str, List[str]] = dict()
        for row in reader:
            verbs[row[0]] = row
    logger.info("Dict Size: %d" % len(verbs))
    note_ids: Sequence[NoteId] = mw.col.find_notes('note:En-irregular-verb ing_text:')
    logger.info("Found note_ids: %d", len(note_ids))
    for note_id in note_ids:
        note: Note = mw.col.get_note(note_id)
        logger.info("Note items: %s" % note.items())
        v1_text: str = note[V1_TEXT_FIELD]
        ing_text_field: str = note[ING_TEXT_FIELD]
        if v1_text in verbs:
            verb_row = verbs[v1_text]
            if not ing_text_field:
                ing_text_target: str = verb_row[3]
                if ing_text_target:
                    note[ING_TEXT_FIELD] = ing_text_target
                    mw.col.update_note(note)
                    logger.info("Updated ING: v1='%s', ING='%s'", v1_text, ing_text_target)
                else:
                    logger.warning("Not found target ING for '%s'", v1_text)
            s_text_field: str = note[S_TEXT_FIELD]
            if not s_text_field:
                s_text_target: str = verb_row[4]
                if s_text_target:
                    note[S_TEXT_FIELD] = s_text_target
                    mw.col.update_note(note)
                    logger.info("Updated S: v1='%s', ING='%s'", v1_text, s_text_target)
                else:
                    logger.warning("Not found target S for '%s'", v1_text)
        else:
            logger.warning("Not found target row for '%s'", v1_text)
    logger.info('Done')

action = aqt.qt.QAction("Fill irregular verbs", mw)
action.triggered.connect(fill)
mw.form.menuTools.addAction(action)


from statistics import correlation
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

#  Create your models here.
class Metadatos(models.Model):
    id = models.AutoField(primary_key=True)
    iduser= models.ForeignKey(User, on_delete=models.CASCADE)
    aliasconxion = models.CharField(max_length=30)
    comentariobd =models.TextField(max_length=150)
    nomhost = models.CharField(max_length=100)
    nompuerto = models.IntegerField()
    nombd = models.CharField(max_length=80)
    usuario = models.CharField(max_length=100)
    passw = models.CharField(max_length=150)
    fechacreacion = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return "{0}-{1}".format(self.aliasconxion,self.nombd)

class schema_gr(models.Model):
    id_m = models.AutoField(primary_key=True)
    id_schema = models.ForeignKey(Metadatos, on_delete=models.CASCADE)
    image = models.ImageField(upload_to="img", max_length=None, null=True)

    def __str__(self):
        return "{0}".format(self.id_schema)


#python3

import sqlite3

#open the db
db = sqlite3.connect('china1')

# Get a cursor object
cursor = db.cursor()

#input variables to fill the db
name = input("Name: ")
province = input("Province: ")
city = input("City: ")
rank = input("Rank: ")
title = input("Title: ")

#inserts into the tabled called "members".  Looks for columns (name, provice, city).  Inserts the value associated with the variables from above.
cursor.execute("INSERT INTO members(name, province, city) VALUES(?, ?, ?)", (name, province, city))

#same thing,  just in the titles table.
cursor.execute("INSERT INTO positions(rank_indiv, title) VALUES(?, ?)", (rank, title))

#writes it to the db
db.commit()


from __future__ import annotations

from collections import namedtuple

import numpy as np

import pygame as pg
from pygame import display, event, K_d, K_ESCAPE, KMOD_CTRL, K_q, KEYDOWN, QUIT
from pygame.color import Color
from pygame.rect import Rect
from pygame.sprite import Sprite
from pygame.surface import Surface
from pygame.time import Clock

from PySimpleGUI import RGB

from typing import Set

# Global constants
RowCol = namedtuple('RowCol', 'row col')
PixelVector2 = namedtuple('PixelVector2', 'x y')

# Assumes that all Blocks are square with side BLOCK_SIDE
BLOCK_SIDE = 15
BLOCK_SPACING = BLOCK_SIDE + 1

class Block(Sprite):
    """
    A generic patch/turtle. Has a PixelVector2 but not necessarily a RowCol. Has a Color.
    """

    def __init__(self, pixel_pos: PixelVector2, color=Color('black')):
        super().__init__()
        self.color = color
        self.pixel_pos: PixelVector2 = pixel_pos
        self.rect = Rect((self.pixel_pos.x, self.pixel_pos.y), (BLOCK_SIDE, BLOCK_SIDE))
        self.image = Surface((self.rect.w, self.rect.h))
        self.image.fill(color)

    def draw(self, screen):
        screen.blit(self.image, self.rect)

class Patch(Block):
    def __init__(self, row_col: RowCol, color=Color('black')):
        super().__init__(SimEngine.WORLD.row_col_to_pixel_pos(row_col), color)
        self.row_col = row_col
        self.turtles = set()

    def neighbors(self, n=8):
        (row, col) = self.row_col
        n_4 = [(0, -1), (-1, 0), (1, 0), (0, 1)]
        n_8 = n_4 + [(-1, -1), (-1, 1), (1, -1), (1, 1)]
        rc_deltas = n_4 if n == 4 else n_8
        patch_class = type(self)
        neighbs: Set[patch_class] = set(patch_class(r, c) for (r, c) in rc_deltas
                                        if SimEngine.WORLD.in_bounds(row+r, col+c))
        return neighbs

class Turtle(Block):
    def __init__(self,
                 pixel_pos: PixelVector2 = PixelVector2(25*BLOCK_SPACING-1, 25*BLOCK_SPACING-1),
                 color=Color('red')):
        super().__init__(pixel_pos, color)
        self.vel = PixelVector2(0, 0)

    def move_turtle(self):
        pass

    def move_turtle_by_vel(self):
        self.move_turtle_dx_dy(self.vel.x, self.vel.y)

    def move_turtle_dx_dy(self, dx, dy):
        """
        Computes the turtle pixel_pos based on its current pixel_pos and its velocity.
        Then calls SIM_ENGINE.place_turtle(turtle) to place it on the screen.
        SIM_ENGINE.place_turtle() wraps around if necessary.
        Removes the turtle from its current Patch and places it in its new Patch.
        """
        current_patch: Patch = self.patch()
        current_patch.turtles.remove(self)
        self.pixel_pos = PixelVector2(self.pixel_pos.x + dx, self.pixel_pos.y + dy)
        SimEngine.SIM_ENGINE.place_turtle(self)
        new_patch: Patch = self.patch()
        new_patch.turtles.add(self)

    def patch(self) -> Patch:
        (row, col) = SimEngine.WORLD.pixel_pos_to_row_col(self.pixel_pos)
        patch = SimEngine.WORLD.patches[row, col]
        return patch

class BasicWorld:

    def __init__(self, patch_class=Patch, patches_shape=RowCol(50, 50), turtle_class=Turtle, nbr_turtles=25):
        SimEngine.WORLD = self
        self.shape = patches_shape
        self.patches = np.array([patch_class(RowCol(r, c))
                                 for r in range(self.shape.row) for c in range(self.shape.col)])
        self.patches: np.ndarray = self.patches.reshape(patches_shape)
        self.turtles: Set[turtle_class] = set(turtle_class() for _ in range(nbr_turtles))
        for turtle in self.turtles:
            turtle.patch().turtles.add(turtle)

    def clear_all(self):
        self.turtles = set()

    def draw(self, screen):
        for patch in self.patches.flat:
            patch.draw(screen)
        for turtle in self.turtles:
            turtle.draw(screen)

    def in_bounds(self, r, c):
        return 0 <= r <= self.shape.row and 0 <= c <= self.shape.col

    @staticmethod
    def pixel_pos_to_row_col(pixel_pos: PixelVector2):
        """
        Get the patch row-col for this pixel_pos
        """
        row = (pixel_pos.y - 1) // BLOCK_SPACING
        col = (pixel_pos.x - 1) // BLOCK_SPACING
        return RowCol(row, col)

    @staticmethod
    def row_col_to_pixel_pos(row_col: RowCol):
        """
        Leave a border of 1 pixel at the top and left of the patches
        """
        return PixelVector2(1+BLOCK_SPACING*row_col.row, 1+BLOCK_SPACING*row_col.col)

    def setup(self):
        pass

    def update(self):
        pass

class SimEngine:
    """
    The engine that runs the simulation.
    """
    # These are globally available as SimEngine.SIM_ENGINE and SimEngine.WORLD
    SIM_ENGINE = None  # The SimEngine object
    WORLD = None       # The world

    def __init__(self, caption="Basic Model"):

        SimEngine.SIM_ENGINE = self

        # Leave a border of 1 pixel at the top and left of the patches
        self.width = 801
        self.height = 801
        self.fps = 60

        # This is the color of the lines between the patches, implemented as the screen background color.

        # self.screen_color = Color('darkslategray')  # (47, 79, 79, 255), same as pygame.colordict.THECOLORS['...']
        # self.screen_color = Color('gray20')  # (51, 51, 51, 255), same as pygame.colordict.THECOLORS['...']
        # A compromize between 'darkslategray' and 'gray20'
        self.screen_color = Color(RGB(50, 60, 60))

        # set_mode() creates a Surface for display
        self.screen = display.set_mode((self.width, self.height))
        display.set_caption(caption)
        self.clock = Clock()
        self.screen_rect = self.screen.get_rect()

    # Fill the screen with background color, then draw blocks, then draw turtle on top. Then update the display.
    def draw(self):
        self.screen.fill(self.screen_color)
        SimEngine.WORLD.draw(self.screen)
        display.update()

    def place_turtle(self, turtle):
        # Wrap around the screen.
        turtle.pixel_pos = PixelVector2(turtle.pixel_pos.x % self.screen_rect.w,
                                        turtle.pixel_pos.y % self.screen_rect.h)
        turtle.rect = Rect((turtle.pixel_pos.x, turtle.pixel_pos.y), (BLOCK_SIDE, BLOCK_SIDE))

    def run_model(self):
        pg.init()
        while True:
            for ev in event.get():
                if ev.type == QUIT or \
                   ev.type == KEYDOWN and (ev.key == K_ESCAPE or
                                           ev.key == K_q or
                                           # The following tests for ctrl-d.
                                           # (See https://www.pygame.org/docs/ref/key.html)
                                           ev.key == K_d and ev.mod & KMOD_CTRL):
                    return

            SimEngine.WORLD.update()
            self.draw()
            self.clock.tick(self.fps)


import numpy as np
import cv2, os
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib import gridspec
import seaborn as sns

class Visual3DSwing:

    def __init__(self) -> None:
        pass

    def set_saved_video(self, output_video, size):
        fourcc = cv2.VideoWriter_fourcc(*"mp4v")
        fps = 60
        video = cv2.VideoWriter(output_video, fourcc, fps, size)
        return video

    def draw_line(self, ax, joint_target_x, joint_target_y, joint_target_z, frame_count, id1, id2, color):
        ax.plot(
                [joint_target_x[frame_count][id1], joint_target_x[frame_count][id2]],
                [joint_target_y[frame_count][id1], joint_target_y[frame_count][id2]],
                [joint_target_z[frame_count][id1], joint_target_z[frame_count][id2]],
                color=color,
                linewidth=3
        )

    def show_3D(
        self,
        input_video1,
        input_video2,
        target_bat, # raw data of baseball bat. If we have 1000 frame , the shape of target_bat is (4, 2000). '4' means (x,y,z, frame index) ; '2000' means (head and tail)*1000
        target_ball,
        target_joint,
        frame_skip, # set the interval. frame_skip = 1 -> show all frames ; frame_skip = 5 -> show one frame every 5 frames
        end_frame, # the last index that you wanna check
        alpha=0.2,
        save_name=None, # output video name
        is_set_lim=True,
    ):
        if save_name is not None:
            video = self.set_saved_video(save_name, (1224, 648))  # since hconcat two img : (1920*2 , 1080) --> resize *0.5 --> (1920, 540)

        target_x, target_y, target_z = target_bat[0], target_bat[1], target_bat[2]
        joint_target_x, joint_target_y, joint_target_z = target_joint[0], target_joint[1], target_joint[2]
        ball_target_x, ball_target_y, ball_target_z, ball_target_frame  = target_ball[0], target_ball[1]-385, target_ball[2], target_ball[3]

        frame_count = -1
        count = -1
        cap = cv2.VideoCapture(input_video1)
        cap2 = cv2.VideoCapture(input_video2)
        history = 0 # show '3' previous bat which color is blue in current frame. Just show the current bat which color is red -> history = 0
        sns.set_style ('dark')

        while cap.isOpened():
            fig = plt.figure(dpi=300)
            fig.set_size_inches(7.2, 7.2)
            # gs = gridspec.GridSpec(1, 1)
            ax = plt.subplot(projection="3d")
            ax.view_init(20, 0)
            if is_set_lim:
                ax.set_xlim(-200, 200)
                ax.set_ylim(-200, 100)
                ax.set_zlim(0, 300)

            ax.set_xlabel("axis x", fontsize=12)
            ax.set_ylabel("axis y", fontsize=12)
            ax.set_zlabel("axis z", fontsize=12)

            frame_count += 1
            if frame_count == end_frame:
                break
            ret, frame = cap.read()
            ret2, frame2 = cap2.read()
            if frame_count % frame_skip != 0:
                continue
            else:
                count += 1
            # if frame is read correctly ret is True
            if not ret:
                print("Can't receive frame (stream end?). Exiting ...")
                break

            for k in range(ball_target_frame.shape[0]):
                if frame_count==ball_target_frame[k]:
                    checkpoint = k
            print(checkpoint)
            if checkpoint>0 and frame_count<591:
                ax.scatter(
                    ball_target_x[checkpoint],
                    ball_target_y[checkpoint],
                    ball_target_z[checkpoint],
                    color="b",
                    marker="o",
                    alpha=0.8,
                    linewidths=2
                )

            if count >= history - 1:
                # ax.scatter(
                #     target_x[count * 2 : (count + 1) * 2],
                #     target_y[count * 2 : (count + 1) * 2],
                #     target_z[count * 2 : (count + 1) * 2],
                #     color="r",
                #     marker="o",
                #     alpha=alpha,
                # )
                # ax.scatter(
                #     target_x[(count - history + 1) * 2 : count * 2],
                #     target_y[(count - history + 1) * 2 : count * 2],
                #     target_z[(count - history + 1) * 2 : count * 2],
                #     color="b",
                #     marker="o",
                #     alpha=alpha,
                # )
                ax.plot(
                    [target_x[count * 2], target_x[count * 2 + 1]],
                    [target_y[count * 2], target_y[count * 2 + 1]],
                    [target_z[count * 2], target_z[count * 2 + 1]],
                    color="lightseagreen",
                    linewidth=3
                )
                # for i in range(1, history):
                #     ax.plot(
                #         [target_x[(count - i) * 2], target_x[(count - 1) * 2 + 1]],
                #         [target_y[(count - i) * 2], target_y[(count - 1) * 2 + 1]],
                #         [target_z[(count - i) * 2], target_z[(count - 1) * 2 + 1]],
                #         color="b",
                #         linewidth=3
                #     )
            else:

                ax.scatter(
                    target_x[count * 2 : (count + 1) * 2],
                    target_y[count * 2 : (count + 1) * 2],
                    target_z[count * 2 : (count + 1) * 2],
                    color="b",
                    marker="o",
                    alpha=alpha,
                )
                ax.plot(
                    [target_x[count * 2], target_x[count * 2 + 1]],
                    [target_y[count * 2], target_y[count * 2 + 1]],
                    [target_z[count * 2], target_z[count * 2 + 1]],
                    color="b",
                    linewidth=3
                )

            ax.scatter(joint_target_x[frame_count][0], joint_target_y[frame_count][0], joint_target_z[frame_count][0], color='black')
            # ax.scatter(joint_target_x[frame_count][11:17], joint_target_y[frame_count][11:17], joint_target_z[frame_count][11:17], color='black')
            # ax.scatter(joint_target_x[frame_count][23:29], joint_target_y[frame_count][23:29], joint_target_z[frame_count][23:29], color='black')

            # drawing
            # body
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 11, 12, 'red')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 11, 23, 'red')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 12, 24, 'red')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 23, 24, 'red')

            # arm
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 12, 14, 'blue')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 14, 16, 'blue')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 11, 13, 'green')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 13, 15, 'green')

            # leg
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 24, 26, 'orange')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 26, 28, 'orange')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 23, 25, 'violet')
            self.draw_line(ax, joint_target_x, joint_target_y, joint_target_z, frame_count, 25, 27, 'violet')

            fig.canvas.draw()
            # convert canvas to image
            img = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep="")
            img = img.reshape(fig.canvas.get_width_height()[::-1] + (3,))
            img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)

            frames = cv2.vconcat([frame, frame2])
            merge_image = cv2.hconcat([frames, img])
            resize_size = (int(merge_image.shape[1] * 0.3), int(merge_image.shape[0] * 0.3))
            merge_image = cv2.resize(merge_image, resize_size)

            cv2.imshow("frame", merge_image)
            if save_name is not None:
                video.write(merge_image)
            if cv2.waitKey(1) == ord("q"):
                break
            plt.close(fig)

        if save_name is not None:
            video.release()
        cv2.destroyAllWindows()
        return

if __name__ == '__main__':

    v3d = Visual3DSwing()

    input_video_1 = './swing_input/1_view1.MP4'
    input_video_2 = './swing_input/1_view2.MP4'
    bat_target = np.load('./swing_input/1_bat_target.npy')
    joint_target = np.load('./swing_input/1_joint_target.npy')
    ball_target = np.load('./swing_input/1_ball_target.npy')
    frame_skip = 1
    end_frame = 800
    out_dir = './swing_output'
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
    out_path = os.path.join(out_dir, '1_swing_result_with_ball.mp4')

    print('ball info. ', ball_target)

    v3d.show_3D(
        input_video_1,
        input_video_2,
        bat_target,
        ball_target,
        joint_target,
        frame_skip,
        end_frame,
        is_set_lim=True,
        save_name=out_path,
    )


from resonances.settings import Config
import math
from typing import Dict
from enum import Enum
from enum import unique
from typing import List
from fractions import gcd

@unique
class _FormatEnum(Enum):
    tex = 'tex'
    simple = 'simple'

CONFIG = Config.get_params()
FORMAT = _FormatEnum(CONFIG['resonance_table']['format'])
_Body = Dict[str, float]
_AXIS_MIN = 1.5

_PLANET_NUMBER = {
    'VENUS': 2,
    'EARTHMOO': 3,
    'MARS': 4,
    'JUPITER': 5,
    'SATURN': 6,
    'URANUS': 7,
    'NEPTUNE': 8,
}

class _ResonanceGeneratorBuilder:
    def __init__(self, body_count: int, order_max: int):
        self.body_count = body_count

        if order_max is not None:
            self.order_max = order_max
        elif body_count == 2:
            self.order_max = 7
        else:
            self.order_max = 25

    def build(self):
        if self.body_count == 2:
            return self._3b_resonance_gen()
        else:
            return self._2b_resonance_gen()

    def _3b_resonance_gen(self):
        for i in range(1, 9):
            for j in range(-self.order_max, self.order_max + 1):
                for k in range(-self.order_max, self.order_max + 1):
                    diff = int(0.0 - i - j - k)
                    if i == 0 or j == 0 or k == 0 or abs(diff) > self.order_max:
                        continue
                    resonance = [i, j, k, 0, 0, diff]
                    yield resonance

    def _2b_resonance_gen(self):
        for i in range(1, self.order_max + 1):
            for j in range(1, self.order_max + 1):
                if gcd(i, j) > 1:
                    continue
                diff = i - j
                resonance = [i, -j, 0, -diff]
                yield resonance

def _build_line_data(resonance: List[int], axis: float) -> str:
    if (FORMAT == _FormatEnum.tex):
        line_data = ' & '.join(str(x) for x in resonance) + ' & %2.4f \\\\' % axis
    else:
        line_data = ' '.join(str(x) for x in resonance) + ' %2.4f' % axis
    return line_data

def generate_resonance_table(body_names: List[str], axis_max: float = None,
                             order_max: int = None) -> List[str]:
    """
    Generates resonance table.
    """
    data = []

    body_count = len(body_names)
    builder = _ResonanceGeneratorBuilder(body_count, order_max)
    for resonance in builder.build():
        if body_count == 2:
            try:
                bodies = [_build_body(x) for x in body_names]
                axis = _build_resonance_axis(resonance, bodies)
            except _MeanMotionException:
                pass
                continue
            if abs(resonance[5]) >= builder.order_max or axis <= _AXIS_MIN:
                continue
            if axis_max is not None and axis >= axis_max:
                continue
            line_data = _build_line_data(resonance, axis)
        elif body_count == 1:
            body_axis = _build_body(body_names[0])['axis']
            ratio = (-resonance[1]) / resonance[0]
            axis = body_axis * (ratio ** (2/3))
            line_data = _build_line_data(resonance, axis)
        else:
            raise Exception('Unexpected count of bodies.')
        pass
        data.append(line_data)
    return data

class _MeanMotionException(Exception):
    pass

def _build_resonance_axis(resonance, bodies: List[_Body]) -> float:
    jupiter = bodies[0]
    body_count = len(bodies)
    K = CONFIG['constants']['k']

    items = []
    for i, body in enumerate(bodies):
        items.append(-resonance[i] * body['mean_motion'])
        items.append(-resonance[i + body_count + 1] * body['longitude_of_periapsis'])
    lin_combination = sum(items)
    mean_motion = lin_combination / resonance[2]
    if mean_motion < 0:
        raise _MeanMotionException()

    axis = (K / mean_motion) ** (2.0/3)
    eps = (jupiter['axis'] - axis) / jupiter['axis']
    longitude_of_periapsis = (
        K / (2 * math.pi) * math.sqrt(axis / jupiter['axis']) *
        (eps ** 2) * jupiter['mean_motion']
    )
    mean_motion = (lin_combination - resonance[2] * longitude_of_periapsis) / resonance[2]
    if mean_motion < 0:
        raise _MeanMotionException()

    axis = (K / mean_motion) ** (2.0/3)
    return axis

def _build_body(by_name: str) -> _Body:
    planet_index = _PLANET_NUMBER[by_name]
    constants = CONFIG['constants']
    longitude_of_periapsis = _from_day_to_year(_from_sec(
        constants['longitude_of_periapsis'][planet_index]))
    mean_motion = _from_day_to_year(_from_sec(
        constants['mean_motion'][planet_index]))
    res = {
        'axis': constants['axis'][planet_index],
        'mean_motion': mean_motion,
        'longitude_of_periapsis': float("%.6f" % longitude_of_periapsis)
    }
    return res

def _from_sec(value):
    return (value/3600.0)*math.pi/180.0

def _from_day_to_year(value):
    return value / 365.25


# coding=UTF-8

from elasticsearch import Elasticsearch
import csv
from elasticsearch import Elasticsearch
from elasticsearch import helpers
from digits2chinese import to_chinese
from chinese import four_to_han
from translate.example import connect
from translate.Baidu_Text_transAPI import translate
import json
import os.path
import csv
from tqdm import tqdm
from clear import clear
import copy
import difflib

DOC_Count = 10

def insert_QAData(doc_name, id, count):
    csv_set = []
    with open(doc_name, 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        rows = csv.reader(csvfile)
        column = [row['答案'] for row in reader]
        json_set = []
        for (i,c) in enumerate(column):
            dataitem = ''
            for j in range(5):
                if i+j <len(column):
                    dataitem += column[i+j]
            dic_tmp = {"name": doc_name[2:], "para_id": count, "paragraph": dataitem}
            csv_set.append(dataitem)
            count += 1
            dicJson = json.dumps(dic_tmp, ensure_ascii=False)
            json_set.append(dicJson)

    with open(doc_name, 'r') as csvfile:
        rows = csv.reader(csvfile)
        with open('./output'+doc_name[1:], 'w') as wfile:
            writer = csv.writer(wfile)
            index = 0
            for row in rows:
                row = row[:-1]
                if index == 0:
                    index += 1
                    continue
                if index < len(csv_set):
                    row.append(csv_set[index-1])
                    index += 1
                    writer.writerow(row)
    def gendata():
        for j in json_set:
            j = eval(j)
            yield {
                "_index": "regulations",
                "name": doc_name[0:-5],
                "para_id": j["para_id"],
                "paragraph": [j["paragraph"]]
            }

    helpers.bulk(es, gendata())
    id += 1
    # csv_file = csv.writer(open('./output/docshenan.csv', 'w'))
    # for i in csv_set:
    #     csv_file.writerow([i])

def insert_json(doc_name, id):
    with open('./regulations/'+doc_name, 'rb') as csv_in:
        with open('./regulations/c'+doc_name, "w", encoding="utf-8") as csv_temp:
            for line in csv_in:
                if not line:
                    break
                else:
                    line = line.decode("utf-8", "ignore")
                    #line = str(line).splitlines(True)
                    for l in line:
                        csv_temp.write(str(l).replace('\\n', ''))
    json_set = []
    csv_set = []
    count = 1
    if doc_name != ".DS_Store" and doc_name != "c.DS_Store":
        with open('./regulations/c'+doc_name, 'r') as f:
            li = f.readlines()
            for row in li:
                samples = json.loads(row)
                for sample in samples:
                    if sample["正文"] != "" and sample["正文"] != " ":
                        #datalist = sample["正文"].split(' ')
                        datalist = clear(sample["正文"])
                        for dataitem in datalist:
                            if len(dataitem) < 30:
                                continue
                            csv_set.append(dataitem)
                            dic_tmp = {"name": doc_name, "para_id": count, "paragraph": dataitem}
                            dicJson = json.dumps(dic_tmp, ensure_ascii=False)
                            json_set.append(dicJson)
                            count += 1
        f.close()
        os.remove('./regulations/c'+doc_name)
    else:
        os.remove('./regulations/'+doc_name)

    def gendata():
        for j in json_set:
            j = eval(j)
            yield {
                "_index": "regulations",
                "name": doc_name[0:-5],
                "para_id": j["para_id"],
                "paragraph": [j["paragraph"]]
            }

    helpers.bulk(es, gendata())
    id += 1
    csv_file = csv.writer(open('./output/docs.csv', 'w'))
    for i in csv_set:
        csv_file.writerow([i])
    # dataset = []
    # for line in csv_file:
    return id, count

def insert(doc_name,id):
    with open('./regulations/'+doc_name, 'r') as f1:
        list1 = f1.readlines()
    for i in range(0, len(list1)):
        list1[i] = list1[i].rstrip('\n')
    string1 ="".join(list1)
    last1 = 0
    last2 = 0
    dic = {"title":doc_name,"paragraphs":[]}
    para_id = 1
    json_set = []
    for i in range(1,300):
        if i<101 or i % 100 == 0:
            str_cn = to_chinese(i)
        else:
            str_cn = four_to_han(i)
        last1 = last2
        last2 = string1.find("第"+str_cn+"条", last2, len(string1))
        if(last2 == -1):
            break
        else:
            if i==1:
                continue
            dic_tmp = {"name":doc_name,"para_id":para_id,"paragraph":string1[last1:last2]}
            dicJson = json.dumps(dic_tmp, ensure_ascii=False)
            json_set.append(dicJson)
            #es.index(index="regulations", doc_type="法律法规", id=id, body=dicJson)
            #dic["paragraphs"].append(dic_tmp)
            para_id += 1
            id +=1
    dic_tmp = {"name":doc_name,"para_id":para_id,"paragraph":string1[last1:len(string1)]}
    dicJson = json.dumps(dic_tmp, ensure_ascii=False)
    json_set.append(dicJson)
    #es.index(index="regulations", doc_type="法律法规", id=id, body=dicJson)

    #helpers.bulk(client=es, actions=json_set)
    def gendata():
        for j in json_set:
            j = eval(j)
            yield {
                "_index": "regulations",
                "name": doc_name[0:-4],
                "para_id":j["para_id"],
                "paragraph":[j["paragraph"]]
            }

    helpers.bulk(es, gendata())
    id +=1
    if f1:
        f1.close()
    return id

def query(question, answer):
    query_list = es.indices.analyze(index="regulations",body={'text':question,'analyzer':"ik_max_word"})
    query1 = {
        "query": {
            "bool": {
                "should": [
                    # {"match": {"paragraph": "发明创造"}},
                    # {"match": {"paragraph": "报酬"}}
                ]
            }
        }
    }
    for q in query_list['tokens']:
        query1["query"]["bool"]["should"].append({"match": {"paragraph": q['token']}})

    #,filter_path="hits.hits._source.paragraphs"
    es.indices.refresh(index="regulations")
    query = es.search(index="regulations", filter_path="hits", scroll='5m', body=query1)
    value = query["hits"]["hits"]
    results = []
    if len(value)>DOC_Count:
        for i in range(DOC_Count):
            para_score = value[i]['_score']
            dataItem = {}
            if in_answer(value[i]['_source']['paragraph'],answer,para_score):
                dataItem['is_selected'] = True
            else:
                dataItem['is_selected'] = False
            dataItem['title'] = value[i]['_source']['name']
            dataItem['paragraphs'] = value[i]['_source']['paragraph']
            results.append(dataItem)
        return results
    else:
        for i in range(len(value)):
            para_score = value[i]['_score']
            dataItem = {}
            if in_answer(value[i]['_source']['paragraph'], answer,para_score):
                dataItem['is_selected'] = True
            else:
                dataItem['is_selected'] = False
            dataItem['title'] = value[i]['_source']['name']
            dataItem['paragraphs'] = value[i]['_source']['paragraph']
            results.append(dataItem)
        return results
    # es查询出的结果第一页
    #results = query['hits']['hits']
    # es查询出的结果总量
    #print(query['__len__'])
    # if 'total' in query:
    #     #print('true')
    #     total = query['hits']['total']
    # else:
    #     #print('false')
    #     total = {'value':1}

def get_name(rootdir):
    name_list = []
    for parent, dirnames, filenames in os.walk(rootdir):
        # for dirname in dirnames:
        #     print("Parent folder:", parent)
        #     print("Dirname:", dirname)
        for filename in filenames:
            name_list.append(filename)
    return name_list

#def build_dataset(paragraphs, ):

def in_answer(para, answer, score):
    '''添加判断该条段落是否出现在答案中'''
    return answer in para

def get_answer(para, answer):
    true_start = answer[0:2]
    true_end = answer[-2:]
    start_score = 0
    end_score = 0
    new_start = 0
    new_end = len(para)-3
    for (i,p) in enumerate(para):
        if i == len(para)-1:
            break
        tmp_s_score = get_simi_score(para[i:i+2], true_start)
        tmp_e_score = get_simi_score(para[i:i+2], true_end)
        if tmp_s_score>start_score:
            start_score = tmp_s_score
            new_start = i
        if tmp_e_score>end_score:
            end_score = tmp_e_score
            new_end = i
    return para[new_start:new_end+2]

def get_simi_score(str1, str2):
    return difflib.SequenceMatcher(None, str1, str2).quick_ratio()

if __name__ == '__main__':
    es = Elasticsearch(hosts="127.0.0.1", port=9200, timeout=200)
    if (es.indices.exists(index='regulations') is not True):
        es.indices.create(index='regulations')
    else:
        es.indices.delete(index="regulations")
        es.indices.create(index='regulations')
    name_list = get_name('./regulations')
    id = 1
    count = 1
    for name in name_list:
        id, count = insert_json(name,id)
        #id+=1

    insert_QAData('./河南检务公开数据.csv', id, count)

    def gen_json(doc_name):
        dataset = []
        csv_file = csv.reader(open(doc_name, 'r'))
        for line in csv_file:
            result = query(line[1], line[2])
            data = {}
            data['documents'] = result
            data['question'] = line[1]
            data['answers'] = [line[2]]
            data['question_type'] = 'DESCRIPTION'
            data['question_id'] = line[0]
            data['fact_or_opinion'] = 'FACT'
            dataset.append(data)
        return dataset

    whole_set = []
    whole_set += gen_json('ques_test.csv')
    whole_set += gen_json('./output/河南检务公开数据.csv')

        #继续写入双向翻译后的数据
        #翻译回来后的文档需要重新寻找一次答案
        # result_new = copy.deepcopy(result)
        # ans_new = data['answers']
        # for re in result_new:
        #     query_trans = re['paragraphs']
        #     translation = translate('zh', 'en', query_trans)
        #     re_translation = translate('en', 'zh', translation)
        #     re['paragraphs'] = re_translation
        #     if(re['is_selected']):
        #         ans_new = get_answer(re_translation, data['answers'])
        # data_new = {}
        # data_new['documents'] = result_new
        # data_new['question'] = line[1]
        # data_new['answers'] = ans_new
        # data_new['question_type'] = 'DESCRIPTION'
        # data_new['question_id'] = line[0]
        # data_new['fact_or_opinion'] = 'FACT'
        # dataset.append(data_new)

    with open("./output/dataset.json", "w") as f:
        json.dump(whole_set, f,ensure_ascii=False)
    print("加载入文件完成...")

    '''还没有写问题类型、factoropinion'''


import sys
import sqlite3
import pandas as pd
from sqlalchemy import *
import re
from nltk.tokenize import word_tokenize
import nltk
nltk.download('punkt')
nltk.download('wordnet')
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer
import numpy as np

from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.pipeline import Pipeline

from sklearn.datasets import make_multilabel_classification
from sklearn.multioutput import MultiOutputClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report

from sklearn.metrics import f1_score
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score

from sklearn.model_selection import GridSearchCV

from statistics import mean

from sklearn.multioutput import MultiOutputRegressor
from sklearn.ensemble import GradientBoostingRegressor

import pickle
import time

def load_data(database_filepath):
    '''
    input : database path
    output : X, Y to use in ML
    '''
    engine = create_engine('sqlite:///{}'.format(database_filepath))

    #engine.table_names()
    df = pd.read_sql_table('InsertTableName', engine)
    X = df.message
    Y = df.iloc[:, 4:]
    category_names = list(df.columns)
    return X, Y, category_names

def tokenize(text):
    '''
    input:text
    output: cleaned and tokenized list of the text
    '''
    # normalize case and remove punctuation
    text = re.sub(r"[^a-zA-Z0-9]", " ", text.lower())

    # tokenize text
    tokens = word_tokenize(text)

    # initiate lemmatizer
    lemmatizer = WordNetLemmatizer()

    # iterate through each token
    clean_tokens = []
    for tok in tokens:

        # lemmatize, normalize case, and remove leading/trailing white space
        clean_tok =  lemmatizer.lemmatize( (tok.strip()).lower())

        clean_tokens.append(clean_tok)

    return clean_tokens

def build_model():
    '''
    output: model
    '''
    pipeline =  Pipeline([
        ('vect', CountVectorizer(tokenizer=tokenize)),
        ('tfidf', TfidfTransformer()),
        ('clf', MultiOutputClassifier(RandomForestClassifier(), n_jobs = -1))
    ])

    parameters = {
        'clf__estimator__min_samples_split': [2]
    }

    model = GridSearchCV(pipeline,param_grid=parameters, n_jobs=2, verbose=3)

    return model

def evaluate_model(model, X_test, Y_test, category_names):
    '''
    output: prints f1 score, precision score and recall score for all categories.
    An overall accuracy is printed showing the proportion of correct predictions.
    '''
    y_pred = model.predict(X_test)

    accuracy=[]
    for a,b,c in zip(Y_test, y_pred.T, category_names):
        print("Column Name: "+c)
        print("f1 score: {}".format(f1_score(Y_test[a], b, average = None)))
        print("Precision score: {}".format(precision_score(Y_test[a], b, average = None)))
        print("Recall score: {}".format(recall_score(Y_test[a], b, average = None)))
        print()
        accuracy.append((Y_test[a] == b).mean())

    print('Mean accuracy')
    print(mean(accuracy))
    pass

def save_model(model, model_filepath):
    # save the model to disk
    pickle.dump(model, open(model_filepath, 'wb'))

def main():
    if len(sys.argv) == 3:
        database_filepath, model_filepath = sys.argv[1:]
        print('Loading data...\n    DATABASE: {}'.format(database_filepath))
        X, Y, category_names = load_data(database_filepath)
        X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

        print('Building model...')
        model = build_model()

        print('Training model...')
        model.fit(X_train, Y_train)

        print('Evaluating model...')
        evaluate_model(model, X_test, Y_test, category_names)

        print('Saving model...\n    MODEL: {}'.format(model_filepath))
        save_model(model, model_filepath)

        print('Trained model saved!')

    else:
        print('Please provide the filepath of the disaster messages database '\
              'as the first argument and the filepath of the pickle file to '\
              'save the model to as the second argument. \n\nExample: python '\
              'train_classifier.py ../data/DisasterResponse.db classifier.pkl')

if __name__ == '__main__':
    main()


"""
A Python module that computes the protein interaction graph from a PDB file.

Author: Eric J. Ma
License: MIT

Intended usage:

```python
from proteingraph import read_pdb

G = read_pdb("/path/to/file.pdb")
```
"""
from collections import defaultdict
from functools import partial
from itertools import combinations
from pathlib import Path

import networkx as nx
import numpy as np
import pandas as pd
from biopandas.pdb import PandasPdb
from scipy.spatial import Delaunay
from scipy.spatial.distance import euclidean, pdist, rogerstanimoto, squareform
from sklearn.preprocessing import LabelBinarizer

from .resi_atoms import (
    AA_RING_ATOMS,
    AROMATIC_RESIS,
    BACKBONE_ATOMS,
    BOND_TYPES,
    CATION_PI_RESIS,
    CATION_RESIS,
    DISULFIDE_ATOMS,
    DISULFIDE_RESIS,
    HYDROPHOBIC_RESIS,
    IONIC_RESIS,
    ISOELECTRIC_POINTS_STD,
    MOLECULAR_WEIGHTS_STD,
    NEG_AA,
    PI_RESIS,
    POS_AA,
    RESI_NAMES,
)

def pdb2df(path: Path) -> nx.Graph:
    """
    Parse the PDB file as a pandas DataFrame object.

    Backbone chain atoms are ignored for the calculation
    of interacting residues.
    """
    atomic_df = PandasPdb().read_pdb(str(path)).df["ATOM"]
    atomic_df["node_id"] = (
        atomic_df["chain_id"]
        + atomic_df["residue_number"].map(str)
        + atomic_df["residue_name"]
    )
    return atomic_df

def compute_chain_pos_aa_mapping(pdb_df):
    """Compute the mapping: chain -> position -> aa."""
    chain_pos_aa = defaultdict(dict)
    for (chain, pos, aa), _ in pdb_df.groupby(
        ["chain_id", "residue_number", "residue_name"]
    ):
        chain_pos_aa[chain][pos] = aa
    return chain_pos_aa

def read_pdb(path: Path) -> nx.Graph:
    """
    Parse PDB file into protein graph.

    Overall function to read PDB and get back graph.
    """
    pdb_df = pdb2df(path)
    rgroup_df = compute_rgroup_dataframe(pdb_df)
    chain_pos_aa = compute_chain_pos_aa_mapping(pdb_df)

    edge_funcs = [
        partial(add_hydrophobic_interactions, rgroup_df=rgroup_df),
        partial(add_disulfide_interactions, rgroup_df=rgroup_df),
        partial(add_hydrogen_bond_interactions, rgroup_df=rgroup_df),
        partial(add_ionic_interactions, rgroup_df=rgroup_df),
        partial(add_aromatic_interactions, pdb_df=pdb_df),
        partial(add_aromatic_sulphur_interactions, rgroup_df=rgroup_df),
        partial(add_cation_pi_interactions, rgroup_df=rgroup_df),
    ]

    G = compute_interaction_graph(pdb_df, chain_pos_aa, edge_funcs=edge_funcs)
    convert_all_sets_to_lists(G)
    return G

def compute_interaction_graph(pdb_df, chain_pos_aa, edge_funcs=None):
    """
    Compute the interaction graph.

    ## Parameters:

    - `pdb_df`: A pandas DataFrame.
        Should be the result of calling `pdb2df`.
    - `chain_pos_aa`: A nested dictionary mapping chain -> pos -> aa.
        Should be the result of calling `compute_chain_pos_aa_mapping`.
    - `edge_funcs`: Arbitrary functions which take in only a graph `G`,
        and uses `add_edge` to add edges to the graph.
    """
    # Add in nodes with their metadata
    # Metadata are:
    # - x, y, z coordinates of C-alpha
    # - chain_id
    # - residue_number
    # - residue_name
    G = nx.Graph()
    for g, d in pdb_df.query("record_name == 'ATOM'").groupby(
        ["node_id", "chain_id", "residue_number", "residue_name"]
    ):
        node_id, chain_id, residue_number, residue_name = g
        x_coord = d.query("atom_name == 'CA'")["x_coord"].values[0]
        y_coord = d.query("atom_name == 'CA'")["y_coord"].values[0]
        z_coord = d.query("atom_name == 'CA'")["z_coord"].values[0]
        G.add_node(
            node_id,
            chain_id=chain_id,
            residue_number=residue_number,
            residue_name=residue_name,
            x_coord=x_coord,
            y_coord=y_coord,
            z_coord=z_coord,
            features=None,
        )

    # Add in edges for amino acids that are adjacent in the linear amino
    # acid sequence.
    for n, d in G.nodes(data=True):
        chain = d["chain_id"]
        pos = d["residue_number"]
        aa = d["residue_name"]

        if pos - 1 in chain_pos_aa[chain].keys():
            prev_aa = chain_pos_aa[chain][pos - 1]
            prev_node = f"{chain}{pos-1}{prev_aa}"
            if aa in RESI_NAMES and prev_aa in RESI_NAMES:
                G.add_edge(n, prev_node, kind={"backbone"})

        if pos + 1 in chain_pos_aa[chain].keys():
            next_aa = chain_pos_aa[chain][pos + 1]
            next_node = f"{chain}{pos+1}{next_aa}"
            if aa in RESI_NAMES and next_aa in RESI_NAMES:
                G.add_edge(n, next_node, kind={"backbone"})

    # Add in each type of edge, based on the above.
    for func in edge_funcs:
        func(G)
    return G

def convert_all_sets_to_lists(G):
    """Convert all node and edge attributes to lists."""
    for n, d in G.nodes(data=True):
        for k, v in d.items():
            if isinstance(v, set):
                G.nodes[n][k] = list(v)

    for u1, u2, d in G.edges(data=True):
        for k, v in d.items():
            if isinstance(v, set):
                G.edges[u1, u2][k] = list(v)

def compute_distmat(pdb_df):
    """
    Compute pairwise euclidean distances between every atom.

    Design choice: passed in a DataFrame to enable easier testing on
    dummy data.
    """
    eucl_dists = pdist(
        pdb_df[["x_coord", "y_coord", "z_coord"]], metric="euclidean"
    )
    eucl_dists = pd.DataFrame(squareform(eucl_dists))
    eucl_dists.index = pdb_df.index
    eucl_dists.columns = pdb_df.index

    return eucl_dists

def compute_rgroup_dataframe(pdb_df):
    """Return the atoms that are in R-groups and not the backbone chain."""
    rgroup_df = filter_dataframe(pdb_df, "atom_name", BACKBONE_ATOMS, False)
    return rgroup_df

def filter_dataframe(dataframe, by_column, list_of_values, boolean):
    """
    Filter function for dataframe.

    Filters the [dataframe] such that the [by_column] values have to be
    in the [list_of_values] list if boolean == True, or not in the list
    if boolean == False
    """
    df = dataframe.copy()
    df = df[df[by_column].isin(list_of_values) == boolean]
    df.reset_index(inplace=True, drop=True)

    return df

def add_hydrophobic_interactions(G, rgroup_df):
    """
    Find all hydrophobic interactions.

    Performs searches between the following residues:
    ALA, VAL, LEU, ILE, MET, PHE, TRP, PRO, TYR

    Criteria: R-group residues are within 5A distance.
    """
    hydrophobics_df = filter_dataframe(
        rgroup_df, "residue_name", HYDROPHOBIC_RESIS, True
    )
    distmat = compute_distmat(hydrophobics_df)
    interacting_atoms = get_interacting_atoms(5, distmat)
    add_interacting_resis(
        G, interacting_atoms, hydrophobics_df, ["hydrophobic"]
    )

def add_disulfide_interactions(G, rgroup_df):
    """
    Find all disulfide interactions between CYS residues.

    Criteria: sulfur atom pairs are within 2.2A of each other.
    """
    disulfide_df = filter_dataframe(
        rgroup_df, "residue_name", DISULFIDE_RESIS, True
    )
    disulfide_df = filter_dataframe(
        disulfide_df, "atom_name", DISULFIDE_ATOMS, True
    )
    distmat = compute_distmat(disulfide_df)
    interacting_atoms = get_interacting_atoms(2.2, distmat)
    add_interacting_resis(G, interacting_atoms, disulfide_df, ["disulfide"])

def add_hydrogen_bond_interactions(G, rgroup_df):
    """Add all hydrogen-bond interactions."""
    # For these atoms, find those that are within 3.5A of one another.
    HBOND_ATOMS = [
        "ND",  # histidine and asparagine
        "NE",  # glutamate, tryptophan, arginine, histidine
        "NH",  # arginine
        "NZ",  # lysine
        "OD1",
        "OD2",
        "OE",
        "OG",
        "OH",
        "SD",  # cysteine
        "SG",  # methionine
        "N",
        "O",
    ]
    hbond_df = filter_dataframe(rgroup_df, "atom_name", HBOND_ATOMS, True)
    distmat = compute_distmat(hbond_df)
    interacting_atoms = get_interacting_atoms(3.5, distmat)
    add_interacting_resis(G, interacting_atoms, hbond_df, ["hbond"])

    # For these atoms, find those that are within 4.0A of one another.
    HBOND_ATOMS_SULPHUR = ["SD", "SG"]
    hbond_df = filter_dataframe(
        rgroup_df, "atom_name", HBOND_ATOMS_SULPHUR, True
    )
    distmat = compute_distmat(hbond_df)
    interacting_atoms = get_interacting_atoms(4.0, distmat)
    add_interacting_resis(G, interacting_atoms, hbond_df, ["hbond"])

def add_ionic_interactions(G, rgroup_df):
    """
    Find all ionic interactions.

    Criteria: ARG, LYS, HIS, ASP, and GLU residues are within 6A.
    """
    ionic_df = filter_dataframe(rgroup_df, "residue_name", IONIC_RESIS, True)
    distmat = compute_distmat(ionic_df)
    interacting_atoms = get_interacting_atoms(6, distmat)

    add_interacting_resis(G, interacting_atoms, ionic_df, ["ionic"])

    # Check that the interacting residues are of opposite charges
    for r1, r2 in get_edges_by_bond_type(G, "ionic"):
        condition1 = (
            G.nodes[r1]["residue_name"] in POS_AA
            and G.nodes[r2]["residue_name"] in NEG_AA
        )

        condition2 = (
            G.nodes[r2]["residue_name"] in POS_AA
            and G.nodes[r1]["residue_name"] in NEG_AA
        )

        is_ionic = condition1 or condition2
        if not is_ionic:
            G.edges[r1, r2]["kind"].remove("ionic")
            if len(G.edges[r1, r2]["kind"]) == 0:
                G.remove_edge(r1, r2)

def add_aromatic_interactions(G, pdb_df):
    """
    Find all aromatic-aromatic interaction.

    Criteria: phenyl ring centroids separated between 4.5A to 7A.

    Phenyl rings are present on PHE, TRP, HIS and TYR.

    Phenyl ring atoms on these amino acids are defined by the following
    atoms:
    - PHE: CG, CD, CE, CZ
    - TRP: CD, CE, CH, CZ
    - HIS: CG, CD, ND, NE, CE
    - TYR: CG, CD, CE, CZ

    Centroids of these atoms are taken by taking:
        (mean x), (mean y), (mean z)
    for each of the ring atoms.

    Notes for future self/developers:
    - Because of the requirement to pre-compute ring centroids, we do not
        use the functions written above (filter_dataframe, compute_distmat,
        get_interacting_atoms), as they do not return centroid atom
        euclidean coordinates.
    """
    dfs = []
    for resi in AROMATIC_RESIS:
        resi_rings_df = get_ring_atoms(pdb_df, resi)
        resi_centroid_df = get_ring_centroids(resi_rings_df)
        dfs.append(resi_centroid_df)

    aromatic_df = (
        pd.concat(dfs).sort_values(by="node_id").reset_index(drop=True)
    )

    distmat = compute_distmat(aromatic_df)
    distmat.set_index(aromatic_df["node_id"], inplace=True)
    distmat.columns = aromatic_df["node_id"]
    distmat = distmat[(distmat >= 4.5) & (distmat <= 7)].fillna(0)
    indices = np.where(distmat > 0)

    interacting_resis = []
    for i, (r, c) in enumerate(zip(indices[0], indices[1])):
        interacting_resis.append((distmat.index[r], distmat.index[c]))

    for i, (n1, n2) in enumerate(interacting_resis):
        assert G.nodes[n1]["residue_name"] in AROMATIC_RESIS
        assert G.nodes[n2]["residue_name"] in AROMATIC_RESIS
        if G.has_edge(n1, n2):
            G.edges[n1, n2]["kind"].add("aromatic")
        else:
            G.add_edge(n1, n2, kind={"aromatic"})

def add_aromatic_sulphur_interactions(G, rgroup_df):
    """Find all aromatic-sulphur interactions."""
    RESIDUES = ["MET", "CYS", "PHE", "TYR", "TRP"]
    SULPHUR_RESIS = ["MET", "CYS"]
    AROMATIC_RESIS = ["PHE", "TYR", "TRP"]

    aromatic_sulphur_df = filter_dataframe(
        rgroup_df, "residue_name", RESIDUES, True
    )
    distmat = compute_distmat(aromatic_sulphur_df)
    interacting_atoms = get_interacting_atoms(5.3, distmat)
    interacting_atoms = zip(interacting_atoms[0], interacting_atoms[1])

    for (a1, a2) in interacting_atoms:
        resi1 = aromatic_sulphur_df.loc[a1, "node_id"]
        resi2 = aromatic_sulphur_df.loc[a2, "node_id"]

        condition1 = resi1 in SULPHUR_RESIS and resi2 in AROMATIC_RESIS
        condition2 = resi1 in AROMATIC_RESIS and resi2 in SULPHUR_RESIS

        if (condition1 or condition2) and resi1 != resi2:
            if G.has_edge(resi1, resi2):
                G.edges[resi1, resi2]["kind"].add("aromatic_sulphur")
            else:
                G.add_edge(resi1, resi2, kind={"aromatic_sulphur"})

def add_cation_pi_interactions(G, rgroup_df):
    """Add cation-pi interactions."""
    cation_pi_df = filter_dataframe(
        rgroup_df, "residue_name", CATION_PI_RESIS, True
    )
    distmat = compute_distmat(cation_pi_df)
    interacting_atoms = get_interacting_atoms(6, distmat)
    interacting_atoms = zip(interacting_atoms[0], interacting_atoms[1])

    for (a1, a2) in interacting_atoms:
        resi1 = cation_pi_df.loc[a1, "node_id"]
        resi2 = cation_pi_df.loc[a2, "node_id"]

        condition1 = resi1 in CATION_RESIS and resi2 in PI_RESIS
        condition2 = resi1 in PI_RESIS and resi2 in CATION_RESIS

        if (condition1 or condition2) and resi1 != resi2:
            if G.has_edge(resi1, resi2):
                G.edges[resi1, resi2]["kind"].add("cation_pi")
            else:
                G.add_edge(resi1, resi2, kind={"cation_pi"})

def get_interacting_atoms(angstroms, distmat):
    """Find the atoms that are within a particular radius of one another."""
    return np.where(distmat <= angstroms)

def add_delaunay_triangulation(G, pdb_df):
    """
    Compute the Delaunay triangulation of the protein structure.

    This has been used in prior work. References:
    - Harrison, R. W., Yu, X. & Weber, I. T. Using triangulation to include
        target structure improves drug resistance prediction accuracy. in 1–1
        (IEEE, 2013). doi:10.1109/ICCABS.2013.6629236
    - Yu, X., Weber, I. T. & Harrison, R. W. Prediction of HIV drug
        resistance from genotype with encoded three-dimensional protein
        structure. BMC Genomics 15 Suppl 5, S1 (2014).

    Notes:
    1. We do not use the add_interacting_resis function, because this
        interaction is computed on the CA atoms. Therefore, there is code
        duplication. For now, I have chosen to leave this code duplication
        in.
    """
    ca_coords = pdb_df.query("atom_name == 'CA'")

    tri = Delaunay(
        ca_coords[["x_coord", "y_coord", "z_coord"]]
    )  # this is the triangulation
    for simplex in tri.simplices:
        nodes = ca_coords.reset_index().loc[simplex, "node_id"]

        for n1, n2 in combinations(nodes, 2):
            if G.has_edge(n1, n2):
                G.edges[n1, n2]["kind"].add("delaunay")
            else:
                G.add_edge(n1, n2, kind={"delaunay"})

def get_ring_atoms(dataframe, aa):
    """
    Return ring atoms from a dataframe.

    A helper function for add_aromatic_interactions.

    Gets the ring atoms from the particular aromatic amino acid.

    Parameters:
    ===========
    - dataframe: the dataframe containing the atom records.
    - aa: the amino acid of interest, passed in as 3-letter string.

    Returns:
    ========
    - dataframe: a filtered dataframe containing just those atoms from the
                    particular amino acid selected. e.g. equivalent to
                    selecting just the ring atoms from a particular amino
                    acid.
    """
    ring_atom_df = filter_dataframe(dataframe, "residue_name", [aa], True)

    ring_atom_df = filter_dataframe(
        ring_atom_df, "atom_name", AA_RING_ATOMS[aa], True
    )
    return ring_atom_df

def get_ring_centroids(ring_atom_df):
    """
    Return aromatic ring centrods.

    A helper function for add_aromatic_interactions.

    Computes the ring centroids for each a particular amino acid's ring
    atoms.

    Ring centroids are computed by taking the mean of the x, y, and z
    coordinates.

    Parameters:
    ===========
    - ring_atom_df: a dataframe computed using get_ring_atoms.
    - aa: the amino acid under study

    Returns:
    ========
    - centroid_df: a dataframe containing just the centroid coordinates of
                    the ring atoms of each residue.
    """
    centroid_df = (
        ring_atom_df.groupby("node_id")
        .mean()[["x_coord", "y_coord", "z_coord"]]
        .reset_index()
    )

    return centroid_df

def get_edges_by_bond_type(G, bond_type):
    """
    Return edges of a particular bond type.

    Parameters:
    ===========
    - bond_type: (str) one of the elements in the variable BOND_TYPES

    Returns:
    ========
    - resis: (list) a list of tuples, where each tuple is an edge.
    """
    resis = []
    for n1, n2, d in G.edges(data=True):
        if bond_type in d["kind"]:
            resis.append((n1, n2))
    return resis

def node_coords(G, n):
    """
    Return the x, y, z coordinates of a node.

    This is a helper function. Simplifies the code.
    """
    x = G.nodes[n]["x_coord"]
    y = G.nodes[n]["y_coord"]
    z = G.nodes[n]["z_coord"]

    return x, y, z

def add_interacting_resis(G, interacting_atoms, dataframe, kind):
    """
    Add interacting residues to graph.

    Returns a list of 2-tuples indicating the interacting residues based
    on the interacting atoms. This is most typically called after the
    get_interacting_atoms function above.

    Also filters out the list such that the residues have to be at least
    two apart.

    ### Parameters

    - interacting_atoms:    (numpy array) result from get_interacting_atoms function.
    - dataframe:            (pandas dataframe) a pandas dataframe that
                            houses the euclidean locations of each atom.
    - kind:                 (list) the kind of interaction. Contains one
                            of :
                            - hydrophobic
                            - disulfide
                            - hbond
                            - ionic
                            - aromatic
                            - aromatic_sulphur
                            - cation_pi
                            - delaunay

    Returns:
    ========
    - filtered_interacting_resis: (set of tuples) the residues that are in
        an interaction, with the interaction kind specified

    """
    # This assertion/check is present for defensive programming!
    for k in kind:
        assert k in BOND_TYPES

    resi1 = dataframe.loc[interacting_atoms[0]]["node_id"].values
    resi2 = dataframe.loc[interacting_atoms[1]]["node_id"].values

    interacting_resis = set(list(zip(resi1, resi2)))
    for i1, i2 in interacting_resis:
        if i1 != i2:
            if G.has_edge(i1, i2):
                for k in kind:
                    G.edges[i1, i2]["kind"].add(k)
            else:
                G.add_edge(i1, i2, kind=set(kind))

class ProteinGraph(nx.Graph):
    """
    The ProteinGraph object.

    Inherits from the NetworkX Graph object.

    Implements further functions for automatically computing the graph
    structure.

    Certain functions are available for integration with the
    neural-fingerprint Python package.
    """

    def __init__(self):
        """Init."""
        super(ProteinGraph, self).__init__()

        self.chain_pos_aa_mapping = compute_chain_pos_aa_mapping()

        # Mapping of chain -> position -> aa
        self.rgroup_df = self.compute_rgroup_dataframe()
        # Automatically compute the interaction graph upon loading.
        self.compute_interaction_graph()
        self.compute_all_node_features()
        self.compute_all_edge_features()

        # Convert all metadata that are set datatypes to lists.
        self.convert_all_sets_to_lists()


from rest_framework import serializers

from serv.core.validators import is_proper_percent
from serv.discount.models import CarShowroomDiscount, SupplierDiscount
from serv.supplier.serializers import CarPriceRelationSupplierSerializerGet
from serv.carshowroom.serializers import CarPriceRelationShowroomSerializerGet

class ShowroomDiscountSerializerGet(serializers.ModelSerializer):
    discounted_record = CarPriceRelationShowroomSerializerGet()

    class Meta:
        model = CarShowroomDiscount
        fields = [
            'discount',
            'discounted_record'
        ]
        depth = 1

class ShowroomDiscountSerializerPost(serializers.ModelSerializer):
    discount = serializers.FloatField(validators=[is_proper_percent])

    class Meta:
        model = CarShowroomDiscount
        fields = [
            'discount',
            'discounted_record'
        ]

class SupplierDiscountSerializerGet(serializers.ModelSerializer):
    discounted_record = CarPriceRelationSupplierSerializerGet()

    class Meta:
        model = SupplierDiscount
        fields = [
            'discount',
            'discounted_record'
        ]
        depth = 1

class SupplierDiscountSerializerPost(serializers.ModelSerializer):
    discount = serializers.FloatField(validators=[is_proper_percent])

    class Meta:
        model = SupplierDiscount
        fields = [
            'discount',
            'discounted_record'
        ]


import argparse

import torch
import torch.nn.functional as F
from torch.utils.data import DataLoader
import numpy as np

from mini_imagenet import MiniImageNet
from samplers import CategoriesSampler
from convnet import Convnet,generator
from utils import pprint, set_gpu, count_acc, Averager, euclidean_metric,dot_metric\
    ,dot_metric_normalize,euclidean_metric_normalize, dot_normalize_multiscale,euclidean_normalize_multiscale,euclidean_multiscale

accuracy_list=[]
loss_list=[]
for runtime in range(5):
    path1='./gen/euclidean_shot_5_lamb100_noprior'+str(runtime)+'/max-acc.pth'
    path2 ='./gen/euclidean_shot_5_lamb100_noprior'+str(runtime)+'/max-acc-gen.pth'
    if __name__ == '__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument('--gpu', default='0')
        parser.add_argument('--load1', default=path1)
        parser.add_argument('--load2', default=path2)
        parser.add_argument('--batch', type=int, default=10000)
        parser.add_argument('--way', type=int, default=5)
        parser.add_argument('--shot', type=int, default=5)
        parser.add_argument('--query', type=int, default=15)
        parser.add_argument('--bound', type=int, default=1)
        parser.add_argument('--bound_correct', default=True)
        parser.add_argument('--multi', default=True)
        parser.add_argument('--distance',type=str,default='euclidean')
        args = parser.parse_args()
        pprint(vars(args))

        set_gpu(args.gpu)

        dataset = MiniImageNet('test')
        sampler = CategoriesSampler(dataset.label,
                                args.batch, args.way, args.shot + args.query)
        loader = DataLoader(dataset, batch_sampler=sampler,
                        num_workers=8, pin_memory=True)

        if args.multi == False:
            gen = generator(1600, 1).cuda()
        else:
            gen = generator(1600, 1600).cuda()
        gen.load_state_dict(torch.load(args.load2))
        gen.eval()

        model = Convnet().cuda()
        model.load_state_dict(torch.load(args.load1))
        model.eval()

        ave_acc = Averager()
        ave_loss = Averager()

        for i, batch in enumerate(loader, 1):
            data, _ = [_.cuda() for _ in batch]
            k = args.way * args.shot
            data_shot, data_query = data[:k], data[k:]

            x = model(data_shot)
            query = model(data_query)

            B, mean, var = gen(torch.cat([query, x], dim=0).mean(dim=0))
            #B_no = torch.ones(B.size()).cuda()
            x = x.reshape(args.shot, args.way, -1).mean(dim=0)
            p = x

            if args.bound_correct:
                if args.distance == 'cosine':
                    if args.multi == False:
                        logits, logits_scaled = dot_metric_normalize(query, p, B)
                    else:
                        logits, logits_scaled = dot_normalize_multiscale(query, p, B)
                else:
                    if args.multi == False:
                        logits, logits_scaled = euclidean_metric_normalize(query, p, B)
                    else:
                        logits, logits_scaled = euclidean_normalize_multiscale(query, p, B)
            else:
                if args.distance == 'cosine':
                    logits = dot_metric(model(data_query), p)
                else:
                    logits, logits_scaled = logits = euclidean_multiscale(query, p,B)
            #logits, logits_no = euclidean_normalize_multiscale(query, p, B_no)

            label = torch.arange(args.way).repeat(args.query)
            label = label.type(torch.cuda.LongTensor)
            #print(torch.mean(logits_scaled))
            loss = F.cross_entropy(logits_scaled, label)

            ave_loss.add(loss.item())
            acc = count_acc(logits_scaled, label)
            ave_acc.add(acc)
            '''print('batch {}: {:.2f}({:.2f})'.format(i, ave_acc.item() * 100, acc * 100))
            print('batch {}: {:.2f}'.format(i, ave_loss.item() ))'''
            x = None; p = None; logits = None
    accuracy_list.append(ave_acc.item()*100)
    loss_list.append(ave_loss.item())
    print(accuracy_list)
    #print(loss_list)

average_acc=sum(accuracy_list)/len(accuracy_list)
print('average_ACC:{}'.format(average_acc))
accuracy_list=[accuracy_list[i]-average_acc for i in range(len(accuracy_list))]
print('error:{}'.format(sum(np.array(accuracy_list)*np.array(accuracy_list))/(len(accuracy_list)-1.0)))


from django import template
from ..helpers import GOOGLE_SCORE_SCALE

register = template.Library()

##
##  Takes a score value and returns a category class name, used for coloring the circle.
##  Score ranges and categories directly from Lighthouse documentation:
##  https://developers.google.com/web/tools/lighthouse/v3/scoring
##  Periodically check above URL for changes in ranges.
##
@register.filter
def scoreClass(scoreValue=0):
    """
    Returns class name based on the score performance.
    """
    try:
        if scoreValue <= GOOGLE_SCORE_SCALE['poor']['max']:
            returnClass = "pl-poorscore"
        elif scoreValue <= GOOGLE_SCORE_SCALE['average']['max']:
            returnClass = "pl-avgscore"
        elif scoreValue >= GOOGLE_SCORE_SCALE['good']['min']:
            returnClass = "pl-goodscore"
        else:
            returnClass = ""
    except Exception as ex:
        returnClass = ""

    return returnClass


import os
from typing import *

import pandas as pd
import torch
from data.preprocessing import cleaning, del_stopword
from torch.utils.data import Dataset
from transformers import AutoTokenizer

class DatasetForHateSpeech(Dataset):
    def __init__(
        self,
        type: str,
        tokenizer: AutoTokenizer,
        path: str,
        config: Dict,
        version: str = "v1",
    ) -> None:
        """
        Arguments:
            - type : 데이터 종류 , keywords=(train, valid, test)
            - tokenizer : 토크나이저 종류
            - path: 데이터 경로
            - config: 각종 설정을 저장한 dict
            - version : 데이터 셋 버전

        Summary:
            Tokenizing 된 Hate Speech 데이터 셋 객체
        """
        self.path = os.path.join(path, f"{type}", f"data_{version}.tsv")
        self.data = pd.read_csv(self.path, sep="\t", encoding="utf-8")

        if "stopwords" in config["data"]["preprocessing"]:
            self.data["comments"] = del_stopword(self.data["comments"].tolist())
        if "cleaning" in config["data"]["preprocessing"]:
            self.data["comments"] = cleaning(self.data["comments"].tolist())

        self.tokenized_data = tokenizer(
            self.data["comments"].tolist(),  # Sentence
            return_tensors="pt",
            padding=True,
            return_token_type_ids=False,
            truncation=True,
            max_length=50,
            add_special_tokens=True,
        )
        self.labels = self.data["label"].tolist()

    def __getitem__(self, idx):
        item = {key: val[idx] for key, val in self.tokenized_data.items()}
        item["labels"] = torch.tensor(self.labels[idx])
        return item

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

class DatasetForSentimentSpeech(Dataset):
    def __init__(
        self,
        tokenizer: AutoTokenizer,
        path: str,
    ) -> None:
        """
        Arguments:
            - tokenizer : 토크나이저 종류
            - path : 데이터 저장된 경로
        Summary:
            Tokenizing 된 감성 분류 데이터 셋 객체
        """
        self.data = pd.read_csv(path)
        self.data = self.data.dropna(axis=0)

        self.tokenized_data = tokenizer(
            self.data["document"].tolist(),  # Sentence
            return_tensors="pt",
            padding=True,
            truncation=True,
            max_length=256,
            add_special_tokens=True,
        )

        self.labels = self.data["label"].tolist()

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

    def __getitem__(self, idx):
        item = {key: val[idx] for key, val in self.tokenized_data.items()}
        item["labels"] = self.labels[idx]
        return item


import telnetlib

def send_telnet_command(ip_address, port, command):
    try:
        # Membuat koneksi Telnet
        tn = telnetlib.Telnet(ip_address, port, timeout=5)

        # Mengirim perintah ke switcher
        tn.write(command.encode("ascii") + b"\r\n")

        # Membaca dan mencetak hasil (opsional)
        result = tn.read_until(b"\r\n", timeout=5).decode("utf-8")
        print(f"Result: {result}")

    except Exception as e:
        print(f"Error: {e}")

    finally:
        # Menutup koneksi Telnet
        tn.close()

def preset1():
    switcher_ip = "192.168.1.39"
    switcher_port = 5000
    switcher_command = "#VID 1>1"
    # Mengirim perintah Telnet
    send_telnet_command(switcher_ip, switcher_port, switcher_command)

def preset2():
    switcher_ip = "192.168.1.39"
    switcher_port = 5000
    switcher_command = "#VID 2>1"
    # Mengirim perintah Telnet
    send_telnet_command(switcher_ip, switcher_port, switcher_command)

def preset3():
    switcher_ip = "192.168.1.39"
    switcher_port = 5000
    switcher_command = "#VID 3>1"
    # Mengirim perintah Telnet
    send_telnet_command(switcher_ip, switcher_port, switcher_command)

def preset4():
    switcher_ip = "192.168.1.39"
    switcher_port = 5000
    switcher_command = "#VID 4>1"
    # Mengirim perintah Telnet
    send_telnet_command(switcher_ip, switcher_port, switcher_command)


def knn_model(tag):
	samples = [[0,1,0,1,1,0],[0,1,1,0,0,1],[1,0,1,0,0,1]]
	feature = ['new','old','high_price','low_price','Amenities<4','Amenities>=4']
	all_class = {0:[0,1,0,1,1,0],1:[0,1,1,0,0,1], 2:[1,0,1,0,0,1]}
	from sklearn.neighbors import NearestNeighbors
	neigh = NearestNeighbors(n_neighbors=1)
	neigh.fit(samples)
	simi, class_ = neigh.kneighbors(tag)
	if simi <= 2:
		return all_class[class_[0][0]]


from elasticsearch import Elasticsearch

#Instantiate Elasticsearch
es = Elasticsearch(HOST="http://localhost", PORT=9200)
es = Elasticsearch()

doc3 = {"sentence" : "Mesut Ozil is the great number 10"}
doc4 = {"sentence" : "Mesut Ozil is the one of greatest assist maker"}

es.index(index="english", id=3, body=doc3)
es.index(index="english", id=4, body=doc4)

res = es.search(index="english",
                body={"from": 0, "size": 1, "query": \
                        {"bool": \
                            {"must_not": \
                                {"match":{"sentence":"assist"}}, \
                                    "should":{"match": \
                                            {"sentence":"Mesut"} \
                                                                }}}})

print(res)