from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
import cv2
import math
from sklearn.preprocessing import LabelEncoder
import sys
import os
import random
#os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import tensorflow as tf
import logging
import seaborn as sns
from tensorflow.python.tools import inspect_checkpoint as chkp

sys.path.append('CNN')
import deepletters_cnn as model
#tf.logging.set_verbosity(tf.logging.ERROR)

class CNN():
    def __init__(self, absolute_root, learning_rate, resume, momentum, batch_size, start_epoch, epochs):
        self.glr = 0

        self.momentum = momentum

        self.learning_rate = learning_rate

        self.absolute_root = absolute_root

        self.resume = resume
        #/model/deephand_mean.npy
        self.mean_image = np.resize(np.load(absolute_root + '/CNN/mean_image.npy'), [227,227,3])

        self.log = logging.getLogger()
        self.log.setLevel(logging.DEBUG)

        self.batch_size = batch_size

        self.start_epoch = start_epoch

        self.epochs = epochs
        #self.secondary_lr = secondary_lr

    def create_graph(self, learning_rate=1e-2, mode="testing"):

        X = tf.placeholder(tf.float32, shape=(None, 227, 227, 3), name='inputs')
        y = tf.placeholder(tf.int64, [None], name='labels')

        dropout = tf.placeholder(tf.float32, shape=(), name='dropout')

        loss3_SLclassifier_1, loss2_SLclassifier_1, loss1_SLclassifier_1 = model.KitModel(weight_file = self.absolute_root + '/auto_gen/weights.npy',
                                                                                X=X, mode=mode)
        #mean_loss = tf.losses.softmax_cross_entropy(tf.one_hot(y, 24), y_out)

        values, indices = tf.nn.top_k(loss3_SLclassifier_1, 24)

        real_loss = tf.losses.softmax_cross_entropy(tf.one_hot(y, 24), loss3_SLclassifier_1)
        aux_loss2 = tf.losses.softmax_cross_entropy(tf.one_hot(y, 24), loss2_SLclassifier_1)
        aux_loss1 = tf.losses.softmax_cross_entropy(tf.one_hot(y, 24), loss1_SLclassifier_1)

        total_loss = real_loss + .3 * aux_loss2 + .3 * aux_loss1

        # vars = tf.trainable_variables()
        # vars = [v for v in vars if 'bias' not in v.name ]
        #
        # lossL2 = tf.add_n([ tf.nn.l2_loss(v) for v in vars
        #               if 'bias' not in v.name ]) * 0.005

        # l1_regularizer = tf.contrib.layers.l1_regularizer(
        #    scale=0.001, scope=None)
        # weights = tf.trainable_variables() # all vars of your graph
        # lossl1 = tf.contrib.layers.apply_regularization(l1_regularizer, vars)

        #total_loss = total_loss + lossL2
        #optimzer = tf.train.AdamOptimizer(learning_rate=learning_rate)
    #optimzer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=self.momentum, use_nesterov=True)
        # have tensorflow compute accuracy
        correct_prediction = tf.equal(tf.argmax(loss3_SLclassifier_1, 1), y)
        top_5_corr = tf.nn.in_top_k(predictions=loss3_SLclassifier_1, targets=y, k=5)

        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        top_5_acc = tf.metrics.mean(top_5_corr)

        confusion = tf.confusion_matrix(labels=y, predictions=tf.argmax(loss3_SLclassifier_1, 1), num_classes=24)

        extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
        with tf.control_dependencies(extra_update_ops):
            #Get only the last layers to train
            # FC1 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_4c/FC')
            # FC2 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'incpetion_5a/FC')
            # FC3 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/FC')
            # loss1_fc_1 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'loss1/fc_1')
            # loss2_fc_1 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'loss2/fc_1')
            # inception_5a_5x5 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5a/5x5')
            # inception_5a_3x3 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5a/3x3')
            # inception_5b_3x3_reduce = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/3x3_reduce')
            # inception_5b_5x5_reduce = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/5x5_reduce')
            # inception_5b_1x1 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/1x1')
            # inception_5b_pool_proj = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/pool_proj')
            # inception_5b_3x3 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/3x3')
            # inception_5b_5x5 = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'inception_5b/5x5')
            #
            # var_list=[FC1, FC2, FC3, loss1_fc_1, loss2_fc_1, inception_5a_5x5, inception_5a_3x3, inception_5b_3x3_reduce,
            #                                inception_5b_5x5_reduce, inception_5b_1x1, inception_5b_pool_proj, inception_5b_3x3, inception_5b_5x5]

            # vars_to_remove = ['inception_4c/FC/kernel:0', 'inception_4c/FC/bias:0', 'incpetion_5a/FC/kernel:0', 'incpetion_5a/FC/bias:0', 'loss1/fc_1/kernel:0', 'loss1/fc_1/bias:0', 'loss2/fc_1/kernel:0','loss2/fc_1/bias:0' ,'inception_5b/3x3_reduce_weight:0', 'inception_5b/3x3_reduce_bias:0',
            #                   'inception_5b/5x5_reduce_weight:0', 'inception_5b/5x5_reduce_bias:0', 'inception_5b/1x1_weight:0', 'inception_5b/1x1_bias:0', 'inception_5b/pool_proj_weight:0',
            #                   'inception_5b/pool_proj_bias:0', 'inception_5b/3x3_weight:0', 'inception_5b/3x3_bias:0', 'inception_5b/5x5_weight:0', 'inception_5b/5x5_bias:0', 'inception_5b/FC/kernel:0', 'inception_5b/FC/bias:0']
            # trainable_variables = tf.get_collection_ref(tf.GraphKeys.TRAINABLE_VARIABLES)
            # #self.log.info(tf.trainable_variables())
            # #self.log.info(trainable_variables)
            # for var in trainable_variables:
            #     #self.log.info('Var name: ' + var.name)
            #
            #     if var.name in vars_to_remove:
            #         trainable_variables.remove(var)
            #         #self.log.info("REMOVED VARIABLE: " + var.name)

            # train_step = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(total_loss, var_list=trainable_variables)
            # upper_train_step = tf.train.AdamOptimizer(learning_rate=.0001).minimize(total_loss, var_list=var_list)
            train_step = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(total_loss)
            upper_train_step = tf.constant([1])

        return loss3_SLclassifier_1, total_loss, train_step, correct_prediction, accuracy, X, y, top_5_corr, top_5_acc, confusion, upper_train_step, dropout
    def get_pictures(self, Xd, location):
        images = np.empty((Xd.shape[0], 227, 227, 3))
        #print(Xd)
        #print(location)
        for i in range(Xd.shape[0]):
            im = cv2.imread(location[i] + "/" + Xd[i])
            # x = random.randint(0, 256 - 227)
            # im = im[x:x+227, x:x+227]
            #
            # if random.random() < .5:
            #     im = cv2.flip(im, 0)
            #print(location[i] + "/" + Xd[i])
            images[i] = im
        assert not np.any(np.isnan(images))
        images = images - self.mean_image
        return images

    def run_model(self, session, predict, loss_val, Xd, yd,
                  epochs=1, batch_size=64, print_every=100,
                  training=None, plot_losses=False,
                  correct_prediction=None, accuracy=None, X=None, y=None, location=None, X_val=None, y_val=None, val_loc=None,
                  saver=None, top_5_correct_prediction=None, top_5_accuracy=None, confusion=None, classes=None, upper_train_step=None, dropout=None, dropout_val=1):

        val_losses = []
        val_accuracies = []
        overall_train_losses = []

        relative_root = None

        # shuffle indicies
        train_indicies = np.arange(Xd.shape[0])
        np.random.shuffle(train_indicies)

        training_now = training is not None

        # setting up variables we want to compute (and optimizing)
        # if we have a training function, add that to things we compute
        variables = [loss_val, correct_prediction, confusion, top_5_correct_prediction, top_5_accuracy]
        if training_now:
            variables[-1] = training
            if self.resume:
                pass
                #overall_train_losses = np.load(self.absolute_root + "/CNN/trained_networks/static_v2_lr-" + str(glr) + "/epoch-" + str(self.start_epoch) + "/static_v2_lr-" + str(glr) + "-overall_train_losses.npy").tolist()
                #overall_train_losses = np.load("C:/Riley/DeepLetters/CNN/trained_networks/one opt/static_v2_lr-1e-06/epoch-7/static_v2_lr-1e-06-overall_train_losses.npy").tolist()
                #val_losses = np.load("C:/Riley/DeepLetters/CNN/trained_networks/one opt/static_v2_lr-1e-06/epoch-7/static_v2_lr-1e-06-val_losses.npy").tolist()

                #val_losses = np.load(self.absolute_root + "/CNN/trained_networks/static_v2_lr-" + str(glr) + "/epoch-" + str(self.start_epoch) + "/static_v2_lr-" + str(glr) + "-val_losses.npy").tolist()

        #else:
           # variables.append(confusion)

        # counter
        iter_cnt = 0

        for e in range(self.start_epoch, epochs):
            # keep track of losses and accuracy
            correct = 0
            tot_top_5_correct = 0
            losses = []
            top_5_accuracies = []
            confusion_matricies = []
            # make sure we iterate over the dataset once
            for i in range(int(math.ceil(Xd.shape[0] / batch_size))):
                # generate indicies for the batch
                start_idx = (i * batch_size) % Xd.shape[0]
                idx = train_indicies[start_idx:start_idx + batch_size]

                # create a feed dictionary for this batch
                feed_dict = {X: self.get_pictures(Xd[idx], location[idx]),
                             y: yd[idx],
                             dropout: dropout_val}
                # get batch size
                actual_batch_size = yd[idx].shape[0]

                # print(actual_batch_size)confusion
                # have tensorflow compute loss and correct predictions
                # and (if given) perform a training step
                loss, corr, confusion_matrix, top_5_corr, top_5_acc = session.run(variables, feed_dict=feed_dict)
               # else:
                #    loss, corr, _, top_5_corr, top_5_acc, batch_confusion = session.run(variables, feed_dict=feed_dict)
                confusion_matricies.append(confusion_matrix)

                # aggregate performance stats
                losses.append(loss * actual_batch_size)

                correct += np.sum(corr)
                tot_top_5_correct += np.sum(top_5_corr)
                # print every now and then
                if training_now and (iter_cnt % print_every) == 0:
                    self.log.info("Iteration " + str(iter_cnt) + ": with minibatch training loss = " + str(loss) + ", an accuracy of " + str(np.sum(corr) / actual_batch_size) + " and a top-5 accuracy of " + str(np.sum(top_5_corr) / actual_batch_size))

                iter_cnt += 1

            relative_root = self.absolute_root + "/CNN/trained_networks/static_v2_lr-" + str(glr) + "/epoch-" + str(e + 1)

            confusion_matricies = np.array(confusion_matricies)
            if training_now:
                pass
                total_correct = correct / (Xd.shape[0]+1)
                epoch_loss = np.sum(losses) / (Xd.shape[0]+1)
                overall_train_losses.append(epoch_loss)
                epoch_top_5_acc = tot_top_5_correct / (Xd.shape[0]+1)
                total_confusion_matrix = np.sum(confusion_matricies) / (Xd.shape[0]+1)

                self.log.info("Epoch " + str(e + 1) + ", Overall loss = " + str(epoch_loss) + ", an accuracy of " + str(total_correct) + " and a top-5 accuracy of " + str(epoch_top_5_acc))
            else:
                total_correct = correct / Xd.shape[0]
                epoch_loss = np.sum(losses) / Xd.shape[0]
                overall_train_losses.append(epoch_loss)
                epoch_top_5_acc = tot_top_5_correct / Xd.shape[0]
                total_confusion_matrix = np.sum(confusion_matricies, axis=0)
                print(confusion_matricies[0])
                print(total_confusion_matrix.shape)

            if plot_losses and training_now is True:
                self.log.info('Validation-------------------------')
                os.mkdir(relative_root)

                cur_val_loss, cur_val_correct = self.run_model(session, predict=predict, loss_val=loss_val, Xd=X_val, yd=y_val,
                                  epochs=self.start_epoch+1, batch_size=self.batch_size, print_every=10000, training=None, plot_losses=True,
                                  correct_prediction=correct_prediction, accuracy=accuracy, X=X, y=y, location=val_loc, top_5_correct_prediction=top_5_correct_prediction,
                                  top_5_accuracy=top_5_accuracy, confusion=confusion, classes=classes, dropout=dropout, dropout_val=1)
                val_losses.append(cur_val_loss)
                val_accuracies.append(cur_val_correct)

                saver.save(session, relative_root + "/static_v2_lr-" + str(glr) + ".ckpt")

                plt.plot(overall_train_losses)
                plt.grid(True)
                plt.title('Epoch {} Loss'.format(e + 1))
                plt.xlabel('Epoch number')
                plt.ylabel('Epoch Loss')

                np.save(relative_root +"/static_v2_lr-" + str(glr) +"-overall_train_losses.npy", overall_train_losses)
                plt.savefig(relative_root +"/static_v2_lr-" + str(glr) +"-TRAIN.png")

                plt.clf()
                plt.plot(val_losses)
                plt.grid(True)
                plt.title('Epoch {} Loss'.format(e + 1))
                plt.xlabel('Validation run')
                plt.ylabel('Loss')

                np.save(relative_root +"/static_v2_lr-" + str(glr) +"-val_losses.npy", val_losses)
                plt.savefig(relative_root +"/static_v2_lr-" + str(glr) + "-VAL.png")
                plt.clf()

                #plt.show()
            if not training_now:
                self.log.info("Validation, Overall loss = " + str(epoch_loss) + ", an accuracy of " + str(total_correct)+ " and a top-5 accuracy of " + str(epoch_top_5_acc))
                total_confusion_matrix = pd.DataFrame(total_confusion_matrix, columns=classes, index=classes)
                total_confusion_matrix = total_confusion_matrix.div(total_confusion_matrix.sum(axis=1), axis=0)
                heatmap = sns.heatmap(total_confusion_matrix, cmap="Blues")
                heatmap.set_title('Test Confusion Matrix')
                heatmap.set_xlabel('Predicted Label')
                heatmap.set_ylabel('True Label')
                heatmap.set_yticklabels(heatmap.get_yticklabels(), rotation=0)
                heatmap = heatmap.get_figure()
                heatmap.savefig(relative_root +"/static_v2_lr-" + str(glr) + "-confusion_matrix.png")
                plt.clf()

        return overall_train_losses, total_correct

    def train(self):

                # tf.train.write_graph(sess.graph_def, 'CNN',
                #          'saved_model.pbtxt', as_text=True)
                # sess.run(tf.global_variables_initializer())
                #
                # tensor_info_x = tf.saved_model.utils.build_tensor_info(X)
                # tensor_info_y = tf.saved_model.utils.build_tensor_info(loss3_SLclassifier_1)
                #
                # table = tf.contrib.lookup.index_to_string_table_from_tensor(
                #     tf.constant(np.array(list('abcdefghiklmnopqrstuvwxy'))))
                #
                # classification_inputs = tf.saved_model.utils.build_tensor_info(
                #       X)
                # classification_outputs_classes = tf.saved_model.utils.build_tensor_info(
                #       table.lookup(tf.to_int64(indices)))
                # classification_outputs_scores = tf.saved_model.utils.build_tensor_info(values)
                #
                # classification_signature = (
                #     tf.saved_model.signature_def_utils.build_signature_def(
                #     inputs={
                #     tf.saved_model.signature_constants.CLASSIFY_INPUTS:
                #           classification_inputs
                #   },
                #   outputs={
                #       tf.saved_model.signature_constants.CLASSIFY_OUTPUT_CLASSES:
                #           classification_outputs_classes,
                #       tf.saved_model.signature_constants.CLASSIFY_OUTPUT_SCORES:
                #           classification_outputs_scores
                #   },
                #   method_name=tf.saved_model.signature_constants.CLASSIFY_METHOD_NAME))
                #
                # prediction_signature = (
                #       tf.saved_model.signature_def_utils.build_signature_def(
                #           inputs={'images': tensor_info_x},
                #           outputs={'scores': tensor_info_y},
                #           method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))
                #
                #
                # builder = tf.saved_model.builder.SavedModelBuilder('CNN/saved_model_v2.pb')
                # builder.add_meta_graph_and_variables(
                # sess,
                # [tf.saved_model.tag_constants.SERVING],
                # signature_def_map= {
                #     'train':
                #         prediction_signature,
                #     tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
                #         classification_signature,
                #     },
                # main_op=tf.tables_initializer(),
                # strip_default_attrs=True)
                #
                # builder.save()
        data = pd.read_csv(self.absolute_root + '/227X227_new_images.csv')
        # idx = []
        # for index, row in data.iterrows():
        #     if 'Outside' not in row['file_name']:
        #         idx.append(index)
        #
        # data = data.drop(idx)
        #
        # data.reset_index(drop=True, inplace=True)

        print(data)

        X_data = np.array(data['file_name'])
        y_data = np.array(data['Letter'])
        location = np.array(data['dir_name'])

        label_encoder = LabelEncoder()
        #'Part5', 'Part2', 'Part3', 'part4','Part1'
        #'C', 'B', 'D', 'A', 'Part5', 'Part2', 'Part3', 'part4', 'user_3', 'user_4', 'user_5', 'user_6', 'user_7', 'user_9', 'user_10', 'Part1'
        train_signers = []
        test_signers = ['cropped_test']

        X_train = data.loc[data['dir_name'].isin(train_signers)]['file_name'].values
        y_train = data.loc[data['dir_name'].isin(train_signers)]['Letter'].values
        y_train = label_encoder.fit_transform(y_train)
        train_loc = data.loc[data['dir_name'].isin(train_signers)]['root'].values

        X_val = data.loc[data['dir_name'].isin(test_signers)]['file_name'].values
        y_val = data.loc[data['dir_name'].isin(test_signers)]['Letter'].values
        y_val = label_encoder.fit_transform(y_val)
        val_loc = data.loc[data['dir_name'].isin(test_signers)]['root'].values

        print(dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_))))

        print(X_val)
        print(val_loc)
        #print(X_train)
        # X_train = np.concatenate((X_data[:26445], X_data[39838:67209]))
        #
        # label_encoder = LabelEncoder()
        # y_train = label_encoder.fit_transform(np.concatenate((y_data[:26445], y_data[39838:67209])))
        # train_loc = np.concatenate((location[:26445], location[39838:67209]))
        #
        # #65773
        # X_val = np.concatenate((X_data[26445:39838], X_data[67209:]))
        # y_val = label_encoder.fit_transform(np.concatenate((y_data[26445:39838], y_data[67209:])))
        # val_loc = np.concatenate((location[26445:39838],location[67209:]))

        for lr in self.learning_rate:
            with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)) as sess:

                with tf.device("/device:GPU:0"):  # "/cpu:0" or "/gpu:0"
                    global glr
                    relative_root = self.absolute_root + "/CNN/trained_networks/static_v2_lr-" + str(lr)

                    glr = lr
                    if self.resume is False:
                        os.mkdir(relative_root)
                    if self.resume and os.path.isdir(relative_root) is False:
                        os.mkdir(relative_root)

                    fileh = logging.FileHandler(relative_root + "/static_v2_lr-" + str(lr) + ".txt", "a+")
                    fileh.setFormatter(logging.Formatter("%(asctime)-15s %(levelname)-8s %(message)s"))
                    fileh.setLevel(logging.INFO)

                    self.log.handlers = [fileh]
                    #log.addHandler(fileh)
                    #log.info('test')

                    with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE) as scope:

                        loss3_SLclassifier_1, total_loss, train_step, correct_prediction, accuracy, X, y, top_5_corr, top_5_acc, confusion, upper_train_step, dropout = self.create_graph(lr, mode="training")

                        saver = tf.train.Saver()

                        sess.run(tf.local_variables_initializer())

                        if self.resume:
                            self.log.info("ENTERED RESUME")
                            saver.restore(sess=sess, save_path="CNN/trained_networks/OG CNN/one opt/static_v2_lr-1e-06/epoch-7/static_v2_lr-1e-06.ckpt")
                            #chkp.print_tensors_in_checkpoint_file(relative_root + "/epoch-20/static_v2_lr-" + str(lr) + ".ckpt", tensor_name='', all_tensors=True)

                            # reader = tf.train.NewCheckpointReader(relative_root + "/epoch-20/static_v2_lr-" + str(lr) + ".ckpt")
                            # restore_dict = dict()
                            # for v in tf.trainable_variables():
                            #   tensor_name = v.name.split(':')[0]
                            #   if reader.has_tensor(tensor_name):
                            #     self.log.info('has tensor ', tensor_name)
                            #     restore_dict[tensor_name] = v
                            #
                            # saver = tf.train.Saver(restore_dict)
                            # sess.run(tf.local_variables_initializer())
                            # saver.restore(sess=sess, save_path=relative_root + "/epoch-50/static_v2_lr-" + str(lr) + ".ckpt")
                            #
                            # is_not_initialized   = sess.run([tf.is_variable_initialized(var) for var in tf.global_variables()])
                            # not_initialized_vars = [v for (v, f) in zip(tf.global_variables(), is_not_initialized) if not f]
                            # self.log.info("NON INITIALIZED VARIABLES" + str(not_initialized_vars))
                            # sess.run(tf.initialize_variables(not_initialized_vars))

                        else:
                            sess.run(tf.global_variables_initializer())

                        self.log.info('Training')

                        self.run_model(sess, predict=loss3_SLclassifier_1, loss_val=total_loss, Xd=X_train, yd=y_train,
                                  epochs=self.start_epoch + self.epochs, batch_size=self.batch_size, print_every=100, training=train_step, plot_losses=True,
                                  correct_prediction=correct_prediction, accuracy=accuracy, X=X, y=y, location=train_loc, X_val=X_val, y_val=y_val, val_loc=val_loc, saver=saver,
                                  top_5_correct_prediction=top_5_corr, top_5_accuracy=top_5_acc, confusion=confusion, classes=list(label_encoder.classes_), upper_train_step=upper_train_step, dropout=dropout)

                        #self.run_model(sess, loss3_SLclassifier_1, total_loss, X_train, y_train, 500, 128, 100, train_step, True, correct_prediction, accuracy, X, y, train_loc)

                        #saver.save(sess, relative_root + "/final/static_v2_lr-" + str(lr) + ".ckpt")

                        #self.log.info('Validation')
                        #loss3_SLclassifier_1, total_loss, train_step, correct_prediction, accuracy, X, y = create_graph(lr, False)
                        #scope.reuse_variables()


#!/usr/bin/env python3
import asyncio, aiohttp
import concurrent.futures
import random, struct
import argparse, logging
import dns.message
import dns.resolver
import time
import requests
import hyper
import urllib.parse
import aioh2
import ssl

# Attempt to use uvloop if installed for extra performance
try:
	import uvloop
	asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError:
	pass

# Handle command line arguments
parser = argparse.ArgumentParser()
parser.add_argument('-a', '--listen-address', default='127.0.0.1',
					help='address to listen on for DNS over HTTPS requests (default: %(default)s)')
parser.add_argument('-p', '--listen-port', type=int, default=53,
					help='port to listen on for DNS over HTTPS requests (default: %(default)s)')
parser.add_argument('-u', '--upstreams', nargs='+', default=['https://1.1.1.1/dns-query', 'https://1.0.0.1/dns-query'],
					help='upstream servers to forward DNS queries and requests to (default: %(default)s)')
parser.add_argument('-t', '--tcp', action='store_true', default=False,
					help='serve TCP based queries and requests along with UDP (default: %(default)s)')
parser.add_argument('--no-cache', action='store_true', default=False,
					help='don\'t cache answers from upstream servers (default: %(default)s)')
parser.add_argument('--active-cache', action='store_true', default=False,
					help='actively replace expired entries by making autonomous requests to the upstream servers (default: %(default)s)')
args = parser.parse_args()

host = args.listen_address
port = args.listen_port
upstreams = args.upstreams
headers = {'accept': 'application/dns-message', 'content-type': 'application/dns-message'}

def main():
	# Setup logging
	logging.basicConfig(level='INFO', format='[%(levelname)s] %(message)s')

	# Setup event loop
	loop = asyncio.get_event_loop()
	# executor = concurrent.futures.ProcessPoolExecutor(max_workers=4)
	# executor = concurrent.futures.ThreadPoolExecutor(max_workers=1000)
	# loop.set_default_executor(executor)

	# Connect to upstream servers
	logging.info('Connecting to upstream servers: %r' % (upstreams))
	resolver = DohResolver(cache=dns.resolver.LRUCache(50000))
	# resolver.connect([(upstream, headers) for upstream in upstreams])
	loop.run_until_complete(resolver.connect([(upstream, headers) for upstream in upstreams]))

	# Setup UDP server
	logging.info('Starting UDP server listening on: %s#%d' % (host, port))
	udp_listen = loop.create_datagram_endpoint(lambda: UdpDohProtocol(resolver), local_addr = (host, port))
	udp, protocol = loop.run_until_complete(udp_listen)

	# Setup TCP server
	if args.tcp:
		logging.info('Starting TCP server listening on %s#%d' % (host, port))
		tcp_listen = loop.create_server(lambda: TcpDohProtocol(resolver), host, port)
		tcp = loop.run_until_complete(tcp_listen)

	# Setup cache worker
	if args.active_cache:
		asyncio.ensure_future(resolver.worker(10))

	# Serve forever
	try:
		loop.run_forever()
	except (KeyboardInterrupt, SystemExit):
		pass

	# Close upstream connections
	# resolver.close()
	loop.run_until_complete(resolver.close())

	# Close listening servers and event loop
	udp.close()
	if args.tcp:
		tcp.close()

	loop.close()

class UdpDohProtocol(asyncio.DatagramProtocol):
	"""
	DNS over HTTPS UDP protocol to use with asyncio.
	"""

	def __init__(self, resolver):
		self.resolver = resolver
		self.loop = asyncio.get_event_loop()
		super().__init__()

	def connection_made(self, transport):
		self.transport = transport

	def datagram_received(self, data, addr):
		asyncio.ensure_future(self.process_packet(data, addr))

	def error_received(self, exc):
		logging.warning('Minor transport error')

	async def process_packet(self, query, addr):
		# Await upstream forwarding coroutine
		# answer = await self.loop.run_in_executor(None, self.resolver.forward, query)
		# answer = self.resolver.resolve(query)
		# answer = await self.loop.run_in_executor(None, forward, 'https://1.1.1.1/dns-query', query, headers)
		answer = await self.resolver.resolve(query)

		# TODO: try loop.run_in_executor(ProcessPool, resolver, query)

		# Send DNS packet to client
		self.transport.sendto(answer, addr)

def forward(upstream, query, headers):
	while True:
		response = requests.post(upstream, data=query, headers=headers)
		if response.status_code == 200:
			return response.content

class TcpDohProtocol(asyncio.Protocol):
	"""
	DNS over HTTPS TCP protocol to use with asyncio.
	"""

	def __init__(self, resolver):
		self.resolver = resolver
		super().__init__()

	def connection_made(self, transport):
		self.transport = transport

	def data_received(self, data):
		asyncio.ensure_future(self.process_packet(data))

	def eof_received(self):
		if self.transport.can_write_eof():
			self.transport.write_eof()

	def connection_lost(self, exc):
		self.transport.close()

	async def process_packet(self, query):
		# Await upstream forwarding coroutine (remove 16-bit length prefix)
		answer = await self.resolver.resolve(query[2:])

		# Send DNS packet to client (add 16-bit length prefix)
		self.transport.write(struct.pack('! H', len(data)) + data)

class DohConnAioh2:
	def __init__(self, upstream, headers):
		self.url = urllib.parse.urlparse(upstream)
		self.headers = headers
		self.conn = None
		self.rtt = None

	async def connect(self):
		self.conn = await aioh2.open_connection(self.url.netloc, 443, ssl=ssl.create_default_context(), functional_timeout=0.2)
		await asyncio.sleep(0.2)
		print(self.conn._transport)

	async def close(self):
		self.conn.close_connection()
		await asyncio.sleep(0.1)

	async def request(self, data, headers=None, end_stream=False):
		if not headers:
			headers = {':method': 'POST', ':path': self.url.path}

		self.rtt = await self.conn.wait_functional()
		sid = await self.conn.start_request({**self.headers, **headers})
		await self.conn.send_data(sid, data, end_stream=end_stream)
		return sid

class DohConn:
	"""
	DNS over HTTPS upstream connection class.
	"""

	def __init__(self, upstream, headers):
		self.url = urllib.parse.urlparse(upstream)
		self.headers = headers
		self.conn = None

	def connect(self):
		self.conn = hyper.HTTP20Connection(self.url.netloc, port=443, secure=True)
		self.conn.connect()

	def close(self):
		self.conn.close()

	def request(self, method, body=None, headers=None):
		if not headers:
			headers = self.headers

		return self.conn.request(method, self.url.path, body=body, headers=headers)

	def response(self, sid=None):
		return self.conn.get_response(stream_id=sid)

class DohResolver:
	"""
	DNS over HTTPS resolver class.
	"""

	def __init__(self, cache=None):
		self.conns = []
		self.cache = cache

	async def connect(self, upstreams):
		"""
		Prepare connection object corresponding to upstream servers.
		"""

		for (url, headers) in upstreams:
			# connection = DohConn(url, headers)
			# connection.connect()
			connection = DohConnAioh2(url, headers)
			await connection.connect()
			self.conns.append(connection)

	async def close(self):
		"""
		Close connection to upstream server.
		"""

		for conn in self.conns:
			# conn.close()
			await conn.close()

	async def resolve(self, query, update=False):
		"""
		Resolve a DNS query using a cache or upstream server.

		Params:
			query  - normal wireformat DNS query
			update - only update cache entry for this query

		Returns:
			A normal wireformat DNS answer.
		"""

		# Check cache if necessary
		if self.cache and not update:
			# Convert wireformat to message object
			request = dns.message.from_wire(query)
			id = request.id
			request = request.question[0]
			request = (request.name, request.rdtype, request.rdclass)

			# Return cached entry if possible
			cached = self.cache.get(request)
			if cached:
				cached.response.id = id
				answer = cached.response.to_wire()
				return answer

		# Resolve via upstream server
		# answer = self.forward(query)
		answer = await self.forward_aioh2(query)

		# Add answer to cache if necessary
		if self.cache:
			if update:
				# Convert wireformat to message object
				request = dns.message.from_wire(query)
				id = request.id
				request = request.question[0]
				request = (request.name, request.rdtype, request.rdclass)

			response = dns.message.from_wire(answer)
			response = dns.resolver.Answer(*request, response, False)
			self.cache.put(request, response)

		return answer

	def forward(self, query):
		"""
		Perform DNS over HTTPS lookup using POST method.

		Params:
			query - normal wireformat DNS query

		Returns:
			A normal wireformat DNS answer.

		Notes:
			Using DNS over HTTPS POST format as described here:
			https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-12
			https://developers.cloudflare.com/1.1.1.1/dns-over-https/wireformat/
		"""

		# Await upstream response
		index = 0
		while True:
			sid = self.conns[index].request('POST', body=query)
			http = self.conns[index].response(sid=sid)

			if http.status == 200:
				return http.read()

			index = (index + 1) % len(self.conns)

	async def forward_aioh2(self, query):
		index = 0
		while True:
			conn = self.conns[index]
			sid = await conn.request(query, end_stream=True)
			http = await conn.conn.recv_response(sid)
			print(http)
			return await conn.conn.read_stream(sid, -1)

	async def worker(self, period, max=1000):
		"""
		Worker to process cache entries and preemptively replace expiring entries.

		Params:
			period - time to wait between cache scans (in seconds)
			max    - maximum number of concurrent autonomous requests (0 means unlimited)

		"""

		while True:
			expiring = 0

			for request, response in self.cache.data.items():
				if response.value.expiration > (time.time() + period):
					continue

				query = dns.message.make_query(*request).to_wire()
				asyncio.ensure_future(self.resolve(query, True))
				expiring += 1

				if max and expiring >= max:
					break

			if expiring > 0:
				logging.info('Cache, updating %d/%d' % (expiring, len(self.cache.data)))

			await asyncio.sleep(period)

if __name__ == '__main__':
	main()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Computer',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('computer_name', models.CharField(help_text=b'\xe4\xb8\xbb\xe6\x9c\xba\xe5\x90\x8d', max_length=100)),
                ('config', models.TextField(help_text=b'\xe4\xb8\xbb\xe6\x9c\xba\xe9\x85\x8d\xe7\xbd\xae')),
            ],
            options={
            },
            bases=(models.Model,),
        ),
    ]


# Gra "Wieże Hanoi" napisana w języku Python 3 z wykorzystaniem biblioteki PyGame

import sys, pygame

# inicjalizacja modułów

pygame.init()
pygame.mixer.init()

# stałe

WIDTHsc = 1280
HEIGHTsc = 720
FPS = 60
WIDTH_TOWER = 20
HEIGHT_TOWER = 100

# tytuł gry

GAME_TITLE = 'Wieże Hanoi'

# okno głowne
GAME_SURFACE = pygame.display.set_mode((WIDTHsc, HEIGHTsc))

# tytuł
pygame.display.set_caption('Wieże Hanoi')

# stałe dla kolorów
class Palette:
    def __init__(self):

        self.GREEN = (110, 111, 47)
        self.BLACK = (0, 0, 0)
        self.WHITE = (255, 255, 255)
        self.BROWN = (139, 69, 19)

# obiekt klasy Palette
col = Palette()

while True:

     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             sys.exit(0)
           #kolor tla
        #GAME_SURFACE.fill(col.GREEN)
     tlo = pygame.image.load("IMG_2012png.png").convert()
        # pobieramy informacje o ekranie - tle
     screen = pygame.display.get_surface()

#wieże
     wieza1 = pygame.draw.rect(tlo, col.BROWN, pygame.Rect(310,500,15,170))
     wieza2 = pygame.draw.rect(tlo, col.BROWN, pygame.Rect(620, 500, 15, 170))
     wieza3 = pygame.draw.rect(tlo, col.BROWN, pygame.Rect(930, 500, 15, 170))

        # przypisanie grafiki do określonego miejsca ekranu
     screen.blit(tlo, (0, 0))

     pygame.display.flip()
        #pygame.display.update()


# Copyright (c) Gorilla-Lab. All rights reserved.
from ipdb import set_trace
import numpy as np

import torch
from torch.cuda.amp import autocast as autocast, GradScaler

from gorilla.utils import Timer

from solver import solver_IterLNL
from utils import to_cuda
from losses import SmoothCELoss

class SolverLS(solver_IterLNL):
    # NOTE: After a source model is trained, put its filepath into the dict below
    source_models = {
        "VisDA2017_T2V": "models/source_models/VisDA2017_T2V_resnet101_seed_0_lr_0.0003_ep_3_gamma_0.0003/best_model.pth.tar",  # ResNet101
    }

    def __init__(self, model, dataloaders, evaluator, cfg):
        # NOTE: use BaseSolver's init function, not use solver_IterLNL one
        super(solver_IterLNL, self).__init__(model, dataloaders, cfg)
        if self.cfg.distributed:
            # self.model will be used in model forward and backward, and
            # self._model will be used as `self.model` in other situation of not paralleled version
            self._model = self.model.module
        else:
            self._model = self.model
        # NOTE: currently it is not ensured reliable to run amp and DDP simultaneously
        if self.cfg.amp:
            self.scaler = GradScaler()

        self.evaluator = evaluator
        self.criterions = {"SmoothCELoss": SmoothCELoss(self.cfg.label_smooth, self.cfg.num_classes),
                           }
        self.best_acc = 0  # best acc in a loop
        self.loop = -1
        self.best_epoch = -1
        self.timer = Timer()

        self.pseudo_labels_prev = np.zeros(len(self.dataloaders["train_tgt_no_drop"].dataset))  # record pseudo_labels in previous loop

        # KD do not need warmup, here just keep the change from iterlnl code as less as possible
        self.cfg.max_iters = self.cfg.max_epochs * self.iters_per_epoch
        self.warmup_iters = self.cfg.warmup_epochs * self.iters_per_epoch
        self.actual_max_iters = int(self.cfg.max_iters + self.warmup_iters)

        self.start_loop = -1

    def solve(self):
        self.train_first_source_model()
        # self.evaluate()
        self.get_pseudo_label_of_target_data()
        self.train_a_new_target_model()

        with open("log/summary.log", "a") as fp:
            fp.write(f"{self.cfg.log_dir}: acc {self.acc:.2f} best {self.best_acc:.2f} in epoch {self.best_epoch}\n")

    def get_pseudo_label_of_target_data(self):
        self.model.eval()
        logits = torch.zeros(len(self.dataloaders["train_tgt_no_drop"].dataset), self.cfg.num_classes).cuda()  # .cuda(): 20M gpu memory for 3s faster
        batch_size = self.dataloaders["train_tgt_no_drop"].batch_size
        filepaths = []
        for i, data in enumerate(self.dataloaders["train_tgt_no_drop"]):
            target_data, filepath = data["img"], data["path"]
            if torch.cuda.is_available():
                target_data = target_data.cuda()
            with torch.no_grad():
                logit = self.model(target_data)["cate"]
            logits[i * batch_size: i * batch_size + logit.size(0), :] = logit
            filepaths += filepath
        soft_label = torch.softmax(logits, dim=1)
        _, pseudo_labels = torch.max(soft_label, dim=1)
        pseudo_labels = pseudo_labels.cpu().numpy()

        ## update the noisy labels of target data.
        if self.cfg.dataset == "Digit":
            self.dataloaders["train_tgt"].dataset.reload(pseudo_labels)
        else:
            self.dataloaders["train_tgt"].dataset.paths = filepaths
            self.dataloaders["train_tgt"].dataset.targets = pseudo_labels
        # NOTE: it is necessary to iter(dataloaders) at once for immediately apply the changes of dataset
        data_iterator = iter(self.dataloaders["train_tgt"])
        self.data_iterators["train_tgt"] = data_iterator

    def train_a_new_target_model(self):
        # reset model parameters
        if self.cfg.not_pretrain:
            self.reset_params(self._model.G)
        else:
            self.load_pretrained_dict(self._model.G)
        self.reset_params(self._model.F)

        self.best_acc = 0
        self.epoch = 0

        self.model.train()
        # reset lr_scheduler
        self.lr_scheduler.last_epoch = 0
        self.lr_scheduler.step()

        self.actual_max_iters = int(self.cfg.max_iters + self.warmup_iters)
        self.log_buffer.clear()
        for self.iter in range(1, self.actual_max_iters + 1):
            # self.logger.info(f"Iter {self.iter}")
            # check_rand_state(self.logger)
            self.timer.reset()

            # self.logger.info("before get_samples...")
            samples = self.get_samples("train_tgt")
            # self.logger.info("after get_samples...")
            # idx is used in distillation loss
            data, gt, idx = samples["img"], samples["target"], samples["idx"]
            # display("data", data)

            batch_size = data.size(0)

            data = to_cuda(data)
            gt = to_cuda(gt)

            self.log_buffer.update({"data_time": self.timer.since_start()})

            # manually call __enter__() and __exit__() to replace 'with' statement and only write code block once
            if self.cfg.amp:
                _autocast = autocast()
                _autocast.__enter__()

            logit = self.model(data)["cate"]
            # compute the category loss of feature_source
            loss_C = self.criterions["SmoothCELoss"](logit, gt)
            # NOTE: we need to maximize loss_GD, so its symbol is negative
            loss_total = loss_C
            self.optimizer.zero_grad()

            if self.cfg.amp:
                _autocast.__exit__()
                self.scaler.scale(loss_total).backward()
                self.scaler.unscale_(self.optimizer)
                self.scaler.step(self.optimizer)
                self.scaler.update()
            else:
                loss_total.backward()
                self.optimizer.step()

            self.log_buffer.update({
                "train/loss/total": loss_total.item()})
            self.evaluator.process(logit, gt)

            self.log_buffer.update({"batch_time": self.timer.since_start()})
            self.lr_scheduler.step()

            if self.iter % self.cfg.log_interval == 0:
                self.acc = self.evaluator.evaluate()["acc"]  # become a member for using self.write()
                self.evaluator.reset()

                self.log_buffer.average(self.cfg.log_interval)
                self.write("train")

            if self.iter % self.cfg.save_interval == 0:
                self.save("latest_model", meta=dict(loop=self.loop,
                                                    iters=self.iter))

            if self.iter % self.iters_per_epoch == 0:
                self.logger.info("lr after epoch {}:".format(self.epoch+1))
                for group in self.optimizer.param_groups:
                    self.logger.info(group["lr"])

                self.epoch += 1

            if self.iter % self.cfg.test_interval == 0:
                self.evaluate()
                self.model.train()

    def write(self, mode):
        r"""
        Write infos into log file and tensorboard.
        mode can be 'train' or 'eval'.
        """
        if mode == "train":
            out_tmp = self.log_buffer.output
            log_string = ("Tr loop {}  ep [{}/{}]  it [{}/{}]  BT {:.3f}  DT {:.3f}   acc {:.3f}\n"
                            "loss_total {:.3f}\n").format(
                        self.loop+1, self.epoch+1, self.max_epochs+self.cfg.warmup_epochs, self.iter, self.actual_max_iters,
                        out_tmp["batch_time"], out_tmp["data_time"], self.acc,
                        out_tmp["train/loss/total"])

            self.logger.info(log_string)

            super(solver_IterLNL, self).write()

        elif mode == "eval":
            print_string = ("Te it [{}/{}]  Time {:.3f}   "
                            "Target acc {:.3f}  Best acc so far {:.3f} in epoch {}").format(
                                self.iter, self.actual_max_iters,
                                self.timer.since_last(),
                                self.acc, self.best_acc, self.best_epoch)
            self.logger.info(print_string + "\n")
            self.tb_writer.add_scalars(
                "acc", {
                    "test": self.acc,
                    "best_acc": self.best_acc
                }, self.iter)

        else:
            raise NotImplementedError("mode: {} for Solver.write()".format(mode))


# -*- coding: utf-8 -*-
#!/usr/bin/python3
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from dateutil.relativedelta import relativedelta
import logging

_intervalTypes = {
    'work_days': lambda interval: relativedelta(days=interval),
    'days': lambda interval: relativedelta(days=interval),
    'hours': lambda interval: relativedelta(hours=interval),
    'weeks': lambda interval: relativedelta(days=7*interval),
    'months': lambda interval: relativedelta(months=interval),
    'minutes': lambda interval: relativedelta(minutes=interval),
}

from odoo.exceptions import Warning
from datetime import datetime

try:
    import simplejson as json
except ImportError:
    import json     # noqa

from odoo.release import serie
from odoo.tools.translate import _

_logger = logging.getLogger(__name__)

from odoo import models,fields,api,_

class ebay_instance_conf_installer(models.TransientModel):
    _name = 'ebay.instance.conf.installer'
    _inherit = 'res.config.installer'

    name = fields.Char("Instance Name")
    warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse')
    dev_id = fields.Char('Dev ID',size=256,help="Dev ID")
    app_id = fields.Char('App ID',size=256,help="App ID")
    cert_id = fields.Char('Cert ID',size=256,help="Cert ID")
    server_url = fields.Char('Server URL',size=256,help="eBay Server URL")
    environment = fields.Selection([('is_sandbox', 'Sandbox'),('is_production', 'Production')],'Environment')
    auth_token = fields.Text('Token',help="eBay Token")
    country_id = fields.Many2one('res.country',string = "Country")

    @api.onchange('environment')
    def onchange_environment(self):
        if self.environment == 'is_sandbox':
            self.server_url = 'https://api.sandbox.ebay.com/ws/api.dll'
        else:
            self.server_url = 'https://api.ebay.com/ws/api.dll'

    @api.multi
    def execute(self):
        self.env['ebay.instance.ept'].create({'name':self.name,
                                         'dev_id':self.dev_id,
                                         'app_id':self.app_id,
                                         'cert_id':self.cert_id,
                                         'server_url':self.server_url,
                                         'environment':self.environment,
                                         'auth_token':self.auth_token,
                                         'country_id':self.country_id.id,
                                         'warehouse_id':self.warehouse_id.id,
                                         })
        return super(ebay_instance_conf_installer, self).execute()

class ebay_instance_general_conf_installer(models.TransientModel):
    _name = 'ebay.instance.general.conf.installer'
    _inherit = 'res.config.installer'

    @api.model
    def _default_instance(self):
        instances = self.env['ebay.instance.ept'].search([])
        return instances and instances[0].id or False

    instance_id = fields.Many2one('ebay.instance.ept', 'Instance', default=_default_instance)
    warehouse_id = fields.Many2one('stock.warehouse',string = "Warehouse")
    partner_id = fields.Many2one('res.partner', string='Default Customer')
    country_id = fields.Many2one('res.country',string = "Country")
    lang_id = fields.Many2one('res.lang', string='Language')
    order_prefix = fields.Char(size=10, string='Order Prefix')
    price_tax_included = fields.Boolean(string='Is Price Tax Included?')
    tax_id = fields.Many2one('account.tax', string='Default Sales Tax')

    order_auto_import = fields.Boolean(string='Auto Order Import?')
    order_import_interval_number = fields.Integer('Import Order Interval Number',help="Repeat every x.")
    order_import_interval_type = fields.Selection( [('minutes', 'Minutes'),
            ('hours','Hours'), ('work_days','Work Days'), ('days', 'Days'),('weeks', 'Weeks'), ('months', 'Months')], 'Import Order Interval Unit')
    order_import_next_execution = fields.Datetime('Next Execution', help='Next execution time')

    ebay_order_auto_update=fields.Boolean(string="Auto Order Update ?")
    order_update_interval_number = fields.Integer('Update Order Interval Number',help="Repeat every x.")
    order_update_interval_type = fields.Selection( [('minutes', 'Minutes'),
            ('hours','Hours'), ('work_days','Work Days'), ('days', 'Days'),('weeks', 'Weeks'), ('months', 'Months')], 'Update Order Interval Unit')
    order_update_next_execution = fields.Datetime('Next Execution', help='Next execution time')

    stock_auto_export=fields.Boolean(string="Stock Auto Export?")
    update_stock_interval_number = fields.Integer('Update Order Interval Number',help="Repeat every x.")
    update_stock_interval_type = fields.Selection( [('minutes', 'Minutes'),
            ('hours','Hours'), ('work_days','Work Days'), ('days', 'Days'),('weeks', 'Weeks'), ('months', 'Months')], 'Update Order Interval Unit')
    update_stock_next_execution = fields.Datetime('Next Execution', help='Next execution time')

    auto_update_payment=fields.Boolean(string="Auto Update Payment On invoice paid ?")
    ebay_default_product_category_id = fields.Many2one('product.category','Default Product Category')
    stock_field = fields.Many2one('ir.model.fields', string='Stock Field')
    pay_mthd = fields.Selection([('PayPal', 'PayPal'),('PaisaPay', 'PaisaPay')],'Payment Methods',help="Method of Payment")
    email_add = fields.Char('Email Address', size=126,help="Seller Email Address")
    site_id = fields.Many2one('ebay.site.details','Site')
    pricelist_id = fields.Many2one('product.pricelist', string='Pricelist')
    shipment_charge_product_id=fields.Many2one("product.product","Shipment Fee",domain=[('type','=','service')])
    create_new_product=fields.Boolean("Auto Create New Product",default=False)
    create_quotation_without_product=fields.Boolean("Create Quotation Without Product",default=False)
    fiscal_position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position')
    team_id=fields.Many2one('crm.team', 'Sales Team',oldname='section_id')
    post_code = fields.Char('Postal Code',size=64,help="Enter the Postal Code for Item Location")
    company_id=fields.Many2one('res.company',string="Company")
    discount_charge_product_id=fields.Many2one("product.product","Order Discount",domain=[('type','=','service')])
    ebay_plus=fields.Boolean("Is eBay Plus Account",default=False)
    order_import_user_id = fields.Many2one('res.users',string="User",help='User')
    order_status_update_user_id = fields.Many2one('res.users',string="User",help='User')
    stock_update_user_id = fields.Many2one('res.users',string="User",help='User')

    use_dynamic_desc = fields.Boolean("Use Dynamic Description Template", help='If ticked then you can able to use dynamic product description for an individual product only.')
    fetch_token_boolean = fields.Boolean(string='Fetch Token Boolean',related='instance_id.fetch_token_boolean', store=False)

    @api.onchange('instance_id')
    def onchange_instance_id(self):
        values = {}
        context = dict(self._context or {})
        instance = self.instance_id or False
        self.price_tax_included= instance and instance.price_tax_included or False
        self.warehouse_id = instance and instance.warehouse_id and instance.warehouse_id.id or False
        self.lang_id = instance and instance.lang_id and instance.lang_id.id or False
        self.order_prefix = instance and instance.order_prefix and instance.order_prefix
        self.stock_field = instance and instance.stock_field and instance.stock_field.id or False
        self.pricelist_id = instance and instance.pricelist_id and instance.pricelist_id.id or False
        self.fiscal_position_id = instance and instance.fiscal_position_id and instance.fiscal_position_id.id or False
        self.order_auto_import=instance and instance.order_auto_import
        self.stock_auto_export=instance and instance.stock_auto_export
        self.ebay_order_auto_update=instance and instance.ebay_order_auto_update
        self.ebay_default_product_category_id=instance and instance.ebay_default_product_category_id and instance.ebay_default_product_category_id.id or False
        self.pay_mthd=instance and instance.pay_mthd
        self.email_add=instance and instance.email_add
        self.site_id=instance and instance.site_id and instance.site_id.id or False
        self.team_id=instance and instance.team_id and instance.team_id.id or False
        self.shipment_charge_product_id=instance and instance.shipment_charge_product_id and instance.shipment_charge_product_id.id or False
        self.post_code=instance and instance.post_code or False
        self.tax_id=instance and instance.tax_id and instance.tax_id.id or False
        self.create_new_product=instance and instance.create_new_product or False
        self.create_quotation_without_product=instance and instance.create_quotation_without_product or False
        self.company_id=instance and instance.company_id and instance.company_id.id or False
        self.discount_charge_product_id=instance and instance.discount_charge_product_id and instance.discount_charge_product_id.id or False
        self.ebay_plus=instance and instance.ebay_plus or False
        self.auto_update_payment= instance and instance.auto_update_payment
        self.use_dynamic_desc=instance and instance.use_dynamic_desc or False
        try:
            inventory_cron_exist = instance and self.env.ref('ebay_ept.ir_cron_auto_export_inventory_instance_%d'%(instance.id),raise_if_not_found=False)
        except:
            inventory_cron_exist=False
        if inventory_cron_exist:
            self.update_stock_interval_number=inventory_cron_exist.interval_number or False
            self.update_stock_interval_type=inventory_cron_exist.interval_type or False

        try:
            order_import_cron_exist = instance and self.env.ref('ebay_ept.ir_cron_send_ebay_import_sales_orders_instance_%d'%(instance.id),raise_if_not_found=False)
        except:
            order_import_cron_exist=False
        if order_import_cron_exist:
            self.order_import_interval_number = order_import_cron_exist.interval_number or False
            self.order_import_interval_type = order_import_cron_exist.interval_type or False
        try:
            order_update_cron_exist = instance and self.env.ref('ebay_ept.ir_cron_update_order_status_instance_%d'%(instance.id),raise_if_not_found=False)
        except:
            order_update_cron_exist=False
        if order_update_cron_exist:
            self.order_update_interval_number= order_update_cron_exist.interval_number or False
            self.order_update_interval_type= order_update_cron_exist.interval_type or False

    @api.multi
    def execute(self):
        instance = self.instance_id
        values = {}
        if instance:
            values['warehouse_id'] = self.warehouse_id and self.warehouse_id.id or False
            values['lang_id'] = self.lang_id and self.lang_id.id or False
            values['order_prefix'] = self.order_prefix and self.order_prefix
            values['stock_field'] = self.stock_field and self.stock_field.id or False
            values['pricelist_id'] = self.pricelist_id and self.pricelist_id.id or False
            values['fiscal_position_id'] = self.fiscal_position_id and self.fiscal_position_id.id or False
            values['order_auto_import']=self.order_auto_import
            values['stock_auto_export']=self.stock_auto_export
            values['create_new_product']=self.create_new_product or False
            values['create_quotation_without_product']=self.create_quotation_without_product or False
            values['ebay_order_auto_update']=self.ebay_order_auto_update
            values['ebay_default_product_category_id']=self.ebay_default_product_category_id and self.ebay_default_product_category_id.id or False
            values['pay_mthd']=self.pay_mthd
            values['email_add']=self.email_add
            values['site_id']=self.site_id and self.site_id.id or False
            values['team_id']=self.team_id and self.team_id.id or False
            values['post_code']=self.post_code or False
            values['price_tax_included']=self.price_tax_included or False
            values['company_id']=self.company_id and self.company_id.id or False
            values['shipment_charge_product_id']=self.shipment_charge_product_id and self.shipment_charge_product_id.id or False
            values['discount_charge_product_id']=self.discount_charge_product_id and self.discount_charge_product_id.id or False
            values['ebay_plus']=self.ebay_plus or False
            values['tax_id']=self.tax_id and self.tax_id.id or False
            values['use_dynamic_desc']=self.use_dynamic_desc or False
            values['auto_update_payment']=self.auto_update_payment or False
            instance.write(values)
            instance.confirm()
            self.setup_order_import_cron(instance)
            self.setup_order_status_update_cron(instance)
            self.setup_update_stock_cron(instance)
        return super(ebay_instance_general_conf_installer, self).execute()

    @api.multi
    def setup_order_import_cron(self,instance):
        if self.order_auto_import:
            try:
                cron_exist = self.env.ref('ebay_ept.ir_cron_send_ebay_import_sales_orders_instance_%d'%(instance.id),raise_if_not_found=False)
            except:
                cron_exist=False
            nextcall = datetime.now()
            nextcall += _intervalTypes[self.order_import_interval_type](self.order_import_interval_number)
            vals = {
                    'active' : True,
                    'interval_number':self.order_import_interval_number,
                    'interval_type':self.order_import_interval_type,
                    'nextcall':nextcall.strftime('%Y-%m-%d %H:%M:%S'),
                    'args':"([{'instance_id':%d}])"%(instance.id),
                    'user_id': self.order_import_user_id and self.order_import_user_id.id}

            if cron_exist:
                vals.update({'name' : cron_exist.name})
                cron_exist.write(vals)
            else:
                try:
                    import_order_cron = self.env.ref('ebay_ept.ir_cron_send_ebay_import_sales_orders')
                except:
                    import_order_cron=False
                if not import_order_cron:
                    raise Warning('Core settings of eBay are deleted, please upgrade eBay Connector module to back this settings.')

                name = instance.name + ' : ' +import_order_cron.name
                vals.update({'name' : name})
                new_cron = import_order_cron.copy(default=vals)
                self.env['ir.model.data'].create({'module':'ebay_ept',
                                                  'name':'ir_cron_send_ebay_import_sales_orders_instance_%d'%(instance.id),
                                                  'model': 'ir.cron',
                                                  'res_id' : new_cron.id,
                                                  'noupdate' : True
                                                  })
        else:
            try:
                cron_exist = self.env.ref('ebay_ept.ir_cron_send_ebay_import_sales_orders_instance_%d'%(instance.id))
            except:
                cron_exist=False

            if cron_exist:
                cron_exist.write({'active':False})
        return True

    @api.multi
    def setup_order_status_update_cron(self,instance):
        if self.ebay_order_auto_update:
            try:
                cron_exist = self.env.ref('ebay_ept.ir_cron_update_order_status_instance_%d'%(instance.id))
            except:
                cron_exist=False
            nextcall = datetime.now()
            nextcall += _intervalTypes[self.order_update_interval_type](self.order_update_interval_number)
            vals = {'active' : True,
                    'interval_number':self.order_update_interval_number,
                    'interval_type':self.order_update_interval_type,
                    'nextcall':nextcall.strftime('%Y-%m-%d %H:%M:%S'),
                    'args':"([{'instance_id':%d}])"%(instance.id),
                    'user_id': self.order_status_update_user_id and self.order_status_update_user_id.id}

            if cron_exist:
                vals.update({'name' : cron_exist.name})
                cron_exist.write(vals)
            else:
                try:
                    update_order_cron = self.env.ref('ebay_ept.ir_cron_update_order_status')
                except:
                    update_order_cron=False
                if not update_order_cron:
                    raise Warning('Core settings of eBay are deleted, please upgrade eBay Connector module to back this settings.')

                name = instance.name + ' : ' +update_order_cron.name
                vals.update({'name' : name})
                new_cron = update_order_cron.copy(default=vals)
                self.env['ir.model.data'].create({'module':'ebay_ept',
                                                  'name':'ir_cron_update_order_status_instance_%d'%(instance.id),
                                                  'model': 'ir.cron',
                                                  'res_id' : new_cron.id,
                                                  'noupdate' : True
                                                  })
        else:
            try:
                cron_exist = self.env.ref('ebay_ept.ir_cron_update_order_status_instance_%d'%(instance.id))
            except:
                cron_exist=False
            if cron_exist:
                cron_exist.write({'active':False})
        return True

    @api.multi
    def setup_update_stock_cron(self,instance):
        if self.stock_auto_export:
            try:
                cron_exist = self.env.ref('ebay_ept.ir_cron_auto_export_inventory_instance_%d'%(instance.id))
            except:
                cron_exist=False
            nextcall = datetime.now()
            nextcall += _intervalTypes[self.update_stock_interval_type](self.update_stock_interval_number)
            vals = {'active' : True,
                    'interval_number':self.update_stock_interval_number,
                    'interval_type':self.update_stock_interval_type,
                    'nextcall':nextcall.strftime('%Y-%m-%d %H:%M:%S'),
                    'args':"([{'instance_id':%d}])"%(instance.id),
                    'user_id': self.stock_update_user_id and self.stock_update_user_id.id}
            if cron_exist:
                vals.update({'name' : cron_exist.name})
                cron_exist.write(vals)
            else:
                try:
                    update_stock_cron = self.env.ref('ebay_ept.ir_cron_auto_export_inventory')
                except:
                    update_stock_cron=False
                if not update_stock_cron:
                    raise Warning('Core settings of eBay are deleted, please upgrade eBay Connector module to back this settings.')

                name = instance.name + ' : ' +update_stock_cron.name
                vals.update({'name':name})
                new_cron = update_stock_cron.copy(default=vals)
                self.env['ir.model.data'].create({'module':'ebay_ept',
                                                  'name':'ir_cron_auto_export_inventory_instance_%d'%(instance.id),
                                                  'model': 'ir.cron',
                                                  'res_id' : new_cron.id,
                                                  'noupdate' : True
                                                  })
        else:
            try:
                cron_exist = self.env.ref('ebay_ept.ir_cron_auto_export_inventory_instance_%d'%(instance.id))
            except:
                cron_exist=False
            if cron_exist:
                cron_exist.write({'active':False})
        return True

    @api.multi
    def modules_to_install(self):
        modules = super(ebay_instance_general_conf_installer, self).modules_to_install()
        return set([])

class ebay_get_ebay_detail_installer(models.TransientModel):
    _name = 'ebay.operation.installer'
    _inherit = 'res.config.installer'

    instance_ids = fields.Many2many("ebay.instance.ept",'ebay_instance_get_ebay_detail_rel','process_id','instance_id',"Instances")
    is_ebay_details=fields.Boolean("Get eBay Details",default=False)
    get_use_preferences=fields.Boolean("Get User Preferences",default=False)
    is_import_category=fields.Boolean("Import Categories",default=False)
    is_import_store_category=fields.Boolean("Import Store Categories",default=False)
    level_limit=fields.Integer("Level Limit",default=0)
    only_leaf_categories=fields.Boolean("Only Leaf Categories",default=True)
    store_level_limit=fields.Integer("Level Limit",default=0)
    store_only_leaf_categories=fields.Boolean("Only Leaf Categories",default=True)
    is_import_product=fields.Boolean("Sync Products",default=False)
    from_date=fields.Date("From Date")
    to_date=fields.Date("To Date")
    import_sales_orders=fields.Boolean("Import Sales Order",default=False)

    @api.model
    def default_get(self,fields):
        res = super(ebay_get_ebay_detail_installer,self).default_get(fields)
        if 'instance_ids' in fields:
            instance_ids = self.env['ebay.instance.ept'].search([])
            res.update({'instance_ids':[(6,0,instance_ids.ids)]})
        return res

    @api.model
    def get_ebay_result(self,instance):
        api = instance.get_trading_api_object()
        para={}
        api.execute('GeteBayDetails', para)
        results = api.response.dict()
        return results

    @api.model
    def get_ebay_basic_result(self,instance):
        api = instance.get_trading_api_object()
        para={}
        api.execute('GeteBayDetails', para)
        results = api.response.dict()
        return results

    @api.model
    def update_ebay_result(self,instance,results):
        payment_option_obj=self.env['ebay.payment.options']
        site_details_obj=self.env['ebay.site.details']
        ebay_shipping_service_obj=self.env['ebay.shipping.service']
        shipping_locations_obj=self.env['ebay.shipping.locations']
        exclude_shipping_locations_obj=self.env['ebay.exclude.shipping.locations']
        refund_options_obj=self.env['ebay.refund.options']
        feedback_score_obj=self.env['ebay.feedback.score']

        payment_option_obj.get_payment_options(instance,results.get('PaymentOptionDetails',[]))
        site_details_obj.get_site_details(instance,results.get('SiteDetails',False))
        refund_options_obj.create_refund_details(instance,results.get('ReturnPolicyDetails',{}))
        feedback_score_obj.create_buyer_requirement(instance,results.get('BuyerRequirementDetails',{}))
        results_first_array = results.get('ShippingServiceDetails',[])
        results_second_array = results.get('ExcludeShippingLocationDetails',[])
        results_third_array = results.get('ShippingLocationDetails',[])

        ebay_shipping_service_obj.shipping_service_create(results_first_array,instance)
        exclude_shipping_locations_obj.create_exclude_shipping_locations(results_second_array,instance)
        shipping_locations_obj.create_shipping_locations(results_third_array,instance)
        buyer_requirement=results.get('BuyerRequirementDetails',{})
        ship_to_register_country=buyer_requirement.get('ShipToRegistrationCountry',False)
        linked_paypal_account=buyer_requirement.get('LinkedPayPalAccount')
        ship_to_register_country=True if ship_to_register_country=='true' else False
        linked_paypal_account=True if linked_paypal_account=='true' else False
        instance.write({'is_paypal_account':linked_paypal_account,'is_primary_shipping_address':ship_to_register_country})
        return True

    @api.multi
    def execute(self):
        if self._context.get('get_ebay_detail',False) :
            if not self.is_ebay_details :
                raise Warning("You must need to select Get eBay Details in order to continue with the next step.")
        if self._context.get('get_user_preferences',False) :
            if not self.get_use_preferences :
                raise Warning("You must need to select Get User Preferences in order to continue with the next step or either you can skip this step.")
        if self._context.get('import_categories',False) :
            if not self.is_import_category :
                raise Warning("You must need to select Import Categories in order to continue with the next step or either you can skip this step.")
        if self._context.get('import_store_categories',False) :
            if not self.is_import_store_category :
                raise Warning("You must need to select Import Store Categories in order to continue with the next step or either you can skip this step.")
        if self._context.get('sync_active_products',False) :
            if not self.is_import_product :
                raise Warning("You must need to select Sync Products in order to continue with the next step or either you can skip this step.")
        if self._context.get('import_sale_order',False) :
            if not self.import_sales_orders :
                raise Warning("You must need to select Import Sales Order in order to finish with configuration process or either you can skip this and finished process.")
#        self.execute_simple()
        return super(ebay_get_ebay_detail_installer, self).execute()

    @api.multi
    def execute_simple(self):
        if self.instance_ids:
            instances=self.instance_ids
        else:
            instances=self.env['ebay.instance.ept'].search([])
        ebay_site_policy_obj=self.env['ebay.site.policy.ept']
        category_obj=self.env['ebay.category.master.ept']
        ebay_product_listing_obj=self.env['ebay.product.listing.ept']
        sale_order_obj=self.env['sale.order']
        if self.is_ebay_details:
            for instance in instances:
                results=self.get_ebay_result(instance)
                results and self.update_ebay_result(instance, results)
                results=self.get_ebay_basic_result(instance)
                results and self.update_ebay_result(instance, results)
        if self.get_use_preferences:
            for instance in instances:
                ebay_site_policy_obj.sync_policies(instance)
        if self.is_import_category:
            category_obj.import_category(instances,self.level_limit,self.only_leaf_categories)
        if self.is_import_store_category:
            category_obj.import_store_category(instances,self.store_level_limit,self.store_only_leaf_categories)
        if self.is_import_product:
            from_date = datetime.strptime(self.from_date,"%Y-%m-%d").date()
            to_date = datetime.strptime(self.to_date,"%Y-%m-%d").date()
            delta = to_date - from_date
            if delta and delta.days > 120 :
                raise Warning("Time ranges must be a less than 120 days.")
            for instance in instances:
                ebay_product_listing_obj.sync_product_listings(instance,self.from_date,self.to_date)
        if self.import_sales_orders:
            for instance in instances:
                sale_order_obj.ebay_import_sales_order(instance,False)
        return True

    @api.multi
    def modules_to_install(self):
        modules = super(ebay_get_ebay_detail_installer, self).modules_to_install()
        return set([])

class ebay_payment_option_instance_conf_installer(models.TransientModel):
    _name = 'ebay.payment.option.instance.conf.installer'
    _inherit = 'res.config.installer'

    @api.model
    def _default_instance(self):
        instances = self.env['ebay.instance.ept'].search([])
        return instances and instances[0].id or False

    instance_id=fields.Many2one("ebay.instance.ept",string="Instance",required=True,default=_default_instance)
    payment_option_ids = fields.One2many("ebay.payment.option.conf.installer",'ebay_payment_option_wizard_id',string="Payment Options")

    @api.multi
    def execute(self):
        for payment_option in self.payment_option_ids :
            if payment_option.payment_option_id :
                payment_option.payment_option_id.write({
                                                    'auto_workflow_id' : payment_option.auto_workflow_id and payment_option.auto_workflow_id.id or False,
                                                    'payment_term_id' : payment_option.payment_term_id and payment_option.payment_term_id.id or False,
                                                    'update_payment_in_ebay' : payment_option.update_payment_in_ebay,})
        return super(ebay_payment_option_instance_conf_installer, self).execute()

    @api.onchange('instance_id')
    def onchange_instance(self):
        payment_option_obj = self.env['ebay.payment.options']
        payment_option_ids = []
        if self.instance_id :
            payment_options = payment_option_obj.search([('instance_id','=',self.instance_id.id)])
            for payment_option in payment_options :
                result= {}
                result.update({'instance_id':payment_option.instance_id.id,
                               'detail_version' : payment_option.detail_version,
                               'description' : payment_option.description,
                               'auto_workflow_id' : payment_option.auto_workflow_id and payment_option.auto_workflow_id.id or False,
                               'payment_term_id' : payment_option.payment_term_id and payment_option.payment_term_id.id or False,
                               'update_payment_in_ebay' : payment_option.update_payment_in_ebay,
                               'payment_option_id' : payment_option.id})
                payment_option_ids.append(result)
        self.payment_option_ids = payment_option_ids

    @api.model
    def default_get(self, fields):
        res = super(ebay_payment_option_instance_conf_installer,self).default_get(fields)
        instances = self.env['ebay.instance.ept'].search([])
        if instances :
            payment_option_obj = self.env['ebay.payment.options']
            payment_options = payment_option_obj.search([('instance_id','=',instances[0].id)])
            payment_option_list = []
            for payment_option in payment_options :
                result= {}
                result.update({'instance_id':payment_option.instance_id.id,
                               'detail_version' : payment_option.detail_version,
                               'description' : payment_option.description,
                               'auto_workflow_id' : payment_option.auto_workflow_id and payment_option.auto_workflow_id.id or False,
                               'payment_term_id' : payment_option.payment_term_id and payment_option.payment_term_id.id or False,
                               'update_payment_in_ebay' : payment_option.update_payment_in_ebay,
                               'payment_option_id' : payment_option.id})
                payment_option_list.append((0, 0,result))
            res.update({'payment_option_ids' : payment_option_list})
        return res

class ebay_payment_option_conf_installer(models.TransientModel):
    _name = 'ebay.payment.option.conf.installer'

    instance_id=fields.Many2one("ebay.instance.ept",string="Instance",required=True)
#     name=fields.Char("PaymentOption")
    detail_version=fields.Char("DetailVersion")
    description=fields.Char("Description")
    auto_workflow_id=fields.Many2one("sale.workflow.process.ept","Auto Workflow")
    payment_term_id = fields.Many2one('account.payment.term', string='Payment Term')
    update_payment_in_ebay = fields.Boolean("Update Payment in eBay",default=False)
    payment_option_id = fields.Many2one('ebay.payment.options','Payment Option')
    ebay_payment_option_wizard_id = fields.Many2one('ebay.payment.option.instance.conf.installer',string="Payment Option Wizard")


# -*- coding: utf-8 -*-
'''
This script will read the *.rgb files and produce pngs from them to be
displayed in the gui.
'''

from __future__ import print_function, absolute_import, unicode_literals, division
from collections import OrderedDict
import glob
import os

from qtpy import QtGui, QtCore
import numpy as np

try:
    import vtk
except ImportError:
    vtk = None

SCRIPT_DIRECTORY = os.path.abspath(os.path.dirname(__file__))
COLOR_MAP_EXT = '.rgb'
COLOR_MAPS = glob.glob(os.path.join(SCRIPT_DIRECTORY, '*' + COLOR_MAP_EXT))

def read_rgb(path):
    """
    Given a file path, extract the rgb values.
    """
    rgb_list = []
    with open(path) as f:
        for line in f:
            rgb = line.split()
            if len(rgb) == 3:
                try:
                    rgb_list.append([float(v) for v in rgb])
                except:
                    pass
    return rgb_list

def get_color_map_dict():
    '''return a dictionary of color maps'''
    color_dict = OrderedDict()
    for f in COLOR_MAPS:
        name = os.path.basename(f).replace(COLOR_MAP_EXT, '').lower()
        rgb = read_rgb(f)
        color_dict[name] = rgb
        color_dict[name + '_reversed'] = list(reversed(rgb))
    return color_dict

def get_color_map_pngs():
    '''return a dictionary of name:path_to_png'''
    pngs = OrderedDict()
    for f in glob.glob(os.path.join(SCRIPT_DIRECTORY,'*.png')):
        name = os.path.basename(f).replace('.png', '').lower()
        pngs[name] = f
    return pngs

icon_cache = OrderedDict()
def build_qicons():
    if icon_cache:
        return icon_cache

    icons = OrderedDict()
    for name, png in get_color_map_pngs().items():
        pix = QtGui.QPixmap(png)
        icons[name] = {
            'bar': QtGui.QIcon(pix.scaled(100, 25, transformMode=QtCore.Qt.SmoothTransformation)),
            'icon': QtGui.QIcon(pix.scaled(25, 25, transformMode=QtCore.Qt.SmoothTransformation)),
            }
    icon_cache.update(icons)
    return icons

def build_vtk_lookup_tables():
    '''build and return lookup tables for vtk'''
    LUTs = OrderedDict()
    for name, colors in get_color_map_dict().items():
        lookup_table = vtk.vtkLookupTable()
        lookup_table.SetNumberOfTableValues(len(colors))

        for i, c in enumerate(colors):
            lookup_table.SetTableValue(i, c[0], c[1], c[2], 1.0)

        LUTs[name] = lookup_table
    return LUTs

if __name__ == "__main__":
    '''Use matplotlib to generate previews of the color maps and save them as
    png files so that they can be displayed in the gui'''
    from matplotlib import pyplot as plt
    from matplotlib.colors import LinearSegmentedColormap

    def plot_color_gradients(name, cmap, gradient):
        fig, axes = plt.subplots(1, figsize=(20, 1))
        fig.subplots_adjust(top=1, bottom=0, left=0, right=1)
        axes.imshow(gradient, aspect='auto', cmap=cmap)
        # Turn off *all* ticks & spines, not just the ones with colormaps.
        axes.set_axis_off()
        fig.savefig(name+'.png', dpi=1)

    gradient = np.linspace(0, 1, 256)
    gradient = np.vstack((gradient, gradient))

    for name, colors in get_color_map_dict().items():
        # normal
        cmap = LinearSegmentedColormap.from_list(name, colors)
        plot_color_gradients(name, cmap, gradient)

        # revered
        cmap = LinearSegmentedColormap.from_list(name, list(reversed(colors)))
        plot_color_gradients(name+'_reversed', cmap, gradient)


from django.contrib import admin
from .models import User
# Register your models here.
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    '''Admin View for User'''

    list_display = (
        'id',
        'email',
        'is_staff',
        'is_active'
        )
    list_filter = (
        'is_staff',
        'is_active'
    )
    search_fields = (
        'email',
        )


import keras
from keras.models import model_from_json, Sequential
from keras.layers import Conv2D, Dense, Flatten, Activation, BatchNormalization, GlobalAveragePooling2D
from keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint
from keras.utils import get_custom_objects, CustomObjectScope
from keras.preprocessing.image import ImageDataGenerator
from keras.datasets import mnist
from keras import backend as K

import os
import sys
import argparse
import json
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

sys.path.append('..')
import functions
from callbacks import EpochLog
from my_json_encoder import MyJsonEncoder

parser = argparse.ArgumentParser()
parser.add_argument('activation', help='Activation function name to be approximated')
parser.add_argument('rg', help='Approximate range of x')
parser.add_argument('deg', help='Approximate degree of polynomial')
parser.add_argument('--bn', action='store_true')
parser.add_argument('--gap', action='store_true')
parser.add_argument('--full', action='store_true')
parser.add_argument('--da', action='store_true')
args = parser.parse_args()
activation_str = args.activation
rg_str = args.rg
deg_str = args.deg
bn_enabled = args.bn
gap_enabled = args.gap
full_enabled = args.full
da_enabled = args.da

ACTIVATION_FUNCTION_MAP = {
    'swish_rg3_deg4': functions.swish_rg3_deg4,
    'swish_rg4_deg4': functions.swish_rg4_deg4,
    'swish_rg5_deg4': functions.swish_rg5_deg4,
    'swish_rg6_deg4': functions.swish_rg6_deg4,
    'swish_rg7_deg4': functions.swish_rg7_deg4,
    'swish_rg8_deg4': functions.swish_rg8_deg4,
    'mish_rg4_deg4': functions.mish_rg4_deg4,
    'mish_rg5_deg4': functions.mish_rg5_deg4,
    'mish_rg6_deg4': functions.mish_rg6_deg4
}

APPROX_ACTIVATION_NAME = f'{activation_str}_rg{rg_str}_deg{deg_str}'
if APPROX_ACTIVATION_NAME not in ACTIVATION_FUNCTION_MAP:
    print(f'\'{APPROX_ACTIVATION_NAME}\' is not registered.')
    sys.exit(1)
APPROX_ACTIVATION = ACTIVATION_FUNCTION_MAP[APPROX_ACTIVATION_NAME]

# Register custom activation function
get_custom_objects().update({APPROX_ACTIVATION_NAME: APPROX_ACTIVATION})

# Declare constants
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
BASE_FILE_NAME = f'{os.path.splitext(os.path.basename(__file__))[0]}-{APPROX_ACTIVATION_NAME}'
if bn_enabled:
    BASE_FILE_NAME+='-BN'
if gap_enabled:
    BASE_FILE_NAME+='-GAP'
if full_enabled:
    BASE_FILE_NAME+='-full'
if da_enabled:
    BASE_FILE_NAME+='-DA'
LOG_FILE_PATH = f'{CUR_DIR}/epoch_logs/{BASE_FILE_NAME}_log.txt'
# MODEL_FILE_PATH = f'{CUR_DIR}/saved_models/{BASE_FILE_NAME}_model.h5'
MODEL_WEIGHTS_PATH = f'{CUR_DIR}/saved_models/{BASE_FILE_NAME}_weights.h5'
MODEL_STRUCTURE_PATH = f'{CUR_DIR}/saved_models/{BASE_FILE_NAME}_structure.json'
HISTORY_FILE_PATH = f'{CUR_DIR}/histories/{BASE_FILE_NAME}_history.json'
HISTORY_GRAPH_PATH = f'{CUR_DIR}/graphs/{BASE_FILE_NAME}_history.png'

BATCH_SIZE = 128
NUM_CLASSES = 10
EPOCHS = 150
IMG_HIGHT, IMG_WIDTH = 28, 28

def preprocess_input_image(train_input, test_input):
    if K.image_data_format() == 'channels_first':
        train_input = train_input.reshape(
            train_input.shape[0], 1, IMG_HIGHT, IMG_WIDTH)
        test_input = test_input.reshape(
            test_input.shape[0], 1, IMG_HIGHT, IMG_WIDTH)
    else:
        train_input = train_input.reshape(
            train_input.shape[0], IMG_HIGHT, IMG_WIDTH, 1)
        test_input = test_input.reshape(
            test_input.shape[0], IMG_HIGHT, IMG_WIDTH, 1)

    # Normalization
    train_input = train_input.astype('float32')
    test_input = test_input.astype('float32')
    train_input /= 255.0
    test_input /= 255.0

    return train_input, test_input

def mnist_model(input_shape):
    model = Sequential()

    model.add(Conv2D(5, (5, 5), strides=(2, 2), input_shape=input_shape))
    if bn_enabled:
        model.add(BatchNormalization())
    model.add(Activation(APPROX_ACTIVATION_NAME))

    model.add(Conv2D(50, (5, 5), strides=(2, 2)))
    if bn_enabled:
        model.add(BatchNormalization())
    model.add(Activation(APPROX_ACTIVATION_NAME))

    if gap_enabled:
        model.add(GlobalAveragePooling2D())
    else:
        model.add(Flatten())
    model.add(Dense(NUM_CLASSES, activation='softmax'))

    return model

def main():
    if os.path.exists(LOG_FILE_PATH):
        os.remove(LOG_FILE_PATH)

    # Load mnist data
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    x_train, x_test = preprocess_input_image(x_train, x_test)
    input_shape = x_train[0].shape

    print('input shape:', input_shape)
    print(x_train.shape[0], 'train samples')
    print(x_test.shape[0], 'test samples')

    # Convert class vectors to binary class metrices (One Hot Encoding)
    y_train = keras.utils.to_categorical(y_train, NUM_CLASSES)
    y_test = keras.utils.to_categorical(y_test, NUM_CLASSES)

    # Split data for training and validation
    if da_enabled:
        X_train, X_val, Y_train, Y_val = train_test_split(x_train, y_train, test_size=0.1, random_state=42)

    # Define CNN model
    model = mnist_model(input_shape)
    # Compile the model
    model.compile(loss='categorical_crossentropy',
                  optimizer=keras.optimizers.Adadelta(),
                  metrics=['accuracy'])

    print(model.summary())
    with open(LOG_FILE_PATH, 'a') as f:
        model.summary(print_fn=lambda x: f.write(x + "\r\n"))
        f.write("\n\n")

    model_structure_json = model.to_json()
    with open(MODEL_STRUCTURE_PATH, 'w') as f:
        f.write(model_structure_json)

    # Define callbacks
    # early_stopping = EarlyStopping(monitor='val_loss', patience=10, verbose=1)
    learning_rate_reduction = ReduceLROnPlateau(monitor='val_loss',
                                                patience=3,
                                                verbose=1,
                                                factor=0.5,
                                                min_lr=0.0001)
    model_checkpoint = ModelCheckpoint(MODEL_WEIGHTS_PATH,
                                       monitor='val_loss',
                                       save_best_only=True,
                                       save_weights_only=True)
    epoch_log = EpochLog(LOG_FILE_PATH)

    callbacks = [
        # early_stopping,
        learning_rate_reduction,
        model_checkpoint,
        epoch_log
    ]

    if da_enabled:
        # Data augumentation
        datagen = ImageDataGenerator(
            rotation_range=15,
            zoom_range = 0.1,
            width_shift_range=0.1,
            height_shift_range=0.1,
            horizontal_flip=False,
            vertical_flip=False
        )

        steps_per_epoch = X_train.shape[0] // BATCH_SIZE

        # Train model
        history = model.fit_generator(datagen.flow(X_train, Y_train, batch_size=BATCH_SIZE),
                                      epochs=EPOCHS,
                                      steps_per_epoch=steps_per_epoch,
                                      validation_data=(X_val, Y_val),
                                      verbose=1,
                                      callbacks=callbacks)
    else:
        # Train model
        history = model.fit(x_train, y_train,
                            batch_size=BATCH_SIZE,
                            epochs=EPOCHS,
                            verbose=1,
                            validation_split=0.1,
                            callbacks=callbacks)

    # Save history
    with open(HISTORY_FILE_PATH, 'w') as f:
        json.dump(history.history, f, cls=MyJsonEncoder)

    # Visualize training history
    functions.plot_training_history(history.history, HISTORY_GRAPH_PATH)

    # Load best model
    with CustomObjectScope({APPROX_ACTIVATION_NAME: APPROX_ACTIVATION}):
        with open(MODEL_STRUCTURE_PATH, 'r') as f:
            model_structure_json = f.read()
        best_model = model_from_json(model_structure_json)
        best_model.load_weights(MODEL_WEIGHTS_PATH)
        best_model.compile(loss='categorical_crossentropy',
                           optimizer=keras.optimizers.Adadelta(),
                           metrics=['accuracy'])

    # Evaluate model
    test_loss, test_acc = best_model.evaluate(x_test, y_test, verbose=1)

    print('Test loss:', test_loss)
    print('Test accuracy:', test_acc)
    with open(LOG_FILE_PATH, 'a') as f:
        f.write("\n\nTest loss: {}, Test accuracy: {}\n".format(
            test_loss, test_acc))

    # Predict for test samples
    preds = best_model.predict(x_test, verbose=1)
    print("Prediction result:")
    print(preds)

if __name__ == '__main__':
    main()


import json
import os

import numpy as np

from examples.pybullet.utils.pybullet_tools.utils import connect, dump_body, disconnect, wait_for_interrupt, \
    get_movable_joints, get_sample_fn, set_joint_positions, get_joint_name, link_from_name, set_point, set_quat, \
    add_line, quat_from_euler, Euler, HideOutput, create_cylinder, load_pybullet, inverse_kinematics, get_link_pose

JSON_FILENAME = 'voronoi_S1.0_09-05-2018.json'

KUKA_PATH = 'framefab_kr6_r900_support/urdf/kr6_r900_workspace.urdf'

# [u'base_frame_in_rob_base', u'element_list', u'node_list', u'assembly_type', u'model_type', u'unit']

def parse_point(json_point):
    return np.array([json_point['X'], json_point['Y'], json_point['Z']]) / 1e3 # / 1e3

def parse_origin(json_data):
    return parse_point(json_data['base_frame_in_rob_base']['Origin'])

def parse_elements(json_data):
    return [tuple(json_element['end_node_ids'])
            for json_element in json_data['element_list']] # 'layer_id

def parse_node_points(json_data):
    origin = parse_origin(json_data)
    return [origin + parse_point(json_node['point']) for json_node in json_data['node_list']]

def parse_ground_nodes(json_data):
    return {i for i, json_node in enumerate(json_data['node_list']) if json_node['is_grounded'] == 1}

def sample_confs(robot, num_samples=10):
    joints = get_movable_joints(robot)
    print('Joints', [get_joint_name(robot, joint) for joint in joints])
    sample_fn = get_sample_fn(robot, joints)
    for i in range(num_samples):
        print('Iteration:', i)
        conf = sample_fn()
        set_joint_positions(robot, joints, conf)
        wait_for_interrupt()

def draw_elements(node_points, elements):
    color = (1, 0, 0, 1)
    element_lines = []
    for (n1, n2) in elements:
        p1 = node_points[n1]
        p2 = node_points[n2]
        element_lines.append(add_line(p1, p2, color=color[:3]))
    return element_lines

def create_elements(node_points, elements, radius=0.0005, color=(1, 0, 0, 1)):
    element_bodies = []
    for (n1, n2) in elements:
        p1 = node_points[n1]
        p2 = node_points[n2]
        height = np.linalg.norm(p2 - p1)
        if height == 0:
            continue
        center = (p1 + p2) / 2
        # extents = (p2 - p1) / 2
        body = create_cylinder(radius, height, color=color)
        set_point(body, center)
        element_bodies.append(body)

        delta = p2 - center
        x, y, z = delta
        phi = np.math.atan2(y, x)
        theta = np.math.acos(z / np.linalg.norm(delta))

        euler = Euler(pitch=theta, yaw=phi)
        # euler = Euler() # Default is vertical
        quat = quat_from_euler(euler)
        set_quat(body, quat)
    return element_bodies

def pddlstream(node_points, elements, ground_nodes):
    # stripstream/lis_scripts/run_print.py
    # stripstream/lis_scripts/print_data.txt

    nodes = list(range(node_points))

    init = []

    for n in nodes:
        init.append(('Node', n))
    for n in ground_nodes:
        init.append(('Connected', n))
    for e in elements:
        #init.append(('Element', e))
        n1, n2 = e
        #init.append(('Edge', n1, n2))
        init.append(('Connection', n1, e, n2))

def main(viewer=True):
    root_directory = os.path.dirname(os.path.abspath(__file__))
    with open(os.path.join(root_directory, JSON_FILENAME), 'r') as f:
        json_data = json.loads(f.read())

    elements = parse_elements(json_data)
    node_points = parse_node_points(json_data)
    ground_nodes = parse_ground_nodes(json_data)

    print('Nodes: {} | Ground: {} | Elements: {}'.format(
        len(node_points), len(ground_nodes), len(elements)))
    #print(json_data['assembly_type']) # extrusion
    #print(json_data['model_type']) # spatial_frame
    #print(json_data['unit']) # millimeter

    connect(use_gui=viewer)
    #floor = load_model('models/short_floor.urdf')
    with HideOutput():
        robot = load_pybullet(os.path.join(root_directory, KUKA_PATH))
    dump_body(robot)
    draw_elements(node_points, elements)

    tool_name = 'eef_tcp_frame'
    link = link_from_name(robot, tool_name)
    node_order = list(range(len(node_points)))
    np.random.shuffle(node_order)

    movable_joints = get_movable_joints(robot)
    sample_fn = get_sample_fn(robot, movable_joints)
    for n in node_order:
        point = node_points[n]
        set_joint_positions(robot, movable_joints, sample_fn())
        conf = inverse_kinematics(robot, link, (point, None))
        if conf is not None:
            set_joint_positions(robot, movable_joints, conf)
            continue
        link_point, link_quat = get_link_pose(robot, link)
        print(point, link_point)
        #user_input('Continue?')
        wait_for_interrupt()
    # TODO: draw the transforms

    #element_bodies = create_elements(origin, node_points, elements)
    #print('Bodies: {}'.format(len(elements)))

    #user_input('Finish?')
    wait_for_interrupt()
    disconnect()

if __name__ == '__main__':
    main()


import argparse
import random

import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

from resunet.model import ResUNet
from train_magnet_functions import train
from trainer import Trainer

if __name__ == "__main__":

    parser = argparse.ArgumentParser()

    parser.add_argument("--train_dataset_dir_path", required=False, type=str,
                        help="Path to the training dataset. Expects 'images' and 'masks' directory inside with images and masks named the same.")
    parser.add_argument("--validation_dataset_dir_path", required=False,
                        type=str,
                        help="Path to the validation dataset. Expects 'images' and 'masks' directory inside with images and masks named the same.")
    parser.add_argument("--logs_root", default="logs", type=str)
    parser.add_argument("--epochs", default=10, type=int)
    parser.add_argument("--batch_size", default=32, type=int)
    parser.add_argument("--plot_model", action="store_true", default=False)
    parser.add_argument("--seed", default=42, type=int)

    args = parser.parse_args()

    args.plot_model = True

    np.random.seed(args.seed)
    tf.random.set_seed(args.seed)
    random.seed(args.seed)

    model = ResUNet(input_shape=(256, 256, 2), classes=2, filters_root=16,
                    depth=4,final_activation='sigmoid')
    model.summary()

    if args.plot_model:
        from tensorflow.python.keras.utils.vis_utils import plot_model

        plot_model(model, show_shapes=True)
    print(args)
    dataset = np.load('c:/datasets/transformer/sdf.npy')
    x = dataset[:, :, :, :-1]
    x[:, :, :, 1] = x[:, :, :, 1] * x[:, :, :, 0]
    y = dataset[:, :, :, -1]

    # scale
    x_scaler = MinMaxScaler()
    y_scaler = MinMaxScaler()
    n, row, col, channel = x.shape
    x_f = x.reshape(n * row * col, channel)
    n, row, col = y.shape
    y_f = y.reshape(n * row * col, 1)
    x_scaler.fit(x_f)
    y_scaler.fit(y_f)
    x_f = x_scaler.transform(x_f)
    y_f = y_scaler.transform(y_f)
    y = y_f.reshape(n, row, col, 1)
    x = x_f.reshape(n, row, col, channel)
    # split
    x_train, x_valid, y_train, y_valid = train_test_split(
        x, y, test_size=0.33, random_state=42)
    y_train = np.concatenate((y_train, 1 - y_train), axis=3)
    y_valid = np.concatenate((y_valid, 1 - y_valid), axis=3)
    del x_f, y_f, x, y, dataset
    trainer = Trainer(name='ResUNet-transformer-sdf',
                      checkpoint_callback=True)
    train(
        model=model,
        trainer=trainer,
        x_train=x_train,
        y_train=y_train,
        x_valid=x_valid,
        y_valid=y_valid
    )