"""
IDP 3 Group 9 - Tidal Lagoon Mathematical Model
Module: Main Program
Gianluca Cantone 2019-2020

Program Modules

 1. Main_Model.py - This file, runs simulation on the system to calculate how fast lagoon drains/fills and how much power will be generated.
 2. 3D_Model - 3D model of the bay (with visuals) plus integration function across whole model, function integrate and plot graph at all height levels.
 3. Grid_Element_Integration.py - Single element integration stand alone program (functions copied into 3D_Model.py)
 3. Optimizer - Runs simulator iterativly looking for best configuration

"""

#Libraries ====================================================================
import math as m
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import logging

#Global Variables =============================================================

Global_Time = [0]
Global_Volume = [0]
Global_Tide = [0]
Global_Head = [0]
Global_Head_Difference = [0]
Global_Velocity = [0]
Global_Discharge = [0]
Profile_List = []
Global_Head_Loss = [0]
Global_Power = [0]
Global_Power_Elec = []

Civil_Price = 143400000      #Good
Blade_Price = 1500000        #Good
Turbine_Price = 2000000      #(Just guide vanes atm)
Shaft_Price = 200000         #Good
Gearbox_Price = 134352       #Good
Generator_Price = 250000     #Good
Electrical_Price = 473329    #Good
Sluice_Price = 200000        #Good

Startup_Cost = 0
Payback_Time = 0

#Efficiency terms:

Eff_Turbine = 0.8
Eff_Gearbox = 0.9
Eff_Generator = 0.97

#Main Program =================================================================

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
log = logging.getLogger()
log.setLevel(logging.WARNING)

print("\n")
print("======================================================================")
print("IDP 3 Group 9: Tidal Lagoon Mathematical Model and Simulation Software")
print("======================================================================")
print("This software simulates the performance of our tidal lagoon system under different configurations and operating conditions. Type help() to see a list of commands and how to use them")

def Run_Simulation(**kwargs):

    #Parameters passed:

    Step_Size = kwargs["step"]
    Tidal_Function = kwargs["tidal_function"]
    Turbines = kwargs["turbines"]
    Turbine_Diameter = kwargs["diameter"]
    Sluices = kwargs["slucies"]
    Sluice_Size = kwargs["sluice_size"]
    Profile_Number = kwargs["profile"]
    Run_Time = kwargs["time"]
    Econ = kwargs["econ"]
    Output = kwargs["output"]
    Graphs = kwargs["graphs"]
    Graph_Head = kwargs["graph_head"]
    Graph_QV = kwargs["graph_QV"]
    Graph_P = kwargs["graph_P"]

    #Global Variables

    global Civil_Price, Blade_Price, Turbine_Price, Gearbox_Price, Generator_Price, Sluice_Price, Startup_Cost, Payback_Time
    global Eff_Turbine, Eff_Gearbox, Eff_Generator
    global Global_Time, Global_Volume, Global_Tide, Global_Head, Global_Head_Difference, Global_Velocity, Global_Discharge, Global_Head_Loss, Global_Power, Global_Power_Elec
    Global_Time = [0]
    Global_Volume = [0]
    Global_Tide = [0]
    Global_Head = [0]
    Global_Head_Difference = [0]
    Global_Velocity = [0]
    Global_Discharge = [0]
    Global_Head_Loss = [0]
    Global_Power = [0]
    Global_Power_Elec = []

    #Local Variables

    V_0 = 18891820
    Euler_Volume = [0]
    Euler_Volume_Tide = [0]
    Euler_Volume[0] = V_0
    Euler_Volume_Tide[0] = V_0
    Time = [0]
    M = 1453217
    G = 9.807
    rho = 1029
    Discharge_Coefficient= 0.8
    Sluicing_Discharge_Coefficient = 0.98
    Friction_Factor = 0.00035
    Draft_Length = 10
    Draft_Diameter = 10
    State = 0                   #0 = Waiting, 1 = filling sluice, 2 = draining generation, 3 = filling generation, 4 = draining sluice
    Current_Time = Step_Size
    Operational_Profile = Profile_List[Profile_Number-1]
    Profile_Stage = 0
    Total_Stages = len(Operational_Profile)
    Total_Mechanical_Energy = 0
    Total_Electrical_Energy = 0

    #Initial Calculations

    Area = np.pi*np.power((Turbine_Diameter/4),2)*Turbines
    Sluice_Area =  (np.pi*np.power((Turbine_Diameter/4),2)*Turbines)+(Sluice_Size*Sluices)

    '''
    Read operational algorithm profile, then switch between 5 different states, checking stopping conditions each time. Put Euler approximation in different function
    Operational states:
        -Filling_Sluice
        -Filling_Generation
        -Draining_Sluice
        -Draining_Generation
        -Transition (waiting)
    Save data to global arrays
    Plot graph using given parameters
    If value in square root turns negative, return an error. (This should only happen if sluice gates are not shut at the right time, it means the tide is higher than the lagoon)
    '''

    if Output == True:
        log.setLevel(logging.INFO)
    else:
        log.setLevel(logging.WARNING)

    print("\nRunning simulation...\n")

    State = Operational_Profile[0][0]
    Average_Head = 0
    AH_Count = 0
    Runtime = 0
    Flow_Rate_Average = 0
    Max_Head = []

    while Current_Time < Run_Time:

        if State == 0:

            log.info("In state 0: Waiting for tidal shift")

            while State == 0:

                if Current_Time > Run_Time:
                    State = 5
                    log.info("Runtime elapsed")
                elif Global_Tide[-1] < Operational_Profile[Profile_Stage][1]:
                    Profile_Stage = (Profile_Stage+1)%Total_Stages
                    State = Operational_Profile[Profile_Stage][0]
                else:
                    Global_Time.append(Current_Time)
                    Global_Tide.append(Evaluate_Tidal_Function(Tidal_Function, Current_Time))
                    Global_Volume.append(Global_Volume[-1])
                    Global_Head.append((Global_Volume[-1])/(M))
                    Global_Head_Difference.append(Global_Head[-1]-Global_Tide[-1])
                    Global_Velocity.append(0)
                    Global_Discharge.append(0)
                    Global_Head_Loss.append(0)
                    Global_Power.append(0)
                    Current_Time += Step_Size

        if State == 1:

            log.info("In state 1: Filling lagoon via sluicing")

            while State == 1:

                if Current_Time > Run_Time:
                    State = 5
                    log.info("Runtime elapsed")
                elif Global_Head[-1] > Operational_Profile[Profile_Stage][1]:
                    Profile_Stage = (Profile_Stage+1)%Total_Stages
                    State = Operational_Profile[Profile_Stage][0]
                else:

                    Global_Time.append(Current_Time)
                    Global_Tide.append(Evaluate_Tidal_Function(Tidal_Function, Current_Time))
                    #Global_Volume.append(Global_Volume[Current_Time-1]+Step_Size*Sluice_Area*Sluicing_Discharge_Coefficient*np.sqrt(2*G)*np.sqrt(Global_Tide[Current_Time]-((Global_Volume[Current_Time-1])/(M))-Pipe_Loss))

                    if (Global_Tide[-1])-((Global_Volume[-1])/(M)) < 0:
                        log.info("WARNING: Target value of " + str(Operational_Profile[Profile_Stage][1]) + "m in state 1 could not be met!")
                        Global_Volume.append(Global_Volume[-1])
                        Profile_Stage = (Profile_Stage+1)%Total_Stages
                        State = Operational_Profile[Profile_Stage][0]
                        Global_Velocity.append(Global_Velocity[-1])
                        Global_Discharge.append(Global_Discharge[-1])
                    else:
                        #Global_Volume.append(Global_Volume[-1]+Step_Size*Sluice_Area*Sluicing_Discharge_Coefficient*np.sqrt(2*G)*np.sqrt((Global_Tide[-1])-((Global_Volume[-1])/(M))-Pipe_Loss))
                        #Global_Velocity.append(np.sqrt(2*G)*np.sqrt((Global_Tide[-1])-((Global_Volume[-1])/(M))-Pipe_Loss))

                        Global_Velocity.append(np.sqrt(2*G*((Global_Tide[-1])-((Global_Volume[-1])/(M)))/(1+Friction_Factor*(Draft_Length/Draft_Diameter))))
                        Global_Volume.append(Global_Volume[-1]+Step_Size*Sluice_Area*Sluicing_Discharge_Coefficient*Global_Velocity[-1])

                        Global_Discharge.append(Global_Velocity[-1]*Sluice_Area*Sluicing_Discharge_Coefficient)

                    Global_Head.append((Global_Volume[-1])/(M))
                    Global_Head_Difference.append(Global_Head[-1]-Global_Tide[-1])
                    Global_Head_Loss.append(0)
                    Global_Power.append(0)
                    Current_Time += Step_Size
                    #print("the time is: " + str(Current_Time))

        if State == 2:

            log.info("In state 2: Draining lagoon via energy generation")

            while State == 2:

                if Current_Time > Run_Time:
                    State = 5
                    log.info("Runtime elapsed")
                elif Global_Head[-1] < Operational_Profile[Profile_Stage][1]:
                    Profile_Stage = (Profile_Stage+1)%Total_Stages
                    State = Operational_Profile[Profile_Stage][0]
                    #Current_Time = Run_Time+1
                else:

                    Global_Time.append(Current_Time)
                    Global_Tide.append(Evaluate_Tidal_Function(Tidal_Function, Current_Time))

                    if (Global_Volume[-1])/(M)-(Global_Tide[-1]) < 0:
                        log.info("WARNING: Target value of " + str(Operational_Profile[Profile_Stage][1]) + "m in state 2 could not be met!")
                        Global_Volume.append(Global_Volume[-1])
                        Profile_Stage = (Profile_Stage+1)%Total_Stages
                        State = Operational_Profile[Profile_Stage][0]
                        Global_Velocity.append(Global_Velocity[-1])
                        Global_Discharge.append(Global_Discharge[-1])
                        Global_Head_Loss.append(Global_Head_Loss[-1])
                        Global_Power.append(Global_Power[-1])
                    else:
                        #Global_Volume.append(Global_Volume[-1]-Step_Size*Area*Discharge_Coefficient*np.sqrt(2*G)*np.sqrt((Global_Volume[-1])/(M)-(Global_Tide[-1])-Turbine_Loss-Pipe_Loss))
                        #Global_Velocity.append(np.sqrt(2*G)*np.sqrt((Global_Volume[-1])/(M)-(Global_Tide[-1])-Turbine_Loss-Pipe_Loss))

                        Global_Velocity.append(np.sqrt((2*G*((Global_Volume[-1])/(M)-(Global_Tide[-1]))*(1-Eff_Turbine))/(1-Eff_Turbine*Friction_Factor*(Draft_Length/Draft_Diameter))))
                        Global_Volume.append(Global_Volume[-1]-Step_Size*Area*Discharge_Coefficient*Global_Velocity[-1])

                        Global_Discharge.append(Global_Velocity[-1]*Area*Discharge_Coefficient)
                        Global_Head_Loss.append(((Global_Volume[-1])/(M)-Global_Tide[-1]-(Friction_Factor*(Draft_Length/Draft_Diameter)*(Global_Velocity[-1]**2/(2*G)))))
                        Global_Power.append(rho*G*Global_Discharge[-1]*Global_Head_Loss[-1])

                    Global_Head.append((Global_Volume[-1])/(M))
                    Global_Head_Difference.append(Global_Head[-1]-Global_Tide[-1])
                    Current_Time += Step_Size

                    Average_Head += abs(Global_Head_Difference[-1])
                    Max_Head.append(abs(Global_Head_Difference[-1]))
                    AH_Count += 1
                    if Current_Time > 50000:
                        Runtime += 1*Step_Size
                    Flow_Rate_Average += Global_Discharge[-1]

        if State == 3:

            log.info("In state 3: Filling lagoon via energy generation")

            while State == 3:

                if Current_Time > Run_Time:
                    State = 5
                    log.info("Runtime elapsed")
                elif Global_Head[-1] > Operational_Profile[Profile_Stage][1]:
                    Profile_Stage = (Profile_Stage+1)%Total_Stages
                    State = Operational_Profile[Profile_Stage][0]
                else:

                    Global_Time.append(Current_Time)
                    Global_Tide.append(Evaluate_Tidal_Function(Tidal_Function, Current_Time))
                    #Global_Volume.append(Global_Volume[Current_Time-1]+Step_Size*Sluice_Area*Sluicing_Discharge_Coefficient*np.sqrt(2*G)*np.sqrt(Global_Tide[Current_Time]-((Global_Volume[Current_Time-1])/(M))-Pipe_Loss))

                    if (Global_Tide[-1])-((Global_Volume[-1])/(M)) < 0:
                        log.info("WARNING: Target value of " + str(Operational_Profile[Profile_Stage][1]) + "m in state 1 could not be met!")
                        Global_Volume.append(Global_Volume[-1])
                        Profile_Stage = (Profile_Stage+1)%Total_Stages
                        State = Operational_Profile[Profile_Stage][0]
                        Global_Velocity.append(Global_Velocity[-1])
                        Global_Discharge.append(Global_Discharge[-1])
                        Global_Head_Loss.append(Global_Head_Loss[-1])
                        Global_Power.append(Global_Power[-1])
                    else:
                        #Global_Volume.append(Global_Volume[-1]+Step_Size*Sluice_Area*Sluicing_Discharge_Coefficient*np.sqrt(2*G)*np.sqrt((Global_Tide[-1])-((Global_Volume[-1])/(M))-Pipe_Loss))
                        #Global_Velocity.append(np.sqrt(2*G)*np.sqrt((Global_Tide[-1])-((Global_Volume[-1])/(M))-Pipe_Loss))

                        Global_Velocity.append(np.sqrt((2*G*((Global_Tide[-1])-(Global_Volume[-1])/(M))*(1-Eff_Turbine))/(1-Eff_Turbine*Friction_Factor*(Draft_Length/Draft_Diameter))))
                        Global_Volume.append(Global_Volume[-1]+Step_Size*Area*Discharge_Coefficient*Global_Velocity[-1])

                        Global_Discharge.append(Global_Velocity[-1]*Area*Discharge_Coefficient)
                        Global_Head_Loss.append(Global_Tide[-1]-((Global_Volume[-1])/(M))-(Friction_Factor*(Draft_Length/Draft_Diameter)*(Global_Velocity[-1]**2/(2*G))))
                        Global_Power.append(rho*G*Global_Discharge[-1]*Global_Head_Loss[-1])

                    Global_Head.append((Global_Volume[-1])/(M))
                    Global_Head_Difference.append(Global_Head[-1]-Global_Tide[-1])
                    Current_Time += Step_Size

                    Average_Head += abs(Global_Head_Difference[-1])
                    Max_Head.append(abs(Global_Head_Difference[-1]))
                    AH_Count += 1
                    if Current_Time > 50000:
                        Runtime += 1*Step_Size
                    Flow_Rate_Average += Global_Discharge[-1]

        if State == 4:

            log.info("In state 4: Waiting for tidal shift")

            while State == 4:

                if Current_Time > Run_Time:
                    State = 5
                    log.info("Runtime elapsed")
                elif Global_Tide[-1] > Operational_Profile[Profile_Stage][1]:
                    Profile_Stage = (Profile_Stage+1)%Total_Stages
                    State = Operational_Profile[Profile_Stage][0]
                else:
                    Global_Time.append(Current_Time)
                    Global_Tide.append(Evaluate_Tidal_Function(Tidal_Function, Current_Time))
                    Global_Volume.append(Global_Volume[-1])
                    Global_Head.append((Global_Volume[-1])/(M))
                    Global_Head_Difference.append(Global_Head[-1]-Global_Tide[-1])
                    Global_Velocity.append(0)
                    Global_Discharge.append(0)
                    Global_Head_Loss.append(0)
                    Global_Power.append(0)
                    Current_Time += Step_Size

        log.info("Current time: " + str(Current_Time))

    Average_Head = (Average_Head/AH_Count)
    Flow_Rate_Average = (Flow_Rate_Average/AH_Count)

    #50000 start offset, run for 86400

    print("\nSimulation complete\n")
    print("Average head difference across turbines (m): " + str(Average_Head))
    print("Max head difference across turbines (m): " + str(max(Max_Head)))
    print("Run time (s): " + str(Runtime))
    print("Average discharge (m^3s^-1): " + str(Flow_Rate_Average))

    #Energy generation calculations
    print("\n================================================================")
    print("Running energy calculations...")

    for Power in Global_Power:

        if np.isnan(Power) == True:
            Power = 0

        Global_Power_Elec.append(Power*Eff_Gearbox*Eff_Generator)
        Total_Mechanical_Energy += int(Power*Step_Size)
        Total_Electrical_Energy += int(Global_Power_Elec[-1]*Step_Size)

    Energy_Lost = Total_Mechanical_Energy-Total_Electrical_Energy
    Efficiency = (Eff_Turbine*Eff_Gearbox*Eff_Generator)
    print("Total mechanical energy generated (J): " + str(Total_Mechanical_Energy))
    print("Energy lost (J): " + str(Energy_Lost))
    print("System efficiency: " + str(Efficiency))
    print("Total electrical energy generated (J): " + str(Total_Electrical_Energy))
    print("Total electrical energy generated (kWh): " + str(Total_Electrical_Energy/3.6e+6))
    #Print peak power and total energy
    #Print final power and energy and percentage lost

    if Econ == True:                                                            #Section for calculating economic assessment.

        print("\n================================================================")
        print("Running economic assessment of configuration...")

        Startup_Cost = Civil_Price+(Turbines*(Blade_Price+Shaft_Price+Turbine_Price+Gearbox_Price+(2*Sluice_Price)+Generator_Price+Electrical_Price))+(Sluices*Sluice_Price)
        Running_Costs_Day = 823 #a day
        Total_Running_Costs = Running_Costs_Day*(Run_Time/86400)
        Energy_Price = 92.5/1000 #per kWh
        Turnover = (Total_Electrical_Energy/(3.6e+6))*Energy_Price
        Gross_Profit = Turnover-Total_Running_Costs
        Net_Profit = Gross_Profit-Startup_Cost
        Payback_Time = Startup_Cost/Gross_Profit

        print("Startup costs: " + str(Startup_Cost))
        print("Running costs: " + str(Total_Running_Costs))
        print("Turnover: " + str(Turnover))
        print("Gross profit: " + str(Gross_Profit))
        print("Net profit: " + str(Net_Profit))
        print("Pay back time in years: " + str(Payback_Time))

        if Graphs == True:

            plt.figure(figsize=plt.figaspect(1)*2)
            ax = plt.axes()
            plt.title("Break-Even Analysis")
            ax.set_xlabel("Time (Years)")
            ax.set_ylabel("Equity (£)")

            Fixed_Costs_Plot = ax.plot([0,Payback_Time,2*Payback_Time], [Startup_Cost, Startup_Cost, Startup_Cost], "--", label="Fixed costs", color="red", linewidth=3)
            Total_Costs_Plot = ax.plot([0,Payback_Time,2*Payback_Time], [Startup_Cost, (Total_Running_Costs*Payback_Time + Startup_Cost), (Total_Running_Costs*Payback_Time*2 + Startup_Cost)], "--", label="Total costs", color="darkred", linewidth=3)
            Revenue_Plot = ax.plot([0,Payback_Time,2*Payback_Time], [0, (Turnover*Payback_Time), (Turnover*Payback_Time*2)], label="Revenue", color="blue", linewidth=3)

            Lines = Fixed_Costs_Plot+Total_Costs_Plot+Revenue_Plot
            Labels =[l.get_label() for l in Lines]
            ax.legend(Lines, Labels)
            plt.minorticks_on()
            ax.grid(which='major', color='black', linestyle='-', linewidth=1)
            ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

    #Take into account maintencance downtimes

    if Graphs == True:

        plt.figure(figsize=plt.figaspect(1)*2)

        ax = plt.axes()
        second_ax = ax.twinx()
        plt.title("Lagoon Volume, Lagoon Height and Tide Height Vs Time (Double Effect)")
        ax.set_xlabel("Time (s)")
        ax.set_ylabel("Volume (m^3)")
        second_ax.set_ylabel('Height (m)')
        Filling_Plot = ax.plot(Global_Time, Global_Volume, label="Lagoon Volume", color="deepskyblue", linewidth=3)
        Lagoon_Head_Plot = second_ax.plot(Global_Time, Global_Head, "--", label="Lagoon height", color="green", linewidth=2)
        Tide_Height_Plot = second_ax.plot(Global_Time, Global_Tide, "--", label="Tide height", color ="blue", linewidth=2)

#        plt.title("Lagoon Volume, Lagoon Height and Tide Height Vs Time (Double Effect)", fontsize='30', weight='bold')
#        ax.set_xlabel("Time (s)", fontsize='30', weight='bold')
#        ax.set_ylabel('Height (m)', fontsize='30', weight='bold')
#        Lagoon_Head_Plot = ax.plot(Global_Time, Global_Head, "--", label="Lagoon height", color="green", linewidth=2)
#        Tide_Height_Plot = ax.plot(Global_Time, Global_Tide, "--", label="Tide height", color ="blue", linewidth=2)
#        ax.set_ylabel('Height (m)')

        if Graph_Head == True:
            Head_Difference_Plot = second_ax.plot(Global_Time, Global_Head_Difference, "--", label="Head difference", color ="orange", linewidth=2)
            Lines = Filling_Plot+Lagoon_Head_Plot+Tide_Height_Plot+Head_Difference_Plot
        else:
            Lines = Filling_Plot+Lagoon_Head_Plot+Tide_Height_Plot
            #Lines = Lagoon_Head_Plot+Tide_Height_Plot

        Labels =[l.get_label() for l in Lines]
        ax.legend(Lines, Labels)

        #ax.legend(Lines, Labels, fontsize='30')

        plt.minorticks_on()
        ax.grid(which='major', color='black', linestyle='-', linewidth=1)
        ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)
        ax.set_ylim(0,2e7)

#        for tick in ax.xaxis.get_major_ticks():
#                tick.label.set_fontsize(30)
#                tick.label.set_weight('bold')
#
#        for tick in ax.yaxis.get_major_ticks():
#                tick.label.set_fontsize(30)
#                tick.label.set_weight('bold')

        if Graph_QV == True:

            #Red graphs

            plt.figure(figsize=plt.figaspect(1)*2)
            QVax = plt.axes()
            second_QVax = QVax.twinx()
            plt.title("Velocity & Discharge Vs Time")
            QVax.set_xlabel("Time (s)")
            QVax.set_ylabel("Velocity (ms^-1)")
            second_QVax.set_ylabel('Discharge (m^3s^-1)')

            Velocity_Plot = QVax.plot(Global_Time, Global_Velocity, label="Flow velocity", color="red", linewidth=2)
            Discharge_Plot = second_QVax.plot(Global_Time, Global_Discharge, "--", label="Total discharge", color="maroon", linewidth=2)
            Lines = Velocity_Plot+Discharge_Plot
            Labels =[l.get_label() for l in Lines]
            QVax.legend(Lines, Labels)
            plt.minorticks_on()
            QVax.grid(which='major', color='black', linestyle='-', linewidth=1)
            QVax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

        if Graph_P == True:

            plt.figure(figsize=plt.figaspect(1)*2)
            Pax = plt.axes()
            plt.title("Mechanical & Electrical Power Vs Time")
            Pax.set_xlabel("Time (s)")
            Pax.set_ylabel("Power (w)")

            Mech_Power_Plot = Pax.plot(Global_Time, Global_Power, label="Mechanical Power", color="gold", linewidth=2)
            Elec_Power_Plot = Pax.plot(Global_Time, Global_Power_Elec, "--", label="Electrical Power", color="y", linewidth=2)
            Lines = Mech_Power_Plot+Elec_Power_Plot
            Labels =[l.get_label() for l in Lines]
            Pax.legend(Lines, Labels)
            plt.minorticks_on()
            Pax.grid(which='major', color='black', linestyle='-', linewidth=1)
            Pax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

#            plt.title("Mechanical & Electrical Power Vs Time", fontsize='30', weight='bold')
#            Pax.set_xlabel("Time (s)", fontsize='30', weight='bold')
#            Pax.set_ylabel("Power (w)", fontsize='30', weight='bold')
#            Pax.legend(Lines, Labels, fontsize='30')
#
#            for tick in Pax.xaxis.get_major_ticks():
#                tick.label.set_fontsize(30)
#                tick.label.set_weight('bold')
#
#            for tick in Pax.yaxis.get_major_ticks():
#                tick.label.set_fontsize(30)
#                tick.label.set_weight('bold')

def Evaluate_Tidal_Function(Type, Time):

    if Type == "sine":
        return (6.5*np.cos(2*np.pi*0.0000231*Time-np.pi)+6.5)

    elif Type == "sine_average":
        return (4*np.cos(2*np.pi*0.0000231*Time-np.pi)+6.5)
    elif Type == "Newport_1":
        Time += 14000
        return ( (3.678*np.cos(2*np.pi*(2.236e-5)*Time+(48.06*(np.pi/180)))) +
                 (1.4298*np.cos(2*np.pi*(2.239e-5)*Time-(130.6*(np.pi/180)))) +
                 (1.4986*np.cos(2*np.pi*(2.315e-5)*Time+(176.7*(np.pi/180)))) +
                 (0.7298*np.cos(2*np.pi*(2.194e-5)*Time-(53.75*(np.pi/180)))) + 6.278)

def Optimize(Item, Mode):

    global Global_Power, Profile_List, Eff_Turbine, Eff_Gearbox, Eff_Generator, Startup_Cost, Payback_Time

    if Item == "blade_size":

        Power = []
        Diameters = np.arange(1,12.5,0.5)
        Profile_List = []

        print("Calculating blade diameter optimization")

        if Mode == "single":
            Setup_Profile([[1,12],[0,5],[2,0]])
        elif Mode == "double":
            Setup_Profile([[3,14],[0,5],[2,0],[4,7]])

        for Turbine in np.arange(1,21,1):

            Power.append([])

            for Diameter in np.arange(1,12.5,0.5):

                Total_Mechanical_Energy = 0
                Run_Simulation(step=100, tidal_function="Newport_1", turbines=Turbine, diameter=Diameter, slucies=0, sluice_size=80, profile=1, time=60*60*24*365, econ=False, output=False, graphs=False, graph_head=False, graph_QV=False, graph_P=False)

                Cut_Count = 0

                for Energy in Global_Power:
                    Total_Mechanical_Energy += Energy*100

                Power[Turbine-1].append(Total_Mechanical_Energy)

        plt.figure(figsize=plt.figaspect(1)*2)
        ax = plt.axes()
        plt.title("Energy Output Vs Blade Diameter For Different Number of Turbines In Single Effect Mode (Newport Tidal Data)")
        ax.set_xlabel("Blade Diameter (m)")
        ax.set_ylabel("Energy Output (J)")

        Count = 0

        for i in Power:
            Temp = ax.plot(Diameters, Power[Count], label=("Turbines: " + str(Count+1)), linewidth=2)
            Count += 1

        #ax.legend("1 turbine","2 turbines","3 turbines","4 turbines","5 turbines","6 turbines","7 turbines","8 turbines","9 turbines","10 turbines","11 turbines","12 turbines","13 turbinse","14 turbines","15 turbines","16 turbines","17 turbines","18 turbines","19 turbines","20 turbines",)
        ax.legend()
        plt.minorticks_on()
        ax.grid(which='major', color='black', linestyle='-', linewidth=1)
        ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

    elif Item == "turbine_number":

        Power = []
        Turbines = np.arange(1,31,1)
        Diameters = np.arange(1,12.5,0.5)
        Profile_List = []

        print("Calculating turbine number optimization")

        if Mode == "single":
            Setup_Profile([[1,12],[0,5],[2,0]])
        elif Mode == "double":
            Setup_Profile([[3,14],[0,5],[2,0],[4,7]])

        Count = 0

        for Diameter in np.arange(1,12.5,0.5):

            Power.append([])
            Count += 1

            for Turbine in np.arange(1,31,1):

                Total_Mechanical_Energy = 0
                Run_Simulation(step=100, tidal_function="Newport_1", turbines=Turbine, diameter=Diameter, slucies=0, sluice_size=80, profile=1, time=60*60*24*365, econ=False, output=False, graphs=False, graph_head=False, graph_QV=False, graph_P=False)

                for Energy in Global_Power:
                    #Global_Power_Elec.append(i*Eff_Turbine*Eff_Gearbox*Eff_Generator)
                    Total_Mechanical_Energy += Energy*100

                Power[Count-1].append(Total_Mechanical_Energy)

        plt.figure(figsize=plt.figaspect(1)*2)
        ax = plt.axes()

        if Mode == "single":
            plt.title("Energy Output Vs Number of Turbines For Different Blade Diameters In Single Effect Mode (Newport Tidal Data)")
        elif Mode == "double":
            plt.title("Energy Output Vs Number of Turbines For Different Blade Diameters In Double Effect Mode (Newport Tidal Data)")

        ax.set_xlabel("Number of Turbines")
        ax.set_ylabel("Energy Output (J)")

        Count = 0

        for i in Power:
            Temp = ax.plot(Turbines, Power[Count], label=("Diameter: " + str(Diameters[Count])), linewidth=2)
            Count += 1

        #ax.legend("1 turbine","2 turbines","3 turbines","4 turbines","5 turbines","6 turbines","7 turbines","8 turbines","9 turbines","10 turbines","11 turbines","12 turbines","13 turbinse","14 turbines","15 turbines","16 turbines","17 turbines","18 turbines","19 turbines","20 turbines",)
        ax.legend()
        plt.minorticks_on()
        ax.grid(which='major', color='black', linestyle='-', linewidth=1)
        ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

    elif Item == "algorithm":

        Profile_List = []
        Power = []
        Triggers = np.arange(13,-1,-0.5)
        for i in range(len(Triggers)):
            Triggers[i] = (Triggers[i]/13)*100
        Count = 1
        Turbine_Count = 0

        for Turbines in np.arange(1,26,1):

            Power.append([])
            Profile_List = []
            Turbine_Count += 1
            Count = 1

            for i in np.arange(13,-1,-0.5):

                Total_Mechanical_Energy = 0
                Setup_Profile([[3,14],[0,i],[2,0],[4,0]])
                Run_Simulation(step=100, tidal_function="sine", turbines=Turbine_Count, diameter=5.87, slucies=0, sluice_size=80, profile=Count, time=150000, econ=False, output=False, graphs=False, graph_head=False, graph_QV=False, graph_P=False)

                for Energy in Global_Power:
                        #Global_Power_Elec.append(i*Eff_Turbine*Eff_Gearbox*Eff_Generator)
                        Total_Mechanical_Energy += Energy

                Power[Turbine_Count-1].append(Total_Mechanical_Energy)
                Count += 1

        plt.figure(figsize=plt.figaspect(1)*2)
        ax = plt.axes()
        plt.title("Energy Output Vs Sluice Gate Triggering Height (Double Effect)")
        ax.set_xlabel("Lagoon Triggering Height as (Percentage of Tidal Range)")
        ax.set_ylabel("Energy Output (J)")

        Count = 0

        for i in Power:
            Temp = ax.plot(Triggers, Power[Count], label=("Turbines: " + str(Count+1)), linewidth=2)
            Count += 1

        ax.legend()
        plt.minorticks_on()
        ax.grid(which='major', color='black', linestyle='-', linewidth=1)
        ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

    elif Item == "power":

        Power = [[],[]]
        Per_Turbine = []
        Turbines = np.arange(1,41,1)

        for Turbine in np.arange(1,41,1):

            Run_Simulation(step=100, tidal_function="Newport_1", turbines=Turbine, diameter=5.87, slucies=0, sluice_size=80, profile=1, time=60*60*24*365, econ=False, output=False, graphs=False, graph_head=False, graph_QV=False, graph_P=False)

            Max_Mechanical_Power = max(Global_Power)
            Max_Electrical_Power = (Max_Mechanical_Power*Eff_Gearbox*Eff_Generator)

            Power[0].append(Max_Mechanical_Power)
            Power[1].append(Max_Electrical_Power)
            Per_Turbine.append(Max_Electrical_Power/Turbine)

        plt.figure(figsize=plt.figaspect(1)*2)
        ax = plt.axes()
        plt.title("Max Power Output Vs Number of Turbines")
        ax.set_xlabel("Number of Turbines")
        ax.set_ylabel("Max Power Output (W)")

        Temp = ax.plot(Turbines, Power[0], label=("Mechanical Power"), color="gold", linewidth=2)
        Temp2 = ax.plot(Turbines, Power[1], "--", label=("Electrical Power"), color="y", linewidth=2)
        Temp2 = ax.plot(Turbines, Per_Turbine, "--", label=("Electrical Power Per Turbine"), color="red", linewidth=2)

        ax.legend()
        plt.minorticks_on()
        ax.grid(which='major', color='black', linestyle='-', linewidth=1)
        ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

    elif Item == "payback":

        Profile_List = []
        Turbines = np.arange(3,41,1)
        Startup_Costs = []
        Payback_Times = []

        if Mode == "single":
            Setup_Profile([[1,12],[0,5],[2,0]])
        elif Mode == "double":
            Setup_Profile([[3,14],[0,5],[2,0],[4,7]])

        for Turbine in Turbines:

            Run_Simulation(step=100, tidal_function="Newport_1", turbines=Turbine, diameter=5.87, slucies=0, sluice_size=80, profile=1, time=60*60*24*365, econ=True, output=False, graphs=False, graph_head=False, graph_QV=False, graph_P=False)
            Startup_Costs.append(Startup_Cost)
            Payback_Times.append(Payback_Time)

        plt.figure(figsize=plt.figaspect(1)*2)
        ax = plt.axes()
        plt.title("Number of Turbines Vs Payback Time")
        ax.set_xlabel("Number of Turbines")
        ax.set_ylabel("Payback Time (Years)")

        Temp = ax.plot(Turbines, Payback_Times, label=("Diameter: 5.87m"), color="blue", linewidth=2)

        ax.legend()
        plt.minorticks_on()
        ax.grid(which='major', color='black', linestyle='-', linewidth=1)
        ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

def Print_Costs():
    print("Here are some costs")

def Set_Costs(**kwargs):
    print("Setting costs")

def Heads_Graph():          #Shows a graph of lagoon height and tidal height against time parameter. Tidal height is built into program, volume comes from analyitic function call.

    Volume, Time = Analyitic_Simulation_Simple()
    print(Volume)
    Tide_Heights = [0]
    M = 1453217

    for i in range(len(Volume)):
        Volume[i] = Volume[i]/M
        Tide_Heights.append(5*np.sin(2*np.pi*0.0000463*(i+1)+1)+5)

    print("Time: " + str(len(Time)))
    print("Volume: " + str(len(Volume)))
    print("Tide height: " + str(len(Tide_Heights)))
    plt.figure(figsize=plt.figaspect(1)*2)
    ax = plt.axes() #proj_type = 'ortho'
    plt.title("Lagoon Elevation Head And Tidal Height")
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Head (m)")
    ax.plot(Time, Volume)
    Time.append(Time[len(Time)-1]+1)
    ax.plot(Time, Tide_Heights)
    plt.minorticks_on()

    ax.grid(which='major', color='black', linestyle='-', linewidth=1)
    ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

def Tidal_Function_Testing(Interval=86400):     #Shows a graph of a desired tidal function hardcoded in. The time interval is taken as the parameter.

    xlim = np.arange(0, 60* 60 *26, 60*60*2)
    Time = [0]
    Tide_Height = [0]
    FFT_Tidal_Function = [0]

    for i in range(Interval):

        Time.append(i)
        #Tide_Height.append(6*np.cos(2*np.pi*0.0000231*i-np.pi)+6)
        #FFT_Tidal_Function.append((3.68*np.sin(2*np.pi*(2.236e-5)*i*10))+(1.499*np.cos(2*np.pi*(2.315e-5)*i*10))+(0.73*np.cos(2*np.pi*(2.195e-5)*i*10))+(0.3581*np.sin(2*np.pi*(2.322e-5)*i*10)))
        FFT_Tidal_Function.append((3.678*np.cos(2*np.pi*(2.236e-5)*i+(48.06*(np.pi/180))))+(1.4298*np.cos(2*np.pi*(2.239e-5)*i-(130.6*(np.pi/180))))+(1.4986*
                                  np.cos(2*np.pi*(2.315e-5)*i+(176.7*(np.pi/180))))+(0.7298*np.cos(2*np.pi*(2.194e-5)*i-(53.75*(np.pi/180)))) + 6.278)

    plt.figure(figsize=plt.figaspect(1)*2)
    ax = plt.axes() #proj_type = 'ortho'
    plt.title("Contiuous Tidal Function Over 2019 (From Newport DFT)")
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Ocean Height (m)")
    ax.plot(Time, FFT_Tidal_Function)
    plt.minorticks_on()
    #plt.xticks(xlim, [str(n).zfill(2) + ':00' for n in np.arange(0, 26,2)])
    ax.grid(which='major', color='black', linestyle='-', linewidth=1)
    ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

def Analyitic_Simulation_Simple(Duration=21600):        #Calculates the volume and graphs it over a time parameter analyitically.

    M = 1453217
    G = 9.807
    V_0 = 18891820
    Area = (np.power(7.5,2)/4)*np.pi
    Time = [0]
    Volume = [0]
    Volume[0] = V_0
    Euler_Volume = [V_0]

    for i in range(Duration):
        Time.append(i)
        Volume.append(np.power(np.sqrt(V_0)-0.5*Area*i*np.sqrt((2*G)/(M)),2))
        Euler_Volume.append(Euler_Volume[-1]-(Area*np.sqrt(2*G*(Euler_Volume[-1]/M))))

    plt.figure(figsize=plt.figaspect(1)*2)
    ax = plt.axes() #proj_type = 'ortho'
    plt.title("Volume Vs Time")
    ax.set_xlabel("Time (s)")
    ax.set_ylabel("Volume (m^3)")
    ax.plot(Time, Volume)
    ax.plot(Time, Euler_Volume)
    ax.legend("Analytical", "Numerical")
    plt.minorticks_on()
    ax.grid(which='major', color='black', linestyle='-', linewidth=1)
    ax.grid(which='minor', color='black', linestyle='--', linewidth=0.5)

    return Volume, Time

def Setup_Profile(states=[]):

    #Format [[State number, triggering lagoon head], ...]
    print("Adding profile to list of saved profiles. This is profile number " + str(len(Profile_List)+1))
    Profile_List.append(states)

def help(*args):

    if len(args) == 0:

        print("Help:")
        print("\n1. To run a simulation, you must first setup an operating profile to tell the lagoon how it should operate. To learn how to do this, type help('profile'). Alternativly, you can use a defaul profile already built into the program. Profile 1 is a simple single effect profile, profile 2 is a simple double effect profile.")
        print("\n2. To learn how to run a simulation, type help('sim').")

    elif args[0] == "profile":

        print("Help profile:")
        print("\nThe lagoon can be in one of 5 states at any given time: \
State 0 - This is the waiting state, the lagoon is waiting for a head difference to build up before opening the sluice gates.\n\
State 1 - The lagoon is filling WITHOUT generating electricity. In this state, turbines are not moving, water is entering the lagoon through the turbine shafts and through sluice gates in the wall.\n\
State 2 - The lagoon is draining whilst generating electricity.\n\
State 3 - The lagoon is filling whilst generating electricity.\n\
State 4 - The lagoon is draining WITHOUT generating electricity.\n")
        print("The operational algorithm governs which states the lagoon switches between and when. The algorithm is built up of stages, each stage coresponds to one state and the condition that must be met to move to the next stage (state).\
              For example: Setup_Profile([[1,12],[0,5],[2,0]]) has 3 stages. The first stage says the simulation will start in state 1 and will transition to the next state when the water height reaches 12 m, the second state is state 0 and\
 the transition from that is when the water height is at 5 m. The final state is state 2, when the water level reaches 0 m then cycle will loop back to state 1. The water height is in reference to the lagoon or ocean height\
 depending on what makes sense for that particular state. Similarly, transitions are taken when the water height is above or below the triggering value, not equal and is again dependant on the particular state. As a safety\
 mechanism to ensure the simulation always runs, if a state transition isnt met and the tide changes direction, the state will switch despite the condition not being\
 met. Any profile can theoretically be constructed with any number of stages using this template. Built in profiles 1 and 2 are single and double effect modes respectivly.")

    elif args[0] == "sim":

        print("Help simulation:")
        print("\nTo run a simulation, run the following function call and changes the parameters as you desire: \n")
        print('Run_Simulation(step=100, tidal_function="Newport_1", turbines=25, diameter=5.88, slucies=0, sluice_size=80, profile=2, time=60*60*24*365, econ=True, output=False, graphs=True, graph_head=True, graph_QV=True, graph_P=True))')
        print("\nThe above command executes a simulation using our final lagoon configuration over the course of a year. Alternativly, you can change the tidal_function parameter to 'sine', the time (in seconds) to a diffrerent amount and any other numerical value to what you want to test. The final boolen parameters are used to toggle the display opf certain graphs as well as debug information to the console. Make sure you have setup a profile for your simulation run or use one of the two built in (profiles 1 or 2).")

    else:

        print("Help command unknown, are you sure you typed it correctly?")

Setup_Profile([[1,12],[0,5],[2,0]])
Setup_Profile([[3,14],[0,5],[2,0],[4,7]])


import os
import db_controller
import helpers

ROOT_PATH = "var/www/aws_flask/voip-forum-api"
XML_FILE = os.path.join(ROOT_PATH, "static/instructions.xml")

def make_xml():
	FRONT = "<Response>\n"
	middle = ""
	BACK = "</Response>"
	db = db_controller.Database() #create connection to database

	for message in db.get_messages():
		print(message)
		message = helpers.replace_badchars(message)
		middle += f"<Say voice=\"alice\"> {message} </Say>\n"
		middle += "<Pause length=\"2\"/>\n"

	full_xml = FRONT + middle + BACK

	with open(XML_FILE, 'w') as file:
			file.write(full_xml)


from sys import stdin

def readint():
    return int(stdin.readline())

n = readint()

while n != 0:
    names = []
    for _ in range(n):
        names.append(stdin.readline().strip())

    names.sort(key=lambda name: name[0:2])

    for name in names:
        print(name)
    print()

    n = readint()


# class that will be used to get the information from the ipinfo.io website
import ipinfo
from setup_log import setup_logger
# token = "7269b8c71f592f" # my privet token

# setting up log File
log = setup_logger.setup_logger(logger_name="ipinfo_py", log_file='log_files\ipinfo_class.log')

# creating a class to get lat and log
class LatLon():
    def __init__(self):
        try:
            log.info("Connecting to ipinfo api")
            # connection to ipinof api through the api token
            self.token = "7269b8c71f592f" # my secret token
            self.handler = ipinfo.getHandler(self.token)
            self.res = self.handler.getDetails()
            log.info("Connection to ipinfo api successful")
        except Exception as e:
            log.info("Connection to ipinfo api FAILED:- " + str(e))

    def get_latlon(self):
        """Function will return Latitude and Longitude"""
        try:
            log.info("Getting Latitude and Longitude")
            # getting the latitude and longitude from the ipinfo api
            lat = self.res.latitude
            lon = self.res.longitude
            return lat, lon
        except Exception as e:
            log.info("Failed to returning Latitude Longitude:- " + str(e))


import unittest
from itertools import izip
from os.path import join

import geopandas as gpd

from context import src
from src import GetIncidentCounts

class TestGetIncidentCounts(unittest.TestCase):
    test_2006_fp = join('TestIncFiles', 'test_2006.csv')

    def test_get_call_data(self):
        pts, call_types = GetIncidentCounts.get_call_data(self.test_2006_fp)

        exp_pts = [
            (-80.93953700, 35.23977900),
            (-80.88772400, 35.21648000),
            (-80.90232300, 35.27923800),
            (-80.86900700, 35.20734900),
            (-80.91755900, 35.20787200),
        ]

        exp_calls = [
            u'611 Dispatched & canceled en route',
            u'321 EMS call, excluding vehicle accident with inju',
            u'531 Smoke or odor removal',
            u'321 EMS call, excluding vehicle accident with inju',
            u'321 EMS call, excluding vehicle accident with inju'
        ]
        pts = [(pt.x, pt.y) for pt in pts]
        for pt, exp_pt in izip(pts, exp_pts):
            self.assertAlmostEqual(pt[0], exp_pt[0], delta=0.0000001)
            self.assertAlmostEqual(pt[1], exp_pt[1], delta=0.0000001)

        self.assertListEqual(call_types, exp_calls)

class TestAverageCounts(unittest.TestCase):
    def test_avg_counts1(self):
        count_dict = \
            {0: {'2016':
                {
                    315: 5,
                    316: 35,
                    317: 65
                },
                '2015':
                    {
                        315: 10,
                        316: 40,
                        317: 70
                    },
                '2014':
                    {
                        315: 15,
                        316: 45,
                        317: 75
                    },
                '2013':
                    {
                        315: 20,
                        316: 50,
                        317: 80
                    },
                '2012':
                    {
                        315: 25,
                        316: 55,
                        317: 85,
                        318: 5
                    },
            }
            }

        year = '2016'
        all_inc_types = {315, 316, 317, 318}
        avg_counts = GetIncidentCounts.average_counts(count_dict, year, all_inc_types)
        exp_dict = \
            {0:
                {'2016':
                    {
                        315: 15,
                        316: 45,
                        317: 75,
                        318: 1
                    }
                }
            }
        self.assertDictEqual(avg_counts, exp_dict)

class TestDataFrame(unittest.TestCase):
    def test_generated_df_integrated(self):
        test_file = join('TestShpFile', 'MecklenburgCounty_NC_tract', 'MecklenburgCounty_NC_tract.shp')
        dem_gdf = gpd.read_file(test_file)
        exp_rec_nums_2006 = [207, 99, 44, 41, 35]
        exp_inc_types_2006 = ['611 Dispatched & canceled en route',
                              '321 EMS call, excluding vehicle accident with inju',
                              '531 Smoke or odor removal',
                              '321 EMS call, excluding vehicle accident with inju',
                              '321 EMS call, excluding vehicle accident with inju'
                              ]

        years = ['2006']
        base_shape = 'TRACTCE'
        all_counts, all_inc_types = GetIncidentCounts.get_all_counts(geo_df=dem_gdf, base_shape=base_shape,
                                                                     log_folder='TestIncFiles', years=years)
        geo_df = GetIncidentCounts.generate_count_gdf(geo_df=dem_gdf, base_shape=base_shape, all_counts=all_counts)

        self.assertSetEqual(all_inc_types, set(exp_inc_types_2006))
        for rn, it in izip(exp_rec_nums_2006, exp_inc_types_2006):
            val = geo_df.loc[rn, it]
            self.assertEqual(val, 1)

if __name__ == '__main__':
    unittest.main()


from gearbox.migrations import Migration

class AddTableCountry(Migration):

    database = "common"

    def up(self):
        t = self.table('Country', area="Sta_Data_2_256", label="Countries", dump_name="country", desc='''Country codes (ISO) and names
''')
        t.column('Country', 'character', format="xxx", initial="", max_width=6, label="Country", column_label="Country", position=2, order=10, help="Country Code (according to ISO Standard)")
        t.column('CoName', 'character', format="x(30)", initial="", max_width=60, label="Name of Country", column_label="Name of Country", position=3, order=20, help="Name of Country")
        t.column('FraudGroup', 'character', format="x(8)", initial="", max_width=16, label="Fraud Group", column_label="FraudGrp", position=4, order=30, help="Roaming Fraud Group")
        t.index('Country', [['Country']], area="Sta_Index_3", primary=True, unique=True)
        t.index('CoName', [['CoName']], area="Sta_Index_3")

    def down(self):
        self.drop_table('Country')


#(©)Codexbotz

from pyrogram import __version__
from bot import Bot
from config import OWNER_ID
from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery

@Bot.on_callback_query()
async def cb_handler(client: Bot, query: CallbackQuery):
    data = query.data
    if data == "about":
        await query.message.edit_text(
            text = f"○ ᴄʀᴇᴀᴛᴏʀ : sᴀɴᴅʏ\n○ ʟᴀɴɢᴜᴀɢᴇ : ᴘʏᴛʜᴏɴ𝟹\n○ ʟɪʙʀᴀʀʏ : ᴘʏʀᴏɢʀᴀᴍ ᴀsʏɴᴄɪᴏ {__version__}\n○ Channel : @MensBotz\n○ Support Group : @MensSupportt\n\n🔋 ᴘᴏᴡᴇʀᴇᴅ ʙʏ :- @MensBotZ",
            disable_web_page_preview = True,
            reply_markup = InlineKeyboardMarkup(
                [
                    [
                        InlineKeyboardButton("🔒 Close", callback_data = "close")
                    ]
                ]
            )
        )
    elif data == "close":
        await query.message.delete()
        try:
            await query.message.reply_to_message.delete()
        except:
            pass


try:
    for n in range(5):
        if (n > 3):
            raise Exception("数字 {} 大于3,异常".format(n))
        print(n)
### as 表示给 Exception 命名
except Exception as ex:
    print(ex)
finally:
    print("不管如何,finall都会执行")

python_base/一些注意事项/写一段自定义异常代码.py

写一段自定义异常代码.py


import tkinter as tk

from DBConnection import connectToDB
from UserCredentials import loginUser
from GradingFunctionality import AccessingFiles

def cannedCommentScreen():
    """
    This method creates the tkinter window, labels and entry boxes in order for the user to enter
    comments and save them.
    :return:
    """
    window = tk.Tk()
    window.title("Inspector - Grading Application")
    window.geometry("600x380+250+200")
    window.resizable(False, False)
    window.attributes("-topmost", 1)

    userID = loginUser.getUserID()

    conn = connectToDB.connectToDatabase()
    cur = conn.cursor()

    comments_lbl = tk.Label(window, fg="black", text="Enter canned comments below",
                            font=("Calibri Bold", 16))
    comments_lbl.place(x=180, y=10)

    comment1_lbl = tk.Label(window, fg="black", text="Comment 1: ", font=("Calibri", 12))
    comment1_lbl.place(x=30, y=82)
    commentsEntry1: tk.Text = tk.Text(window, height="2", width="50")
    commentsEntry1.place(x=150, y=78)
    comment2_lbl = tk.Label(window, fg="black", text="Comment 2: ", font=("Calibri", 12))
    comment2_lbl.place(x=30, y=131)
    commentsEntry2: tk.Text = tk.Text(window, height="2", width="50")
    commentsEntry2.place(x=150, y=127)
    comment3_lbl = tk.Label(window, fg="black", text="Comment 3: ", font=("Calibri", 12))
    comment3_lbl.place(x=30, y=181)
    commentsEntry3: tk.Text = tk.Text(window, height="2", width="50")
    commentsEntry3.place(x=150, y=177)
    comment4_lbl = tk.Label(window, fg="black", text="Comment 4: ", font=("Calibri", 12))
    comment4_lbl.place(x=30, y=231)
    commentsEntry4: tk.Text = tk.Text(window, height="2", width="50")
    commentsEntry4.place(x=150, y=227)
    comment5_lbl = tk.Label(window, fg="black", text="Comment 5: ", font=("Calibri", 12))
    comment5_lbl.place(x=30, y=281)
    commentsEntry5: tk.Text = tk.Text(window, height="2", width="50")
    commentsEntry5.place(x=150, y=277)

    def displayPrevious():
        """
        This method allows the user to display previously saved canned comments of the associated module code and
        assignment No. Throw exception if the user clicks the edit button if there are no previous canned comments
        saved in the database.
        :rtype: object
        """
        moduleCode = AccessingFiles.getModuleCode()
        assignmentNo = AccessingFiles.getAssignmentNo()

        if moduleCode and assignmentNo != "":
            try:
                cur.execute("SELECT * FROM cannedComments WHERE user_id=%s AND moduleCode = %s AND assignmentno = %s",
                            (userID, moduleCode, assignmentNo))
                cannedComments = cur.fetchone()
                conn.commit()

                commentsEntry1.insert(tk.END, cannedComments[3])
                commentsEntry2.insert(tk.END, cannedComments[4])
                commentsEntry3.insert(tk.END, cannedComments[5])
                commentsEntry4.insert(tk.END, cannedComments[6])
                commentsEntry5.insert(tk.END, cannedComments[7])

            except TypeError:
                error_lbl = tk.Label(window, text="No Previous records saved in the database\t\t", fg="red",
                                     font=("Calibri", 10))
                error_lbl.place(x=200, y=315)
        else:
            error_lbl = tk.Label(window, text="Please enter Module Code and Assignment No.", fg="red",
                                 font=("Calibri", 10))
            error_lbl.place(x=200, y=315)

    def saveCommentsButton():
        """
        This method is called when the save button is pressed. The contents of each entry box are saved
        into the cannedComments table in the postgresql database table. If the module code entered has
        comments already associated with it in the database the comments will be updated, otherwise
        the comments will just be inserted into the database.
        :return: array of comments that have been saved
        """
        moduleCode = AccessingFiles.getModuleCode()
        assignmentNo = AccessingFiles.getAssignmentNo()

        if moduleCode or assignmentNo != "":
            cur.execute("SELECT * FROM cannedComments WHERE user_id=%s AND moduleCode = %s AND assignmentno = %s",
                        (userID, moduleCode, assignmentNo))
            cannedComments = cur.fetchall()
            conn.commit()

            comment1 = commentsEntry1.get("1.0", 'end-1c')
            comment2 = commentsEntry2.get("1.0", 'end-1c')
            comment3 = commentsEntry3.get("1.0", 'end-1c')
            comment4 = commentsEntry4.get("1.0", 'end-1c')
            comment5 = commentsEntry5.get("1.0", 'end-1c')
            # When save button is pressed, save the comments and destroy the entry's and labels

            if not cannedComments:
                insertComments = "INSERT INTO cannedComments (user_id, moduleCode, assignmentNo, comment1, comment2, comment3, comment4, comment5) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
                val1 = (userID, moduleCode, assignmentNo, comment1, comment2, comment3, comment4, comment5)
                # Executes the insertion ans passes values username and password into the insertion
                cur.execute(insertComments, val1)
                conn.commit()
                newCommentsSaved_lbl = tk.Label(window, text="Canned Comments have been saved\t\t\t",
                                                font=("Calibri", 10))
                newCommentsSaved_lbl.place(x=200, y=315)

            else:
                updateComments = "Update cannedComments set comment1 = %s, comment2 = %s , comment3 = %s , comment4 = %s , comment5 = %s where user_id =%s and moduleCode=%s and assignmentNo = %s"
                val2 = (comment1, comment2, comment3, comment4, comment5, userID, moduleCode, assignmentNo)
                cur.execute(updateComments, val2)
                conn.commit()
                commentsUpdated_lbl = tk.Label(window, text="Canned Comments have been updated\t\t\t",
                                               font=("Calibri", 10))
                commentsUpdated_lbl.place(x=200, y=315)

            return [comment1, comment2, comment3, comment4, comment5]
        else:
            error_lbl = tk.Label(window, text="Please enter Module Code and Assignment No. in previous screen",
                                 fg="red",
                                 font=("Calibri", 10))
            error_lbl.place(x=180, y=315)

    def closeWindow():
        """
        This method is called when the close button is pressed and it destroys the tkinter canned comments window.
        """
        window.destroy()

    editButton = tk.Button(window, text="Edit Comments", width=13, command=displayPrevious)
    editButton.place(x=453, y=45)

    saveButton = tk.Button(window, text="Save", width=13, command=saveCommentsButton)
    saveButton.place(x=370, y=350)

    closeButton = tk.Button(window, text="Close", width=13, fg="red", command=closeWindow)
    closeButton.place(x=100, y=350)


import hypchat
import signal
import time
import logging
import subprocess

logging.basicConfig(
    format='%(asctime)s : %(levelname)s : %(message)s', level=logging.DEBUG)

bot_name = '/pyexec'
room_name = 'YOUR_ROOM_NAME'
api_key = 'YOUR_APIV2_KEY'

def timeout(a, b):
    raise RuntimeError

def subprocess_exec(src):

    signal.signal(signal.SIGALRM, timeout)
    signal.alarm(10)

    try:
        logging.debug('attempting to run %s' % src)
        cmd = 'python -c \'%s\'' % src.replace("\'", "\"")
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
        out, err = p.communicate()

        if out:
            result = out
        if err:
            result = err

    except SyntaxError as e:
        logging.debug('SyntaxError')

        result += str(e)
    except RuntimeError:
        logging.debug('ran too long')
        result += "Ran too long"

    signal.alarm(0)
    return result

def get_room(name, all_rooms):
    for room in all_rooms:
        if room['name'] == name:
            return room

def eval_bot_mentions(all_messages):
    for message in all_messages:
        message_text = message['message']
        if message_text.startswith(bot_name + ' '):
            logging.debug(message)
            text = message_text.replace(bot_name + ' ', '').strip()
            yield message['from']['mention_name'], text

if __name__ == "__main__":
    hc = hypchat.HypChat(api_key)
    logging.debug('connected to hipchat')

    all_rooms = hc.rooms(max_results=1000)['items']
    target_room = get_room(room_name, all_rooms)
    logging.debug('located %s Lounge room' % (room_name))

    after_message_id = target_room.latest(maxResults=1)['items'][0]['id']
    logging.debug('starting from id %s' % after_message_id)

    while True:
        try:
            logging.debug('fetching new messages')
            new_messages = target_room.latest(
                not_before=after_message_id)['items']
        except hypchat.requests.HttpServiceUnavailable:
            time.sleep(15)
            continue

        after_message_id = new_messages[-1]['id']
        for partner, text in eval_bot_mentions(new_messages[1:]):
            out = subprocess_exec("%s" % text)
            if out:
                logging.debug('trying to send %s/%s/%s' % (partner, text, out))

                target_room.message("@%s>>> %s\n%s" % (partner, text, out))
        time.sleep(5)


import tensorflow as tf
import numpy as np
from tqdm import tqdm
import os
from sklearn.utils import shuffle
from PIL import Image

def load_smaple(sample_dir,shuffle_flag = True):

    print("loading dataset...")
    lfilenames = []
    labelnames = []

    for dirpath,dirnames,filenames in os.walk(sample_dir):
        for filename in filenames:
            filepath = os.sep.join([dirpath,filename])
            lfilenames.append(filepath)
            labelname = dirpath.split("\\")[-1]
            labelnames.append(labelname)

    lab = list(sorted(set(labelnames)))
    labdict = dict(zip(lab,list(range(len(lab)))))
    labels = [labdict[i] for i in labelnames]

    if shuffle_flag:
        return shuffle(np.asarray(lfilenames),np.asarray(labels)),np.asarray(lab)
    else:
        return (np.asarray(lfilenames),np.asarray(labels)),np.asarray(lab)

dir_path = "man_woman"
(filenames,labels),_ = load_smaple(dir_path,False)

def make_TFRec(filenames,labels):
    #1.创建writer
    writer = tf.python_io.TFRecordWriter("mydata.tfrecords")
    for i in tqdm(range(len(labels))):
        image = Image.open(filenames[i])
        img = image.resize((256,256))
        img_raw = img.tobytes()
        #2.读取到的内容转化为tfrecords格式
        example = tf.train.Example( #example
                  features = tf.train.Features(#features
                      feature = {"label": tf.train.Feature(int64_list = tf.train.Int64List(value = [labels[i]])),
                                 "img_raw": tf.train.Feature(bytes_list = tf.train.BytesList(value = [img_raw]))}))#feature字典
        writer.write(example.SerializeToString())#序列化压缩
    writer.close()

make_TFRec(filenames,labels)

def read_and_decode(filenames,flag="train",batch_size=3):
    #1.读取文件生成队列
    if flag == "train":
        filename_queue = tf.train.string_input_producer(filenames)
    else:
        filename_queue = tf.train.string_input_producer(filenames,num_epochs=1,shuffle=False)
    #2.从队列读取example
    reader = tf.TFRecordReader()
    _,serialized_example = reader.read(filename_queue)
    #3.将example解析为features
    features = tf.parse_single_example(serialized_example,
                                       features = {"label":tf.FixedLenFeature([],tf.int64),
                                                   "img_raw":tf.FixedLenFeature([],tf.string)})
    #4.将features解析为图片数据
    image = tf.decode_raw(features['img_raw'],tf.uint8)
    image = tf.reshape(image,[256,256,3])
    label = tf.cast(features['label'],tf.int32)

    if flag == "train":
        image = tf.cast(image,tf.float32) * (1./255) - 0.5
        img_batch,label_batch = tf.train.batch([image,label],batch_size=batch_size,capacity=20)
        return img_batch,label_batch

    return image,label
TFRecordfilnames = ["mydata.tfrecords"]
image,label = read_and_decode(TFRecordfilnames,flag='test')

save_image_path = "show\\"
if tf.gfile.Exists(save_image_path):
    tf.gfile.DeleteRecursively(save_image_path)
tf.gfile.MakeDirs(save_image_path)

with tf.Session() as sess:
    sess.run(tf.local_variables_initializer())

    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(coord=coord)

    myset = set([])
    try:
        i = 0
        while True:
            example,example_label = sess.run([image,label])
            example_label = str(example_label)
            if example_label not in myset:
                myset.add(example_label)
                tf.gfile.MakeDirs(save_image_path+example_label)
            img = Image.fromarray(example,'RGB')
            img.save(save_image_path+example_label+"\\"+str(i)+'_Label_'+'.jpg')
            print(i)
            i += 1
    except tf.errors.OutOfRangeError:
        print('Done Test -- epoch limit reached')
    finally:
        coord.request_stop()
        coord.join(threads)
        print("stop()")


import sys

if sys.version_info.major >= 3:
	import configparser as ConfigParser
else:
	import ConfigParser
import json

####################### DEFAULT CONFIGURATION ############################

thresholds = [40, 48, 56, 60]
#             ^   ^   ^   ^
#             0   1   2   3

# Set interval of updates
delay = 10 #Seconds

bus = '1'
device = '0x6c'
address = '1'
speeds = ['0', '2', '3', '4', '1']
speedLabels = ['OFF', '25 percent', '50 percent', '75 percent', 'Full speed']
margin = 2

##########################################################################

class ConfigException(Exception):
	def __init__(self, value):
		self.value = value
	def __str__(self):
		return str(self.value)

def getConfig(configPath):
	dirty = False
	Config = ConfigParser.ConfigParser()
	try:
		Config.read(configPath)
	except ConfigParser.InterpolationError:
		raise ConfigException('Invalid config file')

	configHash = {}

	# Global
	if not 'Global' in Config.sections():
		"""
		Config['Global'] = {
				'thresholds': json.dumps(thresholds),
				'delay': delay
		}
		"""
		Config.add_section('Global')
		dirty = True

	try:
		configHash['thresholds'] = json.loads(Config.get('Global', 'thresholds'))
	except ConfigParser.NoOptionError:
		configHash['thresholds'] = thresholds
		#Config['Global']['thresholds'] = json.dumps(thresholds)
		Config.set('Global', 'thresholds', json.dumps(thresholds))
		dirty = True
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	try:
		configHash['delay'] = int(Config.get('Global', 'delay'))
	except ConfigParser.NoOptionError:
		configHash['delay'] = delay
		#Config['Global']['delay'] = delay
		Config.set('Global', 'delay', str(delay))
		dirty = True
	except ValueError:
		raise ConfigException('Invalid value for "delay" option')
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	# Advanced
	if not 'Advanced' in Config.sections():
		"""
		Config['Advanced'] = {
				'bus': bus,
				'device': device,
				'address': address,
				'speeds': json.dumps(speeds),
				'speedLabels': json.dumps(speedLabels),
				'margin': margin
		}
		"""
		Config.add_section('Advanced')
		dirty = True

	try:
		configHash['bus'] = Config.get('Advanced', 'bus')
	except ConfigParser.NoOptionError:
		configHash['bus'] = bus
		#Config['Advanced']['bus'] = bus
		Config.set('Advanced', 'bus', bus)
		dirty = True
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	try:
		configHash['device'] = Config.get('Advanced', 'device')
	except ConfigParser.NoOptionError:
		configHash['device'] = device
		#Config['Advanced']['device'] = device
		Config.set('Advanced', 'device', device)
		dirty = True
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	try:
		configHash['address'] = Config.get('Advanced', 'address')
	except ConfigParser.NoOptionError:
		configHash['address'] = address
		#Config['Advanced']['address'] = address
		Config.set('Advanced', 'address', address)
		dirty = True
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	try:
		configHash['speeds'] = json.loads(Config.get('Advanced', 'speeds'))
	except ConfigParser.NoOptionError:
		configHash['speeds'] = speeds
		#Config['Advanced']['speeds'] = json.dumps(speeds)
		Config.set('Advanced', 'speeds', json.dumps(speeds))
		dirty = True
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	try:
		configHash['speedLabels'] = json.loads(Config.get('Advanced', 'speedLabels'))
	except ConfigParser.NoOptionError:
		configHash['speedLabels'] = speedLabels
		#Config['Advanced']['speedLabels'] = json.dumps(speedLabels)
		Config.set('Advanced', 'speedLabels', json.dumps(speedLabels))
		dirty = True
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	try:
		configHash['margin'] = int(Config.get('Advanced', 'margin'))
	except ConfigParser.NoOptionError:
		configHash['margin'] = margin
		#Config['Advanced']['margin'] = margin
		Config.set('Advanced', 'margin', str(margin))
		dirty = True
	except ValueError:
		raise ConfigException('Invalid value for "margin" option')
	except ConfigParser.InterpolationError as e:
		raise ConfigException('Error in config file. Message was:\n    ' + str(e))

	if dirty:
		with open(configPath, 'w+') as configfile:
			Config.write(configfile)

	return configHash


from flask import Flask

app=Flask(__name__)

@app.route('/')
def index():
    # return '{"a":"a","b":"b"}'
    return  '''
    <note>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Dont forget the meeting!</body>
    </note>
    '''

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


#!/usr/bin/env python3
# -*- кодировка: utf-8 -*-
import math
import sys

if __name__ == '__main__':
    # Ввести список одной строкой.
    A = list(map(int, input().split()))
    # Проверить количество элементов списка.
    if len(A) != 10:
       print("Неверный размер списка", file=sys.stderr)
       exit(1)

# Найти искомую сумму.
s = sum([a for a in A if abs(a) < 5])
print(s)


from typing import Optional

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

class Solution:
    def __init__(self, diameter=0) -> None:
        self.diameter = diameter

    # Calculates depth at a specefic node and updates the diameter
    def find_diam(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0

        left_depth = self.find_diam(root.left)
        right_depth = self.find_diam(root.right)

        self.diameter = max(left_depth + right_depth, self.diameter)

        return 1 + max(left_depth, right_depth)

    def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0

        self.find_diam(root)

        return self.diameter

root = TreeNode(1)
node2 = TreeNode(1)
node3 = TreeNode(1)
node4 = TreeNode(1)
node5 = TreeNode(1)
node6 = TreeNode(1)
node7 = TreeNode(1)
node8 = TreeNode(1)
node9 = TreeNode(1)
node10 = TreeNode(1)
node11 = TreeNode(2)

root.right = node2
node2.right = node3
node3.right = node4
node4.right = node5
node5.right = node6
node6.right = node7
node7.right = node8
node8.right = node9
node9.right = node10
node10.left = node11

print(Solution().diameterOfBinaryTree(root))  # 10


# -*- coding: utf-8 -*-
"""
Created on Sun Dec  1 13:41:17 2019

@author: Scott
"""

in_file = 'E:\Music\Playlists\Test.m3u'
out_file = 'E:\Documents\Coding\Playlist Functions\Test.m3u8'

f = open(in_file,"r")

for line in f:
    x = line.split('\\')
    print(x[3:])


import json
import random
import re
from os import listdir
from os.path import exists, isdir, join as path_join, splitext as path_splitext
from typing import Literal, Union

from omegaconf import OmegaConf, listconfig, dictconfig
from pydantic import Field, validator

from invokeai.app.invocations.baseinvocation import (
    BaseInvocation,
    BaseInvocationOutput,
    InvocationContext,
    invocation,
    invocation_output,
    InputField,
    OutputField,
    UIType,
    WithMetadata,
    WithWorkflow,
)

@invocation_output("lookups_output")
class LookupTableOutput(BaseInvocationOutput):
    """Base class for invocations that output a JSON lookup table"""
    lookups: str = OutputField(default=None, description="The output lookup table")

@invocation_output("halved_prompt_output")
class HalvedPromptOutput(BaseInvocationOutput):
    """Base class for invocations that return a prompt as well as each half independently"""
    prompt: str = OutputField(default="", description="The output prompt")
    part_a: str = OutputField(default="", description="First part of the output prompt")
    part_b: str = OutputField(default="", description="Second part of the output prompt")

@invocation(
    "lookup_table_from_file",
    title="Lookup Table from File",
    tags=["prompt", "lookups", "grammar", "file"],
    category="prompt",
    version="1.1.0",
)
class LookupTableFromFileInvocation(BaseInvocation):
    """Loads a lookup table from a YAML file"""
    file_path: str = InputField(description="Path to lookup table YAML file")

    @validator("file_path")
    def file_path_exists(cls, v):
        if not exists(v):
            raise ValueError(FileNotFoundError)
        return v

    def parsedTemplateLines(self, lines: list):
        "Parse the rows of a template key, creating copies etc."
        results = []
        for line in lines:
            if isinstance(line, str):
                if (0 < len(line)) and (line[0] == "\\"):  # We use backslash to escape parsing
                    results.append(line[1:])
                else:
                    # - N * ..., where N is a number, adds N copies of prompt "..."
                    _match = re.match(r"\s*(\d+)\s*\*\s*(.*)", line)
                    if _match is not None:
                        for i in range(int(_match[1])):
                            results.append(_match[2])
                    # - ?N, where N is a number, is treated as an instruction to add N "empty" choices:
                    elif re.match(r"\?[\d]+$", line):
                        results.extend(["" for number_of_times in range(int(line[1:]))])
                    else:
                        results.append(line)
            elif isinstance(line, listconfig.ListConfig) and (len(line) == 3):
                for i in range(int(line[0])):
                    results.append(line[1:])
            elif isinstance(line, list):
                results.append(line)
            else:
                results.append(OmegaConf.to_object(line))
        return results

    def lookupTableFromFile(self, file_path: str):
        lookup_table = {}
        raw_conf = OmegaConf.load(file_path)
        prompt_section = raw_conf.get("prompt")
        if isinstance(prompt_section, dictconfig.DictConfig):
            for k, v in prompt_section.items():
                # Add singular "template" and "negative" entries
                #  to "templates" and "negatives" lists:
                if (k == "template"):
                    if "templates" not in lookup_table:
                        lookup_table['templates'] = []
                    lookup_table['templates'].extend(self.parsedTemplateLines([v]))
                elif (k == "negative"):
                    if "negatives" not in lookup_table:
                        lookup_table['negatives'] = []
                    lookup_table["negatives"].extend(self.parsedTemplateLines([v]))
                else:
                    if (k not in lookup_table):
                        lookup_table[k] = []
                    lookup_table[k].extend(self.parsedTemplateLines(v))
        return lookup_table

    def invoke(self, context: InvocationContext) -> LookupTableOutput:
        lookups = None
        if isdir(self.file_path):
            lookups = {}
            for pathname in listdir(self.file_path):
                if (not isdir(pathname)) and (path_splitext(pathname)[-1].lower() == ".yaml"):
                    pathname = path_join(self.file_path, pathname)
                    this_lookup_table = self.lookupTableFromFile(pathname)
                    for k, v in iter(this_lookup_table.items()):
                        if k not in lookups:
                            lookups[k] = []
                        lookups[k].extend(v)
        else:
            lookups = self.lookupTableFromFile(self.file_path)
        return LookupTableOutput(lookups=json.dumps(lookups))

@invocation(
    "lookup_from_prompt",
    title="Lookups Entry from Prompt",
    tags=["prompt", "lookups", "grammar"],
    category="prompt",
    version="1.1.0",
)
class LookupsEntryFromPromptInvocation(BaseInvocation):
    """Creates a lookup table of a single heading->value"""
    heading: str = InputField(default=None, description="Heading for the lookup table entry")
    lookup: str = InputField(default="", description="The entry to place under Heading in the lookup table")

    def invoke(self, context:InvocationContext) ->  LookupTableOutput:
        lookups = {}
        lookups[self.heading] = [self.lookup]
        return LookupTableOutput(lookups=json.dumps(lookups))

@invocation(
    "prompt_from_lookup_table",
    title="Prompt from Lookup Table",
    tags=["prompt", "lookups", "grammar"],
    category="prompt",
    version="1.1.0",
)
class PromptFromLookupTableInvocation(BaseInvocation):
    """Creates prompts using lookup table templates"""
    lookups: list[str] = InputField(
        description="Lookup table(s) containing templates (JSON)",
        default_factory=list,
    )
    remove_negatives: bool = InputField(default=False, description="Whether to strip out text between []")
    strip_parens_probability: float = InputField(default=0.0, ge=0.0, le=1.0,
                                            description="Probability of removing attention group weightings")

    @validator("lookups")
    def validate_lookups(cls, v):
        valid = False
        if isinstance(v, list):
            for i in v:
                loaded = json.loads(i)
                if "templates" in loaded:
                    valid = True
                    break
    #    else:
    #        if (not (v is None)) and ("templates" in json.loads(v)):
    #            valid = True
        if (not valid) and (not (len(v) == 0)):
            raise ValueError("'templates' key must be present in lookup table(s)")
        return v

    def templateExpand(self,
                       s :          str,
                       lookups :    dict,
                       reflection : str    = ""):
        "Used internally to replace words with their template lookups. Single pass."
        _split = re.split(r'({[\d:\w]+})', s)
        result = ""
        for word in _split:
            _lookup = None
            if re.fullmatch(r'({\w+})', word):
                _lookup = random.choice(lookups[word[1:-1]])
            else:
                _lookup = word
            if isinstance(_lookup, (list, listconfig.ListConfig)):
                result = result + _lookup[0]
                reflection = " " + _lookup[1] + reflection
            else:
                result = result + _lookup
        return result, reflection

    def cleanup(self, string_in : str):
        "Regex to clean formatting typos occurring during generation (TODO: improve)"
        # Condense whitespace
        _str = re.sub(r"\s+", " ", string_in, 0)
        _str = re.sub(r"\s([,;])\s", lambda match: (match.group(1) + " "), _str, 0)
        # Remove empty sets of parens
        _str = re.sub(r"\(\)[\+\-]*", "", _str)
        # Condense whitespace again
        _str = re.sub(r"\s+", " ", _str, 0)
        _str = re.sub(r"\s([,;])\s", lambda match: (match.group(1) +  " "), _str, 0)
        _str = re.sub(r",+\s", ", ", _str, 0)
        # Now we attempt to combine prefixes and suffixes.
        _collapsed = re.sub(r"(\S+?)\s*@@\s*(\S+)", lambda match: self.prefixer(match.group(1), match.group(2)), _str, 0)
        while _collapsed != _str:
            _str = _collapsed
            _collapsed = re.sub(r"(\S+?)\s*@@\s*(\S+)", lambda match: self.prefixer(match.group(1), match.group(2)), _str, 0)
        # Remove instances of "a apple" errors by subbing "an", w/ or w/o parens in the way.
        string_out = re.sub(
            r"(^[Aa]\s|\s[Aa]\s)([\(]*)([aeiouAEIOU])",
            lambda match: ((" a" if (len(match.group(1))==3) else "a") + "n " + match.group(2) + match.group(3)), _str, 0
        )
        return string_out

    def prefixer(self, a : str, b: str):
        "Attach pre/suffixes (indicated w/'@@') and rearrange parens/+/-"
        result = None
        if re.match(r"[\)\+\-]+$", b):
            result = a + b + " @@"
        else:
            # Allow a single trailing hyphen but move the rest of ), +, -:
            _aWeighting = re.match(r"\S*?(-?)([\)*\+\-]*)\s*$", a)
            _newA = a
            if _aWeighting is not None:
                _newA = a[0:_aWeighting.start(2)]
                _aWeighting = _aWeighting[2]
            # grab parens from the front of b:
            _bWeighting = re.match(r"\s*(\(*)(\S*)", b)
            _newB = b
            if _bWeighting is not None:
                _newB = _bWeighting[2]
                _bWeighting = _bWeighting[1]
            # now subtract the parens that cancel out:
            _newAWeighting = _aWeighting.replace(")", "", _bWeighting.count("("))
            _nSubs = len(_aWeighting) - len(_newAWeighting)
            _newBWeighting = _bWeighting.replace("(", "", _nSubs) if (0 < _nSubs) else _bWeighting
            _raw = _newBWeighting + _newA + _newB + _newAWeighting
            # subtract trailing +-'s that cancel:
            result = _raw.replace("+-", "", 1)
            while _raw != result:
                _raw = result
                result = _raw.replace("+-", "", 1)
        return result

    def invoke(self, context: InvocationContext) -> HalvedPromptOutput:
        lookups = {}
#        if isinstance(self.lookups, list):
        for lookup_table in reversed(self.lookups):
            lookup_table = json.loads(lookup_table)
            for k, v in iter(lookup_table.items()):
                if k not in lookups:
                    lookups[k] = []
                lookups[k].extend(v)
#        else:
#            lookups = json.loads(self.lookups)
        template_strings = lookups['templates']
        base_negatives = lookups['negatives'] if ('negatives' in lookups) else []
        result = None
        appendices = None

        for i in range(1):
            base, reflection = self.templateExpand(random.choice(template_strings), lookups=lookups, reflection="")
            next, reflection = self.templateExpand(base, lookups=lookups, reflection=reflection)
            while ((next != base) or (re.search(r'{\w+}', base))):
                base = next
                next, reflection = self.templateExpand(base, lookups=lookups, reflection=reflection)
            appendices = ""
            while reflection != "":
                appendix = reflection
                next, reflection = self.templateExpand(appendix, lookups=lookups, reflection="")
                while ((next != appendix) or (re.search(r'{\w+}', appendix))):
                    appendix = next
                    next, reflection = self.templateExpand(appendix, lookups=lookups, reflection=reflection)
                appendices = appendices + appendix

            if random.random() < self.strip_parens_probability:
                # Strip off parentheses and pluses, then trailing minuses w/o and w/ commas afterward
                base = re.sub(r"[\(\)+]", "", base, 0)
                base = re.sub(r"\-+\s", " ", base, 0)
                base = re.sub(r"\-+,", ",", base, 0)
                appendices = re.sub(r"[\(\)+]", "", appendices, 0)
                appendices = re.sub(r"\-+\s", " ", appendices, 0)
                appendices = re.sub(r"\-+,", ",", appendices, 0)
            if self.remove_negatives:
                # strip out anything between []
                base = re.sub(r"\[[^\]\[]*\]", "", base, 0)
                appendices = re.sub(r"\[[^\]\[]*\]", "", appendices, 0)

            base = self.cleanup(base)
            appendices = self.cleanup(appendices)

            if not (self.remove_negatives or (not base_negatives)):
                appendices = appendices + " " + random.choice(base_negatives)

            result = (base+appendices).strip()

        return HalvedPromptOutput(prompt=result, part_a=base.strip(), part_b=appendices.strip())


#!/usr/bin/env python

from khemia import MolReader
import argparse

def main():
    parser = argparse.ArgumentParser(description='Convert molecule file')
    parser.add_argument('--in', '-i', type=str, required=True, dest='iname', help='Input file')
    args = parser.parse_args()

    reader = MolReader(args.iname)

    count = 0
    error = 0
    for mol in reader:
        if mol is None:
            error += 1
        else:
            count += 1
    reader.close()

    print('mol: %d, error: %d' % (count, error))

if __name__ == '__main__':
    main()


from math import *

cities_distances = [('X0', 0.0), ("X1", 100.0),
                    ("X2", 200.0), ("X3", 250.0), ("X4", 300.0)]

friends_list = ["A1", "A2", "A3", "A4", "A5"]

friends_location = [("A1", "X1"), ("A2", "X2"), ("A3", "X3"), ("A4", "X4")]

def get_distance(trip):
    distance = 0

    last_place = cities_distances[0]

    for location in trip:
        new_place = list(
            filter(lambda loc: loc[0] == location, cities_distances))[0]

        b = last_place[1]
        c = new_place[1]

        # from the therorem of pythagore
        a = sqrt(c ** 2 - b ** 2)

        distance = distance + ((a) if a > 0 else 0)

        last_place = new_place

    return distance

# print(get_distance(('X0', 'X1', 'X2', 'X3', 'X4', 'X0')))
print(get_distance(('X0', 'X1', 'X2')))


#-*-coding:utf-8-*-
#Lenet-5 model

import torch

import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class LeNet(nn.Module):
    def __init__(self,num_class):
        super(LeNet,self).__init__()
        #input[N,1,28,28]
        #self.conv1 = nn.Conv2d(1,6,5)  # gray image
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.avepool = nn.AvgPool2d(2,2)
        self.conv2 = nn.Conv2d(6,16,5)
        #flatten[N,400]
        #self.fc1 = nn.Linear(400,120)
        self.fc1 = nn.Linear(44944, 120)
        self.fc2 = nn.Linear(120,84)
        self.fc3 = nn.Linear(84,num_class)
    def forward(self,x):
        str0 = x
        x = F.relu(self.conv1(x))
        x = self.avepool(x)
        x = F.relu(self.conv2(x))
        x = self.avepool(x)
        # (64,16,53,53)
        x = x.view((-1,44944))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        #x = F.softmax(self.fc3(x), dim=1)
        x = self.fc3(x)
        return x


# Author: Allen Anker
# Created by Allen Anker on 20/08/2018
"""
You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise).

Note:
You have to rotate the image in-place, which means you have to modify the input 2D matrix directly.
DO NOT allocate another 2D matrix and do the rotation.
"""

class Solution:
    def rotate(self, matrix):
        """
        First reverse up to down, then swap the symmetry ones
        :type matrix: List[List[int]]
        """
        for i in range(len(matrix)//2):
            j = len(matrix) - i - 1
            row = matrix[i]
            matrix[i] = matrix[j]
            matrix[j] = row
        for i in range(len(matrix)):
            for j in range(i):
                temp = matrix[i][j]
                matrix[i][j] = matrix[j][i]
                matrix[j][i] = temp
        pass

solution = Solution()
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
solution.rotate(matrix)


import setuptools

NAME = 'augmentation'
VERSION = '0.0.1'
DESCRIPTION = 'Exploring image augmentation'
AUTHOR = 'greyhypotheses'
URL = 'https://github.com/greyhypotheses/augmentation'
PYTHON_REQUIRES = '=3.7.9'

with open('README.md') as f:
    readme_text = f.read()

setuptools.setup()(
    name=NAME,
    version=VERSION,
    description=DESCRIPTION,
    long_description=readme_text,
    author=AUTHOR,
    url=URL,
    python_requires=PYTHON_REQUIRES,
    package_dir={'': 'src'},
    packages=setuptools.find_packages('src', exclude=['docs', 'tests'])
)


import random

from lib.Const import *

# 食物类, 用于提升坦克能力

class Prop(pygame.sprite.Sprite):

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        # 消灭当前所有敌人
        self.boom = './assets/images/prop/boom.png'
        # 当前所有敌人静止一段时间
        self.clock = './assets/images/prop/clock.png'
        # 使得坦克子弹可碎钢板
        self.gun = './assets/images/prop/gun.png'
        # 使得大本营的墙变为钢板
        self.iron = './assets/images/prop/iron.png'
        # 坦克获得一段时间的保护罩
        self.protect = './assets/images/prop/protect.png'
        # 坦克升级
        self.star = './assets/images/prop/star.png'
        # 坦克生命+1
        self.tank = './assets/images/prop/tank.png'
        # 所有食物
        self.props = [self.boom, self.clock, self.gun,
                      self.iron, self.protect, self.star, self.tank]
        # 是否存在
        self.isDestroyed = False
        self.hit = False
        # 存在时间
        self.times = 1000
        self.kind = random.randint(0, 6)
        # 加载图片
        self.image = pygame.image.load(self.props[self.kind])
        self.rect =  self.rect = self.image.get_rect()
        # 随机坐标
        self.rect.x, self.rect.y = random.randint(100, 500), random.randint(100, 500)

    # 生成道具
    def draw(self):
        if self.times > 0 and not self.isDestroyed:
            self.isDestroyed = False
            self.isHit()
        else:
            self.isDestroyed = True
        # 定时
        self.times -= 1

    def isHit(self):
        if self.hit:
            self.destroy()

    def destroy(self):
        self.isDestroyed = True

    def update(self):
        self.draw()
        if self.isDestroyed:
            self.kill()


#%%
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import pandas as pd
import geopandas as gpd
import wlfun as wl
from arcgis.gis import GIS
import matplotlib.dates as mdates
from pygeostat.data import iotools
from sklearn.linear_model import LinearRegression
from shapely.geometry import Point
import matplotlib
from wlob import wlob
from scipy.spatial import cKDTree
from tqdm import tqdm
import cmcrameri.cm as cmc

sys.path.insert(0,'src')
import config

well_filter = 0
# %%
# Loading relevant shapefiles
# First, we must load some relevant shapefiles. We'll grab California, the Central Valley, the Corcorcan Clay, and the zone map for CVHM (to do: add CV2Sim). I project everything onto Albers as an arbitrary choice, but as long as all crs's for the dataframes align, any geographic projection should be fine.
CA_map = gpd.read_file(config.shapefile_dir / 'CA_State_TIGER2016.shp')
CA_map.to_crs(epsg=config.crs_latlon, inplace=True)

CV_map = gpd.read_file(config.shapefile_dir / 'Alluvial_Bnd.shp')
CV_map.to_crs(epsg=config.crs_latlon, inplace=True)

CC_map = gpd.read_file(config.shapefile_dir / 'corcoran_clay_depth_feet.shp')
CC_map.to_crs(epsg=config.crs_latlon, inplace=True)

#===============================
## Periodic Data
# %%
well_measurements = pd.read_csv(config.data_raw / 'CASGEM/measurements.csv', parse_dates=['msmt_date'])
well_stations = pd.read_csv(config.data_raw /'CASGEM/stations.csv')
well_perforations = pd.read_csv(config.data_raw / 'CASGEM/perforations.csv')

# calling the well object
wlo = wlob(well_stations,well_measurements,well_perforations, CA_map, CV_map, CC_map)

#Read CVHM zone data
zone_map = wlo.get_cvhm_lyr()
zone_map.info()

# %%
#plot study domain
wl.get_cv_map(CA = CA_map,CV = CV_map, corcoran = CC_map, zone_map = None)
# print(well_measurements["wlm_qa_desc"].unique())

# If interested to remove wells with specific comments, such as recent pumping. use following
if well_filter == 1:
    well_stations = wlo.well_filter_qa()
#well_stations.info()

# %%
# combine well perforation, stations, and measurements
well_msp = wlo.well_meas_perfor_combine()
well_msp.head()

#%%
cv_all_sites = wlo.get_well_from_use_region(filter_qa = None, well_use = None, all_wells = 1, CV_map = CV_map, CC_map = None)
cv_obs_sites = wlo.get_well_from_use_region(filter_qa = None, well_use = 'Observation', all_wells = None, CV_map = CV_map, CC_map = None)
cv_ag_sites = wlo.get_well_from_use_region(filter_qa = None, well_use = 'Irrigation', all_wells = None, CV_map = CV_map, CC_map = None)
cv_industry_sites = wlo.get_well_from_use_region(filter_qa = None, well_use = 'Industrial', all_wells = None, CV_map = CV_map, CC_map = None)
cv_resident_sites = wlo.get_well_from_use_region(filter_qa = None, well_use = 'Residential', all_wells = None, CV_map = CV_map, CC_map = None)

#%%
# Process zones and get shallow wells
shallow_wells_all = wlo.get_shallow_wells(zone_map, cv_all_sites,cv_obs_sites, well_type = 'all')
shallow_wells = wlo.get_shallow_wells(zone_map, cv_all_sites,cv_obs_sites, well_type = 'obs')

# thickness files are in meters
shallow_wells["layer1_thk"].describe()
# %%
#plt.figure(figsize=(8,6))

# %%
shallow_measurements = well_msp[well_msp["site_code"].isin(shallow_wells["site_code"])]
shallow_measurements_all = well_msp[well_msp["site_code"].isin(shallow_wells_all["site_code"])]
shallow_measurements.head()

#%%
shallow_measurements_all.to_csv(config.data_processed / 'shallow_wells_all_cvhm.csv')
#%%
st_list = ['351296N1193938W004','361600N1197800W001','362122N1192962W001','362301N1192828W001','362400N1198300W002']
wlo.get_wells_by_aquifer(cv_obs_sites,shallow_wells,st_list)

#%%

# Plot well time series if number of observation is above a threshold
site_codes = list(shallow_measurements["site_code"].unique())
fig = plt.figure(figsize=(16,12))
count = 0
for site_code in site_codes:
    single_well = shallow_measurements[shallow_measurements["site_code"].isin([site_code])]
    single_well = single_well.sort_values(["msmt_date"], ascending=[True])
    if single_well["gse_gwe"].count() > 100:
        plt.plot(single_well["msmt_date"], single_well["gse_gwe"], label=site_codes[count])
        count += 1
    if count == 5:
        break
plt.title('Select Monitoring Wells Time Series', fontsize=20)
plt.ylabel('Depth to Groundwater (ft)', fontsize=16)
plt.setp(plt.gca().get_xticklabels(), rotation=30, horizontalalignment='right')
plt.gca().xaxis.set_major_locator(mdates.YearLocator())
#plt.gca().invert_xaxis()
plt.grid(zorder=0)
plt.legend(fontsize=16)

# %%
wlo.get_well_plot_by_type(cv_sites = cv_resident_sites, well_label = 'Residential')
wlo.get_well_plot_by_type(cv_sites = cv_obs_sites, well_label = 'Observation')
wlo.get_well_plot_by_type(cv_sites = cv_ag_sites, well_label = 'Agricultural')
wlo.get_well_plot_by_type(cv_sites = cv_industry_sites, well_label = 'Industrial')
#%%
wlo.get_well_plot_by_type(cv_sites = cv_all_sites, well_label = 'All')

#----------------------------------
# well interpolation
#----------------------------------

#%%
CA_map = gpd.read_file(config.shapefile_dir / 'CA_State_TIGER2016.shp')
CA_map.to_crs(epsg='4326', inplace=True)

CV_map = gpd.read_file(config.shapefile_dir / 'Alluvial_Bnd.shp')
CV_map.to_crs(epsg='4326', inplace=True)
# %%

# user input
in_path = config.data_processed / 'shallow_wells_all_cvhm.csv'
target_year = '2021'
target_season = 'spring'
monitoring_weight = 0.8
n_realizations = 10000
crs_latlon='epsg:4326' # WGS 84
crs_projected='epsg:3488' # California Albers

x_ = np.arange(-123, -118, 0.10)
y_ = np.arange(34.5, 41, 0.10)
print(len(x_))
print(len(y_))
xx,yy = np.meshgrid(x_,y_,indexing = 'ij')
xx_flat = xx.reshape(-1)
yy_flat = yy.reshape(-1)

meshgrid_points = [Point(xy) for xy in zip(xx_flat,
                                           yy_flat)]
meshgrid_frame = gpd.GeoDataFrame(meshgrid_points, crs=crs_latlon, geometry=meshgrid_points)
# %%
new_binary = mpl.colors.ListedColormap(np.array([[1., 1., 1., 1.],
       [0., 0., 0., 0.]]))
CV_overlay = np.zeros(xx.shape)
CV_geom = CV_map['geometry'].values[0]
for i in tqdm(range(len(CV_overlay))):
    for j in range(len(CV_overlay[0,:])):
        potentialPoint = Point(xx[i,j], yy[i,j])
        if potentialPoint.within(CV_geom):
            CV_overlay[i,j] = 1
# %%
well_measurements = pd.read_csv(in_path, parse_dates=['msmt_date'])
print(len(well_measurements))
site_points = [Point(xy) for xy in zip(well_measurements["longitude"], well_measurements["latitude"])]

well_measurements = gpd.GeoDataFrame(well_measurements, crs=crs_latlon, geometry=site_points)
well_measurements = well_measurements.to_crs(crs_projected)
# %%
if target_season == 'spring':
    start_month = '01'
    mid_month = '03'
    end_month = '06'
else:
    start_month = '06'
    mid_month = '09'
    end_month='12'

mask = ((well_measurements['msmt_date'] > target_year+start_month+'01') &
        (well_measurements['msmt_date'] <= target_year+end_month+'01'))
# %%

timeframed_measurements = well_measurements.loc[mask]
timeframed_measurements = timeframed_measurements[timeframed_measurements['gse_gwe'].notnull()]
# %%

timeframed_measurements = timeframed_measurements[timeframed_measurements['gse_gwe'] > 0]
# %%
timeframed_measurements['drop'] = True
# %%
timeframed_measurements_x = timeframed_measurements['geometry'].x
timeframed_measurements_y = timeframed_measurements['geometry'].y
timeframed_measurements_lat = timeframed_measurements["latitude"]
timeframed_measurements_lon = timeframed_measurements["longitude"]
timeframed_measurements_z = timeframed_measurements['gse_gwe']
timeframed_measurements_type = timeframed_measurements["well_use"]
# %%

meshgrid_frame = meshgrid_frame.to_crs(crs_projected)
# %%

xx_flat = meshgrid_frame['geometry'].x
yy_flat = meshgrid_frame['geometry'].y
xx_yy = np.array((xx_flat,yy_flat)).T

# %%
# Stacking the x, y, and z data together in a new array
timeframed_measurements_xyz = np.vstack((timeframed_measurements_x, timeframed_measurements_y, timeframed_measurements_z)).T
# %%
bootstrap_timeframed_measurements_xyz = np.zeros((n_realizations, int(len(timeframed_measurements_xyz)*0.8), 3))
p_array = np.ones((int(len(timeframed_measurements_xyz))))*(1-monitoring_weight)/len(
    timeframed_measurements_type[timeframed_measurements_type!='Observation'])
p_array[timeframed_measurements_type=='Observation']=monitoring_weight/len(
timeframed_measurements_type[timeframed_measurements_type=='Observation'])
for i in range(len(bootstrap_timeframed_measurements_xyz)):
    bootstrap_indices = np.random.choice(np.arange(len(timeframed_measurements_xyz)),
                                         size=int(len(timeframed_measurements_xyz)*0.8),
                                        replace=False,
                                        p=p_array)
    bootstrap_timeframed_measurements_xyz[i] = timeframed_measurements_xyz[bootstrap_indices]
# %%
bootstrap_IDW = []
for i in tqdm(range(len(bootstrap_timeframed_measurements_xyz))):
    bootstrap_IDW.append(wl.tree(bootstrap_timeframed_measurements_xyz[i,:,:2],
                            bootstrap_timeframed_measurements_xyz[i,:,2]))

#%%
bootstrap_realizations = []
for i in tqdm(range(len(bootstrap_IDW))):
    z = bootstrap_IDW[i](xx_yy)
    bootstrap_realizations.append(z)

# %%
z_mean = np.array(bootstrap_realizations)
z_mean = np.reshape(z_mean, (n_realizations,len(x_),len(y_)))
z_mean = np.mean(z_mean, axis=0)

# %%
z_var = np.array(bootstrap_realizations)
z_var = np.sqrt(np.var(z_var, axis=0))
z_var = np.reshape(z_var, (len(x_),len(y_)))

# %%
fig, ax = plt.subplots(figsize=(15,15))
#CA_map.boundary.plot(ax=ax, zorder=3)
#plt.grid(zorder=2.5, color='k')
CV_map.boundary.plot(ax=ax, zorder=3)
plt.pcolormesh(xx, yy, z_mean, zorder=-2, cmap=cmc.batlow)
#plt.colorbar()
plt.colorbar().set_label(label='Groundwater Depth (ft)',size=20)
#plt.scatter(timeframed_measurements_lon, timeframed_measurements_lat, color='red', s=10)
plt.pcolormesh(xx, yy, CV_overlay, cmap=new_binary, zorder=-1)
plt.title('IDW interpolation: spring 2021 (mean of 10000 realizations)', fontsize=20)
plt.xlabel('Longitude', fontsize=20)
plt.ylabel('Latitude', fontsize=20)

#%%
# Export groundwater depth data
loc_file = f'{config.data_processed}/GWdepth_interpolated'
with open(f'{loc_file}/GWdepth_spring.npy', 'wb') as f:
    np.save(f, z_mean)

with open(f'{loc_file}/X_cv_gwdepth.npy', 'wb') as f:
    np.save(f, xx)
with open(f'{loc_file}/Y_cv_gwdepth.npy', 'wb') as f:
    np.save(f, yy)

# %%
fig, ax = plt.subplots(figsize=(15,15))
#CA_map.boundary.plot(ax=ax, zorder=3)
CV_map.boundary.plot(ax=ax, zorder=4)
plt.pcolormesh(xx, yy, z_var/z_mean, zorder=1, cmap=cmc.batlow)
plt.colorbar().set_label(label='Groundwater Depth Standard Deviation (ft)',size=20)
plt.pcolormesh(xx, yy, CV_overlay, cmap=new_binary, zorder=2)
#plt.scatter(timeframed_measurements_lon, timeframed_measurements_lat, color='red', s=10)
plt.scatter(timeframed_measurements_lon, timeframed_measurements_lat, color='red', s=10)
plt.title('IDW interpolation: spring 2021 variance', fontsize=20)
plt.xlabel('Longitude', fontsize=20)
plt.ylabel('Latitude', fontsize=20)
plt.grid(zorder=0)
#plt.savefig('OK_CV_only_vari.png', dpi=300)
    # %%

#%%
# Find ids for given coordinate
# Convert x y to meshgrid
coord = [-121.00000000000011, 37.50000000000004]

gwd_sel = wl.resistivity_value_from_xy(xx = xx, yy = yy,values = z_mean, coord = coord)
print(gwd_sel)