#Usage: python3 kptable-appendix-11b.py [-h] [--help]
import datetime
import pathlib
import pandas as pd
import xlsxwriter
from lukeghg.crf.crfxmlconstants import ch4co2eq, n2oco2eq, ctoco2
from lukeghg.crf.crfxmlfunctions import ConvertFloat,ConvertSign, ConvertToCO2, SumTwoValues, SumBiomassLs
from lukeghg.crf.crfxmlfunctions import PaddingList, GenerateRowTitleList

#These constants will come from CrfXMLConstants
#Please check the
#ch4co2eq=25.0
#n2oco2eq=298.0
#ctoco2=44.0/12.0
#nkset={'IE','NA','NO','NE'}
#Sort the Records based on YearName in ascending order
def SortKey(x):
    return x.attrib['YearName']
#---------------------------------The main program begins--------------------------------------------------

def appendix11b(start,end,directory,file_name):
    #Command line generator
    global ch4co2eq, n2oco2eq,ctoco2
    inventory_year=end
    #Output file, the table
    kptable_appendix_11b_file = file_name
    directory=directory+'/'
    #Table Appendix-11b Afforestation/Reforestation and Deforestation files
    #Deforestation "Conversion to water CH4" comes from NIR folder
    kp4a2_fl_to_waters_ch4_org=directory+'KP4A2_FLtowaters_orgsoil_CH4.csv'
    #The rest of the files are from  crf-folder.
    kp4a_agr_bm_gains_losses=directory+'KP4A_agr_bm_gains_losses.csv'
    #2015 file name change
    #2016 file name change
    #2015:kpa2_ar_under_D_gains='KP4A2_AR_und_defor_treebm_gains.csv'
    kpa2_ar_under_D_gains=directory+'KP4A2_AR_und_D_living_biomass_gains_trees.csv'
    kp4a2_sl_soil=directory+'KP4A2_SL_soil.csv'
    kp4a2_ar_under_d_soil=directory+'KP4A2_AR_und_defor_soils.csv'
    #2015 KP_MTT_UID.csv in two files: KP_defor_mineral.csv and KP_defor_organic.csv
    #kp_uid_mtt='KP_MTT_UID.csv'
    kp_defor_mineral=directory+'KP_defor_mineral.csv'
    kp_defor_organic=directory+'KP_defor_organic.csv'
    kp4a2_fl_to_wl_soil=directory+'KP4A2_FLtoWL_soils.csv'
    kp4a2_clglpewesl_deadwood=directory+'KP4A2_CLGLPEWESL_deadwood.csv'
    kp4a2_d_living_biomass_losses_trees=directory+'KP4A2_D_living_biomass_losses_trees.csv'
    kp4a2_fl_to_waters_org_soil=directory+'KP4A2_FLtowaters_orgsoil.csv'
    #2015 rename
    #kp4a2_d_mineralization='KP4A2_D_mineraalisationcl_gl_sl.csv'
    kp4a2_d_mineralization=directory+'KPA2_soil_leaching_N2O.csv'
    #2015 addition is Afforestation mineralization
    kp4_ar_mineralization=directory+'KP4_Affor_mineralization.csv'
    kp4a2_fl_to_wl_non_co2=directory+'KP4A2_FLtoWL_soils_nonCO2.csv'
    kp4_living_biomass_gains_trees=directory+'KP4_living_biomass_gains_trees.csv'
    kp4_ar_living_biomass_losses_trees=directory+'KP4A1_AR_living_biomass_losses_trees.csv'
    kp4a1_clglsl_mineral_soil=directory+'KP4A1_CLGLSL_mineral_soil.csv'
    kp4a1_ar_org_soil=directory+'KP4A1_AR_Organic_soil_C.csv'
    kp4a11_wildfires=directory+'KP4A11_wildfires.csv'
    kp4a1_clglpewesl_organic_soils_nonco2=directory+'KP4A1_CLGLPEWESL_organic_soils_nonco2.csv'
    kp4_hwp_ard=directory+'KP4_HWP-AR.csv'
    #Data for the two Tables in Appendix 1
    #1. Deforestation: Conversion to water CH4
    #Change in 2015: use third (CH4) line in kp4a2_fl_to_waters_org_soil
    #----------------------------------------
    f = open(kp4a2_fl_to_waters_org_soil)
    #Read to a list [[year,val1],[year,val2]....,[year,valN]]
    ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Third line is CH4
    ls = ls[2]
    #Convert to CO2
    ls.pop(0)
    fl_to_waters_ch4_co2_ls = [ConvertToCO2(ch4co2eq,x) for x in ls]
    f.close()
    #2. Agriculture Afforestation and Deforestation biomasses
    #---------------------------------------------------------
    f = open(kp4a_agr_bm_gains_losses)
    agr_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Pick the deforestation, the first part in the file
    agr_d_ls = agr_ls[0:8]
    #Pick the Afforestation and Reforestation, rest of the file
    agr_ar_ls = agr_ls[8:len(agr_ls)]
    #Deforestation: Sum the biomassess: Cropland, Grassland, North and South Finland,
    #above ground and below ground
    agr_d_bm_ls=SumBiomassLs(agr_d_ls)
    #Afforestation: Sum the biomassess: Cropland, Grassland, North and South Finland,
    #above ground and below ground
    agr_ar_bm_ls=SumBiomassLs(agr_ar_ls)
    #Convert to CO2 and convert sign: if biomass increases -> emissiosn decrease and vice versa
    agr_d_co2_ls=[ConvertSign(ConvertToCO2(ctoco2,x)) for x in agr_d_bm_ls]
    agr_ar_co2_ls=[ConvertSign(ConvertToCO2(ctoco2,x)) for x in agr_ar_bm_ls]
    f.close()
    #3. Deforestation biomass losses in trees
    #----------------------------------------
    f = open(kp4a2_d_living_biomass_losses_trees)
    d_trees_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Sum the biomasses, CL, GL, SETT, WL, North and South Finland, below and above ground
    trees_bm_ls = SumBiomassLs(d_trees_ls)
    #Convert to CO2 and convert sign: if biomass increases -> emissions decrease and vice versa
    trees_d_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in trees_bm_ls]
    f.close()
    #Deforestation Biomass: Afforestation/Reforestation under Deforestation, gains
    #---------------------------------------------------------------------
    f = open(kpa2_ar_under_D_gains)
    ar_under_d_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    ar_under_d_sum_ls = SumBiomassLs(ar_under_d_ls)
    #Convert to CO2 and convert sign: if biomass increases -> emissions decrease and vice versa
    ar_under_d_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in ar_under_d_sum_ls]
    f.close()
    #Deforestation: DOM+SOM Mineral soils
    #-----------------------------------
    f = open(kp4a2_sl_soil)
    d_sl_soil_ls =  [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_sl_soil_sum_ls = SumBiomassLs(d_sl_soil_ls)
    d_sl_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_sl_soil_sum_ls]
    f.close()
    f = open(kp4a2_ar_under_d_soil)
    d_ar_under_d_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Sum the both lines
    d_ar_under_d_min_soil_sum_ls = SumBiomassLs(d_ar_under_d_soil_ls)
    d_ar_under_d_min_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_ar_under_d_min_soil_sum_ls]
    f.close()
    #Settlements are now in Mineral soil, take lines 9 and 10
    f = open(kp4a2_clglpewesl_deadwood)
    d_clglpewesl_deadwood_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_clglpewesl_deadwood_ls = d_clglpewesl_deadwood_ls[8:len(d_clglpewesl_deadwood_ls)]
    d_clglpewesl_deadwood_min_sum_ls = SumBiomassLs(d_clglpewesl_deadwood_ls)
    d_clglpewesl_deadwood_min_co2_ls =  [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_clglpewesl_deadwood_min_sum_ls]
    f.close()
    f = open(kp_defor_mineral)
    d_mtt_min_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_mtt_min_soil_ls = d_mtt_min_soil_ls[0:4]
    d_mtt_min_soil_sum_ls = SumBiomassLs(d_mtt_min_soil_ls)
    d_mtt_min_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_mtt_min_soil_sum_ls]
    f.close()
    d_dom_som_min_soil_deadwood_sum_co2_ls = [SumTwoValues(a,SumTwoValues(b,SumTwoValues(c,d))) for (a,b,c,d) in zip(d_sl_soil_co2_ls,
                                                                                d_ar_under_d_min_soil_co2_ls,
                                                                                d_clglpewesl_deadwood_min_co2_ls,
                                                                                d_mtt_min_soil_co2_ls)]

    #Deforestation: DOM+SOM Organic soils + Deadwood
    #-----------------------------------------------
    f = open(kp4a2_fl_to_wl_soil)
    d_fl_to_wl_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_fl_to_wl_soil_sum_ls = SumBiomassLs(d_fl_to_wl_soil_ls)
    d_fl_to_wl_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_fl_to_wl_soil_sum_ls]
    f.close()
    f = open(kp4a2_clglpewesl_deadwood)
    d_clglpewesl_deadwood_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_clglpewesl_deadwood_ls = d_clglpewesl_deadwood_ls[0:8]
    d_clglpewesl_deadwood_org_sum_ls = SumBiomassLs(d_clglpewesl_deadwood_ls)
    d_clglpewesl_deadwood_org_co2_ls =  [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_clglpewesl_deadwood_org_sum_ls]
    f.close()
    f = open(kp_defor_organic)
    d_mtt_org_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_mtt_org_soil_sum_ls = SumBiomassLs(d_mtt_org_soil_ls)
    d_mtt_org_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_mtt_org_soil_sum_ls]
    #print(8,d_mtt_org_soil_co2_ls)
    f.close()
    d_dom_som_org_soil_deadwood_sum_co2_ls=[SumTwoValues(a,SumTwoValues(b,c)) for (a,b,c) in
                                            zip(d_fl_to_wl_soil_co2_ls,d_clglpewesl_deadwood_org_co2_ls,d_mtt_org_soil_co2_ls)]
    #Deforestation: Conversion to water CO2
    #Change in 2015: Lines 1 and 2 are C
    #--------------------------------------
    f = open(kp4a2_fl_to_waters_org_soil)
    d_fl_to_waters_org_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Lines 1,2 are C
    d_fl_to_waters_org_soil_ls = d_fl_to_waters_org_soil_ls[0:2]
    d_fl_to_waters_org_soil_sum_ls = SumBiomassLs(d_fl_to_waters_org_soil_ls)
    d_fl_to_waters_org_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in d_fl_to_waters_org_soil_sum_ls]
    f.close()
    #Deforestation: Mineralization
    #-----------------------------
    f = open(kp4a2_d_mineralization)
    d_mineralization_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #2015 two last lines are N2O
    d_mineralization_ls = d_mineralization_ls[2:len(d_mineralization_ls)]
    d_mineralization_sum_ls =  SumBiomassLs(d_mineralization_ls)
    d_mineralization_co2_ls = [ConvertToCO2(n2oco2eq,x) for x in d_mineralization_sum_ls]
    f.close()
    #Deforestation: Drained and rewetted organic soils N2O
    #-----------------------------------------------------
    f = open(kp4a2_fl_to_wl_non_co2)
    d_fl_to_wl_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_fl_to_wl_n2o_ls = d_fl_to_wl_ls[0:1]
    d_fl_to_wl_n2o_sum_ls =  SumBiomassLs(d_fl_to_wl_n2o_ls)
    d_fl_to_wl_n2o_co2_ls = [ConvertToCO2(n2oco2eq,x) for x in d_fl_to_wl_n2o_sum_ls]
    f.close()
    #Deforestation: Drained and rewetted organic soils CH4
    #-----------------------------------------------------
    f = open(kp4a2_fl_to_wl_non_co2)
    d_fl_to_wl_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    d_fl_to_wl_ch4_ls = d_fl_to_wl_ls[1:2]
    d_fl_to_wl_ch4_sum_ls =  SumBiomassLs(d_fl_to_wl_ch4_ls)
    d_fl_to_wl_ch4_co2_ls = [ConvertToCO2(ch4co2eq,x) for x in d_fl_to_wl_ch4_sum_ls]
    f.close()
    #Deforestation HWP
    #-----------------
    #HWP is IE
    d_hwp_ls = ['IE']*(inventory_year-1990+1)
    #4. Afforestation living biomass gains and losses trees
    #-------------------------------------------
    f = open(kp4_living_biomass_gains_trees)
    ar_trees_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    f.close()
    #Pick the Afforestation part, 2015 mineral and organic are added (not separately in the file)
    ar_bm_gains_trees_ls = ar_trees_ls[4:len(ar_trees_ls)]
    #Sum the biomasses, CL, CL, WLpeat, WLorg, Settlement, mineral, orgaing, South and North Finland
    ar_bm_sum_gains_trees_ls = SumBiomassLs(ar_bm_gains_trees_ls)
    f = open(kp4_ar_living_biomass_losses_trees)
    ar_bm_losses_trees_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    f.close()
    ar_bm_sum_losses_trees_ls = SumBiomassLs(ar_bm_losses_trees_ls)
    ar_bm_net_trees_ls = [SumTwoValues(x,y) for (x,y) in zip(ar_bm_sum_gains_trees_ls,ar_bm_sum_losses_trees_ls)]
    #Convert to CO2 and convert sign: if biomass increases -> emissions decrease and vice versa
    trees_ar_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in ar_bm_net_trees_ls]
    #5. Afforestation, DOM+SOM Mineral soils
    #----------------------------------------
    f = open(kp4a1_clglsl_mineral_soil)
    dom_som_min_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    dom_som_min_soil_sum_ls = SumBiomassLs(dom_som_min_soil_ls)
    #Convert to CO2 and convert sign: if biomass increases -> emissions decrease and vice versa
    dom_som_min_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in dom_som_min_soil_sum_ls]
    f.close()
    #6. Afforestation, DOM+SOM Organinc soils
    #----------------------------------------
    f=open(kp4a1_ar_org_soil)
    dom_som_org_soil_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    dom_som_org_soil_sum_ls = SumBiomassLs(dom_som_org_soil_ls)
    #Convert to CO2 and convert sign: if biomass increases -> emissions decrease and vice versa
    dom_som_org_soil_co2_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in dom_som_org_soil_sum_ls ]
    f.close()
    #7. Biomass burning
    #------------------
    f=open(kp4a11_wildfires)
    biomass_burning_ls = [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #CO2 South and North Finland
    bm_burning_co2_ls = biomass_burning_ls[0:2]
    bm_burning_co2_sum_ls = SumBiomassLs(bm_burning_co2_ls)
    #CH4 South and North Finland
    bm_burning_ch4_ls = biomass_burning_ls[2:4]
    bm_burning_ch4_sum_ls = SumBiomassLs(bm_burning_ch4_ls)
    #N2O South and North Finland
    bm_burning_n2o_ls  = biomass_burning_ls[4:6]
    bm_burning_n2o_sum_ls = SumBiomassLs(bm_burning_n2o_ls)
    #Convert ch4 and n2o to co2eq and sum all three emissions
    biomass_burning_ch4co2eq_ls = [ConvertToCO2(ch4co2eq,x) for x in bm_burning_ch4_sum_ls]
    biomass_burning_n2oco2eq_ls = [ConvertToCO2(n2oco2eq,x) for x in bm_burning_n2o_sum_ls]
    biomass_burning_co2_sum_ls = [SumTwoValues(x,SumTwoValues(y,z)) for (x,y,z) in zip(bm_burning_co2_sum_ls,biomass_burning_ch4co2eq_ls,biomass_burning_n2oco2eq_ls)]
    #print(biomass_burning_co2_sum_ls)
    f.close()
    #8. 2015 addition Mineralization
    #-------------------------------
    f=open(kp4_ar_mineralization)
    ar_mineralization_ls=[x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #South and North Fianland
    ar_mineralization_no2_ls = ar_mineralization_ls[0:2]
    ar_mineralization_n2o_sum_ls=SumBiomassLs(ar_mineralization_no2_ls)
    ar_mineralization_n2o_co2_ls = [ConvertToCO2(n2oco2eq,x) for x in ar_mineralization_n2o_sum_ls]
    #9.Drained organic soils N2O
    #---------------------------
    f=open(kp4a1_clglpewesl_organic_soils_nonco2)
    drained_org_soils_nonco2_ls =  [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Two lines in the file, the first one is CH4
    drained_org_soils_sum_ch4_ls = drained_org_soils_nonco2_ls[0:1]
    drained_org_soils_sum_ch4_ls =  SumBiomassLs(drained_org_soils_sum_ch4_ls)
    #Convert from N2O to CO2
    drained_org_soils_sum_ch4co2eq_ls = [ConvertToCO2(ch4co2eq,x) for x in drained_org_soils_sum_ch4_ls]
    f.close()
    #10.Drained organic soils CH4
    #---------------------------
    f=open(kp4a1_clglpewesl_organic_soils_nonco2)
    drained_org_soils_nonco2_ls =  [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #Two lines in the file, the second one is CH4
    drained_org_soils_sum_n2o_ls = drained_org_soils_nonco2_ls[1:2]
    drained_org_soils_sum_n2o_ls = SumBiomassLs(drained_org_soils_sum_n2o_ls)
    #Convert from CH4 to CO2
    drained_org_soils_sum_n2oco2eq_ls = [ConvertToCO2(n2oco2eq,x) for x in drained_org_soils_sum_n2o_ls]
    f.close()
    #11.HWP afforestation
    #--------------------
    f=open(kp4_hwp_ard)
    hwp_ard_ls =  [x.rpartition('#')[2].split() for x in f.readlines() if x.count('#') != 1]
    #2015 the file structure is in 3 parts: 1) Initial stock, 2) Gains and losses 3) half-time information
    #The sum of gains and losses will go to the table
    #2016 the file structure is for each item: 1) half life, 2) init stock, 3) gains and 4) losses
    #Pick every fourth item starting from the first right place in the list
    hwp_ar_ls_gains = hwp_ard_ls[2::4]
    hwp_ar_ls_losses = hwp_ard_ls[3::4]
    hwp_ar_ls = hwp_ar_ls_gains+hwp_ar_ls_losses
    #print(hwp_ar_ls)
    hwp_ar_sum_ls = SumBiomassLs(hwp_ar_ls)
    #Removals are good for the atmosphere, change the sign
    hwp_ar_sum_ls = [ConvertSign(ConvertToCO2(ctoco2,x)) for x in hwp_ar_sum_ls]
    #HWP does not have full time series from 1990
    hwp_padding_ls = PaddingList(inventory_year,hwp_ar_sum_ls)
    hwp_padding_ls = ['IE']*len(hwp_padding_ls)
    hwp_ar_sum_co2_ls = hwp_padding_ls+hwp_ar_sum_ls
    f.close()

    #Create the two tables Afforestation/Reforestation and Deforestation
    #-------------------------------------------------------------------
    print("Creating first text file for Afforestation/Reforestation and Deforestation in", file_name)
    f1 = open(kptable_appendix_11b_file,'w')
    delim ='#'
    table_name="Appendix_11b"
    table_header="Net emissions and removals from the ativities under Articles 3.3\n"
    table1title1="Table 1_App_11b Net emissions and removals from Afforestation and Reforestation, kt CO2eq.\n"
    table2title2="Table 2_App_11b Net emissions and removals from Deforestation, ktCO2eq.\n"
    table1columns1=delim+"Biomass"+delim+"DOM+SOM Mineral soils"+delim+"DOM+SOM Organic soils"+delim+"Biomass burning"+delim+"Mineralization"+delim
    table1columns1=table1columns1+"Drained organic soils N2O"+delim+"Drained organic soils CH4"+delim+"HWP"+delim+"Total\n"
    table2columns2=delim+"Biomass"+delim+"DOM+SOM Mineral soils"+delim+"DOM+SOM Organic soils+Deadwood"+delim+"Conversion to water CO2"+delim+"Mineralization"+delim
    table2columns2=table2columns2+"Drained and rewetted organic soils CH4"+delim+"Drained and rewetted organic soils NO2"+delim
    table2columns2=table2columns2+"HWP"+delim+"Conversion to water CH4"+delim+"Total"+"#\n"
    #Row titles from 199 to inventory year
    row_title_ls = GenerateRowTitleList(start,inventory_year)
    f1.write(table_name)
    f1.write(table_header)
    #Afforestation and Reforestation
    f1.write(table1title1)
    f1.write(table1columns1)
    for (year,agr_ar_co2,trees_ar_co2,dom_som_min,dom_som_org,bm_burning,ar_min_co2,n2oco2eq,ch4co2eq,hwp) in zip(row_title_ls,agr_ar_co2_ls,trees_ar_co2_ls,
                                                                                dom_som_min_soil_co2_ls,
                                                                                dom_som_org_soil_co2_ls,
                                                                                biomass_burning_co2_sum_ls,
                                                                                ar_mineralization_n2o_co2_ls,
                                                                                drained_org_soils_sum_n2oco2eq_ls,
                                                                                drained_org_soils_sum_ch4co2eq_ls,
                                                                                hwp_ar_sum_co2_ls):
        total=SumTwoValues(SumTwoValues(SumTwoValues(SumTwoValues(SumTwoValues(SumTwoValues(SumTwoValues(SumTwoValues(agr_ar_co2,trees_ar_co2),
                                                                                dom_som_min),dom_som_org),bm_burning),
                                                                                ar_min_co2),n2oco2eq),ch4co2eq),hwp)
        f1.write(str(year)+delim+str(SumTwoValues(agr_ar_co2,trees_ar_co2))+"#"+str(dom_som_min)+"#"+str(dom_som_org)+"#"+str(bm_burning)+"#")
        f1.write(str(ar_min_co2)+"#"+str(n2oco2eq)+"#"+str(ch4co2eq)+"#"+str(hwp)+"#"+str(total)+"#\n")
    f1.write("Data from:"+"#"+kp4a_agr_bm_gains_losses+" Lines:9-"+str(len(agr_ls))+"#"+kp4a1_clglsl_mineral_soil+"#"+kp4a1_ar_org_soil+"#"+kp4a11_wildfires+"#")
    f1.write(kp4_ar_mineralization+" Lines:1,2"+delim+kp4a1_clglpewesl_organic_soils_nonco2+" Line:1"+"#"+kp4a1_clglpewesl_organic_soils_nonco2+" Line:2"+"#"+kp4_hwp_ard+"#\n")
    f1.write("#"+kp4_living_biomass_gains_trees+" Lines:5-"+str(len(ar_trees_ls))+"#"+"#"+"#"+"CO2 Lines:1-2,CH4 Lines:3-4,N2O Lines:5-6"+"####"+"Gains Lines:3,7,11 etc."+"#\n")
    f1.write("#"+kp4_ar_living_biomass_losses_trees+"#######"+"Losses Lines:4,8,12 etc."+"#\n")
    f1.write('\n\n')

    #Deforestation
    f1.write(table2title2)
    f1.write(table2columns2)
    for (year,agr_d_co2,trees_d_co2,ar_under_d_co2,
        d_sl_soil_co2,d_ar_under_d_min_soil_co2,d_mtt_min_soil_co2,d_clglpewesl_deadwood_min_co2,
        dom_som_org_soil_deadwood_co2,
        d_fl_to_waters_org_soil_co2,
        d_mineralization_co2,
        d_fl_to_wl_ch4_co2,d_fl_to_wl_n2o_co2,
        d_hwp,
        to_waters_ch4) in zip(row_title_ls,agr_d_co2_ls,trees_d_co2_ls,ar_under_d_co2_ls,
                            d_sl_soil_co2_ls,d_ar_under_d_min_soil_co2_ls,d_mtt_min_soil_co2_ls,d_clglpewesl_deadwood_min_co2_ls,
                            d_dom_som_org_soil_deadwood_sum_co2_ls,
                            d_fl_to_waters_org_soil_co2_ls,
                            d_mineralization_co2_ls,
                            d_fl_to_wl_ch4_co2_ls,d_fl_to_wl_n2o_co2_ls,
                            d_hwp_ls,
                            fl_to_waters_ch4_co2_ls):
        biomass = SumTwoValues(agr_d_co2,trees_d_co2)
        biomass = SumTwoValues(biomass,ar_under_d_co2)
        dom_som_min_soil=SumTwoValues(d_sl_soil_co2,d_ar_under_d_min_soil_co2)
        dom_som_min_soil=SumTwoValues(dom_som_min_soil,d_mtt_min_soil_co2)
        dom_som_min_soil=SumTwoValues(dom_som_min_soil,d_clglpewesl_deadwood_min_co2)
        total1 = SumTwoValues(SumTwoValues(SumTwoValues(SumTwoValues(agr_d_co2,trees_d_co2),ar_under_d_co2),d_sl_soil_co2),d_ar_under_d_min_soil_co2)
        total2 = SumTwoValues(SumTwoValues(d_mtt_min_soil_co2,d_clglpewesl_deadwood_min_co2),dom_som_org_soil_deadwood_co2)
        total3 = SumTwoValues(SumTwoValues(d_fl_to_waters_org_soil_co2,d_mineralization_co2),d_fl_to_wl_ch4_co2)
        total4 = SumTwoValues(SumTwoValues(d_fl_to_wl_n2o_co2,d_hwp),to_waters_ch4)
        total = total1+total2+total3+total4
        f1.write(str(year)+delim+str(biomass)+delim+str(dom_som_min_soil)+delim+str(dom_som_org_soil_deadwood_co2)+delim+str(d_fl_to_waters_org_soil_co2)+delim+
                str(d_mineralization_co2)+delim+str(d_fl_to_wl_ch4_co2)+delim+str(d_fl_to_wl_n2o_co2)+delim+str(d_hwp)+delim+str(to_waters_ch4)+"#"+str(total)+"#\n")

    f1.write("Data from:"+"#"+kp4a_agr_bm_gains_losses+" Lines:1-8"+delim+kp4a2_sl_soil+delim+kp4a2_fl_to_wl_soil+delim+kp4a2_fl_to_waters_org_soil+" Lines:1,2"+"#")
    f1.write(kp4a2_d_mineralization+delim+kp4a2_fl_to_wl_non_co2+" Line:2"+delim+kp4a2_fl_to_wl_non_co2+" Line:1"+delim+"No file"+delim)
    f1.write(kp4a2_fl_to_waters_org_soil+" Line:3"+"#\n")
    f1.write("#"+kp4a2_d_living_biomass_losses_trees+delim+kp4a2_ar_under_d_soil+delim+kp4a2_clglpewesl_deadwood+" Lines:1-8"+"#\n")
    f1.write("#"+kpa2_ar_under_D_gains+delim+kp_defor_mineral+delim+kp_defor_organic+"#\n")
    f1.write("#"+delim+kp4a2_clglpewesl_deadwood+" Lines:9-10"+"#\n")
    now = datetime.datetime.now()
    #print(str(now))
    f1.write("Date produced: "+str(now)+"\n")
    f1.close()
    #Create excel
    p = pathlib.Path(file_name)
    stem = p.stem
    p_excel = pathlib.Path(stem+'.xlsx')
    print("Creating Excel file for Afforestation/Reforestation and Deforestation in", str(p_excel))
    #Define max number of columns, dataframe can adjust to it
    names=['col' + str(x) for x in range(12) ]
    df = pd.read_csv(file_name,engine='python',header=None,delimiter='#',keep_default_na=False,names=names,dtype=str)
    writer = pd.ExcelWriter(p_excel,engine='openpyxl')
    df_float = df.applymap(ConvertFloat)
    df_float.to_excel(writer,file_name,header=False)
    writer.close()


import glob

import cv2
import numpy as np
from tqdm import tqdm

class Calibration(object):
    def __init__(self, targetfilepath):
        # termination criteria
        self.criteria = (cv2.TERM_CRITERIA_EPS +
                         cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-5)

        # prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
        self.worldPoints = np.zeros((9 * 6, 3), np.float32)  # 모두 [0] 체스판에서 찾을 점의 3D좌표 셋 바탕
        self.worldPoints[:, :2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2)
        # 월드 좌표계의 베이스를 잡아줌, 왼쪽 맨 위를 원점으로 함(0,0,0)
        # 체스판이므로 Z-좌표값은 0으로 함

        # Arrays to store object points and image points from all the images.
        self.objectPoints = []  # 3d point in real world space, 켈리브레이션 넣을때 셋 지정하려고
        self.imagePoints = []  # 2d points in image plane.

        self.cameraMatrix = None
        self.distortion = None
        self.img_shape = None
        self.rvecs = None
        self.tvecs = None

# 덤프를 제거한 원하는 본질만 담은 것 & 회전벡터는 3x3으로 처리해놓기도 함
        self.targetRvecs = []
        self.targetTvecs = []

        self.readfile(targetfilepath)

    def readfile(self, targetfilepath):

        targetimagefile = glob.glob(targetfilepath + '\\*.jpg')
        #targetimagefile.sort()

        print("start loading files")
        for i in tqdm(range(len(targetimagefile))):

            # print(targetimagefile[i])

            imgmat = cv2.imread(targetimagefile[i])

            # 그레이 스케일로 변경
            imggray = cv2.cvtColor(imgmat, cv2.COLOR_BGR2GRAY)

            # Find the chess board corners
            # 성공 여부, 코너 포인트 리스트
            # 이미지, 모서리 수, 플래그
            ret, corners = cv2.findChessboardCorners(imggray, (9, 6), None)

            if ret is True:
                # If found, add object points, image points (after refining them)
                cv2.cornerSubPix(imggray, corners, (11, 11), (-1, -1), self.criteria)  # 찾은 코너에 대한 보정
                self.imagePoints.append(corners)
                self.objectPoints.append(self.worldPoints)

                # ret = cv2.drawChessboardCorners(imgmat, (9, 6), corners, ret)
                # cv2.imshow("test", imgmat)
                # cv2.waitKey(1)

        self.img_shape = cv2.cvtColor(cv2.imread(targetimagefile[0]), cv2.COLOR_BGR2GRAY).shape[::-1]
        self.calibrate(len(targetimagefile))

    def calibrate(self, target_lenght):
        print("enter 1d calibration")
        ret, self.cameraMatrix, self.distortion, self.rvecs, self.tvecs = cv2.calibrateCamera(
            objectPoints=self.objectPoints,
            imagePoints=self.imagePoints,
            imageSize=self.img_shape,
            cameraMatrix=self.cameraMatrix,
            distCoeffs=self.distortion,
            rvecs=self.rvecs,
            tvecs=self.tvecs)
        print(ret)
        # 한 카메라에 대한 켈리브레이션:
        # 성공여부, camera matrix, distortion coefficients, rotation and translation vector"s"
        # R|t는 한 뷰에 대한 월드 원점 - 2D 뷰의 영상중점 (cx,cy)간 좌표변환들
        print("exit 1d calibration")

        # for i in tqdm(range(target_lenght)):
        #     dst, _ = cv2.Rodrigues(self.rvecs[i])
        #     self.targetRvecs.append(dst)
        #     self.targetTvecs.append(self.tvecs[i])
        # print("Rodrigues eqs is solved")
        # for i, (r, t) in enumerate(zip(self.rvecs, self.tvecs)):
        #        dst, _ = cv2.Rodrigues(r)  # 회전벡터의 경우 표현방식이 달라서 변환 필요. 로드리게스 변환 참조.
        #        print(i, "번째 회전이동 : \n", dst)
        #        print(i, "번째 평행이동 : \n", t)


# -*- coding: utf-8 -*-
"""
Created on Fri Feb 17 10:15:08 2023

@author: anjan
"""
import numpy as np

def swap_rows(A,p,q):
    """
    Parameters
    ----------
    A: A numpy.ndarry matrix of any dimensions

    p,q : integers
        The indices of two rows of the matrix.

    Returns
    -------
    numpy.ndarry matrix A with row p swapped with row q.

    """

    A[[p,q],:]=A[[q,p],:]

    return A

def partial_pivot(L,P,U,k,max_index):
    """

    Parameters
    ----------
    max_index: integer
        The index of the maximum of the absolutes
        in the elements below the pivot
    L : square matrix
        A Lower Triangular Matrix
        in the intermediate stage of a Gaussian Elimination
    P : square matrix
        A permuation matrix
    U : square matrix
        The matrix in the intermediate stage of Gaussian Elimination
        that would eventually return an Upper triangular matrix
    k : integer
        The row index of the pivot of the matrix U

    Returns
    -------
    numpy.ndarry matrices L,P,U with rows pivoted

    """
    U[:,k:]=swap_rows(U[:,k:],k,max_index)
    P=swap_rows(P,k,max_index)
    L[:,:k]=swap_rows(L[:,:k],k,max_index)

    return L,P,U

def GE_step(L,U,k,j):
    # This function performs the Gaussian
    # Elimination step for row j and column k

    L[j,k]=U[j,k]/U[k,k]
    U[j, k: ]=U[j,k:]-L[j,k]*U  [k,k:]
    return L,U

def LU_factorize(A):
    """

    Parameters
    ----------
    A : TYPE
        DESCRIPTION.

    Returns
    -------
    L,U,P : 2D Numpy arrays which satisfy LU=PA and are obtained
            using Gaussian Elimination with partial pivoting

    """
    n=A.shape[0]
    A=A.astype(float)
    L=np.identity(n)
    P=np.identity(n)
    U=A.copy()
    pivots=[]

    for k in range(n):
        max_index = k + np.argmax(np.abs(U[k:, k]))

        if U[max_index,k]!=0:
            pivots.append(U[max_index,k])

        else:
            return ("The matrix is singular and the rank is at least {}"
                    .format(len(pivots)))

        if max_index != k:
              L,P,U=partial_pivot(L,P,U,k,max_index)

        for j in range(k+1,n):
           L,U=GE_step(L,U,k,j)
    return L,U,P

def substitution(L,U,P,b):
    """

    Parameters
    ----------
    L : 2D Numpy Array
        A lower triangular Matrix.
    U : 2D Numpy Array
        .
    P : 2D Numpy Array
        A permutation Matrix
    b : 1D Numpy Array
        A vector which satisfies the relation LUx=Pb

    Returns
    -------
    x_ : 1D Numpy Array
        Returns the vector x_ for which LUx_=Pb is true

    """
    n=len(b)
    # Solving PLU=PB
    b_=np.matmul(P,b)
    #Solve Ly=Pb_ using forward substitution
    # Get y=y_
    y_=np.zeros(n)

    for i in range(len(y_)):
        if i==0:
            y_[i]=b_[0]
        else:
           y_[i]=(b_[i]-np.matmul(L[i,:i],y_[:i]))/(L[i,i])

    #Solve Ux=y_ using backward substitution
    # Get x=x_
    x_=np.zeros(n)
    for j in range(n-1,-1,-1):
        if j==n-1:
            x_[j]=y_[j]/U[j,j]
        else:
            x_[j]=(y_[j]-np.matmul(U[j,j+1:],x_[j+1:]))/U[j,j]

    return x_

def p_piv(p):
    """

    Parameters
    ----------
    p : 2D Numpy array
        Permutation Matrix

    Returns
    -------
    piv : 1D Numpy array
        Pivot indices representing the permutation
        matrix P: row i of matrix was
        interchanged with row piv[i].

    """
    n=p.shape[0]
    piv=np.zeros(n)
    for col in range(n):
       i= np.argmax(np.abs(p[:,col]))
       piv[col]=i

    return piv

n=10
A=np.random.rand(n,n)
b=np.random.rand(n)

L,U,P=LU_factorize(A)

my_PA_LU_norms=np.linalg.norm(P@A-np.matmul(L,U))

print(my_PA_LU_norms)


"""
General Numerical Solver for the 1D Time-Dependent Schrodinger Equation.

Authors:
- Jake Vanderplas <vanderplas@astro.washington.edu>
- Andre Xuereb (imaginary time propagation, normalized wavefunction

For a theoretical description of the algorithm, please see
http://jakevdp.github.com/blog/2012/09/05/quantum-python/

License: BSD style
Please feel free to use and modify this, but keep the above information.
"""
import numpy as np
from scipy import fftpack
import matplotlib.pyplot as plt
from matplotlib import animation
import seaborn as sns
sns.set()

class Schrodinger(object):
    """
    Class which implements a numerical solution of the time-dependent
    Schrodinger equation for an arbitrary potential
    """
    def __init__(self, x, psi_x0, V_x, k0=None, hbar=1, m=1, t0=0.0):
        """
        Parameters
        ----------
        x : array_like, float
            Length-N array of evenly spaced spatial coordinates
        psi_x0 : array_like, complex
            Length-N array of the initial wave function at time t0
        V_x : array_like, float
            Length-N array giving the potential at each x
        k0 : float
            The minimum value of k.  Note that, because of the workings of the
            Fast Fourier Transform, the momentum wave-number will be defined
            in the range
              k0 < k < 2*pi / dx ,
            where dx = x[1]-x[0].  If you expect nonzero momentum outside this
            range, you must modify the inputs accordingly.  If not specified,
            k0 will be calculated such that the range is [-k0,k0]
        hbar : float
            Value of Planck's constant (default = 1)
        m : float
            Particle mass (default = 1)
        t0 : float
            Initial time (default = 0)
        """
        # Validation of array inputs
        self.x, psi_x0, self.V_x = map(np.asarray, (x, psi_x0, V_x))
        N = self.x.size
        assert self.x.shape == (N,)
        assert psi_x0.shape == (N,)
        assert self.V_x.shape == (N,)

        # Validate and set internal parameters
        assert hbar > 0
        assert m > 0
        self.hbar = hbar
        self.m = m
        self.t = t0
        self.dt_ = None
        self.N = len(x)
        self.dx = self.x[1] - self.x[0]
        self.dk = 2 * np.pi / (self.N * self.dx)

        # Set momentum scale
        if k0 == None:
            self.k0 = -0.5 * self.N * self.dk
        else:
            assert k0 < 0
            self.k0 = k0
        self.k = self.k0 + self.dk * np.arange(self.N)

        self.psi_x = psi_x0
        self.compute_k_from_x()

        # Variables which hold steps in evolution
        self.x_evolve_half = None
        self.x_evolve = None
        self.k_evolve = None

    def _set_psi_x(self, psi_x):
        assert psi_x.shape == self.x.shape
        self.psi_mod_x = (psi_x * np.exp(-1j * self.k[0] * self.x)
                          * self.dx / np.sqrt(2 * np.pi))
        self.psi_mod_x /= self.norm
        self.compute_k_from_x()

    def _get_psi_x(self):
        return (self.psi_mod_x * np.exp(1j * self.k[0] * self.x)
                * np.sqrt(2 * np.pi) / self.dx)

    def _set_psi_k(self, psi_k):
        assert psi_k.shape == self.x.shape
        self.psi_mod_k = psi_k * np.exp(1j * self.x[0] * self.dk
                                        * np.arange(self.N))
        self.compute_x_from_k()
        self.compute_k_from_x()

    def _get_psi_k(self):
        return self.psi_mod_k * np.exp(-1j * self.x[0] * self.dk
                                        * np.arange(self.N))

    def _get_dt(self):
        return self.dt_

    def _set_dt(self, dt):
        assert dt != 0
        if dt != self.dt_:
            self.dt_ = dt
            self.x_evolve_half = np.exp(-0.5 * 1j * self.V_x
                                         / self.hbar * self.dt)
            self.x_evolve = self.x_evolve_half * self.x_evolve_half
            self.k_evolve = np.exp(-0.5 * 1j * self.hbar / self.m
                                    * (self.k * self.k) * self.dt)

    def _get_norm(self):
        return self.wf_norm(self.psi_mod_x)

    psi_x = property(_get_psi_x, _set_psi_x)
    psi_k = property(_get_psi_k, _set_psi_k)
    norm = property(_get_norm)
    dt = property(_get_dt, _set_dt)

    def compute_k_from_x(self):
        self.psi_mod_k = fftpack.fft(self.psi_mod_x)

    def compute_x_from_k(self):
        self.psi_mod_x = fftpack.ifft(self.psi_mod_k)

    def wf_norm(self, wave_fn):
        """
        Returns the norm of a wave function.

        Parameters
        ----------
        wave_fn : array
            Length-N array of the wavefunction in the position representation
        """
        assert wave_fn.shape == self.x.shape
        return np.sqrt((abs(wave_fn) ** 2).sum() * 2 * np.pi / self.dx)

    def solve(self, dt, Nsteps=1, eps=1e-3, max_iter=1000):
        """
        Propagate the Schrodinger equation forward in imaginary
        time to find the ground state.

        Parameters
        ----------
        dt : float
            The small time interval over which to integrate
        Nsteps : float, optional
            The number of intervals to compute (default = 1)
        eps : float
            The criterion for convergence applied to the norm (default = 1e-3)
        max_iter : float
            Maximum number of iterations (default = 1000)
        """
        eps = abs(eps)
        assert eps > 0
        t0 = self.t
        old_psi = self.psi_x
        d_psi = 2 * eps
        num_iter = 0
        while (d_psi > eps) and (num_iter <= max_iter):
            num_iter += 1
            self.time_step(-1j * dt, Nsteps)
            d_psi = self.wf_norm(self.psi_x - old_psi)
            old_psi = 1. * self.psi_x
        self.t = t0

    def time_step(self, dt, Nsteps=1):
        """
        Perform a series of time-steps via the time-dependent Schrodinger
        Equation.

        Parameters
        ----------
        dt : float
            The small time interval over which to integrate
        Nsteps : float, optional
            The number of intervals to compute.  The total change in time at
            the end of this method will be dt * Nsteps (default = 1)
        """
        assert Nsteps >= 0
        self.dt = dt
        if Nsteps > 0:
            self.psi_mod_x *= self.x_evolve_half
            for num_iter in range(Nsteps - 1):
                self.compute_k_from_x()
                self.psi_mod_k *= self.k_evolve
                self.compute_x_from_k()
                self.psi_mod_x *= self.x_evolve
            self.compute_k_from_x()
            self.psi_mod_k *= self.k_evolve
            self.compute_x_from_k()
            self.psi_mod_x *= self.x_evolve_half
            self.compute_k_from_x()
            self.psi_mod_x /= self.norm
            self.compute_k_from_x()
            self.t += dt * Nsteps

######################################################################
# Helper functions for gaussian wave-packets
def gauss_x(x, a, x0, k0):
    """
    a gaussian wave packet of width a, centered at x0, with momentum k0
    """
    return ((a * np.sqrt(np.pi)) ** (-0.5)
            * np.exp(-0.5 * ((x - x0) * 1. / a) ** 2 + 1j * x * k0))

def gauss_k(k, a, x0, k0):
    """
    analytical fourier transform of gauss_x(x), above
    """
    return ((a / np.sqrt(np.pi)) ** 0.5
            * np.exp(-0.5 * (a * (k - k0)) ** 2 - 1j * (k - k0) * x0))

######################################################################
# Utility functions for running the animation
def theta(x):
    """
    theta function :
      returns 0 if x<=0, and 1 if x>0
    """
    x = np.asarray(x)
    y = np.zeros(x.shape)
    y[x > 0] = 1.0
    return y

def square_barrier(x, width, height):
    return height * (theta(x) - theta(x - width))

######################################################################
# Create the animation

# specify time steps and duration
dt = 0.01
N_steps = 50
t_max = 120
frames = int(t_max / float(N_steps * dt))

# specify constants
hbar = 1.0   # planck's constant
m = 1.9      # particle mass

# specify range in x coordinate
N = 2 ** 11
dx = 0.1
x = dx * (np.arange(N) - 0.5 * N)

# specify potential
V0 = 1.5
L = hbar / np.sqrt(2 * m * V0)
a = 3 * L
x0 = -60 * L
V_x = square_barrier(x, a, V0)
V_x[x < -98] = 1E6
V_x[x > 98] = 1E6

# specify initial momentum and quantities derived from it
p0 = np.sqrt(2 * m * 0.2 * V0)
dp2 = p0 * p0 * 1. / 80
d = hbar / np.sqrt(2 * dp2)

k0 = p0 / hbar
v0 = p0 / m
psi_x0 = gauss_x(x, d, x0, k0)

# define the Schrodinger object which performs the calculations
S = Schrodinger(x=x,
                psi_x0=psi_x0,
                V_x=V_x,
                hbar=hbar,
                m=m,
                k0=-28)

######################################################################
# Set up plot
fig = plt.figure('Quantum Tunneling')

# plotting limits
xlim = (-100, 100)
klim = (-5, 5)

# top axes show the x-space data
ymin = 0
ymax = V0
ax1 = fig.add_subplot(211, xlim=xlim,
                      ylim=(ymin - 0.2 * (ymax - ymin),
                            ymax + 0.2 * (ymax - ymin)))
psi_x_line, = ax1.plot([], [], c='r', label=r'$|\psi(x)|$')
V_x_line, = ax1.plot([], [], c='k', label=r'$V(x)$')
center_line = ax1.axvline(0, c='k', ls=':', label=r"$x_0 + v_0t$")

title = ax1.set_title("")
ax1.legend(prop=dict(size=12))
ax1.set_xlabel('$x$')
ax1.set_ylabel(r'$|\psi(x)|$')

# bottom axes show the k-space data
ymin = abs(S.psi_k).min()
ymax = abs(S.psi_k).max()
ax2 = fig.add_subplot(212, xlim=klim,
                      ylim=(ymin - 0.2 * (ymax - ymin),
                            ymax + 0.2 * (ymax - ymin)))
psi_k_line, = ax2.plot([], [], c='r', label=r'$|\psi(k)|$')

p0_line1 = ax2.axvline(-p0 / hbar, c='k', ls=':', label=r'$\pm p_0$')
p0_line2 = ax2.axvline(p0 / hbar, c='k', ls=':')
mV_line = ax2.axvline(np.sqrt(2 * V0) / hbar, c='k', ls='--',
                      label=r'$\sqrt{2mV_0}$')
ax2.legend(prop=dict(size=12))
ax2.set_xlabel('$k$')
ax2.set_ylabel(r'$|\psi(k)|$')

V_x_line.set_data(S.x, S.V_x)

######################################################################
# Functions to Animate the plot
def init():
    psi_x_line.set_data([], [])
    V_x_line.set_data([], [])
    center_line.set_data([], [])

    psi_k_line.set_data([], [])
    title.set_text("")
    return (psi_x_line, V_x_line, center_line, psi_k_line, title)

def animate(i):
    S.time_step(dt, N_steps)
    psi_x_line.set_data(S.x, 4 * abs(S.psi_x))
    V_x_line.set_data(S.x, S.V_x)
    center_line.set_data(2 * [x0 + S.t * p0 / m], [0, 1])

    psi_k_line.set_data(S.k, abs(S.psi_k))
    return (psi_x_line, V_x_line, center_line, psi_k_line, title)

# call the animator.
# blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=frames, interval=30, blit=True)

# uncomment the following line to save the video in mp4 format.  This
# requires either mencoder or ffmpeg to be installed on your system
# anim.save('schrodinger_barrier.mp4', fps=15,
#          extra_args=['-vcodec', 'libx264'])
plt.tight_layout()
plt.show()


import pickle
from flask import Flask,request,app,jsonify,url_for,render_template
import nltk, re, string
from nltk.corpus import stopwords, twitter_samples
from sklearn.linear_model import LogisticRegression
import pickle
from sklearn.feature_extraction.text import CountVectorizer
from Utilities import process_tweet
from nltk.corpus import stopwords

app=Flask(__name__)

app.config['SECRET_KEY'] = 'mysecretkey'

logistic=pickle.load(open('model.pkl','rb'))
cv=pickle.load(open('cv.pkl','rb'))

def predict_sentiment(tweet):
    tweet = process_tweet(tweet)
    tweet = cv.transform([tweet])
    if logistic.predict(tweet) == 1:
        sentiment = 'Positive Sentiment'
    elif logistic.predict(tweet) == 0:
        sentiment = 'Negetive Sentiment'
    else:
        sentiment = 'Neutral Sentiment'
    return sentiment

@app.route('/',methods=['GET','POST'])
def index():

    return render_template('index.html')

@app.route('/prediction',methods=['GET','POST'])
def prediction():

    sentiment=predict_sentiment(request.form['tweet'])
    print(sentiment)
    return render_template('prediction.html', prediction_text="Your tweet is  of {}".format(sentiment))

if __name__=="__main__":
    app.run(debug=True)


import sys
input = lambda : sys.stdin.readline().strip()
N = int(input())

# # 480 -> 408 : 비트 연산으로 2의 배수 제거
# a = [i&1 for i in range(N+1)]
# a[1] = 0
# # 640 -> 480 : 원소 -> 원소 제곱근
# for i in range(3, int(N**0.5)+1, 2):
#     if a[i]:
#         # 408 -> 392 : i의 2 배수부터 탐색 -> i의 제곱부터 탐색
#         for j in range(i*i, N+1, i):
#             a[j] = 0

# sosu_list = [2]
# for i in range(N+1):
#     if a[i] == True:
#         sosu_list.append(i)

# answer, temp, e = 0, 0, 0
# for i in range(len(sosu_list)):
#     while temp<N and e<len(sosu_list):
#         # 1600 -> 772 : sum -> 원소 누적 합
#         temp += sosu_list[e]
#         e += 1
#     if temp==N:
#         answer += 1
#     # 772 -> 640 : temp 다시 계산 -> 투포인터
#     temp -= sosu_list[i]

# 408 -> 208 : 비트마스킹
a = [255 for _ in range(N//8 +1)]

def is_prime(n):
    return True if a[n>>3] & (1<<(n&7)) else False

def set_composite(n):
    a[n>>3] &= ~(1 << (n&7))

set_composite(0)
set_composite(1)

for i in range(2, int(N**(1/2))+1):
    if is_prime(i):
        for j in range(i*i, N+1, i):
            set_composite(j)

sosu_list = list()
for i,sosu in enumerate(a):
    for j in range(8):
        if sosu & (1 << j) and i*8+j <= N:
            sosu_list.append(i*8+j)

answer, temp, e = 0, 0, 0
for i in range(len(sosu_list)):
    while temp<N and e<len(sosu_list):
        temp += sosu_list[e]
        e += 1
    if temp==N:
        answer += 1
    temp -= sosu_list[i]

print(answer)

5월_4주/BOJ_소수의연속합/BOJ_소수의연속합_염성현.py

BOJ_소수의연속합_염성현.py


from __future__ import unicode_literals

import urllib

from vigilo.vigiconf.lib.confclasses.validators import arg, String, List
from vigilo.vigiconf.lib.confclasses.test import Test
from vigilo.common.gettext import l_

class NagiosPlugin(Test):
    """Test générique pour utiliser un plugin Nagios externe"""

    @arg(
        'name', String,
        l_('Display name'),
        l_("""
            Name to display in the GUI.

            This setting also controls the name of the service
            created in Nagios (service_description).
        """)
    )
    @arg(
        'command', String,
        l_('Command'),
        l_("Command to execute to call the plugin (check_command)")
    )
    @arg(
        'metrics', List(types=String),
        l_('Metrics'),
        l_("List of metrics returned by the plugin that should be graphed")
    )
    @arg(
        'unit', String,
        l_('Unit'),
        l_("Unit used by the plugin's metrics")
    )
    def add_test(self, name, command, metrics=(), unit=''):
        # Service
        self.add_external_sup_service(name, command)

        # Métrologie
        if not metrics:
            return

        rrd_metrics = []
        for metric in metrics:
            # On construit un nom unique pour le fichier RRD
            # qui stockera les données de performance,
            # sur le modèle "NagiosPlugin-<service URL-encodé>@<métrique>"
            # et le nom du service pour rendre le nom du fichier unique.
            rrd = "NagiosPlugin-%s@%s" % (urllib.quote_plus(name), metric)
            self.add_perfdata_handler(name, rrd, metric, metric,
                                      rra_template='discrete')
            rrd_metrics.append(rrd)

        # Un graphe est automatiquement créé avec toutes les métriques.
        self.add_graph("Plugin-%s" % name, rrd_metrics, 'lines', unit)

# vim:set expandtab tabstop=4 shiftwidth=4:


import numpy
import matplotlib.pyplot as plt
import  pylab
import dcf
import utility as util
import logistic_regression as lr
import svm
from tqdm import tqdm
from copy import deepcopy
from preprocessing import preprocess_Z_score
import matplotlib

# ======================================== FEATURES plots ==========================================
def plot_features_distr(D, labels, features, gau=False):
    n_features = len(features)
    _gau = "gau-" if gau else ""
    males = D[:, labels == 0]
    females = D[:, labels == 1]
    bins = 30

    for feature in range(n_features):
        plt.Figure()
        plt.xlabel(features[feature])

        dataset_m = males[feature, :]
        dataset_f = females[feature, :]

        plt.hist(dataset_m, bins=bins, density=True, label='male', alpha=0.4)
        plt.hist(dataset_f, bins=bins, density=True, label='female', alpha=0.4)

        plt.legend()
        plt.savefig(f"./plots/features/{_gau}/{features[feature]}.png", format="png")
        plt.show()

def plot_relation_beetween_feautures(D, labels, features):
    n_features = len(features)

    males = D[:, labels == 0]
    females = D[:, labels == 1]

    for featureA in range(n_features):
        for featureB in range(featureA, n_features):
            if featureA == featureB:
                continue
            plt.figure()
            plt.xlabel(labels[featureA])
            plt.ylabel(labels[featureB])

            plt.scatter(males[featureA, :], males[featureB, :], label='Male', alpha=0.4)
            plt.scatter(females[featureA, :], males[featureB, :], label='Female', alpha=0.4)

            plt.legend()
            plt.show()

# ============================================ CORRELATION between features plots ======================================================
def pearson_coeff(x, y):
    """
    Given two arrays evaluate the Pearson coefficient
    Parameters
    ---------
    x: numpy.array
        first array
    y: numpy.array
        second array
    """
    cov = numpy.cov(x, y)[0][1]

    x_var = numpy.var(x)
    y_var = numpy.var(y)

    return numpy.abs(cov / (numpy.sqrt(x_var) * numpy.sqrt(y_var)))

def plot_heatmap(D, features, color):
    """
    Plot the heatmap of a given dataset. This heat map will show the pearson coefficient between all the feauters.
    Parameters
    ---------
    D: dataset
    color: an optional value with the color of the heatmap
    """
    n_features = len(features)
    coeffs = numpy.zeros((n_features, n_features))

    # evaluate the person coefficient for each feature
    for i in range(n_features):
        for j in range(n_features):
            coeffs[i][j] = pearson_coeff(D[i, :], D[j, :])

    # plot the heat map
    fig, ax = plt.subplots()
    im = ax.imshow(coeffs, interpolation='nearest', cmap=color)
    plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")
    # Loop over data dimensions and create text annotations.
    for i in range(len(coeffs)):
        for j in range(len(coeffs)):
            text = ax.text(j, i, numpy.around(coeffs[i, j],2),
                        ha="center", va="center", color="w")
    ax.set_title("Heat map")
    fig.tight_layout()
    plt.show()

# ================================================= MIN DCFs Plots ============================================================================
def compare_min_DCF_logreg(DTR, DTE, LTR, LTE, applications, quadratic=False, preprocessing=False, weighted=False):
    lambdas = [1e-6, 2e-6, 5e-6, 1e-5, 2e-5, 5e-5, 1e-4, 2e-4, 5e-4, 1e-3, 2e-3, 5e-3, 8e-3, 1e-2, 2e-2, 5e-2, 1e-1, 0.3, 0.5, 1, 5, 10, 50, 100]
    app_labels = ['minDCF(pi=0.5)', 'minDCF(pi=0.1)', 'minDCF(pi=0.9)']
    quadratic_ = 'quadratic' if quadratic else 'linear'
    colors = ['b', 'r', 'g']
    params = {
        'weighted' : weighted
    }

    max_y = 0
    DCFs_dict = dict()

    file_prefix = lr.compute_filename_prefix(quadratic, preprocessing, weighted)
    train_minDCFs, train_lambdas = lr.load_results(file_prefix)
    PATH = f"./plots/LogReg/experimental/{file_prefix}-minDCF.png"

    for i, application in enumerate(applications):
        pi, Cfn, Cfp = application
        params['priors'] = [pi, 1-pi]

        DCFs = lr.compute_minDCF_for_lambda(DTR, DTE, LTR, LTE, application, lambdas, quadratic, params)
        DCFs_dict[application] = DCFs
        max_y = max(max_y, numpy.amax(numpy.hstack((train_minDCFs[application], DCFs))))

        plt.plot(train_lambdas, train_minDCFs[application], color=colors[i], label=f"{app_labels[i]} [Val]", linestyle='dashed')
        plt.plot(lambdas, DCFs, color=colors[i], label=f"{app_labels[i]} [Eval]")

    plt.ylim(0, max_y + 0.05)
    plt.xscale('log')
    plt.title(f"DCF {quadratic_} logistic regression")
    plt.xlabel('lambda')
    plt.ylabel('DCF')
    plt.legend()
    plt.savefig(PATH, format='png')
    plt.show()
    return lambdas, DCFs_dict

def plot_min_DCF_logreg(folds, folds_labels, k, applications, quadratic=False, preprocessing=False, weighted=False):
    lambdas = [1e-6, 2e-6, 5e-6, 1e-5, 2e-5, 5e-5, 1e-4, 2e-4, 5e-4, 1e-3, 2e-3, 5e-3, 8e-3, 1e-2, 2e-2, 5e-2, 1e-1, 0.3, 0.5, 1, 5, 10, 50, 100]
    #lambdas = [1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 5e-2, 1e-1, 0.3, 0.5, 1, 5, 10]
    app_labels = ['minDCF(pi=0.5)', 'minDCF(pi=0.1)', 'minDCF(pi=0.9)']
    colors = ['b', 'r', 'g']
    max_y = 0

    quadratic_ = "quadratic" if quadratic else "linear"

    file_prefix = lr.compute_filename_prefix(quadratic, preprocessing, weighted)
    PATH = f"./plots/LogReg/{file_prefix}-minDCF.png"

    DCFs_dict = {}

    max_y = 0
    for i, application in enumerate(applications):
        DCFs = []
        pi, Cfn, Cfp = application
        classPriors = [pi, 1-pi]
        for l in tqdm(lambdas):
            if not quadratic:
                STE = util.k_folds(folds, folds_labels, k, lr.logreg, priors=classPriors, lambda_=l, preprocessing=preprocessing, weighted=weighted)
            else:
                STE = util.k_folds(folds, folds_labels, k, lr.quadratic_logreg, priors=classPriors, lambda_=l, preprocessing=preprocessing, weighted=weighted)
            scores = numpy.hstack(STE)
            DCF = dcf.compute_min_DCF(scores, numpy.hstack(folds_labels), pi, Cfn, Cfp)
            max_y = max(max_y, DCF)
            DCFs.append(DCF)
            DCFs_dict[application] = DCFs
        plt.plot(lambdas, DCFs, color=colors[i], label=app_labels[i])

    plt.ylim(0, max_y+0.1)
    plt.xscale('log')
    plt.title(f"DCF {quadratic_} logistic regression")
    plt.xlabel('lambda')
    plt.ylabel('DCF')
    plt.legend()
    plt.savefig(PATH, format='png')
    plt.show()
    return lambdas, DCFs_dict
# ================================================= MIN DCFs SVM Plots ============================================================================
def compare_min_DCF_svm(DTR, DTE, LTR, LTE, kernel:str, evaluation_points: tuple, balanced: bool, preprocessing: bool):
    #plot features
    #Cs = [0.005, 0.02,0.05, 0.10, 0.20, 0.30, 0.5, 0.8, 1, 5, 10, 20, 50]
    Cs = [0.005, 0.05, 0.1, 0.5, 1, 5]

    colors = ['b', 'r', 'g']
    app_labels = ['minDCF(pi=0.5)', 'minDCF(pi=0.1)', 'minDCF(pi=0.9)'] if kernel != 'rbf' else ['log(\u03BB)=-1', 'log(\u03BB)=-2', 'log(\u03BB)=-3']
    balanced_ = "balanced" if balanced else "not balanced"

    file_prefix = svm.compute_filename_prefix(balanced, preprocessing)
    train_minDCFs, train_Cs = svm.load_results(file_prefix, kernel)
    PATH = f"./plots/SVM/experimental/{kernel}-{file_prefix}-minDCF.png"

    max_y = 0
    minDCFs_dict = dict()

    for i, ep in enumerate(evaluation_points):
        DCFs = []
        if kernel == 'linear':
            pi, Cfn, Cfp = ep
            params = util.build_params(priors=[pi, 1-pi], balanced=balanced, kernel=kernel)
        elif kernel == 'poly':
            pi, Cfn, Cfp = ep
            params = util.build_params(priors=[pi, 1-pi], balanced=balanced, kernel=kernel, d=2, c=1,)
        elif kernel == 'rbf':
            params = util.build_params(priors=[0.5, 0.5], balanced=balanced, kernel=kernel, gamma=ep)

        minDCFs = svm.compute_minDCF_for_parameter(DTR, DTE, LTR, LTE, ep, Cs, params)
        minDCFs_dict[ep] = minDCFs
        max_y = max(max_y, numpy.amax(numpy.hstack((train_minDCFs[ep], minDCFs))))

        minDCFs = numpy.array(minDCFs).ravel()
        plt.plot(Cs, minDCFs, color=colors[i], label=f"{app_labels[i]} [Eval]")
        train_minDCF = numpy.array(train_minDCFs[ep]).ravel()
        plt.plot(train_Cs, train_minDCF, color=colors[i], label=f"{app_labels[i]} [Val]", linestyle='dashed' )

    plt.ylim(0, max_y+0.05)
    plt.title(f"minDCF for {kernel} SVM ({balanced_})")
    plt.xscale('log')
    plt.xlabel('C')
    plt.ylabel('DCF')
    plt.legend()
    plt.savefig(PATH, format="png")
    plt.show()
    return Cs, minDCFs_dict

def plot_min_DCF_svm(folds, folds_labels, k, applications, balanced=False, preprocessing=None):

    balanced_ = "balanced" if balanced else "not balanced"
    preprocessing_ = preprocessing if preprocessing else "raw"

    PATH = f"./plots/SVM/{preprocessing_}-linear-{balanced_}-minDCF.png"

    Cs = [0.005, 0.02,0.05, 0.10, 0.20, 0.30, 0.5, 0.8, 1, 5, 10, 20, 50]
    colors = ['b', 'r', 'g']
    app_labels = ['minDCF(pi=0.5)', 'minDCF(pi=0.1)', 'minDCF(pi=0.9)']
    minDCFs_dict = {}

    max_y = 0

    for i, application in enumerate(applications):
        DCFs = []
        pi, Cfn, Cfp = application
        classPriors = [pi, 1-pi]
        for C in tqdm(Cs):
            scores = util.k_folds(folds, folds_labels, k, svm.train_SVM_linear,SVM=True, C = C, balanced=balanced, preprocessing=preprocessing)
            scores = numpy.hstack(scores)
            minDCF = dcf.compute_min_DCF(scores, numpy.hstack(folds_labels), pi, Cfn, Cfp)
            DCFs.append(minDCF)
        DCFs = numpy.array(DCFs)
        minDCFs_dict[application] = DCFs.ravel()
        plt.plot(Cs, DCFs.ravel(), color=colors[i], label=app_labels[i])

    plt.ylim(0, 1)
    plt.title(f"minDCF for linear SVM ({balanced_})")
    plt.xscale('log')
    plt.xlabel('C')
    plt.ylabel('DCF')
    plt.legend()
    plt.savefig(PATH, format="png")
    plt.show()
    return Cs, minDCFs_dict

def plot_min_DCF_poly_svm(folds, folds_labels, k, applications, degree=2.0, balanced=False, preprocessing=None):
    balanced_ = "balanced" if balanced else "not balanced"
    preprocessing_ = "z-norm" if preprocessing else "raw"
    PATH = f"./plots/SVM/{preprocessing_}-poly{int(degree)}-{balanced_}-minDCF.png"
    Cs = [0.005, 0.05, 0.1, 0.5, 1, 5]
    colors = ['b', 'r', 'g']
    app_labels = ['minDCF(pi=0.5)', 'minDCF(pi=0.1)', 'minDCF(pi=0.9)']
    minDCFs_dict = {}
    for i, application in enumerate(applications):
        DCFs = []
        pi, Cfn, Cfp = application
        classPriors = [pi, 1-pi]
        for C in tqdm(Cs):
            scores = util.k_folds(folds, folds_labels, k, svm.train_non_linear_SVM,  SVM=True, kernel='poly', C=C, d=degree, c=1, balanced=balanced, preprocessing=preprocessing)
            scores = numpy.hstack(scores)
            minDCF = dcf.compute_min_DCF(scores, numpy.hstack(folds_labels), pi, Cfn, Cfp)
            DCFs.append(minDCF)
        DCFs = numpy.array(DCFs)
        minDCFs_dict[application] = DCFs.ravel()
        plt.ylim(0, 1)
        plt.title(f"DCF for Poly(d={int(degree)}) SVM ({balanced_})")
        plt.xscale('log')
        plt.xlabel('C')
        plt.ylabel('DCF')
        plt.plot(Cs, DCFs.ravel(), color=colors[i], label=app_labels[i])
        plt.legend()
    plt.savefig(PATH, format="png")
    plt.show()
    return Cs, minDCFs_dict

def plot_min_DCF_RBFsvm(folds, folds_labels, k, gammas, balanced=False, preprocessing=False):
    balanced_ = "balanced" if balanced else "not-balanced"
    preprocessing_ = "z-norm" if preprocessing else "raw"
    PATH = f"./plots/SVM/{preprocessing_}-RBF-{balanced_}-minDCF.png"
    Cs = [0.005, 0.01,0.02,0.05, 0.08, 0.10, 0.20, 0.30, 0.5, 0.8, 1, 3, 5, 10, 20, 50]
    colors = ['b', 'r', 'g']
    app_labels = ['log(\u03B3)=-1', 'log(\u03B3)=-2', 'log(\u03B3)=-3']

    minDCFs_dict = {}

    for i,gamma in enumerate(gammas):
        DCFs = []
        pi, Cfn, Cfp = (0.5, 1, 1)
        classPriors = [pi, 1-pi]
        for C in tqdm(Cs):
            scores = util.k_folds(folds, folds_labels, k, svm.train_non_linear_SVM, SVM=True, kernel='rbf', gamma=gamma, C=C, balanced=balanced, preprocessing=preprocessing)
            scores = numpy.hstack(scores)
            minDCF = dcf.compute_min_DCF(scores, numpy.hstack(folds_labels), pi, Cfn, Cfp)
            DCFs.append(minDCF)
        DCFs = numpy.array(DCFs)
        minDCFs_dict[gamma] = DCFs.ravel()
        plt.ylim(0, 1)
        plt.title("DCF for RBF kernel SVM")
        plt.xscale('log')
        plt.xlabel('C')
        plt.ylabel('DCF')
        plt.plot(Cs, DCFs.ravel(), color=colors[i], label=app_labels[i])
        plt.legend()
    plt.savefig(PATH, format="png")
    plt.show()

    return Cs, minDCFs_dict
# ================================================= MIN DCFs GMM Plots ============================================================================

def plot_minDCF_GMM_hist(DCFs_list: list, G: int, labels: list, filename='plot', experimental= False, title="", colors=['lightsalmon', 'orangered', 'gold', 'orange']):
    x_labels = list(map(lambda val:2**val, range(G)))
    x = numpy.arange(len(x_labels))
    width = 0.18
    _experimental = "experimental/" if experimental else ""
    path = f"./plots/GMM/{_experimental}{filename}.png"

    n_hists = len(DCFs_list)
    offsets = list( range(-int(n_hists/2) - 1, int(n_hists/2) + 2, 2))
    print("n_hist:", n_hists, "offsets", offsets)

    fig, ax = plt.subplots()
    for DCFs, offset, label, color in zip(DCFs_list, offsets, labels, colors):
        ax.bar(x + offset*width/2, DCFs, width, label=label, color=color)

    ax.set_ylabel('DCF')
    ax.set_xticks(x, x_labels)
    ax.legend()
    ax.set_title(title)
    fig.tight_layout()
    plt.savefig(path, format='png')

    plt.show()

# ================================================================ DET Plot ===================================================================
def plot_DET(llrs:list, L: numpy.array, plot_labels:list, colors: list =['r', 'b', 'm', 'g', 'y'], save_figure:bool = True, training:bool = True, multiple_labels: bool = False):
    training_ = "training" if training else "experimental"
    models = "-".join(plot_labels)
    PATH = f"./plots/evaluation/{training_}/DET_{models}.png"

    fig,ax = plt.subplots()

    if not multiple_labels:
        for llr, plot_label, color in zip(llrs, plot_labels, colors):
            print(plot_label)
            DET_points_FNR, DET_points_FPR = compute_DET_points(llr, L)
            ax.plot(DET_points_FNR, DET_points_FPR, color=color, label=plot_label)
    else:
        for llr, lbl, plot_label, color in zip(llrs, L, plot_labels, colors):
            DET_points_FNR, DET_points_FPR = compute_DET_points(llr, lbl)
            ax.plot(DET_points_FNR, DET_points_FPR, color=color, label=plot_label)
    ax.set_xlabel("FPR")
    ax.set_ylabel("FNR")

    ax.set_xscale('log')
    ax.set_yscale('log')

    ax.legend()
    if save_figure:
        plt.savefig(PATH, format='png')
    plt.show()

def compute_DET_points(llr, L):
    tresholds = numpy.concatenate([numpy.array([-numpy.inf]),numpy.sort(llr),numpy.array([numpy.inf])])
    N_label0 = (L == 0).sum()
    N_label1 = (L == 1).sum()
    DET_points_FNR = numpy.zeros(L.shape[0] +2 )
    DET_points_FPR = numpy.zeros(L.shape[0] +2 )
    for (idx,t) in enumerate(tresholds):
        pred = 1 * (llr > t)
        FNR = 1 - (numpy.bitwise_and(pred == 1, L == 1 ).sum() / N_label1)
        FPR = numpy.bitwise_and(pred == 1, L == 0).sum() / N_label0
        DET_points_FNR[idx] = FNR
        DET_points_FPR[idx] = FPR
    return DET_points_FNR, DET_points_FPR
# =============================================== ROC Plots ==================================================
def plot_ROC(llrs: list, labels: list, plot_labels: list, save_figure:bool = True, training:bool = True):
    training_ = "training" if training else "experimental"
    models = "-".join(plot_labels)
    PATH = f"./plots/evaluation/{training_}/ROC_{models}.png"

    for llr, plot_label in zip(llrs, plot_labels):
        ROC_points_TPR, ROC_points_FPR = compute_ROC_points(llr, labels)
        plt.plot(ROC_points_FPR, ROC_points_TPR, label=plot_label)

    plt.xlabel("FPR")
    plt.ylabel("TPR")
    plt.legend()
    plt.grid()

    if save_figure:
        plt.savefig(PATH, format='png')

    plt.show()

def compute_ROC_points(llr, L):
    tresholds = numpy.concatenate([numpy.array([-numpy.inf]),numpy.sort(llr),numpy.array([numpy.inf])])
    N_label0 = (L == 0).sum()
    N_label1 = (L == 1).sum()
    ROC_points_TPR = numpy.zeros(L.shape[0] +2 )
    ROC_points_FPR = numpy.zeros(L.shape[0] +2 )
    for (idx,t) in enumerate(tresholds):
        pred = 1 * (llr > t)
        TPR = numpy.bitwise_and(pred == 1, L == 1 ).sum() / N_label1
        FPR = numpy.bitwise_and(pred == 1, L == 0).sum() / N_label0
        ROC_points_TPR[idx] = TPR
        ROC_points_FPR[idx] = FPR
    return ROC_points_TPR, ROC_points_FPR

# =========================================================== Bayes Error Plot =============================================================
def bayes_error_plot(llrs: list, labels: list, plot_labels: list, log_regs: list, n_points:int = 100, colors: list = ['r', 'b', 'g', 'm', 'y'], save_figure: bool = True, training:bool = True, calibrated: bool = False, multiple_labels:bool = False):
    training_ = "training" if training else "experimental"
    models = "-".join(plot_labels)
    calibrated_ = "-calibrated" if calibrated else ""
    PATH = f"./plots/evaluation/{training_}/BEP_{models}{calibrated_}.png"

    max_y = 0
    if not multiple_labels:
        for llr, plot_label, log_reg, color in zip(llrs, plot_labels, log_regs, colors):
            p_array = numpy.linspace(-3, 3, n_points)
            minDCFs = dcf.bayes_error_points(p_array, llr, labels, True, log_reg)
            max_y = max(max_y, numpy.max(minDCFs))
            actDCFs = dcf.bayes_error_points(p_array, llr, labels, False, log_reg)
            max_y = max(max_y, numpy.max(actDCFs))
            plt.plot(p_array, minDCFs, label=f"{plot_label} minDCF", color=color, linestyle='dashed')
            plt.plot(p_array, actDCFs, label=f"{plot_label} actDCF", color=color)
    else:
        for llr, lbl, plot_label, log_reg, color in zip(llrs, labels, plot_labels, log_regs, colors):
            p_array = numpy.linspace(-3, 3, n_points)
            minDCFs = dcf.bayes_error_points(p_array, llr, lbl, True, log_reg)
            max_y = max(max_y, numpy.max(minDCFs))
            actDCFs = dcf.bayes_error_points(p_array, llr, lbl, False, log_reg)
            max_y = max(max_y, numpy.max(actDCFs))
            plt.plot(p_array, minDCFs, label=f"{plot_label} minDCF", color=color, linestyle='dashed')
            plt.plot(p_array, actDCFs, label=f"{plot_label} actDCF", color=color)

    title = "Bayes Error Plot"

    plt.yticks(numpy.arange(0, min(max_y+0.1, 1), 0.05))
    plt.title(title)
    plt.legend()

    if save_figure:
        plt.savefig(PATH, format='png')

    plt.show()


import math

class magicChecker:

    def __init__(self, square, order):
        self.square = square
        self.n = order
        self.mag_num = int(self.findMagicNumber())
        self.square_multi = {}

    def findMagicNumber(self):
        summ = (self.n/2.) * (math.pow(self.n,2) + 1)
        return summ

    def checkIfMultiMagic(self, power):
        ''' Construct New Square '''
        for x in self.square.keys():
            self.square_multi[x] = int(math.pow(self.square[x], power))

    def checkIfMagic(self):
        for i in range(1, self.n + 1):
            if self.checkRow(i):
                pass
            else:
                return False
        for j in range(1, self.n + 1):
            if self.checkCol(j):
                pass
            else:
                return False
        if self.checkDiag():
            pass
        else:
            return False
        return True

    def checkCol(self, k):
        sum_col = 0
        for i in range(1, self.n + 1):
            sum_col += self.square[i,k]
        if sum_col == self.mag_num:
            return True
        else:
            return False

    def checkRow(self, k):
        sum_row = 0
        for j in range(1, self.n + 1):
            sum_row += self.square[k,j]
        if sum_row == self.mag_num:
            return True
        else:
            return False

    def checkDiag(self):
        sum_diag_1 = 0
        sum_diag_2 = 0
        for k in range(1, self.n + 1):
            sum_diag_1 += self.square[k,k]
        for k in range(1, self.n + 1):
            sum_diag_2 += self.square[k, self.n+1-k]
        if sum_diag_1 == self.mag_num and sum_diag_2 == self.mag_num:
            return True
        else:
            return False

class magicCheckerMulti(magicChecker):

    def __init__(self, square, order, power):
        self.n = order
        self.mag_num = int(self.findMagicNumber())
        self.square = {}
        for x in square.keys():
            self.square[x] = int(math.pow(square[x], power))


import requests
from bs4 import BeautifulSoup
import re
from domains import CONTENT_AREA
from emoji import emojize
from urllib.parse import urlparse

# ChatGPT d2ee59b7-b368-4a5f-b3af-2e33b7f33b4a
example_url = [
    "https://backlinko.com/actionable-seo-tips",
    "https://www.semrush.com/blog/seo-tips/",
    "https://www.wordstream.com/blog/ws/2021/03/05/seo-strategy",
    "https://ahrefs.com/blog/seo-tips/",
    "https://backlinko.com/actionable-seo-tips",
    "https://developers.google.com/search/docs/fundamentals/seo-starter-guide",
    "https://www.pcmag.com/how-to/easy-but-powerful-seo-tips-to-boost-traffic-to-your-website",
    "https://www.searchenginejournal.com/seo-tips/374673/",
    "https://www.bdc.ca/en/articles-tools/marketing-sales-export/marketing/seo-small-businesses-10-ways-rank-higher",
]

def get_status_code(url):
    response = requests.get(url)
    return response.status_code

def get_domain(url):
    """Get the domain of a URL"""
    domain = url.split("//")[-1].split("/")[0].split(".")[0]
    return domain

def is_valid_url(url):
    """
    Check if the given URL is valid or not.

    Parameters:
    url (str): The URL to be checked.

    Returns:
    bool: True if the URL is valid, False otherwise.
    """
    regex = re.compile(
        r"^(https?://)?"  # http:// or https:// (optional)
        r"((([A-Z0-9][A-Z0-9-]{0,61}[A-Z0-9])|localhost)\.)+"  # domain...
        r"([A-Z]{2,6})"  # domain extension
        r"(:\d{1,5})?"  # optional port
        r"(\/.*)?$",
        re.IGNORECASE,
    )  # path (optional)
    return bool(regex.match(url))

def domain_disclaimer(url):
    """Display a disclaimer message if domain not defined in domains.py"""
    domain = get_domain(url)
    if domain not in CONTENT_AREA:
        return emojize(
            ":folded_hands:Content area is undefined, result may not be valid.",
            variant="emoji_type",
        )
    else:
        return emojize(
            ":thumbs_up: Good news! The content area has already been defined, the result should be more valid.",
            variant="emoji_type",
        )

def get_title(url):
    """Get the title of a webpage"""
    try:
        # Make request to webpage
        response = requests.get(url)

        # Parse webpage content using Beautiful Soup
        soup = BeautifulSoup(response.content, "html.parser")

        # Get title of webpage
        title = soup.title.string

        return title

    except:
        return "Unable to get title"

def get_description(url):
    """Get the description of a webpage"""
    try:
        # Make request to webpage
        response = requests.get(url)

        # Parse webpage content using Beautiful Soup
        soup = BeautifulSoup(response.content, "html.parser")

        # Get description from meta tags
        meta_tags = soup.find_all("meta")
        description = ""
        for tag in meta_tags:
            if tag.get("name", None) == "description":
                description = tag.get("content", None)

        return description

    except:
        return "Unable to get description"

def get_content(url):
    try:
        # Check if domain is registered
        parsed_url = urlparse(url)
        domain = (
            parsed_url.netloc.split(".")[-2]
            if parsed_url.netloc.count(".") >= 2
            else parsed_url.netloc
        )
        content_class = CONTENT_AREA.get(domain)

        if content_class:
            # Make request to webpage
            response = requests.get(url)

            # Parse webpage content using Beautiful Soup
            soup = BeautifulSoup(response.content, "html.parser")

            # Get content of webpage using class
            content = soup.find("div", class_=content_class)
            return content.get_text()
        else:
            # Make request to webpage
            response = requests.get(url)

            # Parse webpage content using Beautiful Soup
            soup = BeautifulSoup(response.content, "html.parser")

            # Get content of webpage using tag "body"
            content = soup.find("body")
            return content.get_text()

    except:
        return "Unable to get content"

def get_content_with_html(url):
    """Get the content of a webpage with HTML elements"""
    try:
        # Check if domain is registered
        domain = get_domain(url)
        content_class = CONTENT_AREA.get(domain)

        if content_class:
            # Make request to webpage
            response = requests.get(url)

            # Parse webpage content using Beautiful Soup
            soup = BeautifulSoup(response.content, "html.parser")

            # Get content of webpage using class
            content = soup.find("div", class_=content_class)
            return str(content)
        else:
            # Make request to webpage
            response = requests.get(url)

            # Parse webpage content using Beautiful Soup
            soup = BeautifulSoup(response.content, "html.parser")

            # Get content of webpage using tag "body"
            content = soup.find("body")
            return str(content)

    except:
        return "Unable to get content"

def get_h1(url):
    """Get the H1 of a webpage"""
    try:
        # Make request to webpage
        response = requests.get(url)

        # Parse webpage content using Beautiful Soup
        soup = BeautifulSoup(response.content, "html.parser")

        # Get H1 of webpage
        h1 = soup.find("h1").text if soup.find("h1") else None

        return h1
    except:
        return "Unable to get H1"

def get_headings(content_html):
    soup = BeautifulSoup(content_html, "html.parser")
    # Mencari semua elemen heading
    headings = soup.find_all(["h1", "h2", "h3"])
    # Inisialisasi list untuk menyimpan heading
    all_headings = []
    # Perulangan untuk setiap heading
    for heading in headings:
        # Menambahkan tag sesuai dengan tipe heading
        if heading.name == "h1":
            all_headings.append(f"<H1>{heading.text}")
        elif heading.name == "h2":
            all_headings.append(f"<H2>{heading.text}")
        elif heading.name == "h3":
            all_headings.append(f"<H3>{heading.text}")

    # Mengembalikan list heading
    return all_headings

def get_first_parapraph(content):
    soup = BeautifulSoup(content, "html.parser")
    first_pargraph = soup.find("p")

    if first_pargraph:
        return first_pargraph.text.strip()
    else:
        " "


import os
from skimage import io
import copy
import numpy as np
import random
from glob import glob
import json
from sklearn.preprocessing import MultiLabelBinarizer

import torch
import torch.utils.data as data
from torchvision import transforms, datasets
from src.datasets.root_paths import DATA_ROOTS

CLASSES = ['Sea and ocean',
            'Coniferous forest',
            'Mixed forest',
            'Moors and heathland',
            'Transitional woodland/shrub',
            'Sparsely vegetated areas',
            'Discontinuous urban fabric',
            'Non-irrigated arable land',
            'Pastures',
            'Complex cultivation patterns',
            'Broad-leaved forest',
            'Water bodies',
            'Land principally occupied by agriculture, with significant areas of natural vegetation',
            'Vineyards',
            'Agro-forestry areas',
            'Industrial or commercial units',
            'Airports',
            'Water courses',
            'Natural grassland',
            'Construction sites',
            'Sclerophyllous vegetation',
            'Peatbogs',
            'Rice fields',
            'Continuous urban fabric',
            'Olive groves',
            'Permanently irrigated land',
            'Mineral extraction sites',
            'Annual crops associated with permanent crops',
            'Dump sites',
            'Green urban areas',
            'Intertidal flats',
            'Bare rock',
            'Fruit trees and berry plantations',
            'Salt marshes',
            'Road and rail networks and associated land',
            'Estuaries',
            'Inland marshes',
            'Sport and leisure facilities',
            'Beaches, dunes, sands',
            'Coastal lagoons',
            'Salines',
            'Port areas',
            'Burnt areas']

class BaseBigEarthNet(data.Dataset):
    NUM_CLASSES = 43
    MULTI_LABEL = True
    NUM_CHANNELS = 12
    FILTER_SIZE = 120

    def __init__(
            self,
            root=DATA_ROOTS["bigearthnet"],
            train=True,
            image_transforms=None,
            seed=42,
        ):
        super().__init__()
        self.root = root
        self.train = train
        self.image_transforms = image_transforms

        self.rs = np.random.RandomState(seed)
        train_paths, test_paths, train_labels, test_labels = self.train_test_split()
        if train:
            self.paths = train_paths
            self.labels = train_labels
        else:
            self.paths = test_paths
            self.labels = test_labels
        self.targets = copy.deepcopy(self.labels)

    def train_test_split(self, train_frac=0.8):
        all_sample_paths = np.array(os.listdir(self.root))
        num_samples = len(all_sample_paths)
        labels = []
        for i in range(num_samples):
            sample_path = all_sample_paths[i]
            metadata_path = glob(os.path.join(self.root, sample_path, '*.json'))[0]
            class_names = set(json.load(open(metadata_path))['labels'])
            labels.append(class_names)

        encoder = MultiLabelBinarizer(classes=CLASSES, sparse_output=False)
        encoded_labels = encoder.fit_transform(labels)
        num_samples = len(all_sample_paths)
        indices = np.arange(num_samples)
        self.rs.shuffle(indices)
        train_indices = indices[:int(num_samples * train_frac)]
        test_indices = indices[int(num_samples * train_frac):]
        train_paths = all_sample_paths[train_indices]
        test_paths = all_sample_paths[test_indices]
        train_labels = encoded_labels[train_indices]
        test_labels = encoded_labels[test_indices]
        return train_paths, test_paths, train_labels, test_labels

    def __getitem__(self, index):
        path = self.paths[index]
        label = self.labels[index]
        img_paths = glob(os.path.join(self.root, path, '*.tif'))
        image = []
        for i, img_path in enumerate(img_paths):
            img = np.asarray(io.imread_collection(img_path), dtype=np.float32) # one of (1, 20, 20), (1, 60, 60), (1, 120, 120)
            resized_img = transforms.Resize(120)(torch.tensor(img))
            image.append(resized_img)
        image = torch.vstack(image)  # (12, 120, 120)
        if self.image_transforms:
            image = self.image_transforms(image)
        return image, label

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

class BigEarthNet(BaseBigEarthNet):

    def __init__(
            self,
            root=DATA_ROOTS["bigearthnet"],
            train=True,
            image_transforms=None,
        ):
        super().__init__()
        self.dataset = BaseBigEarthNet(
            root=root,
            train=train,
            image_transforms=image_transforms,
        )

    def __getitem__(self, index):
        img_data, label = self.dataset.__getitem__(index)
        img2_data, _ = self.dataset.__getitem__(index)
        data = [index, img_data.float(), img2_data.float(), label, label]
        return tuple(data)

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


from mcpi.minecraft import Minecraft as MC

root = MC.create()

my_id = root.getPlayerEntityId("Jooooook")
print("my_id: ", my_id)

my_pos = root.entity.getPos(my_id)
pos_x = {}
pos_z = {}
pos_y = {}

pos_x["Jooooook"] = my_pos.x
print(pos_x)


from flask import Flask, jsonify, request
import json
import os

app = Flask(__name__)

# Load data from JSON file if it exists
def load_data():
    if os.path.exists('investment_funds.json'):
        with open('investment_funds.json') as file:
            return json.load(file)
    else:
        with open('investment_funds.json', 'w') as file:
            json.dump([], file)
            return []

# create data to JSON file
def create_data(new_fund, investment_funds):
    max_id = 0
    with open('investment_funds.json') as file:
        data_file = json.load(file)
        print('file', data_file)
        for fund in data_file:
            print('fund', fund)
            fund_id = fund.get('id')
            if fund_id == max_id:
                max_id += 1
        new_fund['id'] = max_id
        print(new_fund)
    investment_funds.append(new_fund)
    save_data(investment_funds)

# save data to JSON file
def save_data(investment_funds):
    with open('investment_funds.json', 'w') as file:
        json.dump(investment_funds, file, indent=2)

# Load initial data
investment_funds = load_data()

# Endpoint to retrieve a list of all funds
@app.route('/funds', methods=['GET'])
def get_all_funds():
    return jsonify(investment_funds)

# Endpoint to create a new fund
@app.route('/funds', methods=['POST'])
def create_fund():
    data = request.get_json()
    new_fund = {
        'fund_id': data.get('fund_id'),
        'fund_name': data.get('fund_name'),
        'fund_manager': data.get('fund_manager'),
        'description': data.get('description'),
        'nav': data.get('nav'),
        'creation_date': data.get('creation_date'),
        'performance': data.get('performance')
    }
    create_data(new_fund, investment_funds)
    return jsonify(new_fund), 201

# Endpoint to retrieve details of a specific fund using its ID
@app.route('/funds/<int:fund_id>', methods=['GET'])
def get_fund_by_id(fund_id):
    # print('investment_funds', investment_funds)
    for fund in investment_funds:
        print('fund', fund)
        if fund['id'] == fund_id:
            return jsonify(fund)
    return jsonify({'error': 'fund not found'}), 404

# Endpoint to update the performance of a fund using its ID
@app.route('/funds/<int:fund_id>', methods=['PUT'])
def update_fund(fund_id):
    specific_fund = {}
    for fund in investment_funds:
        print('fund', fund)
        print(fund['id'] == fund_id, fund_id)
        if fund['id'] == fund_id:
            specific_fund = fund

    if specific_fund:
        print('true')
        data = request.get_json()
        specific_fund['performance'] = data.get('performance')
        save_data(investment_funds)
        return jsonify(specific_fund)
    return jsonify({'error': 'Fund not found'}), 404

# Endpoint to delete a fund using its ID
@app.route('/funds/<int:fund_id>', methods=['DELETE'])
def delete_fund(fund_id):
    deleted_fund = {}
    for fund in investment_funds:
        print('fund', fund)
        if fund['id'] == fund_id:
            deleted_fund = fund
            investment_funds.remove(fund)
            print('investment_funds', investment_funds)
            save_data(investment_funds)
            break

    return jsonify({'message': 'Fund deleted successfully', 'deleted_fund': deleted_fund})

if __name__ == '__main__':
    app.run(debug=True, port=5001)


def solution(clothes):
    answer = 1
    clothes_dict = {}

    for c in clothes:
        clothes_dict[c[1]] = clothes_dict.get(c[1],[])+[c[0]]

    for key in clothes_dict.keys():
        answer = answer * (len(clothes_dict[key]) + 1)
    return answer - 1

print(solution([["yellowhat", "headgear"], ["bluesunglasses", "eyewear"], ["green_turban", "headgear"]]))
print(solution([["crowmask", "face"], ["bluesunglasses", "face"], ["smoky_makeup", "face"]]))
print(solution([["a", "face"], ["b", "face"],
                ["c", "up"],["d", "up"],
                ["e", "down"],["f", "down"]]))

# 1 : a b
# 2 : c d
# 3 : e f

# a,b,c,d,e,f => 3C1 2C1
# ac/ad/ae/af/bc/bd/be/bf/ce/cf/de/df  => 3C2 2C1 2C1
# ace/acf/ade/aef/bce/bcf/bde/bdf => 3C3 2C1 2C1 2C1 = 8


from functools import wraps
from flask import request, abort, g

from app.models import User

def login_required(f):
    """ This decorator ensures that the current user is logged in before calling the actual view.
    """
    @wraps(f)
    def decorated(*args, **kwargs):
        if request.method != 'OPTIONS':
            token = request.headers.get('Authorization')
            if not token:
                abort(401)
            user = User.verify_auth_token(token)
            if not user:
                abort(401)
            g.user = user
        return f(*args, **kwargs)
    return decorated

def roles_required(*role_names):
    """ This decorator ensures that the current user has all of the specified roles.
    """
    def wrapper(func):
        @wraps(func)
        def decorated_view(*args, **kwargs):
            if request.method != 'OPTIONS':
                token = request.headers.get('Authorization')
                if not token:
                    abort(401)
                user = User.verify_auth_token(token)
                if not user:
                    abort(401)
                g.user = user

                # User must have the required roles
                if not user.has_roles(*role_names):
                    # Redirect to the unauthorized page
                    abort(403)

            # Call the actual view
            return func(*args, **kwargs)
        return decorated_view
    return wrapper


from django import forms
from django.core.exceptions import ValidationError

from manager.models import Accountancy
from manager.wallet_operations import wallet_choice, wallet_data_parse, change_wallet_balance

class AccountancyForm(forms.ModelForm):

    class Meta:
        model = Accountancy
        fields = ()

    def clean(self):
        amount = float(self.data["amount"])
        if amount < 0:
            raise ValidationError("Amount can't be negative.")

        wallet_type, previous_amount = wallet_data_parse(self.data)
        _, self.wallet_obj = wallet_choice(
            wallet_type,
            self.instance.card_id or self.instance.cash_id or self.instance.cryptocurrency_id
        )
        amount = amount - float(previous_amount) if previous_amount else 0

        self.wallet_obj = change_wallet_balance(
            self.instance.IO, self.wallet_obj, amount
        )

        return super().clean()

    def save(self, commit=True):
        accountancy = super(AccountancyForm, self).save(commit=False)
        self.clean()
        if commit:
            accountancy.amount = float(self.data["amount"])
            accountancy.save()
            self.wallet_obj.save()
        return super().save(commit)

class AccountancySearchForm(forms.Form):
    IO_type = forms.CharField(
        max_length=50,
        required=False,
        label="",
        widget=forms.TextInput(attrs={
            "placeholder": "Search by type ...",
            "class": "small_plate _comforta_bold text_shadow"
        })
    )