import json
from dateutil.parser import parse
import optuna
import optuna.storages as storages
from datetime import datetime, timedelta
import math
import sqlite3
import sys
import numpy as np
import pandas as pd
import time
from decimal import Decimal
import trading_data_process as tdp
from numba import jit
pd.options.mode.chained_assignment = None  # 禁用 SettingWithCopyWarning

def calculate_sma_numpy(arr, window):
    return np.convolve(arr, np.ones(window)/window, mode='valid')

def calculate_vwap(df, period=None): #checked，量价都是使用同样的period参数，合理。
    typical_price = (df['high'] + df['low'] + df['close']) / 3
    weighted_typical_price = typical_price * df['volume']
    # 计算 EMA
    ema_typical_price = weighted_typical_price.ewm(span=period, adjust=False).mean()
    ema_volume = df['volume'].ewm(span=period, adjust=False).mean()
    # 计算 VWAP
    vwap = ema_typical_price / ema_volume
    return vwap

def calculate_ema_numpy(arr, span, alpha=None):
    if alpha == None:
        alpha = 2 / (span + 1)
    ema = np.zeros_like(arr, dtype=np.float64)
    ema[0] = arr[0] if not np.isnan(arr[0]) else 0  # Initialize with the first element if it's not NaN, otherwise use 0
    for t in range(1, len(arr)):
        if np.isnan(arr[t]):
            ema[t] = ema[t-1]  # If current value is NaN, use the last EMA value
        else:
            ema[t] = (1 - alpha) * ema[t-1] + alpha * arr[t]
    return ema

def calculate_vwap_numpy(high, low, close, volume, span):
    typical_price = (high + low + close) / 3
    weighted_typical_price = typical_price * volume
    ema_typical_price = calculate_ema_numpy(weighted_typical_price, span)
    ema_volume = calculate_ema_numpy(volume, span)
    #print("ema_typical_price",ema_typical_price)
    #print("ema_volume",ema_volume)
    vwap = ema_typical_price / ema_volume
    #print("vwap",vwap)
    return vwap

#load_data('BTCUSDT_1m.csv', '2023-08-23 00:00:00', 60)

def calculate_atr(df, period=14):#checked
    # 计算前一天的收盘价
    prev_close = df['close'].shift(1)
    # 计算真实最高价
    true_high = df['high'].where(df['high'] > prev_close, prev_close)
    true_low = df['low'].where(df['low'] < prev_close, prev_close)
    # 计算真实范围
    true_range = true_high - true_low
    # 使用Smoothed Moving Average来计算平均真实范围
    smoothing_factor = 1.0 / period  # 根据SmoothedMovingAverage的定义
    atr = true_range.ewm(alpha=smoothing_factor, adjust=False).mean()
    return atr

def calculate_atr_numpy(high, low, close, period=14):
    # Calculating previous day's close
    prev_close = np.roll(close, shift=1)
    prev_close[0] = np.nan
    # Calculating true high and true low
    true_high = np.maximum(high, prev_close)
    true_low = np.minimum(low, prev_close)
    # Calculating true range
    true_range = true_high - true_low
    # Using Smoothed Moving Average to calculate ATR
    smoothing_factor = 1.0 / period
    atr = calculate_ema_numpy(true_range, period,alpha=smoothing_factor)
    return atr

class TradeLogic:
    def __init__(self, df, index,buy_risk_per_trade,sell_risk_per_trade,buy_stop_loss,sell_stop_loss,buy_take_profit,sell_take_profit):
        self.df = df
        self.index = index
        self.buy_risk_per_trade = buy_risk_per_trade
        self.sell_risk_per_trade = sell_risk_per_trade
        self.buy_stop_loss = buy_stop_loss
        self.sell_stop_loss = sell_stop_loss
        self.buy_take_profit = buy_take_profit
        self.sell_take_profit = sell_take_profit
        self.initialize_values()

    def initialize_values(self):
        for col_name in ["position", "cash", "open_direction", "open_cost_price", "max_profit", "BTC_debt", "USDT_debt", "free_BTC", "net_value"]:
            self.df[col_name][self.index] = self.df[col_name][self.index - 1]
        self.calculate_net_value()

    def calculate_net_value(self):
        index = self.index  # 当前索引
        try:
            if self.df['position'][index] > 0:
                self.df['net_value'][index] = self.df['cash'][index] + self.df['close'][index] * self.df['position'][index] - self.df['BTC_debt'][index] * self.df['close'][index] - self.df['USDT_debt'][index]
            elif self.df['position'][index] <= 0:
                self.df['net_value'][index] = self.df['cash'][index] + (self.df['free_BTC'][index] - self.df['BTC_debt'][index]) * self.df['close'][index] - self.df['USDT_debt'][index]
            else:
                self.df['net_value'][index] = self.df['cash'][index] - self.df['BTC_debt'][index] * self.df['close'][index] - self.df['USDT_debt'][index]
        except Exception as e:
            print(f"Current index: {index}")
            print(f"the date is: {self.df['datetime'][index]}")
            print('---------------------------------')
            for column in self.df.columns:
                print('column is: ',column)
                print(self.df[column][index-100:index+100])
            raise e
            # break statement should be inside a loop

    def borrow_Margin(self, coin, how_much_borrow):
        index = self.index
        if coin == 'BTC':
            self.df['BTC_debt'][index] += how_much_borrow
            self.df['free_BTC'][index] += how_much_borrow
        elif coin == 'USDT':
            self.df['USDT_debt'][index] += how_much_borrow
            self.df['cash'][index] += how_much_borrow
        else:
            print("Please input BTC for sell or USDT for buy.")
        self.calculate_net_value()

    def repay_Margin(self):
        index = self.index
        BTC_debt = self.df['BTC_debt'][index]
        USDT_debt = self.df['USDT_debt'][index]
        if BTC_debt > 0:
            self.create_close_order()
            self.df['free_BTC'][index] -= BTC_debt
            self.df['BTC_debt'][index] -= BTC_debt
        elif USDT_debt > 0:
            self.create_close_order()
            self.df['cash'][index] -= USDT_debt
            self.df['USDT_debt'][index] -= USDT_debt
        else:
            #print("No debt to repay.")
            pass
        self.calculate_net_value()

    def calculate_size(self, avg_volume, risk_per_trade):
        self.calculate_net_value()
        index = self.index  # 当前处理的行索引
        account_net_value = self.df['net_value'][index]  # 账户净值
        volume = self.df['volume'][index]  # 当前成交量
        last_close = self.df['close'][index]  # 最后收盘价
        # 检查账户净值是否为负
        if account_net_value <= 0:
            return "Negative value"
        # 计算交易规模
        size = (account_net_value * risk_per_trade * (volume / avg_volume)) / last_close
        # 如果计算出的规模太大，进行调整
        if size * last_close > 2 * account_net_value:
            size = (2 * account_net_value) / last_close
        # 如果计算出的规模太小（小于 11 USDT），进行调整
        if size * last_close < 11:
            size = 11 / last_close
        return size

    def create_buy_order(self, size):
        index = self.index
        size = float(size)
        if size < 0:
            size = abs(size)
        order = self.df['next_open'][index] * size * 1.0005
        self.df['cash'][index] -= order
        #计算成本价，逻辑要写3个：做空时的减仓，做多时的加仓，空仓时做多。
        #做空时减仓有没有可能减到做多，这个需要测试一下。
        pre_position = self.df['position'][index]
        if pre_position < 0:
            pre_total_cost = -pre_position * self.df['open_cost_price'][index]
            self.df['position'][index] += size
            self.df['open_direction'][index] = "BUY"
            extra_cost = size * float(self.df['next_open'][index]) * 1.0005
            self.df['open_cost_price'][index] = (pre_total_cost-extra_cost)/abs(self.df['position'][index])
        elif pre_position > 0:
            pre_total_cost = pre_position * self.df['open_cost_price'][index]
            self.df['position'][index] += size
            self.df['open_direction'][index] = "BUY"
            extra_cost = size * float(self.df['next_open'][index]) * 1.0005
            self.df['open_cost_price'][index] = (pre_total_cost+extra_cost)/abs(self.df['position'][index])
        else:
            self.df['position'][index] += size
            self.df['open_direction'][index] = "BUY"
            self.df['open_cost_price'][index] = self.df['next_open'][index] * 1.0005

        self.calculate_net_value()

    def create_sell_order(self, size):
        index = self.index
        size = float(size)
        if size < 0:
            size = abs(size)
        order = self.df['next_open'][index] * size * 0.9995
        self.df['cash'][index] += order
        #计算成本价，逻辑要写3个：做空时的继续做空，做多时的减仓，空仓时做空。
        #做多时减仓有没有可能减到做空，这个需要测试一下。
        pre_position = self.df['position'][index]
        if pre_position < 0:
            pre_total_cost = -pre_position * self.df['open_cost_price'][index]
            self.df['position'][index] -= size
            self.df['open_direction'][index] = "SELL"
            extra_cost = size * float(self.df['next_open'][index]) * 0.9995
            self.df['open_cost_price'][index] = (pre_total_cost+extra_cost)/abs(self.df['position'][index])
        elif pre_position > 0:
            pre_total_cost = pre_position * self.df['open_cost_price'][index]
            self.df['position'][index] -= size
            self.df['open_direction'][index] = "SELL"
            extra_cost = size * float(self.df['next_open'][index]) * 0.9995
            self.df['open_cost_price'][index] = (pre_total_cost-extra_cost)/abs(self.df['position'][index])
        else:
            self.df['position'][index] -= size
            self.df['open_direction'][index] = "SELL"
            self.df['open_cost_price'][index] = self.df['next_open'][index] * 0.9995
        self.df['free_BTC'][index] -= size
        self.calculate_net_value()

    def create_close_order(self):
        index = self.index
        my_position = self.df['position'][index]

        if my_position > 0:
            self.df['cash'][index] += my_position * self.df['next_open'][index] * 0.9995
            self.df['position'][index] = 0
            self.df['open_direction'][index] = None  # The direction of the open position (Long/Short)
            self.df['open_cost_price'][index] = None  # Cost price of the open position
        elif my_position < 0:
            repay = self.df['next_open'][index] * abs(my_position) * 1.0005
            self.df['free_BTC'][index] += abs(my_position)
            self.df['cash'][index] -= repay
            self.df['position'][index] = 0
            self.df['open_direction'][index] = None  # The direction of the open position (Long/Short)
            self.df['open_cost_price'][index] = None
        self.df['max_profit'][index] = 0
        self.calculate_net_value()

    def handle_absolute_stop_orders(self, buy_signal, sell_signal):
        index = self.index

        max_profit = self.df['max_profit'][index]
        last_close = self.df['close'][index]
        my_position = self.df['position'][index]

        if my_position > 0:  # Long position
            buy_price = self.df['open_cost_price'][index]
            profit = (last_close - buy_price) / buy_price
            if profit < 0:
                profit = 0
            if profit > max_profit:
                self.df['max_profit'][index] = profit
            elif max_profit - profit >= self.buy_take_profit and not buy_signal:
                self.repay_Margin()
            elif last_close < buy_price * (1.0 - self.buy_stop_loss):
                self.repay_Margin()

        elif my_position < 0:  # Short position
            sell_price = self.df['open_cost_price'][index]
            profit = (sell_price - last_close) / sell_price
            if profit < 0:
                profit = 0
            if profit > max_profit:
                self.df['max_profit'][index] = profit
            elif max_profit - profit >= self.sell_take_profit and not sell_signal:
                self.repay_Margin()
            elif last_close > sell_price * (1.0 + self.sell_stop_loss):
                self.repay_Margin()

        self.calculate_net_value()

    def execute_trade(self):
        index = self.index
        my_position = self.df['position'][index]

        buy_risk_per_trade = self.buy_risk_per_trade
        sell_risk_per_trade = self.sell_risk_per_trade

        buy_vwap = self.df['buy_vwap'][index]
        sell_vwap = self.df['sell_vwap'][index]

        buy_atr = self.df['buy_atr'][index]
        sell_atr = self.df['sell_atr'][index]

        buy_atr_sma = self.df['buy_atr_sma'][index]
        sell_atr_sma = self.df['sell_atr_sma'][index]

        last_close = self.df['close'][index]
        last_volume = self.df['volume'][index]
        pre_volume = self.df['volume'][index-1]
        buy_avg_volume = self.df['buy_avg_volume'][index]
        sell_avg_volume = self.df['sell_avg_volume'][index]

        buy_signal = self.df['buy_signal'][index]
        sell_signal = self.df['sell_signal'][index]
        # 在市场中
        if my_position != 0:
            #更新buy price 和 sell price作为止盈止损的依据，这里的价格是最近一次成交的价格。
            # 买入逻辑
            if buy_signal:
                if my_position > 0:
                    size = self.calculate_size(avg_volume=buy_avg_volume, risk_per_trade=buy_risk_per_trade)
                    try:
                        if size - my_position > 0 and (size-my_position)*last_close > 11:
                            extra_buy = size - my_position
                            #print(f"Detected extra long buy signal, we are going to long extra {extra_buy} BTC.")
                            self.borrow_Margin(coin='USDT', how_much_borrow=extra_buy*last_close)
                            self.create_buy_order(size=extra_buy)
                        else:
                            #print(f"Detected long buy signal, but extra size does not meet minium amount 10 USDT.")
                            pass
                    except:
                        print("error")
                        print(f"size is {size}")
                        print(f"the net value is {self.df['net_value'][index]}")
                        print(f"my_position is {my_position}")
                if my_position < 0:  # 空头仓位
                    # 关闭空头，开始买入
                    self.repay_Margin()
                    self.df['max_profit'][index] = 0
                    size = self.calculate_size(avg_volume=buy_avg_volume, risk_per_trade=buy_risk_per_trade)
                    self.borrow_Margin(coin='USDT', how_much_borrow=size*last_close,)
                    self.create_buy_order(size=size)

            # 卖出逻辑
            elif sell_signal:
                if my_position < 0:
                    size = self.calculate_size(avg_volume=sell_avg_volume, risk_per_trade=sell_risk_per_trade)
                    if my_position + size > 0 and (my_position+size)*last_close > 11:
                        extra_sell = my_position + size
                        #print(f"Detected extra short sell signal, we are going to short extra {extra_sell} BTC.")
                        self.borrow_Margin(coin='BTC', how_much_borrow=extra_sell)
                        self.create_sell_order(size=extra_sell)
                    else:
                        #print(f"Detected short sell signal, but extra size does not meet minium amount 10 USDT.")
                        pass
                if my_position > 0:  # 多头仓位
                    # 关闭多头，开始卖出
                    self.repay_Margin()
                    self.df['max_profit'][index] = 0
                    size = self.calculate_size(avg_volume=sell_avg_volume, risk_per_trade=sell_risk_per_trade)
                    self.borrow_Margin(coin='BTC', how_much_borrow=size)
                    self.create_sell_order(size=size)

            self.handle_absolute_stop_orders(buy_signal, sell_signal)
        # 不在市场中
        else:
            self.df['max_profit'][index] = 0
            self.df['open_cost_price'][index] = 0
            # 买入逻辑
            if buy_signal:
                size = self.calculate_size(avg_volume=buy_avg_volume, risk_per_trade=buy_risk_per_trade)
                self.borrow_Margin(coin='USDT', how_much_borrow=size*last_close)
                self.create_buy_order(size=size)

            # 卖出逻辑
            elif sell_signal:
                size = self.calculate_size(avg_volume=sell_avg_volume, risk_per_trade=sell_risk_per_trade)
                self.borrow_Margin(coin='BTC', how_much_borrow=size)
                self.create_sell_order(size=size)
            # 获取当前的 UTC 时间（东0区时间）
        self.calculate_net_value()
        #return self.df.iloc[index]  # Returning the updated DataFrame

def load_data(filepath, end_date, data_len):
    # Step 1: Load the existing data
    df = pd.read_csv(filepath, sep=',')
    df['datetime'] = pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M:%S')
    df.set_index('datetime', inplace=True)
    end_date = pd.to_datetime(end_date, format='%Y-%m-%d %H:%M:%S')

    # Step 2: Filter data based on end_date and data_len
    start_date = end_date - timedelta(days=data_len + 3)  # Adding 5 days as per your requirement
    extended_end_date = end_date + timedelta(minutes=1)  # Extending end_date by 1 minute
    filtered_df = df.loc[start_date:extended_end_date ]
    if filtered_df.empty:
        print(f"the date of {end_date} is not in the data, we are goting to trunc our data.")
        filtered_df = df.loc[start_date:]
    filtered_df['next_open'] = filtered_df['open'].shift(-1)

    # Step 3: Add additional columns that are missing (Populate these columns based on your logic)
    filtered_df['position'] = None  # Position in the trade
    filtered_df['net_value'] = None  # Net value of the trade to be computed based on your logic
    filtered_df['cash'] = None  # Cash available
    filtered_df['open_direction'] = None  # The direction of the open position (Long/Short)
    filtered_df['open_cost_price'] = None  # Cost price of the open position
    filtered_df['max_profit'] = None  # Maximum profit
    filtered_df['BTC_debt'] = None  # BTC debt
    filtered_df['USDT_debt'] = None  # USDT debt
    filtered_df['free_BTC'] = None
    filtered_df['buy_vwap'] = 0
    filtered_df['buy_atr'] = 0
    filtered_df['buy_atr_sma'] = 0
    filtered_df['sell_vwap'] = 0
    filtered_df['sell_atr'] = 0
    filtered_df['sell_atr_sma'] = 0
    return filtered_df

#load_data('BTCUSDT_1m.csv', '2023-08-23 00:00:00', 60)

def calculate_sma_numpy_with_padding(arr, window):
    sma = np.convolve(arr, np.ones(window)/window, mode='valid')
    pad_size = window - 1
    pad = np.full(pad_size, np.nan)
    sma_padded = np.concatenate((pad, sma))
    return sma_padded

# Function to calculate indicators for a specific range in numpy arrays
def calculate_indicators_for_range_inplace(start, end, arrays, buy_vwap_period,buy_atr_period,buy_atr_sma_period,sell_vwap_period,sell_atr_period,sell_atr_sma_period,max_length):
    arrays['buy_vwap'] = arrays['buy_vwap'].astype(float)
    arrays['sell_vwap'] = arrays['buy_vwap'].astype(float)
    arrays['buy_atr'] = arrays['buy_vwap'].astype(float)
    arrays['sell_atr'] = arrays['buy_vwap'].astype(float)
    arrays['buy_atr_sma'] = arrays['buy_vwap'].astype(float)
    arrays['sell_atr_sma'] = arrays['buy_vwap'].astype(float)
    start = start - max_length
    end = end + 1

    arrays['buy_vwap'][start:end] = calculate_vwap_numpy(arrays['high'][start:end], arrays['low'][start:end], arrays['close'][start:end], arrays['volume'][start:end], buy_vwap_period)
    arrays['buy_atr'][start:end] = calculate_atr_numpy(arrays['high'][start:end], arrays['low'][start:end], arrays['close'][start:end], buy_atr_period)
    arrays['buy_atr_sma'][start:end] = calculate_sma_numpy_with_padding(arrays['buy_atr'][start:end], buy_atr_sma_period)
    arrays['sell_vwap'][start:end] = calculate_vwap_numpy(arrays['high'][start:end], arrays['low'][start:end], arrays['close'][start:end], arrays['volume'][start:end], sell_vwap_period)
    arrays['sell_atr'][start:end] = calculate_atr_numpy(arrays['high'][start:end], arrays['low'][start:end], arrays['close'][start:end], sell_atr_period)
    arrays['sell_atr_sma'][start:end] = calculate_sma_numpy_with_padding(arrays['sell_atr'][start:end], sell_atr_sma_period)

if __name__ == "__main__":
    data_all = load_data("BTCUSDT_1m.csv", '2023-08-29 00:00:00', 6)

    start_time_total = time.time()
    symbol = 'BTC/USDT'
    last_action = 'free'
    buy_price = None
    sell_price = None
    max_profit = 0
    pre_my_position = 0

    with open('/home/WLH_trade/0615/trading/best_strategy', 'r') as file:
        best_strategy = json.load(file)

    sell_volume_window = best_strategy['1']['sell_volume_window']
    buy_volume_window = best_strategy['1']['buy_volume_window']
    buy_volume_multiplier = best_strategy['1']['buy_volume_multiplier']
    sell_volume_multiplier = best_strategy['1']['sell_volume_multiplier']
    buy_stop_loss = best_strategy['1']['buy_stop_loss']
    sell_stop_loss = best_strategy['1']['sell_stop_loss']
    buy_take_profit = best_strategy['1']['buy_take_profit']
    sell_take_profit = best_strategy['1']['sell_take_profit']
    sell_vwap_period = best_strategy['1']['sell_vwap_period']
    buy_vwap_period = best_strategy['1']['buy_vwap_period']
    buy_risk_per_trade = best_strategy['1']['buy_risk_per_trade']
    sell_risk_per_trade = best_strategy['1']['sell_risk_per_trade']
    buy_atr_period = best_strategy['1']['buy_atr_period']
    sell_atr_period = best_strategy['1']['sell_atr_period']
    #buy_atr_sma_period = best_strategy['1']['buy_atr_sma_period']
    #sell_atr_sma_period = best_strategy['1']['sell_atr_sma_period']
    buy_atr_sma_period = 5
    sell_atr_sma_period = 5
    max_length = max(sell_volume_window,buy_volume_window,sell_vwap_period,buy_vwap_period,sell_atr_period,buy_atr_period,sell_atr_sma_period,buy_atr_sma_period) + 1
    print(f"now we used the best strategy: {best_strategy['0']}, and its parameters are: {best_strategy['1']}")
    '''
    # 1. 计算VWAP
    data_all['buy_vwap'] = calculate_vwap(data_all, period=buy_vwap_period)
    data_all['sell_vwap'] = calculate_vwap(data_all, period=sell_vwap_period)

    # 2. 计算ATR
    data_all['buy_atr'] = calculate_atr(data_all, period=buy_atr_period)
    data_all['sell_atr'] = calculate_atr(data_all, period=sell_atr_period)

    # 3. 计算ATR的SMA（Simple Moving Average）
    data_all['buy_atr_sma'] = data_all['buy_atr'].rolling(window=buy_atr_sma_period ).mean()
    data_all['sell_atr_sma'] = data_all['sell_atr'].rolling(window=sell_atr_sma_period ).mean()

    # 4. 计算平均交易量
    data_all['buy_avg_volume'] = data_all['volume'].rolling(window=buy_volume_window).mean()
    data_all['sell_avg_volume'] = data_all['volume'].rolling(window=sell_volume_window).mean()
    # 预先计算买入和卖出条件
    data_all['buy_condition1'] = data_all['close'] > data_all['buy_vwap']
    data_all['buy_condition2'] = data_all['volume'].shift(1) > data_all['buy_avg_volume'] * buy_volume_multiplier * (data_all['buy_atr'] / data_all['buy_atr_sma'])
    data_all['buy_condition3'] = data_all['volume'] > data_all['buy_avg_volume'] * buy_volume_multiplier * (data_all['buy_atr'] / data_all['buy_atr_sma'])
    data_all['buy_signal'] = data_all['buy_condition1'] & (data_all['buy_condition2'] | data_all['buy_condition3'])

    data_all['sell_condition1'] = data_all['close'] < data_all['sell_vwap']
    data_all['sell_condition2'] = data_all['volume'].shift(1) > data_all['sell_avg_volume'] * sell_volume_multiplier * (data_all['sell_atr'] / data_all['sell_atr_sma'])
    data_all['sell_condition3'] = data_all['volume'] > data_all['sell_avg_volume'] * sell_volume_multiplier * (data_all['sell_atr'] / data_all['sell_atr_sma'])
    data_all['sell_signal'] = data_all['sell_condition1'] & (data_all['sell_condition2'] | data_all['sell_condition3'])
    '''
    # 创建一个字典来存储转换后的NumPy数组
    numpy_arrays = {}
    numpy_arrays['datetime'] = data_all.index.strftime('%Y-%m-%d %H:%M:%S').to_numpy()

    # 遍历DataFrame的每一列，并将其转换为NumPy数组
    for column in data_all.columns:
        numpy_arrays[column] = data_all[column].to_numpy()

    # Find the index of the row where datetime is '2023-08-23 00:00:00'
    # Note: We first convert the 'datetime' numpy array to a list and then find the index of the target date.
    target_date = '2023-08-23 00:00:00'
    row_at_date = np.where(numpy_arrays['datetime'] == target_date)[0][0]  # Getting the first occurrence

    target_date = pd.to_datetime(target_date, format='%Y-%m-%d %H:%M:%S')
    end_location = datetime.strftime(target_date + timedelta(days=6), '%Y-%m-%d %H:%M:%S')
    end_idx = np.where(numpy_arrays['datetime'] == str(end_location) )[0][0]

    calculate_indicators_for_range_inplace(start=row_at_date, end=end_idx, arrays=numpy_arrays,
                                        buy_vwap_period=buy_vwap_period,buy_atr_period=buy_atr_period,
                                        buy_atr_sma_period=buy_atr_sma_period,
                                        sell_vwap_period=sell_vwap_period,sell_atr_period=sell_atr_period,
                                        sell_atr_sma_period=sell_atr_sma_period,
                                        max_length=max_length)

    numpy_arrays['buy_avg_volume'] = calculate_sma_numpy_with_padding(numpy_arrays['volume'], buy_volume_window)
    numpy_arrays['sell_avg_volume'] = calculate_sma_numpy_with_padding(numpy_arrays['volume'], sell_volume_window)

    # Re-calculating the conditions and signals
    numpy_arrays['buy_condition1'] = numpy_arrays['close'] > numpy_arrays['buy_vwap']
    numpy_arrays['buy_condition2'] = np.roll(numpy_arrays['volume'], shift=1) > numpy_arrays['buy_avg_volume'] * buy_volume_multiplier * (numpy_arrays['buy_atr'] / numpy_arrays['buy_atr_sma'])
    numpy_arrays['buy_condition3'] = numpy_arrays['volume'] > numpy_arrays['buy_avg_volume'] * buy_volume_multiplier * (numpy_arrays['buy_atr'] / numpy_arrays['buy_atr_sma'])
    numpy_arrays['buy_signal'] = numpy_arrays['buy_condition1'] & (numpy_arrays['buy_condition2'] | numpy_arrays['buy_condition3'])

    numpy_arrays['sell_condition1'] = numpy_arrays['close'] < numpy_arrays['sell_vwap']
    numpy_arrays['sell_condition2'] = np.roll(numpy_arrays['volume'], shift=1) > numpy_arrays['sell_avg_volume'] * sell_volume_multiplier * (numpy_arrays['sell_atr'] / numpy_arrays['sell_atr_sma'])
    numpy_arrays['sell_condition3'] = numpy_arrays['volume'] > numpy_arrays['sell_avg_volume'] * sell_volume_multiplier * (numpy_arrays['sell_atr'] / numpy_arrays['sell_atr_sma'])
    numpy_arrays['sell_signal'] = numpy_arrays['sell_condition1'] & (numpy_arrays['sell_condition2'] | numpy_arrays['sell_condition3'])

    # Set the initial values for the relevant columns at the index (row_at_date - 1)
    initial_values = {
        'cash': 10000,
        'position': 0,
        'open_direction': 0,
        'open_cost_price': 0,
        'max_profit': 0,
        'BTC_debt': 0,
        'USDT_debt': 0,
        'net_value': 10000,
        'free_BTC': 0
    }

    # Iterating through the dictionary keys to set the initial values
    for column, initial_value in initial_values.items():
        numpy_arrays[column][row_at_date - 1] = initial_value

    start_time = time.time()

    # 用NumPy数组的长度替换Pandas DataFrame的长度
    for start_idx in range(row_at_date, end_idx+1):  # Replace 'some_column' with an actual column name
        #print(numpy_arrays['datetime'][start_idx])
        # 传递NumPy数组而不是DataFrame
        trade = TradeLogic(
            df=numpy_arrays,
            index=start_idx,
            buy_risk_per_trade=buy_risk_per_trade,
            sell_risk_per_trade=sell_risk_per_trade,
            buy_stop_loss = buy_stop_loss,
            sell_stop_loss = sell_stop_loss,
            buy_take_profit = buy_take_profit,
            sell_take_profit = sell_take_profit)
        trade.execute_trade()  # This modifies numpy_arrays in-place

    final_data = pd.DataFrame.from_dict({key: pd.Series(value) for key, value in numpy_arrays.items()})
    final_data.to_csv('numpy_for_backtest_0903_np.csv', index=False)

    print(numpy_arrays['net_value'][end_idx])
    print('Time taken for total: ', time.time() - start_time_total, ' seconds')
    print('Time taken for loop: ', time.time() - start_time, ' seconds')


# routing_main.py
# Troy Clendenen

# This is the main program for the routing and geocoding
# application.

from geopy.geocoders import Nominatim
from api_keys import *
from routing_config import *
from main_flask import *
import urllib.request
import openrouteservice
import json

def getWeather(coords):

	'''
	getweather()

	Takes in coordinates and outputs a dictionary from
	a json taken from the web which shows weather info
	of a place(s).

	inputs: tuple of coordinate pairs
	outputs: dictionary

	'''

	if weather_use_boundary_box == True:
		# boundary box for finding all cities within a square on the map.
		# [lon-left,lat-bottom,lon-right,lat-top,zoom]

		bbox = [0,0,0,0,weather_zoom]

		# compare coordinates so we can get our boundary box.

		if (coords[0][1] <= coords[1][1]):
			bbox[0] = coords[0][1]
			bbox[2] = coords[1][1]

			if (coords[0][0] <= coords[1][0]):
				bbox[1] = coords[0][0]
				bbox[3] = coords[1][0]

			else:
				bbox[1] = coords[1][0]
				bbox[3] = coords[0][0]

		else:
			bbox[0] = coords[1][1]
			bbox[2] = coords[0][1]

			if (coords[0][0] <= coords[1][0]):
				bbox[1] = coords[0][0]
				bbox[3] = coords[1][0]

			else:
				bbox[1] = coords[1][0]
				bbox[3] = coords[0][0]

		# boundary box url
		weather_url = "https://api.openweathermap.org/data/2.5/box/city?bbox=" + str(bbox[1]) + "," + str(bbox[0]) + "," + str(bbox[3]) + "," + str(bbox[2]) + "," + str(bbox[4]) + "&units=" + units + "&appid=" + weather_api_key
		#print(weather_url)
		weather_api_obj = eval(urllib.request.urlopen(weather_url).read())

	else:
		# single-point url
		weather_url = "https://api.openweathermap.org/data/2.5/weather?lat=" + str(coords[0][1]) + "&lon=" + str(coords[0][0]) + "&units=" + units + "&appid=" + weather_api_key
		#print(weather_url)
		weather_api_obj = eval(urllib.request.urlopen(weather_url).read())

	return weather_api_obj

def printWeather(forecast):

	'''
		printWeather()

		Prints out various weather information from the
		data returned from getWeather()

		inputs: forecast dictionary
		outputs: none

	'''

	print("### Weather Start ###")

	city = forecast["name"]
	precipitation = forecast["weather"][0]["main"]
	detailed_precipitation = forecast["weather"][0]["description"]
	temperature = forecast["main"]["temp"]
	humidity = forecast["main"]["humidity"]
	wind_speed = forecast["wind"]["speed"]
	wind_direction = forecast["wind"]["deg"]

	print("Weather in " + city + ":")
	print("Precipitation: " + precipitation + " (" + detailed_precipitation + ")")
	print("Temperature is " + str(temperature) + " degrees")
	print("Humidity is " + str(humidity) + " percent")
	print("Wind " + str(wind_speed) + " mph at " + str(wind_direction) + " degrees")

	print("### Weather End ###")
	print()

def getAQI(coords):

	'''
		getAQI()

		Takes in coordinates and outputs a dictionary from
		a json taken from the web which shows air quality info
		of a place(s).

		input: tuple of coordinate pairs
		outputs: tuple of dictionaries (start, destination)

	'''

	origin_url = "https://api.waqi.info/feed/geo:" + str(coords[0][1]) + ";" + str(coords[0][0]) + "/?token=" + aqi_api_key
	origin_aqi_obj = eval(urllib.request.urlopen(origin_url).read())

	destination_url = "https://api.waqi.info/feed/geo:" + str(coords[1][1]) + ";" + str(coords[1][0]) + "/?token=" + aqi_api_key
	destination_aqi_obj = eval(urllib.request.urlopen(destination_url).read())

	# access various parts of the json.
	# feel free to change/add whatever you feel like needs to be added.

	aqi_data = (origin_aqi_obj,destination_aqi_obj)

	return aqi_data

def printAQI(aqi_pair):

	'''
		printAQI()

		Prints out the average air quality between 2 places in the
		data returned from getAQI()

		inputs: tuple of dictionaries
		outputs: none

	'''
	print("### Air Quality Index Start ###")

	origin_aqi = aqi_pair[0]["data"]["aqi"]
	destination_aqi = aqi_pair[1]["data"]["aqi"]

	average_aqi = (origin_aqi + destination_aqi) // 2

	print("Air quality index value: " + str(average_aqi))

	if average_aqi <= 50:
		print("Good")
	elif average_aqi <= 100:
		print("Moderate")
	elif average_aqi <= 150:
		print("Unhealthy for Sensitive Groups")
	elif average_aqi <= 200:
		print("Unhealthy")
	elif average_aqi <= 300:
		print("Very Unhealthy")
	elif average_aqi <= 500:
		print("Hazardous")
	else:
		print("Extremely Hazardous")

	print("### Air Quality Index End ###")
	print()

def getRoute(coords, profile):

	'''
		getroute()

		Get a route between 2 points using OpenRouteService
		in the form of a json dictionary

		inputs: tuple of coordinate pairs
		outputs: dictionary
	'''

	try:
		client = openrouteservice.Client(key=maps_api_key)
		routes = client.directions(coords, profile)

	except openrouteservice.exceptions.ApiError:
		routes = 1 # could not find route

	return routes

def printRoute(route):

	'''
		printroute()

		Prints a route based on the input json file.

		input: json file of the route
		outputs: none
	'''
	route_list = []
	if type(route) == dict:
		directions = (route["routes"][0]["segments"][0]["steps"])

		for element in directions:
			route_list.append(element['instruction'] + " for " + str(element['distance']) + " meters.")

	return route_list

def route_main(start, dest):

	'''
		Have the user enter 2 addresses via name,
		and return the route between them.

		Extras: Have it return information about
		air quality in the area, choose between
		car/bike/walk/transit,
	'''

	geolocator = Nominatim(user_agent="project1")
	queryList = []

	done = False
	while not done:

		# origin entry
		found = False
		while not found:
			if start != "":
				start.replace(" ","")
				queryList = start.split(",")

				location = geolocator.geocode(queryList)

				if location != None:
					origin = (location.longitude,location.latitude)
					found = True
				else:
					print("Could not find location. Did you enter it in correctly?")

			else:
				break

		if (found == False):
			done = True
			break

		# destination entry
		found = False
		while not found:
			if dest != "":
				dest.replace(" ","")
				queryList = dest.split(",")

				location = geolocator.geocode(queryList)
				if location != None:
					destination = (location.longitude,location.latitude)
					found = True
				else:
					print("Could not find location. Did you enter it in correctly?")

			else:
				break

		if (found == False):
			done = True
			break

		coords = (origin,destination) #coordinates for our route

		'''
			This is where you can expand what data is
			retrieved with our program.

			route:
				format: json dictionary
				source: OpenRouteService

			aqi:
				format: tuple (origin json, destination json)
				source: Air Quality Open Data Platform

			weather:
				format: json dictionary
				source: OpenWeatherMap

		'''
		return coords
		'''
		route = getRoute(coords)
		aqi = getAQI(coords)
		weather = getWeather(coords)

		# end_data
		###
		# print data

		printRoute(route)
		printAQI(aqi)
		printWeather(weather)
		'''
		# end printing

		#cont = input("continue? (y/n): ")
		#if cont == 'n':
			#done = True
'''
if __name__ == "__main__":
	main()'''


from skimage import metrics
import numpy as np
import cv2
import pandas as pd
import time
import os
import logging

def read_csv(input_file_path):
    """
    :param input_file_path str: The full path to the image
    :returns the pandas read CSV
    Reading the file with full path obtained from the customer input
    """
    csvfile = pd.read_csv(input_file_path)
    return csvfile

def mean_squared_error(imageA, imageB):
    """
    :param imageA obj: A CV2 Image object to compare
    :param imageB obj: A secondary CV2 Image object to compare
    :returns an error index, the lower the error the more similar they are
    The 'Mean Squared Error' between the two images is the
    sum of the squared difference between the two images;
    NOTE: the two images must have the same dimension
    """
    logging.debug("mean_squared_error")
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])

    # return the mean_squared_error, the lower the error, the more "similar"
    # the two images are
    return err

def compare_images(imageA, imageB):
    """
    Compute the mean squared error and structural similarity
    :param imageA obj: A CV2 Image object to compare
    :param imageB obj: A secondary CV2 Image object to compare
    :returns tuple composed of mean_squared_error and negated structural_similarity
    """
    logging.debug("compare_images")
    mse = mean_squared_error(imageA, imageB)
    similarity = metrics.structural_similarity(imageA, imageB)
    return mse, 1-similarity

def compare(filePath1, filePath2):
    """
    Opens, imports and compares two file paths that should be images
    :param filePath1: The full path to an image file.
    :param filePath2: The full path to a secondary image file.
    :returns tuple with mean_squared_error, structural_similarity
              and the duration of the processing
    """
    start = time.time()
    image1 = cv2.imread(filePath1)
    image2 = cv2.imread(filePath2)
    image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
    image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)
    dim = (1024, 768)
    image1 = cv2.resize(image1, dim, interpolation=cv2.INTER_AREA)
    image2 = cv2.resize(image2, dim, interpolation=cv2.INTER_AREA)
    end = time.time()
    duration = end - start
    m, s = compare_images(image1, image2)
    return m, s, duration

def process_csv(input_file_path, output_file_path="Result.csv"):
    """
    Loads the CSV and iterates over the rows to provide similary and processing cost
    :param input_file_path str: The two-column file name containing image paths
    :param output_file_path str: The location to store the process of the input rows
    """
    logging.debug("process_csv")
    csvfile = read_csv(input_file_path)
    print(csvfile.head(5))

    # for loop inside an iteration to evaluate the previous results:
    # empty arrays
    similar = []
    elapsed = []
    for _index, row in csvfile.iterrows():
        filePath1 = row['Image1']
        filePath2 = row['Image2']
        logging.debug("Processing files '{}' and '{}':".format(row['Image1'], row['Image2']))
        m, s, d = compare(filePath1, filePath2)
        similar.append(s)
        elapsed.append(d)
        print(m, s, d)
        if (1-s > 0.9):
            logging.debug("Match")
        else:
            logging.debug("Different")

    csvfile["similar"] = similar
    csvfile["elapsed"] = elapsed
    csvfile.to_csv(output_file_path)


from django.shortcuts import render
from django.db import models
from FamiliApp.models import Familiar
from django.template import Template, loader
from django.http import HttpResponse
# Create your views here.

def familiapp_inicio(request):
    familiar1 = Familiar(nombre = "Jorge", apellido="Rojas", edad=50, ultimo_asado = "01/01/2000")
    familiar1.save()
    familiar2 = Familiar(nombre = "Marcelo", apellido="Miraglia", edad=57, ultimo_asado = "17/05/2017")
    familiar2.save()
    familiar3 = Familiar(nombre = "Juan", apellido="Moreira", edad=37, ultimo_asado = "24/02/1995")
    familiar3.save()
    diccionario = {
        "f1nombre": familiar1.nombre, "f1apellido":familiar1.apellido, "f1edad":familiar1.edad, "f1ultimo_asado":familiar1.ultimo_asado,
        "f2nombre": familiar2.nombre, "f2apellido":familiar2.apellido, "f2edad":familiar2.edad, "f2ultimo_asado":familiar2.ultimo_asado,
        "f3nombre": familiar3.nombre, "f3apellido":familiar3.apellido, "f3edad":familiar1.edad, "f3ultimo_asado":familiar3.ultimo_asado
    }
    plantilla = loader.get_template('FamiliApp/familiapp_inicio.html')
    documento= plantilla.render(diccionario)
    return HttpResponse(documento)


# Databricks notebook source
dbutils.widgets.text("subscription_id", "")
dbutils.widgets.text("resource_group", "")
dbutils.widgets.text("azure_ml_workspace_name", "")
dbutils.widgets.text("model_project_name", "")
dbutils.widgets.text("path_to_mlflow_experiment", "")

# COMMAND ----------

# MAGIC %md
# MAGIC ### Deploy Model as a Web Service in AML
# MAGIC
# MAGIC

# MAGIC The MLFlow model will conainerized and deployed as a web service with AML and Azure Container Instances

# COMMAND ----------

from pyspark.sql.types import *
from pyspark.sql.functions import *
import mlflow
import mlflow.spark
import mlflow.sklearn
import mlflow.azureml
from mlflow.exceptions import RestException
import azureml
import azureml.core

# COMMAND ----------

# MAGIC %md
# MAGIC ## Step 1: Upload and Read Sensor Dataset
# MAGIC
# MAGIC For the training dataset, you will need to upload some data to the Databricks File System (DBFS). Go to File > Upload Data and click "Browse" in the middle box to bring up your file explorer for your local computer. Navigate to the place where you downloaded the artifacts for this workshop and go into the `/Datasets` folder and choose `sensordata.csv`. Once you see a green checkmark, then you just need to press **Next** and then **Done** on the next screen.

# COMMAND ----------

# MAGIC %md
# MAGIC Here we will be creating a database to store some of the tables that we will create during this workshop. The first table will be a Delta Lake table that will hold our uploaded sensor data.

# COMMAND ----------

MODEL_PROJECT_NAME = dbutils.widgets.get("model_project_name")
spark.sql(f"CREATE DATABASE IF NOT EXISTS {MODEL_PROJECT_NAME}")
username = spark.sql("SELECT current_user()").collect()[0][0]
sensorData = spark.read.csv(f"dbfs:/FileStore/shared_uploads/{username}/sensordata.csv", header=True, inferSchema=True)
sensorData.write.saveAsTable(f"{DB_NAME}.sensor", format="delta", mode="overwrite")
dataDf = spark.table("sensor").where(col('Device') == 'Device001')

# COMMAND ----------

# MAGIC %md
# MAGIC With our sensor data table saved, we can create an MLFlow Experiment to house the metrics that we log during our training runs.
# MAGIC
# MAGIC First, within our workspace, we need to create a location for the experiment to be created. Go to a location and create a folder to hold the experiment. Copy the path to the newly-created folder into the `PATH_TO_MLFLOW_EXPERIMENT` variable.
# MAGIC
# MAGIC Next, we first establish a `MlflowClient()` which gives us a connection to the MLFlow Tracking Server and allows us to issue commands via the MLFlow API to do things like create experiments, which we do using `client.create_experiment()`.

# COMMAND ----------

from mlflow.tracking import MlflowClient
PATH_TO_MLFLOW_EXPERIMENT = "ENTER PATH HERE"
client = MlflowClient()
try:
  experiment_id = client.create_experiment(PATH_TO_MLFLOW_EXPERIMENT)
except RestException as r:
  print("Experiment Already Exists, loading experiment...")
except Exception as e:
  print(e)
mlflow.set_experiment(PATH_TO_MLFLOW_EXPERIMENT)

# COMMAND ----------

# MAGIC %md
# MAGIC In this next cell, we take the sensor data and create test and training datasets by splitting up the table using a randomized distribution of data.

# COMMAND ----------

import pandas as pd
import random

#Setup Test/Train datasets
data = dataDf.toPandas()
x = data.drop(["Device", "Time", "Sensor5"], axis=1)
y = data[["Sensor5"]]
train_x, test_x, train_y, test_y = train_test_split(x,y,test_size=0.20, random_state=30)

# COMMAND ----------

# MAGIC %md
# MAGIC With our training and test dataset ready, we are able to run a few training runs for our model.
# MAGIC
# MAGIC We are going to run three runs of the `RandomForestClassifier` from sklearn using the following parameters:
# MAGIC ```python
# MAGIC numEstimators = [10, 15, 20]
# MAGIC maxDepths = [15, 20, 25]
# MAGIC ```
# MAGIC
# MAGIC We will also be leveraging the sklearn autologger to log the parameters for each run, as well as key metrics and the trained model itself. The autologging capabilities of MLFlow make it even easier to get started with training your models and tracking your model performance over various training runs.

# COMMAND ----------

from sklearn.linear_model import LinearRegression, Lasso
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.ensemble import RandomForestRegressor

def fetch_logged_data(run_id):
    client = mlflow.tracking.MlflowClient()
    data = client.get_run(run_id).data
    tags = {k: v for k, v in data.tags.items() if not k.startswith("mlflow.")}
    artifacts = [f.path for f in client.list_artifacts(run_id, "model")]
    return data.params, data.metrics, tags, artifacts

numEstimators = [10, 15, 20]
maxDepths = [15, 20, 25]

mlflow.sklearn.autolog()

for (numEstimator, maxDepth) in [(numTree, maxDepth) for numEstimator in numEstimators for maxDepth in maxDepths]:
  with mlflow.start_run(run_name="Sensor Regression") as run:
    # Fit, train, and score the model
    model = RandomForestRegressor(max_depth = maxDepth, n_estimators = numEstimator)
    model.fit(train_x, train_y)
    preds = model.predict(test_x)

# COMMAND ----------

params, metrics, tags, artifacts = fetch_logged_data(run.info.run_id)

# COMMAND ----------

# MAGIC %md
# MAGIC ## Step 2: Deploy Model to a Azure Container Instance via MLFlow + AzureML
# MAGIC
# MAGIC The next few steps will walk you through the deployment of the model to Azure Machine Leaning Service.

# COMMAND ----------

from azureml.core import Workspace
from azureml.core.webservice import AciWebservice, AksWebservice
from datetime import datetime

# COMMAND ----------

# MAGIC %md
# MAGIC In this cell, we grab the latest run ID, which is needed to know what model from what run to deploy to AzureML.

# COMMAND ----------

expId = mlflow.get_experiment_by_name(PATH_TO_MLFLOW_EXPERIMENT).experiment_id
last_run_id = spark.read.format("mlflow-experiment").load(expId).orderBy(col("end_time").desc()).select("run_id").limit(1).collect()[0][0]
model_uri = "runs:/"+last_run_id+"/model"

# COMMAND ----------

# MAGIC %md
# MAGIC Here we establish a connection to the AzureML workspace so that we can deploy the model that is logged in MLFlow.

# COMMAND ----------

workspace_name = dbutils.widgets.get("azure_ml_workspace_name")
subscription_id = dbutils.widgets.get("subscription_id")
resource_group = dbutils.widgets.get("resource_group")

ws = Workspace.get(name=workspace_name,
               subscription_id=subscription_id,
               resource_group=resource_group)

# COMMAND ----------

# MAGIC %md
# MAGIC In this cell, we establish a `Deployment Configuration` in which we enable logging to Application Insights to ensure that we can capture and query model response and trace information for monitoring purposes.

# COMMAND ----------

service_config = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1, enable_app_insights=True, collect_model_data=True)

# COMMAND ----------

# MAGIC %md
# MAGIC In this last cell, the model from MLFlow and the Deployment Configuration are packaged together, sent to Azure ML, and deployed as an endpoint hosted on an Azure Container Instance.

# COMMAND ----------

azure_service, azure_model = mlflow.azureml.deploy(model_uri=model_uri,
                                                   service_name=endpointName,
                                                   workspace=ws,
                                                   deployment_config=service_config,
                                                   synchronous=True,
                                                   tags={"mlflowExperiment":PATH_TO_MLFLOW_EXPERIMENT, "modelProjectName": MODEL_PROJECT_NAME})


import paho.mqtt.client as mqtt
import ssl
import json
import _thread
import time
from datetime import datetime

broker = "a1vs29u7y7oh8s-ats.iot.eu-west-1.amazonaws.com"
caPath = "./AmazonRootCA1.pem"
certPath = "./certificate.pem.crt"
keyPath = "./private.pem.key"
topic = "sesnor/temp"

def on_connect(client, userdata, flags, rc):
    print("Connected to AWS IoT: " + str(rc))

client = mqtt.Client()
client.on_connect = on_connect
client.tls_set(ca_certs=caPath, certfile=certPath,
               keyfile=keyPath, tls_version=ssl.PROTOCOL_SSLv23)
client.tls_insecure_set(True)
client.connect(broker, 8883, 60)

def publishData():

    while (True):
        timestamp = datetime.now().strftime("%m/%d/%Y, %H:%M:%S")
        data = json.dumps({"timestamp": timestamp,
                           "device_id":"sensor-1",
                           "tempC": 10})
        client.publish(topic, payload=data,qos=0, retain=False)
        print("published")
        time.sleep(5)

_thread.start_new_thread(publishData,())

client.loop_forever()


import cv2
import numpy as np
import sys
import scipy.ndimage
import random
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvas

np.set_printoptions(threshold=sys.maxsize)

def brightness_contrast(image, contrast, brightness):
    return cv2.addWeighted(image, contrast, image, 0, brightness)

def swap_bg(image_):
    image = image_.copy()
    image[:,:,[0,1]] = image[:,:,[1,0]]
    return image

def swap_gr(image_):
    image = image_.copy()
    image[:,:,[1,2]] = image[:,:,[2,1]]
    return image

def swap_rb(image_):
    image = image_.copy()
    image[:,:,[0,2]] = image[:,:,[2,0]]
    return image

def image_histogram(image):
    plt.style.use('ggplot')

    fig = Figure()
    canvas = FigureCanvas(fig)
    ax = fig.subplots()
    ax.margins(x=0)

    if len(image.shape) == 3:
        ax.hist(image[:,:,0].flatten(), np.arange(256), color='blue', label='blue', histtype='step', linewidth=1)
        ax.hist(image[:, :, 1].flatten(), np.arange(256), color='green', label='green', histtype='step', linewidth=1)
        ax.hist(image[:, :, 2].flatten(), np.arange(256), color='red', label='red', histtype='step', linewidth=1)
        ax.set_xlabel('Intensity')
        ax.set_ylabel('Count')
        ax.set_xticks([0,51,51*2,51*3,51*4, 51*5])
        canvas.draw()
        histogram_image = np.array(canvas.renderer.buffer_rgba())

    else:
        ax.hist(image.flatten(), np.arange(256), histtype='step', linewidth=1, color='black')
        ax.set_xlabel('Intensity')
        ax.set_ylabel('Count')
        ax.set_xticks([0,51,51*2,51*3,51*4, 51*5])
        canvas.draw()
        histogram_image = np.array(canvas.renderer.buffer_rgba())

    return histogram_image

def hist_color(image):
    hist_b, bins_b = np.histogram(image[:, :, 0], bins=255, range=(0,256))
    hist_g, bins_g = np.histogram(image[:, :, 1], bins=255, range=(0,256))
    hist_r, bins_r = np.histogram(image[:, :, 2], bins=255, range=(0,256))
    return hist_b, bins_b, hist_g, bins_g, hist_r, bins_r

def hist_bw(image):
    hist, bins = np.histogram(image, bins=255, range=(0,256))
    return hist, bins

def convert_to_bw(image):

    if len(image.shape) == 3:
        return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    else: #if image has one channel just return the same
        return image

def resize_image(image, fx, fy):
    fx=float(fx)
    fy=float(fy)

    if fx < 1 or fy < 1:
        interpolation_method = cv2.INTER_AREA
    else:
        interpolation_method = cv2.INTER_LINEAR

    return cv2.resize(image, None, fx=fx, fy=fy, interpolation=interpolation_method)

def mirror(image):
    return np.fliplr(image)

def flip_upsidedown(image):
    return np.flipud(image)

def rotate_image(image):
    return np.rot90(image)

def replace_color(image_, color_to_replace, target_color, operator):
    image = image_.copy()
    color_to_replace = color_to_replace.split(sep=',')
    color_to_replace = [int(x) for x in color_to_replace]

    target_color = target_color.split(sep=',')
    target_color = [int(x) for x in target_color]

    if operator == '=':
        image[(image[:, :, 0] == color_to_replace[0]) & (image[:, :, 1] == color_to_replace[1]) & (image[:, :, 2] == color_to_replace[2])] = target_color
    elif operator == '<':
        image[(image[:, :, 0] < color_to_replace[0]) & (image[:, :, 1] < color_to_replace[1]) & (
                image[:, :, 2] < color_to_replace[2])] = target_color
    else:
        image[(image[:, :, 0] > color_to_replace[0]) & (image[:, :, 1] > color_to_replace[1]) & (
                image[:, :, 2] > color_to_replace[2])] = target_color

    print('returning')
    return image

def avg_blur(image_, k, times):
    image = image_.copy()
    k=int(k)
    times=int(times)
    for i in range(times):
        image = cv2.blur(image, (k,k))
    return image

def gaussian_blur(image_, k, times):
    image = image_.copy()
    k=int(k)
    times=int(times)
    for i in range(times):
        image = cv2.GaussianBlur(image, (k,k), 0)
    return image

def median_blur(image_, k, times):
    image = image_.copy()
    k=int(k)
    times=int(times)
    for i in range(times):
        image = cv2.medianBlur(image, k)
    return image

def add_border(image_, top=0, bottom=0, left=0, right=0, bordertype=cv2.BORDER_CONSTANT, value=[0,0,0]):
    image = image_.copy()
    bordertype_dict={'cv2.BORDER_CONSTANT': cv2.BORDER_CONSTANT,
                     'cv2.BORDER_REFLECT_101': cv2.BORDER_REFLECT_101,
                     'cv2.BORDER_REFLECT': cv2.BORDER_REFLECT,
                     'cv2.BORDER_REPLICATE': cv2.BORDER_REPLICATE,
                     'cv2.BORDER_WRAP': cv2.BORDER_WRAP
                     }
    if bordertype_dict[bordertype] == cv2.BORDER_CONSTANT:
        image = cv2.copyMakeBorder(image, top, bottom, left, right, bordertype_dict[bordertype], value=value)

    else:
        image = cv2.copyMakeBorder(image, top, bottom, left, right, bordertype_dict[bordertype])

    return image

def intensity_map(image_, map):
    image = image_.copy()
    map = 'COLORMAP_'+ map.upper().replace(' ', '_')

    map_dict = {
         'COLORMAP_AUTUMN' : 0,
          'COLORMAP_BONE' : 1,
          'COLORMAP_JET' : 2,
          'COLORMAP_WINTER' : 3,
          'COLORMAP_RAINBOW' : 4,
          'COLORMAP_OCEAN' : 5,
          'COLORMAP_SUMMER' : 6,
          'COLORMAP_SPRING' : 7,
          'COLORMAP_COOL' : 8,
          'COLORMAP_HSV' : 9,
          'COLORMAP_PINK' : 10,
          'COLORMAP_HOT' : 11,
          'COLORMAP_PARULA' : 12,
          'COLORMAP_MAGMA' : 13,
          'COLORMAP_INFERNO' : 14,
          'COLORMAP_PLASMA' : 15,
          'COLORMAP_VIRIDIS' : 16,
          'COLORMAP_CIVIDIS' : 17,
          'COLORMAP_TWILIGHT' : 18,
          'COLORMAP_TWILIGHT_SHIFTED' : 19,
          'COLORMAP_TURBO' : 20,
          'COLORMAP_DEEPGREEN' : 21
                }
    print(map)
    return cv2.applyColorMap(image, map_dict[map])

def histogram_equalization_bw(image):
    if len(image.shape) == 2:
        return cv2.equalizeHist(image)
    else:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
        image[:,:,0] = cv2.equalizeHist(image[:,:,0])
        return cv2.cvtColor(image, cv2.COLOR_YUV2BGR)

def blend_images(image1, image2, alpha):
    return cv2.addWeighted(image1, alpha, image2, (1-alpha), 0)

def blend_images_bw(image1, image2, percentage):
    return cv2.weighted(image1, percentage, image2, (1-percentage), 0)
    # return image1*percentage + image2*(1-percentage)

def blend_images_color(image1, image2, percentage):
    image1[:,:,0] = image1[:,:,0]*percentage + image2[:,:,0]*(1-percentage)
    image1[:,:,1] = image1[:,:,1]*percentage + image2[:,:,1]*(1-percentage)
    image1[:,:,2] = image1[:,:,2]*percentage + image2[:,:,2]*(1-percentage)
    return image1

def non_linear_blend(image1, image2, percentage):

    pass

def edge_detection(image, threshold1, threshold2, kernelsize, L2grad):
    threshold1 = int(threshold1)
    threshold2 = int(threshold2)
    kernelsize = int(kernelsize)
    if L2grad == 'True': L2grad = True
    else: L2grad = False
    edges = cv2.Canny(image, threshold1, threshold2, apertureSize=kernelsize, L2gradient=L2grad)
    return edges

def cartoonify(image_, thresh1, thresh2):
    # https: // stacks.stanford.edu / file / druid: yt916dh6570 / Dade_Toonify.pdf
    image = image_.copy()
    thresh1 = int(thresh1)
    thresh2 = int(thresh2)
    if len(image.shape) ==3:
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    else:
        gray = image
    gray = cv2.medianBlur(gray, 7)
    canny = cv2.Canny(gray, thresh1, thresh2)
    canny = cv2.dilate(canny,(2,2))
    #find contours to remove small regions to reduce clutter.
    contours, _ = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    print(contours)

    for i, contour in enumerate(contours):
        if cv2.contourArea(contour) < 10:
            for points in contour:
                print(points[0][0])
                print(canny.shape)
                # points[0][:,[0,1]] = points[0][:,[1,0]]
                print([points[0][1],points[0][0]])
                canny[points[0][1],points[0][0]]  = 0

    if len(image.shape)==3:
        color_image = image[::4, ::4, :]
    else:
        color_image = image[::4, ::4]

    for i in range(14):
        color_image = cv2.bilateralFilter(color_image, 9, 0, 0)
    color_image = cv2.resize(color_image, None, fx=4, fy=4, interpolation = cv2.INTER_LINEAR)
    color_image = cv2.medianBlur(color_image, 7)
    #quantize colors
    color_image = color_image // 24 * 24
    #when image is resized above it may get bigger than the original. so cut the extra rows and columns.
    if len(color_image.shape) == 3:
        color_image = color_image[0:canny.shape[0],0:canny.shape[1],:]
    else:
        color_image = color_image[0:canny.shape[0], 0:canny.shape[1]]

    #combining edges and color image
    if len(color_image.shape) ==3:
        color_image[canny == 255, :] = 0
    else:
        color_image[canny == 255] = 0

    return color_image

def extract_color(image, color):
    # extract single color from image
    color = color.split(sep=',')
    color = [int(x) for x in color]

    extracted = np.zeros_like(image)
    extracted[(image[:, :, 0] == color[0]) & (image[:, :, 1] == color[1]) & (
                 image[:, :, 2] == color[2])] = image[(image[:, :, 0] == color[0]) & (image[:, :, 1] == color[1]) & (
                 image[:, :, 2] == color[2])]

    # extracted[np.all(image[:,:,0] == color[0], image[:,:,1] == color[1], image[:,:,2] == color[2])] = image[np.all(image[:,:,0] == color[0], image[:,:,1] == color[1], image[:,:,2] == color[2])]
    return extracted

def mask_result_color(image, mask):
    #when a mask is given, show the resulting image.
    mask[mask>0]=1
    image[:, :, 0] = image[:, :, 0] * mask
    image[:, :, 1] = image[:, :, 1] * mask
    image[:, :, 2] = image[:, :, 2] * mask

    return image

def mask_result_bw(image, mask):
    #when a mask is given, show the resulting image.
    mask[mask > 0] = 1
    image[:, :] = image[:, :] * mask
    return image

def blending_pyramids(imageA, imageB, mask, levels):
    dst = np.zeros_like(mask)
    mask = cv2.normalize(mask,None,0,1,cv2.NORM_MINMAX)
    # mask=dst

    # mask = np.divide(mask,255)

    print(mask.max())

    #make Gaussian pyramids of images A and B
    imageA_pyr_g = [imageA]
    imageB_pyr_g = [imageB]
    mask_pyr_g = [mask]

    pyr_g_img_A = imageA_pyr_g[0]
    pyr_g_img_B = imageB_pyr_g[0]
    pyr_g_mask = mask_pyr_g[0]

    for i in range(levels-1):
        pyr_g_img_A = cv2.pyrDown(pyr_g_img_A)
        imageA_pyr_g.append(pyr_g_img_A)
        # print(pyr_g_img_A.shape)
        pyr_g_img_B = cv2.pyrDown(pyr_g_img_B)
        imageB_pyr_g.append(pyr_g_img_B)
        pyr_g_mask = cv2.pyrDown(pyr_g_mask)
        mask_pyr_g.append(pyr_g_mask)

    for items in imageA_pyr_g:
        print(items.shape)

    #make Laplacian pyramids of image A and B
    lap_pyr_a = []
    lap_pyr_b = []
    lap_pyr_a.append(imageA_pyr_g[-1])
    lap_pyr_b.append(imageB_pyr_g[-1])

    i=len(imageA_pyr_g)-1
    print('i')
    print(i)

    while i > -1:

        la = cv2.pyrUp(imageA_pyr_g[i])
        la = la[:imageA_pyr_g[i-1].shape[0], :imageA_pyr_g[i-1].shape[1]]
        lap_pyr_a.append(cv2.subtract(imageA_pyr_g[i - 1],la))  # i-1
        lb = cv2.pyrUp(imageB_pyr_g[i])
        lb = lb[:imageB_pyr_g[i-1].shape[0], :imageB_pyr_g[i-1].shape[1]]
        lap_pyr_b.append(cv2.subtract(imageB_pyr_g[i - 1], lb))  # i-1
        i-=1

    combined = []
    ci=0
    for a, b, m in zip(lap_pyr_a, lap_pyr_b, mask_pyr_g[::-1]):

        if a.shape[0] > m.shape[0]:
            a = a[:m.shape[0], :]
        if a.shape[1] > m.shape[1]:
            a = a[:, :m.shape[1]]

        if a.shape[0] < m.shape[0]:
            diff = m.shape[0] - a.shape[0]
            a = cv2.copyMakeBorder(src=a, top=0,bottom=diff, right=0, left=0, borderType=cv2.BORDER_REFLECT101)

        if a.shape[1] < m.shape[1]:
            diff = m.shape[1] - a.shape[1]
            a = cv2.copyMakeBorder(src=a, top=0, bottom=0, right=diff, left=0, borderType=cv2.BORDER_REFLECT101)

        if b.shape[0] > m.shape[0]:
            b = b[:m.shape[0], :]
        if b.shape[1] > m.shape[1]:
            b = b[:, :m.shape[1]]

        if b.shape[0] < m.shape[0]:
            diff = m.shape[0] - b.shape[0]
            b = cv2.copyMakeBorder(src=b, top=0, bottom=diff, right=0, left=0, borderType=cv2.BORDER_REFLECT101)

        if b.shape[1] < m.shape[1]:
            diff = m.shape[1] - b.shape[1]
            b = cv2.copyMakeBorder(src=b, top=0, bottom=0, right=diff, left=0, borderType=cv2.BORDER_REFLECT101)

        ma = cv2.multiply(m,a)
        one_minus_m_b = cv2.multiply(1-m, b)

        combined.append(cv2.add(ma, one_minus_m_b))

        ci+=1

    img = combined[0]

    for i, c in enumerate(combined):
        if i !=0:
            img = cv2.pyrUp(img)
            img = img[:c.shape[0], :c.shape[1]]
            img = cv2.add(img,c)

    return img

def ndimage_rotate(image, angle, axes=(1,0), reshape=True, output=None, order=3, mode='constant', cval=0.0, prefilter=True):
    return scipy.ndimage.rotate(image, angle, axes, reshape=True, output=None, order=3, mode='constant', cval=0.0, prefilter=True)

def gamma_correction(image, gamma):
    gamma= float(gamma)
    return (255 * (image/255)**(1/gamma)).astype(np.uint8)

def sketch_algo():
    pass

def pixelate(image, n):
    n = int(n)
    image_copy= image.copy()
    for i in range(n):
        image_copy = cv2.pyrDown(image_copy)
    pixelated =cv2.resize(src=image_copy, dsize=(image.shape[1], image.shape[0]), interpolation=cv2.INTER_NEAREST)
    return pixelated

def perspective_transform_etc():
    pass

def negative_color_picture(image):
    return 255-image

def pseudo_solarised():
    pass

def add_Gaussian_noise(image, sigma, channel):
    sigma = float(sigma)
    image = image.copy()
    if len(image.shape) == 2: channel = -1 #check if image is grayscale
    else:
        if channel == 'Blue': channel = 0
        if channel == 'Green': channel = 1
        if channel == 'Red': channel = 2

    random = np.random.normal(loc=0, scale=sigma, size=(image.shape[0], image.shape[1]))
    if channel !=-1: #if color
        image[:,:,channel] = image[:,:,channel] + random
    else: #if grayscale
        image = image + random
    return image

def add_noise02():
    pass

def noise_bands(image_, width, period, orientation):
    image = image_.copy()

    if orientation == 'horizontal':
        shape_val = image.shape[0]

    if orientation == 'vertical':
        shape_val = image.shape[1]

    band = np.arange(width)

    tiled = np.tile(band, int(shape_val/period))
    tiled = tiled.reshape(-1, width)

    addition_arr = np.arange(period, shape_val, period)

    addition_arr = addition_arr.T

    addition_arr = np.expand_dims(addition_arr,axis=1)

    addition_arr = np.repeat(addition_arr, tiled.shape[1], axis=1)

    tiled = tiled + addition_arr

    tiled = tiled.flatten()

    tiled = tiled[tiled < shape_val]

    return tiled

def band_noise_horizontal(image_, width, period, magnitude):
    image = image_.copy()
    width = int(width)
    period = int(period)
    magnitude = int(magnitude)

    bands = noise_bands(image, width, period, 'horizontal')
    print(bands)
    if len(image.shape) > 2:
        image[bands, :, :] = image[bands, :, :] + magnitude
    else:
        image[bands, :] = image[bands, :] + magnitude

    return image

def band_noise_vertical(image_, width, period, magnitude):
    image = image_.copy()
    width = int(width)
    period = int(period)
    magnitude = int(magnitude)

    bands = noise_bands(image, width, period, 'vertical')
    if len(image.shape) > 2:
        image[:, bands, :] = image[:, bands, :] + magnitude
    else:
        image[:, bands] = image[:, bands] + magnitude

    return image

def saltnpepper_noise_single_channel(image, amount, lower_threshold, upper_threshold):
    #amount should be a float
    # mask = np.random.rand(image.shape[0], image.shape[1])
    # empty_image = np.zeros_like(image)
    # empty_image[mask < amount] = 1

    # flat_empty = empty_image.flatten()

    # flat_image = image.flatten()
    # print(flat_image[flat_image==0].shape)
    # sample = random.sample(range(flat_image.shape[0]), int(amount * flat_image.shape[0]))
    #
    # print(flat_image.shape)
    # print(len(sample))
    #
    # chosen = flat_image[sample]
    #
    # print(chosen.shape)
    #
    # print(chosen[chosen==0].shape)
    # chosen[chosen > upper_threshold] = 0
    # print(chosen[chosen == 0].shape)
    # print(flat_image[flat_image == 0].shape)
    # flat_image[sample][flat_image[sample] > upper_threshold] = 0
    # print(flat_image[flat_image == 0].shape)
    # returned_image = flat_image.reshape(image.shape)
    #
    # return returned_image

    zero_arr = np.zeros_like(image)
    flatimage = image.flatten()

    lower_list = [1,255]

    flatimage[flatimage>upper_threshold] = np.random.randint(0,2,flatimage[flatimage>upper_threshold].shape) * flatimage[flatimage>upper_threshold]
    flatimage[flatimage < lower_threshold] = np.random.choice(lower_list, size=flatimage[flatimage < lower_threshold].shape) * \
                                             flatimage[flatimage < lower_threshold]
    flatimage = flatimage.reshape(image.shape)

    return flatimage

def dither(image_, n):
    # Implements ordered dithering using a 2x2 matrix as described in https://en.wikipedia.org/wiki/Ordered_dithering
    # M = np.array([[0, 0.5], [0.75, 0.25]])

    image = image_.copy()

    n = int(n)

    img = image[::2, ::2]
    img[img>0] = 255

    img1 = image[::2, 1::2]
    img1[img1 > 0.5*n] = 255

    img2 = image[1::2, ::2]
    img2[img2 > 0.75*n] = 255

    img3 = image[1::2, 1::2]
    img3[img3 > 0.25*n] = 255

    return image

def contrast_stretching_single_channel(image, lower_threshold, upper_threshold):
    original_copy = image.copy()
    original_copy[image >= upper_threshold] = 255
    original_copy[image <= lower_threshold] = 0
    original_copy = 255*((image - lower_threshold) / (upper_threshold - lower_threshold))
    # print(original_copy)
    return original_copy#.astype(np.uint8)

def contrast_stretching_RGB_channel(image, lower_threshold, upper_threshold):
    image[:, :, 0] = contrast_stretching_single_channel(image[:, :, 0], lower_threshold, upper_threshold)
    image[:, :, 1] = contrast_stretching_single_channel(image[:, :, 1], lower_threshold, upper_threshold)
    image[:, :, 2] = contrast_stretching_single_channel(image[:, :, 2], lower_threshold, upper_threshold)

    # image = 255 * cv2.normalize(image, None, alpha=0, beta=1.2, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)

    return image.astype(np.uint8)


# [num. channel, height, width], [num, size]
import numpy as np
from config import N, W, LESS_N
import torch

def seqMappingCost(tasks, schedule, flexable=False):
    time = 0
    cost = 0
    for i in range(0, len(schedule)):
        t_idx = int(schedule[i])
        if t_idx >= LESS_N and flexable:
            continue
        tk = tasks[:, t_idx]
        exe_time = max(tk[0], time)
        time = (exe_time + tk[2]) * (exe_time <= (tk[0] + tk[1])) + time * (exe_time > (tk[0] + tk[1]))
        cost = cost + (exe_time - tk[0]) * tk[3] * (exe_time <= (tk[0] + tk[1]))
        cost = cost + tk[4] * (exe_time > (tk[0] + tk[1]))

    return cost

# [height, width], [size] ([0 1 ..0, 1 0 ..., ])
def predictCost(tasks, predict, _N=N, flexable=False):
    # num = tasks.shape[0]
    schedule = np.zeros([_N])
    predict = np.reshape(predict, [_N, _N + 1])
    indices = set(i for i in range(0, _N))
    for i in range(0, _N):
        srt = np.argsort(predict[:, i])[::-1]
        while srt[0] not in indices:
            srt = srt[1::]
        schedule[i] = srt[0]
        indices.remove(srt[0])

    return seqMappingCost(tasks, schedule, flexable=flexable)

def capedActivation(cap=W):
    def f(tensor):
        c = torch.ones(tensor.size()) * cap
        c = c.to('cuda')
        return torch.fmin(tensor, c)

    return f

# outputs and labels shape: [1,110]
def cost_stat(LOADER, _model, flexable=False):
    L = len(LOADER)
    out_cost = np.zeros([L])
    optimal_cost = np.zeros([L])
    for _i, _data in enumerate(LOADER, 0):
        if _i % 500 == 0:
            print(_i)
        _inputs, _labels = _data
        tasks = _inputs[0, 0, :, :].cpu().detach().numpy()
        _outputs = _model(_inputs.to('cuda').float())
        out_cost[_i] = predictCost(tasks, _outputs[0, :].cpu().detach().numpy(), flexable=flexable)
        optimal_cost[_i] = predictCost(tasks, _labels[0, :].cpu().detach().numpy(), _N=LESS_N)

    return out_cost, optimal_cost


from Bio import SeqIO

input_file = "../Code/seq/sequences.fasta"
output_file = open("./red_sequences.fasta", "w+")
coverage = 50

fasta_sequences = SeqIO.parse(open(input_file),'fasta')
counter = 0

for fasta in fasta_sequences:

    if(counter == coverage):
        break

    output_file.write(">"+fasta.id+"\n"+str(fasta.seq)+"\n")

    counter +=1

print("DONE")


from base import *
from matplotlib import pyplot as plt
from filters.spatialFilters import spatialFilterClass
from filters.frequencyFilters import frequencyFilterClass

class dataLoader:
    def __init__(self, cfg):
        self.cfg = cfg
        self.spatial = cfg["spatial"]
        self.frequency = cfg["frequency"]
        self.objS = spatialFilterClass(cfg)
        self.objF = frequencyFilterClass(cfg)

    def loadImage(self):
        if self.cfg["type"] == "image":
            imagePath = Image.open(self.cfg["path"]) #Loads Image
            imgResize = imagePath.resize((self.cfg["height"],self.cfg["width"])) #Resizes Image
            self.img = np.array(imgResize) #Converts to numpy array
            self.imgPadded = np.pad(self.img,((1,1),(1,1),(0,0)),'constant')
        else:
            file = open(self.cfg["path"], "r")
            matrix = []
            for row in file:
                matrix.append([int(x) for x in row.split()])

            self.img = np.array(matrix)
            self.imgPadded = np.pad(self.img, [(1, 1), (1, 1)], mode='constant')

    def save(self,ans):
        save_path = "outputs/result"
        if self.cfg["type"] == "image":
            plt.imshow(ans)
            plt.savefig(save_path +".jpg")

        else:
            f  = open(save_path, "w")
            f.write(str(ans))
            f.close()

    def execute(self):
        self.loadImage()
        if self.spatial:
            for i in self.spatial:
                if self.spatial[i] is True:
                    try:
                        method = getattr(self.objS,i)
                        ans = method(self.imgPadded)
                    except AttributeError:
                        ans = None

        if self.frequency:
            for i in self.frequency:
                if self.frequency[i] is True:
                    ans = self.objF.start(self.img,i)

        if ans is None:
            print("Incorrect Domain / Filter not found ")
        else:
            if self.cfg["save"]:
                self.save(ans)
            else:
                display(self.cfg["type"], ans)


import json
import time
start = time.time()

# First five expanded nodes, instance one: (2, 2), (2, 2), (1, 2), (2, 1), (2, 3)
# First five expanded nodes, instance two: (3, 2), (3, 2), (2, 2), (3, 1), (3, 3)
# Path found: (2, 2), (1, 2), (1, 3), (1, 4), (2, 4), (2, 5), (3, 5) cost: 5.3
# Path 2 found: (3, 2), (2, 2), (1, 2), (1, 3), (1, 4), (2, 4), (2, 3), (3, 3), (3, 4), (4, 4) cost: 8.2

# Action costs defined
action_left = 10
action_right = 9
action_up = 8
action_down = 7
action_suck = 2

# Node object which holds the node location, cost, and cleanliness status
class Node(object):
    location_row = 0
    location_col = 0
    cost = 0
    status = 0

    def __init__(self, location_row, location_col, cost, status):
        self.location_row = location_row
        self.location_col = location_col
        self.cost = cost
        self.status = status

if __name__ == '__main__':
    print('Iterative Deepening')

    # Changing this file will change the input instance.
    # instanceOne.json for instance one, instanceTwo.json for instance two
    inputFile = open('instanceTwo.json')
    squares = json.load(inputFile)['squares']
    startingRow = 0
    startingCol = 0
    depth = 0

    rowNum = 0
    colNum = 0

    # This loop finds the starting point for the vacuum within the graph and sets it to 0
    for row in squares:
        for col in row:
            if col == 2:
                startingCol = colNum
                startingRow = rowNum
                squares[rowNum][colNum] = 0
            colNum += 1
        rowNum += 1
        colNum = 0

    # Define the size of the room, the initial fringe node, and the initial number of nodes to be expanded
    rowNum = len(squares)
    colNum = len(squares[0])
    fringe = [Node(startingRow, startingCol, 0, 0)]
    numberOfExpansions = 1
    expandedNodes = 0
    generatedNodes = 0

    # While there are any dirty rooms, continue
    while any(1 in square for square in squares):
        i = 0

        # Expand a node for each node placed in the previous fringe (i.e. increases the depth by one each iteration)
        while i < numberOfExpansions:
            # Take from the front of the fringe
            currentNode = fringe.pop(0)
            expandedNodes += 1
            print(
                'Expanded Node: ' + '(' + str(currentNode.location_row) + ', ' + str(currentNode.location_col) +
                ') Cost: ' + str(currentNode.cost) + ' Status: ' + str(currentNode.status))

            # If the room is dirty, clean it and check if we're finished
            if currentNode.status == 1:
                squares[currentNode.location_row][currentNode.location_col] = 0
                for row in squares:
                    print(row)
                if not any(1 in square for square in squares):
                    end = time.time()
                    print('Expanded Nodes: ' + str(expandedNodes) +
                          ' Generated Nodes: ' + str(generatedNodes + expandedNodes) +
                          ' Depth Searched: ' + str(depth) +
                          ' Execution Time: ' + str(end - start))
                    print('Success')
                    exit(0)

                # Add a node for the suck operation
                fringe.append(Node(currentNode.location_row,
                                   currentNode.location_col,
                                   currentNode.cost + action_suck,
                                   0
                                   ))
            # If it is in bounds, add a node for the up operation (up first because it is the lowest row)
            if currentNode.location_row - 1 > -1:
                fringe.append(Node(currentNode.location_row - 1,
                                   currentNode.location_col,
                                   currentNode.cost + action_up,
                                   squares[currentNode.location_row - 1][currentNode.location_col]
                                   ))
            # If it is in bounds, add a node for the left operation
            # (left next because it is the second lowest row # and a lower column number than right)
            if currentNode.location_col - 1 > -1:
                fringe.append(Node(currentNode.location_row,
                                   currentNode.location_col - 1,
                                   currentNode.cost + action_left,
                                   squares[currentNode.location_row][currentNode.location_col - 1]
                                   ))
            # If it is in bounds, add a node for the right operation
            # (right next because it is the second lowest row # and a larger column number than left)
            if currentNode.location_col + 1 < colNum:
                fringe.append(Node(currentNode.location_row,
                                   currentNode.location_col + 1,
                                   currentNode.cost + action_right,
                                   squares[currentNode.location_row][currentNode.location_col + 1]
                                   ))
            # If it is in bounds, add a node for the down operation
            # (down last because it is the largest row and column number)
            if currentNode.location_row + 1 < rowNum:
                fringe.append(Node(currentNode.location_row + 1,
                                   currentNode.location_col,
                                   currentNode.cost + action_down,
                                   squares[currentNode.location_row + 1][currentNode.location_col]
                                   ))

            i += 1
        # increase the depth and decide how many nodes to expand next, then clear the fringe to regenerate all nodes
        depth += 1
        numberOfExpansions = len(fringe) + 1
        generatedNodes += len(fringe)
        fringe = [Node(startingRow, startingCol, 0, 0)]

    print('Success')


import torch.hub
from torch.hub import load_state_dict_from_url
import argparse

parser = argparse.ArgumentParser(description='Download PyTorch pretrained model')

parser.add_argument('-u', '--url', type=str, metavar='URL',
                    help="url for pretrained checkpoint your download")

def main():
    args = parser.parse_args()

    torch.hub._validate_not_a_forked_repo=lambda a,b,c: True
    hub_model_names = torch.hub.list('facebookresearch/WSL-Images')

    state_dict = load_state_dict_from_url(args.url, progress=True)

if __name__ == '__main__':
    main()


from env import ENV
import act_section_parser
from backend.graph_io import lkg_to_json

CASE_ID_TO_FILE = dict()
def compute_mapping():
    with open("{}/doc_path_ttl_id.txt".format(ENV["DATASET_PATH"])) as f:
        for line in f.readlines():
            line = line.strip()

            file_name, title, case_id = line.split("-->")
            CASE_ID_TO_FILE[case_id] = file_name+".txt"

def map_acts_with_cases(j):
    compute_mapping()
    # i = 0

    all_cases = list(CASE_ID_TO_FILE.keys())
    for i, case in enumerate(page_of_cases):
        case_file = CASE_ID_TO_FILE[case]
        print("Running act-case mapper for case {}: {}".format(i+1, case_file))
        acts = act_section_parser.fetch_all_acts_in_a_case(case_file)
        # print(acts)
        for act in acts:
            if act in j_new:
                j_new.add_edge(act, case)

    return(j)


from pathlib import Path
import os
import logging

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-wd()1466fa+e@$=beda94(0i4m+7k#04(laqwmuv=6*h6#et0@'

# Load variables from environment
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(",")
DB_DIR = Path(os.environ.get('DB_DIR', 'data'))
DEBUG = bool(os.environ.get('DEBUG', False))
DEBUG_TOOLBAR = bool(os.environ.get('DEBUG_TOOLBAR', False))
DEBUG_HTTP = bool(os.environ.get('DEBUG_HTTP', False))

# Create DB dir if it doesn't exist
if not os.path.exists(DB_DIR):
    os.makedirs(DB_DIR, exist_ok=True)

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'corsheaders',
    'rest_framework',

    'potoforio.core'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
]

ROOT_URLCONF = 'potoforio.potoforio.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'potoforio.potoforio.wsgi.application'

# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': (DB_DIR or BASE_DIR) / 'db.sqlite3',
    }
}

# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"

CORS_ORIGIN_ALLOW_ALL = True

# Allow correct work for basic auth via nginx proxy
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [],
    'DEFAULT_PERMISSION_CLASSES': [],
}

# If debug enable, configurate debug_toolbar
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html
if DEBUG_TOOLBAR:
    INSTALLED_APPS += [
        'debug_toolbar',
    ]

    MIDDLEWARE += [
        'debug_toolbar.middleware.DebugToolbarMiddleware',
    ]

    # https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#configure-internal-ips
    import socket
    hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
    INTERNAL_IPS = [ip[: ip.rfind(".")] + ".1" for ip in ips] + ["127.0.0.1", "10.0.2.2"]

LOG_PATH = DB_DIR / 'log.txt'
LOG_FORMAT = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
LOG_LEVEL = logging.DEBUG if DEBUG else logging.INFO

# Enable logging in to file
logging.basicConfig(filename=LOG_PATH, level=LOG_LEVEL, format=LOG_FORMAT)

# Enable logging in to console
console = logging.StreamHandler()
console.setLevel(LOG_LEVEL)
formatter = logging.Formatter(LOG_FORMAT)
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)


# -*- coding: utf-8 -*-

from __future__ import unicode_literals, division, absolute_import
import logging
from datetime import timedelta
from accio import celery_app
from redis import Redis

class RedisHandler(logging.Handler):
    def __init__(self, task_name, task_id, level):
        logging.Handler.__init__(self, level=level)
        self.redis_db = Redis.from_url(celery_app.conf['ACCIO_LOGVAULT_URL'])
        self.formatter = logging.Formatter('[%(asctime)s] %(levelname)s %(message)s')
        self.task_name = task_name
        self.task_id = task_id

    def emit(self, record):
        k = 'logs:%s:%s' % (self.task_name, self.task_id)
        self.redis_db.rpush(k, self.format(record))
        self.redis_db.expire(k, timedelta(weeks=1))

def getLogger(task_request):
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    if hasattr(task_request, 'task'):
        logger.addHandler(RedisHandler(task_request.task, task_request.id, level=logging.INFO))
    return logger


# 导入Flask类
from flask import Flask, request as rq
import coordinationTransform as a
# 实例化，可视为固定格式
app = Flask(__name__)

# 接口测试
@app.route('/test', methods=['GET'])
def hello_world():
    print("form:", rq.form)
    print("data:", rq.data)
    print("values:", rq.values)
    print("args:", rq.args)
    print("json:", rq.json)

    return rq.json

# 启动web应用，端口为5000
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)


#!/usr/bin/env python
import sys
from datetime import datetime
from math import pi

# Python Assignment 1
# Question 1
print("Twinkle, twinkle, little star,\n\t\
How I wonder what your!\n\t\t\
Up above the world so high,\n\t\t\
Like a diamond in the sky,\n\
Twinkle, twinkle, little star,\n\t\
How I wonder what you are")

# Question 2
print(sys.version)

#Question 3
today = datetime.now()
print(today.strftime("Date = %B %d, %Y\nTime =  %H:%M:%S"))

#Question 4
radius = float(input("enter a radius to compute area of the circle: "))
area = pi*pow(radius,2)
print("Area of a circle for a radius of ",radius," is: ",area)

#Question 5
Fname = input("enter your first name: ")
Lname = input("enter your last name: ")
print(Lname,"",Fname)

#Question 6
num1 = float(input("Enter a first number: "))
num2 = float(input("Enter a second number: "))
print("Addition of ",num1," & ",num2," is ",num1+num2)


from typing import List
from schemas.jobs import Job, JobIn, JobOut
from fastapi import APIRouter, Depends, HTTPException, status, Query
from schemas.jobs import BaseJob
from sqlalchemy.ext.asyncio import AsyncSession
from dependency import get_current_user, get_db
from sql_app.crud import Jobs_CRUD
from sql_app.models import Users

router = APIRouter()

@router.post('create', response_model=JobOut)
async def create_job(job:BaseJob, current_user:Users = Depends(get_current_user),
         db:AsyncSession = Depends(get_db)):
    if current_user.is_company:
        new_job = await Jobs_CRUD.create(current_user.id, job, db )
        return new_job
    else:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail='Only companies can post vacancies')

@router.get('get_list', response_model=List[JobOut])
async def get_list_jobs(offset:int = Query(..., ge=0), limit:int = Query(..., ge=0), db: AsyncSession = Depends(get_db)):
    result = await Jobs_CRUD.get_list_of_jobs(offset, limit, db)
    result = result.scalars().all()
    if result:
        return result
    else:
        raise HTTPException(status.HTTP_404_NOT_FOUND, detail='Jobs not found')

@router.get('by_id', response_model=JobOut)
async def get_job_by_id(pk: int = Query(..., ge=0), db: AsyncSession = Depends(get_db)):
    result =  await Jobs_CRUD.get_job_by_id(pk, db)
    result = result.scalars().all()
    if result:
        return result
    else:
        raise HTTPException(status.HTTP_404_NOT_FOUND, detail='Jobs not found')

@router.put('update', response_model=JobOut)
async def update_job(id: int, input_job:BaseJob, current_user = Depends(get_current_user),
         db: AsyncSession = Depends(get_db)):
    '''обновлять  вакансии могут владельцы или суперюзер'''

    job = await Jobs_CRUD.get_job_by_id(id, db)
    if job.user_id == current_user.id: # тут еще будет проверка на суперпользователя
        updated_job = await Jobs_CRUD.update_job(id, input_job, db)
        return updated_job
    else:
        raise HTTPException(status_code = status.HTTP_403_FORBIDDEN, detail="User Without enough privileges" )

@router.delete('delete', response_model=JobOut)
async def delete_job(id: int, current_user = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
    '''удалять  вакансии могут владельцы или суперюзер'''
    job = await Jobs_CRUD.get_job_by_id(id, db)
    if job:
        if job.user_id == current_user.id:
            result = await Jobs_CRUD.delete_job(id, db)
            return result
        else:
            raise HTTPException(status_code = status.HTTP_403_FORBIDDEN, detail="User Without enough privileges" )
    else:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="This job does not exist")


# %%

import sys
sys.path.append('/Users/williamlopez/Documents/Maastricht University/Internship paper/William/Slobs/new/Python')

import os
import six
import numpy as np
import pandas as pd
import seaborn as sns
import time
import matplotlib.pyplot as plt
from sklearn import tree
import joblib
from imblearn.over_sampling import SMOTE
import lime
import lime.lime_tabular
from sklearn.calibration import calibration_curve, CalibratedClassifierCV
from sklearn import ensemble
import tqdm
from nonconformist.cp import TcpClassifier
from nonconformist.nc import NcFactory
from nonconformist.cp import IcpClassifier
from sklearn.ensemble import RandomForestClassifier
from nonconformist.evaluation import cross_val_score
from nonconformist.evaluation import ClassIcpCvHelper, RegIcpCvHelper
from nonconformist.evaluation import class_avg_c, class_mean_errors, class_one_err, class_one_c, class_empty, class_two_c
from nonconformist.evaluation import reg_mean_errors, reg_median_size

from nonconformist.base import ClassifierAdapter, RegressorAdapter
from nonconformist.icp import IcpClassifier, IcpRegressor
from nonconformist.nc import MarginErrFunc
from nonconformist.nc import ClassifierNc, RegressorNc, RegressorNormalizer
from nonconformist.nc import AbsErrorErrFunc, SignErrorErrFunc

from nonconformist.base import OobClassifierAdapter, OobRegressorAdapter
from nonconformist.icp import OobCpClassifier, OobCpRegressor

from Utilities import Preprocessing as preprocessing
# %%
#* Loaing and formatting data
path = os.getcwd()

path =  '/Users/williamlopez/Documents/Maastricht University/Internship paper/William/Slobs/new'
test = pd.read_csv(path + '/data/slobs_2019_06_test_all.csv')
cvtrain = pd.read_csv(path + '/data/slobs_2019_05_cvtrain_all.csv')
train = pd.read_csv(path + '/data/slobs_2019_04_train.csv')
val = pd.read_csv(path + '/data/slobs_2019_05_val.csv')

prepro = preprocessing()

x_train, x_val, x_test, y_train, y_val, y_test, x_cvtrain, y_cvtrain, x_train_unbalanced, y_train_unbalanced, x_cvtrain_unbalanced, y_cvtrain_unbalanced, og_features, og_features_train, catcolumns, numcolumns = prepro.Get_sets(train, val, test, cvtrain)

# %%
#*loading feature sets from the feature selection results

x_cvtrain, x_cvtrain_unbalanced, x_train, x_train_unbalanced, x_val, x_test = prepro.FeatureSelection(og_features, og_features_train, x_cvtrain, x_cvtrain_unbalanced, x_train, x_train_unbalanced, x_val, x_test)

# %%
model = RandomForestClassifier(n_estimators = 300, n_jobs =-1)

# %%
nc = NcFactory.create_nc(model)	# Create a default nonconformity function
icp = IcpClassifier(nc)			# Create an inductive conformal classifier

x_train_np = x_cvtrain_unbalanced.to_numpy(copy = True)
x_val_np = x_val.to_numpy(copy = True)
x_test_np = x_test.to_numpy(copy = True)

y_train_np = y_cvtrain_unbalanced.to_numpy(copy = True)
y_val_np = y_val.to_numpy(copy = True)
y_test_np = y_test.to_numpy(copy = True)

# %%
print('fitting inductive conformal predictor')
# Fit the ICP using the proper training set
icp.fit(x_train_np, y_train_np)
print('calibrating inductive conformal prediction')
# Calibrate the ICP using the calibration set
icp.calibrate(x_val_np, y_val_np)
print('predicting inductive conformal prediction')
# Produce predictions for the test set, with confidence 95%
prediction = icp.predict(x_test_np, significance=0.05)
prediction_conf_cred = pd.DataFrame(icp.predict_conf(x_test_np),
                                    columns=['Label', 'Confidence', 'Credibility'])
# %%
#Cross validation of the conformal predictor

#icp = IcpClassifier(ClassifierNc(ClassifierAdapter(model),MarginErrFunc()))

icp = OobCpClassifier(ClassifierNc(OobClassifierAdapter(RandomForestClassifier(n_estimators=300, oob_score=True))))

significance = np.arange(0,1,0.025)
significance[0] = 0.01
icp_cv = ClassIcpCvHelper(icp)

scores = cross_val_score(icp_cv,
                         x_train_np,
                         y_train_np,
                         iterations=1,
                         folds=5,
                         scoring_funcs=[class_mean_errors, class_one_err, class_avg_c, class_one_c, class_empty, class_two_c],
                         significance_levels=significance,
                         verbose = True)

print('Classification: SLOBS')
scores = scores.drop(['fold', 'iter'], axis=1)

scores2 = scores.groupby(['significance']).mean()
print(scores2)

#%%

scores2 = scores2.reset_index()

# %%
#cross validated cp

icp = OobCpClassifier(ClassifierNc(OobClassifierAdapter(RandomForestClassifier(n_estimators=100, oob_score=True))))

x_train_np = x_train.to_numpy(copy = True)
x_val_np = x_val.to_numpy(copy = True)
x_test_np = x_test.to_numpy(copy = True)

y_train_np = y_train.to_numpy(copy = True)
y_val_np = y_val.to_numpy(copy = True)
y_test_np = y_test.to_numpy(copy = True)

print('fitting inductive conformal predictor')
# Fit the ICP using the proper training set
icp.fit(x_train_np, y_train_np)

print('predicting inductive conformal prediction')
# Produce predictions for the test set, with confidence 95%
prediction = icp.predict(x_test_np, significance=0.05)

# %%
scores3 = scores2.copy(deep = True)
scores3.reset_index(inplace = True)
# %%

#standard icp
icp = IcpClassifier(ClassifierNc(ClassifierAdapter(model)))
icp.fit(x_train_np, y_train_np)
icp.calibrate(x_val_np, y_val_np)
predictions_knncv_icp = icp.predict(x_test_np, significance = None)

predictions_knncv_icp_df = pd.DataFrame(data = predictions_knncv_icp, columns = ['0','1'])

predictions_knncv_icp_df['target'] = y_test_np
scoring_funcs = [class_mean_errors, class_one_err, class_avg_c, class_one_c, class_empty, class_two_c]

j=0
predictions_knncv_icp =  predictions_knncv_icp_df.to_numpy(copy = True)

columns = ['fold','significance',] + [f.__name__ for f in scoring_funcs]
df2 = pd.DataFrame()

for k, s in enumerate(significance):

    #********Knn****************#
    scores2 = [scoring_func(predictions_knncv_icp[:,:2], predictions_knncv_icp[:,2], s) for scoring_func in scoring_funcs]
    df_score2 = pd.DataFrame([[j, s] + scores2], columns=columns)
    df2 = df2.append(df_score2, ignore_index=True)

df2 = df2.drop(['fold'], axis=1)
resultscv_icp = df2.copy(deep = True)

#%%

plt.title('Error rate of predictions containing only a single output label')

plt.scatter( x = scores2.significance, y = scores2.class_one_err)
plt.plot(scores2.significance, scores2.class_one_err)
plt.xlabel('significance level')
plt.ylabel('Class one errors')
plt.show()
# %%

plt.title('Average number of classes per prediction')
plt.scatter( x = scores2.Significance, y = scores2.class_avg_c)
plt.plot(scores2.significance, scores2.class_avg_c)
plt.xlabel('significance level')
plt.ylabel('Avg N classes')
plt.show()

# %%

plt.title('Rate of prediction sets containing only a single class label')
plt.scatter( x = scores2.significance, y = scores2.class_one_c)
plt.plot(scores2.significance, scores2.class_one_c)
plt.xlabel('significance level')
plt.ylabel('One class rate')
plt.show()

# %%

plt.title('Rate of empty prediction sets ')
plt.scatter( x = scores2.significance, y = scores2.class_empty)
plt.plot(scores2.significance, scores2.class_empty)
plt.xlabel('significance level')
plt.ylabel('Empty sets')
plt.show()

# %%

f, ax = plt.subplots(figsize=(6, 6))
plt.title('Average error rate')
ax.scatter(x = scores2.significance, y = scores2.class_mean_errors)
ax.plot(scores2.significance, scores2.class_mean_errors)
##ax.plot([0, 1], [0, 1],ls="--", transform=ax.transAxes)
lims = [np.min([ax.get_xlim(), ax.get_ylim()]),  # min of both axes
        np.max([ax.get_xlim(),ax.get_ylim()]),  # max of both axes
        ]
ax.plot(lims, lims, ls="--",  alpha=0.75, zorder=0) #ax1.set_aspect('equal')
ax.set_xlim(lims)
ax.set_ylim(lims)
plt.xlabel('Significance level')
plt.ylabel('Average error rate')
plt.show()

#%%
#printing all at the same time

scores2 = resultscv_icp.copy(deep = True)

x1 = scores2['significance']
x2 = scores2['significance']
x3 = scores2['significance']

y1 = scores2['class_two_c']
y2 = scores2['class_one_c']
y3 = scores2['class_empty']

n1 = 'Two class rate'
n2 ='One class rate'
n3 = 'Empty sets'

fig = plt.figure()
ax1 = fig.add_subplot(111)
plt.title('Output set rate ICP')

ax1.scatter(x1, y1, s = 10, marker = "s", label = n1)
ax1.plot(x1, y1)

ax1.scatter(x2, y2, s = 10, marker = "o", label = n2)
ax1.plot(x2, y2)

ax1.scatter(x3, y3, s = 10, marker = "*", label = n3)
ax1.plot(x3, y3)

plt.legend(loc='upper right')
plt.xlabel('significance level')
#plt.ylabel(self.y_ax)
plt.show()

#%%
scores2.to_excel('/Users/williamlopez/Documents/Maastricht University/Internship paper/William/Slobs/new/output/ICPtestscores.xlsx')