import torch
import numpy as np
import torch.nn as nn
import time
from utils.util import AverageMeter
# normal conv2d stacked 50 layers

class separable_conv2d(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=3, padding=1, dilation=1):
        """
            in_channels = out_channels = groups, using thcunn backends of pytorch, otherwise using cudnn
        """
        super(separable_conv2d, self).__init__()
        self.depthwise_conv2d = nn.Conv2d(in_channels=in_channels,
                                          out_channels=out_channels,
                                          kernel_size=kernel_size, stride=1,
                                          padding=padding, dilation=dilation, groups=in_channels)
        self.pointwise_conv2d = nn.Conv2d(in_channels=in_channels,
                                          out_channels=out_channels,
                                          kernel_size=1, stride=1,
                                          padding=0, dilation=dilation, groups=1)
    def forward(self, input):
        output = self.depthwise_conv2d(input)
        output = self.pointwise_conv2d(output)
        return output

class normal_convnet(nn.Module):
    def __init__(self):
        super(normal_convnet, self).__init__()
        self.layer_list = nn.ModuleList()
        self.layer_list.append(nn.Conv2d(3, 256, 3, padding=1, groups=1))
        for index in range(48):
            self.layer_list.append(nn.Conv2d(256, 256, 3, padding=1, groups=1))
        self.layer_list.append(nn.Conv2d(256, 10, 3, padding=1, groups=1))

    def forward(self, x):
        for layer in self.layer_list:
            x = layer(x)
        return x

class sep_convnet(nn.Module):
    def __init__(self):
        super(sep_convnet, self).__init__()
        self.layer_list = nn.ModuleList()
        self.layer_list.append(nn.Conv2d(3, 256, 3, padding=1, groups=1))
        for index in range(48):
            self.layer_list.append(separable_conv2d(256,256,3,1))
        self.layer_list.append(nn.Conv2d(256, 10, 3, padding=1, groups=1))

    def forward(self, x):
        for layer in self.layer_list:
            x = layer(x)

        return x

def inference_test_both():

    #torch.manual_seed(1)
    #torch.backends.cudnn.enabled = False
    #torch.backends.cudnn.benchmark = True
    #torch.backends.cudnn.deterministic=True

    random_input = torch.randn((1, 3, 256, 256))
    random_output = torch.randint(low=0, high=10, size=(1,256,256)) # for 0,1,2,3,4,5,6,7,8,9
    #random_output = torch.randn((1,3,256,256))

    net1 = normal_convnet().to('cuda:0')
    net2 = sep_convnet().to('cuda:0')

    # params = 0
    #params_normal = sum(p.numel() for p in normal_net.parameters() if p.requires_grad)
    #print("Trainable Parameters :", params_normal)

    #criterion = nn.MSELoss().to('cuda:0')
    criterion = nn.CrossEntropyLoss().to('cuda:0')

    #optimizer_1 = torch.optim.Adam(params=net1.parameters(), lr=0.1)
    #optimizer_2 = torch.optim.Adam(params=net2.parameters(), lr=0.1)
    optimizer_1 = torch.optim.SGD(params=net1.parameters(),lr=0.1)
    optimizer_2 = torch.optim.SGD(params=net2.parameters(),lr=0.2)
    #

    cost1 = AverageMeter()
    cost2 = AverageMeter()
    print("Simulate Training ... ...")

    input1 = random_input.to('cuda:0')
    target1 = random_output.to('cuda:0')
    torch.cuda.synchronize()
    tic = time.time()
    optimizer_1.zero_grad()
    output1 = net1(input1)
    loss = criterion(output1, target1)
    loss.backward()
    optimizer_1.step()
    torch.cuda.synchronize()
    cost1.update(time.time() - tic)

    #print(dw_net)
    #params_dw = sum(p.numel() for p in normal_net.parameters() if p.requires_grad)
    #print("Trainable Parameters :", params_dw)
    #optimizer_dw = torch.optim.Adam(params=dw_net.parameters())

    input2 = random_input.to('cuda:0')
    target2 = random_output.to('cuda:0')
    torch.cuda.synchronize()
    tic = time.time()
    optimizer_1.zero_grad()
    output2 = net2(input2)
    loss = criterion(output2, target2)
    loss.backward()
    optimizer_2.step()
    torch.cuda.synchronize()
    cost2.update(time.time() - tic)

    print("Done for All !")

    print("Trainable Parameters:\n"
          "Normal_conv2d: {}\n"
          "Sep_conv2d    : {}".format(parameters_sum(net1), parameters_sum(net2)))
    print("Inference Time cost:\n"
          "Normal_conv2d: {}s\n"
          "Sep_conv2d    : {}s".format(cost1._get_sum(), cost2._get_sum()))

def parameters_sum(model):

    return sum(p.numel() for p in model.parameters() if p.requires_grad)

if __name__ == '__main__':

    '''
    #for separable conv2d
    #Duration:  0.07718038558959961 for normal
    #Duration:  0.041310787200927734 for separable conv2d including depthwise and pointwise
    input = torch.randn(size=(1,256,256,256))
    target = torch.randn(size=(1,256,256,256))

    m1 = nn.Conv2d(256,256,3,padding=1, groups=1,bias=False).to('cuda:0')
    m2 = nn.Conv2d(256,256,3,padding=1, groups=256,bias=False).to('cuda:0')
    m2_p = nn.Conv2d(256,256,1,padding=0, groups=1,bias=False).to('cuda:0')
    criterion = nn.MSELoss().to('cuda:0')
    optimizer_m1 = torch.optim.SGD(params=m1.parameters(),lr=0.1)
    optimizer_m2 = torch.optim.SGD(params=m2.parameters(),lr=0.1)

    tic = time.time()
    input1 = input.to('cuda:0')
    target1 = target.to('cuda:0')
    out1 = m1(input1)
    loss = criterion(out1, target1)
    optimizer_m1.zero_grad()
    loss.backward()
    optimizer_m1.step()
    print("Duration: ", time.time()-tic)

    tic = time.time()
    input2 = input.to('cuda:0')
    target2 = target.to('cuda:0')
    out2 = m2(input2)
    out2 = m2_p(out2)
    loss = criterion(out2, target2)
    optimizer_m2.zero_grad()
    loss.backward()
    optimizer_m2.step()
    print("Duration: ", time.time()-tic)
    '''
    inference_test_both()
    """
    output: for 50 layers stacked up and run 100 iterations
    Normal_conv2d: 17.160080671310425s
    sep_conv2d    : 7.4953773021698s
    """
    """
    output: net1 trainable parameters:  29504000
            net2 trainable parameters:  3417600

            29504000 / 3417600 = 8.6
    net1 = normal_convnet()
    net2 = sep_convnet()
    print("net1 trainable parameters: ", parameters_sum(net1))
    print("net2 trainable parameters: ", parameters_sum(net2))

    """


# -*- coding = utf-8 -*-
#Author: Yihang He
#@Time : 2021/1/4 7:00 上午
#@Author : Yihang He
#@File : testXwlt.py
#@Software: PyCharm

import xlwt

workbook = xlwt.Workbook(encoding= "utf-8")      #创建workbook对象
worksheet = workbook.add_sheet("sheet_1")        #创建工作表
worksheet.write(0,0,"hello")   #写入数据 第一个参数为行 第二个参数为列 第三个为参数内容
workbook.save("student.xls")       #保存数据表


#!/usr/bin/env python

# Example calculation of the partial Chern number (pcn) for a spinor slab model i.e extended in x-y plane
# and finite in the z direction. After the C(l) list is calculated
# the routine plots the pcn density and integrated pcn in a single output PDF.

from __future__ import print_function # python3 style print
from pythtb import * # import TB model class
from numpy import linalg as LA
import matplotlib.pyplot as plt
from pcn import *

# Example model for axion insulator from Phys. Rev. B 83, 245132
def cubic_model(n_layers):
   # set model parameters
   # lattice parameter implicitly set to a=1
   m   = 1.00
   a   = 0.50
   b   = 0.50
   Bx  = 0.40

   # define lattice vectors
   lat=[[ 1.0, 0.0, 0.0],[ 0.0, 1.0, 0.0],[ 0.0, 0.0, 1.0]]
   # define coordinates of orbitals
   # orb = [site a or 0, site b or 1]
   orb=[[0.0,0.0,0.0], [0.0,0.0,0.0]]
   # make 3d model
   my_model=tb_model(3,3,lat,orb,nspin=2)

   # vector with the pauli matrices
   Id = [[1, 0],[ 0, 1]]
   sx = [[0, 1],[ 1, 0]]
   sy = [[0, -1j],[1j, 0]]
   sz = [[1, 0],[0, -1]]
   sd = [[1, 0],[0, 0]]
   s_pauli = np.zeros((4,2,2),dtype=complex)
   s_pauli  = [Id,sx,sy,sz]

   # set on-site energy
   onsite1 =  (3-m)*np.array(s_pauli[0])+Bx*np.array(sz)
   onsite2 = -(3-m)*np.array(s_pauli[0])-Bx*np.array(sz)
   my_model.set_onsite([onsite1,onsite2])

   # set first neighbour hoppings
   my_model.set_hop(b*1.j*np.array(s_pauli[3]), 1, 0, [-1, 0, 0])
   my_model.set_hop(a*np.array(s_pauli[0]), 1, 0,    [ 0, -1, 0])
   my_model.set_hop(a*1.j*np.array(s_pauli[2]), 1, 0, [ 0, 0, -1])

   my_model.set_hop(-b*1.j*np.array(s_pauli[3]), 1, 0, [ 1, 0, 0])
   my_model.set_hop(-a*np.array(s_pauli[0])    , 1, 0, [ 0, 1, 0])
   my_model.set_hop(-a*1.j*np.array(s_pauli[2]), 1, 0, [ 0, 0, 1])

   #second neighbours
   my_model.set_hop(-b*np.array(s_pauli[0]), 0, 0, [ 1, 0, 0])
   my_model.set_hop(-a*np.array(s_pauli[0]), 0, 0, [ 0, 1, 0])
   my_model.set_hop(-a*np.array(s_pauli[0]), 0, 0, [ 0, 0, 1])

   my_model.set_hop(b*np.array(s_pauli[0]), 1, 1, [ 1, 0, 0])
   my_model.set_hop(a*np.array(s_pauli[0]), 1, 1, [ 0, 1, 0])
   my_model.set_hop(a*np.array(s_pauli[0]), 1, 1, [ 0, 0, 1])

   # create finite model in the z direction
   finite_model=my_model.cut_piece(n_layers,2)
   return finite_model

#Set the model and calculate PCN
################################################
#number of layers of the slab
n_layers= 10
#set the slab model
my_model = cubic_model(n_layers)
print("The model has been constructed..")
#focus on half the slab
n_layer    = int(n_layers/2) #
orbs       = 4 #number of orbital*spin per layer
n_orb001   = orbs*n_layer
n_occ      = int(n_layers*orbs/2) #assuming half filling
#calculate the partial Chern number for each orbital
print("Calling subroutine pcn.. (this may take several minutes)")
cl001 = c_l(my_model,n_occ)[:n_orb001]
#################################################

print("Plotting pcn density and integrated pcn..")
#Define rectangular functions
rect001 = np.zeros((n_layer,n_orb001),dtype=float)
for i in range(n_layer):
    for j in range(i*orbs):
        rect001[i,j] = 0.0
    for j in range(orbs):
        rect001[i,i*orbs+j] = 1.0

#Define ramp functions
ramp001 = np.zeros((n_layer,n_orb001),dtype=float)
for i in range(n_layer):
    for j in range(i*orbs):
        ramp001[i,j] = 1.0
    for j in range(orbs):
        ramp001[i,i*orbs+j] = 0.5

#pcn density
cdens    = np.zeros((n_layer),dtype=float)
for i in range(n_layer):
    cdens[i] = -np.dot(rect001[i,:],cl001[:])

#integrated pcn(partial Chern number)
cint = np.zeros((n_layer),dtype=float)
for i in range(n_layer):
    cint[i] = -np.dot(ramp001[i,:],cl001[:])

#Begin Plotting
#Define x-axis i.e. layer depth
layers = np.linspace(0.5, n_layer-0.5, num=n_layer)
labs=['(a)','(b)']
fig, ax = plt.subplots(1,2,figsize=(8.,3.))
#Plot Chern number per layer
ax[0].plot(layers,cdens,color='blue', marker='o',label = "[001]")
ax[0].axhline(0,c='k',ls='dashed')
# put title
ax[0].set_xlabel("layer")
ax[0].set_ylabel(r'$C(l) $')
ax[0].text(-0.7,0.48,labs[0],size=18.)

#Plot integrated Chern number
ax[1].plot(layers,cint,color='blue', marker='o',label = "[001]")
ax[1].set_ylim(0.25,0.55)
ax[1].axhline(0.5,c='k',ls='dashed')
# put title
ax[1].set_xlabel("layer")
ax[1].set_ylabel(r'$C_{int}(n) $')
ax[1].text(-1.0,0.54,labs[1],size=18.)

# make an PDF figure of a plot
fig.tight_layout()
plt.subplots_adjust(wspace=0.35)
fig.savefig("pcn.pdf")

print('Done.\n')
##############################


#Bernardo Carlos Franceschina - 20203080
#Enzo Bassani - 20200398
from helpers.BernardoEnzo_helper import *
from datetime import timedelta
class Procedimento:
    def __init__(self, nome, valor, tempo, descricao):
        self.nome = nome
        self.valor  = valor
        self.descricao = descricao
        self.tempo = tempo

    def editar(self):
        while True:
            option = input("Qual informação deseja editar?\n1) Nome\n2) Valor\n3) Descrição\n4) Tempo\n0) Voltar")
            if (option == '1'):
                self.nome = input('Novo nome: ')
                return
            elif (option == '2'):
                self.valor = getnum('Novo valor: ', 1, 0)
                return
            elif (option == '3'):
                self.descricao = input("Nova descricao: ")
                return
            elif (option == '4'):
                duracao = getnum("Duração(hh:mm): ", 2, 0, [24, 60], separator=":")
                duracao = timedelta(hours=duracao[0], minutes=duracao[1])
                self.tempo = duracao
            elif(option == '0'):
                return
            else: print("Opção inválida")


from PIL import ImageDraw, ImageOps
import cv2
import numpy as np

def remove_notes(data_range, image, x_thresh, y_thresh):
    staves = get_stave_lines(data_range, image, x_thresh)
    bar_lines = get_bar_lines(data_range, image, y_thresh)

    image_copy = image.copy()

    blackout = ImageDraw.Draw(image_copy)
    blackout.rectangle(data_range, fill="#ffffff")
    for pixel in staves + bar_lines:
        colour = image.getpixel(pixel)
        image_copy.putpixel(pixel, colour)

    return image_copy

def remove_stave(data_range, image, x_thresh, y_thresh, recursions=3):
    staves = get_stave_lines(data_range, image, x_thresh)
    # bar_lines = get_bar_lines(data_range, image, y_thresh)

    image_copy = image.copy()

    # blackout = ImageDraw.Draw(image_copy)
    # blackout.rectangle(data_range, fill="#ffffff")
    for pixel in staves:
        image_copy.putpixel(pixel, 255)

    image_array = image.copy()
    image_array = image_array.crop((data_range[0][0], data_range[0][1], data_range[1][0], data_range[1][1]))
    image_array = np.array(image_array)

    thresh = cv2.threshold(image_array, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5))
    image_array = np.invert(cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=1))
    image_array = image_array.tolist()

    for y, row in enumerate(image_array):
        for x, col in enumerate(row):
            pixel_val = int(image_array[y][x])
            pixel_x = x + data_range[0][0]
            pixel_y = y + data_range[0][1]

            if pixel_val == 0:
                image_copy.putpixel((pixel_x, pixel_y), pixel_val)

    # return image_copy
    # image_copy = recurse_pixels(image, staves, recursions, 'horizontal')
    # image_copy = recurse_pixels(image_copy, bar_lines, recursions, 'vertical')

    return image_copy

# https://stackoverflow.com/questions/60521925/how-to-detect-the-horizontal-and-vertical-lines-of-a-table-and-eliminate-the-noi

def get_stave_lines2(data_range, image, x_thresh):  # Updated function
    # Load the image
    image_copy = image.copy()
    image_copy = image_copy.crop((data_range[0][0], data_range[0][1], data_range[1][0], data_range[1][1]))
    image_copy = np.array(image_copy)

    staves = get_stave_lines(data_range, image, x_thresh=x_thresh)  # Shit version

    # blur = cv2.GaussianBlur(image_copy, (3, 3), 0)
    thresh = cv2.threshold(image_copy, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

    # Detect horizontal lines
    horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5))
    horizontal_mask = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, horizontal_kernel, iterations=1)

    # Detect vertical lines
    vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 50))
    vertical_mask = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=1)

    stave_pixels = horizontal_mask.copy()
    stave_pixels.fill(0)

    for pixel in staves:
        x, y = pixel
        x -= (data_range[0][0] + 1)
        y -= (data_range[0][1] + 1)
        stave_pixels[y, x] = 1

    horizontal_mask[horizontal_mask > 0] = 1

    new_horizontal_mask = cv2.bitwise_and(horizontal_mask, stave_pixels)
    new_horizontal_mask = new_horizontal_mask.tolist()

    result_stave_lines = []
    for y, row in enumerate(new_horizontal_mask):
        for x, pixel in enumerate(row):
            if pixel != 0:
                print(pixel)
                result_stave_lines.append((x + data_range[0][0] + 1, y + data_range[0][1] + 1))
    return result_stave_lines

    # cv2.imshow('horizontal_mask', new_horizontal_mask)
    # cv2.imshow('vertical_mask', vertical_mask)
    # cv2.waitKey()

def recurse_pixels(image, pixels, recursions, orientation):
    image_copy = image.copy()

    if recursions > 0:
        pixels_to_check = []
        for pixel in pixels:
            if orientation == 'horizontal':
                # No neighbours above or no neighbours below
                if image_copy.getpixel((pixel[0], pixel[1] - 1)) == 255 or image_copy.getpixel((pixel[0], pixel[1] + 1)) == 255:
                    image.putpixel(pixel, 255)
                else:
                    pixels_to_check.append(pixel)
            else:
                if image_copy.getpixel((pixel[0] - 1, pixel[1])) == 255 or image_copy.getpixel((pixel[0] + 1, pixel[1])) == 255:
                    image.putpixel(pixel, 255)
                else:
                    pixels_to_check.append(pixel)
        image = recurse_pixels(image, pixels_to_check, recursions - 1, orientation)

    return image

def get_stave_lines(data_range, image, x_thresh):
    started_line = False
    lines = []

    for y in range(data_range[0][1], data_range[1][1] + 1):
        for x in range(data_range[0][0], data_range[1][0] + 1):
            pixel_colour = image.getpixel((x, y))
            if pixel_colour != 255:
                if not started_line:
                    lines.append([])
                    started_line = True
                lines[-1].append((x, y))
            else:
                started_line = False
        started_line = False

    kept_pixels = []
    for line in lines:
        if len(line) >= x_thresh:
            for pixel in line:
                kept_pixels.append(pixel)

    kept_pixels = list(dict.fromkeys(kept_pixels))  # Remove duplicates

    return kept_pixels

def get_bar_lines(data_range, image, y_thresh):
    rows = []
    started_row = False

    for x in range(data_range[0][0], data_range[1][0] + 1):
        for y in range(data_range[0][1], data_range[1][1] + 1):
            pixel_colour = image.getpixel((x, y))
            if pixel_colour != 255:
                if not started_row:
                    rows.append([])
                    started_row = True
                rows[-1].append((x, y))
            else:
                started_row = False
        started_row = False

    kept_pixels = []
    for row in rows:
        row_length = len(row)
        if row_length >= y_thresh:
            for pixel in row:
                kept_pixels.append(pixel)

    return kept_pixels


# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import glob
import os

import testtools

class TestDirectories(testtools.TestCase):

    def test_directories(self):
        releases = [x.split('/')[1] for x in glob.glob('specs/*/')]
        for release in releases:
            if release == 'abandoned':
                continue
            files = os.listdir("specs/%s/" % release)
            valid = ['redirects', 'implemented', 'approved']
            for name in files:
                if name.startswith('.'):
                    continue
                self.assertIn(name, valid,
                              "Found unexpected file in "
                              "'specs/%s', specs should be submitted to "
                              "'specs/%s/approved'" % (release, release))


import tkinter as tk
from tkinter import filedialog as fd
from tkinter.messagebox import showinfo
from tkinter import ttk
import time
import cv2
import numpy as np
from PIL import Image, ImageEnhance, ImageDraw
from PIL.ExifTags import TAGS
import sys

class Greeting:
	'''Creates the starting TK-window with file-chooser opening'''

	@classmethod
	def start(cls):
		'''Initializes the GREATING window toolkit with the image CHOOSER, returns the file path'''
		root = tk.Tk()
		root.title('ECG-helper')
		root_width = 700
		root_height = 500
		root.geometry(f'{root_width}x{root_height}+400+150')
		bg = tk.PhotoImage(file = "bg.png")
		canvas1 = tk.Canvas(root, width=root_width, height=root_height)
		canvas1.pack(fill = "both", expand = True)
		canvas1.create_image(0, 0, image = bg, anchor = "nw")
		canvas1.create_text(root_width/2, root_height/3, text = "Welcome! \nTo get started, select the file with the required ECG:", justify=tk.CENTER, font="Verdana 24", fill='#B63340')

		def select_image():
			'''Determines the function of open-button: open a file chooser dialog and allow the user to select an image'''
			global filepath
			filetypes = (('image files', '.png'), ('image files', '.jpg'))
			filepath = fd.askopenfilename(title='Open a file', initialdir='/', filetypes=filetypes)

			if len(filepath) > 0:
				'''ensure a file path was selected'''
				showinfo(title='The file has been selected!', message='Now select a section of \nthe ECG-line for each lead \n(from the top left point \nto the bottom right point)', parent=root)
				root.destroy()
			else:
				showinfo(title='The file was not selected!', message='Try once more')

		open_button = tk.Button(root, activebackground='pink', activeforeground='black', bd='0', fg='#B63340', highlightbackground='#3E4149', relief='flat', overrelief='sunken', text='Select an ECG-image', font="Verdana 17", padx="10", pady="10", command=select_image)
		button_canvas = canvas1.create_window(root_width/3, root_height*2/3, window = open_button)
		root.mainloop()
		return filepath

class Lead:
	'''Opens the image from file and allows to crop all 12 leads from full ECG; save leads as separate files for further usage witth appropriate names'''
	def __init__(self, name, ecg_file):
		self.name = name
		self.cropping = False
		self.x_start, self.y_start, self.x_end, self.y_end = 0, 0, 0, 0
		image = cv2.imread(ecg_file)
		oriImage = image.copy()
		self.mm = self.pixel_in_mm(ecg_file)

		def mouse_crop(event, x, y, flags, param):
			'''if the left mouse button was DOWN, start RECORDING (x, y) coordinates and indicate that cropping is being:'''
			if event == cv2.EVENT_LBUTTONDOWN:
				self.x_start, self.y_start, self.x_end, self.y_end = x, y, x, y
				self.cropping = True
				'''Mouse is Moving:'''
			elif event == cv2.EVENT_MOUSEMOVE:
				if self.cropping == True:
					self.x_end, self.y_end = x, y
					'''if the left mouse button was released:'''
			elif event == cv2.EVENT_LBUTTONUP:
				'''record the ending (x, y) coordinates:'''
				self.x_end, self.y_end = x, y
				'''cropping is finished:'''
				self.cropping = False
				self.box = [self.x_start, self.y_start, self.x_end, self.y_end]

				if len(self.box) == 4:
					'''when two points were found'''
					roi = oriImage[self.box[1]:self.box[3], self.box[0]:self.box[2]]
					cv2.namedWindow(f"{self.name} lead (press 'Enter' to continue)")
					cv2.moveWindow(f"{self.name} lead (press 'Enter' to continue)", self.x_start//2, self.y_start//2)
					cv2.imshow(f"{self.name} lead (press 'Enter' to continue)", roi)
					cv2.imwrite(f"temp_pics/{self.name}.png", roi)
		cv2.namedWindow(f"Select region of {self.name} lead upper-left point >> lower-right point")
		cv2.setMouseCallback(f"Select region of {self.name} lead upper-left point >> lower-right point", mouse_crop)

		i = image.copy()
		if not self.cropping:
			cv2.imshow(f"Select region of {self.name} lead upper-left point >> lower-right point", image)
		elif self.cropping:
			cv2.rectangle(i, (self.x_start, self.y_start), (self.x_end, self.y_end), (255, 0, 0), 2)
			cv2.imshow(f"Select region of {self.name} lead upper-left point >> lower-right point", i)
		cv2.waitKey(0)

	def pixel_in_mm(self, image):
		'''Finds the resolution of image in meta-data PPI to convert it in mm'''
		with Image.open(image) as img:
			img.load()
		exifdata = img.getexif()
		return round(exifdata[282]/2.54/10)

class ChangeLead:
	'''Transforms each lead-image to binary image'''
	def __init__(self, pic):
		self.pic = pic

	@staticmethod
	def cleaning(pic, start_pix):
		'''Static tool for cleaning the image from separate background black points'''
		draw = ImageDraw.Draw(pic)
		width = pic.size[0]
		height = pic.size[1]
		pix = pic.load()

		for x in range(start_pix, width-1, 3):
			for y in range(start_pix, height-1, 3):
				a = pix[x, y]
				sur_colors = []
				sur = [[x-1, y-1], [x, y-1], [x+1, y-1], [x+1, y],
					   [x+1, y+1], [x, y+1], [x-1, y+1], [x-1, y]]
				for s in sur:
					sur_colors.append(pix[s[0],s[1]])
				w = sur_colors.count(255)
				b = sur_colors.count(0)

				if a == 255:
					if w > 5:
						for s in sur:
							draw.point([s[0], s[1]], 255)
					elif w < 2:
						for s in sur:
							draw.point([x, y], 0)
				elif a == 0:
					if b > 7:
						for s in sur:
							draw.point([s[0], s[1]], 0)
					elif b < 2:
						for s in sur:
							draw.point([x, y], 255)
		del draw
		return pic

	def change(self):
		'''Few steps of image-transforming with different tools'''
		with Image.open(self.pic) as img:
			img.load()
		enh = ImageEnhance.Contrast(img)
		out = enh.enhance(3.0)
		fn = lambda x : 255 if x > 40 else 0
		im = out.convert('L').point(fn, mode='1')
		cln = ChangeLead.cleaning(im, 1)
		cln = ChangeLead.cleaning(cln, 2)
		cln = ChangeLead.cleaning(cln, 1)
		cln = ChangeLead.cleaning(cln, 3)
		return cln

class Isoline:
	'''Finds the starting isoline (first 10 mm of lead-image)'''
	def __init__(self, pic):
		'''Collects parameters of lead-image for usage by this in further classes'''
		self.pic = ChangeLead(pic).change()
		self.width = self.pic.size[0]
		self.height = self.pic.size[1]
		self.pix = self.pic.load()
		self.isoline_y = self.find_y()
		self.isoline_x = self.find_x()

	def find_y(self):
		'''Finds the most intensive 1 mm of y from first 10 mm'''
		iso_y = 0
		blacks = 0
		for y in range(self.height-6):
			count_blacks = 0
			for x1 in range(60):
				for y1 in range(y, y+6):
					if self.pix[x1, y1] == 0:
						count_blacks += 1
			if count_blacks >= blacks:
				blacks = count_blacks
				iso_y = y
		return iso_y

	def find_x(self):
		'''Finds the most intensive 2,5 mm of x from first 10 mm'''
		iso_x = 0
		intens = 0
		for x in range(60):
			count_blacks = 0
			for x1 in range(x, x+15):
				for y1 in range(self.isoline_y, self.isoline_y+6):
					if self.pix[x1, y1] == 0:
						count_blacks += 1
			if count_blacks >= intens:
				intens = count_blacks
				iso_x = x
		return iso_x

class ECGline(Isoline):
	'''Collects coordinates of ECG-line only avoding the background points'''
	ecg_coord = []
	def __init__(self, pic):
		super().__init__(pic)

	def x_last(self):
		if len(ECGline.ecg_coord) > 0:
			return max(ECGline.ecg_coord,key=lambda item:item[0])[0]
		else:
			return 0

	def find_start(self, start, span):
		'''Finds start for recursive collection of coordinates'''
		for x in range(start, self.width):
			for y in range(self.isoline_y-span, self.isoline_y+span):
				if y in range(self.height):
					if self.pix[x, y] == 0:
						ECGline.ecg_coord.append((x, y))
						return x, y
				else:
					continue

	def registration(self, x, y):
		'''Collecting coordinates connected with main ECG-line'''

		sur = [(x-1, y-1), (x, y-1), (x+1, y-1), (x+1, y),
			   (x+1, y+1), (x, y+1), (x-1, y+1), (x-1, y)]
		for s in sur:
			if s[0] <= 0 or s[0] >= self.width-1 or s[1] <= 0 or s[1] >= self.height-1:
				continue
			elif s in ECGline.ecg_coord:
				continue
			elif self.pix[s[0],s[1]] == 255:
				continue
			elif self.pix[s[0]-1,s[1]] == 255 and self.pix[s[0]+1,s[1]] == 255:
				continue
			else:
				ECGline.ecg_coord.append(s)
				self.registration(s[0],s[1])

		while self.width - self.x_last() > 15:
			x, y = self.find_start(self.x_last()+1, 24)
			self.registration(x, y)

class RealLead(ECGline):
	'''Redraws the lead-image so that to save only ECG-line'''
	def __init__(self, pic):
		super().__init__(pic)
		self.image = self.draw_ecg()

	def draw_ecg(self):
		'''Fills the noising bg-points with white color'''
		draw = ImageDraw.Draw(self.pic)
		for x in range(self.width):
			for y in range(self.height):
				if (x, y) not in ECGline.ecg_coord:
					draw.point([x, y], 255)
		del draw
		return self.pic

	def fill_gaps(self):
		'''NOT COMPLETED Fills of line gaps with averages'''
		blacks = {}
		for x in range(24, self.width-24):
			blacks[x] = []
			for y in range(self.isoline_y):
				if self.pix[x, y] == 0:
					blacks[x].append(y)

class Cycle(RealLead):
	'''One cardiac cycle from lead with its characteristics'''
	def __init__(self, pic):
		super().__init__(pic)
		self.r = self.wave_R()
		self.j = self.point_J()
		self.local_iso = self.local_iso()
		self.st = self.st_level()

	def mean_line(self, x):
		'''Finds an average y position for specified x of line'''
		blacks = []
		if x in range(self.width):
			for y in range(self.height):
				if self.pix[x, y] == 0:
					blacks.append(y)
		else:
			pass
		if len(blacks) > 0:
			return int(sum(blacks)/len(blacks))
		else:
			return self.isoline_y

	def wave_R(self):
		'''R-wave peak of the current QRS complex'''
		for y in range(self.isoline_y):
			for x in range(20, self.width-20):
				if self.pix[x, y] == 0:
					return x, y

	def point_J(self):
		'''Coordinates of J-point for the current Cycle'''
		x = self.r[0] + 15
		y = self.mean_line(x)
		return x, y

	def local_iso(self):
		'''Isoline y-coordinate just before the current QRS complex'''
		ys = []
		for x in range(self.r[0]-27, self.r[0]-12):
			ys.append(self.mean_line(x))
		return int(sum(ys)/len(ys))

	def st_level(self):
		'''The level of ST-elevetion of the current Cycle'''
		return self.local_iso - self.j[1]

class Pathology:
	'''Some diseases ECG-criteria'''
	mi = []
	def __init__(self, st_elevation):
		self.st_elevation = st_elevation

	def infarction(self):
		'''Defines the location of MI by the names of leads with pathology'''
		if 'III' in self.st_elevation and 'aVF' in self.st_elevation:
			Pathology.mi.append('ECG-signs of the acute inferior (posterior) miocardial infarction')
		elif 'I' in self.st_elevation and 'aVL' in self.st_elevation:
			Pathology.mi.append('ECG-signs of the acute anterior miocardial infarction')
		elif 'V1' in self.st_elevation and 'V2' in self.st_elevation:
			Pathology.mi.append('ECG-signs of the acute septal or right ventricular miocardial infarction')
		elif 'V3' in self.st_elevation and 'V4' in self.st_elevation:
			Pathology.mi.append('ECG-signs of the acute anterior miocardial infarction')
		elif 'V5' in self.st_elevation and 'V6' in self.st_elevation:
			Pathology.mi.append('ECG-signs of the acute lateral miocardial infarction')

class Processing:
	'''Creates the TK-window with Progressbar and provides leads processing'''

	lead_names = ('I', 'II', 'III', 'aVR', 'aVL', 'aVF', 'V1', 'V2', 'V3', 'V4', 'V5', 'V6')
	ecg_file = Greeting.start()
	for l in lead_names:
		Lead(l, ecg_file)
	cv2.destroyAllWindows()

	all_pics = [f'temp_pics/{l}.png' for l in lead_names]
	st_elevation = []

	def justwait(self):
		'''TK-window for processing'''

		def iter_progress(progress=12):
			'''Increments the progress-line with every lead done'''

			root.update_idletasks()
			pb['value'] = 12-progress

			if progress == 0:
				lbl['text'] = 'Done!'
				root.after(1000, root.destroy)
				return
			else:
				lbl['text'] = f'Image processing started.. \n{progress-1}'

			p = Processing.all_pics[12-progress]
			i = Isoline(p)
			e = ECGline(p)
			#e.pic.show()
			sys.setrecursionlimit(10000)
			e.registration(e.find_start(0, 12)[0], e.find_start(0, 12)[1])
			re = RealLead(p)
			#re.image.show()
			c1 = Cycle(p)
			print(f'\nFor lead {p.split("/")[1].split(".")[0]}:')
			print('wave R - ', c1.r)
			print('point J - ', c1.j)
			print('isoline - ', c1.local_iso)
			print('level st - ', c1.st)

			if p.split("/")[1] == 'V2.png' or p.split("/")[1] == 'V3.png':
				if c1.st > 12:
					Processing.st_elevation.append(p.split("/")[1].split('.')[0])
			else:
				if c1.st > 6:
					Processing.st_elevation.append(p.split("/")[1].split('.')[0])
			ECGline.ecg_coord.clear()
			root.after(1, lambda: iter_progress(progress-1))

		root = tk.Tk()
		root.geometry(f'700x500+400+150')
		root.title('Processing...')

		pb = ttk.Progressbar(
			root,
			orient='horizontal',
			mode='determinate',
			length=400,
			maximum=12
		)
		lbl = tk.Label(root, text = f'Image processing started.. \n12', font="Verdana 24")
		lbl.place(relx=0.5, rely=0.3, anchor='center')
		pb.place(relx=0.5, rely=0.5, anchor='center')
		root.after(200, iter_progress)
		root.mainloop()

		print(f'\nST-segment is elevated in {", ".join(Processing.st_elevation)}')
		pat = Pathology(Processing.st_elevation)
		pat.infarction()
		result = Conclusion()
		result.finish()

class Conclusion:
	'''Creates the final TK-window with the conclusion'''

	def finish(self):
		'''Creates the final TK-window with the conclusion'''
		root = tk.Tk()
		root.title('ECG-helper')
		root_width = 700
		root_height = 500
		root.geometry(f'{root_width}x{root_height}+400+150')
		bg = tk.PhotoImage(file = "bg.png")
		canvas1 = tk.Canvas(root, width=root_width, height=root_height)
		canvas1.pack(fill = "both", expand = True)
		canvas1.create_image(0, 0, image = bg, anchor = "nw")

		# take the data
		damage = ";\n    ".join(Pathology.mi)
		summary = f'Rhythm pacemaker: sinus rhythm \nRegularuty of rhythm: regular \nHeart rate: 72 \nElectrical heart axis: left axis deviation \nArrhythmias: - \nConduction disturbances: - \nHypertrophy: -\nMyocardial damage: \n    {damage}'

		canvas1.create_text(root_width/2, root_height/4, text = summary, justify=tk.LEFT, font="Verdana 15", fill='#B63340')
		root.mainloop()

if __name__ == '__main__':
	proc = Processing()
	proc.justwait()


from           django.shortcuts  import render, redirect
from django.contrib.auth.models  import User
from                     .forms  import Userform, CustomerForm, EditUserForm
from  invoice_management.models  import iv_customer, iv_cart
from     django.core.exceptions  import ObjectDoesNotExist
def profile_V(request):
    form = Userform()
    current_user = request.user
    current_user_id=request.user.id-1
    form.fields['username'].initial=        User.objects.all()[current_user_id].username
    form.fields['first_name'].initial=      User.objects.all()[current_user_id].first_name
    form.fields['last_name'].initial=       User.objects.all()[current_user_id].last_name
    form.fields['email'].initial=           User.objects.all()[current_user_id].email

    if(current_user.is_staff):
        if(current_user.is_superuser):
            users = User.objects.all()
            return render(request, 'invoice_profile_management/profile.html', {'user_data':current_user,'form':form,'users':users})
        else:
            return render(request, 'invoice_profile_management/profile.html', {'user_data':current_user,'form':form})
    else:
        try:
            qr = iv_customer.objects.get(user = request.user)
        except ObjectDoesNotExist:
            qr = None
        if(qr):
            cust_qry=           iv_customer.objects.get(user = request.user)
            cart=               iv_cart.objects.filter(customer_fk = cust_qry)
            okc=                iv_customer.objects.get(user = current_user)
            cart=               iv_cart.objects.filter(customer_fk = okc)
            cust_id=            iv_customer.objects.filter(user = current_user)
            qr=                 iv_customer.objects.filter(user = current_user)
            customer_edit = CustomerForm()
            customer_edit.fields['business_address'].initial=   '%s %s' %("  ",qr[0].business_address)
            customer_edit.fields['business_name'].initial=      qr[0].business_name
            customer_edit.fields['business_email'].initial=     qr[0].business_email
            customer_edit.fields['city'].initial=               qr[0].city
            customer_edit.fields['country'].initial=            qr[0].country
            customer_edit.fields['fax'].initial=                qr[0].fax

            return render(request, 'invoice_profile_management/profile.html', {'customer_edit':customer_edit,'user_data':current_user,'form':form,'cart':cart})

        else:
            customer = CustomerForm()
            return render(request, 'invoice_profile_management/profile.html', {'user_data':current_user,'form':form,'customer':customer})

def customer_PROF_V(request):
    form=           Userform()
    customer_edit=  CustomerForm()
    current_user = request.user
    form.fields['username'].initial=      current_user.username
    form.fields['first_name'].initial=    current_user.first_name
    form.fields['last_name'].initial=     current_user.last_name
    form.fields['email'].initial=         current_user.email
    try:
        cust_qry = iv_customer.objects.get(user = request.user)
    except ObjectDoesNotExist:
        cust_qry = None
    if(cust_qry):
        cart = iv_cart.objects.filter(customer_fk = cust_qry)
        context = {'customer_edit':customer_edit,'user_data':current_user,'form':form,'cart':cart}
    else:
        context = {'customer_edit':customer_edit,'user_data':current_user,'form':form}
    if(request.method == 'POST'):
        form = CustomerForm(request.POST)
        if(form.is_valid()):
            form.save(commit=False)
            business_name=         form.cleaned_data["business_name"]
            business_email=        form.cleaned_data["business_email"]
            business_address=      form.cleaned_data["business_address"]
            city=                  form.cleaned_data["city"]
            country=               form.cleaned_data["country"]
            fax=                   form.cleaned_data["fax"]

            customer = iv_customer(               user=current_user,
            business_name=business_name,          business_email=business_email,
            business_address=business_address,    city=city,
            country=country,                      fax=fax)
            customer.save()
            context = {'customer_edit':customer_edit,'user_data':current_user,'form':form}
    if(request.method == 'GET'):
        customer_form = CustomerForm(request.GET)
        if(customer_form.is_valid()):
            customer_form.save(commit=False)
            qry_customer = iv_customer.objects.filter(user = current_user)
            if(qry_customer):
                business_name=          customer_form.cleaned_data["business_name"]
                business_email=         customer_form.cleaned_data["business_email"]
                business_address=       customer_form.cleaned_data["business_address"]
                city=                   customer_form.cleaned_data["city"]
                country=                customer_form.cleaned_data["country"]
                fax=                    customer_form.cleaned_data["fax"]
                qry_customer[0].business_name=      business_name
                qry_customer[0].business_email=     business_email
                qry_customer[0].business_address=   business_address
                qry_customer[0].city=     city
                qry_customer[0].country=  country
                qry_customer[0].fax=      fax
                qry_customer[0].save()
                return render(request, 'invoice_profile_management/profile.html', {'customer_edit':customer_form,'user_data':current_user,'form':form,'cart':cart})

    return render(request, 'invoice_profile_management/profile.html', context)
def invoice_DELETE(request, id):
    current_user =  request.user
    User.objects.get(id = id).delete()
    return redirect('profile')


# coding: utf-8
# Author：Brent
# Date ：2020/7/1 4:21 PM
# Tool ：PyCharm
# Describe ：给你一个由 '1'（陆地）和 '0'（水）组成的的二维网格，请你计算网格中岛屿的数量。
#
# 岛屿总是被水包围，并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
#
# 此外，你可以假设该网格的四条边均被水包围。
#
#
#
# 示例 1:
#
# 输入:
# 11110
# 11010
# 11000
# 00000
# 输出: 1
# 示例 2:
#
# 输入:
# 11000
# 11000
# 00100
# 00011
# 输出: 3
# 解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
#
# 来源：力扣（LeetCode）
# 链接：https://leetcode-cn.com/problems/number-of-islands
from collections import deque
from typing import List

class Solution:
    #        x-1,y
    # x,y-1    x,y      x,y+1
    #        x+1,y
    # 方向数组，它表示了相对于当前位置的 4 个方向的横、纵坐标的偏移量，这是一个常见的技巧
    directions = [(-1, 0), (0, -1), (1, 0), (0, 1)]

    def numIslands(self, grid: List[List[str]]) -> int:
        m = len(grid)
        # 特判
        if m == 0:
            return 0
        n = len(grid[0])
        marked = [[False for _ in range(n)] for _ in range(m)]
        count = 0
        # 从第 1 行、第 1 格开始，对每一格尝试进行一次 DFS 操作
        for i in range(m):
            for j in range(n):
                # 只要是陆地，且没有被访问过的，就可以使用 DFS 发现与之相连的陆地，并进行标记
                if not marked[i][j] and grid[i][j] == '1':
                    # count 可以理解为连通分量，你可以在深度优先遍历完成以后，再计数，
                    # 即这行代码放在【位置 1】也是可以的
                    count += 1
                    self.__dfs(grid, i, j, m, n, marked)
                    # 【位置 1】
        return count

    def __dfs(self, grid, i, j, m, n, marked):
        marked[i][j] = True
        for direction in self.directions:
            new_i = i + direction[0]
            new_j = j + direction[1]
            if 0 <= new_i < m and 0 <= new_j < n and not marked[new_i][new_j] and grid[new_i][new_j] == '1':
                self.__dfs(grid, new_i, new_j, m, n, marked)

    def numIslands_dfs(self, grid: [[str]]) -> int:

        def dfs(grid, i, j, rows, columns):
            # 终止条件：
            # (i, j) 越过矩阵边界;
            # grid[i][j] == 0，代表此分支已越过岛屿边界。
            if not 0 <= i < rows or 0 <= j < columns or grid[i][j] == '0': return
            grid[i][j] = '0'
            dfs(grid, i + 1, j, rows, columns)
            dfs(grid, i - 1, j, rows, columns)
            dfs(grid, i, j + 1, rows, columns)
            dfs(grid, i, j - 1, rows, columns)

        count = 0
        rows = len(grid)
        if rows == 0: return 0
        columns = len(grid[0])
        for i in range(rows):
            for j in range(columns):
                if grid[i][j] == '1':
                    dfs(grid, i, j, rows, columns)
                    count += 1
        return count

    def numIslands_bfs(self, grid: [[str]]) -> int:
        def bfs(grid, i, j):
            queue = [[i, j]]
            while queue:
                [i, j] = queue.pop(0)
                if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == '1':
                    grid[i][j] = '0'
                    queue += [[i + 1, j], [i - 1, j], [i, j - 1], [i, j + 1]]

        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '0': continue
                bfs(grid, i, j)
                count += 1
        return count

if __name__ == '__main__':
    # grid = [['1', '1', '1', '1', '0'],
    #         ['1', '1', '0', '1', '0'],
    #         ['1', '1', '0', '0', '0'],
    #         ['0', '0', '0', '0', '0']]
    grid = []
    solution = Solution()
    result = solution.numIslands_dfs(grid)
    print(result)


import cv2 as cv
import mediapipe as mp
import time

#video cap
capture = cv.VideoCapture(0)

#PIPE utulities
mpHand = mp.solutions.hands
hand = mpHand.Hands()
mpDraw = mp.solutions.drawing_utils

#times
cTime=0
pTime=0

#video cap loop
while True:
    isTrue, frame = capture.read()

    frame = cv.flip(frame,1)

    #results are only uses with RGB
    frameRgb = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
    results = hand.process(frameRgb)

    #Multiple hand landmarks
    if results.multi_hand_landmarks:
        for handlms in results.multi_hand_landmarks:
            mpDraw.draw_landmarks(frame,handlms, mpHand.HAND_CONNECTIONS)
            for id,lm in enumerate(handlms.landmark):
                h,w,c = frame.shape
                cx,cy = int(lm.x*w), int(lm.y*h)
                cv.putText(frame, str(id), (cx,cy), cv.FONT_HERSHEY_COMPLEX_SMALL, 0.75 ,(0,255,255), 1)

    #our FPS
    cTime = time.time()
    fps = int(1/(cTime-pTime))
    pTime=cTime

    cv.putText(frame, str(fps), (10,70), cv.FONT_HERSHEY_SIMPLEX, 2, (255,255,0), 2)

    #Our window
    cv.imshow('frame',frame)

    #Pres 'q' to stop
    if cv.waitKey(1)  & 0xFF == ord('q'):
        break

#refresh
capture.release()
cv.destroyAllWindows()


import sys
import binascii
import zmq.asyncio
import asyncio

loop = zmq.asyncio.ZMQEventLoop()
asyncio.set_event_loop(loop)

import libbitcoin
context = libbitcoin.Context()

async def main():
    client = context.Client("tcp://gateway.unsystem.net:9091")

    idx = "77cb1e9d44f1b8e8341e6e6848bf34ea6cb7a88bdaad0126ac1254093480f13f"
    idx = bytes.fromhex(idx)

    ec, tx_data = await client.transaction(idx)
    if ec:
        print("Couldn't fetch transaction:", ec, file=sys.stderr)
        context.stop_all()
        return
    # Should be 257 bytes.
    print("tx size is %s bytes" % len(tx_data))

    ec, height, index = await client.transaction_index(idx)
    if ec:
        print("Couldn't fetch transaction_index:", ec, file=sys.stderr)
        context.stop_all()
        return
    # 210000 4
    print(height, index)

    context.stop_all()

if __name__ == '__main__':
    tasks = [
        main(),
    ]
    tasks.extend(context.tasks())
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()


# -*- coding: utf-8 -*-
"""
Created on Tue Feb 25 20:39:39 2020

@author: Connor
@Desc: Combining SOM with ANN to predict Frauds
"""

# Hybrid Deep Learning Model

### Building SOM

# Importing the libraries
import numpy as np
import pandas as pd

# Importing the dataset (Using UCI Machine learning Repository)
dataset = pd.read_csv('Credit_Card_Applications.csv')
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, -1].values

# Feature Scaling
from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range = (0, 1))
X = sc.fit_transform(X)

# Training the SOM (Using minisom https://github.com/JustGlowing/minisom/blob/master/minisom.py)
from minisom import MiniSom
som = MiniSom(x = 10, y = 10, input_len = 15, sigma = 1.0, learning_rate = 0.5)
som.random_weights_init(X)
som.train_random(data = X, num_iteration = 100)

# Visualizing the results
from pylab import bone, pcolor, colorbar, plot, show
bone()
pcolor(som.distance_map().T)
colorbar()
markers = ['o', 's']
colors = ['r', 'g']
for i, x in enumerate(X):
    w = som.winner(x)
    plot(w[0] + 0.5,
         w[1] + 0.5,
         markers[y[i]],
         markeredgecolor = colors[y[i]],
         markerfacecolor = 'None',
         markersize = 10,
         markeredgewidth = 2)
show()

# Finding the frauds (dependent on the result of the SOM)
mappings = som.win_map(X)
frauds = np.concatenate((mappings[(7,7)], mappings[(3,5)]), axis = 0)
frauds = sc.inverse_transform(frauds)

### Preparing Supervised Model

# Creating Matrix
customers = dataset.iloc[:, 1:].values

# Creating dependent variable
is_fraud = np.zeros(len(dataset))
for i in range(len(dataset)):
    if dataset.iloc[i, 0] in frauds:
        is_fraud[i] = 1

# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
customers = sc.fit_transform(customers)

### Creating the ANN

# Importing the Keras libraries and packages
from keras.models import Sequential
from keras.layers import Dense

# Initialise ANN
classifier = Sequential()

# Adding Input layers and hidden layers (with Dropout)
classifier.add(Dense(2, kernel_initializer='random_uniform', activation = 'relu', input_shape = (15,)))

# Add Output Layer
classifier.add(Dense(1, kernel_initializer='random_uniform', activation = 'sigmoid'))

# Compiling ANN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

# Fit ANN to Training set
classifier.fit(customers, is_fraud, batch_size = 1, epochs = 2)

# Predicting the probabilities of frauds
y_pred = classifier.predict(customers)
y_pred = np.concatenate((dataset.iloc[:,0:1].values, y_pred), axis = 1)
y_pred = y_pred[y_pred[:, 1].argsort()]


import torch
from model import Model

def compute_psnr(denoised, ground_truth):
    mse = torch.mean((denoised-ground_truth)**2)
    return -10 * torch.log10(mse + 10**(-8))

path_train = '../data/train_data.pkl'
path_val = '../data/val_data.pkl'

if __name__ == "__main__" :
    mod = Model()

    torch.cuda.empty_cache()

    noisy_imgs_1, noisy_imgs_2 = torch.load(path_train)
    noisy_imgs, clean_imgs = torch.load(path_val)

    mod.train(noisy_imgs_1, noisy_imgs_2, 100)

    out = mod.predict(noisy_imgs)

    psnr = compute_psnr(out.cpu().float()/256, clean_imgs.float()/256)


import os
import logging
import cv2
import numpy as np

import torch
from torch import Tensor
from torch.utils.tensorboard.writer import SummaryWriter
from typing import Union

class Logger(): # remember to close

    def __init__(self, path: str, file_name: str='log.txt') -> None:
        self._path = path
        if not os.path.exists(self._path):
            os.mkdir(self._path)

        self._logger = logging.getLogger('train_log_file')    # set logger name
        self._logger.setLevel(logging.INFO)                   # set logger level
        fh_stream = logging.StreamHandler()                         # console handle
        fh_file = logging.FileHandler(os.path.join(self._path, file_name), encoding='utf-8') # log file handle

        fh_stream.setLevel(logging.DEBUG)
        fh_file.setLevel(logging.DEBUG)

        formatter = logging.Formatter('%(asctime)s - %(message)s')
        fh_stream.setFormatter(formatter)
        fh_file.setFormatter(formatter)

        self._logger.addHandler(fh_stream)
        self._logger.addHandler(fh_file)

        self._visual = SummaryWriter(self._path)
        self._train_log_fh = open(os.path.join(self._path, 'train_log.txt'), 'w')
        self._test_log_fh = open(os.path.join(self._path, 'test_log.txt'), 'w')

    def info(self, msg: str) -> None:
        self._logger.info(msg)

    def addImage(self, tag, img, step, dataformats) -> None:
        self._visual.add_image(tag, img, step, dataformats=dataformats)

    def addImages(self, tag, imgs, step, dataformats) -> None:
        self._visual.add_images(tag, imgs, step, dataformats=dataformats)

    def addScalar(self, tag, scalar, step) -> None:
        self._visual.add_scalar(tag, scalar, step)

    # def record(self, phase: str, epoch: int, num: int, output: Tensor, loss: Tensor, step: int, mask: Union[Tensor, None]) -> None:
    #     log_str = f'{phase}_Epoch {epoch} - No.{num}, loss: {loss.item()}'
    #     self._logger.info(log_str)

    #     # 待补充完整

    def recordTrain( self,
                epoch: int,
                num: int,
                loss: float,
                mean_iu: float,
                pixel_accuracy: float,
                mean_accuracy: float,
                class_accuracy: float,
                mean_iu0: float,
                mean_iu1: float,
                step: int):
        phase = 'train'
        # write file
        file_log_str = "%d\t%d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t" % (
                epoch, num, loss, mean_iu, pixel_accuracy, mean_accuracy, class_accuracy, mean_iu0, mean_iu1)
        fh = self._train_log_fh
        fh.writelines(file_log_str + '\n')

        # write log
        log_str = '{:s} epoch_batch: {:d}_{:d} | loss: {:.4f}  | meanIU: {:.4f} | pixelAccuracy: {:.4f} | meanAccuracy: {:.4f} | classAccuracy: {:.4f} | meanIU0: {:.4f} | meanIU1: {:.4f}'.format(
                        phase, epoch, num, loss, mean_iu, pixel_accuracy, mean_accuracy, class_accuracy, mean_iu0, mean_iu1)
        self._logger.info(log_str)

        # write tensorboard
        self.addScalar(phase+'_loss', loss, step)
        self.addScalar(phase+'_mean_iu', mean_iu, step)
        self.addScalar(phase+'_pixel_accuracy', pixel_accuracy, step)
        self.addScalar(phase+'_mean_accuracy', mean_accuracy, step)
        self.addScalar(phase+'_class_accuracy', class_accuracy, step)

    def recordTest(self, epoch, num, img_path, mean_iu, pixel_accuracy, mean_accuracy, class_accuracy, final_diff, mean_iu0, mean_iu1):
        log_str = "%s\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t" % (
                    img_path, mean_iu, pixel_accuracy, mean_accuracy, class_accuracy, final_diff, mean_iu0, mean_iu1)
        self._test_log_fh.writelines(log_str + '\n')
        self._logger.info(f'{epoch}_{num}: ', log_str)

    def summary(self, mean_iu: float, pixel_accuracy: float, mean_accuracy: float, class_accuracy: float, final_diff_all: float, mean_iu0: float, mean_iu1: float):
        log_str = "meanIU:%.4f\tpixelAccuracy:%.4f\tmeanAccuracy:%.4f\tclassAccuracy:%.4f\tFinalDifferenceMean:%.4f\tmeanIU0:%.4f\tmeanIU1:%.4f\t" % (mean_iu, pixel_accuracy, mean_accuracy, class_accuracy, final_diff_all, mean_iu0, mean_iu1)
        self._logger.info(log_str)
        self._test_log_fh.writelines(log_str + '\n')

    def saveImg(self, img: np.ndarray, name: str):
        imgs_dir = os.path.join(self._path, 'imgs')
        if not os.path.exists(imgs_dir):
            os.mkdir(imgs_dir)
        cv2.imwrite(os.path.join(imgs_dir, name), img)

    def saveModel(self, model, epoch: int):
        models_dir = os.path.join(self._path, 'models')
        if not os.path.exists(models_dir):
            os.mkdir(models_dir)
        torch.save(model.state_dict(), 'epoch_'+ str(epoch) + '.pth')

    def close(self):
        self._visual.close()
        self._train_log_fh.close()
        self._test_log_fh.close()


from abc import ABC
import datetime
import logging
import sqlite3
from typing import Optional

import pydantic

from kinobot.exceptions import KinoException

logger = logging.getLogger(__name__)

MIN_BYTES = None

class MissingPermission(KinoException):
    pass

class TicketLog(pydantic.BaseModel):
    ticket_id: int
    request_id: str
    added: datetime.datetime

class Ticket(pydantic.BaseModel):
    id: int
    user_id: str
    added: datetime.datetime
    summary: Optional[str] = None
    log: Optional[TicketLog] = None
    expires_in: datetime.timedelta = datetime.timedelta(days=90)

class User(ABC):
    def __init__(self, user_id):
        self.user_id = user_id

    def is_curator(self):
        return False

    def tickets(self):
        raise NotImplementedError

    def available_tickets(self):
        raise NotImplementedError

    def used_tickets(self):
        raise NotImplementedError

    def append_ticket(self, id=None, summary=None):
        raise NotImplementedError

    def log_ticket(self, ticket_id, request_id):
        raise NotImplementedError

    def delete_tickets(self, count=1):
        raise NotImplementedError

class UserTest(User):
    def __init__(self, user_id, tickets=None, tickets_log=None):
        self.user_id = str(user_id)
        self._tickets = tickets or []
        self._tickets_log = tickets_log or []

    def tickets(self):
        return self._tickets

    def available_tickets(self):
        ticket_log_ids = [tl.ticket_id for tl in self._tickets_log]
        return [ticket for ticket in self._tickets if ticket.id not in ticket_log_ids]

    def used_tickets(self):
        ticket_log_ids = [tl.ticket_id for tl in self._tickets_log]
        return [ticket for ticket in self._tickets if ticket.id in ticket_log_ids]

    def append_ticket(
        self, id=None, summary=None, expires_in=datetime.timedelta(days=90)
    ):
        ticket = Ticket(
            id=id or 123,
            user_id=self.user_id,
            added=datetime.datetime.now(),
            summary=summary,
            expires_in=expires_in,
        )
        self._tickets.append(ticket)

    def log_ticket(self, ticket_id, request_id):
        ticket_log = TicketLog(
            ticket_id=ticket_id, request_id=request_id, added=datetime.datetime.now()
        )
        self._tickets_log.append(ticket_log)

    def delete_tickets(self, count=1):
        pass

class UserDB(User):
    def __init__(self, user_id, db_path):
        self._conn = sqlite3.connect(db_path)
        self._conn.set_trace_callback(logger.debug)
        self._conn.row_factory = sqlite3.Row
        self.user_id = str(user_id)

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self._conn.close()

    def expired_tickets(self):
        sql = (
            "select * from verification_ticket left join verification_ticket_log on verification_ticket.id "
            "= verification_ticket_log.ticket_id where verification_ticket.user_id=? "
            "and datetime(verification_ticket.added, '+' || verification_ticket.days_expires_in || ' days') < datetime('now')"
        )
        result = [
            dict(row) for row in self._conn.execute(sql, (self.user_id,)).fetchall()
        ]

        tickets = []
        for item in result:
            if item["ticket_id"] is not None:
                log = TicketLog(
                    ticket_id=item["ticket_id"],
                    request_id=item["request_id"],
                    added=item["added"],
                )
            else:
                log = None

            tickets.append(
                Ticket(
                    id=item["id"],
                    user_id=self.user_id,
                    added=item["added"],
                    summary=item["summary"],
                    expires_in=datetime.timedelta(days=item["days_expires_in"]),
                    log=log,
                )
            )

        return tickets

    def tickets(self, include_expired=False):
        if include_expired:
            sql = (
                "select * from verification_ticket left join verification_ticket_log on verification_ticket.id "
                "= verification_ticket_log.ticket_id where verification_ticket.user_id=?"
            )
        else:
            sql = (
                "select * from verification_ticket left join verification_ticket_log on verification_ticket.id "
                "= verification_ticket_log.ticket_id where verification_ticket.user_id=? "
                "and datetime(verification_ticket.added, '+' || verification_ticket.days_expires_in || ' days') >= datetime('now')"
            )
        result = [
            dict(row) for row in self._conn.execute(sql, (self.user_id,)).fetchall()
        ]

        tickets = []
        for item in result:
            if item["ticket_id"] is not None:
                log = TicketLog(
                    ticket_id=item["ticket_id"],
                    request_id=item["request_id"],
                    added=item["added"],
                )
            else:
                log = None

            tickets.append(
                Ticket(
                    id=item["id"],
                    user_id=self.user_id,
                    added=item["added"],
                    summary=item["summary"],
                    expires_in=datetime.timedelta(days=item["days_expires_in"]),
                    log=log,
                )
            )

        return tickets

    def available_tickets(self):
        return [ticket for ticket in self.tickets() if ticket.log is None]

    def used_tickets(self):
        return [ticket for ticket in self.tickets(include_expired=True) if ticket.log]

    def append_ticket(
        self, id=None, summary=None, expires_in=datetime.timedelta(days=90)
    ):
        self._conn.execute(
            "insert into verification_ticket (user_id,summary,days_expires_in) values (?,?,?)",
            (self.user_id, summary, expires_in.days),
        )
        self._conn.commit()

    def delete_tickets(self, count=1):
        deleted = 0
        for ticket in self.available_tickets():
            self._conn.execute(
                "delete from verification_ticket where id=?", (ticket.id,)
            )
            self._conn.commit()
            deleted += 1
            if deleted >= count:
                break

        logger.debug("Deleted %d tickets", deleted)

    def log_ticket(self, request_id):
        available_tickets = self.available_tickets()
        if not available_tickets:
            raise MissingPermission(
                "You don't have any available tickets to verify this request."
            )

        ticket = available_tickets[0]
        logger.debug("Using %s", ticket)

        self._conn.execute(
            "insert into verification_ticket_log (ticket_id,request_id) values (?,?)",
            (ticket.id, request_id),
        )
        self._conn.commit()

        return ticket


from sklearn.model_selection import ParameterGrid
from copy import deepcopy
from omegaconf import OmegaConf

import concurrent.futures
import os
from pathlib import Path
from . import BaseSearch
import src.utils.hparam_search_utils as hparam_search_utils
import src.utils.hydra_ad_hoc as hydra_ad_hoc
import src.utils.hydra_custom_resolvers as hydra_custom_resolvers
import src.utils.general as utils

log = utils.get_logger(__name__)

class GridSearch(BaseSearch):
    def __init__(
            self,
            parent_run_name,
            parent_run_idx,
            run_name_str,
            run_name_vars,
            scripts,
            search_space,
            max_workers,
            **kwargs,
    ):
        """
        Grid Search
        Parameters
        ----------
        search_space : should be defined in this format https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.ParameterGrid.html
        max_workers : the maximum number of runs supported in parallel
        """
        super().__init__()

        self.parent_run_name = parent_run_name
        self.parent_run_idx = parent_run_idx
        self.run_name_str = run_name_str
        self.run_name_vars = run_name_vars

        self.max_workers = max_workers

        self.param_configs = ParameterGrid(
            search_space if isinstance(search_space, dict) else OmegaConf.to_object(search_space)
        )

        self.scripts = scripts
        self.hydra = kwargs.get("hydra_dir", "hparam_search")
        self.hydra_log_subdir = kwargs.get("hydra_log_subdir", "hparam_search")

        assert len(self.scripts) == 2, "You should pass both an evalution.py and evaluation_from_file.py scripts"

        self.script_1 = self.scripts[0].script
        script_kwargs = self.scripts[0].script_kwargs
        if script_kwargs is not None:
            self.script_1_kwargs = script_kwargs if isinstance(script_kwargs, dict) else OmegaConf.to_object(
                script_kwargs)
        else:
            self.script_1_kwargs = None
        self.tag_1 = self.scripts[0].tag

        self.script_1_successful_runs_configs = hparam_search_utils.read_configs(self.parent_run_name,
                                                                                self.parent_run_idx,
                                                                                tag=self.tag_1)
        # exit()
        self.script_2 = self.scripts[1].script
        self.script_2_kwargs = self.scripts[1].script_kwargs
        self.tag_2 = self.scripts[1].tag

        self.script_2_successful_runs_configs = hparam_search_utils.read_configs(self.parent_run_name,
                                                                                self.parent_run_idx,
                                                                                tag=self.tag_2)

        self.both_scripts_unsuccessful_param_configs = self.generate_run_configs(self.param_configs,
                                                                                self.script_1_successful_runs_configs,
                                                                                tag=self.tag_1)

        script_2_unsuccessful_param_configs = self.generate_run_configs(self.param_configs,
                                                                        self.script_2_successful_runs_configs,
                                                                        tag=self.tag_1) #used tag_1 because the eval does not create a new folder

        # removing unsuccessful evaluation configs that are going to be run after training with self.both_scripts_unsuccessful_param_configs
        self.script_2_unsuccessful_param_configs = [x for x in script_2_unsuccessful_param_configs if
                                                    x not in self.both_scripts_unsuccessful_param_configs]

        self.results = []

    def successful_config_exists(self, prev_successful_run_configs, parameters_to_comapre_keys,
                                 parameters_to_comapre_values, tag):
        for idx, config in enumerate(prev_successful_run_configs["config"]):
            if hydra_ad_hoc.compare_configs(config, parameters_to_comapre_keys, parameters_to_comapre_values, tag):
                return True, prev_successful_run_configs["run_path"][idx]

        return False, None

    def generate_run_configs(self, param_configs, prev_successful_run_configs, tag):

        log = utils.get_logger(__name__)
        configs = []

        for idx, config in enumerate(param_configs):
            search_params_keys = list(config.keys())
            search_params_values = list(config.values())
            str_params = [f"{k}={v}" for k, v in config.items()]

            successful_config_exists, optional_path = self.successful_config_exists(
                prev_successful_run_configs=prev_successful_run_configs
                , parameters_to_comapre_keys=search_params_keys
                , parameters_to_comapre_values=search_params_values
                , tag=tag)
            if successful_config_exists:
                log.info(
                    f"A successful Run for the following search arguments was found, resulting in this combination getting skipped:\njob:{tag}, search_params:{str_params}\npath to the successful run: {optional_path}")
            else:
                # if a successful config is not found and the tag is not eval, then we can safely assume that the config should be submitted
                # to be rerun.
                log.info(
                    f"No successful training exists for the following search parameters. This search combination will be queued for re-execution.\nfailed search params:{str_params}")
                configs.append(config)

        return configs

    def run_search(self, launcher):
        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            # submit jobs which require both training and evaluation in the following for loop
            # and jobs that only have unfinished evaluation in the next for loop.
            last_idx = 0
            for idx, config in enumerate(self.both_scripts_unsuccessful_param_configs):
                config_keys = list(config.keys())
                cfg = deepcopy(self.script_1_kwargs) if self.script_1_kwargs is not None else dict()
                config["hydra"] = self.hydra
                config["+hydra_log_subdir"] = self.hydra_log_subdir
                config["+parent_run_name"] = os.path.join(self.parent_run_name, str(self.parent_run_idx))
                config["run_name"] = hparam_search_utils.get_trial_name(
                    self.parent_run_name, self.parent_run_idx, idx, self.run_name_str, self.run_name_vars, config
                ) + '_' + self.tag_1

                cfg.update(config)

                eval_cfg = deepcopy(self.script_2_kwargs) if self.script_2_kwargs is not None else dict()
                eval_config = dict()
                for key in config_keys:
                    if key.startswith("model"):
                        eval_config[key.replace("model.", "++model.hparams_overrides.")] = config.pop(key)

                # eval_config["hydra"] = self.hydra
                # eval_config["+hydra_log_subdir"] = self.hydra_log_subdir
                eval_config["+parent_run_name"] = os.path.join(self.parent_run_name, str(self.parent_run_idx))

                # this field is used with hydra custom resolver to retrieve the path of best ckpt
                # run_name is used with wandb, and should not coincide with another run's name.
                # eval_config["run_name"] = config["run_name"].strip("_script_1") + "_script_2"

                # exp_dir_path = os.path.join(os.getcwd(), config["+parent_run_name"], config["run_name"]) # absolute path to 0/1/2
                log_folder = []
                for f in os.getcwd().split('/'):
                    log_folder.append(f)
                    if f == 'logs':
                        break

                exp_dir_path = os.path.join('/'.join(log_folder), config['hydra'], config['+parent_run_name'], config['run_name'])
                print(f"exp_dir_path {exp_dir_path}")
                eval_config["--exp_dir"] = exp_dir_path

                eval_cfg.update(eval_config)

                self.results.append(
                    executor.submit(launcher.run_trial, idx, self.script_1, cfg, self.script_2, eval_cfg))
                last_idx = idx

            for idx_, config in enumerate(self.script_2_unsuccessful_param_configs):
                # note the _ appended to idx, because the idx of runs should not coincide, so unsuccessful evals should be written
                # to new directories, so idx should properly be adjusted (i.e. the correct index is last_idx+idx_)
                eval_cfg = deepcopy(self.script_2_kwargs) if self.script_2_kwargs is not None else dict()
                eval_config = deepcopy(config)
                config_keys = list(config.keys())
                # eval_config["hydra"] = self.hydra
                # eval_config["+hydra_log_subdir"] = self.hydra_log_subdir
                eval_config["+parent_run_name"] = os.path.join(self.parent_run_name, str(self.parent_run_idx))

                # run_name is used with wandb, and should not coincide with another run's name.
                eval_config["--exp_dir"] = hparam_search_utils.get_trial_name(
                    self.parent_run_name, self.parent_run_idx, last_idx + idx_, self.run_name_str,
                    self.run_name_vars, config
                )

                # this should be after get_trial_name because the following will pop parameters required for getting
                # the name, i.e. model.nn_params.d_embedding
                # for key in config_keys:
                #     if "model" in key and "model.checkpoint" not in key:  # chekpoint should be passed as an override, o.w.
                #         # interpolation resolve errors will be raised.
                #         eval_config[key.replace("model.", "++model.hparams_overrides.")] = eval_config.pop(key)

                # exp_dir_path = os.path.join('/'.join(log_folder), config['hydra'], config['+parent_run_name'],
                #                             config['run_name'])
                eval_cfg.update(eval_config)

                # script_2 (evaluation) is passed as script_1 to the launcher, and script_2 is None by default.
                self.results.append(executor.submit(launcher.run_trial, last_idx + idx_, self.script_2, eval_cfg))

            return self.results


from parse import parse

def day4():
    def loadData():
        entries = []

        with open('2018/data/day4.data', 'rt') as data:
            for line in data:
                entries.append(line.strip())

        entries.sort()

        world = {}

        for line in entries:
            # Starts Shift
            data = parse("[{:d}-{:d}-{:d} {:d}:{:d}] Guard #{:d} begins shift", line)
            if not data is None:
                currentGuard = data[5]
                if not currentGuard in world:
                    world[currentGuard] = [0]*60
                currentGuard = world[currentGuard]
                continue

            # Goes to Sleep
            data = parse("[{:d}-{:d}-{:d} {:d}:{:d}] falls asleep", line)
            if not data is None:
                sleepStart = data[4]
                continue

            # Goes to Sleep
            data = parse("[{:d}-{:d}-{:d} {:d}:{:d}] wakes up", line)
            if not data is None:
                sleepEnd = data[4]
                for i in range(sleepStart, sleepEnd):
                    currentGuard[i] += 1
                continue

        return world

    def part1(input):
        max = 0
        guard = 0

        for k in input:
            sleep = sum(input[k])
            if sleep > max:
                guard = k
                max = sleep

        max = 0
        hour = 0
        w = input[guard]
        for h in range(0, 60):
            if w[h] > max:
                max = w[h]
                hour = h

        answer = guard * hour

        print("Answer part 1 is", answer)

    def part2(input):
        max  = 0
        hour = 0
        guard= 0

        for g in input:
            w = input[g]
            for h in range(0, 60):
                if w[h] > max:
                    max  = w[h]
                    guard= g
                    hour = h

        answer = guard * hour

        print("Answer part 2 is", answer)

    print("")
    print("*******************************")
    print("* Advent of Code 2018 - Day 4 *")
    print("*******************************")
    print("")

    input = loadData()
    part1(input)
    part2(input)

    print("")


#!/usr/bin/env python3

import numpy as np
from collections import deque
import matplotlib.pyplot as plt
import time
import os

from unityagents import UnityEnvironment
import torch
from ddpg_agent import Agent

# Set to True if you want to (re)run the training or False to just watch the trained agent in action
train_now = False

# Initialize Unity environment with 1 or 20 agents
#env = UnityEnvironment(file_name=os.path.join(os.getcwd(),'Reacher_1_Linux/Reacher.x86_64'))
env = UnityEnvironment(file_name=os.path.join(os.getcwd(),'Reacher_20_Linux/Reacher.x86_64'))

# Get the default brain
brain_name = env.brain_names[0]
brain = env.brains[brain_name]

# Reset the environment
env_info = env.reset(train_mode=True)[brain_name]

# Number of agents in the environment
num_agents = len(env_info.agents)
print('Number of agents:', num_agents)

# Size of each action
action_size = brain.vector_action_space_size
print('Size of each action:', action_size)

# Examine the state space
states = env_info.vector_observations
state_size = states.shape[1]
print('There are {} agents. Each observes a state with length: {}'.format(states.shape[0], state_size))
print('The state for the first agent looks like:', states[0])

# Create an agent that controls the agent in the environment
agent = Agent(state_size=state_size, action_size=action_size, random_seed=0)

# Train the agent with DDPG
if train_now:
    n_episodes=200
    average_len=100
    print_every=10
    scores_deque = deque(maxlen=average_len)
    scores = []
    solved = False
    average_score_max = 0
    # Train for n_episodes
    for i_episode in range(1, n_episodes+1):
        env_info = env.reset(train_mode=True)[brain_name]
        states = env_info.vector_observations
        agent.reset()
        score = 0
        actions = [np.array([0.0,0.0,0.0,0.0])]*num_agents
        # Train until environment ends the episode
        while True:
            for env_agent_idx in range(num_agents):
                # Let deep learning agent act based on states
                actions[env_agent_idx] = agent.act(states[env_agent_idx])
            env_info = env.step(actions)[brain_name]
            next_states = env_info.vector_observations
            rewards = env_info.rewards
            dones = env_info.local_done
            for env_agent_idx in range(num_agents):
                # Save to replay buffer
                agent.memorize(states[env_agent_idx], actions[env_agent_idx], \
                           rewards[env_agent_idx], next_states[env_agent_idx], \
                           dones[env_agent_idx])
            # Learn
            agent.step()
            states = next_states
            score += np.sum(rewards)/len(rewards)
            if np.any(dones):
                break
        # Check and track scores
        scores_deque.append(score)
        scores.append(score)
        average_score = np.mean(scores_deque)
        print('\rEpisode {}\tAverage Score: {:.2f}\tScore: {:.2f}'.format(i_episode, average_score, score), end="")
        if i_episode % print_every == 0:
            print('\rEpisode {}\tAverage Score: {:.2f}'.format(i_episode, average_score))
        # Save coefficients to file if environment is solved with current network coefficients
        if average_score >= 30:
            if not solved:
                solved = True
                print('Environment solved after {} episodes.'.format(i_episode))
            if average_score > average_score_max:
                average_score_max = average_score
                torch.save(agent.actor_local.state_dict(), 'checkpoint_actor.pth')
                torch.save(agent.critic_local.state_dict(), 'checkpoint_critic.pth')

    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.plot(np.arange(1, len(scores)+1), scores)
    plt.ylabel('Score')
    plt.xlabel('Episode #')
    plt.minorticks_on()
    plt.grid(b=True, which='major', color='#888888', linestyle='-', alpha=0.5)
    plt.grid(b=True, which='minor', color='#999999', linestyle='-', alpha=0.2)
    plt.savefig('training_scores.png')
    plt.show()

# Now watch a trained agent in action

agent.actor_local.load_state_dict(torch.load('checkpoint_actor.pth'))
agent.critic_local.load_state_dict(torch.load('checkpoint_critic.pth'))
agent.reset()

env_info = env.reset(train_mode=False)[brain_name]
states = env_info.vector_observations
actions = [np.array([0.0,0.0,0.0,0.0])]*num_agents
while True:
    for env_agent_idx in range(num_agents):
        # Let deep learning agent act based on states
        actions[env_agent_idx] = agent.act(states[env_agent_idx])
    env_info = env.step(actions)[brain_name]
    states = env_info.vector_observations
    dones = env_info.local_done
    if np.any(dones):
        break

# Clean up
env.close()


'''Task 1
Files
Write a script that creates a new output file called myfile.txt and writes the string "Hello file world!" in it.
Then write another script that opens myfile.txt, and reads and prints its contents.
Run your two scripts from the system command line.
Does the new file show up in the directory where you ran your scripts?
What if you add a different directory path to the filename passed to open?
Note: file write methods do not add newline characters to your strings; add an explicit ‘\n’
at the end of the string if you want to fully terminate the line in the file. '''

import json
with open('my_file.txt', 'w') as my_file:
    my_file.write('Hello file world!')

with open('my_file.txt') as my_file:
    print(my_file.read())

'''Task 2
Extend Phonebook application
Functionality of Phonebook application:
Add new entries
Search by first name
Search by last name
Search by full name
Search by telephone number
Search by city or state
Delete a record for a given telephone number
Update a record for a given telephone number
An option to exit the program
The first argument to the application should be the name of the phonebook.
Application should load JSON data, if it is present in the folder with application, else raise an error.
After the user exits, all data should be saved to loaded JSON.
'''
import json

def read_file(file_name):
    with open(file_name, 'r') as file_object:
        try:
            load_file = json.load(file_object)
        except json.decoder.JSONDecodeError:
            load_file = []
        return load_file

def rewrite_file(file_name, new_content):
    with open(file_name, 'w') as file_object:
        json.dump(new_content, file_object)

def print_contact(contact):
    print('_' * 30)
    for k, v in contact.items():
        print('l', k, ':', v )

def print_contact_list(contact_list):
    for contact in contact_list:
        print_contact(contact)

def print_file(file_name):
    load_file = read_file(file_name)
    for entry in load_file:
        print_contact(entry)

def input_contact():
    new_contact = {
        'name': input('Имя ').lower(),
        'last_name': input('Фамилия ').lower(),
        'phone': input('Телефон ').lower(),
        'country': input('Страна ').lower(),
        'city': input('Город ').lower()
    }
    return new_contact

def add_contact(file_name, new_contact):
    load_file = read_file(file_name)
    load_file.append(new_contact)
    rewrite_file(file_name, load_file)

def input_search_parameter():
    search_parameter = ''
    while search_parameter not in ('n','l','p','co','ci'):
        search_parameter = (input('Поиск контактапо имени (n), фамилии(1), телефону(p), стране (со), городу(ci), '
                                  'введите параметр поиска ')).lower()
        return search_parameter

def input_search_value():
    search_value = (input('Введите значение: ')).lower()
    return search_value

def dict_parameters():
    parameters = {
        'n': 'name',
        'l': 'last_name',
        'p': 'phone',
        'co': 'country',
        'ci': 'city'
    }
    return parameters

def make_search_contact_list(file_name, search_parameter='n', search_value=''):

    parameters = dict_parameters()
    load_file = read_file(file_name)
    field_name = parameters[search_parameter]
    return list(filter( lambda contact: contact[field_name] == [search_value]))
    search_contact_list = [contact for contact in load_file if contact[field_name] == search_value]
    return search_contact_list

def delete_contacts(file_name, deleted_contact_list):
    load_file = read_file(file_name)
    for contact in deleted_contact_list:
        load_file.remove(contact)
    rewrite_file(file_name, load_file)

def change_contacts(change_contact_list):
    for contact in change_contact_list:
        new_contact = input_contact()
        for k in new_contact.keys():
            if new_contact[k]:
                contact[k] = new_contact[k]
    return change_contact_list

if __name__ == "__main__":
    phone_book = "phone_book.json"
    action = input("Выберите действие для работы с книгой\n"
                   "1. Показать всю телефонную книгу\n2.Добавить контакт\n"
                   "3. Найти Контакт\n 4.Удалить контакт\n"
                   "5. Обновить контакт по номеру телефона\n6.Выити из программы\n")
    if action == '1':
        print_file(phone_book)
    elif action == '2':
        add_contact(phone_book, input_contact())
    elif action == '3':
        found_contacts = make_search_contact_list(phone_book, input_search_parameter(),input_search_value())
        print_contact_list(found_contacts)
    elif action == '4':
        contacts_by_phone = make_search_contact_list(phone_book,'p',input_search_value())
        delete_contacts(phone_book,contacts_by_phone)
    elif action == '5':
        contacts_by_phone = make_search_contact_list(phone_book, 'p', input_search_value())
        print_contact_list(contacts_by_phone)
        delete_contacts(phone_book, contacts_by_phone)
        for contact in change_contacts(contacts_by_phone):
            add_contact(phone_book, contact)
    else: print('Выход')


from transformers import AutoTokenizer, AutoModel

import api

def transformer_from_pretrained(model: str):
    tokenizer = AutoTokenizer.from_pretrained(model)
    embedding = AutoModel.from_pretrained(model)

    return embedding, tokenizer

DIRECTORY = 'C:/Users/bergj/Documents/Geroge Mason/Courses/2020- Fall/CS 695/Proj3'

corpus = api.data.NERCorpus(
        train_file=f'{DIRECTORY}/data/train.txt',
        dev_file=f'{DIRECTORY}/data/dev.txt',
        test_file=f'{DIRECTORY}/data/test.txt'
    )

train_sent_list, train_tags = corpus.train_data()

emb, tok = transformer_from_pretrained('dmis-lab/biobert-v1.1')

train_sent_list = [' '.join(tok for tok in train_sent) for train_sent in train_sent_list]

train_sent_list = tok(train_sent_list[:5], return_tensors="pt", padding=True)

pt_outputs = emb(**train_sent_list)

print(pt_outputs[0])
print(pt_outputs[1])


import matplotlib.pyplot as plt
import pickle
import os
import numpy as np

sourceFileDir = os.path.dirname(os.path.abspath(__file__))
os.chdir(sourceFileDir)

simulation_dir = 'simulation_data'

path = os.path.join(simulation_dir, 'data_of_collisions_1000')

with open(path, 'rb') as fp:
    dic = pickle.load(fp)

for key,values in dic.items():
    print(key, 'number of wins = ', sum(1 for i in values if i < 3))
    runs = len(values)

# del dic[(50,50)], dic[(50,100)], dic[(50,125)], dic[(75,125)], dic[(100,50)], dic[(100,75)], dic[(125,50)], dic[(125,75)], dic[(125,100)], dic[(75,50)], dic[(50,75)]

fig, ax = plt.subplots()
ax.set_title('Boxplot of simulation results with ' + str(runs) + ' runs')
ax.boxplot(dic.values(), patch_artist=True)
ax.set_xticklabels(dic.keys())
ax.yaxis.grid(True)
ax.set_xlabel('Different periods $(p_F, p_S)$')
ax.set_ylabel('Number of collisions until win')
plt.show()


import numpy as np
from scipy.io import wavfile
import librosa
import librosa.display
import matplotlib.pyplot as plt
import math
import base64

def calculate_score(f):
    signal , sr = librosa.load(f)

    signal = signal[:5*sr]
    #print(len(signal))
    mfcc = librosa.feature.mfcc(y= signal , n_mfcc = 13 , sr = sr)
    print(mfcc.shape)
    #avg_r = mfcc.mean(axis=1)
    #print(avg_r.shape)
    #score = avg_r.mean(axis = 0)
    return mfcc

def calculate_new_sample(name,scores,*args):
    if len(args) == 0 : return
    print(args)
    new_avg = []
    for item in args:
        print(item)
        new_avg.append(calculate_score(item))
    #scores[name] = sum(new_avg) / len(new_avg)
    scores[name] = new_avg

def compare(f,scores):
    new_s  = calculate_score(f)
    res = {}
    for i in scores.keys():
        means = []
        for elem in scores[i]:
            means.append( np.mean( np.mean(np.absolute(elem - new_s),axis=1), axis = 0 ) )
        if len(means) == 0:
            res[i] = 2**16
        else:
            res[i] = min(means)
        #res[i] = np.mean(np.absolute(scores[i] - new_s))
    return {k : v for k,v in sorted(res.items() , key= lambda item : item[1])}


import os
import mutagen
import base64
from watchdog.observers import Observer
from tqdm import tqdm
from django.core.exceptions import ObjectDoesNotExist
from core.models import Song, Album, Artist, Folder
from library_builder.fshandler import FSHandler
from library_builder.util import is_audio_file, md5

def scan_directory(dirname, silent=False):
	scanned_songs = 0
	scanned_albums = 0
	scanned_artists = 0
	scanned_folders = 0

	def do_walk(root, subdirs, files, pbar=None):
		scanned_songs = 0
		scanned_albums = 0
		scanned_artists = 0
		scanned_folders = 0

		folder = None

		for file in files:
			if is_audio_file(file):
				# Get folder for the song
				try:
					folder = Folder.objects.get(path=root)
				except ObjectDoesNotExist:
					folder = Folder(path=root)
					folder.save()
					scanned_folders += 1

				filepath = os.path.join(root, file)
				metadata_file = mutagen.File(filepath)

				metadata = {}
				for key in Song.metadata_keys():
					if key in metadata_file:
						metadata[key] = str(metadata_file.get(key))

				# Get artist for the song
				if 'TPE1' in metadata and len(metadata['TPE1']) != 0:
					try:
						artist = Artist.objects.get(
							name__iexact=metadata['TPE1'])
					except ObjectDoesNotExist:
						artist = Artist(name=metadata['TPE1'])
						artist.save()
						scanned_artists += 1
				else:
					artist = Artist.objects.get(pk=0)

				# Get album for the song
				if 'TALB' in metadata:
					album_name = metadata['TALB']
				else:
					album_name = '<Unknown Album>'

				try:
					album = Album.objects.get(
						name__iexact=album_name,
						artist__name__iexact=artist.name
					)
				except ObjectDoesNotExist:
					album = Album(
						name=album_name,
						artist=artist
					)
					album.save()
					scanned_albums += 1

				# Get album art
				if len(album.art) == 0 and 'APIC:' in metadata_file:
					apic = metadata_file['APIC:']
					album.art = base64.b64encode(apic.data).decode('utf-8')
					album.save()

				song, created = Song.objects.update_or_create(
					title=metadata.get('TIT2') or file,
					path=filepath,
					duration=metadata_file.info.length,
					start_time=0.0,
					end_time=metadata_file.info.length - 0.0,
					bitrate=metadata_file.info.bitrate,
					sample_rate=metadata_file.info.sample_rate,
					md5=md5(filepath),
					artist=artist,
					album=album,
					folder=folder,
					audio_format=file.split('.')[1].lower(),
					mime_type=metadata_file.mime[0],
					**metadata
				)
				scanned_songs += 1

				if pbar:
					pbar.update(1)

		return (scanned_songs, scanned_albums, scanned_artists, scanned_folders)

	if not silent:
		num_tracks = 0

		print("Scanning library...")

		for root, subdirs, files in os.walk(os.path.abspath(dirname)):
			for file in files:
				if is_audio_file(file):
					num_tracks += 1

		with tqdm(total=num_tracks, unit="files") as pbar:
			for root, subdirs, files in os.walk(os.path.abspath(dirname)):
				(_songs, _albums, _artists, _folders) = do_walk(root, subdirs, files, pbar=pbar)
				scanned_songs += _songs
				scanned_albums += _albums
				scanned_artists += _artists
				scanned_folders += _folders

		print('Created {} songs, {} albums, {} artists, and {} folders'
                    .format(scanned_songs, scanned_albums, scanned_artists, scanned_folders)
        )
		print()
	else:
		for root, subdirs, files in os.walk(os.path.abspath(dirname)):
			do_walk(root, subdirs, files)


# This is from Geeks for Geeks.Question link at last
# You are given a sorted array a of length n.
# For each i(0<=i<=n-1), you have to make all the elements of the array from index 0 till i equal, using minimum number of operations.
# In one operation you either increase or decrease the array element by 1.
# You have to return a list which contains the minimum number of operations for each i, to accomplish the above task.
# Note:
# 1. 0-based indexing.
# 2. For each index, you need to consider the same array which was given to you at the start.
from typing import List

class Solution:
    def optimalArray(self, n : int, a : List[int]) -> List[int]:
        # code here
        res=[0]
        for i in range (1,n):
            res.append(res[0]+res[i-1]+abs(a[i]-a[i//2]))
        return res

#{
 # Driver Code Starts
class IntArray:
    def __init__(self) -> None:
        pass
    def Input(self,n):
        arr=[int(i) for i in input().strip().split()]#array input
        return arr
    def Print(self,arr):
        for i in arr:
            print(i,end=" ")
        print()

if __name__=="__main__":
    t = int(input())
    for _ in range(t):

        n = int(input())

        a=IntArray().Input(n)

        obj = Solution()
        res = obj.optimalArray(n, a)

        IntArray().Print(res)

# } Driver Code Ends
# Question link
# https://practice.geeksforgeeks.org/problems/d4aeef538e6dd3280dda5f8ed7964727fdc7075f/1


# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response, HttpResponse, Http404, redirect
from django.template.context_processors import csrf
from django.utils.encoding import smart_str
from ftrend.additions import upload_file
from catalog.models import Color, Category
from cart.models import CartProduct
from models import Settings

def video_upload(request):
    if request.method == 'POST' and request.user.is_authenticated():
        f = request.FILES['file']
        path = "/static/uploads/"
        url = upload_file(f, path)
        return HttpResponse(url)
    return HttpResponse("no")

def size_colors(request, data):
    if request.user.is_authenticated():
        selected_colors = data.split(",")
        colors = []
        for color in Color.objects.all():
            if str(color.id) in selected_colors:
                color.selected = 'selected="selected"'
            colors.append(color)
        return render_to_response("size_colors.html", {'colors': colors})
    return HttpResponse("False")

def sort_list():
    mass_object = []
    roots = Category.objects.filter(parent=None)

    def rec_list(obj):
        obj.title = smart_str("— "*obj.step) + smart_str(obj.title)
        mass_object.append(obj)
        children = Category.objects.filter(parent=obj)

        for child in children:
            rec_list(child)

    for root in roots:
        rec_list(root)

    return mass_object

def tree_categories(request, id=-1):
    if request.user.is_authenticated():
        return render_to_response("tree_categories.html", {
            'categories': sort_list(),
        })
    raise Http404

def settings(request):
    if request.user.is_authenticated():
        model = Settings.objects.get(id=1)
        args = {}
        if request.POST:
            model.title = request.POST.get('title')
            model.email = request.POST.get('email')
            model.description = request.POST.get('description')
            model.phone_home = request.POST.get('phone')
            model.contacts = request.POST.get('contacts')
            model.delivery = request.POST.get('delivery')
            model.pay = request.POST.get('pay')
            model.recovery = request.POST.get('recovery')
            model.terms = request.POST.get('terms')
            model.footer_link = request.POST.get('footer_link')
            model.save()
            args['message'] = "yes"
        args.update(csrf(request))
        args['model'] = model
        return render_to_response("set.html", args)
    else:
        return redirect('/admin/')

def get_products_list(request):
    mass_id = []

    for id in request.GET.get("mass_id", "").split(","):
        if id != "":
            mass_id.append(int(id))

    sum_all = 0

    products = []
    for product in CartProduct.objects.filter(id__in=mass_id):
        product.sum = product.price_order * product.count
        sum_all += product.price_order * product.count
        products.append(product)

    return render_to_response("get_products_list.html", {'products': products, 'sum': sum_all})