#import libraries

import os
import string
import glob
import subprocess
from subprocess import Popen
import shutil
import time
import datetime
from datetime import datetime
import pandas as pd
import requests
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from PIL import ImageTk, Image
import plotly.graph_objects as go
from plotly.subplots import make_subplots

#import packages

from packages import tool_path, action

def get_taxonomy_file():
    df_taxonomy = pd.read_csv(tool_path.get_current_path()[0] +'/packages/ressources/taxonomy_by_DB.tsv', sep = '\t') # Read specific taxonomy found in LOTUS_DB
    df_taxonomy_all = pd.read_csv(tool_path.get_current_path()[0] + '/packages/ressources/all_taxonomy_DB.tsv', sep = '\t') # Read general taxonomy found in LOTUS_DB
    return df_taxonomy, df_taxonomy_all

def get_chemontology_file():
    df_chemontology = pd.read_csv(tool_path.get_current_path()[0] + '/packages/ressources/NPClassifier_taxonomy.tsv', sep = '\t')
    return df_chemontology

# Main and most important function to scrap LOTUS
def get_lotus(IDD):

    ############################ Get the code for IDD
    TorC = IDD.split(' : ')[0]
    if TorC == 'T':
        TaxoDB = IDD.split(' : ')[1]
        NPClassifier = ''
        level = IDD.split(' : ')[2]
        name = IDD.split(' : ')[3]
    elif TorC == 'C' :
        TaxoDB = IDD.split(' : ')[1]
        NPClassifier = IDD.split(' : ')[2]
        level = IDD.split(' : ')[3]
        name = IDD.split(' : ')[4]

    elif TorC == 'LTS':
        TaxoDB = IDD.split(' : ')[1]
        NPClassifier = ''
        level = ''
        name = IDD.split(' : ')[2]

    elif TorC == 'F':
        TaxoDB = IDD.split(' : ')[1]
        NPClassifier = ''
        level = ''
        name = IDD.split(' : ')[2]

    print(TorC, TaxoDB, NPClassifier, level, name)

    url = str('https://lotus.naturalproducts.net/api/search/simple?query=' + str(name))

    response = requests.get(url)
    storage = [response.json()]  #get the seaerch result in a json format

    nb = len(str(storage)[1:-1].split("{'id'")) - 1   #get the number of molecule for the search
    print(str(nb) + ' results' )

    ###################################Get all the keys for the research

    list_key_value=[]
    for mol in range(nb):
        for key in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'] :

            if TaxoDB != 'All_Taxonomy_DB' and TorC == 'T':
                if TaxoDB in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][TaxoDB])):
                        if storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][TaxoDB][go][level] != None and name in str(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][TaxoDB][go][level]):
                            key_value = [mol,key, TaxoDB, go]
    #                     print(key_value)
                            list_key_value.append(key_value)
    #                     print(storage[0]['naturalProducts'][key_value[0]]['taxonomyReferenceObjects'][key_value[1]][TaxoDB][0])

            elif TaxoDB == 'All_Taxonomy_DB' and TorC == 'T':
                for taxo in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][taxo])):
                        if storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][taxo][go][level] != None and name in str(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][taxo][go][level]):
                            key_value = [mol,key, taxo, go]
    #                     print(key_value)
                            list_key_value.append(key_value)
    #                     print(storage[0]['naturalProducts'][key_value[0]]['taxonomyReferenceObjects'][key_value[1]][key_value[2]][0])

            elif TaxoDB != 'All_Taxonomy_DB' and TorC == 'C':
                if TaxoDB in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][TaxoDB])):
                        if storage[0]['naturalProducts'][mol][level] != None and name in str(storage[0]['naturalProducts'][mol][level]):
                            key_value = [mol,key,TaxoDB, go]
    #                     print(key_value)
                            list_key_value.append(key_value)

            elif TaxoDB == 'All_Taxonomy_DB' and TorC == 'C':
                for taxo in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][taxo])):
                        if storage[0]['naturalProducts'][mol][level] != None and name in str(storage[0]['naturalProducts'][mol][level]):
                            key_value = [mol,key, taxo, go]
    #                     print(key_value)
                            list_key_value.append(key_value)

            elif TaxoDB != 'All_Taxonomy_DB' and TorC == 'LTS':
                if TaxoDB in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][TaxoDB])):
                        key_value = [mol,key,TaxoDB, go]
                        list_key_value.append(key_value)

            elif TaxoDB == 'All_Taxonomy_DB' and TorC == 'LTS':
                for taxo in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][taxo])):
                        key_value = [mol,key, taxo, go]
                        list_key_value.append(key_value)

            elif TaxoDB != 'All_Taxonomy_DB' and TorC == 'F':
                if TaxoDB in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][TaxoDB])):
                        key_value = [mol,key, TaxoDB, go]
                        list_key_value.append(key_value)

            elif TaxoDB == 'All_Taxonomy_DB' and TorC == 'F':
                for taxo in storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key]:
                    for go in range(len(storage[0]['naturalProducts'][mol]['taxonomyReferenceObjects'][key][taxo])):
                        key_value = [mol,key, taxo, go]
                        list_key_value.append(key_value)

    ######################## transform the keys to search
    df = pd.DataFrame(list_key_value, columns =['mol', 'key', 'taxo', 'go'])
    list_new_key_value = []
    new_list = list(set(df.mol))
    for mol in new_list:
        AA = {}
        list_new_key = set(df.loc[df.mol == mol].key.to_list())

        df2 = df.loc[df.mol == mol]
        aa = {}
        for x in list_new_key:

            list_taxo = list(set(df2.loc[df2.key == x].taxo.to_list()))

            df3 = df2.loc[df2.key == x]

            rst={}
            for y in list_taxo:

                list_go = df3.loc[df3.taxo == y].go.to_list()

                rst[y] = list_go
            aa[x] = rst
        AA = [mol, aa]

        list_new_key_value.append(AA)

    ########################### get Lotus
    global Dict
    Dict = {
            'Lotus_ID' :{} , 'smiles' : {}, 'inchi' : {}, 'inchikey' : {},  'cas' : {}, 'iupac_name' : {}, 'molecular_formula' : {}, 'molecular_weight' : {}, 'xlogp' : {} ,
            'superkingdom':{}, 'kingdom':{}, 'phylum':{}, 'classx':{}, 'order':{}, 'family': {}, 'genus' : {}, 'species' :{} ,
            'chemicalTaxonomyClassyfireKingdom' : {} , 'chemicalTaxonomyClassyfireSuperclass' :{}, 'chemicalTaxonomyClassyfireClass' : {} , 'chemicalTaxonomyClassyfireDirectParent' : {} ,
            'chemicalTaxonomyNPclassifierPathway' : {} ,'chemicalTaxonomyNPclassifierSuperclass' : {} , 'chemicalTaxonomyNPclassifierClass' : {},
            'traditional_name' : {}
           } #Create a global dict to store metadata from LOTUS

    xx = 1  #start dict at 1

    # if TaxoDB != "All_Taxonomy_DB" and TorC == 'T':
    zz = 0
    for molindex in list_new_key_value:

        Dict['Lotus_ID'][xx] = storage[0]['naturalProducts'][molindex[0]]['lotus_id']
        Dict['smiles'][xx] = storage[0]['naturalProducts'][molindex[0]]['smiles']
        Dict['inchi'][xx] = storage[0]['naturalProducts'][molindex[0]]['inchi']
        Dict['inchikey'][xx] = storage[0]['naturalProducts'][molindex[0]]['inchikey']
        Dict['cas'][xx] = storage[0]['naturalProducts'][molindex[0]]['cas']
        Dict['traditional_name'][xx] = storage[0]['naturalProducts'][molindex[0]]['traditional_name'].encode(encoding = 'UTF-8', errors = 'replace')
        Dict['iupac_name'][xx] = (storage[0]['naturalProducts'][molindex[0]]['iupac_name']).encode(encoding = 'UTF-8', errors = 'replace')
        Dict['molecular_formula'][xx] = storage[0]['naturalProducts'][molindex[0]]['molecular_formula']
        Dict['molecular_weight'][xx] = storage[0]['naturalProducts'][molindex[0]]['molecular_weight']
        Dict['xlogp'][xx] = storage[0]['naturalProducts'][molindex[0]]['xlogp']

        Dict['chemicalTaxonomyClassyfireKingdom'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyClassyfireKingdom']
        Dict['chemicalTaxonomyClassyfireSuperclass'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyClassyfireSuperclass']
        Dict['chemicalTaxonomyClassyfireClass'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyClassyfireClass']
        Dict['chemicalTaxonomyClassyfireDirectParent'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyClassyfireDirectParent']
        Dict['chemicalTaxonomyNPclassifierPathway'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyNPclassifierPathway']
        Dict['chemicalTaxonomyNPclassifierSuperclass'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyNPclassifierSuperclass']
        Dict['chemicalTaxonomyNPclassifierClass'][xx] = storage[0]['naturalProducts'][molindex[0]]['chemicalTaxonomyNPclassifierClass']

        spk1={}
        ki1={}
        ph1={}
        cl1={}
        or11={}
        fm1={}
        ge1={}
        spe1={}

        print(molindex[0])
        for key in list_new_key_value[zz][1]: ####################decalage de 1 !!!!!!!! a reparer
            print(key)
            spk={}
            ki={}
            ph={}
            cl={}
            or1={}
            fm={}
            ge={}
            spe={}

            for taxo in list_new_key_value[zz][1][key]:
                print(taxo)
                superkingdom=[]
                kingdom=[]
                phylum=[]
                classx=[]
                order=[]
                family=[]
                genus=[]
                species=[]
                for go in range(len(list_new_key_value[zz][1][key][taxo])):

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['superkingdom'] not in superkingdom:
                        superkingdom.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['superkingdom'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['kingdom'] not in kingdom:
                        kingdom.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['kingdom'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['phylum'] not in phylum:
                        phylum.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['phylum'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['classx'] not in classx:
                        classx.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['classx'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['order'] not in order:
                        order.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['order'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['family'] not in family:
                        family.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['family'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['genus'] not in genus:
                        genus.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['genus'])

                    if storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['species'] not in species:
                        species.append(storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][key][taxo][list_new_key_value[zz][1][key][taxo][go]]['species'])
    #                 print(species)

                spk[taxo] = ' - '.join([str(e) for e in superkingdom])
                ki[taxo] =' - '.join([str(e) for e in kingdom])
                ph[taxo] =' - '.join([str(e) for e in phylum])
                cl[taxo]=' - '.join([str(e) for e in classx])
                or1[taxo]=' - '.join([str(e) for e in order])
                fm[taxo]=' - '.join([str(e) for e in family])
                ge[taxo]=' - '.join([str(e) for e in genus])
                spe[taxo]=' - '.join([str(e) for e in species])

                if taxo in spk1:
                    spk1[taxo]=spk1[taxo] + ' - ' + spk[taxo]
                    ki1[taxo]=ki1[taxo] +' - ' + ki[taxo]
                    ph1[taxo]=ph1[taxo] +' - ' + ph[taxo]
                    cl1[taxo]=cl1[taxo] +' - ' + cl[taxo]
                    or11[taxo]=or11[taxo] +' - ' + or1[taxo]
                    fm1[taxo]= fm1[taxo] +' - ' + fm[taxo]
                    ge1[taxo]=ge1[taxo] +' - ' + ge[taxo]
                    spe1[taxo]=spe1[taxo] +' - ' + spe[taxo]
                else:
                    spk1[taxo]= spk[taxo]
                    ki1[taxo]=ki[taxo]
                    ph1[taxo]=ph[taxo]
                    cl1[taxo]=cl[taxo]
                    or11[taxo]=or1[taxo]
                    fm1[taxo]=fm[taxo]
                    ge1[taxo]=ge[taxo]
                    spe1[taxo]=spe[taxo]

        for taxo in spk1:
            spk1[taxo] = set(spk1[taxo].split(' - '))
            ki1[taxo] = set(ki1[taxo].split(' - '))
    #         print(ki[taxo])
            ph1[taxo] = set(ph1[taxo].split(' - '))
            cl1[taxo] = set(cl1[taxo].split(' - '))
            or11[taxo] = set(or11[taxo].split(' - '))
            fm1[taxo] = set(fm1[taxo].split(' - '))
            ge1[taxo] = set(ge1[taxo].split(' - '))
            spe1[taxo] = set(spe1[taxo].split(' - '))

        print(spe1)

        Dict['superkingdom'][xx] = spk1
        Dict['kingdom'][xx] =ki1
        Dict['phylum'][xx] =ph1
        Dict['classx'][xx] = cl1
        Dict['order'][xx]  = or11
        Dict['family'][xx] = fm1
        Dict['genus'][xx] = ge1
        Dict['species'][xx] = spe1
            #################################################################################
        zz=zz+1
    #         Dict['reference_wikidata_id'][xx] = storage[0]['naturalProducts'][molindex[0]]['taxonomyReferenceObjects'][molindex[1]][molindex[2]][0]['reference_wikidata_id']

        xx = xx + 1 # Next molecule

    global df_lotus
    df_lotus = pd.DataFrame.from_dict(Dict)
    #df_lotus.to_csv('cfmid_input.tsv', sep = '\t', index = False)

    return df_lotus

# Function to search all the selected listed criteria in LOTUS_DB
def get_lotus_add():

    list_IDD = action.get_selected_search_criteria_list()

    if list_IDD[0] == '':

        print(str(datetime.now()) + " Come on, make a choice ! ")
        messagebox.showinfo("Info", "Come on, make a chocie !")
    else :

        Dict_neutral = {
                'Lotus_ID' :{} , 'smiles' : {}, 'inchi' : {}, 'inchikey' : {},  'cas' : {}, 'iupac_name' : {}, 'molecular_formula' : {}, 'molecular_weight' : {}, 'xlogp' : {} ,
                'superkingdom':{}, 'kingdom':{}, 'phylum':{}, 'classx':{}, 'order':{}, 'family': {}, 'genus' : {}, 'species' :{} ,
                'chemicalTaxonomyClassyfireKingdom' : {} , 'chemicalTaxonomyClassyfireSuperclass' :{}, 'chemicalTaxonomyClassyfireClass' : {} , 'chemicalTaxonomyClassyfireDirectParent' : {} ,
                'chemicalTaxonomyNPclassifierPathway' : {} ,'chemicalTaxonomyNPclassifierSuperclass' : {} , 'chemicalTaxonomyNPclassifierClass' : {}
                ,'traditional_name' : {}
        }
        df_general = pd.DataFrame.from_dict(Dict_neutral)

        for IDD in list_IDD:
            #get_lotus(IDD.split(' : ')[1])
            print(IDD)
            get_lotus(IDD)

            df_general = pd.concat([df_general, df_lotus], ignore_index = True)
            df_general= df_general.drop_duplicates(subset=['Lotus_ID'])
        df_general.to_csv(tool_path.get_current_path()[0]+ '/LOTUS_DB_input/cfmid_input.tsv', sep = '\t', index = False)
        fileout = open(tool_path.get_current_path()[0] + '/LOTUS_DB_input/cfmid_input.txt', "w")
        fileout_sirius_db = open(tool_path.get_current_path()[0] + '/LOTUS_DB_input/structural_db.txt', "w") #####230228
        print(str(datetime.now()) + " There are " + str(len(df_general['Lotus_ID'])) +" molecules for " + str(list_IDD))

        messagebox.showinfo("Info", "There are " + str(len(df_general['Lotus_ID'])) +" molecules for " + str(list_IDD))
        for i in df_general['Lotus_ID']:
             fileout.write(i + ' ' + df_general['smiles'][int(str(df_general.Lotus_ID[df_general.Lotus_ID == i ].index.to_list()[0]))] + '\n' )
             fileout_sirius_db.write(df_general['smiles'][int(str(df_general.Lotus_ID[df_general.Lotus_ID == i ].index.to_list()[0]))] + ' ' + i + '\n' ) ######230228
        fileout.close()
        fileout_sirius_db.close() #####230228
    errorlog = open(tool_path.get_current_path()[0] + '/log/' + str(datetime.now()).replace(' ', '_').replace(':', '_').replace('.','_') + '_input_criteria.txt', 'w')
    errorlog.write("This log contains criteria for research in the online LOTUS DataBase on the "+ str(datetime.now()) + " ." + "\n")
    errorlog.write('The research has been made with the "for all selected categories" method.' + "\n")
    errorlog.write("There are " + str(len(df_general['Lotus_ID'])) +" molecules corresponding to your criteria." + "\n")
    for IDD in list_IDD:
        errorlog.write(str(IDD) + "\n")
    errorlog.close()

# Function to search combined selected listed criteria in LOTUS_DB
def get_lotus_or():

    list_IDD = action.get_selected_search_criteria_list()
    if list_IDD[0] == '':
        print(str(datetime.now()) + " Come on, make a choice ! ")
        messagebox.showinfo("Info", "Come on, make a chocie !")
    else :

        Dict_neutral = {
                'Lotus_ID' :{} , 'smiles' : {}, 'inchi' : {}, 'inchikey' : {},  'cas' : {}, 'iupac_name' : {}, 'molecular_formula' : {}, 'molecular_weight' : {}, 'xlogp' : {} ,
                'superkingdom':{}, 'kingdom':{}, 'phylum':{}, 'classx':{}, 'order':{}, 'family': {}, 'genus' : {}, 'species' :{} ,
                'chemicalTaxonomyClassyfireKingdom' : {} , 'chemicalTaxonomyClassyfireSuperclass' :{}, 'chemicalTaxonomyClassyfireClass' : {} , 'chemicalTaxonomyClassyfireDirectParent' : {} ,
                'chemicalTaxonomyNPclassifierPathway' : {} ,'chemicalTaxonomyNPclassifierSuperclass' : {} , 'chemicalTaxonomyNPclassifierClass' : {}
                ,'traditional_name' : {}
        }

        df_general = pd.DataFrame.from_dict(Dict_neutral)
        df_general2 = pd.DataFrame.from_dict(Dict_neutral)

        selected_tax = []
        selected_chemical = []
        selected_formula = []
        for IDD in list_IDD:
            if 'T : ' in IDD:
                selected_tax.append(IDD) # Is the criteria a Taxonomic criteria ?
            elif 'C : ' in IDD:
                #selected_chemical.append(IDD.split(' : ')[4]) # Is the criteria a Chemontologic criteria
                selected_chemical.append(IDD)
            elif 'F : ' in IDD:
                #selected_formula.append(IDD.split(' : ')[2]) # Is the criteria a Formula criteria ?
                selected_formula.append(IDD)
        if selected_tax != [] :         # if taxonomy criteria exist
            for sel_tax in selected_tax:

                get_lotus(sel_tax)

                if selected_chemical != [] : #if taxonomy and chemontoly criteria exist
                    for sel_chemical in selected_chemical:
                        if sel_chemical.split(' : ')[4] in df_lotus['chemicalTaxonomyNPclassifierPathway'].to_list():
                            new_df = df_lotus.loc[(df_lotus['chemicalTaxonomyNPclassifierPathway'] == str(sel_chemical.split(' : ')[4])) | (df_lotus['chemicalTaxonomyNPclassifierPathway'] == str(str(sel_chemical.split(' : ')[4]) + '|' + str(sel_chemical.split(' : ')[4])))] ####230228
                            df_general = pd.concat([df_general, new_df], ignore_index = True)

                        elif sel_chemical.split(' : ')[4] in df_lotus['chemicalTaxonomyNPclassifierSuperclass'].to_list():
                            new_df = df_lotus.loc[(df_lotus['chemicalTaxonomyNPclassifierSuperclass'] == str(sel_chemical.split(' : ')[4]))]
                            df_general = pd.concat([df_general, new_df], ignore_index = True)

                        elif sel_chemical.split(' : ')[4] in df_lotus['chemicalTaxonomyNPclassifierClass'].to_list():
                            new_df = df_lotus.loc[(df_lotus['chemicalTaxonomyNPclassifierClass'] == str(sel_chemical.split(' : ')[4]))]
                            df_general = pd.concat([df_general, new_df], ignore_index = True)

                        if selected_formula != [] :       #if taxonomy and chemontoly and formula criteria exist
                            for sel_formula in selected_formula:
                                if sel_formula.split(' : ')[2] in df_general['molecular_formula'].to_list():
                                    new_df = df_general.loc[(df_general['molecular_formula'] == str(sel_formula.split(' : ')[2]))]
                                    df_general2 = pd.concat([df_general2, new_df], ignore_index = True)
                        else :
                            df_general2 = pd.concat([df_general2, df_general], ignore_index = True) #if taxonomy and chemontoly exist but not formula

                else : #if taxonomy exist but not chemontology
                    if selected_formula != [] : #if taxonomy and formula criteria exist but not chemontology
                        for sel_formula in selected_formula:
                            if sel_formula.split(' : ')[2] in df_lotus['molecular_formula'].to_list():
                                new_df = df_lotus.loc[(df_lotus['molecular_formula'] == str(sel_formula.split(' : ')[2]))]
                                df_general2 = pd.concat([df_general2, new_df], ignore_index = True)
                    else :   # if only taxonomy criteria exist
                        df_general2 = pd.concat([df_general2, df_lotus], ignore_index = True)

        else :    #if taxonomy criteria does not exist
            if selected_chemical != [] :  #if taxonomy criteria does not exist but chemontology exist
                for sel_chemical in selected_chemical:
                    get_lotus(sel_chemical)
                    if selected_formula != [] :    #if taxonomy criteria does not exist but chemontology and formula exist
                        for sel_formula in selected_formula:

                            if sel_formula.split(' : ')[2] in df_lotus['molecular_formula'].to_list():
                                new_df = df_lotus.loc[(df_lotus['molecular_formula'] == str(sel_formula.split(' : ')[2]))]
                                df_general2 = pd.concat([df_general2, new_df], ignore_index = True)
                    else :   #if taxonomy criteria and formula do not exist but chemontology exist
                        df_general2 = pd.concat([df_general2, df_lotus], ignore_index = True)
            else :  #if taxonomy criteria and chemontoly do not exist
                if selected_formula != [] :   #if taxonomy criteria and chemontoly do not exist but formula exist
                    for sel_formula in selected_formula:
                        get_lotus(sel_formula)
                        df_general2 = pd.concat([df_general2, df_lotus], ignore_index = True)

        #messagebox.showinfo("Info", "There are " + str(len(df_general2['Lotus_ID'])) +" molecules for this research")
        df_general2= df_general2.drop_duplicates(subset=['Lotus_ID']) #delete duplicates in the results of the search
        if df_general2['Lotus_ID'].to_list():
            df_general2.to_csv(tool_path.get_current_path()[0]+ '/LOTUS_DB_input/cfmid_input.tsv', sep = '\t', index = False)  #export metadata in .TSV file

            fileout = open(tool_path.get_current_path()[0]+ '/LOTUS_DB_input/cfmid_input.txt', "w") #export LOTUS_ID and SMILES in text file
            fileout_sirius_db = open(tool_path.get_current_path()[0] + '/LOTUS_DB_input/structural_db.txt', "w") #####230228
            for i in df_general2['Lotus_ID']:
                 fileout.write(i + ' ' + df_general2['smiles'][int(str(df_general2.Lotus_ID[df_general2.Lotus_ID == i ].index.to_list()[0]))] + '\n' )
                 fileout_sirius_db.write(df_general2['smiles'][int(str(df_general2.Lotus_ID[df_general2.Lotus_ID == i ].index.to_list()[0]))] + ' ' + i + '\n' ) ######230228
            fileout.close()
            fileout_sirius_db.close()
            print(str(datetime.now()) + " There is a total of " + str(len(df_general2['Lotus_ID'].to_list()))  + " molecules for requested categories.")
            messagebox.showinfo("Info", "There is a total of " + str(len(df_general2['Lotus_ID'].to_list()))  + " molecules for requested categories.")
        else:
            messagebox.showinfo("Info", "There is no molecules for requested categories.")
            print(str(datetime.now()) + " Info", "There is no molecules for requested categories.")

    errorlog = open(tool_path.get_current_path()[0] + '/log/' + str(datetime.now()).replace(' ', '_').replace(':', '_').replace('.','_') + '_input_criteria.txt', 'w')
    errorlog.write("This log contains criteria for research in the online LOTUS DataBase on the "+ str(datetime.now()) + " ." + "\n")
    errorlog.write('The research has been made with the "for selected chemical class.es in selected family.ies" method.' + "\n")
    errorlog.write("There are " + str(len(df_general2['Lotus_ID'])) +" molecules corresponding to your criteria." + "\n")
    for IDD in list_IDD:
        errorlog.write(str(IDD) + "\n")
    errorlog.close()

#get the cfmid 4.0 docker image identifier to log
def get_cfmid_docker_image():
    ID_container_id = open(tool_path.get_current_path()[0] + '/CFM_ID_4/ID_container_cfmid.txt', 'r').read().split('\n')[0]
    return ID_container_id


import numpy as np
import torch
from  torch.utils.data.dataloader import DataLoader
from torchvision import transforms
from functions import*
import os
'''
bbvi without Rao_Blackwellization and Control Variates
'''
num_epochs=1
batchSize=500
num_S=5#训练的采样数量
dim=1000000+1
eta=0.05#步长
num_St=100#测试的采样数量
interval=20
#读取数据
train_index=np.linspace(0,999999,1000000)
with open('./dataset/criteo-train-sub1000000.txt','r') as f:
    train_datas=f.readlines()
train_loader=DataLoader(train_index,batch_size=batchSize,shuffle=True)

#定义分布参数
para=torch.zeros(dim*2,requires_grad=True)
#para[dim:]=torch.ones(dim)*(-0.5)
#其他变量
scale=1000000/batchSize
G=torch.zeros(dim*2)

#需要储存结果
elbo_list=[]
para_list=[]

#开始迭代
for epoch in range(num_epochs):
    for i ,data_index in enumerate(train_loader):
        labels,images=data_preprocess(train_datas,data_index,dim)
        revise=batchSize/len(images)
        #过程变量
        gradients=torch.zeros((num_S,dim*2))
        #ELBO evaluate & record para
        if i==len(train_loader)-1:
            para_list.append(para.clone().detach().numpy())
        if (epoch*len(train_loader)+i)%interval==0:
            elbo_list.append(elbo_evaluate(images,labels,para,dim,scale,revise,num_St).item())
        #算法起始位置
        z_samples=sampleZ(para,dim,num_S)
        log_qs=ng_log_Qs(para,z_samples,dim)
        log_priors=ng_log_Priors(z_samples,dim)
        log_likelihoods=ng_log_Likelihoods(images,labels,z_samples,dim)
        for s in range(len(z_samples)):
            gradients[s]=grad_log_Q(para,z_samples[s],dim)
        elbo_temp=log_likelihoods*revise+log_priors/scale-log_qs/scale
        grad_temp=torch.matmul(torch.diag(elbo_temp),gradients)
        grad_avg=torch.mean(grad_temp,0)
        G+=grad_avg*grad_avg
        rho=eta/torch.sqrt(G)
        update=rho*grad_avg
        para.data+=update
        #print information
        print(torch.median(update.abs()),torch.max(update.abs()))
        if (epoch*len(train_loader)+i)%interval==0:
            print('Epoch[{}/{}], step[{}/{}]'.format(\
                epoch+1,
                num_epochs,
                i+1,len(train_loader)))
            print('ELBO: {:.3f}\n'.format(\
                elbo_list[len(elbo_list)-1]))

if not os.path.exists('./result_elbo'):
    os.makedirs('./result_elbo')
result=np.array(elbo_list)
np.save('./result_elbo/bbvi_basic.npy',result)

if not os.path.exists('./result_para'):
    os.makedirs('./result_para')
result=np.array(para_list)
np.save('./result_para/bbvi_basic.npy',result)


import sys
sys.stdin = open("circlecross.in", "r")
sys.stdout = open("circlecross.out", "w")

log = input()

def get_index(target):
    inx = []
    for i in range(len(log)):
        if log[i] == target:
            inx.append(i)
    return inx[0], inx[1]

alphabet = []
path = dict()
for i in range(26):
    letter = chr(65+i)
    inx1, inx2 = get_index(letter)
    path[letter] = (inx1, inx2)
    alphabet.append(letter)

ans = 0
for i in range(26):
    for j in range(26):
        letter1 = alphabet[i]
        letter2 = alphabet[j]

        inx1, inx2 = path[letter1]
        inx3, inx4 = path[letter2]

        if inx1 < inx3 < inx2 < inx4:
            ans += 1

print(ans)


'''
Bitwise operations done on the files
'''
import cv2
import numpy as np

img1 = np.zeros((250, 500, 3),np.uint8)
img1 = cv2.rectangle(img1, (200,0), (300, 100), (255,255,255), -1)

img2 = np.zeros((250, 500, 3),np.uint8)
img2 = cv2.rectangle(img2, (0, 0), (250, 250), (255,255,255), -1)

cv2.imshow('image1',img1)
cv2.imshow('image2',img2)

bitAnd = cv2.bitwise_and(img2,img1)
#cv2.imshow('bit-AND',bitAnd)

bitOr = cv2.bitwise_or(img2, img1)
#cv2.imshow('bit-or',bitOr)

bitnot = cv2.bitwise_not(img2)
cv2.imshow('bitnot',bitnot)

cv2.waitKey(0)
cv2.destroyAllWindows()


#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Created on Feb 20, 2013

@author: Maribel Acosta
@author: Fabian Floeck
@author: Michael Ruster
'''

from mw.xml_dump import Iterator as mwIterator
from mw.xml_dump.functions import EXTENSIONS as mwExtensions
from mw.xml_dump.functions import open_file

from functions.print import *
import functions.PageProcessing as PageProcessing
import functions.DumpConditions as Conditions

import os
from sys import argv

def extractFileNamesFromPath(path):
    """ Returns a list of file names that are identified under path.
    If path is a directory, its contents will be returned non-recursively. Thus,
    all non-directories with the suffix of a supported datatype will be returned.
    The list will be sorted alphabetically in ascending manner.
    If path identifies a file, it will be returned as a list.
    When path does neither, a FileNotFoundError is thrown.
    """
    if os.path.isdir(path):
        directoryContents = os.listdir(path)
        fileNames = []
        # filter for XML files only.
        for supportedFiletype in mwExtensions.keys():
            fileNames.extend(os.path.join(path, f)
                               for f in directoryContents
                               if f.lower().endswith("." + supportedFiletype)
                            )
        fileNames.sort()
    elif os.path.isfile(path):
        fileNames = [path]
    else:
        raise FileNotFoundError('No file or directory could be found in "%s"' % path)
    return fileNames

def analyseDumpsAndOutputWriteToDisk(path, blockLog, condition):
    """ Load dump file(s) from path and iterate over their pages and their
    revisions. All revisions will be matched against the blockLog to calculate
    how many seconds after the creation of the revision, the author was blocked
    (if s/he was blocked at all afterwards).
    """
    assert ((condition == Conditions.isRegisteredUserTalk and not blockLog) or
            (condition == Conditions.isDeletionDiscussion and blockLog)), '[E] Blocks may not be empty when processing deletion discussions.'

    if condition == Conditions.isDeletionDiscussion:
        print("[I] Loading blocked users and the associated blocking timestamps into memory.", end=' ')
        import BlockTimeCalculation
        blocks = BlockTimeCalculation.createBlockedUsersDict(blockLog)
        print("Done.")
    else:
        blocks = None

    for fileName in extractFileNamesFromPath(path):
        print('[I] Now processing the file "%s".' % fileName)
        # Access the file.
        dumpIterator = mwIterator.from_file(open_file(fileName))

        # Iterate over the pages.
        for page in dumpIterator:

            shouldDeletionDiscussionsBeProcessed = condition == Conditions.isDeletionDiscussion
            if condition(page):
                (revisions_order, revisions) = PageProcessing.process(page, shouldDeletionDiscussionsBeProcessed)

                if shouldDeletionDiscussionsBeProcessed:
                    assert blocks, '[E] Blocks was empty.'
                    writeAllRevisions(revisions_order, revisions, blocks)
                else:
                    assert page.title, '[E] The page title was empty.'
                    writeAllRevisions(revisions_order, revisions, blocks, page.title)

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description="WikiWho DiscussionParser: An algorithm for extracting posts on Wikipedia page deletion discussions and checking when the post's author has last been blocked.",
                                     epilog="""
                                     WikiWho DiscussionParser, Copyright (C) 2015 Fabian Flöck, Maribel Acosta, Michael Ruster (based on wikiwho by Fabian Flöck, Maribel Acosta).
                                     WikiWho DiscussionParser comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. For more information, see the LICENSE and README.md files this program should have been distributed with.
                                     """)

    parser.add_argument('-i', dest='pageDumpPath', required=True,
                        help='Path to the Wikipedia page(s) dump (XML, 7z, bz2…).')
    parser.add_argument('-b', dest='blockLog',  type=argparse.FileType('r'),
                        default=None, nargs='?',
                        help='Path to the block log file produced wit 0nse/WikiParser (CSV).'),
    parser.add_argument('-c', dest='condition', nargs='?',
                        default='isDeletionDiscussion', type=str,
                        help='Decide whether you want to process deletion discussions or user warnings. It must identify a boolean method returning True or False on a Page object. Available options are "isDeletionDiscussion" and "isRegisteredUserTalk". The default is "isDeletionDiscussion".')

    args = parser.parse_args()
    condition = Conditions.parse(args.condition)

    analyseDumpsAndOutputWriteToDisk(args.pageDumpPath, args.blockLog, condition)


# Para abrir y cerrar un archivo.

file = open("./documents/Texto de prueba.txt", mode="r", encoding="utf-8")
print(file.read())
file.close()

print("=" * 20)

# Para abrir un archivo y cerrarlo de manera automática.
with open("./documents/Texto de prueba.txt", encoding="utf-8") as file:
    for line in file:
        print(line)

# Escribir algún texto en un archivo.
nuevo_archivo = open("./documents/Nuevo archivo.txt", mode="w", encoding="utf-8")
nuevo_archivo.write("Hola, esta es la primera línea del archivo. \n")