import csv
import os
import re
import subprocess
import shutil

import luigi
import numpy as np
import pandas
from Bio.PDB import NeighborSearch, PDBParser, Atom, Residue

import functions.db_functions as db_functions
import functions.misc_functions as misc_functions
import functions.proasis_api_funcs as proasis_api_funcs

class LeadTransfer(luigi.Task):
    reference_structure = luigi.Parameter()
    pandda_directory = luigi.Parameter()
    name = luigi.Parameter()
    proasis_directory = luigi.Parameter(default='/dls/science/groups/proasis/LabXChem/')

    def requires(self):
        return AddProject(protein_name=str(self.name).upper())

    def output(self):
        mod_date = misc_functions.get_mod_date(self.reference_structure)
        return luigi.LocalTarget('logs/leads/' + str(self.name).upper() + '_' + mod_date + '.added')

    def run(self):
        #try:
            self.name = str(self.name).upper()
            pandda_analyse_centroids = str(self.pandda_directory + '/analyses/pandda_analyse_sites.csv')
            if os.path.isfile(pandda_analyse_centroids):
                site_list = pandas.read_csv(str(pandda_analyse_centroids))['native_centroid']
                print((' Searching for residue atoms for ' + str(len(site_list)) + ' site centroids \n'))
                print(' NOTE: 3 residue atoms are required for each site centroid \n')

                print(site_list)

            else:
                raise Exception('file does not exist!')

            no = 0
            for centroid in site_list:
                # print('next centroid')
                structure = PDBParser(PERMISSIVE=0).get_structure(str(self.name), str(self.reference_structure))
                no += 1

                # initial distance for nearest neighbor (NN) search is 20A
                neighbor_distance = 20

                centroid_coordinates = centroid.replace('(', '[')
                centroid_coordinates = centroid_coordinates.replace(')', ']')
                centroid_coordinates = eval(str(centroid_coordinates))

                # define centroid as an atom object for NN search
                centroid_atom = Atom.Atom('CEN', centroid_coordinates, 0, 0, 0, 0, 9999, 'C')
                atoms = list(structure.get_atoms())
                center = np.array(centroid_atom.get_coord())
                ns = NeighborSearch(atoms)

                # calculate NN list
                neighbors = ns.search(center, neighbor_distance)
                res_list = []

                # for each atom in the NN list
                for neighbor in neighbors:
                    try:
                        # get the residue that the neighbor belongs to
                        parent = Atom.Atom.get_parent(neighbor)
                        # if the residue is not a water etc. (amino acids have blank)
                        if parent.get_id()[0] == ' ':
                            # get the chain that the residue belongs to
                            chain = Residue.Residue.get_parent(parent)
                            # if statements for fussy proasis formatting
                        if len(str(parent.get_id()[1])) == 3:
                            space = ' '
                        if len(str(parent.get_id()[1])) == 2:
                            space = '  '
                        if 'HOH' not in str(parent.get_resname()):
                            res = (
                                str(parent.get_resname()) + ' ' + str(chain.get_id()) + space + str(parent.get_id()[1]))
                            res_list.append(res)

                    except:
                        continue
            res_list = (list(set(res_list)))
            print(res_list)
            lig1 = str("'" + str(res_list[0]) + ' :' + str(res_list[1]) + ' :'
                       + str(res_list[2]) + " ' ")
            print(lig1)

            # some faff to get rid of waters and add remaining ligands in multiples of 3 - proasis is fussy
            alt_lig_option = " -o '"
            res_string = ""
            full_res_string = ''
            count = 0

            for i in range(3, len(res_list)):
                count += 1

            multiple = int(round(count / 3) * 3)
            count = 0
            for i in range(3, multiple):
                if count == 0:
                    res_string += alt_lig_option
                if count <= 1:
                    res_string += str(res_list[i] + ' ,')
                    count += 1
                elif count == 2:
                    res_string += str(res_list[i] + " '")
                    full_res_string.join(res_string)
                    count = 0

            # copy reference structure to proasis directories
            ref_structure_file_name = str(self.reference_structure).split('/')[-1]
            proasis_project_directory = str(str(self.proasis_directory) + '/' + str(self.name))
            proasis_reference_directory = str(str(proasis_project_directory) + '/reference/')
            proasis_reference_structure = str(proasis_reference_directory + '/' + str(ref_structure_file_name))

            if not os.path.isdir(str(proasis_project_directory)):
                os.mkdir(proasis_project_directory)
            if not os.path.isdir(proasis_reference_directory):
                os.mkdir(proasis_reference_directory)
            shutil.copy2(self.reference_structure, proasis_reference_structure)

            submit_to_proasis = str('/usr/local/Proasis2/utils/submitStructure.py -p ' + str(self.name) + ' -t ' + str(
                self.name) + '_lead -d admin -f ' + str(proasis_reference_structure) + ' -l ' + str(
                lig1) + "-x XRAY -n")
            print(submit_to_proasis)
            process = subprocess.Popen(submit_to_proasis, stdout=subprocess.PIPE, shell=True)
            out, err = process.communicate()
            out = out.decode('ascii')
            if err:
                err = err.decode('ascii')
            print(out)
            if err:
                raise Exception('There was a problem submitting this lead: ' + str(err))

            strucidstr = misc_functions.get_id_string(out)

            if len(strucidstr)=='':
                raise Exception('No strucid was detected: ' + str(out) + ' ; ' + str(err))

            add_lead = str('/usr/local/Proasis2/utils/addnewlead.py -p ' + str(self.name) + ' -s ' + str(strucidstr))
            process = subprocess.Popen(add_lead, stdout=subprocess.PIPE, shell=True)
            out, err = process.communicate()
            out = out.decode('ascii')
            if err:
                err = err.decode('ascii')
            print(out)
            if err:
                raise Exception('There was a problem submitting this lead: ' + str(err))

            conn, c = db_functions.connectDB()

            c.execute(
                'UPDATE proasis_leads SET strucid = %s WHERE reference_pdb = %s and pandda_path = %s',
                (strucidstr, self.reference_structure, self.pandda_directory))

            conn.commit()

            with self.output().open('wb') as f:
                f.write('')

# class AddProject(luigi.Task):
#     protein_name = luigi.Parameter()
#
#     def output(self):
#         self.protein_name = str(self.protein_name).upper()
#         return luigi.LocalTarget(str('logs/projects/' + str(self.protein_name) + '.added'))
#
#     def run(self):
#         try:
#             self.protein_name = str(self.protein_name).upper()
#             add_project = str(
#                 '/usr/local/Proasis2/utils/addnewproject.py -c admin -q OtherClasses -p ' + str(self.protein_name))
#             process = subprocess.Popen(add_project, stdout=subprocess.PIPE, shell=True)
#             out, err = process.communicate()
#             out = out.decode('ascii')
#             if err:
#                 err = err.decode('ascii')
#             if len(out) > 1:
#                 with self.output().open('w') as f:
#                     f.write(str(out))
#             else:
#                 with self.output().open('w') as f:
#                     f.write(str(err))
#         except:
#             with self.output().open('w') as f:
#                 f.write('FAIL')

class FindLigands(luigi.Task):
    bound_conf = luigi.Parameter()

    def requires(self):
        conn, c = db_functions.connectDB()
        c.execute('select protein from proasis_hits where bound_conf like %s', (self.bound_conf,))
        rows = c.fetchall()
        protein_list = []
        for row in rows:
            protein_list.append(str(row[0]).upper())
        return [AddProject(protein_name=protein) for protein in list(set(protein_list))]

    def output(self):
        out_name = '_'.join(self.bound_conf.split('/')[-4:-1])
        return luigi.LocalTarget('logs/find_ligands/' + out_name + '.done')

    def run(self):
        try:
            ligand_list = list(set(db_functions.get_pandda_lig_list(self.bound_conf)))
        except:
            try:
                pdb_file = open(self.bound_conf, 'r')
                ligand_list = []
                for line in pdb_file:
                    if "LIG" in line:
                        try:
                            lig_string = re.search(r"LIG.......", line).group()
                            ligand_list.append(list(filter(bool, list(lig_string.split(' ')))))
                        except:
                            continue
            except:
                ligand_list = None

        if ligand_list:
            unique_ligands = [list(x) for x in set(tuple(x) for x in ligand_list)]
        else:
            unique_ligands = None

        conn, c = db_functions.connectDB()
        c.execute('UPDATE proasis_hits SET ligand_list=%s WHERE bound_conf=%s',(str(unique_ligands), self.bound_conf))
        conn.commit()
        print(unique_ligands)

        with self.output().open('wb') as f:
            f.write('')

class CopyFilesForProasis(luigi.Task):
    protein_name = luigi.Parameter()
    hit_directory = luigi.Parameter()
    crystal = luigi.Parameter()
    bound_pdb = luigi.Parameter()
    mod_date = luigi.Parameter()

    def check_modification_date(self, filename):
        if os.path.isfile(filename):
            proasis_file_date = misc_functions.get_mod_date(filename)
            modification_date = self.mod_date
            if proasis_file_date != modification_date:
                conn, c = db_functions.connectDB()
                c.execute('SELECT strucid FROM proasis_hits WHERE bound_conf = %s and modification_date = %s',
                          (self.bound_pdb, modification_date))
                rows = c.fetchall()
                for row in rows:
                    if len(str(row[0])) > 1:
                        proasis_api_funcs.delete_structure(str(row[0]))
                        c.execute(
                            'UPDATE proasis_hits SET strucid = NULL WHERE bound_conf = %s and modification_date = %s',
                            (self.bound_pdb, modification_date))

    def requires(self):
        return FindLigands(bound_conf=self.bound_pdb)

    def output(self):
        return luigi.LocalTarget(str('logs/proasis_file_transfer/' + self.crystal + '_' + self.mod_date + '.done'))

    def run(self):
        # set up directory paths for where files will be stored (for proasis)
        self.protein_name = str(self.protein_name).upper()
        proasis_protein_directory = str(str(self.hit_directory) + '/' + str(self.protein_name) + '/')
        proasis_crystal_directory = str(str(self.hit_directory) + '/' + str(self.protein_name) + '/'
                                        + str(self.crystal) + '/')

        # if the proasis project (protein) dir does not exist, create it
        if not os.path.isdir(proasis_protein_directory):
            print('not a directory')
            os.mkdir(proasis_protein_directory)

        # if the crystal directory does not exist, create it
        if not os.path.isdir(proasis_crystal_directory):
            print('not a directory')
            os.mkdir(proasis_crystal_directory)

        # find the name of the file, and create filepath name in proasis directories
        pdb_file_name = str(self.bound_pdb).split('/')[-1]
        proasis_bound_pdb = str(proasis_crystal_directory + pdb_file_name)

        self.check_modification_date(proasis_bound_pdb)

        #if the bound pdb is in a refinement folder, change the path to find the map files
        if 'Refine' in str(self.bound_pdb).replace(pdb_file_name, ''):
            remove_string = str(str(self.bound_pdb).split('/')[-2] + '/' + pdb_file_name)
            map_directory = str(self.bound_pdb).replace(remove_string, '')
        else:
            map_directory = str(self.bound_pdb).replace(pdb_file_name, '')

        # copy the 2fofc and fofc maps over to the proasis directories
        if os.path.isfile(str(map_directory + '/2fofc.map')):
            shutil.copy2(os.path.join(map_directory,'2fofc.map'), proasis_crystal_directory)
        else:
            raise Exception('2f0fc map not found! Will not upload to proasis!')

        if os.path.isfile(str(map_directory + '/fofc.map')):
            shutil.copy2(os.path.join(map_directory, 'fofc.map'), proasis_crystal_directory)
        else:
            raise Exception('f0fc map not found! Will not upload to proasis!')

        if os.path.isfile(str(map_directory + '/refine.mtz')):
            shutil.copy2(os.path.join(map_directory, 'refine.mtz'), proasis_crystal_directory)
        else:
            raise Exception('mtz file not found! Will not upload to proasis!')

        #copy refinement pdb specified in datasource to proasis directories
        print('Copying refinement pdb...')

        # copy the file to the proasis directories
        shutil.copy2(self.bound_pdb, proasis_crystal_directory)

        with self.output().open('wb') as f:
            f.write('')

class GenerateSdfFile(luigi.Task):
    # for sdf generation
    crystal = luigi.Parameter()
    smiles = luigi.Parameter()

    # for CopyFilesForProasis() requirement
    protein_name = luigi.Parameter()
    hit_directory = luigi.Parameter()
    bound_pdb = luigi.Parameter()

    def requires(self):
        pass

    def output(self):
        self.protein_name = str(self.protein_name).upper()
        proasis_crystal_directory = os.path.join(self.hit_directory, self.protein_name, self.crystal)

        return luigi.LocalTarget(str(os.path.join(proasis_crystal_directory, str(self.crystal + '.sdf'))))

    def run(self):
        self.protein_name = str(self.protein_name).upper()
        proasis_crystal_directory = os.path.join(self.hit_directory, self.protein_name, self.crystal)
        misc_functions.create_sd_file(self.crystal, self.smiles,
                                      str(os.path.join(proasis_crystal_directory, str(self.crystal + '.sdf'))))

class CheckFilesForUpload(luigi.Task):
    # bound state pdb file from refinement
    bound_pdb = luigi.Parameter()
    mod_date = luigi.Parameter()

    def requires(self):
        pass

    def output(self):
        return luigi.LocalTarget('logs/upload_checks/' + str(self.bound_pdb.split('/')[-1] + '_' + self.mod_date + '.done'))

    def run(self):
        conn, c = db_functions.connectDB()
        exists = db_functions.column_exists('proasis_hits', 'exists_pdb')
        if not exists:
            execute_string = str("ALTER TABLE proasis_hits ADD COLUMN exists_pdb text;")
            c.execute(execute_string)
            conn.commit()
        if os.path.isfile(self.bound_pdb):
            db_functions.check_file_status('mtz', 'refine.mtz', self.bound_pdb)
            db_functions.check_file_status('2fofc', '2fofc.map', self.bound_pdb)
            db_functions.check_file_status('fofc', 'fofc.map', self.bound_pdb)
            status = 1
        else:
            status = 0

        c.execute('UPDATE proasis_hits SET exists_pdb=%s WHERE bound_conf=%s', (status, self.bound_pdb))
        conn.commit()

        c.execute("SELECT strucid, exists_pdb, exists_2fofc, exists_fofc, exists_mtz FROM proasis_hits WHERE bound_conf=%s and strucid !=''", (self.bound_pdb,))
        rows = c.fetchall()
        for row in rows:
            if '0' in [str(row[1]), str(row[2]), str(row[3]), str(row[4])]:
                proasis_api_funcs.delete_structure(str(row[0]))
                c.execute("UPDATE proasis_hits SET strucid='' WHERE bound_conf=%s", (self.bound_pdb,))
                conn.commit()

        with self.output().open('wb') as f:
            f.write('')

class HitTransfer(luigi.Task):
    # bound state pdb file from refinement
    bound_pdb = luigi.Parameter()
    # the directory that files should be copied to on the proasis side
    hit_directory = luigi.Parameter(default='/dls/science/groups/proasis/LabXChem/')
    # the name of the crystal
    crystal = luigi.Parameter()
    # the name of the protein name (i.e. proasis project name)
    protein_name = luigi.Parameter()
    # smiles string for the ligand
    smiles = luigi.Parameter()
    # modification date to check whether the structure needs updating or not
    mod_date = luigi.Parameter()

    ligands = luigi.Parameter()

    def requires(self):
        self.protein_name = str(self.protein_name).upper()
        return AddProject(protein_name=self.protein_name), CopyFilesForProasis(protein_name=self.protein_name, hit_directory=self.hit_directory,
                                   crystal=self.crystal,
                                   bound_pdb=self.bound_pdb, mod_date=self.mod_date), FindLigands(
            bound_conf=self.bound_pdb), GenerateSdfFile(crystal=self.crystal, smiles=self.smiles,
                                                        protein_name=self.protein_name,
                                                        hit_directory=self.hit_directory, bound_pdb=self.bound_pdb)

    def output(self):
        return luigi.LocalTarget('logs/hits/' + str(self.crystal) + '_' + self.mod_date + '.added')

    def run(self):
        self.protein_name = str(self.protein_name).upper()
        self.ligands = eval(self.ligands)

        # proasis_protein_directory = str(str(self.hit_directory) + '/' + str(self.protein_name) + '/')
        proasis_crystal_directory = str(str(self.hit_directory) + '/' + str(self.protein_name) + '/'
                                        + str(self.crystal) + '/')

        pdb_file_name = str(self.bound_pdb).split('/')[-1]
        proasis_bound_pdb = str(proasis_crystal_directory + pdb_file_name)

        # Check whether there is already an entry for crystal in masterdb
        conn, c = db_functions.connectDB()

        c.execute("SELECT strucid, bound_conf FROM proasis_hits WHERE crystal_name LIKE %s", (self.crystal,))
        rows = c.fetchall()

        current_visit = str(self.bound_pdb).split('/')[4]
        title = str(self.crystal)

        if len(self.ligands) == 1:
            lig_string = str(proasis_api_funcs.get_lig_strings(self.ligands)[0])
            print('submission string:\n')
            submit_to_proasis = str("/usr/local/Proasis2/utils/submitStructure.py -d 'admin' -f " + "'" +
                                    str(proasis_bound_pdb) + "' -l '" + lig_string + "' -m " +
                                    str(os.path.join(proasis_crystal_directory, str(self.crystal) + '.sdf')) +
                                    " -p " + str(self.protein_name) + " -t " + title + " -x XRAY -N")

            # submit the structure to proasis
            strucid, err, out = proasis_api_funcs.submit_proasis_job_string(submit_to_proasis)

        # same as above, but for structures containing more than one ligand
        elif len(self.ligands) > 1:
            ligands_list = proasis_api_funcs.get_lig_strings(self.ligands)
            print(ligands_list)
            lig1 = ligands_list[0]
            lign = " -o '"
            for i in range(1, len(ligands_list) - 1):
                lign += str(ligands_list[i] + ',')
            lign += str(ligands_list[len(ligands_list) - 1] + "'")

            submit_to_proasis = str("/usr/local/Proasis2/utils/submitStructure.py -d 'admin' -f " + "'" +
                                    str(proasis_bound_pdb) + "' -l '" + lig1 + "' " + lign + " -m " +
                                    str(os.path.join(proasis_crystal_directory, str(self.crystal) + '.sdf')) +
                                    " -p " + str(self.protein_name) + " -t " + title + " -x XRAY -N")
            print(submit_to_proasis)

            strucid, err, out = proasis_api_funcs.submit_proasis_job_string(submit_to_proasis)

        elif len(self.ligands)==0:
            raise Exception('No ligands were found!')

        if strucid != '':

            out, err = proasis_api_funcs.add_proasis_file(file_type='2fofc_c', filename=os.path.join(proasis_crystal_directory, '2fofc.map'),
                                  strucid=strucid, title=str(self.crystal + '_2fofc'))

            print(out)
            if err:
                raise Exception(out)

            out, err = proasis_api_funcs.add_proasis_file(file_type='fofc_c', filename=os.path.join(proasis_crystal_directory, 'fofc.map'),
                                  strucid=strucid, title=str(self.crystal + '_fofc'))

            print(out)
            if err:
                raise Exception(out)

            out, err = proasis_api_funcs.add_proasis_file(file_type='mtz', filename=os.path.join(proasis_crystal_directory, 'refine.mtz'),
                                  strucid=strucid, title=str(self.crystal + '_mtz'))

            print(out)

            if err:
                raise Exception(out)

        else:
            raise Exception('proasis failed to upload structure: ' + out)

        # add strucid to database
        print('Updating master DB')
        conn, c = db_functions.connectDB()
        c.execute("UPDATE proasis_hits SET strucid=%s where bound_conf=%s and modification_date=%s",
                  (str(strucid), str(self.bound_pdb), str(self.mod_date)))

        conn.commit()
        print(c.query)
        print(c.statusmessage)

        if 'UPDATE 0' in c.statusmessage:
            proasis_api_funcs.delete_structure(strucid)
            raise Exception('db was not updated! structure removed from proasis!')

        with self.output().open('wb') as f:
            f.write('')

class WriteBlackLists(luigi.Task):
    def requires(self):
        return FindSoakDBFiles(), StartLeadTransfers(), StartHitTransfers()

    def output(self):
        return luigi.LocalTarget('logs/blacklists.done')

    def run(self):
        proposal_dict, strucids = db_functions.get_strucid_list()
        fedid_list = db_functions.get_fedid_list()

        directory_path = '/usr/local/Proasis2/Data/BLACKLIST'

        for fedid in fedid_list:
            db_functions.create_blacklist(fedid, proposal_dict, directory_path)

        with open('/usr/local/Proasis2/Data/BLACKLIST/other_user.dat', 'w') as f:
            wr = csv.writer(f)
            wr.writerow(strucids)

        with open(str(directory_path + '/uzw12877.dat'),'w') as f:
            f.write('')

        with self.output().open('wb') as f:
            f.write('')


# -*- coding: utf-8 -*-

from data import *
from geometry import *
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, \
    NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import tkinter as tk
from tkinter import ttk
from tkinter import *
from tkinter import filedialog
from matplotlib import pyplot as plt
import matplotlib
matplotlib.use("TkAgg")
LARGE_FONT = ("Verdana", 12)

# Variables globales
global group
group = import_data("villes.csv")
group.name = "Test"

class MainPage(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "Travelling salesman problem")

        # Définition des frames
        self.commandes = tk.Frame(self)
        self.commandes.grid(row=0, column=0, sticky=W+E+N+S)
        self.affichage = tk.Frame(self)
        self.affichage.grid(row=2, column=0, sticky=W+E)
        self.fig = plt.figure(1)
        canvas = FigureCanvasTkAgg(self.fig, self.affichage)
        canvas.get_tk_widget().pack(side="top", fill=BOTH, expand=True)
        toolbar = NavigationToolbar2TkAgg(canvas, self.affichage)
        toolbar.update()
        canvas._tkcanvas.pack(side="top", fill=BOTH, expand=True)

        # Commandes
        button = ttk.Button(self.commandes, text="Charger groupe",
                            command=lambda: self.charger())
        button.grid(row=0, column=0)
        button2 = ttk.Button(self.commandes, text="Ajouter noeud",
                             command=lambda: self.ajouter_noeud())
        button2.grid(row=0, column=1)
        button3 = ttk.Button(self.commandes, text="Calcul",
                             command=lambda: self.calcul(group))
        button3.grid(row=0, column=2)

        # Nouveau noeud
        nv_noeud = tk.Frame(self)
        nv_noeud.grid(row=1, column=0, sticky=W+E)
        Label(nv_noeud, text="Nom du noeud :").grid(row=1, column=0)
        self.nv_noeud_nom = Entry(nv_noeud, textvariable=StringVar())
        self.nv_noeud_nom.grid(row=1, column=1)
        Label(nv_noeud, text="Index :").grid(row=1, column=2)
        self.nv_noeud_index = Entry(nv_noeud, textvariable=StringVar())
        self.nv_noeud_index.grid(row=1, column=3)
        Label(nv_noeud, text="X = ").grid(row=1, column=4)
        self.nv_noeud_X = Entry(nv_noeud, textvariable=StringVar())
        self.nv_noeud_X.grid(row=1, column=5)
        Label(nv_noeud, text="Y = ").grid(row=1, column=6)
        self.nv_noeud_Y = Entry(nv_noeud, textvariable=StringVar())
        self.nv_noeud_Y.grid(row=1, column=7)

    def charger(self):
        global group
        filename = filedialog.askopenfilename()
        group = import_data(filename)
        group.name = filename
        print("Chargement du fichier {}".format(filename))
        print(group)
        return group

    def ajouter_noeud(self):
        global group
        # group += Node(index=14, name="Barcelone", xy=[2.17340,41.38506])
        group += Node(index=int(self.nv_noeud_index.get()),
                      name=self.nv_noeud_nom.get(),
                      xy=[float(self.nv_noeud_X.get()),
                          float(self.nv_noeud_Y.get())])
        print(group)
        return group

    def calcul(self, group):
        self.fig.clear()
        self.fig.add_axes([0.1, 0.1, 0.8, 0.8])
        path1, cost1 = travelling_salesman_problem(group, CostMatrix(group),
                                                   ["Paris", "Moscou"],
                                                   self.fig.axes[0])
        self.fig.canvas.draw()


from __future__ import division
import numpy as np

import keras.backend as K
from keras.layers import BatchNormalization, Convolution2D, Activation, add, InputSpec
from keras.engine.topology import Layer
import tensorflow as tf

class Normalize(Layer):
    """Normalization layer as described in ParseNet paper.
    # Arguments
        scale: Default feature scale.
    # Input shape
        4D tensor with shape:
        `(samples, channels, rows, cols)` if dim_ordering='th'
        or 4D tensor with shape:
        `(samples, rows, cols, channels)` if dim_ordering='tf'.
    # Output shape
        Same as input
    # References
        http://cs.unc.edu/~wliu/papers/parsenet.pdf
    """

    def __init__(self, scale=20, **kwargs):

        self.scale = scale
        if K.image_dim_ordering() == 'tf':
            self.axis = 3
        else:
            self.axis = 1
        super(Normalize, self).__init__(**kwargs)

    def build(self, input_shape):
        self.input_spec = InputSpec(shape=input_shape)
        shape = (input_shape[self.axis],)
        init_gamma = self.scale * np.ones(shape)
        self.gamma = K.variable(init_gamma, name='{}_gamma'.format(self.name))
        self.trainable_weights = [self.gamma]
        super(Normalize, self).build(input_shape)

    def call(self, x, mask=None):
        output = K.l2_normalize(x, self.axis)
        output *= self.gamma
        return output

class PriorBox(Layer):
    """Generate the prior boxes of designated sizes and aspect ratios.

    # Arguments
        img_size: Size of the input image as tuple (w, h).
        min_size: Minimum box size in pixels.
        max_size: Maximum box size in pixels.
        aspect_ratios: List of aspect ratios of boxes.
        flip: Whether to consider reverse aspect ratios.
        variances: List of variances for x, y, w, h.
        clip: Whether to clip the prior's coordinates
            such that they are within [0, 1].
    # Input shape
        4D tensor with shape:
        `(samples, channels, rows, cols)` if dim_ordering='th'
        or 4D tensor with shape:
        `(samples, rows, cols, channels)` if dim_ordering='tf'.
    # Output shape
        3D tensor with shape:
        (samples, num_boxes, 8)
    # References
        https://arxiv.org/abs/1512.02325

    """

    def __init__(self, img_size, min_size, max_size=None, aspect_ratios=None,
                 flip=True, variances=[0.1], clip=True, **kwargs):

        if K.image_dim_ordering() == 'tf':
            self.waxis = 2
            self.haxis = 1
        else:
            self.waxis = 3
            self.haxis = 2

        self.img_size = img_size
        if min_size <= 0:
            raise Exception('min_size must be positive.')

        self.min_size = min_size
        self.max_size = max_size
        self.aspect_ratios = [1.0]

        if max_size:
            if max_size < min_size:
                raise Exception('max_size must be greater than min_size.')
            self.aspect_ratios.append(1.0)

        if aspect_ratios:
            for ar in aspect_ratios:
                if ar in self.aspect_ratios:
                    continue
                self.aspect_ratios.append(ar)
                if flip:
                    self.aspect_ratios.append(1.0 / ar)

        self.variances = np.array(variances)
        self.clip = clip

        super(PriorBox, self).__init__(**kwargs)

    def compute_output_shape(self, input_shape):

        num_priors_ = len(self.aspect_ratios)
        layer_width = input_shape[self.waxis]
        layer_height = input_shape[self.haxis]
        num_boxes = num_priors_ * layer_width * layer_height
        return (input_shape[0], num_boxes, 8)

    def call(self, x, mask=None):

        if hasattr(x, '_keras_shape'):
            input_shape = x._keras_shape
        elif hasattr(K, 'int_shape'):
            input_shape = K.int_shape(x)

        layer_width = input_shape[self.waxis]
        layer_height = input_shape[self.haxis]

        img_width = self.img_size[0]
        img_height = self.img_size[1]

        # define prior boxes shapes
        box_widths = []
        box_heights = []

        for ar in self.aspect_ratios:
            if ar == 1 and len(box_widths) == 0:
                box_widths.append(self.min_size)
                box_heights.append(self.min_size)
            elif ar == 1 and len(box_widths) > 0:
                box_widths.append(np.sqrt(self.min_size * self.max_size))
                box_heights.append(np.sqrt(self.min_size * self.max_size))
            elif ar != 1:
                box_widths.append(self.min_size * np.sqrt(ar))
                box_heights.append(self.min_size / np.sqrt(ar))

        box_widths = 0.5 * np.array(box_widths)
        box_heights = 0.5 * np.array(box_heights)

        # define centers of prior boxes
        step_x = img_width / layer_width
        step_y = img_height / layer_height

        linx = np.linspace(0.5 * step_x, img_width - 0.5 * step_x, layer_width)
        liny = np.linspace(0.5 * step_y, img_height - 0.5 * step_y, layer_height)

        centers_x, centers_y = np.meshgrid(linx, liny)
        centers_x = centers_x.reshape(-1, 1)
        centers_y = centers_y.reshape(-1, 1)

        # define xmin, ymin, xmax, ymax of prior boxes
        num_priors_ = len(self.aspect_ratios)

        prior_boxes = np.concatenate((centers_x, centers_y), axis=1)
        prior_boxes = np.tile(prior_boxes, (1, 2 * num_priors_))

        # Normalize to 0-1
        prior_boxes[:, ::4] -= box_widths
        prior_boxes[:, 1::4] -= box_heights
        prior_boxes[:, 2::4] += box_widths
        prior_boxes[:, 3::4] += box_heights
        prior_boxes[:, ::2] /= img_width
        prior_boxes[:, 1::2] /= img_height
        prior_boxes = prior_boxes.reshape(-1, 4)

        # clip to 0-1
        if self.clip:
            prior_boxes = np.minimum(np.maximum(prior_boxes, 0.0), 1.0)

        # define variances
        num_boxes = len(prior_boxes)
        # print(self.variances)

        if len(self.variances) == 1:
            variances = np.ones((num_boxes, 4)) * self.variances[0]
        elif len(self.variances) == 4:
            variances = np.tile(self.variances, (num_boxes, 1))
        else:
            raise Exception('Must provide one or four variances.')

        prior_boxes = np.concatenate((prior_boxes, variances), axis=1)
        prior_boxes_tensor = K.expand_dims(K.variable(prior_boxes), 0)

        if K.backend() == 'tensorflow':
            pattern = [tf.shape(x)[0], 1, 1]
            prior_boxes_tensor = tf.tile(prior_boxes_tensor, pattern)

        # print(K.int_shape(prior_boxes_tensor)) # for debugging purpose

        return prior_boxes_tensor

# def Residual_Block(num_filters_inp, num_filters_out, prev_layer):
def Residual_Block(num_filters_out, prev_layer, name):
    '''
    A customizable residual unit with convolutional and shortcut blocks
    Args:
      num_filters_inp: number of channels/filters coming in, from input or previous layer
      num_maps_out: how many output channels/filters this block will produce
      prev_layer: the previous layer
    '''

    out = prev_layer

    out = BatchNormalization(axis=1)(out)
    out = Activation('relu')(out)
    out = Convolution2D(num_filters_out, kernel_size=1, padding='same')(out)

    out = BatchNormalization(axis=1)(out)
    out = Activation('relu')(out)
    out = Convolution2D(num_filters_out * 2, kernel_size=3, padding='same')(out)

    # if num_filters_inp != num_filters_out:
    #     prev_layer = Convolution2D(num_filters_out, kernel_size=1)(prev_layer)

    return add([out, prev_layer], name=name)


import math
import random
import numpy as np
import pygame
import os
from pygame.locals import *

class Ball():
    def __init__(self, x, y, w, h):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.last_touch = 0  # Remember who touched the ball last
        self.color = (255, 255, 255)
        self.rect = pygame.Rect(self.x, self.y, w, h)
        self.MAX_BOUNCE_ANGLE = 75
        self.reset_ball()

    def move(self):
        self.x += self.vector[0]
        self.y += self.vector[1]
        # Collisison with left and right wall
        if self.x <= 0 - self.w:
            return 2, True
        if self.x >= 210 - self.w:
            return 1, True
        # Collisison with top and bottom wall
        if (self.y - abs(self.vector[1]) <= 35 and self.vector[1] < 0) or (self.y + abs(self.vector[1]) >= 235 and self.vector[1] > 0):
            self.vector = (self.vector[0], -1 * self.vector[1])

        self.rect = pygame.Rect(self.x - self.w/2, self.y-self.h/2, self.w, self.h)

        return 0, False

    def reflect(self, offcenter, direction, player):
        # print("offcenter: ", offcenter)
        normalized_offcenter = offcenter / 10 * direction
        # print("norm offcenter: ",normalized_offcenter)
        bounce_angle = normalized_offcenter * self.MAX_BOUNCE_ANGLE
        # print("bounce_angle: ", bounce_angle)
        if player == 1:
            self.vector = (3 * (math.cos(math.radians(bounce_angle)) + 1)*self.speed_mul, 8 * -math.sin(math.radians(bounce_angle))*self.speed_mul)
        else:
            self.vector = (-3 * (math.cos(math.radians(bounce_angle)) + 1)*self.speed_mul, 8 * math.sin(math.radians(bounce_angle))*self.speed_mul)
        # print("vector: ", self.vector)
        self.speed_mul += .005

    def reset_ball(self):
        self.x = 105
        self.y = 135
        self.last_touch = 0
        self.rect = pygame.Rect(self.x - self.w/2, self.y-self.h/2, self.w, self.h)
        # Reset ball in random direction
        bounce_angle = np.random.random() * 40
        side = random.choice([True, False])
        if side == True:
            d = 1
        else:
            d = -1
        up_down = random.choice([True, False])
        if up_down == True:
            u = 1
        else:
            u = -1
        self.vector = (d * 3 * (math.cos(math.radians(bounce_angle)) + 1), u * 6 * math.sin(math.radians(bounce_angle)))
        self.speed_mul = 0.8

class Player():
    def __init__(self, player_number):
        self.player_number = player_number
        self.score = 0
        self.x = 0
        self.y = 0
        self.w = 5
        self.h = 20
        self.rect = None
        self.color = (0, 0, 0)
        self.reset()
        self.paddle_speed = 3
        self.name = ""

    def move_up(self):
        if self.y - self.paddle_speed >= 35 + self.h / 2:
            self.y -= self.paddle_speed
        self.rect = pygame.Rect(self.x, self.y - self.h / 2, self.w, self.h)

    def move_down(self):
        if self.y + self.paddle_speed <= 235 - self.h / 2:
            self.y += self.paddle_speed
        self.rect = pygame.Rect(self.x, self.y - self.h / 2, self.w, self.h)

    def reset(self):
        if self.player_number == 1:
            self.x = 10
            self.color = (0, 255, 0)
        else:
            self.x = 195
            self.color = (255, 0, 0)
        self.y = 135
        self.rect = pygame.Rect(self.x, self.y - self.h / 2, self.w, self.h)

class Pong():
    MOVE_UP, MOVE_DOWN, STAY = 1, 2, 0
    def __init__(self, headless=False):
        # [initiate game environment here]
        pygame.init()
        self.SCREEN_RESOLUTION = (210, 235)
        self.GAME_AREA_RESOLUTION = (210, 200)
        self.GAME_AREA_CENTER = (105, 135)
        if headless:
            os.environ["SDL_VIDEODRIVER"] = "dummy"
            self.screen = pygame.display.set_mode(self.SCREEN_RESOLUTION, 0, 24)
        else:
            self.screen = pygame.display.set_mode(self.SCREEN_RESOLUTION)
        pygame.display.set_caption('Pong')
        pygame.font.init()
        self.myfont = pygame.font.SysFont("Arial", 15)
        # Define colors
        self.BACKGROUND_COLOR = (0, 0, 0)
        # Fill background
        self.background = pygame.Surface(self.screen.get_size())
        self.background = self.background.convert()
        self.background.fill(self.BACKGROUND_COLOR)
        # Draw init stuff
        self.screen.blit(self.background, (0, 0))
        # Define game clock
        self.clock = pygame.time.Clock()
        # Define all game objectsBall
        self.player1 = Player(1)
        self.player2 = Player(2)
        self.ball = Ball(self.GAME_AREA_CENTER[0], self.GAME_AREA_CENTER[1] - 2, 4, 4)
        # Other stuff
        self.p1_move_up = False
        self.p1_move_down = False
        self.p2_move_up = False
        self.p2_move_down = False

    def set_names(self, p1, p2):
        self.player1.name = p1
        self.player2.name = p2
    def step(self, actions):
        """
        This functions is a modification of the openai gym step function for two players. The render option can be set directly in this functions

        TODO:
        catch error if wrong player id is entered

        ARGUMENS:
        player: integer; player=1: left player, player=2: right player
        action: the action the player took
        r: render the game or not

        RETURN:
        observation: return the current state of the game area mirrored so that every player plays from the perspective of the left player. This is done to speed up the training
        reward: the reward the given player got
        done: episode over
        info: debug output
        """
        info = {}
        r = True
        # Draw background if we want to render
        if r: self.background.fill(self.BACKGROUND_COLOR)
        if r: self.screen.blit(self.background, (0, 0))

        # Handle Player1's action
        if actions[0] == self.MOVE_UP:
            self.player1.move_up()
        elif actions[0] == self.MOVE_DOWN:
            self.player1.move_down()

        # Handle Player2's action
        if actions[1] == self.MOVE_UP:
            self.player2.move_up()
        elif actions[1] == self.MOVE_DOWN:
            self.player2.move_down()

        # ==================Logic============================
        # Check if the ball collided with one of the players
        if self.player1.rect.colliderect(self.ball.rect) and self.ball.last_touch is not 1:
            self.__reflect(self.player1.y, 1)
        if self.player2.rect.colliderect(self.ball.rect) and self.ball.last_touch is not 2:
            self.__reflect(self.player2.y, 2)

        # Move ball and check if game is over
        winner, done = self.ball.move()
        player1_reward = 0
        player2_reward = 0
        if done:
            if winner == 1:
                player1_reward = 10
                player2_reward = -10
                self.player1.score += 1
            if winner == 2:
                player1_reward = -10
                player2_reward = 10
                self.player2.score += 1
        # ==================Draw=============================
        if r: self.__draw_scores()
        if r: self.__render_ball()
        if r: self.__render_player1()
        if r: self.__render_player2()
        # =================Return========================
        observation_left = self.__get_observation(1)
        observation_right = self.__get_observation(2)

        return (observation_left, observation_right), (player1_reward, player2_reward), done, info

    def reset(self):
        # paint over the old frame
        self.background.fill(self.BACKGROUND_COLOR)
        self.screen.blit(self.background, (0, 0))
        # TODO Reset player scores
        self.ball.reset_ball()
        self.player1.reset()
        self.player2.reset()

        # Draw the changes so they are in the frame
        self.__render_player1()
        self.__render_player2()
        self.__draw_scores()
        self.__render_ball()
        return self.__get_observation(1), self.__get_observation(2)

    def __reflect(self, player_y, player):
        offcenter = abs(player_y - self.ball.y)
        if player_y > self.ball.y:
            if player == 1:
                direction = 1
            else:
                direction = -1
        else:
            if player == 1:
                direction = -1
            else:
                direction = 1
        self.ball.reflect(offcenter, direction, player)
        self.ball.last_touch = player  # Which player touched the ball last

    def __render_ball(self):
        # Draw ball
        pygame.draw.rect(self.screen, self.ball.color, self.ball.rect)

    def __render_player1(self):
        pygame.draw.rect(self.screen, self.player1.color, self.player1.rect)

    def __render_player2(self):
        pygame.draw.rect(self.screen, self.player2.color, self.player2.rect)

    def __draw_scores(self):
        # Draw the scoreboard
        scoreboard_background = pygame.Rect(0, 0, self.GAME_AREA_RESOLUTION[0], 35)
        scoreboard_border = pygame.Rect(1, 0, self.GAME_AREA_RESOLUTION[0] - 2, 35 - 2)
        scoreboard_separator = pygame.Rect(self.GAME_AREA_RESOLUTION[0] / 2 - 4, 0, 5, 35)
        pygame.draw.rect(self.screen, (150, 150, 150), scoreboard_background)
        pygame.draw.rect(self.screen, (0, 0, 0), scoreboard_border, 4)
        pygame.draw.rect(self.screen, (0, 0, 0), scoreboard_separator)
        #label_player_1 = self.myfont.render("{}".format(self.player1.name), 1, (0,255,0))
        #self.screen.blit(label_player_1, (5,5))
        label_score_p1 = self.myfont.render("{}: {}".format(self.player1.name,self.player1.score), 1, (0, 255, 0))
        self.screen.blit(label_score_p1, (5, 5))
        label_score_p2 = self.myfont.render("{}: {}".format(self.player2.name, self.player2.score), 1, (255, 0, 0))
        self.screen.blit(label_score_p2, (5 + self.SCREEN_RESOLUTION[0] / 2 + 4, 5))
        self.__render_ball()

    def __get_observation(self, player):
        """
        This function computes the observation depending on the player. player gets the normal observation and player 2 the inverted
        """
        if player == 1:
            observation_red = pygame.surfarray.pixels_red(self.screen)[:,35:]
            observation_green = pygame.surfarray.pixels_green(self.screen)[:,35:]
            observation_blue = pygame.surfarray.pixels_blue(self.screen)[:,35:]
            observation = np.stack((observation_red,observation_green, observation_blue),axis=2)
            observation = np.rot90(observation)
        # Player 2 gets a frame with inverted colors and inverted positions so that both sides look the same to the agent
        if player == 2:
            observation_green = pygame.surfarray.pixels_red(self.screen)[:,35:]
            observation_red = pygame.surfarray.pixels_green(self.screen)[:,35:]
            observation_blue = pygame.surfarray.pixels_blue(self.screen)[:,35:]
            observation = np.stack((observation_red,observation_green, observation_blue),axis=2)
            observation = np.rot90(observation)
            observation = np.flip(observation, 1)
        return observation

    def render(self):
        # Make sure game doesn't run at more than 30 frames per second
        # If we dont render we dont want this limitation
        self.clock.tick(60)
        pygame.event.get()

        # This method is used for everything regarding the rendering. Here pygame would paint to the window
        pygame.display.flip()

    def end(self):
        pygame.quit()


################################################################################
# Copyright (c) 2017                                                           #
# Intwine Connect, LLC.                                                        #
#                                                                              #
# BSD-2-Clause                                                                 #
# DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS                                  #
# Redistribution and use in source and binary forms, with or without           #
# modification, are permitted provided that the following conditions are met:  #
# 1. Redistributions of source code must retain the above copyright notice,    #
#    this list of conditions and the following disclaimer.                     #
# 2. Redistributions in binary form must reproduce the above copyright notice, #
#    this list of conditions and the following disclaimer in the documentation #
#    and/or other materials provided with the distribution.                    #
#                                                                              #
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,        #
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR       #
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR            #
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,        #
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,          #
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  #
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,     #
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR      #
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF       #
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                   #
################################################################################

import urllib
import json
import datetime as dt

class cbDevice():
    """CloudBUS Device Class

    """
    guid = None
    data = {}

    def __init__(self, guid=None):
        if guid is not None:
            self.guid = guid

    def setGUID(self, guid):
        """Assigns the cbDevice a specified guid

        Args:
            guid: the string representation of the device identifier
        """

        assert guid is True, "GUID can not be empty"
        self.__init__(guid)

    def getData(self, variable, tstart=None, tend=None):
        """Get data from the CloudBUS device APIs

        Request all reported values of data sent to CloudBUS from this specific
        device with attribute = variable.  If desired, the time range over which
        the data was collected can be specified.

        Args:
            variable: name of the attribute for which to get historical data
            tstart:   optional datetime of the earliest time for which to request
                      the specified attribute. Defaults to Unix time of 0.
            tend:     optional datetime of the most recent time for which to
                      request the specified attribute. Defaults to tomorrow.

        Returns:
            A tuple of lists. Element 0 of the tuple is a list of datetimes and
            element 1 is the list of attibute values at each of the element 0
            datetime points. The two lists will always be the same length. The
            lists are sorted so that element 0 of the time list is the earliest
            reported timestamp.
        """

        if tstart is None:
            tstart = dt.datetime.fromtimestamp(0)
        if tend is None:
            tend = dt.datetime.now() + dt.timedelta(days=1)  # tomorrow

        # build the CloudBUS URI
        url = 'http://54.172.91.188:8080/cloudbus/device/'
        query = '/data?attr=%s' % variable
        query += '&start=' + tstart.strftime("%Y-%m-%d %H:%M:%S")
        query += '&end=' + tend.strftime("%Y-%m-%d %H:%M:%S")
        query = query.replace(' ', '%20')

        # request the URL and read the response
        read_url = urllib.urlopen(url + self.guid + query)
        response = ""
        for line in read_url:
            response += line
        read_url.close()
        resp = json.loads(response)

        # format the data to be returned
        data = dict(resp['data'])
        a = sorted(data.items())
        t_vector = []
        y_vector = []
        for i in a:
            t_vector.append( dt.datetime.fromtimestamp(float(i[0])/1000.0) )
            y_vector.append( float(i[1]) )
        return t_vector, y_vector


# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys

# Find the path to the source files we want to to document, relative to the location of this file,
# convert it to an absolute path.
py_path = os.path.join(os.getcwd(), os.path.dirname(__file__), '../src')
sys.path.insert(0, os.path.abspath(py_path))

# -- Project information -----------------------------------------------------

project = 'Cirq on IQM'
copyright = '2020–2021, Cirq on IQM developers'
author = 'Cirq on IQM developers'

# The short X.Y version.
version = ''
# The full version, including alpha/beta/rc tags.
release = ''
try:
    from cirq_iqm import __version__ as version
except ImportError:
    pass
else:
    release = version

# -- General configuration ---------------------------------------------------

# require a recent version of Sphinx
needs_sphinx = '3.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    'sphinx.ext.napoleon',
    'sphinx.ext.mathjax',
    'sphinx.ext.todo',
    'sphinx_automodapi.automodapi',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.*']

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%Y-%m-%d'

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = True

# directory for the automodapi generated doc files
automodapi_toctreedirnm = 'api/api'

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = 'nature'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Output file base name for HTML help builder.
htmlhelp_basename = 'cirq_iqm-doc'

# -- MathJax options ----------------------------------------------------------

# Here we configure MathJax, mostly to define LaTeX macros.
mathjax_config = {
    'TeX': {
        'Macros': {
            'vr': r'\vec{r}',  # no arguments
            'ket': [r'\left| #1 \right\rangle', 1],  # one argument
            'iprod': [r'\left\langle #1 | #2 \right\rangle', 2],  # two arguments
        }
    }
}

# -- Options for sphinxcontrib.bibtex -------------------------------------------------

# List of all bibliography files used.
bibtex_bibfiles = ['references.bib']


"""
Inorder Predecessor in BST
Given a binary search tree and a node in it, find the in-order predecessor of that node in the BST.

Example

Example1
Input: root = {2,1,3}, p = 1
Output: null

Example2
Input: root = {2,1}, p = 2
Output: 1
Notice
If the given node has no in-order predecessor in the tree, return null

"""

# Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None

class Solution:
    def inorder_predecessor(self, root, p):

        self.predecessor, self.last_node = None, None

        def inorder_traversal(node, p):
            if not node or self.predecessor:
                return

            inorder_traversal(node.left, p)

            if node == p:
                self.predecessor = self.last_node
            else:
                self.last_node = node

            inorder_traversal(node.right, p)

        inorder_traversal(root, p)

        return self.predecessor.val

if __name__ == '__main__':
    p1 = TreeNode(2)
    p2 = TreeNode(1)
    p3 = TreeNode(3)
    p4 = TreeNode(0)

    p1.left = p2
    p1.right = p3
    p2.left = p4

    solution = Solution()

    print(solution.inorder_predecessor(p1, p1))


import cv2
import numpy as np
import threading
import json
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket

server = None
clients = []
capture = None

class SimpleWSServer(WebSocket):
	def handleConnected(self):
		clients.append(self)

	def handleClose(self):
		clients.remove(self)

def run_server():
	global server
	server = SimpleWebSocketServer('', 9000, SimpleWSServer,
								   selectInterval=(1000.0 / 60) / 1000)
	print("run_server")
	server.serveforever()

# t = threading.Thread(target=run_server)
# t.start()

# capture = cv2.VideoCapture(0)

def get_frame(capture):
	print("get_frame")
	success, image = capture.read()
	ret, jpeg = cv2.imencode('.jpg', image)
	return jpeg.tobytes()

t = 100
w = 640

last = 0

def main_code():
	global capture
	capture = cv2.VideoCapture(0)
	global server
	while True:
		ret, image = capture.read()
		# print("ret ",ret)
		img_height, img_width, depth = image.shape
		scale = w / img_width
		h = img_height * scale
		image = cv2.resize(image, (0,0), fx=scale, fy=scale)

		# Apply filters
		grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
		blured = cv2.medianBlur(grey, 9)

		image = np.dstack([cv2.Canny(blured, t / 2, t)] * 3)

		#cv2.imshow('Image previews', image)

		sc = 1
		md = 30
		at = 40
		circles = cv2.HoughCircles(blured, cv2.HOUGH_GRADIENT, sc, md, t, at)

		if circles is not None:
			# We care only about the first circle found.
			circle = circles[0][0]
		if circle.size == 3:
				x, y, radius = int(circle[0]), int(circle[1]), int(circle[2])
				#print(float(x) / float(w), float(y) / float(h), float(radius) / float(w))

				# Highlight the circle
				#cv2.circle(image, (x, y), radius, (0, 0, 255), 1)
				# Draw dot in the center
				#cv2.circle(image, (x, y), 1, (0, 0, 255), 1)

				for client in clients:
						client.sendMessage(unicode(json.dumps({'x': float(x) / float(w), 'y': float(y) / float(h), 'radius': float(radius) / float(w)})))

		# cv2.imshow('Image with detected circle', image)

		# if cv2.waitKey(1) & 0xFF == ord('q'):
			# break

	server.close()

# t1 = threading.Thread(target=main_code)
# t1.start()
# main_code()


# _import_export.py

import os, traceback, sys
import h5py
from glob import glob
from PyQt5.QtWidgets import QFileDialog
from matplotlib.ticker import FormatStrFormatter

import glob_var as cts
import numpy as np
import analysis_functions as af
import scipy.special as sp

class Imp_Exp_Mixin:

    def import_tof(self, filename):
        if cts.software_version != 2:
            with open(filename, 'r', encoding='utf-8', errors='ignore') as file:
            #with open(filename, 'r') as file:#with open(filename, 'r', encoding='utf-8',errors='ignore') as file:
                i = 0
                data = []
                try:
                    cts.path = filename
                    #data = [[float(digit) for digit in line.split()] for line in file]
                    for line in file:
                        if i < cts.skiplines:
                            # skipping header lines
                            pass
                        else:
                            data.append([float(digit) for digit in line.split()])
                        i += 1

                    '''
                    if cts.decimal_separ == 'dot':
                        data = [[float(digit) for digit in line.split()] for line in file]
                    elif cts.decimal_separ == 'comma':
                        data = [[float(digit.replace(',', '.')) for digit in line.split()] for line in file]
                    else:
                        print("Error in the code")'''

                except ValueError: #if the decimal separator is a comma
                    data = [[float(digit.replace(',', '.')) for digit in line.split()] for line in file]

                except IndexError:
                    print('Incorrect data file')
                    self.window().statusBar().showMessage('Incorrect data file')

                except Exception:
                    print(traceback.format_exception(*sys.exc_info()))

                finally:
                    data_array = np.asarray(data)  # converting 1D list into 2D array

        else:
            spectrum_i = cts.spectrum_i
            with h5py.File(filename, 'r') as file:
                cts.path = filename
                path = ''.join(['Scan',cts.str_scan_i,'/Detector000/Data1D/Ch000/'])
                raw_datas = file['Raw_datas']
                data_scan = np.array(raw_datas[path+'Data'])  # whole rabbit trace
                data = data_scan[spectrum_i,cts.skiplines:]  # taking tof spectrum corresponding to asked index
                tof = np.array(raw_datas[path+'X_axis'])[cts.skiplines:]
                data_array = np.column_stack((tof, data))

                self.window().updateglobvar_fn()

        return data_array

    # called by CalibWin or RabbitWin
    def importcalib_lr(self):
        #From a calibration file, loading afit, t0fit, cfit and the first harmonic
        # this function can be call either from the calibration tab or the rabbit tab. This means "self" represents
        # either an instance of CalibWin or RabbitWin.

        calib_tab = self.window().calib_tab
        rabbit_tab = self.window().rabbit_tab

        calib_fname = QFileDialog.getOpenFileName(self, 'Import calibration')
        calib_f = calib_fname[0]
        if (calib_f):
            with open(calib_f, 'r') as file:
                f = file.read().splitlines()
                try:
                    if (len(f) < 3):
                        raise IndexError
                    cts.afit, cts.t0fit, cts.cfit = [float(f[i]) for i in range(3)]

                    # calib_win part
                    calib_tab.calibloaded = True
                    calib_tab.calibBool = True
                    calib_tab.tof2en_btn.setEnabled(True)
                    calib_tab.update_fitpar_fn()

                    # rabbit_win part
                    rabbit_tab.reset_btn()
                    rabbit_tab.importdata_btn.setEnabled(True)

                    cts.calibloaded = True

                    self.window().updateglobvar_fn()

                except IndexError:
                    print('Not enough data in the calib file. Needed: a_fit, t0_fit and c_fit')
                except ValueError:
                    print("Incorrect calibration data")

    # called by CalibWin
    def exportcalib_lr(self):
        # Exporting afit, t0fit, cfit and the first harmonic in a file after choosing its name and location

        filename = QFileDialog.getSaveFileName(self, 'Save XUV')
        fname = filename[0]
        if fname:
            fit_param = self.p_opt
            np.savetxt(fname, fit_param, fmt='%1.4e', delimiter='\t')

    # called by RabbitWin
    def exportrab_lr(self):
        ''' "[Export] RABBIT" button listener. Saves the rabbit in two files: *_counts for the data and *_param for
        the parameters'''
        rab_fname = QFileDialog.getSaveFileName(self)
        rab_f = rab_fname[0]
        try:
            if (rab_f):
                header = 'elow\nehigh\ndE\nstepsnb\nbscanstep_nm\nafit\nt0fit\ncfit\nfirst_harm'
                self.rabbit_param = np.array([cts.elow, cts.ehigh, cts.dE, cts.stepsnb, cts.scanstep_nm,
                                              cts.afit, cts.t0fit, cts.cfit, cts.first_harm])
                np.savetxt((rab_f + "_param.txt"), self.rabbit_param, fmt='%.5e',
                           delimiter='\t',header=header)
                np.savetxt((rab_f + "_counts.txt"), cts.rabbit_mat, fmt='%.5e', delimiter='\t')
        except Exception:
            print(traceback.format_exception(*sys.exc_info()))

    # called by VMIWin
    def exportS3D_lr(self):
        ''' "[Export] RABBIT" button listener. Saves the rabbit in two files: *_counts for the data and *_param for
        the parameters'''

        S3D_fname = QFileDialog.getSaveFileName(self)
        S3D_f = S3D_fname[0]

        theta = np.linspace(0, np.pi / 2, 360, endpoint=False)
        ee, tt = np.meshgrid(cts.energy_vect, theta)
        print('np.shape(ee)'+ str(np.shape(ee)))

        angle_width_360 = cts.angle_width * 360 / 90
        print('angle_width_360 = '+str(angle_width_360))
        print('OK 1')
        S3D = []
        Em_angles_i_360 = [int(k * 360 / 90) for k in cts.angle_list]
        print('OK 2')
        for tau in range(0, len(cts.delay_vect)):
            # print(np.shape(sp.eval_legendre(0, np.cos(tt))))
            # print(np.shape(cts.rabbit_mat_P0[tau]))
            S3D_tau = cts.rabbit_mat_P0[tau] * sp.eval_legendre(0, np.cos(tt)) + \
                      cts.rabbit_mat_P2[tau] * sp.eval_legendre(2, np.cos(tt)) + cts.rabbit_mat_P4[tau] * sp.eval_legendre(4, np.cos(tt))
            S3D.append(S3D_tau)

        for theta_k in Em_angles_i_360:
            RABBIT_intg_ang = []
            theta_k_i = theta_k
            theta_k_f = theta_k + angle_width_360
            for i in range(0, len(S3D)):  # len(S3D) = 80 : delays
                S3D_t = S3D[i]  # (theta, E) at a given delay
                a = np.shape(ee)[1]
                RABBIT_sum = np.zeros([a])
                for j in range(int(theta_k_i), int(theta_k_f)):
                    RABBIT_sum = RABBIT_sum + S3D_t[j] * np.sin(j * 90 / 360 * 2 * np.pi / 360)
                RABBIT_intg_ang.append(RABBIT_sum)

            RABBIT_intg_ang = np.array(RABBIT_intg_ang)
            RABBIT_intg_ang3 = RABBIT_intg_ang.T  # only for saved data for analysis_GUI
            S3D_f = S3D_fname[0]
            theta_i_deg = theta_k_i * 90 / 360
            theta_f_deg = theta_k_f * 90 / 360
            name = cts.ang_filenametype.replace('0_5_deg', str(theta_i_deg) + '_' + str(theta_f_deg)+ '_deg')
            try:
                if (S3D_f):
                    np.savetxt((S3D_f + name +".txt"), RABBIT_intg_ang3, fmt='%.5e',
                               delimiter='\t')
            except Exception:
                print(traceback.format_exception(*sys.exc_info()))

    def save_phVSangle(self):
        ''' "[Export] RABBIT" button listener. Saves the phase VS angle of current SB. If ang intg is calcculated and the box is checked, it is also saved in another file'''

        save_phVSangle_fname = QFileDialog.getSaveFileName(self)
        save_phVSangle_f = save_phVSangle_fname[0]

        C = np.vstack((cts.Phi,cts.DPhi))
        Cbis = np.vstack((cts.Ampl,C))
        D = cts.tt_angles*180/np.pi
        E = np.vstack((D,Cbis)).T

        if cts.Add_angl_intg:
            self.SB_i = cts.sb_order.index(cts.SBi_choice)
            Phi_rec = cts.data_2w_std_ang[:, int(self.SB_i), 3]
            Ampl_rec = cts.data_2w_std_ang[:, int(self.SB_i), 2]
            if cts.Change_Sign:
                Phi_rec = - cts.data_2w_std_ang[:, int(self.SB_i), 3]
            Phi_rec_err = cts.data_2w_std_ang[:, int(self.SB_i), 4]
            U = np.vstack((Phi_rec, Phi_rec_err))
            Ubis = np.vstack((Ampl_rec, U))
            V = np.vstack((cts.angle_list, Ubis)).T

        try:
            if (save_phVSangle_f):
                np.savetxt((save_phVSangle_f + ".txt"), E , fmt='%.5e',
                           delimiter='\t' , header=" Angle(°) \t Amplitude(arbU) \tPhase (rad) evolving with angle\t Phase error(rad) \t")
                if cts.Add_angl_intg:
                    np.savetxt((save_phVSangle_f + '_angularly_intg'+".txt"), V, fmt='%.5e',
                               delimiter='\t',
                               header="Angle(°) \t Ampl(arbU) \t Phase (rad)\t Phase error(rad)\t")
        except Exception:
            print(traceback.format_exception(*sys.exc_info()))

    # called by RabbitWin
    def export_2w_lr(self):
        ''' "[Export] 2w" button listener'''
        twow_fname = QFileDialog.getSaveFileName(self)
        twow_f = twow_fname[0]
        try:
            if (twow_f):
                data_2w = np.dstack((self.energy, cts.peak, cts.peak_phase, cts.rabbit_mat.sum(axis=0)))[0]
                data_2w = np.array(data_2w)
                np.savetxt((twow_f), data_2w, fmt='%.5e', delimiter='\t',
                           header="Photon energy [eV]\t 2w Ampl [arb. u.] \t 2w Phase [rad] \
                            \t delay-integrated RABBIT trace")
        except Exception:
            print(traceback.format_exception(*sys.exc_info()))

    def export_2w_std_lr(self):
        ''' "[Export] 2w" button listener'''
        twow_fname = QFileDialog.getSaveFileName(self)
        twow_f = twow_fname[0]
        try:
            if (twow_f):
                data_2w = np.dstack((cts.bands_vect[:,0],cts.bands_vect[:,1], cts.peak, cts.peak_phase, cts.phase_err))[0]
                data_2w = np.array(data_2w)
                np.savetxt((twow_f), data_2w, fmt='%.5e', delimiter='\t',
                           header="Photon energy min[eV]\t Photon energy max[eV]\t 2w Ampl [arb. u.] \t 2w Phase [rad]\t 2w Phase error [rad]")
        except Exception:
            print(traceback.format_exception(*sys.exc_info()))

    # called by RainbowWin (_Rabbit_win_subwidgets.RainbowWin)
    def export_lr(self) -> None:
        filenamesave = QFileDialog.getSaveFileName(self)
        fname = filenamesave[0]
        try:
            if fname:
                en=[]
                amp=[]
                phase=[]
                header = "FT_padding = " + str(cts.FT_padding) + ", " + \
                         "FT_window = " + str(cts.FT_window) + ", " + \
                         "FT_zero_order = " + str(cts.FT_zero_order) + ", " + \
                         "FT_npad = " + str(cts.FT_npad) + "\n" + \
                         "two_w_average = " + str(cts.two_w_average) + ", " + \
                         "two_w_bfilter = " + str(cts.two_w_bfilter) + ", " + \
                         "two_w_integral = " + str(cts.two_w_integral) + ", " + \
                         "two_w_phioffset = " + str(cts.two_w_phioffset) + "\n\n" + \
                         "energy (eV)\t2w_amplitude\t2w_phase"
                k=0
                for i in range(self.par.energy_rainbow.shape[0]):
                    if (self.par.energy_rainbow[i] - self.par.energy_rainbow[i - 1] >\
                                    2 * cts.dE or i == self.par.energy_rainbow.shape[0] - 1):
                        l = np.array([en, amp, phase])
                        l = np.transpose(l)
                        np.savetxt((fname + "_SB" + str(cts.first_harm + 1 + 2 * k) + ".txt"), l, fmt='%.5e',
                                   delimiter='\t', header=header)
                        del en[:]
                        del amp[:]
                        del phase[:]
                        k += 1
                    en.append(self.par.energy_rainbow[i])
                    amp.append(cts.peak[i])
                    phase.append(cts.peak_phase[i])

        except Exception:
            print(traceback.format_exception(*sys.exc_info()))


import os
import subprocess
import socket
from time import sleep
import psutil
import n4d.responses

class RemoteWebGui:

	def __init__(self):
		self.dbg=False
	#def init

	def _debug(self,msg):
		if self.dbg:
			print("[RemoteWebGui] %s"%msg)
	#def _debug

	# Perhaps a get_first_xpra_port_free is needed...
	def get_first_display_free(self):
		'''
		Returns first Display free from 42
		'''
		display=42
		try:
			while(os.path.isfile('/tmp/.X'+str(display)+'-lock')):
				display+=1
			return ":"+str(display)
		except Exception as e:
			print("Captured: "+str(e))
			return {'status': False, 'msg':'[RemoteGuiManager] '+str(e)}
	#def get_first_display

	def get_first_free_port(self):
		'''
		Returns first opened port, starting by 10013
		'''
		retval=-1
		port=10013
		sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

		while (port<99999):
			status=sock.connect_ex(('127.0.0.1', port))
			self._debug("checking port "+str(port)+" is "+str(status))
			if status!=0:
				retval=port
				break
			port=port+1
		return retval
	#def get_first_free_port

	def create_connection(self,  username, xephyr_options=" -ac -screen 1024x768 -dpi 96 "):
		# Username is needed as parameter and return value must be the port
		os.environ["HOME"]="/home/"+username
		os.environ["XAUTHORITY"]="/home/"+username+"/.Xauthority"

		display=self.get_first_display_free()
		port=self.get_first_free_port()

		self._debug("PORT: %s DISPLAY: %s"%(port,display))

		xephyr_cmd="Xephyr "+xephyr_options+" "+display
		xpra_cmd="xpra start --bind-tcp=0.0.0.0:"+str(port)
		xpra_cmd=xpra_cmd+" --html=on --no-pulseaudio --systemd-run=no --exit-with-children --start-via-proxy=no  --start-child='"+xephyr_cmd+"'"

		self._debug("Exec: "+xpra_cmd)
		try:
			p=subprocess.call([xpra_cmd], shell=True);
		except Exception as e:
			print("[RemoteWebGui] create_connection Exception: {}".format(e))
			return n4d.responses.build_failed_call_response(ret_msg=str(e))
			# return {'status':False, 'msg': str(e)}

		# wait until port is listening
		sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		status=111
		while (status!=0):
			status=sock.connect_ex(('127.0.0.1', port))

		self._debug("port "+str(port)+" is available with status: "+str(status))
		return n4d.responses.build_successful_call_response({"port":str(port), "display":display})
		# return {"status":True, "msg":{"port":str(port), "display":display}}
	#def remote_execute

	def create_connection_vnc(self, id, options):
		try:
			startup='/etc/X11/Xsession'
			if options and isinstance(options,str):
				if options == 'terminal':
					startup='/usr/bin/run_terminal'
				elif options == 'minimal':
					startup='/usr/bin/jwm'
				elif options == 'run_lliurex_up':
					startup = '/usr/sbin/lliurex-up'
				elif options == 'run_synaptic':
					startup = "/usr/sbin/synaptic"
			port=self.get_first_free_port()
			self._debug("PORT: %s DISPLAY: %s"%(port,id))
			chroot = "/opt/ltsp/{}".format(id)
			self.machineid=id
			self.nspawn = subprocess.Popen("/usr/bin/systemd-nspawn -E XDG_CONFIG_DIRS=/home/root/.config/kdedefaults:/etc/xdg/lliurex/classroom:/etc/xdg/lliurex/layouts/current:/etc/xdg/lliurex/desktop:/etc/xdg/xdg-plasma:/etc/xdg -E SHELL=/bin/bash -E LANG=es_ES.utf8 --private-users=0 --private-users-chown -M {} -D{} tigervncserver -SecurityTypes None -depth 24 -geometry 1024x768 -fg -xstartup {}".format(id,chroot,startup),shell=True)
			retry = 3
			while retry>0:
				try:
					p=subprocess.check_output('pgrep tigervncserver',shell=True)
					p=p.strip()
					retry=0
				except Exception as e:
					sleep(1)
					retry-=1
					pass
			self.tiger=int(p)
		except Exception as e:
			print("[RemoteWebGui] create_connection Exception: {}".format(e))
			return n4d.responses.build_failed_call_response(ret_msg=str(e))
			# return {"status":False,"msg":e}
		return n4d.responses.build_successful_call_response({"port": str(port), "process": self.nspawn.pid})
		# return {"status":True, "msg":{"port": str(port), "process": self.nspawn.pid}}

	def close_connection(self, port):
		retval=0
		try:
			cmd='xpra stop tcp:0.0.0.0:'+str(port)
			subprocess.call([cmd], shell=True)
		except Exception as e:
			print("close_connection: %s"%e)
			retval=-1
		return n4d.responses.build_successful_call_response(retval)
		# return retval
	#def close_connection

	def close_connection_vnc(self, port):
		retval=0
		try:
			import os
			try:
				os.kill(self.tiger,15)
				sleep(1)
				os.kill(self.websockify.pid,15)
				sleep(1)
				os.system('machinectl kill {}'.format(self.machineid))
				os.system('machinectl kill {}'.format(self.machineid))
				os.system('machinectl kill {}'.format(self.machineid))
			except:
				pass
		except Exception as e:
			print("close_connection: %s"%e)
			retval=-1
		return n4d.responses.build_successful_call_response(retval)
		# return retval
	#def close_connection

	def run_into_connection(self, command, display):
		self._debug("Sleeping...\n")
		#There's a race condition and sometimes DISPLAY is not set... wait a moment for it
		sleep(7)
		self._debug("Wake up...\n")
		cmd='export DISPLAY='+display+";"+command
		self._debug(cmd)
		try:
			#//p=subprocess.call([cmd], shell=True)
			p=subprocess.Popen([cmd], shell=True)
		except Exception as e:
			print("Run_into_connection: %s"%e)
			p=-1
		return n4d.responses.build_successful_call_response(p)
		# return p
	#def run_into_connection

	def run_into_connection_vnc(self, command, port):
		cmd = "/usr/bin/websockify --web /usr/share/novnc {} localhost:5901".format(port)
		try:
			p=subprocess.Popen([cmd], shell=True)
			self.websockify = p
		except Exception as e:
			print("Run_into_connection: %s"%e)
			p=-1
		return n4d.responses.build_successful_call_response(True)
		# return p
	#def run_into_connection

	def getXpraConnections(self, identifier):
		bind_arr=[]
		display_arr=[]
		ret=[]
		for p in psutil.process_iter(attrs=['cmdline']):
			if len(p.info['cmdline'])>2:
				if (('DISPLAY' in p.info['cmdline'][-1]) and (identifier in p.info['cmdline'][-1])):
					for disp in p.info['cmdline'][-1].split():
						if 'DISPLAY' in disp:
							display_arr.append(disp.split(';')[0].split('=')[-1])
				elif ((len(p.info['cmdline'])>3) and ('bind-tcp' in p.info['cmdline'][3])):
					bind_arr.append(' '.join(p.info['cmdline']))

		for display in display_arr:
			for bind in bind_arr:
				if bind.endswith(display):
					port=bind.split(' ')[3].split(':')[-1]
					ret.append([port, display])
		return n4d.responses.build_successful_call_response(ret)
		# return ret
	#def getXpraConnections

#class RemoteWebGui


from django.urls import path

from .import views

urlpatterns = [
    path('tasks', views.TaskView.as_view(), name='tasks'),
    path('tasks/create', views.TaskCreate.as_view(), name='task-create'),
    path('tasks/<int:pk>', views.TaskRetrieve.as_view(), name='task-detail')
]


from typing import Dict
import pandas as pd
import datetime as dt
from src.typeDefs.iexDamRecord import IIexDamDataRecord
from typing import List

def getIexDamData(targetFilePath: str) -> List[IIexDamDataRecord]:
    iexDamRecords: List[IIexDamDataRecord] = []

    iexDamDf = pd.read_excel(
        targetFilePath, sheet_name="MarketMinute", skiprows= 5, nrows= 96)
    iexDamDf = iexDamDf.rename(columns={
        'None.1': 'time_block', 'Date | Hour | Time Block': 'Date'})
    # for itr in range(iexDamDf['None.1']):
    #     iexDamDf[]
    # del iexDamDf[None]
    iexDamDf = iexDamDf.drop([None, 'Unnamed: 4'], axis=1)
    iexDamDf = iexDamDf.loc[:, ~iexDamDf.columns.duplicated()]
    iexDamDf[['first_block','First','last_block']] = iexDamDf.time_block.str.split(" ",expand=True)
    # iexDamDf[['First','Last']] = iexDamDf.time_block.str.split(expand=True)
    iexDamDf = iexDamDf.drop(['First', 'last_block', 'time_block'], axis=1)
    iexDamDf[['hour','minute']] = iexDamDf.first_block.str.split(":",expand=True)
    iexDamDf['Date'] = iexDamDf['Date'][0]
    iexDamDf[['day','month','year']] = iexDamDf.Date.str.split("-",expand=True)
    iexDamDf['Date'] = pd.to_datetime(iexDamDf[['year', 'month', 'day', 'hour', 'minute']])
    iexDamDf = iexDamDf.drop(['year', 'month', 'day', 'first_block','hour','minute'], axis=1)
    iexDamDf = pd.melt(iexDamDf, id_vars=['Date'])
    # iexDamDf = iexDamDf.rename(columns={
    #     'variable': 'metric_name', 'value': 'data_val',
    #     'Date': 'data_time'})
    iexDamRecords = iexDamDf.to_dict('records')

    return iexDamRecords


import os, os.path, time
from werkzeug.utils import secure_filename
from flask import Flask, request
from effnetb0 import Effnetb0

UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.nitf'}

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
model = Effnetb0()

@app.route('/')
def index():
    return 'Aletheia Service: Try uploading an image to /classify to use this model'

@app.route('/classify', methods=['GET', 'POST'])
def classify():
    def is_file_allowed(filename):
        return os.path.splitext(filename)[1].lower() in ALLOWED_EXTENSIONS
    file = request.files.get('file')
    if file == None or file == '':
        return 'No file given'
    elif not is_file_allowed(file.filename):
        return 'File not allowed. Received {0} but was expecting one of types {1}'.format(file.filename, ALLOWED_EXTENSIONS)
    else:
        filename = secure_filename(file.filename)
        save_destination = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(save_destination)
        pred = model.classify([save_destination])
        return {
            "pred": str(pred[0]),
        }


#Example : Open the serial port method , Output opened successfully through the console

import serial

ser = serial.Serial()
ser.baudrate = 115200
ser.port = 'COM10'
ser.open()

if ser.is_open:
    print("open port",ser.port,"is suceess","baudrate:",ser.baudrate)
else:
    print("open port",ser.port,"is failed","baudrate:",ser.baudrate)


import argparse
import json
import logging
import http.client
import urllib.parse
import datetime
import time
from tqdm import tqdm
from flair.models import SequenceTagger
from flair.data import Sentence
from common.dataset.reader import JSONLineReader
from common.util.random import SimpleRandom
from retrieval.fever_doc_db import FeverDocDB
from rte.riedel.data import FEVERLabelSchema, FEVERGoldFormatter
from nltk.corpus import stopwords
logger = logging.getLogger(__name__)  # pylint: disable=invalid-name
#from allennlp.predictors.predictor import Predictor

# Replace the subscriptionKey string value with your valid subscription key.
subscriptionKey = '<enter valid subscription key>'

host = 'api.cognitive.microsoft.com'
path = '/bing/v7.0/entities'

def get_suggestions(query):
    headers = {'Ocp-Apim-Subscription-Key': subscriptionKey}
    conn = http.client.HTTPSConnection(host)

    mkt = 'en-US'
    params = '?mkt=' + mkt + '&q=' + urllib.parse.quote(query)

    conn.request("GET", path + params, None, headers)
    response = conn.getresponse()
    return response.read()

class FEVERReader:
    """
    Read full text for evidence sentences from fever db
    """

    def __init__(self,
                 db: FeverDocDB) -> None:
        self.db = db
        self.formatter = FEVERGoldFormatter(set(self.db.get_doc_ids()), FEVERLabelSchema())
        self.reader = JSONLineReader()

    def get_doc_line(self,doc,line):
        lines = self.db.get_doc_lines(doc)
        if line > -1:
            return lines.split("\n")[line].split("\t")[1]
        else:
            non_empty_lines = [line.split("\t")[1] for line in lines.split("\n") if len(line.split("\t"))>1 and len(line.split("\t")[1].strip())]
            return non_empty_lines[SimpleRandom.get_instance().next_rand(0,len(non_empty_lines)-1)]

    def get_evidence_text(self, evidence):
        lines = set([self.get_doc_line(d[0], d[1]) for d in evidence])
        premise = " ".join(lines)
        return premise

def contains_word(s, w):
    return f' {w} ' in f' {s} '

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--db', type=str, help='/path/to/saved/db.db')
    parser.add_argument('--split',type=str)
    args = parser.parse_args()

    db = FeverDocDB(args.db)
    split = args.split
    fever = FEVERReader(db)

    #delete the below model from the cache
    #predictor = Predictor.from_path("https://s3-us-west-2.amazonaws.com/allennlp/models/ner-model-2018.04.26.tar.gz")
    tagger = SequenceTagger.load('ner')

    throttle_start = datetime.datetime.now()

    with open("data/fever/{0}.ns.pages.p1.jsonl".format(split),"r") as f:
        with open("data/fever/{0}.ns.ner.pages.p1.jsonl".format(split),"w+") as f2:
            for line in tqdm(f.readlines()):
                js = json.loads(line)

                fever_line = fever.formatter.format_line(js)
                evidence = fever.get_evidence_text(fever_line["evidence"])

                #tags = predictor.predict(
                 #   sentence=evidence
                #)

                evidence_ner = Sentence(evidence)
                claim_ner = Sentence(fever_line["claim"])
                # predict NER tags
                tagger.predict(evidence_ner)
                tagger.predict(claim_ner)
                evidence_tags = evidence_ner.to_dict(tag_type='ner')
                claim_tags = claim_ner.to_dict(tag_type='ner')

                missing_entity = False
                for c_entity in claim_tags["entities"]:
                    if not contains_word(evidence, c_entity["text"]):
                        missing_entity = True
                        break

                claim_tags_list = list([c["text"] for c in claim_tags["entities"]])
                js["ner_claim"] = claim_tags_list
                js["ner_evidence"] = list([c["text"] for c in evidence_tags["entities"]])
                js["ner_missing"] = missing_entity
                js["ner_related"] = []
                js["fact"] = []

                try:
                    throttle_now = datetime.datetime.now() - throttle_start
                    if throttle_now.total_seconds() < 0.25:
                        time.sleep(0.25)

                    bing_res = get_suggestions(' '.join(claim_tags_list))
                    throttle_start = datetime.datetime.now()
                    bing = json.loads(bing_res)
                    if 'entities' in bing:
                        for b_values in bing['entities']['value']:
                            for c in claim_tags_list:
                                if contains_word(b_values['description'], c):
                                    js["ner_related"].append([b_values['name'], c])

                            for w in fever_line["claim"].split():
                                if w not in claim_tags_list and w not in stopwords.words('english'):
                                    if contains_word(b_values['description'], w):
                                        js["fact"].append([b_values['name'], w])
                    else:
                        js["ner_related"] = [["None"]]

                except Exception as e:
                    print(e)

                f2.write(json.dumps(js)+"\n")


#By counting the number of differences between two homologous DNA strands
#taken from different genomes with a common ancestor, we get a measure of
#the minimum number of point mutations that could have occurred on the
#evolutionary path between the two strands.

def distance(DNA_strand1,DNA_strand2):
    '''
    Calculates the hamming distance between two homologous DNA strands
    by counting the differences
    :param DNA_strand1: String
    :param DNA_strand2: String
    :return: int
    '''
    hamming_distance = 0

    if len(DNA_strand1) == len(DNA_strand2):
        for idx in range(len(DNA_strand1)):
            if DNA_strand1[idx] != DNA_strand2[idx]:
                hamming_distance += 1

    return hamming_distance


# Given a binary tree, return the inorder traversal of its nodes' values.

# For example:
# Given binary tree {1,#,2,3},

# Solution 1: Reursion
# Inorder traversal of Binary Tree
#  Visit a position between the recursive traversals of its left and right subtrees.
#  The inorder traversal of a binary tree T can be informally viewed as visiting
#  the nodes of T “from left to right.”
#  Indeed, for every position p, the inorder traversal visits p after all the positions
#   in the left subtree of p and before all the positions in the right subtree of p.
# Pseudo-code

# inorder(p):

# if p has left child lc
#   	inorder(lc)

# perform the visit action for position p

# if p has a right child rc then
# 	inorder(rc)
# Complexity: O(n) time, O(logn) space

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        self.helper(root, res)
        return res

    def helper(self, node, res):
        if not node:
            return
        self.helper(node.left, res)
        res.append(node.val)
        self.helper(node.right, res)

LeetCode-solutions/094-Binary Tree Inorder Traversal/solution.py


from setuptools import setup
import os

data_files = [
    ('share/applications/', ['IRCapp.desktop']),
    ('share/icons/hicolor/scalable/apps/', ['ircapp/core/static/ircapp_bolt.svg']),
    ('lib/python3/dist-packages/', ['rarfile.py']),
    ('lib/python3/dist-packages/', ['inflect.py'])
]

def copy_rec(root_dir):
    mylist = []
    for (dirpath, dirnames, filenames) in os.walk(root_dir):
        for f in filenames:
            mylist.append(("lib/python3/dist-packages/" + dirpath + "/", [os.path.join(dirpath, f)]))
    return mylist

data_files += copy_rec("ircapp")

setup(name='ircapp',
      # Keep version in sync with stdeb/__init__.py and install section
      # of README.rst.
      version='2.0.3',
      author='MrJ',
      description='Simple IRC Client',
      license='MIT',
      url='https://github.com/themadmrj/ircapp',
      #packages = ['ircapp'],
      #packages = ['ircapp/', 'django', 'irc', 'requests', 'cherrypy', 'pytz'],
      entry_points = {
        'gui_scripts' : ['ircapp = ircapp.main:start_ircapp']
      },
      data_files = data_files,

)


import pytz, datetime

year = int(input())
month = int(input())
date = int(input())
hour = int(input())
minute = int(input())

#converting to a date

users_time = datetime.datetime(year,month,date,hour,minute)

kolkata_timezone = pytz.timezone('Asia/Kolkata')
tokyo_timezone = pytz.timezone('Asia/Tokyo')
london_timezone = pytz.timezone('UTC')
sydney_timezone = pytz.timezone('Australia/Sydney')

kolkata_time = pytz.utc.localize(users_time).astimezone(kolkata_timezone)
tokyo_time = pytz.utc.localize(users_time).astimezone(tokyo_timezone)
london_time = pytz.utc.localize(users_time).astimezone(london_timezone)
sydney_time = pytz.utc.localize(users_time).astimezone(sydney_timezone)

print("Kolkata Time is -", kolkata_time.isoformat())
print("Tokyo Time is -", tokyo_time.isoformat())
print("London Time is -", london_time.isoformat())
print("Sydney Time is -", sydney_time.isoformat())


import pathlib
import sys

sys.path.insert(0, str(pathlib.Path(__file__).parent.parent.parent))

from absl import app
from urnai.agents.generic_agent import GenericAgent
from urnai.agents.rewards.default import PureReward
from urnai.agents.states.gym import GymState
from urnai.envs.gym import GymEnv
from urnai.models.ddqn_keras import DDQNKeras
from urnai.models.model_builder import ModelBuilder
from urnai.trainers.trainer import Trainer

def declare_trainer():
    env = GymEnv(id='CartPole-v0')

    action_wrapper = env.get_action_wrapper()
    state_builder = GymState(env.env_instance.observation_space.shape[0])

    helper = ModelBuilder()
    helper.add_input_layer()
    helper.add_fullyconn_layer(25)
    helper.add_output_layer()

    dq_network = DDQNKeras(action_wrapper=action_wrapper, state_builder=state_builder,
                           build_model=helper.get_model_layout(), use_memory=False,
                           gamma=0.99, learning_rate=0.001, epsilon_decay=0.9997, epsilon_min=0.01,
                           memory_maxlen=50000, min_memory_size=1000)

    agent = GenericAgent(dq_network, PureReward())

    # Cartpole-v0 is solved when avg. reward over 100 episodes is greater than or equal to 195
    trainer = Trainer(env, agent, save_path='urnai/models/saved',
                      file_name='cartpole-v0-unified-step-play3',
                      save_every=100, enable_save=True, relative_path=True,
                      max_training_episodes=1000, max_steps_training=500,
                      max_test_episodes=100, max_steps_testing=500)
    return trainer

def main(unused_argv):
    try:
        trainer = declare_trainer()
        trainer.train()
        trainer.play()

    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    app.run(main)