import os
import re
import sys
import argparse
from Sire.Base import *
from datetime import datetime
# Make sure that the OPENMM_PLUGIN_DIR enviroment variable is set correctly.
os.environ["OPENMM_PLUGIN_DIR"] = getLibDir() + "/plugins"

from Sire.IO import *
from Sire.Mol import *
from Sire.CAS import *
from Sire.System import *
from Sire.Move import *
from Sire.MM import *
from Sire.FF import *
from Sire.Units import *
from Sire.Vol import *
from Sire.Maths import *
from Sire.Qt import *
from Sire.ID import *
from Sire.Config import *
from Sire.Analysis import *
from Sire.Tools.DCDFile import *
from Sire.Tools import Parameter, resolveParameters
import Sire.Stream
import time
import numpy as np

#########################################
#       Config file parameters          #
#########################################

combining_rules = Parameter("combining rules", "geometric",
                            """Combining rules to use for the non-bonded interactions.""")

cutoff_type = Parameter("cutoff type", "nocutoff", """The cutoff method to use during the simulation.""")

cutoff_dist = Parameter("cutoff distance", 500 * angstrom,
                        """The cutoff distance to use for the non-bonded interactions.""")

use_restraints = Parameter("use restraints", False, """Whether or not to use harmonic restaints on the solute atoms.""")

def createSystem(molecules):
    #print("Applying flexibility and zmatrix templates...")
    print("Creating the system...")

    moleculeNumbers = molecules.molNums()
    moleculeList = []

    for moleculeNumber in moleculeNumbers:
        molecule = molecules.molecule(moleculeNumber)[0].molecule()
        moleculeList.append(molecule)

    molecules = MoleculeGroup("molecules")
    ions = MoleculeGroup("ions")

    for molecule in moleculeList:
        natoms = molecule.nAtoms()
        if natoms == 1:
            ions.add(molecule)
        else:
            molecules.add(molecule)

    all = MoleculeGroup("all")
    all.add(molecules)
    all.add(ions)

    # Add these groups to the System
    system = System()

    system.add(all)
    system.add(molecules)
    system.add(ions)

    return system

def setupForcefields(system, space):

    print("Creating force fields... ")

    all = system[MGName("all")]
    molecules = system[MGName("molecules")]
    ions = system[MGName("ions")]

    # - first solvent-solvent coulomb/LJ (CLJ) energy
    internonbondedff = InterCLJFF("molecules:molecules")
    if (cutoff_type.val != "nocutoff"):
        internonbondedff.setUseReactionField(True)
        internonbondedff.setReactionFieldDielectric(rf_dielectric.val)
    internonbondedff.add(molecules)

    inter_ions_nonbondedff = InterCLJFF("ions:ions")
    if (cutoff_type.val != "nocutoff"):
        inter_ions_nonbondedff.setUseReactionField(True)
        inter_ions_nonbondedff.setReactionFieldDielectric(rf_dielectric.val)

    inter_ions_nonbondedff.add(ions)

    inter_ions_molecules_nonbondedff = InterGroupCLJFF("ions:molecules")
    if (cutoff_type.val != "nocutoff"):
        inter_ions_molecules_nonbondedff.setUseReactionField(True)
        inter_ions_molecules_nonbondedff.setReactionFieldDielectric(rf_dielectric.val)

    inter_ions_molecules_nonbondedff.add(ions, MGIdx(0))
    inter_ions_molecules_nonbondedff.add(molecules, MGIdx(1))

    # Now solute bond, angle, dihedral energy
    intrabondedff = InternalFF("molecules-intrabonded")
    intrabondedff.add(molecules)

    # Now solute intramolecular CLJ energy
    intranonbondedff = IntraCLJFF("molecules-intranonbonded")

    if (cutoff_type.val != "nocutoff"):
        intranonbondedff.setUseReactionField(True)
        intranonbondedff.setReactionFieldDielectric(rf_dielectric.val)

    intranonbondedff.add(molecules)

    # solute restraint energy
    #
    # We restrain atoms based ont he contents of the property "restrainedatoms"
    #
    restraintff = RestraintFF("restraint")

    if use_restraints.val:
        molnums = molecules.molecules().molNums()

        for molnum in molnums:
            mol = molecules.molecule(molnum)[0].molecule()
            try:
                mol_restrained_atoms = propertyToAtomNumVectorList(mol.property("restrainedatoms"))
            except UserWarning as error:
                error_type = re.search(r"(Sire\w*::\w*)", str(error)).group(0)
                if error_type == "SireBase::missing_property":
                    continue
                else:
                    raise error

            for restrained_line in mol_restrained_atoms:
                atnum = restrained_line[0]
                restraint_atom = mol.select(atnum)
                restraint_coords = restrained_line[1]
                restraint_k = restrained_line[2] * kcal_per_mol / (angstrom * angstrom)

                restraint = DistanceRestraint.harmonic(restraint_atom, restraint_coords, restraint_k)

                restraintff.add(restraint)

    # Here is the list of all forcefields
    forcefields = [internonbondedff, intrabondedff, intranonbondedff, inter_ions_nonbondedff,
                   inter_ions_molecules_nonbondedff, restraintff]

    for forcefield in forcefields:
        system.add(forcefield)

    system.setProperty("space", space)
    system.setProperty("switchingFunction", CHARMMSwitchingFunction(cutoff_dist.val))
    system.setProperty("combiningRules", VariantProperty(combining_rules.val))

    total_nrg = internonbondedff.components().total() + \
                intranonbondedff.components().total() + intrabondedff.components().total() + \
                inter_ions_nonbondedff.components().total() + inter_ions_molecules_nonbondedff.components().total() + \
                restraintff.components().total()

    e_total = system.totalComponent()

    system.setComponent(e_total, total_nrg)

    # Add a monitor that calculates the average total energy and average energy
    # deltas - we will collect both a mean average and an zwanzig average
    system.add("total_energy", MonitorComponent(e_total, Average()))

    return system

def vsiteListToProperty(list):
    prop = Properties()
    i = 0
    for entry in list:
        for key, value in entry.items():
            prop.setProperty("%s(%d)" % (key,i), VariantProperty(value))
        i += 1
    prop.setProperty("nvirtualsites",VariantProperty(i))
    return prop

def readXmlParameters(pdbfile, xmlfile):
# 1) Read a pdb file describing the system to simulate

    p = PDB2(pdbfile)
    s = p.toSystem()
    molecules = s.molecules()
    #print (molecules)
    with open (pdbfile, "r") as f:
        for line in f:
            if line.split()[0] == "CRYST1" :
                print (line)
                pbc_x = float(line.split()[1])
                pbc_y = float(line.split()[2])
                pbc_z = float(line.split()[3])
                space = PeriodicBox(Vector(pbc_x, pbc_y, pbc_z))
                break
            else:
                space = Cartesian()
    #print("space:", space)

    system = System()

     # 2) Now we read the xml file, and store parameters for each molecule

    import xml.dom.minidom as minidom
    xmldoc = minidom.parse(xmlfile)
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: TYPE ~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_type = xmldoc.getElementsByTagName('Type')
    dicts_type = []
    for items in itemlist_type:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_type.append(d)
    dicts_tp =  str(dicts_type).split()
    #print (dicts_tp)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: ATOM ~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_atom = xmldoc.getElementsByTagName('Atom')
    dicts_atom = []
    for items in itemlist_atom:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_atom.append(d)
    dicts_at =  str(dicts_atom).split()
    #print (dicts_at)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: BOND ~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_bond = xmldoc.getElementsByTagName('Bond')
    dicts_bond = []
    for items in itemlist_bond:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_bond.append(d)
    dicts_b =  str(dicts_bond).split()
    #print (dicts_b)

    nbond = itemlist_bond.length

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: ANGLE ~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_angle = xmldoc.getElementsByTagName('Angle')
    dicts_angle = []
    for items in itemlist_angle:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_angle.append(d)
    dicts_ang =  str(dicts_angle).split()
    #print (dicts_angle)

    nAngles= itemlist_angle.length
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: PROPER ~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_proper = xmldoc.getElementsByTagName('Proper')
    dicts_proper = []
    for items in itemlist_proper:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_proper.append(d)
    dicts_pr =  str(dicts_proper).split()
    #print (dicts_pr)

    nProper = itemlist_proper.length

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: IMPROPER ~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_improper = xmldoc.getElementsByTagName('Improper')
    dicts_improper = []
    for items in itemlist_improper:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_improper.append(d)
    dicts_impr =  str(dicts_improper).split()
    #print (dicts_impr)
    nImproper = itemlist_improper.length

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: VIRTUAL SITES ~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_VirtualSite = xmldoc.getElementsByTagName('VirtualSite')
    dicts_virtualsite = []
    for items in itemlist_VirtualSite:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_virtualsite.append(d)
    #dicts_vs =  str(dicts_virtualsite).split()
    #print (dicts_vs)
    nVirtualSites = itemlist_VirtualSite.length

    v_site_CLJ = []
    for i in range(0, int(len(dicts_atom))):
        if dicts_atom[i]['type'][0] == 'v':
            v_site_CLJ = dicts_atom[i]
            dicts_virtualsite.append(v_site_CLJ)

    for i in range(0, len(itemlist_VirtualSite)):
        dicts_virtualsite[i].update(dicts_virtualsite[i+len(itemlist_VirtualSite)])
        dicts_virtualsite[i].update(dicts_virtualsite[i+2*len(itemlist_VirtualSite)])

    dict_vs = []
    for i in range(0, len(itemlist_VirtualSite)):
        dicts_virtualsite[i]
        dict_vs.append(dicts_virtualsite[i])

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~ TAG NAME: RESIDUE ~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_residue = xmldoc.getElementsByTagName('Residue')
    dicts_residue = []
    for items in itemlist_residue:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_residue.append(d)
    dicts_res =  str(dicts_residue).split()
    #print (dicts_res)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~ TAG NAME: NON BONDED FORCE ~~~~~~~~~~~~~~~~
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    itemlist_nonbond = xmldoc.getElementsByTagName('NonbondedForce')
    dicts_nonb = []
    for items in itemlist_nonbond:
        d = {}
        for a in items.attributes.values():
            d[a.name] = a.value
        dicts_nonb.append(d)
    dicts_nb =  str(dicts_nonb).split()
    #print (dicts_nb)
    nNonBonded = itemlist_nonbond.length

    # 3) Now we create an Amberparameters object for each molecule
    molnums = molecules.molNums()

    newmolecules = Molecules()
    for molnum in molnums:
        mol = molecules.at(molnum)
        #print (mol)

        # Add potential virtual site parameters
        if len(dicts_virtualsite) > 0:
            mol = mol.edit().setProperty("virtual-sites", vsiteListToProperty(dict_vs)).commit()

        # We populate the Amberparameters object with a list of bond, angle, dihedrals
        # We look up parameters from the contents of the xml file
        # We also have to set the atomic parameters (q, sigma, epsilon)

        editmol = mol.edit()
        mol_params = AmberParameters(editmol) #SireMol::AmberParameters()
        atoms = editmol.atoms()
        # We update atom parameters see setAtomParameters in SireIO/amber.cpp l2122
        natoms = editmol.nAtoms()
        #print("number of atoms is %s" %natoms)

    #natoms don't include the virtual sites!

    # Loop over each molecule in the molecules object

        opls=[]
        for i in range (0, int(len(dicts_atom)/2)):
            opl={}
            opl = dicts_atom[i]['type']
            opls.append(opl)

        name=[]
        for i in range (0, int(len(dicts_atom)/2)):
            nm={}
            nm = dicts_atom[i]['name']
            name.append(nm)

        two=[]
        #print(len(name))
        for i in range(0, len(name)):
            t=(opls[i],name[i])
            two.append(t)

        import numpy as np

        atom_sorted = []
        for j in range(0, len(two)):
            for i in range(int(len(dicts_atom)/2), len(dicts_atom)):
                if dicts_atom[i]['type'] == two[j][0]:
                    dic_a = {}
                    dic_a = dicts_atom[i]
                    atom_sorted.append(dic_a)

        type_sorted = []
        for j in range(0, len(two)):
            for i in range(0, int(len(dicts_type))):
                if dicts_type[i]['name'] == two[j][0]:
                    dic_t = {}
                    dic_t = dicts_type[i]
                    type_sorted.append(dic_t)
        print(" ")
        print("There are ",natoms," atoms in this molecule. ")
        print("*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*")

        for atom in atoms:
            editatom = editmol.atom(atom.index())

            i = int(str(atom.number()).split('(')[1].replace(")" , " "))

            editatom.setProperty("charge", float(atom_sorted[i-1]['charge']) * mod_electron)
            editatom.setProperty("mass", float(type_sorted[i-1]['mass']) * g_per_mol)
            editatom.setProperty("LJ", LJParameter( float(atom_sorted[i-1]['sigma'])*10 * angstrom , float(atom_sorted[i-1]['epsilon'])/4.184 * kcal_per_mol))
            editatom.setProperty("ambertype", dicts_atom[i-1]['type'])

            editmol = editatom.molecule()

        # Now we create a connectivity see setConnectivity in SireIO/amber.cpp l2144
        # XML data tells us how atoms are bonded in the molecule (Bond 'from' and 'to')

        if natoms > 1:
            print("Set up connectivity")

            con = []
            for i in range(0,int(nbond/2)):
                if natoms > 1:
                    connect_prop= {}
                    connect_prop = dicts_bond[i]['from'], dicts_bond[i]['to']
                con.append(connect_prop)

            conn = Connectivity(editmol.info()).edit()

            for j in range(0,len(con)):
                conn.connect(atoms[int(con[j][0]) ].index(), atoms[int(con[j][1]) ].index())

            editmol.setProperty("connectivity", conn.commit()).commit()
            mol = editmol.setProperty("connectivity", conn.commit()).commit()
            system.update(mol)

             # Now we add bond parameters to the Sire molecule. We also update amberparameters see SireIO/amber.cpp l2154

            internalff = InternalFF()

            bondfuncs = TwoAtomFunctions(mol)
            r = internalff.symbols().bond().r()

            for j in range(0,len(con)):
                bondfuncs.set(atoms[int(con[j][0]) ].index(), atoms[int(con[j][1]) ].index(), float(dicts_bond[j+len(con)]['k'])/(2*100*4.184)* (float(dicts_bond[j+len(con)]['length'])*10 - r) **2  )
                bond_id = BondID(atoms[int(con[j][0])].index(), atoms[int(con[j][1])].index())
                mol_params.add(bond_id, float(dicts_bond[j+len(con)]['k'])/(2*100*4.184), float(dicts_bond[j+len(con)]['length'])*10 )
                editmol.setProperty("bonds", bondfuncs).commit()
                molecule = editmol.commit()

            mol_params.getAllBonds()

            editmol.setProperty("amberparameters", mol_params).commit() # Weird, should work - investigate ?
            molecule = editmol.commit()

        # Now we add angle parameters to the Sire molecule. We also update amberparameters see SireIO/amber.cpp L2172
        if natoms > 2:
            print("Set up angles")

            anglefuncs = ThreeAtomFunctions(mol)
            at1 = []
            for i in range(0, nAngles):
                a1 = {}
                to_str1 = str(re.findall(r"\d+",str(dicts_angle[i]['class1'])))
                if dicts_atom[i]['type'][0] == 'o': #if opls_
                    a1 = int(to_str1.replace("[","").replace("]","").replace("'","") )-800
                else:#if QUBE_
                    a1 = int(to_str1.replace("[","").replace("]","").replace("'","") )

                at1.append(a1)

            at2 = []
            for i in range(0, nAngles):
                a2 = {}
                to_str2 = str(re.findall(r"\d+",str(dicts_angle[i]['class2'])))
                if dicts_atom[i]['type'][0] == 'o': #if opls_
                    a2 = int(to_str2.replace("[","").replace("]","").replace("'","") )-800
                else: #if QUBE_

                    a2 = int(to_str2.replace("[","").replace("]","").replace("'","") )

                at2.append(a2)

            at3 = []
            for i in range(0, nAngles):
                a3 = {}
                to_str3 = str(re.findall(r"\d+",str(dicts_angle[i]['class3'])))
                if dicts_atom[i]['type'][0] == 'o': #if opls_
                    a3 = int(to_str3.replace("[","").replace("]","").replace("'","") )-800
                else: #if QUBE_
                    a3 = int(to_str3.replace("[","").replace("]","").replace("'","") )

                at3.append(a3)

            theta = internalff.symbols().angle().theta()
            for j in range(0,nAngles):
                anglefuncs.set( atoms[at1[j]].index(), atoms[at2[j]].index(), atoms[at3[j]].index(), float(dicts_angle[j]['k'])/(2*4.184) * ( (float(dicts_angle[j]['angle']) - theta )**2 ))
                angle_id = AngleID( atoms[int(at1[j])].index(), atoms[int(at2[j])].index(), atoms[int(at3[j])].index())
                mol_params.add(angle_id, float(dicts_angle[j]['k'])/(2*4.184), float(dicts_angle[j]['angle']) )

        # Now we add dihedral parameters to the Sire molecule. We also update amberparameters see SireIO/amber.cpp L2190

        if natoms > 3:
            print("Set up dihedrals")
            di1 = []

            for i in range(0, nProper):
                d1 = {}
                to_str1 = str(re.findall(r"\d+",str(dicts_proper[i]['class1'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d1 = int(to_str1.replace("[","").replace("]","").replace("'","") )-800
                else:  #if QUBE_
                    d1 = int(to_str1.replace("[","").replace("]","").replace("'","") )

                di1.append(d1)

            di2 = []
            for i in range(0, nProper):
                d2 = {}
                to_str2 = str(re.findall(r"\d+",str(dicts_proper[i]['class2'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d2 = int(to_str2.replace("[","").replace("]","").replace("'","") )-800
                else: #if QUBE_
                    d2 = int(to_str2.replace("[","").replace("]","").replace("'","") )

                di2.append(d2)

            di3 = []
            for i in range(0, nProper):
                d3 = {}
                to_str3 = str(re.findall(r"\d+",str(dicts_proper[i]['class3'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d3 = int(to_str3.replace("[","").replace("]","").replace("'","") )-800
                else: #if QUBE_
                    d3 = int(to_str3.replace("[","").replace("]","").replace("'","") )

                di3.append(d3)

            di4 = []
            for i in range(0, nProper):
                d4 = {}
                to_str4 = str(re.findall(r"\d+",str(dicts_proper[i]['class4'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d4 = int(to_str4.replace("[","").replace("]","").replace("'","") )-800
                else: #if QUBE_
                    d4 = int(to_str4.replace("[","").replace("]","").replace("'","") )

                di4.append(d4)

            dihedralfuncs = FourAtomFunctions(mol)

            phi = internalff.symbols().dihedral().phi()
            for i in range(0,nProper):
                if atoms[int(di1[i])].index() != atoms[int(di4[i])].index():
                    dihedral_id = DihedralID( atoms[int(di1[i])].index(), atoms[int(di2[i])].index(), atoms[int(di3[i])].index(), atoms[int(di4[i])].index())
                    dih1= float(dicts_proper[i]['k1'])/4.184*(1+Cos(int(dicts_proper[i]['periodicity1'])* phi- float(dicts_proper[i]['phase1'])))
                    dih2= float(dicts_proper[i]['k2'])/4.184*(1+Cos(int(dicts_proper[i]['periodicity2'])* phi- float(dicts_proper[i]['phase2'])))
                    dih3= float(dicts_proper[i]['k3'])/4.184*(1+Cos(int(dicts_proper[i]['periodicity3'])* phi- float(dicts_proper[i]['phase3'])))
                    dih4= float(dicts_proper[i]['k4'])/4.184*(1+Cos(int(dicts_proper[i]['periodicity4'])* phi- float(dicts_proper[i]['phase4'])))
                    dih_fun = dih1 + dih2 +dih3 +dih4
                    dihedralfuncs.set(dihedral_id, dih_fun)

                    for t in range(1,5):
                        mol_params.add(dihedral_id, float(dicts_proper[i]['k%s'%t])/4.184, int(dicts_proper[i]['periodicity%s'%t]), float(dicts_proper[i]['phase%s'%t]) )

            print("Set up impropers")

            di_im1 = []
            for i in range(0, nImproper):
                d1 = {}
                to_str1 = str(re.findall(r"\d+",str(dicts_improper[i]['class1'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d1 = int(to_str1.replace("[","").replace("]","").replace("'","") )-800
                else:
                    d1 = int(to_str1.replace("[","").replace("]","").replace("'","") )

                di_im1.append(d1)

            di_im2 = []
            for i in range(0, nImproper):
                d2 = {}
                to_str2 = str(re.findall(r"\d+",str(dicts_improper[i]['class2'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d2 = int(to_str2.replace("[","").replace("]","").replace("'","") )-800
                else:
                    d2 = int(to_str2.replace("[","").replace("]","").replace("'","") )

                di_im2.append(d2)

            di_im3 = []
            for i in range(0, nImproper):
                d3 = {}
                to_str3 = str(re.findall(r"\d+",str(dicts_improper[i]['class3'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d3 = int(to_str3.replace("[","").replace("]","").replace("'","") )-800
                else:
                    d3 = int(to_str3.replace("[","").replace("]","").replace("'","") )

                di_im3.append(d3)

            di_im4 = []
            for i in range(0, nImproper):
                d4 = {}
                to_str4 = str(re.findall(r"\d+",str(dicts_improper[i]['class4'])))
                if dicts_atom[0]['type'][0] == 'o':#if opls_
                    d4 = int(to_str4.replace("[","").replace("]","").replace("'","") )-800
                else:
                    d4 = int(to_str4.replace("[","").replace("]","").replace("'","") )

                di_im4.append(d4)

            improperfuncs = FourAtomFunctions(mol)

            phi_im = internalff.symbols().improper().phi()

            for i in range(0,nImproper):
                improper_id = ImproperID( atoms[int(di_im2[i])].index(), atoms[int(di_im3[i])].index(), atoms[int(di_im1[i])].index(), atoms[int(di_im4[i])].index())
                imp1= float(dicts_improper[i]['k1'])*(1/4.184)*(1+Cos(int(dicts_improper[i]['periodicity1'])* phi_im - float(dicts_improper[i]['phase1'])))
                imp2= float(dicts_improper[i]['k2'])*(1/4.184)*(1+Cos(int(dicts_improper[i]['periodicity2'])* phi_im - float(dicts_improper[i]['phase2'])))
                imp3= float(dicts_improper[i]['k3'])*(1/4.184)*(1+Cos(int(dicts_improper[i]['periodicity3'])* phi_im - float(dicts_improper[i]['phase3'])))
                imp4= float(dicts_improper[i]['k4'])*(1/4.184)*(1+Cos(int(dicts_improper[i]['periodicity4'])* phi_im - float(dicts_improper[i]['phase4'])))
                imp_fun = imp1 + imp2 +imp3 +imp4
                improperfuncs.set(improper_id, imp_fun)
                #print(improperfuncs.potentials())

                for t in range(1,5):
                    mol_params.add(improper_id, float(dicts_improper[i]['k%s'%t])*(1/4.184), int(dicts_improper[i]['periodicity%s'%t]), float(dicts_improper[i]['phase%s'%t]) )

            mol = editmol.setProperty("bond", bondfuncs).commit()
            mol = editmol.setProperty("angle" , anglefuncs).commit()
            mol = editmol.setProperty("dihedral" , dihedralfuncs).commit()
            mol = editmol.setProperty("improper" , improperfuncs).commit()
            system.update(mol)

        # Now we work out non bonded pairs see SireIO/amber.cpp L2213

            print("Set up nbpairs")
            print("*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*")
            ## Define the bonded pairs in a list that is called are12
            #print("Now calculating 1-2 intercactions")
            are12 = []
            for i in range(0, natoms):
                for j in range (0, natoms):
                    if conn.areBonded(atoms[i].index(), atoms[j].index()) == True:
                        #ij = {}
                        ij= (i,j)
                        are12.append(ij)
            are12_bckup = are12[:]

            #print("Now calculating 1-3 intercactions")
            are13 = []
            for i in range(0, natoms):
                for j in range (0, natoms):
                    if conn.areAngled(atoms[i].index(), atoms[j].index()) == True:
                        ij = {}
                        ij= (i,j)
                        are13.append(ij)
            are13_bckup = are13[:]

           # print("Now calculating 1-4 intercactions")
            are14 = []
            for i in range(0, natoms):
                for j in range (0, natoms):

                    if conn.areDihedraled(atoms[i].index(), atoms[j].index()) == True and conn.areAngled(atoms[i].index(), atoms[j].index()) == False:
                        ij = {}
                        ij= (i,j)
                        are14.append(ij)
            are14_bckup = are14[:]

           # print("Now calculating the non-bonded intercactions")
            bonded_pairs_list = are12_bckup + are13_bckup + are14_bckup
            nb_pair_list =[]

            for i in range(0, natoms):
                #print("i=",i)
                for j in range (0, natoms):
                    if i != j and (i,j) not in bonded_pairs_list:
                        nb_pair_list.append((i,j))
            are_nb_bckup = nb_pair_list[:]

            nbpairs = CLJNBPairs(editmol.info(), CLJScaleFactor(0,0))
            #print("Now setting 1-2 intercactions")
            for i in range(0, len(are12)):
                scale_factor1 = 0
                scale_factor2 = 0
                nbpairs.set(atoms.index( int(are12[i][0])), atoms.index(int(are12[i][1])), CLJScaleFactor(scale_factor1,scale_factor2))

            #print("Now setting 1-3 intercactions")
            for i in range(0, len(are13)):
                scale_factor1 = 0
                scale_factor2 = 0
                nbpairs.set(atoms.index( int(are13[i][0])), atoms.index(int(are13[i][1])), CLJScaleFactor(scale_factor1,scale_factor2))

           # print("Now setting 1-4 intercactions")
            for i in range(0, len(are14)):
                scale_factor1 = 1/2
                scale_factor2 = 1/2
                nbpairs.set(atoms.index( int(are14[i][0])), atoms.index(int(are14[i][1])), CLJScaleFactor(scale_factor1,scale_factor2))
                mol_params.add14Pair(BondID(atoms.index( int(are14[i][0])), atoms.index( int(are14[i][1]))),scale_factor1 , scale_factor2)

           # print("Now setting non-bonded intercactions")
            #print("*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*")
            for i in range(0, len(nb_pair_list)):
                scale_factor1 = 1
                scale_factor2 = 1
                nbpairs.set(atoms.index( int(nb_pair_list[i][0])), atoms.index(int(nb_pair_list[i][1])), CLJScaleFactor(scale_factor1,scale_factor2))

                # print("~~~~~~~~~~~~~~~~~~`")

            mol = editmol.setProperty("intrascale" , nbpairs).commit()
            system.update(mol)

        #print("Setup name of qube FF")
        mol = mol.edit().setProperty("forcefield", ffToProperty("qube")).commit()
        system.update(mol)

        molecule = editmol.commit()
        newmolecules.add(molecule)

    return (newmolecules, space)

def ffToProperty(string):
    prop = Properties()
    prop.setProperty("forcefield",VariantProperty("qube"))
    return prop

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description="Read parameters and coordinates from xml and pdb files ",
                                 epilog=" ",
                                 prog="readXmlParameters")

    parser.add_argument('-p', '--pdbfile', nargs="?", help="The pdb file with the coordinates of the molecule.")
    parser.add_argument('-x', '--xmlfile', nargs="?", help="The xml file with the parameters of the molecule.")
    args = parser.parse_args()
    (lig1, space) = readXmlParameters(args.pdbfile, args.xmlfile)
    system = createSystem(lig1) # Sire.System._System.System
    system = setupForcefields(system, space)
    print("Energy computed with the ",combining_rules.val, "combining rules is: ", system.energy())
    print("_________________________________________________________________________________________")


'''
Given two strings s and t, write a function to determine if t is an anagram of s.

For example,
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
'''
import string

def is_anagram(s, t):
    letters = list(string.ascii_lowercase)

    for l in letters:
        if s.count(l) != t.count(l):
            return False

    return True

'''
Given a string `s` and a non-empty string `p`, find all the start indices of `p's` anagram in `s`.

String consists of lowercase English letters only and the length of both strings `s` and `p`
will not be larger than 20,000

The order of output does not matter

Example 1:
Input:
    s: "cbaebabacd" p: "abc"

Output:
    [0,6]

Explanation:
    The substring with start index = 0 is "cba", which is an anagram of "abc"
    The substring with start index = 6 is "bac", which is an anagram of "abc"

Example 2:
Input:
    s: "abab" p: "ab"

Output:
    [0,1,2]

Explanation:
    The substring with start index = 0 is "ab", which is an anagram of "ab"
    The substring with start index = 1 is "ba", which is an anagram of "ab"
    The substring with start index = 2 is "ab", which is an anagram of "ab"
'''

from collections import Counter

class Solution:

    def find_anagrams(self, s, p):

        res = []
        p_counter = Counter(p)
        s_counter = Counter(s[:len(p)-1])

        for i in range(len(p) - 1, len(s)):
            s_counter[s[i]] += 1 # include the new char in the window

            if s_counter == p_counter: # This step is O(1), since there are at most 26 English letters
                res.append(i - len(p) + 1) # Append the starting index

            s_counter[s[i - len(p) + 1]] -= 1 # Decrease the count of oldest char in the window
            if s_counter[s[i - len(p) + 1]] == 0:
                del s_counter[s[i - len(p) + 1]] # Remove the count if it is 0

        return res


"""This script defines the command line entry point for cell anneal and
implements a pipeline including identification of highly variable genes,
deconvolution of each bulk sample, ouput of deconvolution results and
production of a set of plots."""

import argparse
from pathlib import Path
import pandas as pd

from .pipelines import cellanneal_pipe

def init_parser(parser):
    """Initialize parser arguments."""
    parser.add_argument(
        'bulk_data_path', type=str,
        help=("""Path to bulk data file, csv format with sample names as
            columns and genes as rows.""")
    )

    parser.add_argument(
        'celltype_data_path', type=str,
        help=("""Path to celltype reference data file, csv format with sample
            names as columns and genes as rows. """)
    )

    parser.add_argument(
        'output_path', type=str,
        help=("""Path to folder in which to store the results. """)
    )

    parser.add_argument(
        '--bulk_min', type=float, default=1e-5,
        help=("""Minimum relative expression in the bulk sample for a gene
            to be considered.""")
    )

    parser.add_argument(
        '--bulk_max', type=float, default=0.01,
        help=("""Maximum relative expression in the bulk sample for a gene
            to be considered.""")
    )

    parser.add_argument(
        '--disp_min', type=float, default=0.5,
        help=("""Minimum scaled dispersion (var/mean) relative to other
            genes of similar expression for a gene to be considered.""")
    )

    parser.add_argument(
        '--maxiter', type=int, default=1000,
        help=("""Number of initial values from which to run simulated
            annealing.""")
    )

    return parser

def main():
    """ cellanneal. User-friendly deconvolution of bulk RNA-Seq data.

    Deconvovles bulk RNA-Seq data into single-cell populations based
    on Spearman's correlation between bulk sample gene expression and
    single-cell based mixture gene expression. Simulated annealing is
    used to find the optimal mixture.

    Input:
            bulk_data_path
            celltype_data_path
            output_path
            bulk_min
            bulk_max
            disp_min
            maxiter

    Output:

    Example:

    """
    # get a parser object, initialise the inputs and read them into args
    my_parser = argparse.ArgumentParser(
        description=('cellanneal deconvolves bulk RNA-Seq data.'))
    args = init_parser(my_parser).parse_args()

    # grab the individual inputs for further use
    bulk_data_path = Path(args.bulk_data_path)
    celltype_data_path = Path(args.celltype_data_path)
    output_path = Path(args.output_path)
    bulk_min = args.bulk_min
    bulk_max = args.bulk_max
    disp_min = args.disp_min
    maxiter = args.maxiter

    print("\nWelcome to cellanneal!\n")

    """ 1) Import bulk and cell type data """
    print('1A. Importing bulk data ...')
    try:
        bulk_df = pd.read_csv(bulk_data_path, index_col=0, header=0)
        # here, in order to make further course case insensitive,
        # change all gene names to uppercase only
        bulk_df.index = bulk_df.index.str.upper()
        # also, if there are duplicate genes, the are summed here
        bulk_df = bulk_df.groupby(bulk_df.index).sum()
        bulk_names = bulk_df.columns.tolist()
        print('{} bulk samples identified: {}\n'.format(len(bulk_names),
                                                        bulk_names))
    except:
        print("""Your bulk data file could not be imported.
        Please check the documentation for format requirements
        and look at the example bulk data files.""")

    print('1B. Importing celltype reference data ...')
    # import single cell based reference
    try:
        celltype_df = pd.read_csv(celltype_data_path, index_col=0, header=0)
        # here, in order to make further course case insensitive,
        # change all gene names to uppercase only
        celltype_df.index = celltype_df.index.str.upper()
        # also, if there are duplicate genes, the are summed here
        celltype_df = celltype_df.groupby(celltype_df.index).sum()
        celltypes = celltype_df.columns.tolist()
        print('{} cell types identified: {}\n'.format(len(celltypes), celltypes))
    except:
        print("""Your celltype data file could not be imported.
        Please check the documentation for format requirements
        and look at the example celltype data files.""")

    # start pipeline
    cellanneal_pipe(
        celltype_data_path,
        celltype_df,
        bulk_data_path,
        bulk_df,
        disp_min,
        bulk_min,
        bulk_max,
        maxiter,
        output_path)


class Solution:
    def findSpecialInteger(self, arr: List[int]) -> int:
        if len(arr)==0:
            return 0
        elif len(arr)<3:
            return arr[0]
        prev,size=-1,0
        thres=0.25*len(arr)
        for i in arr:
            if prev==i:
                size+=1
                if size>thres:
                    return prev
            else:
                size=1
            prev=i

        # https://leetcode.com/problems/element-appearing-more-than-25-in-sorted-array/


#Initial Commit
#This creates a base object of each class using my own information and
#will use that to test all of the functionallity
#@author A1C Jake Brower 12/31/2020

#this allows me to reference the objects made in classes.py
import classes
#A premade object that represents dates, used in some of my made classes
from datetime import date
#So i can make a list of every object ill be utilizing
from typing import List

#all of this information is from the excel sheet, DOES NOT PULL FROM THE GOOGLE SHEET
name = "Jake Brower"
rank = "A1C"
crewPos = "MSO"
isOnLeave = False
scheduledLeave = None
isoOrRom = False
hundredPercentContact = "Capt Wright"
zoom = "jacobbrower96@gmail.com"
lineSqd = None
dateArrived = date(2020, 7, 13)
classNumber = "20 LAT"
shift = 8
projStartDate = date(2020, 9, 24)
hasPolicyLit = True
cbts = [classes.cbt(True, "CBT 1"), classes.cbt(False, "CBT 2")]
afe = True
crm = True
sec = 2 #0 for bad 1 for s 2 for ts
hasLineBadge = True
hasRedBadge = True
hasRips = True
ipadStatus = 1 #0 for not submitted 1 for submitted 2 for has iPad
hasPHA = True
checkedInWithSarm = True
checkedInWithHarm = True
hasHeadset = True
hasPubs = True
hasGtc = True
updatedDogTags = True
hasFlightGear = True
completedFTAC = True
sereInfo = classes.sere(True, True, date(2020, 8, 31))
hasLOA = True
hasAuth = True
hasVoucher = True
obCBTestStatus = 0 #not sure what this is
completionRep = classes.completionReport(True, False, True, False, False, "This is a comment for A1C Jake Brower")
remarks = "This is a remark for A1C Jake Brower :) ME!!!"
#End of the variables to make 1 airmen object then I get to run tests :)

#This very long line is the test for making the airmen object
a1cJakeBrower = classes.airmen(name, rank, crewPos, isoOrRom, hundredPercentContact, dateArrived, sec, sereInfo, remarks)


"""permet de gérer des étudiants dans une base de donnée au format dbm"""

import dbm
from tkinter import *
import sys, os

class Ihm(Tk):

	def __init__(self,root):

		''' MENU '''

		self.var_choix = StringVar()

		self.message=Label(root, text="Veuillez séléctionner votre choix", fg="black")

		self.button1=Radiobutton(root, text="Creer", variable=self.var_choix, value="create")
		self.button2=Radiobutton(root, text="Supprimer", variable=self.var_choix, value="delete")

		self.button3=Button(root, text="Valider", command=lambda: self.fct_callback(root))

		self.button4=Button(root, text="Quitter", command=root.destroy)

		self.message.pack()

		#self.button5=Button(root, text="Sauvegarder", variable=self.var_choix, self.sauvegarder(root))

		self.button1.pack()
		self.button2.pack()
		self.button3.pack()
		self.button4.pack()

		''' AFFICHAGE DES ETUDIANTS '''
		self.listbox=Listbox(root)

		self.db=dbm.open('etudiant', 'c')
		for i in self.db.keys():
			self.listbox.insert(END, str(self.db[i].decode("utf-8")) +' '+str(i.decode("utf-8")) )

		self.listbox.pack(side='bottom')

		self.db.close()

		''' AJOUT D'ETUDIANTS '''
		self.numer=Label(root, text="Numéro de l'étudiant :")
		self.nom=Label(root, text="Nom de l'étudiant :")
		self.num=Entry(root)
		self.name=Entry(root)
		self.bouton=Button(root, text="Valider", command=lambda: self.fct_callback(root))

		''' SUPPRESSION D'ETUDIANT '''

		self.sup=Button(root, text="Valider pour supprimer")

	def fct_callback(self, root):

		if (self.var_choix.get() =="create"):
			self.create(root)

		if (self.var_choix.get() =="delete"):
			self.delete(root)

	def create(self, root):
		self.numer.pack()
		self.num.pack()
		self.nom.pack()
		self.name.pack()
		self.bouton.pack()

		self.fichier =dbm.open('etudiant', 'c')
		self.info=self.fichier[str(self.num.get())]=self.name.get()
		if (self.name.get() != "" and self.num.get() != ""):
			self.listbox.insert(0, str(self.name.get() +' '+str(self.num.get())))
		else:
			print("veuillez remplir les champs")
		self.fichier.close()

	def selection(self, event):
		'''permet de récuperer l'étudiant selectionné'''

		self.dbbb=dbm.open('etudiant', 'c')
		a=self.listbox.curselection()
		nom=self.listbox.get(a)
		nume=nom.split()

		self.listbox.delete(a)

		del self.dbbb[nume[1]];

		self.dbbb.close()

	def delete(self, root):
		''' permet de supprimer l'étudiant de la listbox et du fichier dbm
		on redirige vers la fonction selection qui va permettre de supprimer'''
		self.sup.pack()

		self.sup.bind('<Button-1>', self.selection)

		self.sup.mainloop()


import xadmin
from .models import *
class PostAdmin(object):
    list_display = ['title', 'created_time', 'tags', 'modified_time', 'category', 'author','isDelete']
    # 列表显示
    search_fields = ['title', 'body']
    #查询字段
    list_filter = ['title', 'tags', 'category', 'author','isDelete']
    #过滤器

    style_fields = {"body": "ueditor"}

class CategoryAdmin(object):
    list_display = ['name','isDelete']
    search_fields = ['name','isDelete']
    list_filter = ['name','isDelete']

class TagAdmin(object):
    list_display = ['name','isDelete']
    search_fields = ['name','isDelete']
    list_filter = ['name','isDelete']

class CommentAdmin(object):
    list_display = ['name','email','text','created_time','post','isDelete']
    search_fields = ['name','isDelete']
    list_filter = ['name','email','text','created_time','post','isDelete']

class CommentBackAdmin(object):
    list_display = ['comment','text','created_time','isDelete']
    search_fields = ['name','isDelete']
    list_filter = ['comment','text','created_time','isDelete']

xadmin.site.register(Post, PostAdmin)
xadmin.site.register(Category,CategoryAdmin)
xadmin.site.register(Tag,TagAdmin)
xadmin.site.register(Comment,CommentAdmin)
xadmin.site.register(CommentBack,CommentBackAdmin)


def exchange_convert(exchange_str):
    """The format of input is "from=source&to=target&amt=amount"
    parameter:the string to slice
    returns:2 Substrings and a float."""

    exchange_list=exchange_str.split("=")
    exchange_to=[]
    for i in range(len(exchange_list)):
        exchange_to +=(str(exchange_list[i]).split("&"))
    currency_from=exchange_to[1]
    currency_to=exchange_to[3]
    amount_from=float(exchange_to[5])
    return (currency_from,currency_to,amount_from)

def currency_response(currency_from,currency_to,amount_from):
    """In this procedure ,data input will make a call to the target webset,and a string
    containing relating information will be put out.
    parameter:currency_from(str);currency_to(str):amount_from(float)
    return:a string from the target webset"""

    from urllib.request import urlopen
    doc = urlopen('http://cs1110.cs.cornell.edu/2016fa/a1server.php?from={}&to={}&amt={}'.format(currency_from,currency_to,amount_from))
    docstr = doc.read()
    doc.close()
    jstr = docstr.decode('ascii')
    return jstr

def get_from_and_to(data_feedback):
    """This procedure is used for fetching the information recieved from the target
    webset,and transform it into a tuple.
    parameter:the string from the webset
    return:a tuple including amount_from,currency_from and amount_to,currency_to"""

    if "false" in data_feedback:
        print("Error,the format of data input is wrong")
        return exit(1)
    else:
        data_feedback=str(data_feedback).split("\"")
        list_get=[]
        for i in range(len(data_feedback)):
            if (data_feedback[i]+" ")[0].isdigit():
                list_get.append(data_feedback[i])
        tuple_get=tuple(list_get)
        return tuple_get

def exchange_main(currency):
    """In this module, the modules we write is integrated together.And the final
    result is given.
    parameter:string with the format of "from=source&to=target&amt=amount"
    return:a float of the amount exchangeg to"""
    currency_from=exchange_convert(currency)[0]
    currency_to=exchange_convert(currency)[1]
    amount_from=exchange_convert(currency)[2]
    exchange_feedback=currency_response(currency_from,currency_to,amount_from)
    amount_to_str=get_from_and_to(exchange_feedback)[1].split(" ")[0]
    amount_to=float(amount_to_str)
    return amount_to

def main():
    print("The format of your input should be:from=source&to=target&amt=amount")
    currency_ex=input()
    print(exchange_main(currency_ex))
    input()

if __name__=="__main__":
    main()


from PIL import Image
from utility import calculate_image_similarity, apply_and_check, apply_and_check_3x3

CLOSENESS_THRESHOLD = 200

def is_close(value_1, value_2, epsilon):
    value_1 = abs(value_1)
    value_2 = abs(value_2)

    if epsilon is not None:
        if value_1 - epsilon < value_2 < value_1 + epsilon:
            return True
    else:
        if value_1 - CLOSENESS_THRESHOLD < value_2 < value_1 + CLOSENESS_THRESHOLD:
            return True

    return False

def is_same_sign(value_1, value_2):

    if value_1 < 0 and value_2 < 0:
        return True

    if value_1 > 0 and value_2 > 0:
        return True

    return False

# C-04 and C-12
def solve_3x3(imageMap, pixel_ratio_map):

    pixel_info_A = pixel_ratio_map.get('A')
    pixel_info_B = pixel_ratio_map.get('B')
    pixel_info_C = pixel_ratio_map.get('C')
    pixel_info_D = pixel_ratio_map.get('D')
    pixel_info_E = pixel_ratio_map.get('E')
    pixel_info_G = pixel_ratio_map.get('G')

    pixel_info_F = pixel_ratio_map.get('F')
    pixel_info_H = pixel_ratio_map.get('H')

    a_b_diff = pixel_info_A.get('black_pixels') - pixel_info_B.get('black_pixels')
    b_c_diff = pixel_info_B.get('black_pixels') - pixel_info_C.get('black_pixels')

    a_d_diff = pixel_info_A.get('black_pixels') - pixel_info_D.get('black_pixels')
    d_g_diff = pixel_info_D.get('black_pixels') - pixel_info_G.get('black_pixels')

    if not is_same_sign(a_d_diff, d_g_diff):
        return -1
    if not is_close(a_b_diff, a_d_diff, None):
        return -1
    if not is_close(a_b_diff, b_c_diff, None):
        return -1
    if not is_close(b_c_diff, d_g_diff, None):
        return -1
    if not is_same_sign(a_b_diff, b_c_diff):
        return -1

    vertical_diff = d_g_diff
    horizontal_diff = b_c_diff

    number_of_answers_filtered = 0
    potential_answers = []

    for i in range(1, 9):
        result = filter_answer_based_on_criteria(imageMap, pixel_ratio_map, str(i), vertical_diff, horizontal_diff)
        if result is not None and result:
            potential_answers.append(i)
        elif not None and not result:
            number_of_answers_filtered += 1

    if len(potential_answers) == 1:
        return potential_answers[0]

    potential_answers = []

    for i in range(1, 9):
        # if i == 4:
        #     print()
        result = filter_answer_based_on_criteria_2(imageMap, pixel_ratio_map, str(i), vertical_diff, horizontal_diff)
        if result is not None and result:
            potential_answers.append(i)
        elif not None and not result:
            number_of_answers_filtered += 1

    if len(potential_answers) == 1:
        return potential_answers[0]

    if len(potential_answers) == 2:
        image_1 = imageMap.get(str(potential_answers[0]))
        image_2 = imageMap.get(str(potential_answers[1]))
        similarity_1 = calculate_image_similarity(image_1, imageMap.get('A'))
        similarity_2 = calculate_image_similarity(image_2, imageMap.get('B'))
        if similarity_1 > similarity_2:
            return potential_answers[0]
        return potential_answers[1]
    return -1

def filter_answer_based_on_criteria_2(image_map, pixel_ratio_map, answer_label, vertical_diff, horizontal_diff):
    black_f = pixel_ratio_map.get('F').get('black_pixels')
    black_h = pixel_ratio_map.get('H').get('black_pixels')
    black_answer = pixel_ratio_map.get(answer_label).get('black_pixels')

    f_1_diff = black_f - black_answer
    h_1_diff = black_h - black_answer

    if (is_close(black_f, black_h, 200) or (is_close(black_answer, black_f - vertical_diff, 200) and is_close(black_answer, black_h - horizontal_diff, 200))) \
            and is_close(f_1_diff, h_1_diff, 200) \
            and is_same_sign(horizontal_diff, h_1_diff) \
            and is_same_sign(vertical_diff, f_1_diff):
        return True

    return None

def filter_answer_based_on_criteria(image_map, pixel_ratio_map, answer_label, vertical_diff, horizontal_diff):
    black_f = pixel_ratio_map.get('F').get('black_pixels')
    black_h = pixel_ratio_map.get('H').get('black_pixels')
    black_answer = pixel_ratio_map.get(answer_label).get('black_pixels')

    f_1_diff = black_f - black_answer
    h_1_diff = black_h - black_answer

    if is_same_sign(f_1_diff, vertical_diff) \
            and is_same_sign(h_1_diff, horizontal_diff) \
            and ((is_close(h_1_diff, horizontal_diff, None)
                  and is_close(f_1_diff, vertical_diff, None)) or is_close(horizontal_diff + vertical_diff, h_1_diff, None)):
        return True

    similarity = calculate_image_similarity(image_map.get(answer_label), image_map.get('F'))
    similarity_2 = calculate_image_similarity(image_map.get(answer_label), image_map.get('H'))

    if similarity > 0.97 and similarity_2 > 0.97:
        return True

    return False


# -*- coding: utf-8 -*-
from django.db import models
from django.utils.timezone import now

from locations.models import Location

class Application(models.Model):
    name = models.CharField(max_length=255)
    description = models.CharField(max_length=255)
    created = models.DateTimeField(auto_now_add=True, null=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

class Campaign(models.Model):
    PROGRAM_TYPES = {
        '1': 'May/June',
        '2': 'Nov/Dec',
    }

    name = models.CharField(max_length=255)
    locations = models.ManyToManyField(Location, limit_choices_to={
        u'type__name__in': [u'State', u'LGA']})
    start_date = models.DateField()
    end_date = models.DateField()
    apps = models.ManyToManyField(Application)
    created = models.DateTimeField(auto_now_add=True, null=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    def campaign_states(self):
        return self.locations.filter(type__name=u'State')

    def campaign_lgas(self, location):
        try:
            if self.locations.get(pk=location.pk) and location.type.name == u'State':
                return self.locations.filter(parent=location,
                    type__name=u'LGA') or location.children.all()
        except Location.DoesNotExist:
            pass

        return Location.objects.none()

    def get_related_objects(self, model_class, state, locations=None):
        try:
            if not locations:
                lgas = self.campaign_lgas(state)
                if lgas.count() == Location.objects.filter(parent=state).count():
                    return model_class.objects.filter(
                        location__code__startswith=state.code,
                        time__range=(self.start_date, self.end_date))
                else:
                    locations = state.get_descendants(include_self=True)

            return model_class.objects.filter(location__in=locations,
                time__range=(self.start_date, self.end_date))
        except Exception:
            pass

        return model_class.objects.none()

    @classmethod
    def active_campaigns(cls, location=None):
        date = now().date()
        qs = cls.objects.filter(start_date__lte=date, end_date__gte=date)

        if location is not None and isinstance(location, Location):
            return qs.filter(locations__lft__lte=location.lft,
                locations__rght__gte=location.rght)

        return qs


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

from django.core.management.base import BaseCommand, CommandError

from datetime import datetime
import time
import requests
import facebook
import geocoder
from incf.countryutils import transformations
import pycountry
import json
import urlparse

from soc_net_dashboards.local import linkedin_access_token, fb_app_id, fb_app_secret
from dashboard.models import LinkedInCountryFollowes, FBCountryFans, Fb_Post, LinkedIn_Post

LINKEDIN_API = 'https://api.linkedin.com/v1/companies/8016'

class Command(BaseCommand):
    def handle(self, *args, **kwargs):
        while True:
            # linkedin company followers
            """
            try:
                geo_codes = [
                    {'code': 'eu.dk.*.5038', 'lng': 12.57, 'lat': 55.66, 'name': 'Copenhagen'},
                    {'code': 'eu.dk.*.5041', 'lng': 10.38, 'lat': 55.38, 'name': 'Odense'},
                    {'code': 'eu.dk.*.5044', 'lng': 9.93, 'lat': 57.03, 'name': 'Ålborg'},
                    {'code': 'eu.dk.*.5045', 'lng': 10.18, 'lat': 56.17, 'name': 'Århus'},
                    {'code': 'eu.dk', 'lng': 8.81, 'lat': 56.05, 'name': 'Denmark'},
                    {'code': 'as.cn', 'lng': 112.19, 'lat': 30.86, 'name': 'China'},
                    {'code': 'na.us', 'lng': -105.71, 'lat': 41.88, 'name': 'United States'},
                    {'code': 'as', 'lng': 103.84, 'lat': 46.86, 'name': 'Asia'},
                    {'code': 'eu', 'lng': 15.471, 'lat': 49.81, 'name': 'Europe'},
                    {'code': 'af', 'lng': 21.75, 'lat': -4.03, 'name': 'Africa'},
                    {'code': 'la', 'lng': -44.92, 'lat': -8.23, 'name': 'South America'},
                    {'code': 'na', 'lng': -101.10, 'lat': 48.91, 'name': 'North America'}
                ]
                for code in geo_codes:
                    payload = {
                                'format': 'json',
                                'oauth2_access_token': linkedin_access_token,
                                'geos': code['code']
                    }

                    followers = requests.get("%s/num-followers" % LINKEDIN_API, params=payload).json()
                    if code['code'] == 'as':
                        followers -= LinkedInCountryFollowes.objects.get(code='as.cn').total
                    elif code['code'] == 'eu':
                        followers -= LinkedInCountryFollowes.objects.get(code='eu.dk').total +\
                            self.denmark_cities_followers()
                    elif code['code'] == 'na':
                        followers -= LinkedInCountryFollowes.objects.get(code='na.us').total
                    elif code['code'] == 'eu.dk':
                        followers -= self.denmark_cities_followers()

                    obj, created = LinkedInCountryFollowes.objects.get_or_create(code=code['code'],
                                        defaults={'total': followers, 'latitude': code['lat'],
                                        'longitude': code['lng'], 'country': code['name']})
                    if not created:
                        obj.total = followers
                        obj.save()

                    time.sleep(1)
            except:
                pass
            # linkedin company status updates
            try:
                payload = {
                            'format': 'json',
                            'oauth2_access_token': linkedin_access_token,
                            'event-type': 'status-update'
                }
                statuses = requests.get("%s/updates" % LINKEDIN_API, params=payload).json()
                for status in statuses['values']:
                    share = status['updateContent']['companyStatusUpdate']['share']
                    obj, created = LinkedIn_Post.objects.get_or_create(post_id=share['id'],
                                        defaults={
                                                    'comments': status['updateComments']['_total'],
                                                    'message': share['comment'],
                                                    'img_url': share['content']['submittedImageUrl'],
                                                    'create_at': datetime.fromtimestamp(share['timestamp'] / 1000)
                                        }
                                )
                    if not created:
                        obj.comments = status['updateComments']['_total']
                        obj.save()
            except:
                pass
            """
            # fb
            fb_access_token = facebook.get_app_access_token(fb_app_id, fb_app_secret)
            graph = facebook.GraphAPI(access_token=fb_access_token)
            profile_posts = graph.get_connections("kundeco", "feed", **{'limit': 100})
            # get page feed
            for post in profile_posts['data']:
                if not post.get('message'): continue

                obj, created = Fb_Post.objects.get_or_create(create_at=post['created_time'],
                    message=post['message'], story=post.get('story'), post_id=post['id']
                )
                if (not created and diff_month(datetime.now(), datetime.strptime(post['created_time'][:-5], '%Y-%m-%dT%H:%M:%S')) > 12) or created:
                    try:
                        post_data = graph.get_object("/%s" % post['id'], **{'fields': 'comments.summary(true),likes.summary(true),shares'})
                        obj.likes = post_data['likes']['summary']['total_count']
                        obj.comments = post_data['comments']['summary']['total_count']
                        obj.shares = post_data['shares']['count'] if post_data.get('shares') else 0
                        obj.save()
                    except:
                        obj.likes = 0
                        obj.shares = 0
                        obj.comments = 0
                        obj.save()

            # get page likes
            url = 'https://maps.googleapis.com/maps/api/geocode/json'
            profile_fans = get_page_fans(graph, '/kundeco/insights/page_fans_country')
            for alpha2, fans in profile_fans['value'].items():
                record = FBCountryFans.objects.filter(code=alpha2)
                if not record.exists():
                    try:
                        country = pycountry.countries.get(alpha2=alpha2).name
                        continent = transformations.cca_to_ctn(alpha2)
                        params = {'sensor': 'false', 'address': country}
                        location = requests.get(url, params=params).json()['results'][0]['geometry']['location']
                        FBCountryFans.objects.create(code=alpha2,
                                            total=fans, latitude=location['lat'], continent=continent,
                                            longitude=location['lng'], country=country)
                    except:
                        pass
                else:
                    record = record.first()
                    record.total = fans
                    record.save()
                time.sleep(1)
            time.sleep(1800)

    def denmark_cities_followers(self):
        return LinkedInCountryFollowes.objects.get(code='eu.dk.*.5038').total +\
                    LinkedInCountryFollowes.objects.get(code='eu.dk.*.5041').total +\
                    LinkedInCountryFollowes.objects.get(code='eu.dk.*.5044').total +\
                    LinkedInCountryFollowes.objects.get(code='eu.dk.*.5045').total

def diff_month(d1, d2):
    return (d1.year - d2.year)*12 + d1.month - d2.month

def get_page_fans(graph, url, **kwargs):
    response = graph.get_object(url, **kwargs)
    if response['data']:
        return response['data'][-1]['values'][-1]
    else:
        params = urlparse.parse_qs(urlparse.urlparse(response['paging']['previous']).query)
        return get_page_fans(graph, url, **{'since': params['since'][0], 'until': params['until'][0]})


"""
Problem statement
Given a sorted array that may have duplicate values, use binary search to
find the first and last indexes of a given value.

For example, if you have the array [0, 1, 2, 2, 3, 3, 3, 4, 5, 6] and the
given value is 3, the answer will be [4, 6] (because the value 3 occurs first
at index 4 and last at index 6 in the array).

The expected complexity of the problem is 𝑂(𝑙𝑜𝑔(𝑛))
"""

def first_and_last_index(arr, number):
    """
    Given a sorted array that may have duplicate values, use binary
    search to find the first and last indexes of a given value.

    Args:
        arr(list): Sorted array (or Python list) that may have duplicate values
        number(int): Value to search for in the array
    Returns:
        a list containing the first and last indexes of the given value
    """

    first_element = find_first_element(arr, number)
    last_element = find_last_element(arr, number)

    return [first_element, last_element]

def find_first_element(arr, target):
    start = 0
    end = len(arr) - 1
    index = -1

    while start <= end:
        mid = int((start + end) / 2)
        if arr[mid] == target:
            # mid could be possible first occurence. So store it in index
            index = mid
            # move left
            end = mid - 1
        elif arr[mid] > target:
            end = mid - 1
        else:
            start = mid + 1
    return index

def find_last_element(arr, target):
    start = 0
    end = len(arr) - 1
    index = -1
    while start <= end:
        mid = int((start + end) / 2)
        if arr[mid] == target:
            index = mid
            start = mid + 1
        elif arr[mid] > target:
            end = mid - 1
        else:
            start = mid + 1
    return index

# Tests
def test_function(test_case):
    input_list = test_case[0]
    number = test_case[1]
    solution = test_case[2]
    output = first_and_last_index(input_list, number)
    if output == solution:
        print("Pass")
    else:
        print("Fail")

input_list = [1]
number = 1
solution = [0, 0]
test_case_1 = [input_list, number, solution]
test_function(test_case_1)

input_list = [0, 1, 2, 3, 3, 3, 3, 4, 5, 6]
number = 3
solution = [3, 6]
test_case_2 = [input_list, number, solution]
test_function(test_case_2)

input_list = [0, 1, 2, 3, 4, 5]
number = 5
solution = [5, 5]
test_case_3 = [input_list, number, solution]
test_function(test_case_3)

input_list = [0, 1, 2, 3, 4, 5]
number = 6
solution = [-1, -1]
test_case_4 = [input_list, number, solution]
test_function(test_case_4)


import base64
from socket import *

# Create a TCP server socket
serverSocket = socket(AF_INET, SOCK_STREAM)  # Prepare a server socket. (AF_INET is used for IPv4 protocols)(SOCK_STREAM is used for TCP)

serverPort = 1994  # Assign a port number
serverSocket.bind(('',1994)) # Bind the socket to server address and server port. '' finds current IP.address

serverSocket.listen(1)  # max. number of threads in the connection queue

# Server should be up and running and listening to the incoming connections
while True:
    print('Ready to serve...')
    connectionSocket, addr = serverSocket.accept()  # Set up a new connection from the client

    try:
        message = connectionSocket.recv(1024)  # Receives the request message from the client
        outputdata=""
		# Extract the path of the requested object from the message. The path is the second part of HTTP header, identified by [1]
        filepath = message.split()[1]

        # Read the file and store the entire content of the requested file in a temporary buffer
        if b'png' in filepath:
            data_uri = base64.b64encode(open(filepath[1:], 'rb').read()).decode('utf-8').replace('\n', '')
            outputdata = ''.format(data_uri)
        else:
		    # Because the extracted path of the HTTP request includes a character '\', we read the path from the second character
            f = open(filepath[1:])
            lines = f.readlines()
            for line in lines:
                outputdata += line

        connectionSocket.send(b"HTTP/1.1 200 OK\r\n\r\n")  # Send the HTTP response header line to the connection socket
        response = outputdata + "\r\n"
        connectionSocket.send(response.encode())  # Send the content of the requested file to the connection socket
        connectionSocket.close()  # Close the client connection socket

    except (IOError, IndexError):
        connectionSocket.send(b"HTTP/1.1 404 Not Found\r\n\r\n")  # Send HTTP response message for file not found
        connectionSocket.send(b"<!DOCTYPE html>
404 NOT FOUND
\r\n")

        connectionSocket.close()  # Close the client connection socket

serverSocket.close()


import numpy
import quadprog
import cvxopt
from numpy import *

def quadprog_solve_qp(P, q, G=None, h=None, A=None, b=None):
# minimize x^T*P*x + q^T*x s.t. Gx <= h and Ax = b
    qp_G = .5 * (P + P.T)   # make sure P is symmetric
    qp_a = -q
    if A is not None:
        qp_C = -numpy.vstack([A, G]).T
        qp_b = -numpy.hstack([b, h])
        meq = A.shape[0]
    else:  # no equality constraint
        qp_C = -G.T
        qp_b = -h
        meq = 0
    return quadprog.solve_qp(qp_G, qp_a, qp_C, qp_b, meq)[0]

def cvxopt_solve_qp(P, q, G=None, h=None, A=None, b=None):
    P = .5 * (P + P.T)  # make sure P is symmetric
    args = [cvxopt.matrix(P), cvxopt.matrix(q)]
    if G is not None:
        args.extend([cvxopt.matrix(G), cvxopt.matrix(h)])
        if A is not None:
            args.extend([cvxopt.matrix(A), cvxopt.matrix(b)])
    sol = cvxopt.solvers.qp(*args,options={'show_progress':False})
    if 'optimal' not in sol['status']:
        return None
    return numpy.array(sol['x']).reshape((P.shape[1],))

if __name__ == "__main__":
    P = array([[2.,0.],[0,2.]])
    q = array([-8.,-6.])
    G = array([[-1.,0.],[0.,-1.],[1.,1.]])
    h = array([0.,0.,5.]).reshape((3,))
    print(quadprog_solve_qp(P,q,G,h))
    print(cvxopt_solve_qp(P,q,G,h))


# encoding: utf-8
import tensorflow as tf
tf.set_random_seed(777)  # for reproducibility

# 模拟生成 x_data 和 y_data 数据, 二阶张量 (matrix)
x_data = [[1., 0., 3., 0., 5.],
          [0., 2., 0., 4., 0.]]

y_data = [1, 2, 3, 4, 5]

# 我们要就的变量
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0), name='Weight')
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='biase')

# 假设，线性模型
hypothesis = tf.matmul(W, x_data) + b

# 成本函数 最小化方差
cost = tf.reduce_mean(tf.square(hypothesis - y_data))

# Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 0.1)
train = optimizer.minimize(cost)

# 启动Graph
sess = tf.Session()
# 初始化变量
init = tf.global_variables_initializer()
sess.run(init)

# 拟合平面
for step in range(2001):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(cost), sess.run(W), sess.run(b))


import random

def out_of_order(arr):
    #Algo works only on arrays tuples
    assert (type(arr) == list or type(arr) == tuple)

    count = 0

    for i in range(len(arr)):
        for j in range(i+1,len(arr)):
            if arr[j] < arr[i]:
                count += 1

    return count

def out_of_order_imp(arr):
    assert (type(arr) == list or type(arr) == tuple)

    count = 0

    def merge_sort(arr):
        nonlocal count

        start = 0
        end = len(arr) - 1

        if len(arr) == 1:
            return arr

        if len(arr) == 2:
            if arr[0] < arr[1]:
                return arr
            else :
                count += 1
                arr[0],arr[1] = arr[1],arr[0]
                return arr

        #4K + 2 Split
        if (end - start + 1) % 4 == 2:
            middle = ((start + end) // 2 ) - 1
        else:
            middle = (start + end) // 2

        left_sorted = merge_sort(arr[start:middle+1])
        right_sorted = merge_sort(arr[middle+1:end+1])

        len_l = len(left_sorted)
        len_r = len(right_sorted)
        i = j = 0
        merged_array = []

        while i < len_l and j < len_r:
            if left_sorted[i] < right_sorted[j]:
                merged_array.append(left_sorted[i])
                i += 1
            else:
                merged_array.append(right_sorted[j])
                count += 1
                j += 1

        while i < len_l:
                merged_array.append(left_sorted[i])
                i += 1
                count += 1
        while j < len_r:
                merged_array.append(right_sorted[j])
                j += 1
        return merged_array

    print('The sorted arrays is: ',merge_sort(arr))
    return count

arr = [1,2,3,4,5]

for i in range(5):
    random.shuffle(arr)
    print('\nThe array is ',arr)
    print('Brute Force: ',out_of_order(arr))
    print('Imp        : ',out_of_order_imp(arr))

Ex3 - Out Of Order Pairs/OutOfOrderBoth.py


import numpy as np
import matplotlib.pyplot as plt

# function to construct Mandelbrot set.
def mandelbrot(n_rows, n_columns, iterations):
    x_cor = np.linspace(-2,1,n_rows)
    y_cor = np.linspace(-2,1,n_columns)
    x_len = len(x_cor)
    y_len = len(y_cor)
    output = np.zeros((x_len,y_len))
    for i in range(x_len):
        for j in range(y_len):
            c = complex(x_cor[i],y_cor[j])
            z = complex(0, 0)
            count = 0
            for k in range(iterations):
                z = (z * z) + c
                count = count + 1
                if (abs(z) > 4):
                    break
            output[i,j] = count
            #print((i/x_len)*100,"% completed")
    print(output)
    plt.imshow(output.T, cmap = "hot")
    plt.axis("off")
    plt.show()

mandelbrot(1000,1000,150)


from forecastio import load_forecast
from os import environ
import pytz

def forecastio_weather(lat, lon, timestamp, forecast_type):
    """Return forecastio forecast object, or None if request error"""
    # api key for forecast.io
    api_key = environ.get('FORECASTIO_KEY')

    # get from forecast.io
    weather = load_forecast(api_key, lat, lon, time=timestamp)

    # pull out list of data
    if forecast_type == 'currently':
        data = [weather.currently()]
    elif forecast_type == 'hourly':
        data = weather.hourly().data
    else:
        raise ValueError('forecast_type must be currently or hourly')

    # put in series
    values = [d.temperature for d in data]
    times = [pytz.utc.localize(d.time) for d in data]
    series = zip(times, values)

    # return
    return series


#!/usr/bin/env python3

# Descripción: Cliente que prueba algoritmos de ordenamiento
#     	       con listas de enteros con valores aleatorios
# Autor: Guillermo Palma
# email: gvpalma@usb.ve
# version 0.1

import sys, traceback, random, time
from ordenamiento import *

# Descripción: Procesa la línea de comandos del programa
# Parametros: args: Arreglo de strings con los argumentos de la línea de comando
# La sipnosis de la línea de comandos es:
#
# pruebaOrdenamiento [all|nlgn] <numero de pruebas> <numero de elementos>
#
# donde  [all|nlgn] es el tipo de algoritmos a ejecutar. Con la opción "nlgn" se ejecutaran
# los algoritmos de orden de ejecución O(nlogn)  y con "all" todos los algoritmos. Se tiene
# que <numero de pruebas> es el número de pruebas que se realizan sobre los algoritmos de
# ordenamiento. El <numero de elementos> indica el número de elementos que va a tener el
# arreglo a ordenar
#
# Pre: Deben ser 3 argumentos y tienen el orden: [all|nlgn] <numero de pruebas> <numero de elementos>.
#
# Retorna: La tubla ("tipo de algoritmos a correr", "numero de pruebas", "numero de elementos")

#Roberto Romero 10-10642
#Verónica Machado 10-10407

def parseArgs(args):
    msg = "Error en la linea de comando:\npruebaOrdenamiento [all|nlgn] <numero de pruebas> <numero de elementos>"
    if len(args) != 4:
        print(msg)
        sys.exit(1)

    if (args[1] != "all" and args[1] != "nlgn"):
        print(msg)
        sys.exit(1)

    return args[1], int(args[2]), int(args[3])

# Descripción: Crea arreglo con n valores enteros
#     	       que son generados de forma aleatoria
# Parametros: n: Número de elementos del arreglo
# Retorna: Un objeto lista con n valores enteros aleatorios entre 0 y 1000000

def obtenerArregloEnteros(n):
    return [random.randint(0, 1000000) for x in range(n)]

# Descripción: Comprueba si un arreglo esta ordenado.
# Parametros: a: objeto lista
# Retorna: True si el arreglo está ordenado, False en caso contrario.

def estaOrdenado(a):
    return True

# Descripción: Prueba los algoritmos de ordenamientos con una lista de elementos.
# Se crea un objeto Ordenamiento y se luego se ejecutan que se hayan indicado
#
# Parametros: datos: objeto lista con elementos de un tipo determinado
#             fcmp: función que compara dos elementos del tipo lista
#             tipo: indica el tipo de algoritmos que se van a correr.
#             si tipo = "all" se ejecutan todos los algoritmos que son
#             proporcionados por el módulo ordenamiento, si tipo = "nlgn"
#             se ejecutan los algoritmos con tiempo de ejecución promedio O(nlgn)
#
# Retorna: Una tupla con los tiempos de ejecución, en segundos, de los algoritmos.
# Se retorna una tupla de pares, donde el el primer par
# es una etiqueta con nombre del algoritmo y el segundo es el tiempo de ejecución en segundos.
# Por ejemplo si tipo = "nlgn", entonces la tupla tiene la forma:
# (("Quicksort", tiempo-QS), ("Mergesort", tiempo-MS) ("Heapsort", tiempo-HS))
# Las etiquetas utilizadas son: "Isertionsort", "Bubblesort0", "Bubblesort1", "Quicksort", "Mergesort" y "Heapsort"

def probarAlgoritmos(datos, fcmp, tipo):

    if tipo == "all" :
        print("Comenzando InsertionSort")
        start_time = time.time()
        arrayResult = list(datos)
        insertion(arrayResult, fcmp)
        assert(estaOrdenado(arrayResult))
        timeIsertion = time.time() - start_time

        print("Comenzando Bubblesort0")
        start_time = time.time()
        arrayResult = list(datos)
        bubblesort0(arrayResult, fcmp)
        assert(estaOrdenado(arrayResult))
        timeBubblesort0 = time.time() - start_time

        print("Comenzando Bubblesort1")
        start_time = time.time()
        arrayResult = list(datos)
        bubblesort1(arrayResult, fcmp)
        assert(estaOrdenado(arrayResult))
        timeBubblesort1 = time.time() - start_time

        time_N_2 = (("Isertionsort", timeIsertion), ("Bubblesort0", timeBubblesort0), ("Bubblesort1", timeBubblesort1))
    else :
        time_N_2 = ()

    print("Comenzando Quicksort")
    start_time = time.time()
    arrayResult = list(datos)
    quicksort(arrayResult, fcmp)
    assert(estaOrdenado(arrayResult))
    timeQuicksort = time.time() - start_time

    start_time = time.time()
    arrayResult = list(datos)
    mergesort(arrayResult, fcmp)
    assert(estaOrdenado(arrayResult))
    timeMergesort = time.time() - start_time

    start_time = time.time()
    arrayResult = list(datos)
    heapsort(arrayResult, fcmp)
    assert(estaOrdenado(arrayResult))
    timeHeapsort = time.time() - start_time

    time_N_lg_N = (("Quicksort", timeQuicksort), ("Mergesort", timeMergesort), ("Heapsort", timeHeapsort))

    return time_N_lg_N + time_N_2

# Descripción: Compara dos números enteros.
#              Con esta función se quiere ordenar los elementos
#              de una lista ascendentemente.
# Parametros: x, y: Elementos de tipo numérico
# Retorna: El valor de (x-y)

def comparadorNumerico1(x, y):
    return x - y

# Descripción: Compara dos números enteros.
#              Con esta función se quiere ordenar los elementos
#              de una lista descendentemente.
# Parametros: x, y: Elementos de tipo numérico
# Retorna: El valor de (y-x)

def comparadorNumerico2(x, y):
    return y - x

# Descripción: Ejecuta o prueba los algoritmos de ordenamiento un número
#              de veces determinado.
# Parametros: numPruebas: Número de veces que se van a ejecutar los algoritmos
#                         de ordenamiento.
#              numElems: Número de elementos numéricos que contiene la lista a generar
#              tipo: string con el tipo de algoritmos a ejecutar. Puede ser "all" o "nlgn"
# Retorna: Retorna una lista cuyos elementos son tuplas de pares con los nombres y tiempo de ejecución
# de los algoritmos de ordenamiento. Cada elemento de la lista corresponde a los resultados de una prueba

def realizarPruebas(numPruebas, numElems, tipo):
    datos = []
    resultadosPruebas = []
    for i in range(numPruebas) :
        print("\nComenzando la prueba: "+str(i+1))
        datos = obtenerArregloEnteros(numElems)
        r = probarAlgoritmos(datos, comparadorNumerico1, tipoDeCorrida)
        resultadosPruebas.append(r)
    return resultadosPruebas

# Descripción: Dado una serie de resultados de pruebas sobre
# algoritmos de ordenamientos, calcula e imprime por la salida
# estándar, el tiempo promedio de ejecución de cada algoritmo
# y el valor de su desviación estándar.
#
# Parametros: results: lista con los resultados de cada una de
#             las pruebas o ejecuciones hechas a los algoritmos de ordenamiento.
#             Cada una de las pruebas es una tupla con los resultados de una
#             ejecución de varios algoritmos.
#
# Retorna: Imprime por la salida estándar el tiempo promedio de ejecución de cada
#           uno de los algoritmos probados, junto con la desviación estándar.

################################
## Inicio de la Aplicación
################################

if __name__ == "__main__":
    tipoDeCorrida, numPruebas, numElems = parseArgs(sys.argv)
    results = realizarPruebas(numPruebas, numElems, tipoDeCorrida)


# Make the SNP-fragment list from a multi-sample barcoded 10x-Genomics bam file and its corresponding VCF file with input options: mmq, mbq and qoffset.
# Written by Ehsan Motazedi, Wageningen UR, 04-11-2016.
# Last mofified: 18-07-2018.

import copy
import difflib
import os
import pysam
import re
import subprocess
import sys
from sys import argv
from genotypes import getAllelesPop, getGenotypesPop
from math import log
from reads import Read
# from memory_profiler import profile

def adjust_seq(read):
	""" Adjust the read sequence according to the mapped positions, i.e. get rid of the insertions and clipped bases."""
	cig = list(_x for _x in re.split('[0-9]{1,}', read.cigarstring) if _x)
	cign = list(_x for _x in re.split('[^0-9]', read.cigarstring) if _x)
	cig = list(cig[_n]*int(cign[_n]) for _n in range(0, len(cig)))
	cig = ''.join(_x for _x in cig if 'D' not in _x) # deleted nucleotides from the reference are not present in the read sequence
	adj_seq = []
	adj_qual = []
	for _n, _x in enumerate(read.seq):
		if cig[_n]=='M': # Allow only match/mismatch of the read nucleotides, i.e. no clipping, no insertion.
			adj_qual.append(read.qual[_n])
			adj_seq.append(_x)
	return ''.join(adj_seq), adj_qual

def frag_gen(varpos, allelelst, genolst, coordinates, nucleotides, qscores):
	""" Generate SNP-fragments from (linked) reads."""
	if (not coordinates) or (not nucleotides):
		return Read(), {}
	var_codes = []
	var_num = []
	var_q = []
	for _n, _x in enumerate(varpos):
		if _x < coordinates[0]:
			continue
		if _x > coordinates[-1]:
			break
		if _x in coordinates:
			if set(genolst[_n].GetGenes()).intersection(set(['.','-'])): # Throw away missing genotypes or genotypes with one or more missing allele(s)
				continue
			if len(set(genolst[_n].GetGenes()))<2: # Do not include in the SNP-fragments belonging to a population member its homozygous alleles
				continue
			try:
				var_codes.append(allelelst[_n][2][nucleotides[coordinates.index(_x)]])
				var_num.append(allelelst[_n][0])
				var_q.append(qscores[coordinates.index(_x)])
			except KeyError: # if the called nucleotide is wrong, i.e. does not exist in VCF alleles
				pass
	try: # return the reads {SNP number: allele} and the associated quality scores {SNP number: Qscore}
		return Read({_x:str(_y) for _x, _y in zip([var_num[0], var_num[1]]+var_num[2:], var_codes)}), {_x:str(_y) for _x, _y in zip(var_num, var_q)}
	except IndexError: # throw away reads with less than 2 SNPs
		return Read(), {}

class InputError(Exception):
	""" Handle invalid input specifications."""
	def __init__(self, msg, *args):
		super(InputError, self).__init__(args)
		self.msg = msg
	def __str__(self):
		return "InputError: {}\n".format(self.msg)
	def __repr__(self):
		return (self.msg,)+self.args+('\n',)

# @profile
def get_frags(bamfile, vcffile, mbq=13, mmq=20, qoffset=33):
	"""
mmq : minimum read mapping quality to consider a read for phasing, default 20\n
qvoffset <33/64> : quality value offset, 33/64 depending on how quality values were encoded, default is 33\n
mbq  : minimum base quality to consider a base for haplotype fragment, default 13\n
	"""
	try:
		all_reads = pysam.Samfile(bamfile, 'rb')
	except IOError:
		raise InputError('The input BAM file was not found!')
	ReadHeader = subprocess.Popen(["samtools","view","-H", bamfile], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
	header, err_header = ReadHeader.communicate()
	if ReadHeader.returncode!=0:
		raise InputError('Failed to read the header from the bam file! Original error message:\n'+err_header)
	if isinstance(header, bytes):
		header=bytes.decode(header)
	else:
		pass
	RGIDs, SMnames = [], []
	for _headerline in header.splitlines(): # pasre the header of the bam file to extract the ID and SM fields of each Read Group
		if _headerline[0:3]=='@RG':
			RGID_added, SM_added = False, False
			for _n, _field in enumerate(_headerline.split()):
				if 'ID' in _field:
					if not RGID_added:
						RGIDs.append(''.join(_headerline.split()[_n].split(':')[1:])) # add read group ID
						RGID_added = True
					else:
						raise InputError('Double ID fields detected in @RG header line!')
				elif 'SM' in _field:
					if not SM_added:
						SMnames.append(''.join(_headerline.split()[_n].split(':')[1:])) # add the sample name associated with the read group ID
						SM_added = True
					else:
						raise InputError('Double SM fields detected in @RG header line!')
			if SM_added and RGID_added:
				pass
			elif SM_added:
				raise InputError('ID field missing in @RG header line!')
			elif RGID_added:
				raise InputError('SM field missing in @RG header line!')
			else:
				raise InputError('ID and SM fields missing in @RG header line!')
	if len(RGIDs)!=len(set(RGIDs)):
		raise InputError('Duplicate read group IDs detected in the bam header!')
	GroupedReadsWithID = [[] for _id in RGIDs] # separate reads belonging to each Read Group
	for _read in all_reads:
		try:
			GroupedReadsWithID[RGIDs.index(dict(_read.get_tags())['RG'])].append(_read)
		except ValueError: # this error occurs if a read group in the read tags is not present in the header. This is NOT expected to happen though!
			SMnames.append(SMnames[RGIDs.index(difflib.get_close_matches(dict(_read.get_tags())['RG'],RGIDs)[0])]) # Choose a sample name for the new read group from the header read groups the most close to it
			RGIDs.append(dict(_read.get_tags())['RG'])
			GroupedReadsWithID.append([_read])
	GroupedReads, GroupedSM = [], [] # combine the reads with different RGID but the same SM as they are assumed to belong to the same sample
	for _SMname, _ReadGroup in zip(SMnames, GroupedReadsWithID):
		if _SMname not in GroupedSM:
			GroupedReads.append(_ReadGroup)
			GroupedSM.append(_SMname)
		else:
			GroupedReads[GroupedSM.index(_SMname)]+=_ReadGroup
	del GroupedReadsWithID
	try:
		genolst = getGenotypesPop(vcffile, GroupedSM)
		allelelst = getAllelesPop(vcffile, GroupedSM)
	except IOError:
		raise InputError('The VCF file was not found!')
	except:
		raise
	varpos = list(_x[1] for _x in allelelst)
	for _group, reads in enumerate(GroupedReads):
		out=open('HapCUT_frags_{}.matrix'.format(GroupedSM[_group]),'w')
		BX_reads = []
		Chromium_barcode = []
		for _r in reads:
			try:
				Chromium_barcode.append(_r.get_tag('BX'))
				BX_reads.append(_r)
			except KeyError:
				pass
		garbage = sys.stderr.write('WARNING: {0:d} reads were not considered as they lacked an adjusted chromium barcode!\n'.format(len(reads)-len(BX_reads)))
		reads = BX_reads
		linked_reads = {_barcode:[] for _barcode in Chromium_barcode}
		frag_lst = {_barcode:[] for _barcode in Chromium_barcode}
		q_lst = {_barcode:[] for _barcode in Chromium_barcode}
		HapCUT =  {_barcode:[] for _barcode in Chromium_barcode}
		for _rnum, _barcode in enumerate(Chromium_barcode): # scan through the alignments to find the linked reads)
			read = copy.deepcopy(reads[_rnum])
			if read.is_unmapped or read.is_duplicate or (read.flag & 0x900): # throw away unmapped reads, duplicates and secondary/supplementary alignments
				continue
			if read.mapping_quality >= mmq:
				try:
					adj_seq, adj_qual =  adjust_seq(read)
					coordinates, nucleotides, quals = list(zip(*[(int(_x), _y, _z) for _x, _y, _z in zip(read.positions, adj_seq.upper(), list(ord(_x)-qoffset for _x in adj_qual)) if _z>=mbq]))
				except ValueError as e:
					if e.args[0][0:len("need more than 0 values to unpack")]=="need more than 0 values to unpack" or e.args[0][0:len("not enough values to unpack")]=="not enough values to unpack":
						coordinates, nucleotides, quals= [(), (), ()]
					else:
						raise
				linked_reads[_barcode].append((coordinates, nucleotides, quals))
		for _barcode, _rec in linked_reads.items():
			try:
				_rec = [tuple(zip(*sorted(zip(*_r), key = lambda _x: int(_x[0])))) for _r in _rec if len(_r[0])>0]
				_rec = sorted(_rec, key = lambda x: x[0][0])
			except IndexError as e:
				if "tuple index out of range" in e.args[0]:
					_rec = [(), (), ()]
				else:
					raise
			else: # Take care of overlaps between paired-end reads or between reads in barcoded molecules
				_rn = 0
				while _rn < len(_rec)-1:
					if _rec[_rn][0][-1]<_rec[_rn+1][0][0]:
						_rn+=1
					else:
						coordinates = [_c for _c in _rec[_rn][0]]+[_c for _c in _rec[_rn+1][0]]
						nucleotides = [_n for _n in _rec[_rn][1]]+[_n for _n in _rec[_rn+1][1]]
						quals = [_q for _q in _rec[_rn][2]]+[_q for _q in _rec[_rn+1][2]]
						coordinates, nucleotides, quals = [_t for _t in zip(*sorted(zip(coordinates,nucleotides,quals), key=lambda x: int(x[0])))]
						unique_q = []
						unique_c = []
						unique_n = []
						for _n, _c in enumerate(coordinates): # remove the duplicates from overlapping positions
							try:
								if unique_c[-1]!=_c:
									#print("\nN:\n",nucleotides, "\nQ:\n", quals)
									unique_c.append(_c)
									unique_n.append(nucleotides[_n])
									unique_q.append(quals[_n])
								elif unique_n[-1]==nucleotides[_n]:
									unique_q[-1] = min(126-qoffset, unique_q[-1]+quals[_n])
								else: # if the called nucleotides differ at overlapping sites, use the one with the highest Phred score and adjust the Phred score.
									if quals[_n]>unique_q[-1]:
										_new_q_score = round(-10*log(1-10**(-unique_q[-1]/10)*(1-10**(-quals[_n]/10)), 10), 5) # Q=-10log(p,10)
										if _new_q_score >= mbq:
											unique_n[-1] = nucleotides[_n]
											unique_q[-1] = _new_q_score
										else:
											del(unique_c[-1], unique_n[-1], unique_q[-1])
									else:
										_new_q_score = round(-10*log(1-(1-10**(-unique_q[-1]/10))*10**(-quals[_n]/10), 10), 5)
										if _new_q_score >= mbq:
											unique_q[-1] = _new_q_score
										else:
											del(unique_c[-1], unique_n[-1], unique_q[-1])
							except IndexError:
								unique_c.append(_c)
								unique_n.append(nucleotides[_n])
								unique_q.append(quals[_n])
						_rec[_rn+1] = (tuple(unique_c), tuple(unique_n), tuple(unique_q))
						_rec[_rn] = ((),(),())
						_rn+=1
				_rec = [tuple(zip(*sorted(zip(*_r), key = lambda _x: int(_x[0])))) for _r in _rec if len(_r[0])>0]
				coordinates = [int(_c)+1 for _r in _rec for _c in _r[0]] # Convert the zero-based BAM coordinates to 1-based, as the coordinates are 1-based in the VCF (like the SAM format).
				nucleotides = [_n for _r in _rec for _n in _r[1]]
				quals = [_q for _r in _rec for _q in _r[2]]
				frag_lst[_barcode], q_lst[_barcode] = frag_gen(varpos, allelelst, genolst[_group], coordinates, nucleotides, quals)
				_HapCUT_alleles = [[]]
				_HapCUT_starts = []
				_snp_alleles = frag_lst[_barcode].GetalleleSet(frag_lst[_barcode].GetBegin(), frag_lst[_barcode].GetEnd())
				if len([_x for _x in _snp_alleles if _x!='-'])>1: #keep only SNP-fragments that have a length of at least 2
					for _n, _allele in enumerate(_snp_alleles): # prepare records from the fragment list and the quality list to be written in HapCUT format
						if _allele == '-' and _HapCUT_alleles[-1]!=[]:
							_HapCUT_alleles.append([])
						elif _allele != '-' and _HapCUT_alleles[-1]==[]:
							_HapCUT_alleles[-1].append(_allele)
							_HapCUT_starts.append(str(_n+frag_lst[_barcode].GetBegin()+1))
						elif _allele != '-':
							_HapCUT_alleles[-1].append(_allele)
					_HapCUT_alleles = _HapCUT_alleles[0:len(_HapCUT_starts)] # eliminate empty allele sets
					for _n in range(0, len(_HapCUT_starts)):
						_HapCUT_alleles[_n] = ''.join(_HapCUT_alleles[_n])
					HapCUT[_barcode] = str(len(_HapCUT_starts))+'\t'+'BX::'+_barcode+'\t'+'\t'.join('\t'.join([_start, _alleles]) for _start, _alleles in zip(_HapCUT_starts, _HapCUT_alleles))+'\t'+''.join(chr(int(_q)+qoffset) for _q in q_lst[_barcode].values())
					out.write(HapCUT[_barcode]+os.linesep)
		out.close()

if __name__ == "__main__":

	bamfile=argv[1]
	vcffile=argv[2]
	#get_frags('../20180327/cultivar1_C1R5_BXsorted.bam','../20180327/cultivar1_C1R5_recoded.vcf', mmq=9, mbq=12)
	get_frags(bamfile,vcffile)#, mmq=9, mbq=12)


class Menu:
    def __init__(self, menu):
        self.type = menu["menu_meal_type"]  # breakfast(1)/lunch(2)/dinner(3)
        self.course = menu["course_txt"]  # A/B/C
        self.name = menu["menu_name"]
        self.image = (
            menu["image_url"] + menu["photo_cd"]
            if menu["image_url"] is not None
            else ""
        )
        self.kcal = menu["kcal"]

    def __repr__(self):
        return f"{self.name}({self.kcal} kcal)"

    def dump(self):
        return {"name": self.name, "image": self.image, "kcal": self.kcal}

class Course:
    def __init__(self):
        self.kcal = 0
        self.main = None
        self.side = []

    def add_menu(self, menu):
        m = Menu(menu)
        if menu["tot_kcal"] != 0:  # only main dish contains tot_kcal value
            self.kcal = menu["tot_kcal"]
            self.main = m
        else:
            self.side.append(m)

    def __repr__(self):
        return f"{repr(self.main)}/" + "/".join([repr(s) for s in self.side])

    def dump(self):
        d = {
            "type": self.main.type,
            "kcal": self.kcal,
            "course": self.main.course,
            "main": self.main.dump(),
            "side": [s.dump() for s in self.side],
        }

        return d


from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from crud.apps.forms import addAsignaturaForm
from crud.apps.models import Logro,Asignatura

def index_view(request):
	lista_asinatura = Asignatura.objects.filter(activo=True)
	lista_logro = Logro.objects.filter(activo=True)
	return render_to_response('index.html', locals(),context_instance=RequestContext(request))

def add_asignatura_view(request):
	if request.method == 'POST':
		nombre = request.POST['nombre']
		pesoAsignatura = request.POST['peso']
		activo = True
		asignatura = Asignatura(nombre=nombre,pesoAsignatura=pesoAsignatura,activo=activo)
		asignatura.save()
		return HttpResponseRedirect('/')
	else:
		return render_to_response('addasignatura.html',context_instance=RequestContext(request))

def add_logro_view(request):
	if request.method == 'POST':
		asignatura = request.POST['asignatura']
		idAsignatura = Asignatura.objects.get(nombre=asignatura)
		nombre = request.POST['nombre']
		descripcion = request.POST['descripcion']
		activo=True
		logro = Logro(idAsignatura=idAsignatura,nombre=nombre,descripcion=descripcion,activo=activo)
		logro.save()
		return HttpResponseRedirect('/')
	else:
		asignaturas = Asignatura.objects.all()
		return render_to_response('addlogro.html',locals(),context_instance=RequestContext(request))

def del_asignatura_view(request, id_asignatura):
	try:
		asignatura = Asignatura.objects.get(idAsignatura = id_asignatura)
		asignatura.delete()
	except Asignatura.DoesNotExist:
		return HttpResponseRedirect("/")

	return HttpResponseRedirect("/")

def del_logro_view(request, id_logro):
	try:
		logro = Logro.objects.get(idLogro = id_logro)
		logro.delete()
	except Logro.DoesNotExist:
		return HttpResponseRedirect("/")

	return HttpResponseRedirect("/")

def edit_logro_view(request,id_logro):
	try:
		logro = Logro.objects.get(idLogro = id_logro)
		if request.method == 'POST':
			if logro:
				asig = request.POST['asignatura']
				nombre = request.POST['nombre']
				descripcion = request.POST['descripcion']
				asignatura = Asignatura.objects.get(nombre = asig)
				logro.idAsignatura = asignatura
				logro.nombre = nombre
				logro.descripcion = descripcion
				logro.save()
				return HttpResponseRedirect('/')
		asignaturas = Asignatura.objects.filter(activo = True)
		ctx = {'logro':logro, 'asignaturas':asignaturas}
		return render_to_response('edit_logro.html',ctx,context_instance=RequestContext(request))
	except Logro.DoesNotExist:
		return HttpResponseRedirect("/")

def edit_asignatura_view(request,id_asignatura):
	try:
		asignatura = Asignatura.objects.get(idAsignatura = id_asignatura)
		if request.method == 'POST':
			form = addAsignaturaForm(request.POST,request.FILES)
			if form.is_valid():
				nombre = form.cleaned_data['nombre']
				pesoAsignatura = form.cleaned_data['pesoAsignatura']
				activo = form.cleaned_data['activo']
				asignatura.nombre = nombre
				asignatura.pesoAsignatura = pesoAsignatura
				asignatura.activo = activo
				asignatura.save()
				return HttpResponseRedirect('/')
		if request.method == 'GET':
			form = 	addAsignaturaForm(initial={
									'nombre':asignatura.nombre,
									'pesoAsignatura':asignatura.pesoAsignatura,
									'activo':asignatura.activo
				})
		ctx = {'form':form,'asignatura':asignatura}
		return render_to_response('edit_asignatura.html',ctx,context_instance=RequestContext(request))
	except Logro.DoesNotExist:
		HttpResponseRedirect("/")


# -*- coding: utf-8 -*-
"""
Created on Wed Feb 27 19:19:06 2019

@author: Salim
"""

"""pandas dataframe"""
import numpy as np
import pandas as pd
from numpy.random import randn

df=pd.DataFrame(data=randn(3,3),index=["a","b","c"],columns=["colum1","colum2","colum3"])
print(df)
print(df["colum1"])
print(df.loc["a"])
print(df[["colum1","colum2"]])
df.drop("colum1",axis=1,inplace=True)#inplace işlemden sonra df güncellenmesini saglar
df["colum2"]
df.iloc[0]#a verir
df.loc["a","colum2"]#a indexsiniz colum2 verir
df.loc[["a","b"],["colum2","colum3"]]#a ve b indexlerinin colum2 ve colum  vrir