import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

from functions import noso
from functions import dtdu_backward
from functions import dodt

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
dtype = torch.float

class fcn(nn.Module):
    def __init__(self, task, thresh, tau_m, tau_s, num_steps, frate):
        super(fcn, self).__init__()
        self.task = task
        self.thresh = thresh
        self.tau_m = tau_m
        self.tau_s = tau_s
        self.num_steps = num_steps
        self.frate = frate

        if self.task == 'mnist':
            self.cfg_fc = [784, 400, 10]

        elif self.task == 'nmnist':
            self.cfg_fc = [34*34*2, 800, 10]
            self.num_steps = 300

        self.fc1 = nn.Linear(self.cfg_fc[0], self.cfg_fc[1], bias=False).float()
        self.fc2 = nn.Linear(self.cfg_fc[1], self.cfg_fc[2], bias=False).float()
        nn.init.normal_(self.fc1.weight, mean=0, std=np.sqrt(2/self.cfg_fc[0]))
        nn.init.normal_(self.fc2.weight, mean=0, std=np.sqrt(2/self.cfg_fc[1]))

    def forward(self, input, batch_size):
        h1_vm = h1_vs = torch.zeros(batch_size, self.cfg_fc[0], dtype=dtype, device=device)
        h1_um = h1_us = h1_spike = torch.zeros(batch_size, self.cfg_fc[1], dtype=dtype, device=device)
        h1_sav = torch.ones(batch_size, self.cfg_fc[1], dtype=dtype, device=device)

        h2_vm = h2_vs = torch.zeros(batch_size, self.cfg_fc[1], dtype=dtype, device=device)
        h2_um = h2_us = h2_spike = h2_u = torch.zeros(batch_size, self.cfg_fc[2], dtype=dtype, device=device)
        h2_sav = torch.ones(batch_size, self.cfg_fc[2], dtype=dtype, device=device)

        # output
        out_t = self.num_steps * torch.ones(batch_size, self.cfg_fc[2], dtype=dtype, device=device)
        out_u = torch.zeros(batch_size, self.cfg_fc[2], dtype=dtype, device=device)
        sum_sp = torch.zeros(len(self.cfg_fc))

        # for backprop
        h1_v = torch.zeros(batch_size, self.cfg_fc[1], self.cfg_fc[0], dtype=dtype, device=device)
        h2_v = torch.zeros(batch_size, self.cfg_fc[2], self.cfg_fc[1], dtype=dtype, device=device)

        h1_dvdt = torch.zeros(batch_size, self.cfg_fc[1], self.cfg_fc[0], dtype=dtype, device=device)
        h2_dvdt = torch.zeros(batch_size, self.cfg_fc[2], self.cfg_fc[1], dtype=dtype, device=device)

        h1_dtdu = torch.zeros(batch_size, self.cfg_fc[1], dtype=dtype, device=device)
        h2_dtdu = torch.zeros(batch_size, self.cfg_fc[2], dtype=dtype, device=device)

        for step in range(self.num_steps):
            # MNIST input encoding : Poisson spike generation
            if self.task == 'mnist':
                in_spike = (input * self.frate > torch.rand(input.size(), device=device)).view(batch_size, -1).float()

            # N-MNIST input encoding
            elif self.task == 'nmnist':
                in_spike = input[:,:,:,:, step].view(batch_size, -1)

            # Calculation of first hidden layer
            h1_sav, h1_vm, h1_vs, h1_um, h1_us, h1_spike = noso(self.thresh,
                                                                self.tau_m,
                                                                self.tau_s,
                                                                self.fc1,
                                                                in_spike,
                                                                h1_sav,
                                                                h1_vm,
                                                                h1_vs,
                                                                h1_spike,
                                                                outneuron=False)
            # Calculation of output layer
            h2_sav, h2_vm, h2_vs, h2_um, h2_us, h2_u, h2_spike = noso(self.thresh,
                                                                      self.tau_m,
                                                                      self.tau_s,
                                                                      self.fc2,
                                                                      h1_spike,
                                                                      h2_sav,
                                                                      h2_vm,
                                                                      h2_vs,
                                                                      h2_spike,
                                                                      outneuron=True)

            # Recoding of output spike timings and output membrane potential
            out_t += dodt.apply(h2_spike, step, self.num_steps)
            out_u += h2_spike * h2_u

            sum_sp[0] += in_spike.sum().item()
            sum_sp[1] += h1_spike.sum().item()
            sum_sp[2] += h2_spike.sum().item()

            # for backprop
            h1_v += torch.unsqueeze((h1_vm - h1_vs), 1) * torch.unsqueeze(h1_spike, 2)
            h2_v += torch.unsqueeze((h2_vm - h2_vs), 1) * torch.unsqueeze(h2_spike, 2)

            h1_dvdt += torch.unsqueeze((h1_vm / self.tau_m - h1_vs / self.tau_s), 1) * torch.unsqueeze(h1_spike, 2)
            h2_dvdt += torch.unsqueeze((h2_vm / self.tau_m - h2_vs / self.tau_s), 1) * torch.unsqueeze(h2_spike, 2)

            h1_dtdu += dtdu_backward(h1_um, h1_us, h1_spike, self.thresh, self.tau_m, self.tau_s)
            h2_dtdu += dtdu_backward(h2_um, h2_us, h2_spike, self.thresh, self.tau_m, self.tau_s)

            if out_t.max() < self.num_steps:
                return out_t, out_u, sum_sp, [h1_v, h2_v], [h1_dvdt, h2_dvdt], [h1_dtdu, h2_dtdu]
        return out_t, out_u, sum_sp, [h1_v, h2_v], [h1_dvdt, h2_dvdt], [h1_dtdu, h2_dtdu]


from calendar import c
from re import S
import sys
import time

import smbus
import spidev
import RPi.GPIO as GPIO

import logging
from ctypes import *

logger = logging.getLogger()
# logger.setLevel(logging.INFO)   # Display all print information
logger.setLevel(logging.FATAL)   # If you don’t want to display too many prints, only print errors, please use this option
ph = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - [%(filename)s %(funcName)s]:%(lineno)d - %(levelname)s: %(message)s")
ph.setFormatter(formatter)
logger.addHandler(ph)

## I2C communication address when SDO is grounded
DFROBOT_BME280_I2C_ADDR_SDO_GND = 0x76
## I2C communication address when SDO is connected to power
DFROBOT_BME280_I2C_ADDR_SDO_VDD = 0x77
## BME280 chip version
BME280_REG_CHIP_ID_DEFAULT = 0x60

# BME280 register address
## 0x88-0xA1 is calibration data, calib00..calib25
BME280_CALIB_DATA_00_25 = 0x88
## The “CHIP_ID” register contains the chip identification code.
BME280_CHIP_ID = 0xD0
## Triggers a reset, all user configuration settings are overwritten with their default state.
BME280_CMD_RESET = 0xE0
## 0xE1-0xF0 is calibration data, calib26..calib41
BME280_CALIB_DATA_26_41 = 0xE1
## The “CTRL_HUM” register
BME280_CTRL_HUM = 0xF2
## The Sensor Status Flags are stored in the “STATUS” register.
BME280_STATUS = 0xF3
## The “CTRL_MEAS” register
BME280_CTRL_MEAS = 0xF4
## The “CONFIG” register
BME280_CONFIG = 0xF5
## The 24Bit pressure data is split and stored in three consecutive registers.
BME280_PRESS_DATA_MSB = 0xF7
## The 24Bit temperature data is split and stored in three consecutive registered.
BME280_TEMP_DATA_MSB = 0xFA
## The 16Bit temperature data is split and stored in two consecutive registered.
BME280_HUM_DATA_MSB = 0xFD

# Sensor configuration
## Sleep mode: It will be in sleep mode by default after power-on reset. In this mode, no measurement is performed and power consumption is minimal.
##             All registers are accessible for reading the chip ID and compensation coefficient.
SLEEP_MODE  = 0x00
## Forced mode: In this mode, the sensor will take a single measurement according to the selected measurement and filtering options. After the
##              measurement is completed, the sensor will return to sleep mode, and the measurement result can be obtained in the register.
FORCED_MODE = 0x01
## Normal mode: Continuously loop between the measurement period and the standby period. The output data rates are related to the ODR mode setting.
NORMAL_MODE = 0x03

## temperature oversampling settings
BME280_TEMP_OSR_SETTINGS = (0x00, 0x20, 0x40, 0x60, 0x80, 0xA0)
## pressure oversampling settings
BME280_PRESS_OSR_SETTINGS = (0x00, 0x04, 0x08, 0x0C, 0x10, 0x14)
## humidity oversampling settings
BME280_HUMI_OSR_SETTINGS = (0x00, 0x01, 0x02, 0x03, 0x04, 0x05)

## IIR filter settings
BME280_IIR_FILTER_SETTINGS = (0x00, 0x04, 0x08, 0x0C, 0x10)

# Controls inactive duration tstandby in normal mode.
## Controls inactive duration tstandby; ODR 2000Hz; Sampling period:0.5 ms
BME280_CONFIG_STANDBY_TIME_0P5  = 0x00
## Sampling period:62.5 ms
BME280_CONFIG_STANDBY_TIME_62P5 = 0x20
## Sampling period:125 ms
BME280_CONFIG_STANDBY_TIME_125  = 0x40
## Sampling period:250 ms
BME280_CONFIG_STANDBY_TIME_250  = 0x60
## Sampling period:500 ms
BME280_CONFIG_STANDBY_TIME_500  = 0x80
## Sampling period:1000 ms
BME280_CONFIG_STANDBY_TIME_1000 = 0xA0
## Sampling period:10 ms
BME280_CONFIG_STANDBY_TIME_10   = 0xC0
## Sampling period:20 ms
BME280_CONFIG_STANDBY_TIME_20   = 0xE0

## Triggers a reset, all user configuration settings are overwritten with their default state.
BME280_CMD_RESET_VALUE = 0xB6

## Standard sea level pressure, unit: pa
STANDARD_SEA_LEVEL_PRESSURE_PA = 101325.00

class DFRobot_BME280(object):
    '''!
      @brief define DFRobot_BME280 base class
      @details for driving the pressure sensor
    '''

    def __init__(self):
        '''!
          @brief Module init
        '''
        # Sea level pressure in Pa.
        self.sea_level_pressure = STANDARD_SEA_LEVEL_PRESSURE_PA
        self._t_fine = 0

    def begin(self):
        '''!
          @brief Initialize sensor
          @return  return initialization status
          @retval True indicate initialization succeed
          @retval False indicate initialization failed
        '''
        ret = False
        chip_id = self._read_reg(BME280_CHIP_ID, 1)
        logger.info(chip_id[0])
        if chip_id[0] == BME280_REG_CHIP_ID_DEFAULT:
            self.reset()
            time.sleep(0.3)
            self._get_coefficients()
            self.set_config_filter(BME280_IIR_FILTER_SETTINGS[0])
            self.set_config_T_standby(BME280_CONFIG_STANDBY_TIME_125)
            self.set_ctrl_meas_sampling_temp(BME280_TEMP_OSR_SETTINGS[3])
            self.set_ctrl_meas_sampling_press(BME280_PRESS_OSR_SETTINGS[3])
            self.set_ctrl_sampling_humi(BME280_HUMI_OSR_SETTINGS[3])
            self.set_ctrl_meas_mode(NORMAL_MODE)
            time.sleep(2)   # warm-up
            ret = True
        return ret

    @property
    def get_temperature(self):
        '''!
          @brief Get pressure measurement value from register, working range (-40 ~ +85 °C)
          @return Return temperature measurements, unit: °C
        '''
        data = self._read_reg(BME280_TEMP_DATA_MSB, 3)
        raw = data[0] << 12 | data[1] << 4 | (data[2] & 0x0F)

        # datasheet, Trimming Coefficient listing in register map with size and sign attributes
        t1, t2, t3, p1, p2, p3, p4, p5, p6, p7, p8, p9, h1, h2, h3, h4, h5, h6 = self._data_calib

        v1 = ((((raw >> 3) - (t1 << 1))) * t2) >> 11
        v2 = (((((raw >> 4) - t1) * ((raw >> 4) - t1)) >> 12) * t3) >> 14
        self._t_fine = v1 + v2
        rslt = (self._t_fine * 5 + 128) >> 8
        return (float(rslt) / 100)   # round((rslt / 100), 2)

    @property
    def get_pressure(self):
        '''!
          @brief Get pressure measurement value from register, working range (300 ~ 1100 hPa)
          @return Return pressure measurements, unit: Pa
          @attention If the reference value is provided before, the absolute value of the current
          @n         position pressure is calculated according to the calibrated sea level atmospheric pressure
        '''
        data = self._read_reg(BME280_PRESS_DATA_MSB, 3)
        raw = data[0] << 12 | data[1] << 4 | (data[2] & 0x0F)

        # datasheet, Trimming Coefficient listing in register map with size and sign attributes
        t1, t2, t3, p1, p2, p3, p4, p5, p6, p7, p8, p9, h1, h2, h3, h4, h5, h6 = self._data_calib

        self.get_temperature   # update _t_fine

        v1 = self._t_fine - 128000
        v2 = v1 * v1 * p6
        v2 = v2 + ((v1 * p5) << 17)
        v2 = v2 + (p4 << 35)
        v1 = ((v1 * v1 * p3) >> 8) + ((v1 * p2) << 12)
        v1 = (((1 << 47) + v1)) * p1 >> 33
        if(v1 == 0):
          return 0
        rslt = 1048576 - raw
        rslt = (((rslt << 31) - v2) * 3125) / v1
        v1 = (p9 * (int(rslt) >> 13) * (int(rslt) >> 13)) >> 25
        v2 = (p8 * int(rslt)) >> 19
        rslt = ((int(rslt) + v1 + v2) >> 8) + (p7 << 4)
        return (float(rslt) / 256)

    @property
    def get_humidity(self):
        '''!
          @brief Get humidity measurement value from register, working range (0 ~ 100 %RH)
          @return Return humidity measurements, unit: %RH
        '''
        data = self._read_reg(BME280_HUM_DATA_MSB, 2)
        raw = data[0] << 8 | data[1]

        # datasheet, Trimming Coefficient listing in register map with size and sign attributes
        t1, t2, t3, p1, p2, p3, p4, p5, p6, p7, p8, p9, h1, h2, h3, h4, h5, h6 = self._data_calib

        self.get_temperature   # update _t_fine

        v1 = self._t_fine - 76800
        v1 = (((((raw <<14) - (h4 << 20) - (h5 * v1)) + 16384) >> 15) * (((((((v1 * h6) >> 10) *
             (((v1 * h3) >> 11) + 32768)) >> 10) + 2097152) * h2 + 8192) >> 14))
        v1 = (v1 - (((((v1 >> 15) * (v1 >> 15)) >> 7) * h1) >> 4))
        if v1 < 0:
            v1 = 0
        elif v1 > 419430400:
            v1 = 419430400
        return (v1 >> 12) / 1024.0

    @property
    def get_altitude(self):
        '''!
          @brief Calculate the altitude based on the atmospheric pressure measured by the sensor
          @return Return altitude, unit: m
          @attention If the reference value is provided before, the absolute value of the current
          @n         position pressure is calculated according to the calibrated sea level atmospheric pressure
        '''
        # see https://www.weather.gov/media/epz/wxcalc/pressureAltitude.pdf
        return 44307.7 * (1 - (self.get_pressure / self.sea_level_pressure) ** 0.190284)

    @property
    def get_data_ready_status(self):
        '''!
          @brief get data ready status
          @return True is data ready
        '''
        temp = self._read_reg(BME280_STATUS, 1)[0]
        if temp & 0b00001000:   # measuring[3]
            return False
        else:
            return True

    def reset(self):
        '''!
          @brief Reset and restart the sensor, restoring the sensor configuration to the default configuration
        '''
        self._write_reg(BME280_CMD_RESET, BME280_CMD_RESET_VALUE)
        time.sleep(0.1)

    def calibrated_absolute_difference(self, altitude):
        '''!
          @brief Take the given current location altitude as the reference value
          @n     to eliminate the absolute difference for subsequent pressure and altitude data
          @param altitude Altitude in current position
          @return Pass the benchmark value successfully will return ture, if failed it will return false
        '''
        # The altitude in meters based on the currently set sea level pressure.
        ret = False
        if STANDARD_SEA_LEVEL_PRESSURE_PA == self.sea_level_pressure:
            self.sea_level_pressure = (self.get_pressure / pow(1.0 - (altitude / 44307.7), 5.255302))
            ret = True
        return ret

    def set_ctrl_meas_mode(self, mode):
        '''!
          @brief Configure measurement mode and power mode
          @param mode The measurement mode and power mode that need to be set:
          @n  SLEEP_MODE(Sleep mode): It will be in sleep mode by default after power-on reset. In this mode,no
          @n                          measurement is performed and power consumption is minimal. All registers
          @n                          are accessible for reading the chip ID and compensation coefficient.
          @n  FORCED_MODE(Forced mode): In this mode, the sensor will take a single measurement according to the selected
          @n                            measurement and filtering options. After the measurement is completed, the sensor
          @n                            will return to sleep mode, and the measurement result can be obtained in the register.
          @n  NORMAL_MODE(Normal mode): Continuously loop between the measurement period and the standby period.
          @n                            The output data rates are related to the ODR mode setting.
        '''
        mask = 0b00000011   # mode[1:0]
        self._write_reg_bits(BME280_CTRL_MEAS, mask, mode)

    def set_ctrl_meas_sampling_temp(self, osrs_t):
        '''!
          @brief Configure the oversampling when measuring temperature (OSR:over-sampling register)
          @details When the IIR filter is enabled, the temperature resolution is 20 bit.
          @n       When the IIR filter is disabled, the temperature resolution is 16 + (osrs_t – 1) bit,
          @n       e.g. 18 bit when osrs_t is set to ‘3’.
          @param - osrs_t 6 temp oversampling mode:
          @n         BME280_TEMP_OSR_SETTINGS[0], temperature sampling×0, Skipped (output set to 0x80000)
          @n         BME280_TEMP_OSR_SETTINGS[1], temperature sampling×2, 16 bit
          @n         BME280_TEMP_OSR_SETTINGS[2], temperature sampling×4, 17 bit
          @n         BME280_TEMP_OSR_SETTINGS[3], temperature sampling×8, 18 bit
          @n         BME280_TEMP_OSR_SETTINGS[4], temperature sampling×16, 19 bit
          @n         BME280_TEMP_OSR_SETTINGS[5], temperature sampling×32, 20 bit
        '''
        mask = 0b11100000   # osrs_t[7:5]
        self._write_reg_bits(BME280_CTRL_MEAS, mask, osrs_t)

    def set_ctrl_meas_sampling_press(self, osrs_p):
        '''!
          @brief Configure the oversampling when measuring press (OSR:over-sampling register)
          @details When the IIR filter is enabled, the pressure resolution is 20 bit.
          @n       When the IIR filter is disabled, the pressure resolution is 16 + (osrs_p – 1) bit,
          @n       e.g. 18 bit when osrs_p is set to ‘3’.
          @param - osrs_t 6 temp oversampling mode:
          @n         BME280_PRESS_OSR_SETTINGS[0], pressure sampling×0, Skipped (output set to 0x80000)
          @n         BME280_PRESS_OSR_SETTINGS[1], pressure sampling×2, 16 bit
          @n         BME280_PRESS_OSR_SETTINGS[2], pressure sampling×4, 17 bit
          @n         BME280_PRESS_OSR_SETTINGS[3], pressure sampling×8, 18 bit
          @n         BME280_PRESS_OSR_SETTINGS[4], pressure sampling×16, 19 bit
          @n         BME280_PRESS_OSR_SETTINGS[5], pressure sampling×32, 20 bit
        '''
        mask = 0b00011100   # osrs_t[4:2]
        self._write_reg_bits(BME280_CTRL_MEAS, mask, osrs_p)

    def set_ctrl_sampling_humi(self, osrs_h):
        '''!
          @brief Configure the oversampling when measuring humidity (OSR:over-sampling register)
          @details For the humidity measurement, oversampling is possible to reduce the noise.
          @n       The resolution of the humidity measurement is fixed at 16 bit ADC output.
          @param - osrs_t 6 temp oversampling mode:
          @n         BME280_HUMI_OSR_SETTINGS[0], humidity sampling×0, Skipped (output set to 0x80000)
          @n         BME280_HUMI_OSR_SETTINGS[1], humidity sampling×2, 16 bit
          @n         BME280_HUMI_OSR_SETTINGS[2], humidity sampling×4, 17 bit
          @n         BME280_HUMI_OSR_SETTINGS[3], humidity sampling×8, 18 bit
          @n         BME280_HUMI_OSR_SETTINGS[4], humidity sampling×16, 19 bit
          @n         BME280_HUMI_OSR_SETTINGS[5], humidity sampling×32, 20 bit
        '''
        mask = 0b00000111   # osrs_t[2:0]
        self._write_reg_bits(BME280_CTRL_HUM, mask, osrs_h)

    def set_config_filter(self, iir_config_coef):
        '''!
          @brief IIR filter coefficient setting(IIR filtering)
          @param - iir_config_coef Set IIR filter coefficient, configurable mode:
          @n         BME280_IIR_FILTER_SETTINGS[0], filter off
          @n         BME280_IIR_FILTER_SETTINGS[1], filter coefficient 2
          @n         BME280_IIR_FILTER_SETTINGS[2], filter coefficient 4
          @n         BME280_IIR_FILTER_SETTINGS[3], filter coefficient 8
          @n         BME280_IIR_FILTER_SETTINGS[4], filter coefficient 16
        '''
        mask = 0b00011100   # osrs_t[4:2]
        self._write_reg_bits(BME280_CONFIG, mask, iir_config_coef)

    def set_config_T_standby(self, odr_set):
        '''!
          @brief Set output data rate in subdivision/sub-sampling mode (ODR:output data rates)
          @param odr_set The output data rate needs to be set, configurable mode:
          @n BME280_CONFIG_STANDBY_TIME_0P5, BME280_CONFIG_STANDBY_TIME_62P5, BME280_CONFIG_STANDBY_TIME_125,
          @n BME280_CONFIG_STANDBY_TIME_250, BME280_CONFIG_STANDBY_TIME_500, BME280_CONFIG_STANDBY_TIME_1000,
          @n BME280_CONFIG_STANDBY_TIME_10, BME280_CONFIG_STANDBY_TIME_20
          @return  return configuration results
          @retval True indicate configuration succeed
          @retval False indicate configuration failed and remains its original state
        '''
        # The IIR filter coefficient.
        ret = True
        mask = 0b11100000   # osrs_t[7:5]
        self._write_reg_bits(BME280_CONFIG, mask, odr_set)
        if (self._read_reg(BME280_CONFIG, 1)[0] & 0xE0):
            logger.warning("Sensor configuration error detected!")
            ret = False
        return ret

    def _uint8_to_int(self,num):
        '''!
          @brief Convert the incoming uint8 type data to int type
          @param num Incoming uint8 type data
          @return data converted to int type
        '''
        if(num>127):
            num = num - 256
        return num

    def _uint16_to_int(self,num):
        '''!
          @brief Convert the incoming uint16 type data to int type
          @param num Incoming uint16 type data
          @return data converted to int type
        '''
        if(num>32767):
            num = num - 65536
        return num

    def _get_coefficients(self):
        '''!
          @brief Get the calibration data in the NVM register of the sensor
        '''
        calib = self._read_reg(BME280_CALIB_DATA_00_25, 26)
        calib1 = self._read_reg(BME280_CALIB_DATA_26_41, 7)
        self._data_calib = (
            (calib[1] << 8) | calib[0],  # T1
            self._uint16_to_int((calib[3] << 8) | calib[2]),  # T2
            self._uint16_to_int((calib[5] << 8) | (calib[4])),  # T3
            (calib[7] << 8) | calib[6],  # P1
            self._uint16_to_int((calib[9] << 8) | calib[8]),  # P2
            self._uint16_to_int((calib[11] << 8) | calib[10]),  # P3
            self._uint16_to_int((calib[13] << 8) | calib[12]),  # P4
            self._uint16_to_int((calib[15] << 8) | calib[14]),  # P5
            self._uint16_to_int((calib[17] << 8) | calib[16]),  # P6
            self._uint16_to_int((calib[19] << 8) | calib[18]),  # P7
            self._uint16_to_int((calib[21] << 8) | calib[20]),  # P8
            self._uint16_to_int((calib[23] << 8) | calib[22]),  # P9
            calib[25],  # H1
            self._uint16_to_int((calib1[1] << 8) | calib1[0]),  # H2
            calib1[2],  # H3
            self._uint16_to_int((calib1[3] << 4) | (calib1[4] & 0x0F)),  # H4
            self._uint16_to_int((calib1[5] << 4) | ((calib1[4] >> 4) & 0x0F)),  # H5
            self._uint8_to_int(calib1[6]),  # H6
        )

    def _write_reg_bits(self, reg, field, val):
        '''!
          @brief writes data to a register
          @param reg register address
          @param data written data
        '''
        temp = self._read_reg(reg, 1)[0]
        temp &= ~field
        temp |= val
        self._write_reg(reg, temp)

    def _write_reg(self, reg, data):
        '''!
          @brief writes data to a register
          @param reg register address
          @param data written data
        '''
        # Low level register writing, not implemented in base class
        raise NotImplementedError()

    def _read_reg(self, reg, length):
        '''!
          @brief read the data from the register
          @param reg register address
          @param length read data length
          @return read data list
        '''
        # Low level register writing, not implemented in base class
        raise NotImplementedError()

class DFRobot_BME280_I2C(DFRobot_BME280):
    '''!
      @brief define DFRobot_BME280_I2C base class
      @details for using I2C protocol to drive the pressure sensor
    '''

    def __init__(self, i2c_addr=0x77, bus=1):
        '''!
          @brief Module I2C communication init
          @param i2c_addr I2C communication address
          @param bus I2C bus
        '''
        self._addr = i2c_addr
        self._i2c = smbus.SMBus(bus)
        super(DFRobot_BME280_I2C, self).__init__()

    def _write_reg(self, reg, data):
        '''!
          @brief writes data to a register
          @param reg register address
          @param data written data
        '''
        if isinstance(data, int):
            data = [data]
            #logger.info(data)
        self._i2c.write_i2c_block_data(self._addr, reg, data)

    def _read_reg(self, reg, length):
        '''!
          @brief read the data from the register
          @param reg register address
          @param length read data length
          @return read data list
        '''
        return self._i2c.read_i2c_block_data(self._addr, reg, length)

class DFRobot_BME280_SPI(DFRobot_BME280):
    '''!
      @brief define DFRobot_BME280_SPI base class
      @details for using SPI protocol to drive the pressure sensor
    '''

    def __init__(self, cs=8, bus=0, dev=0, speed=500000):
        '''!
          @brief Module SPI communication init
          @param cs cs chip select pin
          @param bus SPI bus
          @param dev SPI device number
          @param speed SPI communication frequency
        '''
        self._cs = cs
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        GPIO.setup(self._cs, GPIO.OUT, initial=1)
        GPIO.output(self._cs, GPIO.LOW)
        self._spi = spidev.SpiDev()
        self._spi.open(bus, dev)
        self._spi.no_cs = True
        self._spi.max_speed_hz = speed
        super(DFRobot_BME280_SPI, self).__init__()

    def _write_reg(self, reg, data):
        '''!
          @brief writes data to a register
          @param reg register address
          @param data written data
        '''
        if isinstance(data, int):
            data = [data]
            #logger.info(data)
        reg_addr = [reg & 0x7f]
        GPIO.output(self._cs, GPIO.LOW)
        self._spi.xfer(reg_addr)
        self._spi.xfer(data)
        GPIO.output(self._cs, GPIO.HIGH)

    def _read_reg(self, reg, length):
        '''!
          @brief read the data from the register
          @param reg register address
          @param length read data length
          @return read data list
        '''
        reg_addr = [reg | 0x80]
        GPIO.output(self._cs, GPIO.LOW)
        #logger.info(reg_addr)
        self._spi.xfer(reg_addr)
        time.sleep(0.01)
        # self._spi.readbytes(1)
        rslt = self._spi.readbytes(length)
        GPIO.output(self._cs, GPIO.HIGH)
        return rslt


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import os
import h5py
import random
import numpy as np
from PIL import Image

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import Dataset
from torchvision import models, transforms

from superpixel.slic import SLIC
from lib.make_index import make_data_index, default_loader
from lib.image_process import RandomCropPatches, NonOverlappingCropPatches
from lib.utils import mos_rescale

class IQADataset(Dataset):
    """
    IQA Dataset
    """
    def __init__(self, args, status='train', loader=default_loader):
        """
        :param args: arguments of the model
        :param status: train/val/test
        :param loader: image loader
        """
        self.args = args
        self.status = status
        self.loader = loader

        self.train_database = args.train_database
        self.test_database = args.test_database

        self.image_n_nodes = args.image_n_nodes
        self.patch_n_nodes = args.patch_n_nodes
        self.region_size = args.region_size
        self.ruler = args.ruler
        self.iterate = args.iterate

        self.patch_size = args.patch_size
        self.n_patches_train = args.n_patches_train

        # Train
        train_Info = h5py.File(args.train_info, 'r')
        train_index = train_Info['index']
        train_index = train_index[:, 0 % train_index.shape[1]]
        train_ref_ids = train_Info['ref_ids'][0, :]

        # Test
        test_Info = h5py.File(args.test_info, 'r')
        test_index = test_Info['index']
        test_index = test_index[:, 0 % test_index.shape[1]]
        test_ref_ids = test_Info['ref_ids'][0, :]

        # Get dataset index
        train_index_, test_index_ = [], []
        if 'train' in status:
            print('The Training Set Index is ', train_index, ' and num of Training index is ', len(train_index))
            for i in range(len(train_ref_ids)):
                train_index_.append(i)

            self.index = train_index_
            print("Number of Training Images: {}\n".format(len(self.index)))
            self.mos = train_Info['subjective_scores'][0, self.index]
            # self.mos_std = train_Info['subjective_scoresSTD'][0, self.index]
            im_names = [train_Info[train_Info['im_names'][0, :][i]][()].tobytes()[::2].decode() for i in self.index]

            self.label = []
            self.im_names = []
            self.dis_type = []

            for idx in range(len(self.index)):
                self.im_names.append(os.path.join(args.train_im_dir, im_names[idx]))
                self.label.append(self.mos[idx])

                if self.train_database == 'TID2008' or self.train_database == 'TID2013':
                    self.dis_type.append(int(im_names[idx][4:6]) - 1)

                elif self.train_database == 'KADID':
                    self.dis_type.append(int(im_names[idx][4:6]) - 1)

                elif self.train_database == 'CSIQ':
                    # Distortion Type
                    if 'AWGN' in im_names[idx]:
                        self.dis_type.append(0)
                    elif 'BLUR' in im_names[idx]:
                        self.dis_type.append(1)
                    elif 'contrast' in im_names[idx]:
                        self.dis_type.append(2)
                    elif 'fnoise' in im_names[idx]:
                        self.dis_type.append(3)
                    elif 'JPEG' in im_names[idx]:
                        self.dis_type.append(4)
                    elif 'jpeg2000' in im_names[idx]:
                        self.dis_type.append(5)

                elif self.train_database == 'LIVE':
                    # Distortion Type
                    if 'jp2k' in im_names[idx]:
                        self.dis_type.append(0)
                    elif 'jpeg' in im_names[idx]:
                        self.dis_type.append(1)
                    elif 'wn' in im_names[idx]:
                        self.dis_type.append(2)
                    elif 'gblur' in im_names[idx]:
                        self.dis_type.append(3)
                    elif 'fastfading' in im_names[idx]:
                        self.dis_type.append(4)

                elif self.train_database == 'SIQAD':
                    loc = im_names[idx].find('_')
                    self.dis_type.append(int(im_names[idx][loc + 1]) - 1)

                elif self.train_database == 'SCID':
                    self.dis_type.append(int(im_names[idx][6]) - 1)

        else:
            print('The Testing Set Index is ', test_index, ' and num of test index is ', len(test_index))
            for i in range(len(test_ref_ids)):
                test_index_.append(i)

            self.index = test_index_
            print("Number of Testing Images: {}".format(len(self.index)), '\n')
            self.mos = test_Info['subjective_scores'][0, self.index]
            im_names = [test_Info[test_Info['im_names'][0, :][i]][()].tobytes()[::2].decode() for i in self.index]

            self.label = []
            self.im_names = []
            self.dis_type = []

            for idx in range(len(self.index)):
                self.im_names.append(os.path.join(args.test_im_dir, im_names[idx]))
                self.label.append(self.mos[idx])
                self.dis_type.append(0)

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

    def __getitem__(self, idx):
        im = self.loader(self.im_names[idx])

        # Get CNN input
        if self.status == 'train':
            cnn_input, patch, patch_graph = RandomCropPatches(im, args=self.args, transforms=True)
        else:
            cnn_input, patch, patch_graph = NonOverlappingCropPatches(im, args=self.args, transforms=True)

        # Get labels
        label = torch.as_tensor([self.label[idx], ])

        # Choose whether to use distortion type or distortion level
        dis_type = torch.as_tensor([self.dis_type[idx], ])

        return patch, patch_graph, cnn_input, label, dis_type


from selenium import webdriver
import math
import time
import os
import eel

eel.init('web')

def getUrl(url, volume, chapter):
    if url[-1] != '/':
        url += '/'
    return str(url) + 'v' + str(volume) + '/c' + str(chapter)

def startDriver(url, chapterNumbers, outputFolder='', outputName='output', firstChapter=1, volumeNumber=1):
    options = webdriver.FirefoxOptions()
    options.add_argument('--disable-blink-features=AutomationControlled')
    options.add_argument('--headless')
    chapter = firstChapter
    url = getUrl(url, volumeNumber, chapter)
    print('Запуск парсинга...')
    eel.consoleArea('Запуск парсинга...')
    for i in range(firstChapter, chapterNumbers + 1):
        try:
            print(i)
            eel.consoleArea(i)
            driver = webdriver.Firefox(
                executable_path='geckodriver.exe',
                options=options
            )
            driver.get(url=url)
            outputSource = 'output/' + outputFolder + '/' + outputName + '_c' + str(chapter) + '.txt'
            title = 'Том '+str(volumeNumber)+' глава '+str(chapter)+'\n'
            time.sleep(5)
            print('Запись файла...')
            eel.consoleArea('Запись файла...')
            p = driver.find_element_by_xpath("//*[@class='reader-container container container_center']")
            t = title + p.text
            with open(outputSource, 'w', encoding='utf-8') as file:
                file.write(t)
            print('[' + str(chapter) + '] глава готова')
            eel.consoleArea('[' + str(chapter) + '] глава готова')
            url = driver.find_element_by_xpath(
                "//*[@class='reader-next__btn button text-truncate button_label button_label_right']").get_attribute(
                "href")
            chapter += 1
        except Exception as ex:
            print(ex)
        finally:
            driver.close()
            driver.quit()

# url = 'https://ranobelib.me/sss-class-suicide-hunter'
# chapterNumbers = 1
# outputFolder = 'F:/Project/Python/RanobeLib downloader/output/SSS-Class Suicide Hunter'
# outputName = 'SSS-Class Suicide Hunter'
# firstChapter = 1
# volumeNumber = 1

@eel.expose
def start(url, chapterNumbers, outputFolder, outputName, firstChapter, volumeNumber):

    url = str(url)
    chapterNumbers = int(chapterNumbers)
    outputFolder = str(outputFolder)
    outputName = str(outputName)
    firstChapter = int(firstChapter)
    volumeNumber = int(volumeNumber)

    t0 = time.time()

    if not os.path.exists('output/' + outputFolder):
        os.mkdir('output/' + outputFolder)
    outFile = open('output/' + outputFolder + '/outFile.txt', 'w', encoding='utf-8')
    startDriver(url, chapterNumbers, outputFolder, outputName, firstChapter, volumeNumber)

    t1 = time.time() - t0
    print("Time elapsed: ", math.ceil(t1), "second")
    eel.consoleArea("Прошло: " + str(math.ceil(t1)) + " секунд" + '\n' + "Глав сохранено: " + str(chapterNumbers))
    outFile.write(
        "Прошло: " + str(math.ceil(t1)) + " секунд" + '\n' + "Глав сохранено: " + str(chapterNumbers)
    )

eel.start('index.html', size=(700, 700))


import ply.lex as lex

# List of token names.   This is always required
tokens = (
   'PROP',
   'TRUE',
   'FALSE',
   'NOT',
   'AND',
   'OR',
   'IMPLY',
   'X',
   'U',
   'F',
   'G',
   'R',
   'LPAREN',
   'RPAREN',
)

# Regular expression rules for simple tokens
t_PROP    = r'[a-zA-Z_][a-zA-Z0-9_]*'
t_TRUE    = r'True'
t_FALSE   = r'False'
t_NOT     = r'Not'
t_AND     = r'And'
t_OR      = r'Or'
t_IMPLY   = r'Imply'
t_X       = r'X'
t_U       = r'U'
t_F       = r'F'
t_G       = r'G'
t_R       = r'R'
t_LPAREN  = r'\('
t_RPAREN  = r'\)'

# A regular expression rule with some action code
def t_NUMBER(t):
    r'\d+'
    t.value = int(t.value)
    return t

# Define a rule so we can track line numbers
def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

# A string containing ignored characters (spaces and tabs)
t_ignore  = ' \t'

# Error handling rule
def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

# Build the lexer
lexer = lex.lex()


from django.contrib import admin
from django.urls import path
from final import views

urlpatterns = [
    path("", views.index, name="root"),
    path("about/", views.about, name="about"),
    path("signup/", views.signup, name="signup"),
    path("login/", views.loginUser, name="login"),
    path("contact/", views.contact, name="contact"),
    path("logout/", views.logoutUser, name="logout"),
    path("services/", views.services, name="services")
]


import os
from setuptools import setup, find_packages
from nats import __version__

this_dir = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(this_dir, 'requirements.txt')) as f:
    requirements = f.read().splitlines()

setup(
    name='nats-client',
    version=__version__,
    description='NATS client for Python 2',
    long_description=
    'Tornado based Python client for NATS, a lightweight, high-performance cloud native messaging system',
    url='https://github.com/nats-io/nats.py2',
    author='Waldemar Quevedo',
    author_email='wally@synadia.com',
    license='Apache 2.0 License',
    packages=['nats', 'nats.io', 'nats.protocol'],
    install_requires=requirements,
    zip_safe=True,
    classifiers=[
        'Intended Audience :: Developers',
        'Programming Language :: Python',
    ])


from flask import Flask,request,jsonify
import numpy as np
from scipy.signal import find_peaks
import pandas as pd

app = Flask(__name__)

@app.route('/data_process',methods=['GET'])
def data_process():
    dict1={}
    if '[' and ']' and "," in request.args['C1 raw']:
        input_control=request.args['C1 raw'].strip('[').strip(']').split(',')
        #print(input_control)
        input_test=request.args['T1 raw'].strip('[').strip(']').split(',')
    elif ',' in request.args['C1 raw']:
        input_control=request.args['C1 raw'].split(',')
        print(input_control)
        input_test=request.args['T1 raw'].split(',')

    elif '\n' in  request.args['C1 raw']:
        input_control=request.args['C1 raw'].split('\n')
        input_control=input_control[0:-2]
        #print(input_control)
        input_test=request.args['T1 raw'].split('\n')
        input_test = input_test[0:-2]

    else:
        input_control=request.args['C1 raw'].split(' ')
        #print(input_control)
        input_test=request.args['T1 raw'].split(' ')

    peaks1, _ = find_peaks(input_control, prominence=1,width=15)
    peaks2, _ = find_peaks(input_test, prominence=1,width=15)
    if len(peaks1)!=0 or len(peaks2)!=0:
        print('Peak1: {} Peak2: {}'.format(peaks1, peaks2))
        peak_diff = float(input_control[peaks1[0]]) - float(input_test[peaks2[0]])
        percentage_change = (peak_diff) / float(input_control[peaks1[0]]) * 100
        if percentage_change < 19:
            result = 'Negative'
        elif percentage_change >= 19:
            result = 'Positive'

        dict1['Result']=result
        dict1['Peak C1 raw index']=str(peaks1[0])
        dict1['Peak T1 raw index']=str(peaks2[0])
        dict1['Peak C1 raw']=str(input_control[peaks1[0]])
        dict1['Peak T1 raw']=str(input_test[peaks2[0]])
        dict1['Peak Difference']=str(peak_diff)
        dict1['Percentage Change']=str(percentage_change)
        return jsonify(dict1)

    else:

        dict1['Result']='Inconclusive'
        dict1['Peak C1 raw index']='0'
        dict1['Peak T1 raw index']='0'
        dict1['Peak C1 raw']='0'
        dict1['Peak T1 raw']='0'
        dict1['Peak Difference']='0'
        dict1['Percentage Change']='0'
        return jsonify(dict1)

if __name__ == '__main__':
    app.run(debug=True)
#http://127.0.0.1:5000/data_process?control=[123456]&test=[546789]


#SIEMPRE SIEMPRE SIEMPRE que abrimos un fichero lo tenemos que CERRAR después
#Si abrimos un fichero con with, python hace el close() por nosotros :))

fichero = 'nombres2.txt' #qué tengo que poner como fichero?
            #qué pasa si no está en la misma carpeta?

import pickle
import csv

with open(fichero) as f:
    print(f) #qué imprime?

with open(fichero) as f: #qué ha pasado?
    print(f.read())

with open(fichero,encoding='utf8') as f: #qué ha pasado?
    print(f.read())

with open(fichero,encoding='utf8') as f: #por qué sale así? cómo podemos solucionarlo?
    for line in f:
        print(line.strip())

with open(fichero,encoding='utf8') as f:
    lines=f.readlines() #lines=[Rocío,Ana...]
    for l in lines:
        print(l)

with open(fichero,mode='a',encoding='utf8') as f:
    f.write('\nIrene') #probar primero sin \n

lista=[1,2,3,4]
with open('lista.pickle',mode='wb') as f:
    pickle.dump(lista, f)

with open('lista.pickle',mode='rb') as f:
    print(pickle.load(f))

with open('lista.pickle',mode='rb') as f:
    x = pickle.load(f)
    x[0]=9
with open('lista.pickle',mode='wb') as f:
    pickle.dump(x,f)
with open('lista.pickle',mode='rb') as f:
    print(pickle.load(f))

import csv

with open('personas.csv', mode='r') as fichero:
    csv_reader = csv.reader(fichero, delimiter=',')#guardamos las líneas del fichero en csv_reader
    contador = 0
    for linea in csv_reader:#¿qué es una línea en un csv?

        if contador == 0:
            cabeceras = linea
            contador += 1

        else:
            print('Línea ' + str(contador) + ':')

        for i in range(len(cabeceras)):
            print(cabeceras[i], '->', linea[i])
            contador += 1

with open('personas.csv', mode='a', encoding='utf8', newline='') as fichero:
    csv_writer = csv.writer(fichero, delimiter=',')
    linea = ['Pablo','Buendía','24']
    csv_writer.writerow(linea)
    linea = ['Enrique', None,'15']
    csv_writer.writerow(linea)

import json
diccionario = {
    'nombre':'Marta',
    'edad':25
}

with open('diccionario.json',mode='w',encoding='utf8') as f:
    json.dump(diccionario,f)

with open('diccionario.json',mode='w',encoding='utf8') as f:
    json.dump(diccionario,f)


""" Loading logic """
import sqlite3
import sys
from decimal import Decimal
from datetime import datetime

def load_data(database_uri: str, data: list) -> bool:
    """
    Loads Bitcoin rate data into an SQLite database.

    Args:
        database_uri (str): The URI of the SQLite database.
        data (list): The list containing the data to load.

    Returns:
        bool: True if the data was successfully loaded, False otherwise.
    """
    schema = {
        "database_name": "bitcoin_rate_tracker",
        "schema_name": "dbo",
        "table": "bitcoin_rates",
        "fields": {
            "unique_number": "INTEGER PRIMARY KEY AUTOINCREMENT",
            "timestamp": "DATETIME2 NOT NULL",
            "chart_name": "VARCHAR(10) NOT NULL",
            "usd_rate": "DECIMAL(18, 4) NOT NULL",
            "gbp_rate": "DECIMAL(18, 4) NOT NULL",
            "eur_rate": "DECIMAL(18, 4) NOT NULL",
        },
    }

    try:
        # Prepare the data for insertion
        formatted_data = [
            str(item)
            if isinstance(item, Decimal)
            else item.isoformat()
            if isinstance(item, datetime)
            else str(item)
            for item in data
        ]

        # Connect to SQLite database
        connection = sqlite3.connect(database_uri)
        with connection:
            cursor = connection.cursor()

            # Create table schema
            create_table_query = f"""
            CREATE TABLE IF NOT EXISTS {schema['table']} (
                {', '.join(f'{column} {specification}' for column, specification in schema['fields'].items())},
                UNIQUE (timestamp)
            );
            """
            cursor.execute(create_table_query)

            # Insert data into SQLite table
            insert_query = f"""
            INSERT INTO {schema['table']} ({', '.join(field for field in schema['fields'] if field != 'unique_number')})
            VALUES ({', '.join(['?'] * (len(schema['fields']) - 1))})
            ON CONFLICT (timestamp) DO UPDATE SET
                {', '.join(f"{field} = excluded.{field}" for field in schema['fields'] if field not in ('unique_number', 'timestamp'))}
            """
            cursor.execute(insert_query, formatted_data)
            connection.commit()

            # The maximum timestamp is the timestamp of the last inserted record
            max_timestamp = formatted_data[0]

            # Delete records older than 48 hours from the maximum timestamp in the SQLite table
            delete_query = f"""
                DELETE FROM {schema['table']}
                WHERE datetime(timestamp) < datetime('{max_timestamp}', '-48 hours')
            """
            cursor.execute(delete_query)
            connection.commit()

            return cursor.lastrowid > 0

    except sqlite3.Error as error_msg:
        print("Error: " + str(error_msg))
        sys.exit()

    finally:
        connection.close()


"""
EECS 445 - Winter 2017 - Project 2
FER2013 - Skeleton
This file reads the dataset and provides a function `preprocessed_data`
that returns preprocessed images, labels
Usage: python -m data_scripts.fer2013
"""

import numpy as np
from scipy.misc import imresize
from sklearn.utils import resample
import pandas

from utils.config import get, print_if_verbose

class FER2013:
    filename = ''
    data_stored = False
    train_images = np.zeros(0)
    train_labels = np.zeros(0)
    val_images = np.zeros(0)
    val_labels = np.zeros(0)
    test_images = np.zeros(0)
    test_labels = np.zeros(0)

    def __init__(self):
        self.filename = get('DATA.FER_PATH')
        self.data_stored = False

    def get_images_labels(self, matrix):
        image_row_len = len(np.fromstring(matrix[0, 1], dtype=int, sep=' '))
        image_dim = int(np.sqrt(image_row_len))
        # images = np.zeros((matrix.shape[0], image_dim, image_dim))
        labels = matrix[:, 0]
        images = []
        for i in range(matrix.shape[0]):
            image_row = np.fromstring(matrix[i, 1], dtype=int, sep=' ')
            images.append(np.reshape(image_row, (image_dim, image_dim)))
        images = np.array(images)
        return images, labels

    def read_csv(self):
        df = pandas.read_csv(self.filename)
        mat = df.as_matrix()
        train_mat = mat[mat[:, 2] == 'Training', :]
        val_mat = mat[mat[:, 2] == 'PublicTest', :]
        test_mat = mat[mat[:, 2] == 'PrivateTest', :]
        self.train_images, self.train_labels = self.get_images_labels(
            train_mat)
        self.val_images, self.val_labels = self.get_images_labels(val_mat)
        self.test_images, self.test_labels = self.get_images_labels(test_mat)
        self.data_stored = True

    def balance_classes(self, images, labels, count=5000):
        balanced_images, balanced_labels = [], []
        unique_labels = set(labels)
        for l in unique_labels:
            l_idx = np.where(labels == l)[0]
            l_images, l_labels = images[l_idx], labels[l_idx]
            # Consistent resampling to facilitate debugging
            resampled_images, resampled_labels = resample(l_images,
                                                          l_labels,
                                                          n_samples=count,
                                                          random_state=0)
            balanced_images.extend(resampled_images)
            balanced_labels.extend(resampled_labels)
        balanced_images = np.array(balanced_images)
        balanced_labels = np.array(balanced_labels)
        print('---Shuffled images shape: {}'.format(balanced_images.shape))
        print('---Shuffled labels shape: {}'.format(balanced_labels.shape))
        assert(len(balanced_images) == len(balanced_labels))
        shuffle_idx = np.random.permutation(len(balanced_images))
        return balanced_images[shuffle_idx], balanced_labels[shuffle_idx]

    def resize(self, images, new_size=32):
        resized = []
        for i in range(images.shape[0]):
            resized_image = imresize(images[i],
                                     size=(new_size, new_size),
                                     interp='bicubic')
            resized.append(resized_image)
        return np.array(resized)

    def preprocessed_data(self, split, dim=32, one_hot=False, balance_classes=True):
        if not self.data_stored:
            self.read_csv()
        if split == 'train':
            print_if_verbose('Loading train data...')
            images, labels = self.train_images, self.train_labels
            # TODO: Remove blank images
            temp_im = [];
            temp_lb = [];
            for i in range(len(images)):
                if(np.linalg.norm(images[i]) >= 1):
                    temp_im += [images[i]];
                    temp_lb += [labels[i]];
            images = np.array(temp_im);
            labels = np.array(temp_lb);

            if balance_classes:
                images, labels = self.balance_classes(images, labels, 5000)
        elif split == 'val':
            print_if_verbose('Loading validation data...')
            images, labels = self.val_images, self.val_labels
            # TODO: Remove blan                                                                                k images
            temp_im = [];
            temp_lb = [];
            for i in range(len(images)):
                if(np.linalg.norm(images[i]) >= 1):
                    temp_im += [images[i]];
                    temp_lb += [labels[i]];
            images = np.array(temp_im);
            labels = np.array(temp_lb);

            if balance_classes:
                images, labels = self.balance_classes(images, labels, 500)
        elif split == 'test':
            print_if_verbose('Loading test data...')
            images, labels = self.test_images, self.test_labels
            # TODO: Remove blank images
            temp_im = [];
            temp_lb = [];
            for i in range(len(images)):
                if(np.linalg.norm(images[i]) >= 1):
                    temp_im += [images[i]];
                    temp_lb += [labels[i]];
            images = np.array(temp_im);
            labels = np.array(temp_lb);

            if balance_classes:
                images, labels = self.balance_classes(images, labels, 500)
        else:
            print_if_verbose('Invalid input!')
            return
        images = self.resize(images, dim)
        # TODO: Normalize, add dimension, one-hot encoding of labels
        temp_im = [];
        temp_lb = [];
        for i in range(len(images)):
            t_im = images[i];
            mu = np.mean(t_im);
            t_im = np.add(t_im, -mu);
            std = np.std(t_im);
            t_im = np.divide(t_im, std);
            temp_im.append(np.expand_dims(t_im,axis = 2))
            if(one_hot):
                temp_vec = [0, 0, 0, 0, 0, 0, 0];
                temp_vec[labels[i]] = 1
                temp_lb += [temp_vec];
        images = np.array(temp_im);
        if(one_hot):
            labels = np.array(temp_lb);
        print_if_verbose('---Images shape: {}'.format(images.shape))
        print_if_verbose('---Labels shape: {}'.format(labels.shape))
        return images, labels

if __name__ == '__main__':
    data = FER2013()
    images, labels = data.preprocessed_data('train')  # 'train' or 'val' or 'test'


from plenum.common.constants import SERVICES, VALIDATOR, TARGET_NYM, DATA
from sovrin_common.roles import Roles
from stp_core.network.port_dispenser import genHa

import pytest

from sovrin_client.test.cli.helper import doSendNodeCmd

def testSuspendNode(be, do, trusteeCli, newNodeAdded):
    """
    Suspend a node and then cancel suspension. Suspend while suspended
    to test that there is no error
    """
    newNodeVals = newNodeAdded

    be(trusteeCli)

    newNodeVals['newNodeData'][SERVICES] = []
    doSendNodeCmd(do, newNodeVals)
    # Re-suspend node
    newNodeVals['newNodeData'][SERVICES] = []
    doSendNodeCmd(do, newNodeVals,
                  expMsgs=['node already has the same data as requested'])

    # Cancel suspension
    newNodeVals['newNodeData'][SERVICES] = [VALIDATOR]
    doSendNodeCmd(do, newNodeVals)

    # Re-cancel suspension
    newNodeVals['newNodeData'][SERVICES] = [VALIDATOR]
    doSendNodeCmd(do, nodeVals=newNodeVals,
              expMsgs=['node already has the same data as requested'])

@pytest.mark.skip(reason='INDY-133. Broken compatibility')
def testSuspendNodeWhichWasNeverActive(be, do, trusteeCli, nymAddedOut,
                                       poolNodesStarted, trusteeMap):
    """
    Add a node without services field and check that the ledger does not
    contain the `services` field and check that it can be blacklisted and
    the ledger has `services` as empty list
    """
    newStewardSeed = '0000000000000000000KellySteward2'
    newStewardIdr = 'DqCx7RFEpSUMZbV2mH89XPH6JT3jMvDNU55NTnBHsQCs'
    be(trusteeCli)
    do('send NYM dest={{remote}} role={role}'.format(
        role=Roles.STEWARD.name),
       within=5,
       expect=nymAddedOut, mapper={'remote': newStewardIdr})
    do('new key with seed {}'.format(newStewardSeed))
    nport, cport = (_[1] for _ in genHa(2))
    nodeId = '6G9QhQa3HWjRKeRmEvEkLbWWf2t7cw6KLtafzi494G4G'
    newNodeVals = {
        'newNodeIdr': nodeId,
        'newNodeData': {'client_port': cport,
                        'client_ip': '127.0.0.1',
                        'alias': 'Node6',
                        'node_ip': '127.0.0.1',
                        'node_port': nport
                        }
    }
    doSendNodeCmd(do, newNodeVals)

    for node in poolNodesStarted.nodes.values():
        txn = [t for _, t in node.poolLedger.getAllTxn()][-1]
        assert txn[TARGET_NYM] == nodeId
        assert SERVICES not in txn[DATA]

    do('new key with seed {}'.format(trusteeMap['trusteeSeed']))
    newNodeVals['newNodeData'][SERVICES] = []
    doSendNodeCmd(do, newNodeVals)

    for node in poolNodesStarted.nodes.values():
        txn = [t for _, t in node.poolLedger.getAllTxn()][-1]
        assert txn[TARGET_NYM] == nodeId
        assert SERVICES in txn[DATA] and txn[DATA][SERVICES] == []


# -*- coding: utf-8 -*-
from django.db.models import Count, Case, When
from django.db.models.functions import TruncDate
from django.utils.translation import gettext as _
from django.utils.translation import get_language

import plotly.offline as plotly
import plotly.graph_objs as go

from core.utils import duration_parts

from reports import utils

def diaperchange_intervals(changes):
    """
    Create a graph showing intervals of diaper changes.
    :param changes: a QuerySet of Diaper Change instances.
    :returns: a tuple of the the graph's html and javascript.
    """

    changes = changes.order_by("time")
    intervals = []
    intervals_solid = []
    intervals_wet = []
    last_change = changes.first()
    for change in changes[1:]:
        interval = change.time - last_change.time
        if interval.total_seconds() > 0:
            intervals.append(interval)
            if change.solid:
                intervals_solid.append(interval)
            if change.wet:
                intervals_wet.append(interval)
        last_change = change

    trace_solid = go.Scatter(
        name=_("Solid"),
        line=dict(shape="spline"),
        x=list(changes.values_list("time", flat=True))[1:],
        y=[i.total_seconds() / 3600 for i in intervals_solid],
        hoverinfo="text",
        text=[_duration_string_hms(i) for i in intervals_solid],
    )

    trace_wet = go.Scatter(
        name=_("Wet"),
        line=dict(shape="spline"),
        x=list(changes.values_list("time", flat=True))[1:],
        y=[i.total_seconds() / 3600 for i in intervals_wet],
        hoverinfo="text",
        text=[_duration_string_hms(i) for i in intervals_wet],
    )

    trace_total = go.Scatter(
        name=_("Total"),
        line=dict(shape="spline"),
        x=list(changes.values_list("time", flat=True))[1:],
        y=[i.total_seconds() / 3600 for i in intervals],
        hoverinfo="text",
        text=[_duration_string_hms(i) for i in intervals],
    )

    layout_args = utils.default_graph_layout_options()
    layout_args["barmode"] = "stack"
    layout_args["title"] = _("<b>Diaper Change Intervals</b>")
    layout_args["xaxis"]["title"] = _("Date")
    layout_args["xaxis"]["rangeselector"] = utils.rangeselector_date()
    layout_args["yaxis"]["title"] = _("Interval (hours)")

    fig = go.Figure(
        {
            "data": [trace_solid, trace_wet, trace_total],
            "layout": go.Layout(**layout_args),
        }
    )
    output = plotly.plot(
        fig,
        output_type="div",
        include_plotlyjs=False,
        config={"locale": get_language()},
    )
    return utils.split_graph_output(output)

def _duration_string_hms(duration):
    """
    Format a duration string with hours, minutes and seconds. This is
    intended to fit better in smaller spaces on a graph.
    :returns: a string of the form Xm.
    """
    h, m, s = duration_parts(duration)
    return "{}h{}m{}s".format(h, m, s)


#!/usr/bin/env python3

import argparse
import logging
import requests
import sys

from alert_autoconf.config import read_from_file
from json import JSONDecodeError

LOG_LEVEL = "DEBUG"

def parse_params() -> dict:
    parser = argparse.ArgumentParser(add_help=True)
    parser.add_argument(
        "-u",
        "--url",
        default="localhost",
        help="Graphite system render url",
        required=False,
    )
    parser.add_argument(
        "-c", "--config", help="Path to trigger description", required=True
    )
    parser.add_argument(
        "-l", "--log-level", default=LOG_LEVEL, help="Log level.", required=False
    )
    parser.add_argument(
        "-C", "--cluster",
        help="Cluster name. If specified, {cluster} will be replaced with this name.",
        required=False,
    )

    return parser.parse_args()

def main():
    frmt = "[%(asctime)s] %(levelname)s:%(name)s:%(funcName)s:%(message)s"
    logging.basicConfig(
        level=logging.getLevelName(LOG_LEVEL),
        stream=sys.stdout,
        format=frmt,
        datefmt="%Y-%m-%d %H:%M:%S",
    )

    _logger = logging.getLogger("validate")

    params = parse_params()
    log_level = params.log_level.upper()

    if LOG_LEVEL != log_level:
        logging.getLogger().setLevel(logging.getLevelName(log_level))
        _logger.setLevel(logging.getLevelName(log_level))

    is_valid = True
    data = read_from_file(params.config, params.cluster)

    for trigger in data.triggers:
        for n, target in enumerate(trigger.targets):
            request_params = {
                "format": "json",
                "target": target,
                "from": "-1min",
                "noNullPoints": "true",
                "maxDataPoints": 1,
            }
            try:
                r = requests.get(params.url, params=request_params)
                r.json()
                _logger.info('Trigger: "%s", target: "%s" OK' % (trigger.name, n))
            except JSONDecodeError as e:
                is_valid = False
                _logger.error(
                    'Trigger: "%s", target: "%s" ERROR: %s' % (trigger.name, n, r.text)
                )
            except Exception as e:
                is_valid = False
                _logger.error(
                    'Trigger: "%s", target: "%s", exception: "%s"'
                    % (trigger.name, n, e)
                )

    if not is_valid:
        sys.exit(1)

if __name__ == "__main__":
    main()


from collections import deque
N = int(input())

def bfs():
    cnt = -1
    q = deque()
    for i in range(10):
        q.append(i)

    while q:
        s = q.popleft()
        cnt += 1
        if cnt == N:
            print(s)
            break
        for i in range(s%10):
            q.append(s * 10 + i)
    else:
        print(-1)

bfs()


"""Use simple rate comparisions, try predicting event rates."""
import numpy as np
import matplotlib.pyplot as plt

from frbpoppy import Survey

from tests.convenience import plot_aa_style, rel_path

ALPHAS = np.around(np.linspace(-0.2, -2.5, 7), decimals=2)
SURVEYS = ('parkes-htru', 'arecibo-palfa', 'askap-fly', 'fast-crafts')

def compare_surveys(surv1, surv2, alpha):
    """Event rate surv1 / Event rate surv2 for an alpha."""
    omega = surv1.beam_size_at_fwhm/surv2.beam_size_at_fwhm
    T_rec = surv1.T_rec/surv2.T_rec
    gain = surv1.gain/surv2.gain
    beta = surv1.beta/surv2.beta
    SEFD = T_rec*beta/gain
    bw = surv1.bw/surv2.bw
    S_min = surv1.snr_limit/surv2.snr_limit

    return omega * (SEFD * S_min)**alpha * (bw)**(-alpha/2)

def analytical_rates(surveys=SURVEYS, alphas=ALPHAS):
    """Use a analytical model to scale detection rates to various alphas."""
    rates = {}

    for surv in surveys:

        # Get survey parameters
        surv1 = Survey(surv)
        surv1.set_beam('perfect', n_sidelobes=0.5)
        surv2 = Survey(surveys[0])
        surv2.set_beam('perfect', n_sidelobes=0.5)

        # Calculate rate per alpha
        rate = []
        for alpha in alphas:
            rate.append(compare_surveys(surv1, surv2, alpha))
        rates[surv] = rate

    return rates

def main():
    """Plot analytical rates."""
    rates = analytical_rates()

    for surv in rates:
        rate = rates[surv]

        plot_aa_style()

        plt.plot(ALPHAS, rate, label=surv)

        plt.xlabel(r'$\alpha_{\text{in}}$')
        plt.ylabel(rf'Events / {SURVEYS[0]}')
        plt.xlim((min(ALPHAS), max(ALPHAS)))
        plt.yscale('log')
        plt.legend()
        plt.gca().invert_xaxis()
        plt.grid(True)
        plt.tight_layout()
        plt.savefig(rel_path('./plots/rates_analytical.pdf'))

if __name__ == '__main__':
    main()


import html
import os
import re

import requests

class DirFile:
    def __init__(self, shop_data_dict, img_list, path, shop):
        self.shop_data_dict = shop_data_dict
        self.img_list = img_list
        self.path = path
        self.shop = shop

    def save_to_local(self):
        try:
            folder_name = self.shop_data_dict["title"]
            folder_name = folder_name.replace(" ", "")
            folder = self.path + "/" + self.shop + "-" + folder_name

            print("===================================================================")
            if not os.path.exists(folder):
                os.makedirs(folder)
                print("파일생성")
            else:
                print("파일 존재")

        except OSError:
            print('Error : Creating folder with ' + folder)

        except Exception as e:
            print('Exception 에러 발생!')
            print(str(e))

        else:
            txt_file_location = folder + "/" + folder_name + ".txt"
            cleanr = re.compile("<.*?>")
            print(txt_file_location)
            # txt 파일 저장
            with open(txt_file_location, "w", encoding="utf-8") as txtFile:
                for shop_data in self.shop_data_dict.values():
                    txtFile.write(html.unescape(re.sub(cleanr, "", str(shop_data).replace("
", "\n").replace("
", "\n"))) + "\n\n")

                print("txt 파일 저장 완료")
            # 이미지 저장
            key = 0
            for img_file in self.img_list:
                img_file_name = folder + "/" + folder_name + '_' + str(key + 1) + '.jpg'

                r = requests.get(img_file)
                file = open(img_file_name, "wb")
                file.write(r.content)
                file.close()

                key += 1
            print("이미지 저장 완료")
            print("===================================================================")


import copy
import datetime as dt
import decimal
import re

import pytest
import pytz

from google.cloud import bigquery
from google.cloud import bigquery_storage_v1beta1
from google.protobuf import timestamp_pb2

def _to_bq_table_ref(proto_table_ref, partition_suffix=""):
    """Converts protobuf table reference to bigquery table reference.

    Args:
        proto_table_ref (bigquery_storage_v1beta1.types.TableReference):
            A protobuf reference to a table.
        partition_suffix (str):
            An optional suffix to append to the table_id, useful for selecting
            partitions of ingestion-time partitioned tables.

    Returns:
        google.cloud.bigquery.table.TableReference
    """
    return bigquery.table.TableReference.from_api_repr(
        {
            "projectId": proto_table_ref.project_id,
            "datasetId": proto_table_ref.dataset_id,
            "tableId": proto_table_ref.table_id + partition_suffix,
        }
    )

@pytest.mark.parametrize(
    "data_format,expected_schema_type",
    (
        (None, "avro_schema"),  # Default format (Avro).
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO, "avro_schema"),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW, "arrow_schema"),
    ),
)
def test_read_rows_as_blocks_full_table(
    client, project_id, small_table_reference, data_format, expected_schema_type
):
    session = client.create_read_session(
        small_table_reference,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
    )
    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )
    schema_type = session.WhichOneof("schema")
    assert schema_type == expected_schema_type

    blocks = list(client.read_rows(stream_pos))

    assert len(blocks) > 0
    block = blocks[0]
    assert block.status.estimated_row_count > 0

@pytest.mark.parametrize(
    "data_format,expected_schema_type",
    (
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO, "avro_schema"),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW, "arrow_schema"),
    ),
)
def test_read_rows_as_rows_full_table(
    client, project_id, small_table_reference, data_format, expected_schema_type
):
    session = client.create_read_session(
        small_table_reference,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
    )
    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )

    rows = list(client.read_rows(stream_pos).rows(session))

    assert len(rows) > 0

@pytest.mark.parametrize(
    "data_format",
    (
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW),
    ),
)
def test_basic_nonfiltered_read(client, project_id, table_with_data_ref, data_format):
    session = client.create_read_session(
        table_with_data_ref,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
    )
    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )

    rows = list(client.read_rows(stream_pos).rows(session))

    assert len(rows) == 5  # all table rows

def test_filtered_rows_read(client, project_id, table_with_data_ref):
    read_options = bigquery_storage_v1beta1.types.TableReadOptions()
    read_options.row_restriction = "age >= 50"

    session = client.create_read_session(
        table_with_data_ref,
        "projects/{}".format(project_id),
        format_=bigquery_storage_v1beta1.enums.DataFormat.AVRO,
        requested_streams=1,
        read_options=read_options,
    )
    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )

    rows = list(client.read_rows(stream_pos).rows(session))

    assert len(rows) == 2

@pytest.mark.parametrize(
    "data_format",
    (
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW),
    ),
)
def test_column_selection_read(client, project_id, table_with_data_ref, data_format):
    read_options = bigquery_storage_v1beta1.types.TableReadOptions()
    read_options.selected_fields.append("first_name")
    read_options.selected_fields.append("age")

    session = client.create_read_session(
        table_with_data_ref,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
        read_options=read_options,
    )
    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )

    rows = list(client.read_rows(stream_pos).rows(session))

    for row in rows:
        assert sorted(row.keys()) == ["age", "first_name"]

def test_snapshot(client, project_id, table_with_data_ref, bq_client):
    before_new_data = timestamp_pb2.Timestamp()
    before_new_data.GetCurrentTime()

    # load additional data into the table
    new_data = [
        {u"first_name": u"NewGuyFoo", u"last_name": u"Smith", u"age": 46},
        {u"first_name": u"NewGuyBar", u"last_name": u"Jones", u"age": 30},
    ]

    destination = _to_bq_table_ref(table_with_data_ref)
    bq_client.load_table_from_json(new_data, destination).result()

    # read data using the timestamp before the additional data load
    session = client.create_read_session(
        table_with_data_ref,
        "projects/{}".format(project_id),
        format_=bigquery_storage_v1beta1.enums.DataFormat.AVRO,
        requested_streams=1,
        table_modifiers={"snapshot_time": before_new_data},
    )
    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )

    rows = list(client.read_rows(stream_pos).rows(session))

    # verify that only the data before the timestamp was returned
    assert len(rows) == 5  # all initial records

    for row in rows:
        assert "NewGuy" not in row["first_name"]  # no new records

def test_column_partitioned_table(
    client, project_id, col_partition_table_ref, bq_client
):
    data = [
        {"description": "Tracking established.", "occurred": "2017-02-15"},
        {"description": "Look, a solar eclipse!", "occurred": "2018-02-15"},
        {"description": "Fake solar eclipse reported.", "occurred": "2018-02-15"},
        {"description": "1 day after false eclipse report.", "occurred": "2018-02-16"},
        {"description": "1 year after false eclipse report.", "occurred": "2019-02-15"},
    ]

    destination = _to_bq_table_ref(col_partition_table_ref)
    bq_client.load_table_from_json(data, destination).result()

    # Read from the table with a partition filter specified, and verify that
    # only the expected data is returned.
    read_options = bigquery_storage_v1beta1.types.TableReadOptions()
    read_options.row_restriction = "occurred = '2018-02-15'"

    session = client.create_read_session(
        col_partition_table_ref,
        "projects/{}".format(project_id),
        format_=bigquery_storage_v1beta1.enums.DataFormat.AVRO,
        requested_streams=1,
        read_options=read_options,
    )

    assert session.streams  # there should be some data to fetch

    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )
    rows = list(client.read_rows(stream_pos).rows(session))

    assert len(rows) == 2

    expected_descriptions = ("Look, a solar eclipse!", "Fake solar eclipse reported.")
    for row in rows:
        assert row["occurred"] == dt.date(2018, 2, 15)
        assert row["description"] in expected_descriptions

@pytest.mark.parametrize(
    "data_format",
    (
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW),
    ),
)
def test_ingestion_time_partitioned_table(
    client, project_id, ingest_partition_table_ref, bq_client, data_format
):
    data = [{"shape": "cigar", "altitude": 1200}, {"shape": "disc", "altitude": 750}]
    destination = _to_bq_table_ref(
        ingest_partition_table_ref, partition_suffix="$20190809"
    )
    bq_client.load_table_from_json(data, destination).result()

    data = [
        {"shape": "sphere", "altitude": 3500},
        {"shape": "doughnut", "altitude": 100},
    ]
    destination = _to_bq_table_ref(
        ingest_partition_table_ref, partition_suffix="$20190810"
    )
    bq_client.load_table_from_json(data, destination).result()

    data = [
        {"shape": "elephant", "altitude": 1},
        {"shape": "rocket", "altitude": 12700},
    ]
    destination = _to_bq_table_ref(
        ingest_partition_table_ref, partition_suffix="$20190811"
    )
    bq_client.load_table_from_json(data, destination).result()

    read_options = bigquery_storage_v1beta1.types.TableReadOptions()
    read_options.row_restriction = "DATE(_PARTITIONTIME) = '2019-08-10'"

    session = client.create_read_session(
        ingest_partition_table_ref,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
        read_options=read_options,
    )

    assert session.streams  # there should be some data to fetch

    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )
    rows = list(client.read_rows(stream_pos).rows(session))
    assert len(rows) == 2

    actual_items = {(row["shape"], row["altitude"]) for row in rows}
    expected_items = {("sphere", 3500), ("doughnut", 100)}
    assert actual_items == expected_items

@pytest.mark.parametrize(
    "data_format",
    (
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW),
    ),
)
def test_decoding_data_types(
    client, project_id, all_types_table_ref, bq_client, data_format
):
    data = [
        {
            u"string_field": u"Price: € 9.95.",
            u"bytes_field": bigquery._helpers._bytes_to_json(b"byteees"),
            u"int64_field": -1085,
            u"float64_field": -42.195,
            u"numeric_field": "1.4142",
            u"bool_field": True,
            u"geography_field": '{"type": "Point", "coordinates": [-49.3028, 69.0622]}',
            u"person_struct_field": {u"name": u"John", u"age": 42},
            u"timestamp_field": 1565357902.017896,  # 2019-08-09T13:38:22.017896
            u"date_field": u"1995-03-17",
            u"time_field": u"16:24:51",
            u"datetime_field": u"2005-10-26T19:49:41",
            u"string_array_field": [u"foo", u"bar", u"baz"],
        }
    ]

    # Explicit schema is needed to recognize bytes_field as BYTES, and not STRING.
    # Since partial schemas are not supported in load_table_from_json(), a full
    # schema needs to be specified.
    schema = [
        bigquery.SchemaField("string_field", "STRING"),
        bigquery.SchemaField("bytes_field", "BYTES"),
        bigquery.SchemaField("int64_field", "INT64"),
        bigquery.SchemaField("float64_field", "FLOAT64"),
        bigquery.SchemaField("numeric_field", "NUMERIC"),
        bigquery.SchemaField("bool_field", "BOOL"),
        bigquery.SchemaField("geography_field", "GEOGRAPHY"),
        bigquery.SchemaField(
            "person_struct_field",
            "STRUCT",
            fields=(
                bigquery.SchemaField("name", "STRING"),
                bigquery.SchemaField("age", "INT64"),
            ),
        ),
        bigquery.SchemaField("timestamp_field", "TIMESTAMP"),
        bigquery.SchemaField("date_field", "DATE"),
        bigquery.SchemaField("time_field", "TIME"),
        bigquery.SchemaField("datetime_field", "DATETIME"),
        bigquery.SchemaField("string_array_field", "STRING", mode="REPEATED"),
    ]

    job_config = bigquery.LoadJobConfig(schema=schema)
    destination = _to_bq_table_ref(all_types_table_ref)
    bq_client.load_table_from_json(data, destination, job_config=job_config).result()

    session = client.create_read_session(
        all_types_table_ref,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
    )

    assert session.streams  # there should be data available

    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=session.streams[0]
    )

    rows = list(client.read_rows(stream_pos).rows(session))

    expected_result = {
        u"string_field": u"Price: € 9.95.",
        u"bytes_field": b"byteees",
        u"int64_field": -1085,
        u"float64_field": -42.195,
        u"numeric_field": decimal.Decimal("1.4142"),
        u"bool_field": True,
        u"geography_field": "POINT(-49.3028 69.0622)",
        u"person_struct_field": {u"name": u"John", u"age": 42},
        u"timestamp_field": dt.datetime(2019, 8, 9, 13, 38, 22, 17896, tzinfo=pytz.UTC),
        u"date_field": dt.date(1995, 3, 17),
        u"time_field": dt.time(16, 24, 51),
        u"string_array_field": [u"foo", u"bar", u"baz"],
    }

    result_copy = copy.copy(rows[0])
    del result_copy["datetime_field"]
    assert result_copy == expected_result

    # Compare datetime separately, AVRO and PYARROW return different object types,
    # although they should both represent the same value.
    # TODO: when fixed, change assertion to assert a datetime instance!
    expected_pattern = re.compile(r"2005-10-26( |T)19:49:41")
    assert expected_pattern.match(str(rows[0]["datetime_field"]))

@pytest.mark.parametrize(
    "data_format",
    (
        (bigquery_storage_v1beta1.enums.DataFormat.AVRO),
        (bigquery_storage_v1beta1.enums.DataFormat.ARROW),
    ),
)
def test_resuming_read_from_offset(client, project_id, data_format):
    shakespeare_ref = bigquery_storage_v1beta1.types.TableReference()
    shakespeare_ref.project_id = project_id
    shakespeare_ref.dataset_id = "public_samples_copy"
    shakespeare_ref.table_id = "shakespeare"

    read_session = client.create_read_session(
        shakespeare_ref,
        "projects/{}".format(project_id),
        format_=data_format,
        requested_streams=1,
    )

    assert read_session.streams  # there should be data available

    stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=read_session.streams[0], offset=0
    )
    read_rows_stream = client.read_rows(stream_pos)

    # fetch the first two batches of rows
    rows_iter = iter(read_rows_stream)
    some_rows = next(rows_iter)
    more_rows = next(rows_iter)

    # fetch the rest of the rows using the stream offset
    new_stream_pos = bigquery_storage_v1beta1.types.StreamPosition(
        stream=read_session.streams[0], offset=some_rows.row_count + more_rows.row_count
    )
    remaining_rows_count = sum(
        1 for _ in client.read_rows(new_stream_pos).rows(read_session)
    )

    # verify that the counts match
    expected_len = 164656  # total rows in shakespeare table
    actual_len = remaining_rows_count + some_rows.row_count + more_rows.row_count
    assert actual_len == expected_len


#Socratica Video 22 List Comprehension
#list comprehension [expression for variable in collection if test1 and test2]
#list comprehension [expression for variable1 in collection1 and variable2 in collection2]
squares = []
for i in range(1, 11):
	squares.append(i**2)
print(squares) #print [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
squares2 = [i**2 for i in range(1,11)]
print(squares2) #print [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

movies = ["Star Wars", "Gandhi", "Casablanca", "Shawshank Redemption", "Toy Story" "Gone With The Wind", "Citizen Kane", "It's A Wonderful Life", "The Wizard Of Oz", "Gattaca", "Rear Window", "Ghostbusters", "To Kill A Mockingbird", "Good Will Hunting", "2001: A Space Odyssey", "Raiders Of The Lost Ark",
"Groundhog Day", "Close Encounters Of The Third Kind"]
gmovies = []
for title in movies:
	if title.startswith("G"):
		gmovies.append(title)
print(gmovies) #print ['Gandhi', 'Gattaca', 'Ghostbusters', 'Good Will Hunting', 'Groundhog Day']
gmovies2 = [title for title in movies if title.startswith("G")]
print(gmovies2) #print ['Gandhi', 'Gattaca', 'Ghostbusters', 'Good Will Hunting', 'Groundhog Day']

movies2 = [("Citizen Kane", 1941), ("Spirited Away", 2001), ("It's A Wonderful Life", 1946), ("Gattaca", 1997), ("No Country For Old Men", 2007), ("Rear Window", 1954), ("The Lord Of The Rings:  The Fellowship Of The Ring", 2001), ("Groundhog Day", 1993), ("Close Encounters Of The Third Kind", 1977),
("The Royal Tenenbaums", 2001), ("The Aviator", 2004), ("Raiders Of The Lost Ark", 1981)]
movies2001 = []
for key, value in movies2:
	if value > 2000:
		movies2001.append(key)
print(movies2001) #print ['Spirited Away', 'No Country For Old Men', 'The Lord Of The Rings:  The Fellowship Of The Ring', 'The Royal Tenenbaums', 'The Aviator']
movies20012 = [title for (title, year) in movies2 if year > 2000]
print(movies20012) #print ['Spirited Away', 'No Country For Old Men', 'The Lord Of The Rings:  The Fellowship Of The Ring', 'The Royal Tenenbaums', 'The Aviator']

vectorlist = [2, -3, 1]
print(4*vectorlist) #print [2, -3, 1, 2, -3, 1, 2, -3, 1, 2, -3, 1] or vectorlist+vectorlist+vectorlist+vectorlist.  Adding lists concatenates them.
wvectorlist = [4*x for x in vectorlist]
print(wvectorlist) #print [8, -12, 4]

#Cartesian product a={1,3} b={x,y} a*b={(1,x), (1,y), (3,x), (3,y)}
oddlist = [1, 3, 5, 7]
evenlist = [2, 4, 6, 8]
cartesianproduct = [(a,b) for a in oddlist for b in evenlist]
print(cartesianproduct) #print [(1, 2), (1, 4), (1, 6), (1, 8), (3, 2), (3, 4), (3, 6), (3, 8), (5, 2), (5, 4), (5, 6), (5, 8), (7, 2), (7, 4), (7, 6), (7, 8)]
cartesianproductproduct = [a*b for a in oddlist for b in evenlist]
print(cartesianproductproduct) #print [2, 4, 6, 8, 6, 12, 18, 24, 10, 20, 30, 40, 14, 28, 42, 56]
print(max(cartesianproductproduct)) #print 56

list1 = [1]
list2 = [2, 3]
list3 = [4, 5, 6]
list123 = [a*b*c for a in list1 for b in list2 for c in list3]
print(list123) #print [8, 10, 12, 12, 15, 18]
listall = [[1], [2, 3], [4, 5, 6]]
listallproduct = [a for a in listall]
print(listallproduct) #print [[1], [2, 3], [4, 5, 6]]

#RM 018maximumpathsumi.py Project Euler
# lista = [3]
# listb = [7, 4]
# listc = [2, 4, 6]
# listd = [8, 5, 9, 3]
# listabcd = [print(a, b, c, d) for a in lista for b in listb for c in listc for d in listd if a+b+c+d==23] #print 3 7 6 9 which is incorrect.  Want 3 7 4 9

#https://www.pythonforbeginners.com/basics/list-comprehensions-in-python
#result = [transform for iteration if filter]
result = [evennumber for evennumber in range(0,6) if evennumber % 2 == 0]
print(result) #print [0, 2, 4]
x = [i for i in range(0,11)]
print(x) #print [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
listofwords = ["this","is","a","list","of","words"]
firstletters = [eachlistofwords[0] for eachlistofwords in listofwords]
print(firstletters) #print ['t', 'i', 'a', 'l', 'o', 'w']
print(x.upper() for x in ["a","b","c"]) #print <generator object <genexpr> at 0x7facced5c360>
print([x.upper() for x in ["a","b","c"]]) #print ["A","B","C"]
extractnumbersinstring = "Hello 12345 World"
numbersasstring = [x for x in extractnumbersinstring if x.isdigit()]
print(numbersasstring) #print ['1', '2', '3', '4', '5']
stringasstring = [x for x in extractnumbersinstring if x.isalpha()]
print(stringasstring) #print ['H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd']
def double(x):
	return x*2
print([double(x) for x in range(0,11)]) #print [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
print([double(x) for x in range(0,11) if x % 2 == 0]) #print [0, 4, 8, 12, 16, 20]

#https://hackernoon.com/list-comprehension-in-python-8895a785550b
lista = [1, 2, 3, 4]
listb = [2, 3, 4, 5]
matchnumbers = [a for a in lista for b in listb if a == b]
print(matchnumbers) #print [2, 3, 4]

#https://docs.python.org/3.5/tutorial/datastructures.html
listx = [1, 2, 3]
listy = [3, 1, 4]
xandytuple = [(x,y) for x in listx for y in listy if x!= y]
print(xandytuple) #print [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
#long way
xandytuple = []
for x in listx:
	for y in listy:
		if x != y:
			xandytuple.append((x,y))
print(xandytuple) #print [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
vector = [-4, -2, 0, 2, 4]
absolutevector = [abs(eachvector) for eachvector in vector]
print(absolutevector) #print [4, 2, 0, 2, 4]
from math import pi
pinumbers = [str(round(pi, i)) for i in range(1,7)]
print(pinumbers) #print ['3.1', '3.14', '3.142', '3.1416', '3.14159', '3.141593']

#continue 5.1.4 Nested List Comprehensions 07/17/18
a1 = [[3, 0, 0], [7, 4, 0], [2, 4, 6]]
transpose = [[row[i] for row in a1] for i in range(0,3)]
print(transpose) #print [[3, 7, 2], [0, 4, 4], [0, 0, 6]]
transpose = [[row[i] for row in a1 for i in range(0,3)]]
print(transpose) #print [[3, 0, 0, 7, 4, 0, 2, 4, 6]]

#3x4 matrix 3 lists length 4
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
onelist = []
for i in range(0,3):
	for j in range(0,3):
		print(matrix[i][j]) #print 1\n 2\n 3\n 5\n 6\n 7\n \n 10\n 11
		onelist.append(matrix[i][j])
print(onelist) #print [1, 2, 3, 5, 6, 7, 9, 10, 11]
print([row[i] for row in matrix for i in range(0,3)]) #print [1, 2, 3, 5, 6, 7, 9, 10, 11]
#3x4 matrix 3 lists length 4
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
onelist = []
for i in range(0,3):
	for j in range(0,4):
		print(matrix[i][j]) #print 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n 11\n 12
		onelist.append(matrix[i][j])
print(onelist) #print [1, 2, 3, 5, 6, 7, 9, 10, 11, 12]
print([row[i] for row in matrix for i in range(0,4)]) #print [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

#3x4 matrix 3 lists length 4
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
transposed = []
for i in range(0,3):
	transposedrow = []
	for eachlist in matrix:
		print(eachlist[i]) #print 1\n 5\n 9\n 2\n 6\n 10\n 3\n 7\n 11
		transposedrow.append(eachlist[i])
	transposed.append(transposedrow)
print(transposed) #print [[1, 5, 9], [2, 6, 10], [3, 7, 11]]
print([[row[i] for row in matrix] for i in range(0,3)]) #print [[1, 5, 9], [2, 6, 10], [3, 7, 11]]
#3x4 matrix 3 lists length 4
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
transposed = []
for i in range(0,4):
	transposedrow = []
	for eachlist in matrix:
		print(eachlist[i]) #print 1\n 5\n 9\n 2\n 6\n 10\n 3\n 7\n 11\n 4\n 8
		transposedrow.append(eachlist[i])
	transposed.append(transposedrow)
print(transposed) #print [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
print([[row[i] for row in matrix] for i in range(0,4)]) #print [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

#zip() function creates a list of tuples
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
print(list(zip(*matrix))) #print [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
print(zip(*matrix)) #print <zip object at 0x7ff55d585f88>

letterhundreds = [("a",232), ("b",343), ("c", 543), ("d",23)]
print(letterhundreds) #print [('a', 232), ('b', 343), ('c', 543), ('d', 23)]
pivotletterhundreds = list(zip(*letterhundreds))
print(pivotletterhundreds) #print [('a', 'b', 'c', 'd'), (232, 343, 543, 23)]
print(pivotletterhundreds[0]) #print ('a', 'b', 'c', 'd')
print(list(pivotletterhundreds[0])) #print ['a', 'b', 'c', 'd']

#Python Implementing _zip_ with list comprehensions — Reuven Lerner.pdf https://lerner.co.il/2016/08/30/implementing-zip-list-comprehensions/
#Python 2’s “zip” returns a list, but Python 3’s “zip” returns an iterator object or <zip object at . . . >
#Use zip for string and tuples
sletters = "abcde"
tnumbers = (1, 2, 3, 4, 5)
tnumbersoneless = (1, 2, 3, 4)
umore = ("jack","sack","tack","back","pack")
print(zip(sletters, tnumbers)) #print <zip object at 0x7f66c7048b08>
print(list(zip(sletters, tnumbers))) #print [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
print(list(zip(sletters, tnumbersoneless))) #print [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
print(list(zip(sletters, tnumbers, umore))) #print [('a', 1, 'jack'), ('b', 2, 'sack'), ('c', 3, 'tack'), ('d', 4, 'back'), ('e', 5, 'pack')]
#Lists to dictionaries
names = ["Tom", "Dick", "Harry"]
ages = [50, 35, 60]
print(dict(zip(names, ages))) #print {'Tom': 50, 'Dick': 35, 'Harry': 60}
from itertools import repeat
def zip_longest(*args, fillvalue="put fillvalue here"):
    # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
    iterators = [iter(it) for it in args]
    num_active = len(iterators)
    if not num_active:
        return
    while True:
        values = []
        for i, it in enumerate(iterators):
            try:
                value = next(it)
            except StopIteration:
                num_active -= 1
                if not num_active:
                    return
                iterators[i] = repeat(fillvalue) #repeat() function is from the itertools module
                value = fillvalue
            values.append(value)
        yield tuple(values)
print(zip_longest(sletters, tnumbersoneless)) #print <generator object zip_longest at 0x7fe1faac9a98>
print(zip(zip_longest(sletters, tnumbersoneless))) #print <zip object at 0x7f6a2b8e64c8>
print(list(zip_longest(sletters, tnumbersoneless))) #print [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 'put fillvalue here')]
#Zip in list comprehension
sletterstnumbers = [(sletters[i], tnumbers[i]) for i in range(0,len(sletters))]
print(sletterstnumbers) #print [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
#Author wanted to create a function to clean things up
def shortest_sequence_range(*args):
	return range(len(sorted(args, key=len)[0]))
print([(sletters[i], tnumbers[i]) for i in shortest_sequence_range(sletters, tnumbers)]) #print [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]


# Uncomment the next two lines to enable the admin:
from django.conf.urls import patterns, include, url
from productes import views

urlpatterns = patterns('',
    url(r'^$', views.llistarProductes, name='llistarProductes'),
    url(r'^llistarCategories/$', views.llistarCategories, name='llistarCategories'),
    url(r'^llistarCategoriesAjax/$', views.llistarCategoriesAjax, name='llistarCategoriesAjax'),
    url(r'^llistarProductes/$', views.llistarProductes, name='llistarProductes'),
    url(r'^afegirProducte/(?P<categoria>\w+)/$', views.afegirProducte, name='afegirProducte'),
    url(r'^afegirProducte/$', views.afegirProducte, name='afegirProducte'),
    url(r'^afegirCategoria/$', views.afegirCategoria, name='afegirCategoria'),
    url(r'^editarProducte/(?P<idProducte>\d+)/$', views.editarProducte, name='editarProducte'),
    url(r'^dadesProducte/(?P<idProducte>\d+)/$', views.dadesProducte, name='dadesProducte'),
 )


import copy
import matplotlib.pyplot as plt
from numpy import sqrt, inf
from sklearn.model_selection import train_test_split
from tqdm import tqdm
import torch
import torch.nn as nn
import torch.optim as optim

from models.cnn import CNN
from linegeneration.generate_lines import create_image_set
from utils.logger import logger
from plot.lines_visualisation import create_multiplots
from utils.angle_operations import normalize_angle
from utils.misc import load_list_from_file
from models.model import loss_fn_dic
from utils.save_model import save_model
from utils.settings import settings
from utils.statistics import calculate_std_dev, accuracy

plt.rcParams.update({
    "text.usetex": True,
    "font.family": "serif"
})

def main():

    if settings.synthetic:
        # Read Synthetic data
        N = settings.patch_size_x
        n = settings.n_synthetic
        X, y = create_image_set(n, N, background=True, aa=True)  # n images of size NxN

        image_set_test, angles_test = create_image_set(n, N, background=True, aa=True)
        fig, axes = create_multiplots(image_set_test, angles_test, number_sample=n, cmap='copper')
        plt.show()

        # X = X.reshape(n, N*N)
        # # Set title for loss evolution with respect to epoch and model name
        # model_name = f'best_model_experimental_Dx_convolution_{settings.loss_fn}_batch{settings.batch_size}_epoch{settings.n_epochs}_kernel{settings.kernel_size_conv}'
        #
        # ax_title = f'Training on the synthetic patches (convolution) \n Learning rate: {settings.learning_rate} | Epochs: {settings.n_epochs} | Batch: {settings.batch_size} | Kernel: {settings.kernel_size_conv}'

    else:
        X_path = settings.x_path
        y_path = settings.y_path
        X, y = torch.load(X_path), [float(x) for x in load_list_from_file(y_path)]
        # Set title for loss evolution with respect to epoch and model name
        model_name = f'best_model_experimental_Dx_convolution_{settings.loss_fn}_batch{settings.batch_size}_epoch{settings.n_epochs}_kernel{settings.kernel_size_conv}'
        ax_title = f'Training on the experimental patches (convolution + Dx) \n Learning rate: {settings.learning_rate} | Epochs: {settings.n_epochs} | Batch: {settings.batch_size} | Kernel: {settings.kernel_size_conv}'

    # Load data
    X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.7, shuffle=True)

    # Convert to 2D PyTorch tensors
    X_train = torch.tensor(X_train, dtype=torch.float32)
    y_train = torch.tensor(y_train, dtype=torch.float32).reshape(-1, 1)
    X_test = torch.tensor(X_test, dtype=torch.float32)
    y_test = torch.tensor(y_test, dtype=torch.float32).reshape(-1, 1)
    logger.info('Dataset has been set up successfully')

    # Set hyperparameters
    batch_size = settings.batch_size
    learning_rate = settings.learning_rate
    num_epochs = settings.n_epochs

    # Initialize model
    kernel_size_conv = settings.kernel_size_conv
    network = CNN(kernel_size_conv)

    name_criterion = settings.loss_fn
    criterion = loss_fn_dic[name_criterion]

    optimizer = optim.Adam(network.parameters(), lr=learning_rate)  # optimizer
    logger.info('Model has been initialized')

    # Move network and data tensors to device
    device = network.device
    network.to(device)
    X_train = X_train.to(device)
    y_train = y_train.to(device)
    X_test = X_test.to(device)
    y_test = y_test.to(device)

    # We use the pre-defined number of epochs to determine how many iterations to train the network on
    batch_start = torch.arange(0, len(X_train), batch_size)
    # Hold the best model
    best_loss = inf   # init to infinity
    best_weights = None
    history = []

    # Initialize the progress bar
    pbar = tqdm(range(num_epochs), desc="Training Progress", unit="epoch")

    for epoch in range(num_epochs):
        network.train()  # prepare model for training
        # Load in the data in batches using the train_loader object
        for start in batch_start:
            # Take a batch
            X_batch = X_train[start:start + batch_size]
            y_batch = y_train[start:start + batch_size]

            # Forward pass
            y_pred = network(X_batch)
            loss = criterion(y_pred, y_batch)

            # Backward pass
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

        # Evaluate accuracy at the end of each epoch
        network.eval()
        y_pred = network(X_test)

        mse = criterion(y_pred, y_test)
        mse = float(mse)
        history.append(mse)

        # Update the progress bar description
        pbar.update(1)
        pbar.set_postfix({"Loss": mse})

        if mse < best_loss:
            best_loss = mse
            best_weights = copy.deepcopy(network.state_dict())
            acc = accuracy(y_test, y_pred)

    # Close the progress bar
    pbar.close()
    # logger.info('Training is ended')

    # Restore model and return best accuracy
    network.load_state_dict(best_weights)
    y_pred = network(X_test)
    std = calculate_std_dev(y_pred, y_test)

    # if anti_alias:
    #     model_name = f'best_model_cnn_synthetic_gaussian{sigma}_kernel{kernel_size_conv}_aa.pt'
    # save_model(network, model_name, 'cnn')

    # Plot accuracy
    fig, ax = plt.subplots()
    ax.set_title(ax_title, fontsize=12)
    print("MSE: %.4f" % best_loss)
    print("STD: % .4f" % std)
    print(f"Accuracy: {acc}")
    ax.set_xlabel('Epoch')
    ax.set_ylabel(f'Loss ({name_criterion})')
    ax.plot(history)

    # Add a text box to the plot
    textstr = '\n'.join((
        r'$Loss = %.4f$' % (best_loss, ) + f' ({settings.loss_fn})',
        r'$\sigma = %.4f$' % (std, ),
        r'$Accuracy = %.4f$' % (acc, )
    ))

    props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
    ax.text(0.9, 0.9, textstr, transform=ax.transAxes, fontsize=14, ha='right', va='top', bbox=props)
    # plt.savefig(f".\saved\plot\{model_name}.png")
    plt.show()

    # Plot some lines and patches
    # if torch.cuda.is_available():
    #     y_pred_numpy = y_pred.cpu().cpu().detach().numpy()
    # else:
    #     y_pred_numpy = y_pred.cpu().detach().numpy()

    # fig1, axes1 = create_multiplots(X_test.cpu(), y_test.cpu(), y_pred_numpy, number_sample=16)
    # plt.tight_layout()
    # plt.savefig(f".\saved\plot\{model_name}_patches.png")
    # plt.show()

if __name__ == '__main__':
    main()