import os
import re
from PyPDF2 import PdfReader, PdfWriter
from wand.image import Image
from wand.color import Color
from PIL import Image as PImage

def radio_size(w,h,x,model):
    if model == "w":
        return round(w / h * x)
    elif model == "h":
        return round(h / w * x)
    else:
        return round(w / h * x)

def get_img_size(fn, types=True):
    '''
        types = True cm
        types = False pixel
    '''
    img = PImage.open(fn)
    dpi = img.info['dpi'][0]
    if types:
        width, height = map(lambda x: x/dpi*2.54, img.size)
    else:
        width, height = map(lambda x: x, img.size)
    return round(width), round(height), dpi

def split_and_rename_pdfs(input_folder, output_folder):
    # 检查输出文件夹是否存在，如果不存在则创建它
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    # 遍历输入文件夹中的所有文件
    for filename in os.listdir(input_folder):
        if filename.endswith('.pdf'):
            # 构造输入文件路径
            input_path = os.path.join(input_folder, filename)

            # 打开输入的PDF文件
            with open(input_path, 'rb') as file:
                reader = PdfReader(file)
                # 遍历每一页
                for page_number in range(len(reader.pages)):
                    # 创建一个新的PDF写入器
                    writer = PdfWriter()

                    # 获取当前页
                    page = reader.pages[page_number]

                    regex_str = r'限公司(59JF(.?)*)'
                    page_content = page.extract_text()
                    match = re.search(regex_str, page_content)
                    match_str = match.group(1).strip()

                    # 构造输出文件名
                    # output_filename = f"{os.path.splitext(filename)[0]}_page{page_number + 1}.pdf"
                    output_filename = f'{match.group(1).strip()}.pdf'
                    output_path = os.path.join(output_folder, output_filename)
                    if not os.path.exists(output_path):

                        # 将当前页添加到新的PDF文件中
                        writer.add_page(page)

                        # 保存新的PDF文件
                        # if not os.path.exists(output_path):
                        with open(output_path, 'wb') as output_file:
                                writer.write(output_file)

                    if match:
                        extracted_content = match_str

                        # 构造新的文件路径
                        new_filename = f"{extracted_content}.pdf"
                        new_path = os.path.join(output_folder, new_filename)

                        # 重命名文件
                        # Construct the output JPEG filename
                        output_jpeg_filename = f"{os.path.splitext(new_filename)[0]}.jpg"
                        output_jpeg_path = os.path.join('img', output_jpeg_filename)

                        if not os.path.exists(new_path):
                            os.rename(output_path, new_path)

                        if not os.path.exists(output_jpeg_path):
                            # Convert PDF file to JPEG
                            if not os.path.exists('img'):
                                os.makedirs('img')

                            with Image(filename=new_path,resolution = 300) as img:
                                # img.background_color = Color("white")
                                img.alpha_channel = 'remove'
                                img.compression_quality = 100
                                img.resolution = 300
                                img.units = 'pixelsperinch'
                                img.format = 'jpg'

                                img.resize(radio_size(img.width,img.height,1600,"w"),1600)
                                img.crop(height=1500)
                                img.resize(radio_size(img.width,img.height,1600,"w"),1600)

                                # 扩展画布
                                img.extent(width=750,height=1600,gravity="center")

                                # 图片裁切
                                # img.crop(height=1600,top=60)

                                # Save the JPEG image
                                img.save(filename=output_jpeg_path)

                            print(match_str)

# 输入文件夹路径和输出文件夹路径
input_folder = 'data'
output_folder = 'output'

# 调用函数进行分页、提取内容和重命名操作
split_and_rename_pdfs(input_folder, output_folder)


"""
Chapter 4 Graph and Trees
Problem - Minimal Tree: Given a sorted (increasing order) array with unique integer elements,
write an algorithm to create a binary search tree with minimal height.
"""
import sys
sys.path.append('../../DataStructures')
from BinaryTree import Node

def createMinTree(array):

    if len(array) > 1:
        midPt = len(array)//2
        root = Node(array[midPt])
        print(array, array[midPt], midPt, array[:midPt])
        root.left = createMinTree(array[:midPt])
        root.right = createMinTree(array[midPt:])
        return root

def inOrderTraversal(root):
    if root != None:
        inOrderTraversal(root.left)
        print(root.data)
        inOrderTraversal(root.right)

testOrderedArray = [1,2,3,4,5,6,7]
headOfBST = createMinTree(testOrderedArray)
inOrderTraversal(headOfBST)


import hashlib
import hmac
import logging
from urllib.parse import urlencode
from slack.environment_vars import SLACK_SIGNING_SECRET

logger = logging.getLogger()
logger.setLevel(logging.WARNING)

def isVerifiedSlackRequest(
		slack_signature=None,
		slack_request_timestamp=None,
		req_body=None
):
		basestr =  str.encode('v0:' + str(slack_request_timestamp) + ':') + req_body
		new_signature = 'v0=' + hmac.new(
				str.encode(SLACK_SIGNING_SECRET),
				basestr,
				hashlib.sha256
		).hexdigest()

		if hmac.compare_digest(new_signature, slack_signature):
				return True
		else:
				logger.warning('Verification failed. new_signature: {my_signature}, slack_signature: {slack_signature}')
				return False


def decoded_vigenere_char(string_char, key_char):
	string_alphabet = alphabet
	if string_char.isupper():
		string_alphabet = alphabet_upper

	key_alphabet = alphabet
	if key_char.isupper():
		key_alphabet = alphabet_upper

	position = ((string_alphabet.find(string_char) - key_alphabet.find(key_char)) % len(string_alphabet))
	return string_alphabet[position]

# main
alphabet = "abcdefghijklmnopqrstuvwxyz"
alphabet_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

print('Introduzca la cadena a decodificar')
encoded_string = input().strip()

print('Introduzca la clave')
key = input().strip()

decoded_string = ""
for index in range(len(encoded_string)):
	decoded_string += decoded_vigenere_char(encoded_string[index], key[index % len(key)])

print(decoded_string)


"""
Co2 METER

This class keeps track of how much Co2
is being emmited in the experient (roughly) every month
"""

class Co2_Meter:
    def __init__(self) -> None:

        #energe consumed by the household, provided by the grid
        self.total_grid_consumed_house = 0

        #energy lost in battery discharging actions
        self.total_lost_in_out = 0

        #energy lost in battery charging actions
        self.total_lost_in_in = 0

        #energy lost/sold to the grid from batteries
        self.total_lost_to_Grid = 0

        #energy stored in batteries that was provided by the grid
        self.total_grid_in_battery = 0

        #energy stored in batteries that was provided by the solar panels
        self.total_produced_in_battery = 0

        #energy that was stored in the batteries at the last time the meter was run
        self.prev_kWs_batteries = 0

    def reset(self):
        """
        Reset metrics
        """
        self.total_grid_consumed_house = 0
        self.total_lost_in_out = 0
        self.total_lost_in_in = 0
        self.total_grid_in_battery = 0
        self.total_produced_in_battery = 0
        self.total_lost_to_Grid = 0

    def amount_co2(self, stat_batteries, ev_garage):
        """
        Calculate kG of emited co2

        stat_batteries: array with stationary batteries
        ev_garage: obj that will return array with EVs

        returns KG os Co2

        """

        #get total energy stored in batteries and find the % grid source
        totalenergy_batteries = self.total_produced_in_battery + self.total_grid_in_battery

        percentage_gridEnergy_in_battery = self.total_grid_in_battery / totalenergy_batteries \
                                                if totalenergy_batteries > 0 else 0

        #get current energy stored in batteries that came from grid
        #this will be deducted(as it was not consumed)
        curr_kWs_batteries = sum([battery.current_Capacity for battery in stat_batteries] + \
            [ev.battery.current_Capacity for ev in ev_garage.get_All_Vehicles()]) * percentage_gridEnergy_in_battery

        #subtract amount in batteries in the previous co2 meter run
        amortize_batteries = curr_kWs_batteries - self.prev_kWs_batteries
        self.prev_kWs_batteries = curr_kWs_batteries

        #Get energy from grid that was lost in dis/charging actions (therefore not consumed)
        lost_inout_dirty = percentage_gridEnergy_in_battery * (self.total_lost_in_in + self.total_lost_in_out)

        #total grid energy is sum:
        #-consumed by the house from the grid
        #-consumed by the house from batteries that came from grid before being in battery
        total_dirty_energy_consumed = self.total_grid_consumed_house + (self.total_grid_in_battery - \
                                                                        amortize_batteries - \
                                                                        lost_inout_dirty - \
                                                                        self.total_lost_to_Grid * percentage_gridEnergy_in_battery)
        #transform kWh to KG
        return total_dirty_energy_consumed * 0.233

    def update(self, decisions, real_house_consumption):
        """
        Update Metrics Every hour

        decisions: Decision Algorithm decisions
        real_house_consumption: real house consumption

        """

        for charge in range(0, len(decisions), 2):
            #Every charge action as a even index and every discharge action has an odd index
            discharge = charge + 1

            if decisions[discharge].obj == "Grid":  #From Grid

                if decisions[charge].obj == "Consumption":  #To House
                    consumed = min([decisions[charge].energy_amount,real_house_consumption])
                    self.total_grid_consumed_house += consumed
                else: #To Battery
                    self.total_lost_in_in += decisions[charge].energy_amount * 0.02
                    self.total_grid_in_battery += decisions[discharge].energy_amount * 0.98

            elif decisions[discharge].obj == "Production": #From Panels

                if decisions[charge].obj == "Consumption":  #To House
                    pass
                elif decisions[charge].obj == "Grid":   #To Grid
                    pass
                else:   #To battery
                    self.total_lost_in_in += decisions[charge].energy_amount * 0.02
                    self.total_produced_in_battery += decisions[charge].energy_amount * 0.98

            else:   #From battery
                self.total_lost_in_out += decisions[discharge].energy_amount / 0.98  * 0.02

                if decisions[charge].obj != "Consumption":  #To House
                    self.total_lost_in_in += decisions[charge].energy_amount * 0.02
                else: #To Grid
                    consumed = min([decisions[charge].energy_amount,real_house_consumption])
                    self.total_lost_to_Grid += decisions[charge].energy_amount - consumed


import itertools
import re

from django.utils.importlib import import_module

def get_function(path):
    parts = path.split(".")
    module = import_module(".".join(parts[:-1]))
    return getattr(module, parts[-1])

class ChoiceEnum(object):
    def __init__(self, choices):
        if isinstance(choices, basestring):
            choices = choices.split()
        if all([isinstance(choices, (list,tuple)),
                all(isinstance(x, tuple) and len(x) == 2 for x in choices)]):
            values = choices
        else:
            values = zip(itertools.count(1), choices)
        for v, n in values:
            name = re.sub('[- ]', '_', n.upper())
            setattr(self, name, v)
            if isinstance(v, str):
                setattr(self, v.upper(), v)
        self._choices = values

    def __getitem__(self, idx):
        return self._choices[idx]

    def getdisplay(self, key):
        return [v[1] for v in self._choices if v[0] == key][0]


# This python script takes in the price history dictionary from a pickle file.
# price_history[ticker]=[minute level opening price data]
# This estimates what profit we would get if we buy at particular percent from original price and sell at another percent of original price.

#There are three different algorithms I am testing. All algorithms use the following behavior:
#   - It sells the same stock if it jumps up to sell percent above the average buy price using a limit order
#   - It buys the same stock if it falls to buy percent below a certain price. It can re-buy the same stock 3-4 times.
#   - It re-calculates limit order sell price to be a total profit of sell percent above the average buy price.

# Max Price Algorithm
#   - It keeps track of the max price of the stock since we last sold it. It updates a buy order to buy_percent below the max price if max price went up by more than 1 percent.
#   - This keeps the bot in the range of the stock so that it can keep buying and selling (prevents a bot from having a sitting buy order if there is a large jump in price)

# Keep Some Algorithm
#   - The algorithm always owns some of the stock. It sets optimal buy and sell orders
#   - Works the same as max price, it just never fully sells all of stock.

# New Buy Percent Algorithm
#   - It sets a buy price at new buy percent below last purchase price

import pandas as pd
import time
import pickle
from mpl_toolkits import mplot3d
import matplotlib.pyplot as plt

def new_buy_algo(price,buy_order,sell_order,buy_proportion,sell_proportion,new_buy_proportion,num_buys,max_buys,profit_proportion):
    """
    Estimates profit if we buy stock at new_buy_proportion below last sell price, buy again at buy percent below previous buy price, and
    sell at sell_proportion above average buy price.
    Pass in the latest price and algorithm will determine if orders were filled, what new orders to place, and profit obtained

    price - current price of stock
    buy_order - the price that we buy more stock (0 if no buy orders)
    sell_order - the price that we sell the stock (0 if no sell orders)
    buy_proportion - the proportion below the last buy price for a new buy order
    sell_proportion - the propoartion above the average buy price for a new sell order
    new_buy_proportion - the proportion below the last sell price for a new buy order
    num_buys - the number of times we bought the stock so far
    max_buys - the number of times we are allowed to buy the same stock
    profit_proportion - the profit we have obtained so far

    Returns num_buys, buy_order, sell_order, and profit proportion
    """
    if buy_order>0 and price<=buy_order:
        #Our buy order was successfully placed
        num_buys+=1

        total_buy=0
        #Re-calculate sell price
        for i in range(num_buys):
            #What is the total amount spent on buy orders thus far
            total_buy += buy_order*(1+buy_proportion)**i
        average_buy = total_buy/num_buys

        sell_order = average_buy*(1+sell_proportion)

        if num_buys<max_buys:
            #Calculate new buy order price
            buy_order = buy_order*(1-buy_proportion)
        else:
            buy_order = 0

    if sell_order>0 and price>=sell_order:
        #Our sell order was successfully placed
        profit_proportion += num_buys/max_buys*sell_proportion

        buy_order = sell_order*(1-new_buy_proportion)
        sell_order = 0
        num_buys = 0

    return (num_buys,buy_order,sell_order,profit_proportion)

def max_price_algo(price,buy_order,sell_order,buy_proportion,sell_proportion,new_buy_proportion,num_buys,max_buys,profit_proportion,calc_proportion):
    """
    Estimates profit if we buy stock at new_buy_proportion below max price since last sell, buy again at buy percent below previous buy price, and
    sell at sell_proportion above average buy price.
    Pass in the latest price and algorithm will determine if orders were filled, what new orders to place, and profit obtained

    price - current price of stock
    buy_order - the price that we buy more stock (0 if no buy orders)
    sell_order - the price that we sell the stock (0 if no sell orders)
    buy_proportion - the proportion below the last buy price for a new buy order
    sell_proportion - the propoartion above the average buy price for a new sell order
    new_buy_proportion - the proportion below the last sell price for a new buy order
    num_buys - the number of times we bought the stock so far
    max_buys - the number of times we are allowed to buy the same stock
    profit_proportion - the profit we have obtained so far
    calc_proportion - if max price increases by this proportion, re-calculate the buy order

    Returns num_buys, buy_order, sell_order, and profit proportion
    """
    if buy_order>0 and price<=buy_order:
        #Our buy order was successfully placed
        num_buys+=1

        total_buy=0
        #Re-calculate sell price
        for i in range(num_buys):
            #What is the total amount spent on buy orders thus far
            total_buy += buy_order*(1+buy_proportion)**i
        average_buy = total_buy/num_buys

        sell_order = average_buy*(1+sell_proportion)

        if num_buys<max_buys:
            #Calculate new buy order price
            buy_order = buy_order*(1-buy_proportion)
        else:
            buy_order = 0

    if sell_order>0 and price>=sell_order:
        #Our sell order was successfully placed
        profit_proportion += num_buys/max_buys*sell_proportion

        buy_order = sell_order*(1-new_buy_proportion)
        sell_order = 0
        num_buys = 0

    #If we haven't bought any stock yet and the price increases above calc_proportion, re-caculate buy order
    if num_buys==0 and price*(1-new_buy_proportion)>buy_order*(1+calc_proportion):
        buy_order = price*(1-new_buy_proportion)

    return (num_buys,buy_order,sell_order,profit_proportion)

def new_buy_zero(price,buy_order,sell_order,buy_proportion,sell_proportion,num_buys,max_buys,profit_proportion,calc_proportion,last_sell):
    """
    This assumes new_buy_proportion is zero. It won't ever sell all of stock.
    Estimates profit if we buy again at buy percent below previous buy price, and
    sell at sell_proportion above average buy price.
    Pass in the latest price and algorithm will determine if orders were filled, what new orders to place, and profit obtained

    price - current price of stock
    buy_order - the price that we buy more stock (0 if no buy orders)
    sell_order - the price that we sell the stock (0 if no sell orders)
    buy_proportion - the proportion below the last buy price for a new buy order
    sell_proportion - the propoartion above the average buy price for a new sell order
    num_buys - the number of times we bought the stock so far
    max_buys - the number of times we are allowed to buy the same stock
    profit_proportion - the profit we have obtained so far
    calc_proportion - if max price increases by this proportion, re-calculate the buy order (set to zero if we don't want to change buy order)
    last_sell - the last price the stock was sold at. If last sell is zero, set this equal to the first buy price

    Returns num_buys, buy_order, sell_order, profit proportion, and last_sell
    """
    if buy_order>0 and price<=buy_order:
        #Our buy order was successfully placed
        num_buys+=1

        total_buy=0
        #Re-calculate sell price
        for i in range(num_buys):
            #What is the total amount spent on buy orders thus far
            total_buy += buy_order/(1-buy_proportion)**i
        average_buy = total_buy/num_buys

        sell_order = average_buy*(1+sell_proportion)

        if num_buys<max_buys:
            #Calculate new buy order price
            buy_order = buy_order*(1-buy_proportion)
        else:
            buy_order = 0

    if sell_order>0 and price>=sell_order:
        #Our sell order was successfully placed
        profit_proportion += num_buys/max_buys*sell_proportion

        buy_order = sell_order*(1-buy_proportion)
        last_sell = sell_order
        sell_order = 0
        num_buys = 1 #Assume we don't sell all of stock

    #If we only have 1 buy and price increases by calc proportion, change buy order
    if num_buys==1 and calc_proportion>0 and price>last_sell*(1+calc_proportion):
        buy_order = price*(1-buy_proportion)
        profit_proportion += 1/max_buys*calc_proportion
        last_sell = price

    #For calc proportion equal to zero, re-calculate at the sell proportion
    if num_buys==1 and calc_proportion==0 and price>last_sell*(1+sell_proportion):
        buy_order = price*(1-buy_proportion)
        profit_proportion += 1/max_buys*sell_proportion
        last_sell = price

    return (num_buys,buy_order,sell_order,profit_proportion,last_sell)

if __name__=="__main__":
    file_name = 'save.p'

    price_history = pickle.load(open("Price_History_April3_May15.p","rb"))

    test_tickers = ['ASTC']

    #test_tickers = ['MSFT']
    #Number of times we allow the bot to re-buy the same stock without any sells
    max_buys = 3
    profit_ticker_percent = {}

    buy_percent = []
    new_buy_percent = []

    update_x=True

    #Calc Proportion to Test for new_buy_proportion = 0
    new_buy_zero_calc = [0,0.02,0.05,0.1,0.2,0.3,0.5,1]

    #New buy proportions to test
    new_buy_proportions = [0]

    #Max price new buy proportions to test
    max_price_new_buys = [0]
    #Max price calc proportion to test
    calc_proportion = 0.01

    #Total algorithms we are running
    total_algos = len(new_buy_zero_calc)+len(new_buy_proportions)+len(max_price_new_buys)

    #Get the profit for each ticker
    for ticker in test_tickers:

        for y in range(20):

            sell_proportion = y*0.5/100+1/100

            #Reset profits before trying out new sell percent
            profit_ticker_percent[ticker] = []
            for i in range(total_algos):
                profit_ticker_percent[ticker].append([])

            if len(buy_percent) > 0:
                update_x = False

            #Create a 2-D plot of profit buy_percent for each sell percent
            for x in range(200):

                #Buy percent ranges from 0.5% buy below previous sell to 10%
                buy_proportion = x*0.1/100+0.5/100

                index=0
                #Buy order - the new price for us to buy stock
                buy_order = [price_history[ticker][index]] * total_algos
                #Sell order - the new price for us to sell stock (start at zero because we don't own stock)
                sell_order = [0] * total_algos
                #num buys - the total number of buys we have without any sells
                num_buys = [0] * total_algos
                profit_proportion = [0] * total_algos
                #Last sell is used for new buy zero calculations
                last_sell = [price_history[ticker][index]] * len(new_buy_zero_calc)

                #Loop for each price in price_history
                while index < len(price_history[ticker]):

                    price = price_history[ticker][index]

                    #For each new calc proportion for new buy zero, run the new_buy_zero algorithm
                    for i in range(len(new_buy_zero_calc)):
                        (num_buys[i],buy_order[i],sell_order[i],profit_proportion[i],last_sell[i]) = new_buy_zero(price,buy_order[i],sell_order[i],buy_proportion,sell_proportion,num_buys[i],max_buys,profit_proportion[i],new_buy_zero_calc[i],last_sell[i])

                    #For each new buy proportion, run the new_buy algorithms
                    for j in range(len(new_buy_proportions)):
                        k = j + len(new_buy_zero_calc) #get the index right for variables shared with new_buy_zero algorithm
                        (num_buys[k],buy_order[k],sell_order[k],profit_proportion[k]) = new_buy_algo(price,buy_order[k],sell_order[k],buy_proportion,sell_proportion,new_buy_proportions[j],num_buys[k],max_buys,profit_proportion[k])

                    #For each new buy proportion, run the new_buy algorithms
                    for j in range(len(max_price_new_buys)):
                        k = j + len(new_buy_zero_calc) + len(new_buy_proportions) #get the index right for variables shared with new_buy_proportion algorithm
                        #Max price algorithm with new_buy_proportion = 0.25/100 and calc_proportion = 0.01
                        (num_buys[k],buy_order[k],sell_order[k],profit_proportion[k]) = max_price_algo(price,buy_order[k],sell_order[k],buy_proportion,sell_proportion,max_price_new_buys[j],num_buys[k],max_buys,profit_proportion[k],calc_proportion)

                    index+=1

                last_price = price_history[ticker][-1]
                #For new_buy_zero calcs, set profit based on ending price.
                for i in range(len(new_buy_zero_calc)):
                    profit_proportion[i] -= (1/max_buys)*(last_sell[i]-last_price)/last_sell[i]

                for i in range(total_algos):
                    profit_ticker_percent[ticker][i].append(profit_proportion[i]*100)
                if update_x:
                    buy_percent.append(buy_proportion*100)

                """
                print('-------------------------------------------------------------')
                print('{} had a profit percent of {}.'.format(ticker,profit_ticker_percent[ticker]/buys_allowed))
                print('The number times we bought and sold was {}.'.format(times_sold))
                print('The last price is {}, and the last buy average was {}.'.format(last_price,average_buy))
                print('-------------------------------------------------------------')
                """

                #total_profit_percent = sum(profit_ticker_percent.values())/buys_allowed
                #print('Total percent profit:  {}'.format(total_profit_percent))
                #print('Average percent profit:  {}'.format(total_profit_percent/len(test_tickers)))

            fig = plt.figure()

            #Plot results of each new_buy_zero_calc algorithm
            for index in range(len(new_buy_zero_calc)):
                plt.plot(buy_percent,profit_ticker_percent[ticker][index],label="zero = {}".format(new_buy_zero_calc[index]*100))

            #Plot results of each new_buy_proportion algorithm
            for index in range(len(new_buy_proportions)):
                index2 = index+len(new_buy_zero_calc)
                plt.plot(buy_percent,profit_ticker_percent[ticker][index2],label="new = {}".format(new_buy_proportions[index]*100))

            #Plot results of each max_price algorithm
            for index in range(len(max_price_new_buys)):
                index2 = index+len(new_buy_proportions)+len(new_buy_zero_calc)
                plt.plot(buy_percent,profit_ticker_percent[ticker][index2],label="max = {}".format(max_price_new_buys[index]*100))

            plt.xlabel('Buy Percent')
            plt.ylabel('Profit')
            plt.title('Sell Percent = {}'.format(sell_proportion*100))
            plt.legend()
            plt.show()

    """
    pickle.dump(profit_ticker_percent,open("PofitbyPercent_BuyNewBuy_April3_May15_3_SGBX.p","wb"))
    pickle.dump(buy_percent,open("BuyPercent_SGBX.p","wb"))
    pickle.dump(new_buy_percent,open("NewBuyPercent_SGBX.p","wb"))
    """


from models.PageBugClassfier import PageBugClassfier
import numpy as np

classfier = PageBugClassfier()

classfier.fit(np.array([
  ["Valid","ONE","TWO","THREE"],
  ["INVALID","ONE","THREE","FIVE"],
  ["INVALID","ONE","FOUR","THREE"],
  ["INVALID","ONE","TWO","FOUR"]
]))

predections = classfier.predict([["ONE","THREE","ONE"]])

print(predections)


#! /usr/bin/env python3
###############################################################################
#                                                                             #
# GALORE: Gaussian and Lorentzian broadening for simulated spectra            #
#                                                                             #
# Developed by Adam J. Jackson and Alex Ganose                                #
# at University College London (2018)                                         #
#                                                                             #
###############################################################################
#                                                                             #
# This file is part of Galore. Galore is free software: you can redistribute  #
# it and/or modify it under the terms of the GNU General Public License as    #
# published by the Free Software Foundation, either version 3 of the License, #
# or (at your option) any later version.  This program is distributed in the  #
# hope that it will be useful, but WITHOUT ANY WARRANTY; without even the     #
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    #
# See the GNU General Public License for more details.  You should have       #
# received a copy of the GNU General Public License along with this program.  #
# If not, see <http://www.gnu.org/licenses/>.                                 #
#                                                                             #
###############################################################################
from argparse import ArgumentParser
from itertools import cycle

import logging
import numpy as np
from matplotlib import pyplot as plt
plt.style.use('seaborn-colorblind')

from galore.cross_sections import get_cross_sections_scofield

def main():
    parser = get_parser()
    args = parser.parse_args()
    args = vars(args)
    run(**args)

def get_parser():
    parser = ArgumentParser()
    parser.add_argument('--emin', type=float, default=1,
                        help="Minimum energy in keV")
    parser.add_argument('--emax', type=float, default=20,
                        help="Maximum energy in keV")
    parser.add_argument('--megabarn', action='store_true',
                        help="Set y-axis unit to megabarn/electron")
    parser.add_argument('--size', type=float, nargs=2, default=None,
                        help="Figure dimensions in cm")
    parser.add_argument('--output', '-o', type=str, default=None,
                        help="Output filename. If not given, plot to screen.")
    parser.add_argument('--fontsize', type=int, default=12,
                        help="Font size in pt")
    parser.add_argument(
        '--style', type=str, nargs='+', default=['seaborn-colorblind'],
        help='Plotting style: a sequence of matplotlib styles and paths to '
             'style files. The default palette is called "seaborn-colorblind".'
        )
    parser.add_argument('elements', type=str, nargs='+', help="""
        Space-separated symbols for elements in material.""")

    return parser

def run(elements, emin=1, emax=10, megabarn=False, size=None, output=None,
        fontsize=10, style=None):
    energies = np.linspace(emin, emax, 200)
    cross_sections = get_cross_sections_scofield(energies, elements)

    if style is not None:
        plt.style.use(style)

    if size is None:
        fig = plt.figure()
    else:
        size_inches = [float(x) / 2.54 for x in size]
        fig = plt.figure(figsize=size_inches)

    ax = fig.add_subplot(1, 1, 1)

    colors = cycle(('C0', 'C1', 'C2', 'C3', 'C4'))
    markers = cycle(('o', '^', 'D', 'x', '*'))

    if megabarn:
        unit = "Mb"
        conversion = 1E6
    else:
        unit = "barn"
        conversion = 1

    for element in elements:
        color, marker = next(colors), next(markers)
        linestyles = cycle((['-', '--', ':', '-.']))

        if 'warning' in cross_sections[element]:
            logging.warning("  {0}: {1}".format(
                element, cross_sections[element]['warning']))

        for orbital in 'spdf':
            if (orbital in cross_sections[element] and
                    cross_sections[element][orbital] is not None):
                ax.plot(energies,
                        cross_sections[element][orbital] / conversion,
                        color=color, linestyle=next(linestyles),
                        marker=marker, markevery=40,
                        label='{0}-{1}'.format(element, orbital),
                        markersize=5)

    ax.tick_params(labelsize=(fontsize - 2))
    ax.set_xlabel('Photon energy / keV', fontsize=fontsize)
    ylabel = ('Photoionization cross-section /'
              ' {} electron$^{{-1}}$'.format(unit))
    ax.set_ylabel(ylabel, fontsize=fontsize)
    ax.set_yscale('log')
    ax.legend(loc='lower right', fontsize=fontsize)
    fig.subplots_adjust(right=0.98, top=0.98)

    if output is None:
        plt.show()
    else:
        fig.savefig(output, bbox_inches='tight')

if __name__ == '__main__':
    main()


import random

#create a function that picks numbers 0-9 and add them
#to the list randomly, if the number isn't in the list, don't add the number

def SuperBowlNumbers():
		superBowlLine = []
		while len(superBowlLine) < 10:
			r = random.randint(0,9)
			if r in superBowlLine:
				print("Not adding duplicates.")
			else:
				superBowlLine.append(r)
			#if not in list append, else don't do anything
		print(superBowlLine)

SuperBowlNumbers()
#Bengals are X-axis
SuperBowlNumbers()
#Rams are Y-axis


import subprocess
import time
import os

class Command(object):
    path = ""
    env = {}

    def __init__(self, path=None):
        if path is None:
            self.path = os.getcwd()
        else:
            self.path = path

        kubeconfig = os.getenv("KUBECONFIG")
        assert kubeconfig is not None, "KUBECONFIG needs to be set in the environment"
        self.setenv("KUBECONFIG", kubeconfig)

        path = os.getenv("PATH")
        assert path is not None, "PATH needs to be set in the environment"
        self.setenv("PATH", path)

    def setenv(self, key, value):
        assert key is not None and value is not None, f"Name or value of the environment variable cannot be None: [{key} = {value}]"
        self.env[key] = value

    def run(self, cmd, stdin=None):
        output = None
        exit_code = 0
        try:
            if stdin is None:
                output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, cwd=self.path, env=self.env)
            else:
                output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, cwd=self.path, env=self.env, input=stdin.encode("utf-8"))
        except subprocess.CalledProcessError as err:
            output = err.output
            exit_code = err.returncode
            print('ERROR MESSGE:', output)
            print('ERROR CODE:', exit_code)
        return output.decode("utf-8"), exit_code

    def run_wait_for_status(self, cmd, status, interval=20, timeout=180):
        cmd_output = None
        exit_code = -1
        start = 0
        while ((start + interval) <= timeout):
            cmd_output, exit_code = self.run(cmd)
            if status in cmd_output:
                return True, cmd_output, exit_code
            time.sleep(interval)
            start += interval
        print("ERROR: Time out while waiting for status message.")
        return False, cmd_output, exit_code

    def run_wait_for(self, resource_type, resource_name, wait_for="condition=Available", timeout_seconds=180):
        cmd = "oc  wait --for={} --timeout={}s {} {}".format(wait_for, timeout_seconds, resource_type, resource_name)
        output, exit_code = self.run(cmd)
        return output, exit_code


# import the BME680 library for RPI
import bme680

# import time library for delay purposes
import time

# import datetime library for timestamp
from datetime import datetime

# initialise the sensor
sensor = bme680.BME680()

# define the sampling rate for individual paramters
sensor.set_humidity_oversample(bme680.OS_2X)
sensor.set_pressure_oversample(bme680.OS_4X)
sensor.set_temperature_oversample(bme680.OS_8X)

# filter out noises
sensor.set_filter(bme680.FILTER_SIZE_3)

# loop to read data
while True:
    # if data is available
    if sensor.get_sensor_data():
        now  = datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)")
        pres = sensor.data.pressure
        hum = sensor.data.humidity
        temp = sensor.data.temperature
        print(now, temp, pres,hum)

        #if sensor.data.heat_stable:
        #    output += f", {sensor.data.gasresitance} ohms"
        #print(output)

        time.sleep(5)


#!/usr/bin/env python3
"""Class Transformer"""
import tensorflow as tf
Encoder = __import__('9-transformer_encoder').Encoder
Decoder = __import__('10-transformer_decoder').Decoder

class Transformer(tf.keras.Model):
    """Class Transformer"""
    def __init__(self, N, dm, h, hidden, input_vocab, target_vocab,
                 max_seq_input, max_seq_target, drop_rate=0.1):
        """Class Constructor"""
        super(Transformer, self).__init__()
        self.encoder = Encoder(N, dm, h, hidden,
                               input_vocab, max_seq_input, drop_rate)
        self.decoder = Decoder(N, dm, h, hidden,
                               target_vocab, max_seq_target, drop_rate)
        self.linear = tf.keras.layers.Dense(target_vocab)

    def call(self, inputs, target, training, encoder_mask, look_ahead_mask,
             decoder_mask):
        """Public instance method that returns a tensor of shape
        (batch,target_seq_len, target_vocab) containing the
        transformer output"""
        enc_output = self.encoder(inputs, training, encoder_mask)
        dec_output = self.decoder(target, enc_output, training,
                                  look_ahead_mask, decoder_mask)
        final_output = self.linear(dec_output)
        return final_output


import copy
from Number import Number
import help

class State:
    def __init__(self):
        self.list = [] # list of list of object Number
        self.remaining = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # list of remaining integer 0-9 which is not used yet

    # Getter and Setter
    def getList(self):
        return self.list
    def getRemaining(self):
        return self.remaining
    def copyList(self, input_list):
        self.list = copy.deepcopy(input_list)
    def copyRemaining(self, input_list):
        self.remaining = copy.deepcopy(input_list)
    def removeRemaining(self, idx):
        return self.remaining.remove(idx)

    # Assigning (with pop) value from self.remaining[idx]
    def assigning(self, idx):
        for i in range(0, len(self.getList()[-1])):
            for e in self.getList():
                if (i < len(e)):
                    if (not e[i].isSetByValue()):
                        e[i].setValue(idx)
                        self.removeRemaining(idx)
                        return 0

    # Return other childs of this state
    # Child has one more than its parent which is assigned from remaining to list
    def childs(self):
        childs = []

        for i in self.getRemaining():
            child = State()
            child.copyList(self.getList())
            child.copyRemaining(self.getRemaining())

            child.assigning(i)
            childs.append(child)

        return childs

    # Return maximum index i which satisfy the condition
    # the condition: all element (list) in self.getList() at index i is input by value or len(list)-1 < levelDOne()
    def levelDone(self):
        lili = []
        level = 0
        while level < len(self.getList()[-1]) and self.getList()[-1][level].isSetByValue():
            level +=1
        lili.append(level-1)
        for li in self.getList():
            level = 0
            while level < len(li) and li[level].isSetByValue():
                level +=1
            if not level == len(li):
                lili.append(level-1)
        return min(lili)

    # Return true if there is no rules break
    def isGood(self):
        listX = []
        level = self.levelDone()
        for li in self.getList():
            if li[-1].isSetByValue() and li[-1].getValue()==0:
                return False

            if len(li) <= level:
                listX.append(li[:])
            else:
                listX.append(li[:level+1])
        return help.isRight(listX)


from werkzeug.routing import BaseConverter, ValidationError

_users = [
    {'id': '1', 'username': 'Admin'},
    {'id': '2', 'username': 'Stone'}
]

def find_user(userid):
    for user in _users:
        if userid == user['id']:
            return user

class ValidUserConverter(BaseConverter):

    def to_python(self, value):
        if not find_user(value) is None:
            return find_user(value)['username']
        raise ValidationError()


# vim: set sts=4 ts=8 sw=4 tw=99 et:

def LineHasContinuation(line):
    num_escapes = 0

    pos = len(line) - 1
    while pos >= 0:
        if line[pos] != '\\':
            break
        num_escapes += 1
        pos -= 1

    return num_escapes % 2 == 1

def Preprocess(lines):
    chars = ''

    ignoring = False
    for line in lines:
        if line.endswith('\n'):
            line = line[:len(line) - 1]
        has_continuation = LineHasContinuation(line)
        if has_continuation:
            if ignoring:
                continue
            if line.startswith('#'):
                ignoring = True
                continue
            chars += line[:len(line) - 1]
        else:
            ignoring = False
            if line.startswith('#'):
                continue
            chars += line
    return chars

class Parser(object):
    def __init__(self, fp):
        self.chars_ = Preprocess(fp.readlines())
        self.pos_ = 0

    def parse(self):
        while True:
            tok = self.lex(':')
            if tok is None or tok == ':':
                break
            if tok == '\n' or tok == '\r':
                raise Exception('Unexpected newline in make dependency rules')

        if tok is None:
            raise Exception('No Makefile dependency rules found')

        self.pos_ += 1

        items = []
        while True:
            tok = self.lex()
            if tok == '\n' or tok == '\r' or tok is None:
                break
            if tok.isspace():
                continue
            items.append(tok)
        return items

    def lex(self, stop_token = None):
        token = self.peek()
        if token is None:
            return None
        self.pos_ += 1

        if token.isspace():
            return token

        while True:
            c = self.peek()
            if c is None or c == stop_token or c.isspace():
                break
            self.pos_ += 1
            if c == '\\':
                next_char = self.peek()
                if next_char is None:
                    token += '\\'
                    continue
                token += next_char
                self.pos_ += 1
            else:
                token += c

        return token

    def skip_newline(self, c):
        if c == '\r':
            self.pos_ += 1
            if self.peek() == '\n':
                self.pos_ += 1
            return True
        if self.peek() == '\n':
            self.pos_ += 1
            return True
        return False

    def peek(self):
        if self.pos_ >= len(self.chars_):
            return None
        return self.chars_[self.pos_]

def ParseDependencyFile(filename, fp):
    p = Parser(fp)
    return p.parse()


def año_biciesto(year):
    if year % 4 != 0:
        return False
    elif year % 100 !=0:
        return True
    elif year % 400 !=0:
        return False
    else:
        return True

if año_biciesto(int(input('Ingrese el año '))) == True:
    print('El año es año biciesto')

else:
    print('El año no es biciesto')


import numpy as np

class NaiveBayes:
    def fit(self, X, y):
        # get number of samples (rows) and features (columns)
        self.amostras, self.n_caracteristicas = X.shape
        # get number of uniques classes
        self.classes = len(np.unique(y))

        # create three zero-matrices to store summary stats & prior
        self.medias = np.zeros((self.classes, self.n_caracteristicas))
        self.variancias = np.zeros((self.classes, self.n_caracteristicas))
        self.prioris = np.zeros(self.classes)

        for c in range(self.classes):
            # create a subset of data for the specific class 'c'
            X_c = X[y == c]

            # calculate statistics and update zero-matrices, rows=classes, cols=features
            self.medias[c, :] = np.mean(X_c, axis=0)
            self.variancias[c, :] = np.var(X_c, axis=0)
            self.prioris[c] = X_c.shape[0] / self.amostras

    def predict(self, X):
        # for each sample x in the dataset X
        y_hat = [self.get_class_probability(x) for x in X]
        return np.array(y_hat)

    def gaussiana(self, x, mean, var):
        # implementation of gaussian density function
        const = 1 / np.sqrt(var * 2 * np.pi)
        proba = np.exp(-0.5 * ((x - mean) ** 2 / var))

        return const * proba

    def get_class_probability(self, x):
        # store new posteriors for each class in a single list
        verossimilhanças = list()

        for c in range(self.classes):
            # get summary stats & prior
            media = self.medias[c]
            variancia = self.variancias[c]
            priori = np.log(self.prioris[c])

            # calculate new posterior & append to list
            verossimilhança = np.sum(np.log(self.gaussiana(x, media, variancia)))
            verossimilhança = priori + verossimilhança
            verossimilhanças.append(verossimilhança)

        # return the index with the highest class probability
        return np.argmax(verossimilhanças)

    def accuracy(self, predictions: np.ndarray, y: np.ndarray) -> float:
        return np.sum(predictions == y) / predictions.shape[0]


sourcefile = "Cell_Phones_&_Accessories.txt"
filename2 = "training_data.txt"

offending = ["review/text","review/score"]

def fixup( filename ):
    fin = open( filename )
    fout = open( filename2 , "w")
    for line in fin:
        if True in [item in line for item in offending]:
        	fout.write(line)
    fin.close()
    fout.close()

fixup(sourcefile)


from pprint import pprint
import numpy as np

sequ1 = "ACCGAAGTAC"
sequ2 = "AGAGGTAC"
LEFT = "--"
UP = "||"
DIAG = "\\"

def dir(left, diag, up, x, y):
    if left > diag and left > up:
        return left, LEFT
    if up > diag and up > left:
        return up, UP
    if diag > left and diag > up:
        return diag, DIAG
    if left == up and up > diag:
        if x < y:
            return up, UP
        else:
            return left, LEFT

    if left == diag and diag > up:
        if x > y:
            return left, LEFT
        else:
            return diag, DIAG

    if diag == up and up > left:
        if x < y:
            return up, UP
        else:
            return diag, DIAG

    if left == up == diag:
        if x > y:
            return left, LEFT
        elif x < y:
            return up, UP
        else:
            return diag, DIAG

    return diag, DIAG

def needleman(sequ2, sequ1, match=3, mismatch=-2, gap=-1):
    score = np.full((len(sequ1) + 1, len(sequ2) + 1), 0)
    direction = np.full((len(sequ1) + 1, len(sequ2) + 1), "NONE")

    for y in range(0, len(score)):
        for x in range(0, len(score[0])):
            if y == 0:
                direction[y][x] = LEFT
                score[y][x] = -1 * x
            if x == 0:
                direction[y][x] = UP
                score[y][x] = -1 * y

    direction[0][0] = DIAG

    for y in range(1, len(score)):
        for x in range(1, len(score[0])):
            left = score[y][x - 1] + gap
            up = score[y - 1][x] + gap
            diag = 0
            if sequ1[y - 1] == sequ2[x - 1]:
                diag = score[y - 1][x - 1] + match
            else:
                diag = score[y - 1][x - 1] + mismatch

            temp = dir(left, diag, up, x, y)
            score[y][x] = temp[0]
            direction[y][x] = temp[1]
    return score, direction

def needleman_backtrack(directions, sequ2, sequ1):
    sequ2 = "-" + sequ2
    sequ1 = "-" + sequ1
    x = len(directions) - 1
    y = len(directions[0]) - 1
    gen_sequenz = [[], []]
    while x > 0 or y > 0:
        if directions[x][y] == DIAG:
            gen_sequenz[0].append(sequ1[x])
            gen_sequenz[1].append(sequ2[y])
            x -= 1
            y -= 1
        elif directions[x][y] == UP:
            gen_sequenz[0].append(sequ1[x])
            gen_sequenz[1].append("-")
            x -= 1
        elif directions[x][y] == LEFT:
            gen_sequenz[0].append("-")
            gen_sequenz[1].append(sequ2[y])
            y -= 1

    seq1 = gen_sequenz[1]
    seq2 = gen_sequenz[0]
    seq1 = seq1[::-1]
    seq2 = seq2[::-1]
    return seq1, seq2

score, direction = needleman(sequ1, sequ2, match=3, mismatch=-2, gap=-3)
pprint(score, indent=1, width=300)
pprint(direction, indent=1, width=300)
q, w = needleman_backtrack(direction, sequ1, sequ2)
print("\n", q, "\n", w, "\n")

score, direction = needleman("ACCGAAGTAC", "AGAGGTAC", match=1, mismatch=-4, gap=-1)
pprint(score, indent=1, width=300)
pprint(direction, indent=1, width=300)
q, w = needleman_backtrack(direction, sequ1, sequ2)
print("\n", q, "\n", w, "\n")

score, direction = needleman("ACCGAAGTAC", "AGAGGTAC", match=2, mismatch=-5, gap=-3)
pprint(score, indent=1, width=300)
pprint(direction, indent=1, width=300)
q, w = needleman_backtrack(direction, sequ1, sequ2)
print("\n", q, "\n", w, "\n")


import copy
import decimal
import unittest

import openhtf as htf
from openhtf.util import test as htf_test
from openhtf.util import validators

class TestInRange(unittest.TestCase):

  def test_raises_if_invalid_arguments(self):
    with self.assertRaisesRegex(ValueError, 'Must specify minimum'):
      validators.InRange()
    with self.assertRaisesRegex(ValueError, 'Minimum cannot be greater'):
      validators.InRange(minimum=10, maximum=0)

  def test_invalidates_non_numbers(self):
    self.assertFalse(validators.InRange(0, 10)(float('nan')))
    self.assertFalse(validators.InRange(0, 10)(None))

  def test_upper_and_lower_bound_validator(self):
    test_validator = validators.InRange(minimum=-10, maximum=10)
    for valid_value in [-10, 0, 10]:
      self.assertTrue(test_validator(valid_value))
    for invalid_value in [-float('inf'), -11, 11, float('inf')]:
      self.assertFalse(test_validator(invalid_value))

  def test_lower_bound_validator(self):
    test_validator = validators.InRange(minimum=-10)
    for valid_value in [-10, 0, 10, float('inf')]:
      self.assertTrue(test_validator(valid_value))
    for invalid_value in [-float('inf'), -11]:
      self.assertFalse(test_validator(invalid_value))

  def test_upper_bound_validator(self):
    test_validator = validators.InRange(maximum=10)
    for valid_value in [-float('inf'), -10, 0, 10]:
      self.assertTrue(test_validator(valid_value))
    for invalid_value in [11, float('inf')]:
      self.assertFalse(test_validator(invalid_value))

  def test_str_does_not_raise(self):
    for args in [(None, 10), (0, None), (0, 10), (5, 5)]:
      test_validator = validators.InRange(*args)
      str(test_validator)
      # Check that we constructed a usable validator.
      self.assertTrue(test_validator(5))

  def test_comparable_with_equivalent_in_range_validator(self):
    validator_a = validators.InRange(minimum=0, maximum=10)
    validator_b = validators.InRange(minimum=0, maximum=10)
    self.assertEqual(validator_a, validator_b)
    validator_c = validators.InRange(maximum=10)
    self.assertNotEqual(validator_a, validator_c)

  def test_with_custom_type(self):
    hex_int = lambda x: int(x, 16)
    test_validator = validators.InRange('0x10', '0x12', type=hex_int)
    self.assertTrue(test_validator(0x11))
    self.assertFalse(test_validator(0x9))
    self.assertEqual(test_validator.minimum, 0x10)
    self.assertEqual(test_validator.maximum, 0x12)

class TestAllInRange(unittest.TestCase):

  def setUp(self):
    super().setUp()
    self.minimum = -20.5
    self.maximum = 0.3
    self.marginal_minimum = -10.1
    self.marginal_maximum = -8.2
    self.validator = validators.AllInRangeValidator(self.minimum, self.maximum,
                                                    self.marginal_minimum,
                                                    self.marginal_maximum)

  def test_properties(self):
    with self.subTest('minimum'):
      self.assertAlmostEqual(self.validator.minimum, self.minimum)
    with self.subTest('maximum'):
      self.assertAlmostEqual(self.validator.maximum, self.maximum)
    with self.subTest('marginal_minimum'):
      self.assertAlmostEqual(self.validator.marginal_minimum,
                             self.marginal_minimum)
    with self.subTest('marginal_maximum'):
      self.assertAlmostEqual(self.validator.marginal_maximum,
                             self.marginal_maximum)

  def test_returns_false_for_out_of_range_values(self):
    with self.subTest('beyond_minimum'):
      self.assertFalse(self.validator([self.minimum - 1, self.maximum]))
    with self.subTest('beyond_maximum'):
      self.assertFalse(self.validator([self.minimum, self.maximum + 1]))

  def test_returns_true_within_bounds(self):
    with self.subTest('with_all_values_set'):
      self.assertTrue(self.validator([self.minimum, self.maximum]))

  def test_returns_true_within_bounds_without_maximum(self):
    validator = validators.AllInRangeValidator(self.minimum, None)
    self.assertTrue(validator([self.minimum, self.maximum]))

  def test_returns_true_within_bounds_without_minimum(self):
    validator = validators.AllInRangeValidator(None, self.maximum)
    self.assertTrue(validator([self.minimum, self.maximum]))

  def test_is_marginal_is_marginal_returns_true_for_out_of_range_values(self):
    with self.subTest('beyond_marginal_minimum'):
      self.assertTrue(
          self.validator.is_marginal([self.minimum, self.marginal_maximum - 1]))
    with self.subTest('beyond_marginal_maximum'):
      self.assertTrue(
          self.validator.is_marginal([self.marginal_minimum + 1, self.maximum]))

  def test_is_marginal_false_within_bounds(self):
    self.assertFalse(
        self.validator.is_marginal(
            [self.marginal_minimum + 1, self.marginal_maximum - 1]))

  def test_is_marginal_false_fully_out_of_range(self):
    self.assertFalse(
        self.validator.is_marginal([self.minimum - 1, self.maximum + 1]))

  def test_is_marginal_false_without_marginal_bounds(self):
    validator = validators.AllInRangeValidator(self.minimum, self.minimum)
    self.assertFalse(validator.is_marginal([self.minimum, self.maximum]))

  def test_raises_for_unset_minimum_and_maximum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(None, None)
    self.assertIn('Must specify minimum, maximum, or both',
                  str(raises_context.exception))

  def test_raises_for_minimum_above_maximum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(minimum=self.maximum, maximum=self.minimum)
    self.assertIn('Minimum cannot be greater than maximum',
                  str(raises_context.exception))

  def test_raises_for_marginal_minimum_without_minimum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(None, self.maximum, self.marginal_minimum,
                                     self.marginal_maximum)
    self.assertIn('Marginal minimum was specified without a minimum',
                  str(raises_context.exception))

  def test_raises_for_marginal_maximum_without_maximum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(self.minimum, None, self.marginal_minimum,
                                     self.marginal_maximum)
    self.assertIn('Marginal maximum was specified without a maximum',
                  str(raises_context.exception))

  def test_raises_for_marginal_minimum_below_minimum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(
          minimum=self.marginal_minimum,
          maximum=None,
          marginal_minimum=self.minimum,
          marginal_maximum=None)
    self.assertIn('Marginal minimum cannot be less than the minimum',
                  str(raises_context.exception))

  def test_raises_for_marginal_maximum_below_maximum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(
          minimum=None,
          maximum=self.marginal_maximum,
          marginal_minimum=None,
          marginal_maximum=self.maximum)
    self.assertIn('Marginal maximum cannot be greater than the maximum',
                  str(raises_context.exception))

  def test_raises_for_marginal_minimum_above_marginal_maximum(self):
    with self.assertRaises(ValueError) as raises_context:
      validators.AllInRangeValidator(
          self.minimum,
          self.maximum,
          marginal_minimum=self.marginal_maximum,
          marginal_maximum=self.marginal_minimum)
    self.assertIn(
        'Marginal minimum cannot be greater than the marginal maximum',
        str(raises_context.exception))

class TestEqualsValidator(unittest.TestCase):

  def test_with_built_in_pods(self):
    for val in [1, '1', 1.0, False, (1,), [1], {1: 1}]:
      self.assertTrue(validators.Equals(val)(val))

  def test_with_custom_class(self):

    class MyType(object):
      A = 10

    my_type = MyType()
    self.assertTrue(validators.Equals(my_type)(my_type))

  def test_with_custom_type(self):
    hex_int = lambda x: int(x, 16)
    self.assertTrue(validators.Equals('0x12', type=hex_int)(0x12))
    self.assertEqual(validators.Equals('0x12', type=hex_int).expected, 0x12)

  def test_str_does_not_raise(self):
    equality_validator = validators.Equals(1)
    str(equality_validator)
    # Check that we constructed a usable validator.
    self.assertTrue(equality_validator(1))

  def test_comparable_with_equivalent_equals_validator(self):
    validator_a = validators.Equals('12.3')
    validator_b = validators.Equals('12.3')
    self.assertEqual(validator_a, validator_b)
    validator_c = validators.Equals('01,2')
    self.assertNotEqual(validator_a, validator_c)

class TestEqualsFactory(unittest.TestCase):

  def test_with_numbers(self):
    for expected in [1, 1.0, decimal.Decimal(1), int(1)]:
      number_validator = validators.equals(expected)
      self.assertTrue(number_validator(expected))
      self.assertFalse(number_validator(0))

  def test_with_string(self):
    string_validator = validators.equals('aardvark')
    self.assertTrue(string_validator('aardvark'))
    self.assertFalse(string_validator('aard'))
    self.assertFalse(string_validator('aardvarka'))

  def test_with_object(self):

    class MyType(object):
      val = 'A'

    my_type_a = MyType()
    object_validator = validators.equals(my_type_a)
    self.assertTrue(object_validator(my_type_a))
    my_type_b = MyType()
    self.assertFalse((object_validator(my_type_b)))

class TestWithinPercent(unittest.TestCase):

  def test_raises_for_negative_percentage(self):
    with self.assertRaisesRegex(ValueError, 'percent argument is'):
      validators.WithinPercent(expected=100, percent=-1)

  def test_raises_for_larger_marginal_percent(self):
    with self.assertRaisesRegex(ValueError, 'marginal_percent argument is'):
      validators.WithinPercent(expected=100, percent=2, marginal_percent=3)

  def test_is_marginal(self):
    validator = validators.WithinPercent(
        expected=100, percent=10, marginal_percent=5)
    with self.subTest('returns_true_on_marginal_measurement'):
      self.assertTrue(validator.is_marginal(106))
    with self.subTest('returns_false_on_non_marginal_measurement'):
      self.assertFalse(validator.is_marginal(102))

  def test_within_percent_less_than_one_hundred(self):
    validator = validators.WithinPercent(expected=100, percent=5)
    for valid_value in [95, 95.0, 100, 100.0, 105, 105.0]:
      self.assertTrue(
          validator(valid_value),
          msg='{} should validate, but did not'.format(valid_value))
    for invalid_value in [94, 94.0, 106, 106.0]:
      self.assertFalse(
          validator(invalid_value),
          msg='{} should not validate, but did'.format(invalid_value))

  def test_within_percent_greater_than_one_hundred(self):
    validator = validators.WithinPercent(expected=100, percent=200)
    for valid_value in [-100, 100, 300]:
      self.assertTrue(
          validator(valid_value),
          msg='{} should validate, but did not'.format(valid_value))
    for invalid_value in [-101, 301]:
      self.assertFalse(
          validator(invalid_value),
          msg='{} should not validate, but did'.format(invalid_value))

  def test_equals_equivalent_within_percent_validator(self):
    validator_a = validators.WithinPercent(expected=100, percent=10)
    validator_b = validators.WithinPercent(expected=100, percent=10)
    self.assertEqual(
        validator_a,
        validator_b,
        msg='Validators should compare equal, but did not.')

  def test_not_equals_when_not_equivalent(self):
    validator_a = validators.WithinPercent(expected=100, percent=10)
    validator_b = validators.WithinPercent(expected=100, percent=11)
    validator_c = validators.WithinPercent(expected=101, percent=10)
    validator_d = lambda unused_x: True  # Everything's fine!
    for validator in [validator_b, validator_c, validator_d]:
      self.assertNotEqual(validator_a, validator)

  def test_string_representation_does_not_raise(self):
    validator_a = validators.WithinPercent(expected=100, percent=10)
    str(validator_a)
    # Check that we constructed a usable validator.
    self.assertTrue(validator_a(100))

  def test_is_deep_copyable(self):
    validator_a = validators.WithinPercent(expected=100, percent=10)
    # Call implemented functions, try catch the cases where they might change
    # state in a non-deepcopyable manner.
    validator_a(1)
    str(validator_a)
    validator_a == 'a'  # pylint: disable=pointless-statement
    validator_b = copy.deepcopy(validator_a)
    self.assertEqual(validator_a.expected, validator_b.expected)
    self.assertEqual(validator_a.percent, validator_b.percent)

class DimensionPivotTest(htf_test.TestCase):
  """Tests validators.DimensionPivot. Used with dimensioned measurements."""

  _test_value = 10
  _sub_validator = validators.in_range(0, _test_value)
  _test_measurement = htf.Measurement('pivot').with_dimensions(
      'height', 'width').dimension_pivot_validate(_sub_validator)

  @htf_test.yields_phases
  def testPasses(self):

    @htf.measures(self._test_measurement)
    def phase(test):
      test.measurements.pivot[10, 10] = self._test_value - 2
      test.measurements.pivot[11, 10] = self._test_value - 1

    phase_record = yield phase
    self.assertMeasurementPass(phase_record, 'pivot')

  @htf_test.yields_phases
  def testFails(self):

    @htf.measures(self._test_measurement)
    def phase(test):
      test.measurements.pivot[11, 12] = self._test_value - 1
      test.measurements.pivot[14, 12] = self._test_value + 1

    phase_record = yield phase
    self.assertMeasurementFail(phase_record, 'pivot')

class ConsistentEndDimensionPivotTest(htf_test.TestCase):
  """Tests validators.ConsistentEndRange. Similar to DimensionPivot."""

  _sub_validator = validators.in_range(minimum=5)
  _test_measurement = htf.Measurement('pivot').with_dimensions(
      'time').consistent_end_dimension_pivot_validate(_sub_validator)

  @htf_test.yields_phases
  def testPasses(self):

    @htf.measures(self._test_measurement)
    def phase(test):
      test.measurements.pivot[0] = 0
      test.measurements.pivot[1] = 2
      test.measurements.pivot[2] = 6
      test.measurements.pivot[3] = 8

    phase_record = yield phase
    self.assertMeasurementPass(phase_record, 'pivot')

  @htf_test.yields_phases
  def testFails(self):

    @htf.measures(self._test_measurement)
    def phase(test):
      test.measurements.pivot[0] = 3
      test.measurements.pivot[1] = 4
      test.measurements.pivot[2] = 6
      test.measurements.pivot[3] = 4

    phase_record = yield phase
    self.assertMeasurementFail(phase_record, 'pivot')


# /usr/bin/python
'''
curl request
resposne:
{"results": [{"alternatives": [{"confidence": 0.7269427, "transcript": "hello Pandey Ji how are you doing"}]}]

 json.dumps({'apple': 'cat', 'banana':'dog', 'pear':'fish'})
'{"pear": "fish", "apple": "cat", "banana": "dog"}'

json.loads( encoded_str )
'''
import requests
import json

def curl_get_request():
    url = "http://localhost:5002/"
    response = requests.post(url, data={'key1': 'value1', 'key2': 'value2'})
    jString = response.content  # string
    jload = json.loads(jString)  # dictionary
    return jload

if __name__ == "__main__":
    dData = curl_get_request()
    print(dData)
# print dData['name'];


import sys
# print('geopandas' in sys.modules)
from time import time
import numpy as np
import pandas as pd
import geopandas as gpd
from pathlib import Path
import h5py
import matplotlib as mpl
import matplotlib.pyplot as plt
# to convert long / lat to points and do calculations on geometries
from shapely import Point

class VIIRSImage:

    def __init__(self, ls_path):

        stime = time()
        print(f'Instantiating LandsatImage object for {ls_path}.')

        self.path = ls_path
        self.h5 = h5py.File(self.path)
        self.h5_array = np.array(self.h5['HDFEOS/GRIDS/VNP_Grid_DNB/Data Fields/DNB_BRDF-Corrected_NTL'])
        self.mandatory_qf_array = np.array(self.h5['HDFEOS/GRIDS/VNP_Grid_DNB/Data Fields/Mandatory_Quality_Flag'])
        self.qf_cloud_mask_array = np.array(self.h5['HDFEOS/GRIDS/VNP_Grid_DNB/Data Fields/QF_Cloud_Mask'])
        self.mask_array = None
        self.scaled_array = None
        self.filtered_array = None

        # Don't need to pad array like the Landsat images

        self.spin_up()

        print(f'LandsatImage object for {self.path} instantiated in {np.around(time() - stime, decimals=2)} seconds.')

    def spin_up(self):

        stime = time()
        print(f'Loading Quality Flag array...')
        # Already Qualtiy Flag arrays as attributes above, so really not loading anything
        print(f'Quality Flag array loaded in {np.around(time() - stime, decimals=2)} seconds.')
        print(f'Making mask from Quality Flags to filter array...')
        ctime = time()
        self.make_masks()
        print(f'Mask made in {np.around(time() - ctime, decimals=2)} seconds.')
        print(f'Applying Scale Factor and Additive Offset...')
        ctime = time()
        self.apply_factors_offsets_sr()
        print(f'Scale factors and additive offsets applied in {np.around(time() - ctime, decimals=2)} seconds.')
        print(f'Filtering array using mask...')
        ctime = time()
        #self.filtered_array = np.empty((self.tif.asarray().shape[0], self.tif.asarray().shape[1]))
        self.get_filtered_array()
        print(f'Array filtered using mask in {np.around(time() - ctime, decimals=2)} seconds.')

    def get_filtered_array(self):
        # np.where is like an if else statement np.where(<condition>, <if condition true>, <if condition false>)
        # Only going to look at the those places in mask array that are NaNs (i.e. not set to False by a Quality Flag)

        self.filtered_array = np.where(np.isnan(self.mask_array),
                                       self.scaled_array,
                                       np.nan)

        print(f"Filtered Array shape: {self.filtered_array.shape}")

    def apply_factors_offsets_sr(self):

        scale_factor = 0.1
        additive_offset = 0

        self.scaled_array = np.multiply(self.h5_array, scale_factor)

        return np.add(self.scaled_array, additive_offset)

    def make_masks(self):

        assert self.mandatory_qf_array.shape == self.qf_cloud_mask_array.shape

        gf_rows, gf_cols = self.mandatory_qf_array.shape

        self.mask_array = np.full((gf_rows, gf_cols), np.nan)

        it_mandatory_qf_array = np.nditer(self.mandatory_qf_array, flags=['multi_index'])

        it_qf_cloud_mask_array = np.nditer(self.qf_cloud_mask_array, flags=['multi_index'])

        for (qf_cloud_mask_value, qf_array_value) in zip(it_qf_cloud_mask_array, it_mandatory_qf_array):

            fill, poor_quality = unpack_mandatory_qf(qf_array_value)

            day, cloud, shadow, sea = qf_cloud_mask(qf_cloud_mask_value)

            pixel_index = it_mandatory_qf_array.multi_index

            if fill:
                self.mask_array[pixel_index] = True

            if poor_quality:
                self.mask_array[pixel_index] = True

            if cloud:
                self.mask_array[pixel_index] = True

            if shadow:
                self.mask_array[pixel_index] = True

            if day:
                self.mask_array[pixel_index] = True

            if sea:
                self.mask_array[pixel_index] = True

def unpack_mandatory_qf(qf):

    fill = False
    if qf == 225:
        fill = True

    poor_quality = False
    if qf == 2 or qf == 3:
        poor_quality = True

    return fill, poor_quality

def qf_cloud_mask(qf):

    unpacked = bin(qf)[2:]

    while len(unpacked) < 16:
        unpacked = '0' + unpacked

    reversed = ''

    unpacked_list = list(unpacked)
    while unpacked_list:
        reversed += unpacked_list.pop()

    day = False
    if reversed[0] == '1':
        day = True

    cloud = False
    if reversed[9] == '1':
        cloud = True

    shadow = False
    if reversed[8] == '1':
        shadow = True

    # looking at bit 1-3, recall that python is not in-point inclusive
    sea = False
    if reversed[1:4] == "011":
        sea = True

    return day, cloud, shadow, sea

def get_diff_array(ls_one, ls_two):

    return np.subtract(ls_one.filtered_array,
                       ls_two.filtered_array,
                       where=~np.isnan(ls_one.filtered_array) & ~np.isnan(ls_two.filtered_array),
                       out=np.full((ls_one.filtered_array.shape[0],
                                    ls_one.filtered_array.shape[1]),
                                   np.nan))

def plot_images_main(path_one, path_two):

    # Create LandsatImage objects
    ls_one = VIIRSImage(path_one)
    ls_two = VIIRSImage(path_two)

    # Get the difference between the arrays
    diff_arr = get_diff_array(ls_one, ls_two)

    norm = mpl.colors.Normalize(vmin=0, vmax=1)
    cmap = mpl.colormaps["jet"]
    cmap.set_bad('k')
    my_cmap = mpl.cm.ScalarMappable(cmap=cmap, norm=norm)

    fig = plt.figure(figsize=(12, 12), constrained_layout=True)

    ax = fig.add_subplot(1, 3, 1)

    ax.imshow(ls_one.filtered_array, cmap=my_cmap.cmap)
    ax.set_title('Before')

    ax = fig.add_subplot(1, 3, 2)

    ax.imshow(ls_two.filtered_array, cmap=my_cmap.cmap)
    ax.set_title('After')

    norm = mpl.colors.Normalize(vmin=-1, vmax=1)
    cmap = mpl.colormaps["seismic"]
    cmap.set_bad('k')
    my_cmap = mpl.cm.ScalarMappable(cmap=cmap, norm=norm)

    ax = fig.add_subplot(1, 3, 3)
    ax.set_title('Difference')

    ax.imshow(diff_arr, cmap=my_cmap.cmap)

    plt.show()

if __name__ == '__main__':

    if False:

        test_file1 = '/Users/brevi/Documents/All_Files/2022_2024_Non_Harvard/Work_with_Ian_Paynter/LAADS_Tools/inputs/2017_09_19_to_2017_09_20_VNP46A2_5000_h11v07_pr_maria/VNP46A2.A2017262.h11v07.001.2020300190702.h5'

        test_file2 = '/Users/brevi/Documents/All_Files/2022_2024_Non_Harvard/Work_with_Ian_Paynter/LAADS_Tools/inputs/2017_09_19_to_2017_09_20_VNP46A2_5000_h11v07_pr_maria/VNP46A2.A2017263.h11v07.001.2021117133537.h5'

        plot_images_main(path_one=test_file1, path_two=test_file2)

        # ls_one = ViirsNtlImage(ls_path=test_file1)