from __future__ import print_function

import numpy as np
import cv2
import subprocess
import itertools
from multiprocessing import Pool

import sys
import os
import time

import numpy as np
import theano
import theano.tensor as T

import lasagne

f = subprocess.check_output(["ls"]).split()
files = []
#make list of files that contain ellipse data
for i in f:
    if "ellipseList.txt" in i:
        files.append(i)
print(files)

class Image:
	def __init__(self, filename, window_size):
		self.im = cv2.imread(filename,0)
		#self.im = cv2.resize(self.im,(0,0),fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
		self.mask = []
		self.mask_small = []
		self.windows = []
		self.windows_small = []
		self.scores = []
		self.scores_small = []
		self.cx = []
		self.cy = []
		self.decimation_factor = []
		self.imno = 0
		#self.slide = [-6,-4,-2,0,2,4,6]
		self.slide = [-3,-2,-1,0,1,2,3]
		self.window_size = window_size

	def ellipse(self, ellipse_info):
		ellipse_info = ellipse_info.split(" ")
		axes = [float(ellipse_info[0]),float(ellipse_info[1])]
		decim_fac = int(max(max(axes[0]*2/self.window_size,axes[1]*2/self.window_size),1))
		self.decimation_factor.append(decim_fac)

		#print "best decimation is %.2f and %.2f"%(axes[0]*2/32,axes[1]*2/32)
		theta = float(ellipse_info[2])
		self.cx.append(float(ellipse_info[3]))
		self.cy.append(float(ellipse_info[4]))
		#print "diameter is %0.2f"%(2*max(axes[0],axes[1]))
		y,x = np.ogrid[0:self.im.shape[0],0:self.im.shape[1]]
		mask = np.power(((x-self.cx[-1])*np.cos(theta) + (y-self.cy[-1])*np.sin(theta))/axes[0],2) + np.power(((x-self.cx[-1])*np.sin(theta) - (y-self.cy[-1])*np.cos(theta))/axes[1],2) <= 1
		self.mask.append(mask)
		#self.mask.append(mask[::2,::2])
		#self.cx[-1] /= 2
		#self.cy[-1] /= 2

	def ellipse_decim(self, ellipse_info):
		ellipse_info = ellipse_info.split(" ")
		axes = [float(ellipse_info[0])/2,float(ellipse_info[1])/2]
		print("best decimation is %.2f and %.2f"%(axes[0]*2/32,axes[1]*2/32))
		theta = float(ellipse_info[2])
		self.cx.append(float(ellipse_info[3])/2)
		self.cy.append(float(ellipse_info[4])/2)
		#print "diameter is %0.2f"%(2*max(axes[0],axes[1]))
		y,x = np.ogrid[0:self.im.shape[0],0:self.im.shape[1]]
		mask = np.power(((x-self.cx[-1])*np.cos(theta) + (y-self.cy[-1])*np.sin(theta))/axes[0],2) + np.power(((x-self.cx[-1])*np.sin(theta) - (y-self.cy[-1])*np.cos(theta))/axes[1],2) <= 1
		self.mask.append(mask)

	def get_score(self,mask,cx,cy,x,i,ellipse_size):
		s = self.window_size/2
		flag = False
		flag = flag or cy+x[0]-s < 0
		flag = flag or cx+x[0]-s < 0
		flag = flag or cy+x[1]+s+1 > mask.shape[0]
		flag = flag or cx+x[1]+s+1 > mask.shape[1]
		if flag == True:
			return -1.
		#intersect = np.sum(self.mask[i][cy+x[0]-16:cy+x[0]+17,cx+x[1]-16:cx+x[1]+17]).astype(float)
		#union = ellipse_size - intersect + (32*32)

		intersect = np.sum(mask[cy+x[0]-s:cy+x[0]+s+1,cx+x[1]-s:cx+x[1]+s+1]).astype(float)
		union = ellipse_size - intersect + (4*s*s)
		self.imno += 1

		#CHOOSE THE SCORE YOU WANT
		return np.float32(intersect/union)
		#return intersect/ellipse_size

	def get_random_window(self,image,mask,center):
		s = self.window_size/2
		rand_mask = mask[center[0]-s:center[0]+s+1,center[1]-s:center[1]+s+1]
		if rand_mask.size < (self.window_size**2) or np.sum(rand_mask) > 5:
			return None
		return image[center[0]-s:center[0]+s+1,center[1]-s:center[1]+s+1].astype(np.float32)

	def get_windows(self):
		s = self.window_size/2
		self.image_slides = []
		self.score_slides = []
		for i in xrange(len(self.mask)):
			image = cv2.resize(self.im,(0,0),fx=1./self.decimation_factor[i],fy=1./self.decimation_factor[i],interpolation=cv2.INTER_AREA)
			mask = cv2.resize(self.mask[i].astype(np.uint8),(0,0),fx=1./self.decimation_factor[i],fy=1./self.decimation_factor[i],interpolation=cv2.INTER_AREA).astype(bool)
			mask_size = np.sum(mask)
			cx = int(round(self.cx[i]/self.decimation_factor[i]))
			cy = int(round(self.cy[i]/self.decimation_factor[i]))
			self.score_slides.append(map(lambda x: self.get_score(mask,cx,cy,x,i,mask_size), itertools.product(self.slide,self.slide)))
			self.image_slides.append(map(lambda x: image[cy+x[0]-s:cy+x[0]+s+1,cx+x[1]-s:cx+x[1]+s+1].astype(np.float32), itertools.product(self.slide,self.slide)))

		#generate random images
		self.random_slides = []
		self.random_scores = []
		mask = np.zeros(self.im.shape)
		for i in xrange(len(self.mask)):
			mask = np.maximum(mask, self.mask[i].astype(int))
		mask = mask.astype(bool)
		rand = np.random.rand(self.imno,2)
		rand[:,0] *= self.im.shape[0]
		rand[:,1] *= self.im.shape[1]
		rand = rand.astype(int)
		iterate = 0
		goal = 2*self.imno
		while(self.imno < goal):
			try:
				randy = rand[iterate,0]
				randx = rand[iterate,1]
			except IndexError:
				rand = np.random.rand(self.imno,2)
				rand[:,0] *= self.im.shape[0]
				rand[:,1] *= self.im.shape[1]
				rand = rand.astype(int)
				iterate=0
				continue
			try:
				small = mask[randy-s:randy+s+1,randx-s:randx+s+1]
				#print "shape is %d %d"%(small.shape[0],small.shape[1])
				#print "val is %d"%np.sum(small)
			except IndexError:
				iterate+=1
				continue
			iterate+=1
			if small.size - (self.window_size**2) < 10:
				continue
			elif np.sum(small) > 10:
				continue
			self.random_slides.append(self.im[randy-s:randy+s+1,randx-s:randx+s+1].astype(np.float32))
			self.random_scores.append(np.float32(0))
			self.imno += 1
			#print "Adding random image"
			#print "%d left to go"%(goal-self.imno)

	def get_data(self):
		flatten = lambda l: [item for sublist in l for item in sublist]
		return flatten(self.image_slides)+self.random_slides, flatten(self.score_slides)+self.random_scores

def info(filename):
	with open(filename,"r") as f:
		slides = []
		scores = []
		while(True):
			try:
				imgpath = f.readline().split("\n")[0]+".jpg"
				if imgpath == ".jpg":
					return np.array(slides), np.array(scores)
				#print imgpath
				e = Image(imgpath,32)
				numfaces = f.readline().strip()
				#print numfaces
				print(numfaces)
				for i in xrange(int(numfaces)):
					ellipse_info = f.readline().split("\n")[0]
					#print ellipse_info
					e.ellipse(ellipse_info)
					#plt.imshow(e.im,cmap="gray",alpha=0.5)
					#plt.imshow(e.ellipse(ellipse_info),alpha=0.1,cmap="gray")
					#plt.show()
				e.get_windows()
				ims, im_scores = e.get_data()
				for i in xrange(len(ims)):
					slides.append(ims[i])
					scores.append(im_scores[i])
				#print
				#e.get_windows()
			except ValueError as a:
				#pass
				#    print e
				return
	#return

#info(files[0])
#exit()

pool = Pool(4)
a = np.array(pool.map(info,files[:2]))

images = np.concatenate(a[:,0]).tolist()
scores = np.concatenate(a[:,1]).tolist()

i=0
while(True):
	if i==len(images):
		break
	elif images[i].shape != (33,33):
		del images[i]
		del scores[i]
	else:
		i+=1

images = np.array(images)
scores = np.array(scores)

# images_flat = []
# scores_flat = []

# for i in xrange(len(images)):
# 	assert len(images[i]) == len(scores[i])
# 	for j in xrange(len(images[i])):
# 		print type(scores[i][j])
# 		images_flat.append(images[i][j])
# 		scores_flat.append(scores[i][j])

# images = np.array(images_flat)
# scores = np.array(scores_flat)

images = images[np.where(scores >= 0)]
scores = scores[np.where(scores >= 0)]
#scores_second = np.add(-1,scores)
#scores = np.concatenate((scores[:,np.newaxis],scores_second[:,np.newaxis]),axis=1)

#data = np.stack((images,scores[:,np.newaxis]),axis=1)
#np.random.shuffle(data)
#print(data.shape)

# plt.hist(scores,bins=50)
# plt.show()

# rand_range = (np.random.rand(10)*1000).astype(int)
# for i in xrange(10):
# 	print images[rand_range[i]].shape
# 	plt.imshow(images[rand_range[i]],cmap="gray",interpolation="nearest")
# 	print scores[rand_range[i]]
# 	plt.show()

print(scores.shape)
print(np.amin(scores))

def build_cnn(input_var=None):
	# As a third model, we'll create a CNN of two convolution + pooling stages
	# and a fully-connected hidden layer in front of the output layer.

	# Input layer, as usual:
	network = lasagne.layers.InputLayer(shape=(None, 1, 33, 33),
	                                    input_var=input_var)
	# This time we do not apply input dropout, as it tends to work less well
	# for convolutional layers.

	# Convolutional layer with 32 kernels of size 5x5. Strided and padded
	# convolutions are supported as well; see the docstring.
	network = lasagne.layers.Conv2DLayer(
		network, num_filters=32, filter_size=(5, 5),
		nonlinearity=lasagne.nonlinearities.rectify,
		W=lasagne.init.GlorotUniform())
	# Expert note: Lasagne provides alternative convolutional layers that
	# override Theano's choice of which implementation to use; for details
	# please see http://lasagne.readthedocs.org/en/latest/user/tutorial.html.

	# Max-pooling layer of factor 2 in both dimensions:
	network = lasagne.layers.MaxPool2DLayer(network, pool_size=(2, 2))

	# Another convolution with 32 5x5 kernels, and another 2x2 pooling:
	network = lasagne.layers.Conv2DLayer(
			network, num_filters=32, filter_size=(5, 5),
			nonlinearity=lasagne.nonlinearities.rectify)
	network = lasagne.layers.MaxPool2DLayer(network, pool_size=(2, 2))

	# A fully-connected layer of 256 units with 50% dropout on its inputs:
	network = lasagne.layers.DenseLayer(
			lasagne.layers.dropout(network, p=.5),
			num_units=256,
			nonlinearity=lasagne.nonlinearities.rectify)

	# And, finally, the 10-unit output layer with 50% dropout on its inputs:
	network = lasagne.layers.DenseLayer(
			network,
			num_units=1,
			nonlinearity=lasagne.nonlinearities.sigmoid)

	return network

def iterate_minibatches(inputs, targets, batchsize, shuffle=False):
    assert len(inputs) == len(targets)
    if shuffle:
        indices = np.arange(len(inputs))
        np.random.shuffle(indices)
    for start_idx in range(0, len(inputs) - batchsize + 1, batchsize):
        if shuffle:
            excerpt = indices[start_idx:start_idx + batchsize]
        else:
            excerpt = slice(start_idx, start_idx + batchsize)
        yield inputs[excerpt], targets[excerpt]

def main(data,model='cnn', num_epochs=500):
    # Load the dataset
    print("Loading data...")

    X = data[0].reshape(-1, 1, 33, 33)
    X /= np.float32(255)
    Y = np.round_(data[1]).astype(np.float32)
    #X = X.astype(np.float32)
    #Y = Y.astype(np.float32)
    # X_train = X[0:300000]
    # y_train = Y[0:300000]
    # X_val = X[-20000:]
    # y_val = Y[-20000:]
    # X_test = X[300000:400000]
    # y_test = Y[300000:400000]

    X_train = X[0:50000]
    y_train = Y[0:50000]
    X_val = X[-4000:]
    y_val = Y[-4000:]
    X_test = X[50000:80000]
    y_test = Y[50000:80000]

    # Prepare Theano variables for inputs and targets
    input_var = T.tensor4('inputs')
    target_var = T.fvector('targets')

    # Create neural network model (depending on first command line parameter)
    network = build_cnn(input_var)

    # Create a loss expression for training, i.e., a scalar objective we want
    # to minimize (for our multi-class problem, it is the cross-entropy loss):
    prediction = lasagne.layers.get_output(network)
    loss = lasagne.objectives.binary_hinge_loss(prediction, target_var, log_odds=False)
    loss = loss.mean()
    # We could add some weight decay as well here, see lasagne.regularization.

    # Create update expressions for training, i.e., how to modify the
    # parameters at each training step. Here, we'll use Stochastic Gradient
    # Descent (SGD) with Nesterov momentum, but Lasagne offers plenty more.
    params = lasagne.layers.get_all_params(network, trainable=True)
    updates = lasagne.updates.nesterov_momentum(
            loss, params, learning_rate=0.01, momentum=0.9)

    # Create a loss expression for validation/testing. The crucial difference
    # here is that we do a deterministic forward pass through the network,
    # disabling dropout layers.
    test_prediction = lasagne.layers.get_output(network, deterministic=True)
    test_loss = lasagne.objectives.binary_hinge_loss(test_prediction,
                                                            target_var, log_odds=False)
    test_loss = test_loss.mean()
    # As a bonus, also create an expression for the classification accuracy:
    test_acc = T.mean(T.eq(test_prediction, target_var),
                      dtype=theano.config.floatX)
    #test_acc = T.mean(lasagne.objectives.binary_hinge_loss(prediction, target_var, log_odds=False),
    #					dtype=theano.config.floatX)

    # Compile a function performing a training step on a mini-batch (by giving
    # the updates dictionary) and returning the corresponding training loss:
    train_fn = theano.function([input_var, target_var], loss, updates=updates)

    # Compile a second function computing the validation loss and accuracy:
    val_fn = theano.function([input_var, target_var], [test_loss, test_acc])

    # Finally, launch the training loop.
    print("Starting training...")
    # We iterate over epochs:
    for epoch in range(num_epochs):
        # In each epoch, we do a full pass over the training data:
        train_err = 0
        train_batches = 0
        start_time = time.time()
        for batch in iterate_minibatches(X_train, y_train, 500, shuffle=True):
            inputs, targets = batch
            train_err += train_fn(inputs, targets)
            train_batches += 1

        # And a full pass over the validation data:
        val_err = 0
        val_acc = 0
        val_batches = 0
        for batch in iterate_minibatches(X_val, y_val, 500, shuffle=False):
            inputs, targets = batch
            err, acc = val_fn(inputs, targets)
            val_err += err
            val_acc += acc
            val_batches += 1

        # Then we print the results for this epoch:
        print("Epoch {} of {} took {:.3f}s".format(
            epoch + 1, num_epochs, time.time() - start_time))
        print("  training loss:\t\t{:.6f}".format(train_err / train_batches))
        print("  validation loss:\t\t{:.6f}".format(val_err / val_batches))
        print("  validation accuracy:\t\t{:.2f} %".format(
            val_acc / val_batches * 100))

    # After training, we compute and print the test error:
    test_err = 0
    test_acc = 0
    test_batches = 0
    for batch in iterate_minibatches(X_test, y_test, 500, shuffle=False):
        inputs, targets = batch
        err, acc = val_fn(inputs, targets)
        test_err += err
        test_acc += acc
        test_batches += 1
    print("Final results:")
    print("  test loss:\t\t\t{:.6f}".format(test_err / test_batches))
    print("  test accuracy:\t\t{:.2f} %".format(
        test_acc / test_batches * 100))

    # Optionally, you could now dump the network weights to a file like this:
    # np.savez('model.npz', *lasagne.layers.get_all_param_values(network))
    #
    # And load them again later on like this:
    # with np.load('model.npz') as f:
    #     param_values = [f['arr_%d' % i] for i in range(len(f.files))]
    # lasagne.layers.set_all_param_values(network, param_values)

main([images,scores])


import math
from typing import List

import numpy as np
import torch
import torch.jit as jit
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor
from torch.nn import Parameter

from language_models.language_base_model import LanguageBaselightning

class RNNCell(jit.ScriptModule):
    def __init__(self, input_size, hidden_size):
        super(RNNCell, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        # Initialize the weights with random numbers.
        self.weight_ih = Parameter(torch.randn(hidden_size, input_size))
        self.weight_hh = Parameter(torch.randn(hidden_size, hidden_size))
        self.bias_ih = Parameter(torch.randn(hidden_size)) # input to hidden
        self.bias_hh = Parameter(torch.randn(hidden_size)) # hidden to hidden
        self.reset_parameters()

    def reset_parameters(self):
        stdv = 1.0 / math.sqrt(self.hidden_size)
        for weight in self.parameters():
            weight.data.uniform_(-stdv, stdv)

    @jit.script_method
    def forward(self, input: Tensor, state: Tensor):
        # input is the input at the current timestep
        # state is the hidden state from the previous timestep
        hx = state
        hidden = (
            torch.mm(input, self.weight_ih.t())
            + self.bias_ih
            + torch.mm(hx, self.weight_hh.t())
            + self.bias_hh
        )
        hy = torch.tanh(hidden)
        return hy

class RNNLayer(jit.ScriptModule):
    def __init__(self, cell, *cell_args):
        super(RNNLayer, self).__init__()
        self.cell = cell(*cell_args)

    @jit.script_method
    def forward(self, input: Tensor, state: Tensor):
        inputs = input.unbind(1)

        outputs = torch.jit.annotate(List[Tensor], [])
        for i in range(len(inputs)):
            state = self.cell(inputs[i], state)
            outputs += [state]
        return torch.stack(outputs, 1), state

class JitRNN_language_model(LanguageBaselightning):
    def __init__(
        self,
        vocab_size: int,
        embedding_size: int,
        hidden_size: int,
        padding_idx: int,
        learning_rate: int = 0.001,
    ):
        super(JitRNN_language_model, self).__init__()
        self.vocab_size = vocab_size
        self.hidden_size = hidden_size
        # self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        # self.padding_idx = torch.tensor(padding_idx).to(self.device)
        self.padding_idx = torch.tensor(padding_idx)
        self.learning_rate = learning_rate

        self.embedding = nn.Embedding(
            vocab_size, embedding_size, padding_idx=self.padding_idx
        )

        self.dense = nn.Linear(hidden_size, embedding_size)

        self.rnn = RNNLayer(RNNCell, embedding_size, hidden_size)

        self.output_layer = nn.Linear(embedding_size, vocab_size)
        self.hidden = None

        # tie the weights of the output embeddings with the input embeddings
        self.output_layer.weight = self.embedding.weight
        self.loss_func = nn.CrossEntropyLoss()

    def forward(self, x, seq_length):
        batch_size, seq_length = x.size()
        # get embedding encoder
        x = self.embedding(x)
        # get output of rnn
        self.hidden = torch.zeros(batch_size, self.hidden_size).type_as(x)

        output, self.hidden = self.rnn(x, self.hidden)

        out = self.dense(output)
        out = self.output_layer(out)
        return out.view(
            batch_size, seq_length, self.vocab_size
        )  # Dimensions -> Batch x Sequence x Vocab

    def reset_intermediate_vars(self):
        self.hidden = None

    def detach_intermediate_vars(self):
        self.hidden = self.hidden.detach()

# class RNN(nn.Module):

#     # you can also accept arguments in your model constructor

#     #  we don't use the output in this implemention
#     def __init__(
#         self,
#         embed_size,
#         hidden_size,
#     ):
#         super(RNN, self).__init__()

#         self.hidden_size = hidden_size
#         # input_size = embed_size + hidden_size
#         self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
#         # self.i2h = nn.Linear(input_size, hidden_size)
#         self.Wih = nn.Linear(embed_size, hidden_size)
#         self.Whh = nn.Linear(hidden_size, hidden_size)
#         # self.h2o = nn.Linear(input_size, output_size)

#     def forward(self, data, last_hidden):

#         wi = self.Wih(data)
#         wh = self.Whh(last_hidden)
#         hidden = torch.relu(wi + wh)
#         # output = self.h2o(input)
#         return hidden

#     def initHidden(self, batch_size):
#         # return torch.zeros(batch_size,self.hidden_size).to(self.device)
#         return nn.init.kaiming_uniform_(torch.empty(batch_size, self.hidden_size)).to(
#             self.device
#         )

# class RNN_language_model(nn.Module):
#     def __init__(
#         self,
#         vocab_size: int,
#         embed_size: int,
#         hidden_size: int,
#         padding_idx: int,
#     ):
#         super(RNN_language_model, self).__init__()
#         self.vocab_size = vocab_size
#         self.hidden_size = hidden_size
#         self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
#         self.padding_idx = torch.tensor(padding_idx).to(self.device)

#         self.embedding = nn.Embedding(
#             vocab_size, embed_size, padding_idx=self.padding_idx
#         )

#         self.dense = nn.Linear(hidden_size, embed_size)
#         # note that output_size = vocab_size
#         self.rnn_cell = RNN(
#             embed_size,
#             hidden_size,
#         )

#         self.output_layer = nn.Linear(embed_size, vocab_size)

#         # tie the weights of the output embeddings with the input embeddings
#         # self.output_layer.weight = self.embedding.weight
#         self.loss_func = nn.CrossEntropyLoss()

#     def forward(self, x, seq_length):
#         batch_size, seq_length = x.size()
#         # get embedding encoder
#         x = self.embedding(x)
#         # get output of rnn
#         self.hidden = self.rnn_cell.initHidden(batch_size)

#         hiddens = []
#         # recurrent rnn
#         for i in range(seq_length):
#             hidden_next = self.rnn_cell(x[:, i, :], self.hidden)
#             hiddens.append(hidden_next.unsqueeze(1))
#             self.hidden = hidden_next
#         hidden_tensor = torch.cat(hiddens, 1)
#         out = hidden_tensor.contiguous().view(-1, self.hidden_size)
#         out = self.dense(out)
#         out = self.output_layer(out)
#         return (
#             out.view(batch_size, seq_length, self.vocab_size),
#             self.hidden,
#         )  # Dimensions -> Batch x Sequence x Vocab

#     def loss(self, predictions, y, mask):
#         predictions = predictions.view(-1, predictions.size(2))
#         predictions *= torch.stack([mask] * predictions.size(1)).transpose(0, 1).float()
#         return self.loss_func(predictions, y)


class Graph:
    def __init__(self,Vertices):
        self.V = Vertices
        self.graph = []

    def addEdge(self,u,v,w):
        self.graph.append([u,v,w])

    def find(self,parent,i):
        if parent[i] == i:
            return i
        return self.find(parent,parent[i])

    def print_g(self):
        print(self.graph)

    def union(self,parent,rank,x,y):
        xroot = self.find(parent,x) # locating the root node
        yroot = self.find(parent,y)

        if rank[xroot] < rank[yroot]: # assign the root which has maximum height
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else: # if height are same then assign either and increase the height by one
            parent[yroot] = xroot
            rank[xroot] += 1

    def print_kruskal(self,result):
        cost = 0
        print("Edges in MST:")
        for u,v,w in result:
            cost += w
            print(f"{u}--{v}--->{w}")
        print(f"Cost-->{cost}")

    def kruskal(self):
        result = []
        i,e = 0,0 # i -> index in the graph e->index of result arr

        # sort the array acc to weights
        self.graph = sorted(self.graph, key = lambda x:x[2])
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node) # every node points to itself
            rank.append(0) # level is 0

        while e<self.V-1:# picking the smallest weighted edge
            u,v,w = self.graph[i]
            i += 1
            x = self.find(parent,u)
            y = self.find(parent,v)

            # if parent of both are diff then no cycle, add in the result
            if x!=y:
                e += 1
                result.append([u,v,w])
                self.union(parent,rank,x,y) # assign the parents and rank.
        self.print_kruskal(result)

g = Graph(6)
g.addEdge(0,1,12)
g.addEdge(1, 2,15)
g.addEdge(1, 3,12)
g.addEdge(2, 4,13)
g.addEdge(2, 5,5)
g.addEdge(3, 2,6)
g.addEdge(3,4,6)
g.kruskal()


volume = int(input())
pipe1 = int(input())
pipe2 = int(input())
hours = float(input())
total_volume = (pipe1 + pipe2) * hours
if total_volume <= volume:
    pool_percent = (total_volume / volume) * 100
    pipe1_percent = ((pipe1 * hours) / total_volume) * 100
    pipe2_percent = ((pipe2 * hours) / total_volume) * 100
    print(f"The pool is {pool_percent:.2f}% full. Pipe 1: {pipe1_percent:.2f}%. Pipe 2: {pipe2_percent:.2f}%")
else:
    over_volume = total_volume - volume
    print(f"For {hours} hours the pool overflow with {over_volume:.2f} liters")


#!/usr/bin/python3
import os, os.path
import json
import subprocess
from flask import Flask, request, redirect, abort
from time import sleep

app = Flask(__name__)

GITROOT = '/home/ubuntu/service/'

@app.route('/')
def index():
    return redirect('https://github.com/TauWu/spider_monitor_api')

@app.route('/', methods=['POST'])
def commit():
    payload = {"repository":{"name":"spider_monitor_api"}}
    reponame = payload['repository']['name']
    reponame = "%s/bash"%reponame

    repodir = os.path.join(GITROOT, reponame)
    os.chdir(repodir)

    os.system("./start_service.sh")
    sleep(10)

    return 'success.'

application = app # For WSGI

if __name__ == '__main__':
    app.run('0.0.0.0',port=9000,debug=True)


"""
650. 2 Keys Keyboard

There is only one character 'A' on the screen of a notepad. You can perform one
of two operations on this notepad for each step:
    1. Copy All: You can copy all the characters present on the screen.
    2. Paste: You can paste the characters which are copied last time.
Given an integer n, return the minimum number of operations to get the
character 'A' exactly n times on the screen.
"""

def min_steps_naive(n):
    """Naive recursive solution."""

    # Base case: you start off with 1 'A' already on the screen, therefore, the
    # number of operations needed to get to 1 'A' is 0.
    if n == 1:
        return 0

    min_ops = float('inf')
    for i in range(1, n):
        if n % i == 0:
            ops = min_steps_naive(i) + n // i
            min_ops = min(min_ops, ops)

    return min_ops

def min_steps_rec(n, dp):
    """Memoized dynamic programming solution."""
    if n == 1:
        return 0

    # Check if solution was already computed in dp table.
    if dp[n] != float('inf'):
        return dp[n]

    for i in range(1, n):
        if n % i == 0:
            ops = min_steps_rec(i, dp) + n // i
            dp[n] = min(dp[n], ops)

    return dp[n]

def min_steps(n):
    """Bottom-up dynamic programming solution."""

    # dp[i] represents the min. no. of operations needed to get to i "A"s.
    dp = [float('inf') for _ in range(n + 1)]

    # Base case
    dp[1] = 0

    # Calculate dp[i] from 2 <= i <= n
    for i in range(2, n + 1):

        # If n % i != 0, there is no point in calculating dp[i].
        if n % i == 0:

            # Then try every possibility from 1 to i
            for j in range(1, i):
                if i % j == 0:
                    ops = dp[j] + i // j
                    dp[i] = min(dp[i], ops)

    return dp[n]


# !/usr/bin/env python

import rospy
import websocket
import json

# from msg.ObjectArray import ObjectArray
from detection.msg._ObjectArray import ObjectArray

LABELS = ["human", "unknown", "animals"]

try:
    import thread
except ImportError:
    import _thread as thread
import time

def on_message(ws, message):
    pass
    # print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("### closed ###")

def on_open(ws):
    def run(*args):
        drone_id = 1
        latitude = 55.751574
        longtitude = 37.573856
        while True:
            if on_object_array.last_object_array is None:
                continue
            object_array = on_object_array.last_object_array
            on_object_array.last_object_array = None
            cnt = {l: 0 for l in LABELS}
            for object in object_array.objects:
                cnt[LABELS[object.label]] += 1
            data = {
                'drone_id': drone_id,
                'latitude': latitude,
                'longtitude': longtitude,
                'timestamp': time.time(),
                'humans': cnt['human'],
                'animals': cnt["animals"],
                'unknown': cnt["unknown"]
            }
            time.sleep(1)
            latitude += 0.001
            ws.send(json.dumps(data))
        ws.close()

    thread.start_new_thread(run, ())

def on_object_array(msg):
    on_object_array.last_object_array = msg

on_object_array.last_object_array = None

if __name__ == "__main__":
    rospy.init_node("sender")

    sub_objects = rospy.Subscriber("/detection/yolo/objects", ObjectArray, on_object_array)

    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("ws://192.168.86.248:8080/drone/", on_message=on_message, on_error=on_error,
                                on_close=on_close)
    ws.on_open = on_open
    ws.run_forever()


import numpy as np
from numpy import array, trace, random, linalg
from numpy.linalg import norm

def projectorOnto(vector):
    """ Returns a rank-1 projector onto a given vector
    """
    return np.tensordot(vector, vector.conj(), 0)

def randomPureState(dim):
    """ Generates Haar-random pure state density matrix

    dim - dimension of the resulting matrix
    """
    psi = random.randn(dim) + 1j*random.randn(dim)
    proj = projectorOnto(psi)
    proj /= trace(proj)
    return proj

def randomMixedState(dim):
    """ Generates Hilbert - Schmidt distributed random mixed states

    dim - dimension of the resulting matrix
    """
    state = random.randn(dim, dim) + 1j*random.randn(dim, dim)
    state = state.dot(state.T.conj())
    state /= trace(state)
    return state

def isMeasurementValid(measurement, eps = 1e-12):
    """ Checks whether a given measurement is valid (i.e. a normalized rank-1 projector)

    measurement - the measurement to check
    eps - internal test error
    """
    return ((abs(trace(measurement) - 1.) <= eps) and
            (measurement == measurement.T.conj()).all() and
            (linalg.matrix_rank(measurement) == 1))

def isDensityMatrix(rho, eps = 1e-12):
    """ Checks whether a given matrix rho is a density matrix
    (i.e. Hermitian, positive semidefinite with unit trace)

    rho - the density matrix to check
    eps - internal test error
    """
    if ((abs(trace(rho) - 1.) > eps) or
        (rho != rho.T.conj()).all()):
        return False
    return (linalg.eigvalsh(rho) >= -eps).all()

def bornRule(trueState, measurement):
    """ Calculates probability according to the Born's rule

    trueState - the true state's density matrix
    measurement - a normalized rank-1 projector
    """
    return trace(trueState.dot(measurement)).real

def measure(trials, trueState, measurement, checkValidity = False):
    """ Returns measured counts

    trials - the number of repetitions of the measurement
    trueState - the true density matrix to measure
    measurement - a normalized rank-1 projector
    """
    if checkValidity:
        if ((not isMeasurementValid(measurement)) or
            (not isDensityMatrix(trueState))):
            raise ValueError('Invalid true state and/or measurement were given')
    p = bornRule(trueState, measurement)
    n = random.binomial(trials, np.clip(p, 0, 1))
    return array([n, trials - n])

# Sample qubit true states
trueStates = array([
    [[1., 0.], [0., 0.]], # H state
    [[0.5, 0.5], [0.5, 0.5]], # D state
    [[0.5, -0.5j], [0.5j, 0.5]], # R state
    [[0.7, 0.], [0., 0.3]], # 30% mixed state
    [[0.39759026+0.j, -0.48358514+0.07521739j], [-0.48358514-0.07521739j, 0.60240974+0.j]], # Random pure state #1
    [[0.37719362+0.j, 0.18480147+0.44807032j], [0.18480147-0.44807032j, 0.62280638+0.j]], # Random pure state #2
    [[0.62829064+0.j, 0.13397942-0.30318748j], [0.13397942+0.30318748j, 0.37170936+0.j]], # Random mixed state #1
    [[0.75525869+0.j, 0.27476800-0.2559911j], [0.27476800+0.2559911j, 0.24474131+0.j]] # Random mixed state #2
    ])


from django.conf.urls import url

from .views import(
    AddQuestionCreateAPIView,
    QuestionListAPIView,
    QuestionRUDAPIView,
    QuestionImageRUDAPIView,
    UserQuestionListAPIView,

    TopicCreateAPIView,
    TopicRUDAPIView,
    SubTopicCreateAPIView,
    SubTopicRUDAPIView,

    QuestionOptionCreateAPIView,
    QuestionOptionRUDAPIView,

    QuestionSolutionCreateAPIView,
    QuestionSolutionRUDAPIView,

    QuestionDiscussionCreateAPIView,
    QuestionDiscussionRUDAPIView,
)

urlpatterns = [

    url(r'^$'                             ,QuestionListAPIView.as_view()            ,name="questions"),
    url(r'user'                           ,UserQuestionListAPIView.as_view()        ,name="user_questions"),
    url(r'create'                ,AddQuestionCreateAPIView.as_view()       ,name="question_create"),
    url(r'edit/(?P<pk>\d+)'      ,QuestionRUDAPIView.as_view()             ,name="question_edit"),
    url(r'edit-image/(?P<pk>\d+)',QuestionImageRUDAPIView.as_view()        ,name="question_edit_image"),

    url(r'option-create'                  ,QuestionOptionCreateAPIView.as_view()    ,name="question_answer_create"),
    url(r'option-edit/(?P<pk>\d+)'        ,QuestionOptionRUDAPIView.as_view()       ,name="question_answer_edit"),
    ###################
    url(r'solution-create'                ,QuestionSolutionCreateAPIView.as_view()  ,name="question_solution_create"),
    url(r'solution-edit/(?P<pk>\d+)'      ,QuestionSolutionRUDAPIView.as_view()     ,name="question_solution_edit"),

    url(r'discussion-create'              ,QuestionDiscussionCreateAPIView.as_view(),name="discussion_create"),
    url(r'discussion-edit/(?P<pk>\d+)'    ,QuestionDiscussionRUDAPIView.as_view()   ,name="discussion_edit"),
    ###################

    url(r'topic-create'                   ,TopicCreateAPIView.as_view()       ,name="topic_create"),
    url(r'topic-edit/(?P<pk>\d+)'         ,TopicRUDAPIView.as_view()             ,name="topic_edit"),

    url(r'subTopic-create'                ,SubTopicCreateAPIView.as_view()       ,name="subTopic_create"),
    url(r'subTopic-edit/(?P<pk>\d+)'      ,SubTopicRUDAPIView.as_view()             ,name="subTopic_edit"),
]


import pytest

from src.same_tree import Solution
from src.utils.binary_tree import list_to_tree

@pytest.mark.parametrize(
    "list_p,list_q,equal",
    [
        ([1, 2, 3], [1, 2, 3], True),
        ([1, 2], [1, None, 2], False),
        ([], [], True),
        ([1, 2, 1], [1, 1, 2], False),
    ],
)
def test_solution(list_p, list_q, equal):
    p = list_to_tree(list_p)
    q = list_to_tree(list_q)

    assert Solution().isSameTree(p, q) is equal


from rest_framework import status

def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'code': status.HTTP_200_OK,
        'message': '',
        'result': {
            'token': token,
            'user_id': user.id,
            'username': user.username
        }
    }


from datetime import date

from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession

from api.deps import get_db
from crud.analytics import get_analytics_by_range_of_dates, get_analytics_by_student_id
from schemas.analytics import AnalyticsByRangeOfDates

router = APIRouter()

@router.get("/", response_model=list[AnalyticsByRangeOfDates | None])
async def get_analytics_by_dates(
    date_start: date = Query(...), date_end: date = Query(...), db: AsyncSession = Depends(get_db)
):
    """Get analytics by all students by range of dates.

    Args:
        date_start: Range start date.
        date_end:  Range end date incl.
        db: SQLAlchemy local session.

    Returns:
        List of AnalyticsByRangeOfDates each containing emotion, emotion's count and date.
    """
    return await get_analytics_by_range_of_dates(
        db=db, date_start=date_start, date_end=date_end
    )

@router.get("/{student_track_id}", response_model=list[AnalyticsByRangeOfDates | None])
async def get_analytics_by_student(
    student_track_id: int,
    date_start: date = Query(...),
    date_end: date = Query(...),
    db: AsyncSession = Depends(get_db),
):
    """Get analytics by student's track id and range of dates.

    Args:
        student_track_id: Student's track ID.
        date_start: Range date start.
        date_end: Range date end.
        db: SQLAlchemy local session,

    Returns:
        List of AnalyticsByRangeOfDates each containing emotion, emotion's count and date.
    """
    return await get_analytics_by_student_id(
        db=db, student_track_id=student_track_id, start_date=date_start, end_date=date_end
    )


from batch import create_udb
from projectMetrics import projectMetric
from subprocess import call
import git
import sys
import datetime
import os
import shutil
import time

def main():
    git_repo = sys.argv[1]      # git repo is the relative path from the folder
    all_sha1 = []
    sha_dtime = []
    repo = git.Repo(git_repo)

    for commit in repo.iter_commits('master'):
        sha = commit.hexsha
        get_sha = repo.git.rev_parse(sha)
        all_sha1.append(get_sha)
        sha_dtime.append(datetime.datetime.fromtimestamp(commit.committed_date))
    start_time = time.time()
    print(len(all_sha1))
    exit()
    g = git.Git(git_repo)

    for i in range(len(all_sha1)):
        sha = all_sha1[i]
        d_time = sha_dtime[i]
        g.checkout(sha)
        db_name = create_udb(git_repo)
        projectMetric(db_name,sha,d_time)
        call('rm -f ' + db_name)

    print("--- %s minutes ---" % round((time.time() - start_time) / 60,5))

if __name__ == '__main__':
    main()


import tensorflow as tf

def unpool(value, name='unpool'):
    """From: https://github.com/tensorflow/tensorflow/issues/2169
    N-dimensional version of the unpooling operation from
    https://www.robots.ox.ac.uk/~vgg/rg/papers/Dosovitskiy_Learning_to_Generate_2015_CVPR_paper.pdf
    :param value: A Tensor of shape [b, d0, d1, ..., dn, ch]
    :param name: A string for scope name.
    :return: A Tensor of shape [b, 2*d0, 2*d1, ..., 2*dn, ch]
    """
    with tf.name_scope(name) as scope:
        sh = value.get_shape().as_list()
        dim = len(sh[1:-1])
        out = (tf.reshape(value, [-1] + sh[-dim:]))
        for i in range(dim, 0, -1):
            out = tf.concat([out, tf.zeros_like(out)], i)
        out_size = [-1] + [s*2 for s in sh[1:-1]] + [sh[-1]]
        out = tf.reshape(out, out_size, name=scope)
    return out

class ConvolutionalAutoencoder(tf.keras.Model):
    def __init__(self, num_neuron=256, kernal1=32, kernal2=16, shape=(32, 32, 3)):
        assert type(num_neuron) == int
        assert type(kernal1) == int
        assert type(kernal2) == int
        assert len(shape) == 3
        super().__init__()

        if not tf.executing_eagerly():
            raise NotImplementedError('Eager execution is needed but it return as : {}'.format(tf.executing_eagerly()))
        else:
            init = tf.contrib.layers.xavier_initializer()
            pooled_shape = (shape[0]/4, shape[1]/4, shape[2])
            self.conv1 = tf.keras.layers.Conv2D(
                filters=kernal1,
                kernel_size=5,
                padding='SAME',
                activation=tf.nn.relu,
                kernel_initializer=init)
            self.max1 = tf.keras.layers.MaxPool2D(
                pool_size=(2, 2),
                strides=(2, 2),
                padding='SAME')
            self.conv2 = tf.keras.layers.Conv2D(
                filters=kernal2,
                kernel_size=5,
                padding='SAME',
                activation=tf.nn.relu,
                kernel_initializer=init)
            self.max2 = tf.keras.layers.MaxPool2D(
                pool_size=(2, 2),
                strides=(2, 2),
                padding='SAME')
            self.flatten1 = tf.keras.layers.Flatten()
            self.dense1 = tf.keras.layers.Dense(
                units=num_neuron,
                activation=tf.nn.relu,
                kernel_initializer=init)
            self.dense2 = tf.keras.layers.Dense(
                units=pooled_shape[0]*pooled_shape[1]*kernal2,
                activation=tf.nn.relu,
                kernel_initializer=init)

            self.deflatten1 = tf.keras.layers.Reshape(
                target_shape=(int(pooled_shape[0]), int(pooled_shape[1]), kernal2))

            self.deconv1 = tf.keras.layers.Conv2DTranspose(
                filters=kernal1,
                kernel_size=5,
                padding='SAME',
                activation=tf.nn.relu,
                kernel_initializer=init)
            self.deconv2 = tf.keras.layers.Conv2DTranspose(
                filters=shape[2],
                kernel_size=5,
                padding='SAME',
                activation=tf.nn.sigmoid,
                kernel_initializer=init)

    def call(self, img):
        """Pass the batch of images to forward propagate into the networks.
        :param img: Input images with shape as [batch_size, image_size, image_size, image_channel].
        :return: Reconstruction images with shape as same as img.
        """
        x = self.conv1(img)
        x = self.max1(x)
        x = self.conv2(x)
        x = self.max2(x)
        x = self.flatten1(x)
        x = self.dense1(x)
        x = self.dense2(x)
        x = self.deflatten1(x)
        x = unpool(x)
        x = self.deconv1(x)
        x = unpool(x)
        x = self.deconv2(x)
        return x


# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, tools, _
from odoo import SUPERUSER_ID
import io
import csv
import base64
import ftplib
from odoo.tools import pycompat
import logging
_logger = logging.getLogger(__name__)
from odoo.exceptions import UserError, AccessError

from odoo.addons.website_mail.models.mail_message import MailMessage
from datetime import datetime, timedelta
from odoo.http import request
from odoo.exceptions import ValidationError
from odoo.addons.website_sale.models.sale_order import SaleOrder

def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs):
	""" Method monkey patched to handle multiple UoM from website """
	self.ensure_one()
	print (kwargs, 'In Override method \n\n\n\n\n\n\n')
	product_context = dict(self.env.context)
	product_context.setdefault('lang', self.sudo().partner_id.lang)
	SaleOrderLineSudo = self.env['sale.order.line'].sudo().with_context(product_context)
	# change lang to get correct name of attributes/values
	product_with_context = self.env['product.product'].with_context(product_context)
	product = product_with_context.browse(int(product_id))

	try:
		if add_qty:
			add_qty = float(add_qty)
	except ValueError:
		add_qty = 1
	try:
		if set_qty:
			set_qty = float(set_qty)
	except ValueError:
		set_qty = 0
	quantity = 0
	order_line = False
	if self.state != 'draft':
		request.session['sale_order_id'] = None
		raise UserError(_('It is forbidden to modify a sales order which is not in draft status.'))
	if line_id is not False:
		order_line = self._cart_find_product_line(product_id, line_id, **kwargs)[:1]

	# Create line if no line with product_id can be located
	if not order_line:
		if not product:
			raise UserError(_("The given product does not exist therefore it cannot be added to cart."))

		no_variant_attribute_values = kwargs.get('no_variant_attribute_values') or []
		received_no_variant_values = product.env['product.template.attribute.value'].browse([int(ptav['value']) for ptav in no_variant_attribute_values])
		received_combination = product.product_template_attribute_value_ids | received_no_variant_values
		product_template = product.product_tmpl_id

		# handle all cases where incorrect or incomplete data are received
		combination = product_template._get_closest_possible_combination(received_combination)

		# get or create (if dynamic) the correct variant
		product = product_template._create_product_variant(combination)

		if not product:
			raise UserError(_("The given combination does not exist therefore it cannot be added to cart."))

		product_id = product.id

		values = self._website_product_id_change(self.id, product_id, qty=1)

		# add no_variant attributes that were not received
		for ptav in combination.filtered(lambda ptav: ptav.attribute_id.create_variant == 'no_variant' and ptav not in received_no_variant_values):
			no_variant_attribute_values.append({
				'value': ptav.id,
			})

		# save no_variant attributes values
		if no_variant_attribute_values:
			values['product_no_variant_attribute_value_ids'] = [
				(6, 0, [int(attribute['value']) for attribute in no_variant_attribute_values])
			]

		# add is_custom attribute values that were not received
		custom_values = kwargs.get('product_custom_attribute_values') or []
		received_custom_values = product.env['product.template.attribute.value'].browse([int(ptav['custom_product_template_attribute_value_id']) for ptav in custom_values])

		for ptav in combination.filtered(lambda ptav: ptav.is_custom and ptav not in received_custom_values):
			custom_values.append({
				'custom_product_template_attribute_value_id': ptav.id,
				'custom_value': '',
			})

		# save is_custom attributes values
		if custom_values:
			values['product_custom_attribute_value_ids'] = [(0, 0, {
				'custom_product_template_attribute_value_id': custom_value['custom_product_template_attribute_value_id'],
				'custom_value': custom_value['custom_value']
			}) for custom_value in custom_values]

		# create the line
		order_line = SaleOrderLineSudo.create(values)
		if 'product_uom_id' in kwargs:
			order_line.product_uom = int(kwargs['product_uom_id'])
			order_line.product_uom_change()

		try:
			order_line._compute_tax_id()
		except ValidationError as e:
			# The validation may occur in backend (eg: taxcloud) but should fail silently in frontend
			_logger.debug("ValidationError occurs during tax compute. %s" % (e))
		if add_qty:
			add_qty -= 1

	# compute new quantity
	if set_qty:
		quantity = set_qty
	elif add_qty is not None:
		quantity = order_line.product_uom_qty + (add_qty or 0)

	# Remove zero of negative lines
	if quantity <= 0:
		linked_line = order_line.linked_line_id
		order_line.unlink()
		if linked_line:
			# update description of the parent
			linked_product = product_with_context.browse(linked_line.product_id.id)
			linked_line.name = linked_line.get_sale_order_line_multiline_description_sale(linked_product)
	else:
		# update line
		no_variant_attributes_price_extra = [ptav.price_extra for ptav in order_line.product_no_variant_attribute_value_ids]
		values = self.with_context(no_variant_attributes_price_extra=tuple(no_variant_attributes_price_extra))._website_product_id_change(self.id, product_id, qty=quantity)
		if self.pricelist_id.discount_policy == 'with_discount' and not self.env.context.get('fixed_price'):
			order = self.sudo().browse(self.id)
			product_context.update({
				'partner': order.partner_id,
				'quantity': quantity,
				'date': order.date_order,
				'pricelist': order.pricelist_id.id,
				'force_company': order.company_id.id,
			})
			product_with_context = self.env['product.product'].with_context(product_context)
			product = product_with_context.browse(product_id)
			values['price_unit'] = self.env['account.tax']._fix_tax_included_price_company(
				order_line._get_display_price(product),
				order_line.product_id.taxes_id,
				order_line.tax_id,
				self.company_id
			)

		if 'product_uom_id' in kwargs:
			values.update({'product_uom': int(kwargs['product_uom_id'])})
		else:
			del values['product_uom']

		order_line.write(values)
		order_line.product_uom_change()

		# link a product to the sales order
		if kwargs.get('linked_line_id'):
			linked_line = SaleOrderLineSudo.browse(kwargs['linked_line_id'])
			order_line.write({
				'linked_line_id': linked_line.id,
			})
			linked_product = product_with_context.browse(linked_line.product_id.id)
			linked_line.name = linked_line.get_sale_order_line_multiline_description_sale(linked_product)
		# Generate the description with everything. This is done after
		# creating because the following related fields have to be set:
		# - product_no_variant_attribute_value_ids
		# - product_custom_attribute_value_ids
		# - linked_line_id
		order_line.name = order_line.get_sale_order_line_multiline_description_sale(product)

	option_lines = self.order_line.filtered(lambda l: l.linked_line_id.id == order_line.id)

	return {'line_id': order_line.id, 'quantity': quantity, 'option_ids': list(set(option_lines.ids))}

SaleOrder._cart_update = _cart_update

class ProductBrand(models.Model):
	_name = "product.brand"

	name = fields.Char("Brand")

class product(models.Model):

	_inherit = 'product.template'

	brand_id = fields.Many2many("product.brand", string="Brand")
	extra_units = fields.Many2many('uom.uom', 'product_id', 'uom_id', 'prod_uom_rel', string="Extra Units")

	def units_web(self):

		product = self.env['product.template'].sudo().browse(self.id)
		units = [product.uom_id]
		for item in product.extra_units:
			units.append(item)

		return units


import random
import pygame
import copy

l = [[random.choice([0, 1]) for i in range(48)] for i in range(48)]
k = [[0 for i in range(48)] for i in range(48)]

pygame.init()
s = pygame.display.set_mode((480, 480), 0, 32)
o = True

def z(x, y):
    m = 0
    for i in (x - 1, x, x + 1):
        for j in (y - 1, y, y + 1):
            if i == x and y == j:
                continue
            if i < 0 or i > 47 or j < 0 or j > 47:
                continue
            if l[i][j] == 1:
                m += 1
    return m

while o:
    s.fill((255, 255, 255))
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            o = False

    for x in range(48):
        for y in range(48):
            a = z(x, y)
            if a == 2:
                k[x][y] = l[x][y]
            elif a == 3:
                k[x][y] = 1
            else:
                k[x][y] = 0
    for x in range(48):
        for y in range(48):
            if k[x][y] == 1:
                s.fill((0, 0, 255), (y * 10, x * 10, 10, 10))
                pygame.draw.rect(s, (0, 0, 0), (y * 10, x * 10, 10, 10), 1)
                l = copy.deepcopy(k)
    pygame.display.update()
    pygame.time.wait(100)


#Day 14 - 30 days of code, scope
class Difference:
    def __init__(self, a):
        self.__elements = a

    def computeDifference(self):
        new_array = list(map(lambda x: abs(x), self.__elements))
        v_max = max(new_array)
        v_min = min(new_array)
        self.maximumDifference = v_max - v_min

mi_lista = Difference([-3,2,3])
mi_lista.computeDifference()
print(mi_lista.maximumDifference)


import numpy as np
import ROOT
ROOT.gROOT.SetStyle("ATLAS")

software = [
'acts',
'athena',
]

sample = 'ttbar'
#sample = 'singleMu_100GeV'

event_name = "ttbar 14 TeV"
#event_name = "single Mu pT = 100 GeV"

string = '===>>>  done processing event'

log_lines_grid = [line.replace('|TIMER ACTS| ','') for line in open('output_{}.txt'.format(software[0]+'_'+sample)) if string in line or '|TIMER ACTS|' in line]
acts_values = list(filter(None,[lines[:].strip() for lines in log_lines_grid]))

log_lines_grid = [line.replace('|TIMER ATHENA| ','') for line in open('output_{}.txt'.format(software[1]+'_'+sample)) if string in line or '|TIMER ATHENA|' in line]
athena_values = list(filter(None,[lines[:].strip() for lines in log_lines_grid]))

h_acts_grid_time_PPP = ROOT.TH1F("h_acts_grid_time_PPP", "", 25, 0.0, 60)
h_athena_grid_time_PPP = ROOT.TH1F("h_athena_grid_time_PPP", "", 25, 0.0, 60)

h_acts_grid_time_SSS = ROOT.TH1F("h_acts_grid_time_SSS", "", 50, 0.0, 50)
h_athena_grid_time_SSS = ROOT.TH1F("h_athena_grid_time_SSS", "", 50, 0.0, 50)

h_acts_finder_time_PPP = ROOT.TH1F("h_acts_finder_time_PPP", "", 25, 0.0, 17)
h_athena_finder_time_PPP = ROOT.TH1F("h_athena_finder_time_PPP", "", 25, 0.0, 17)

h_acts_finder_time_SSS = ROOT.TH1F("h_acts_finder_time_SSS", "", 100, 0.0, -500)
h_athena_finder_time_SSS = ROOT.TH1F("h_athena_finder_time_SSS", "", 100, 0.0, -500)

h_acts_filter2_time_PPP = ROOT.TH1F("h_acts_finder_time_SSS", "", 25, 0.0, -100)
h_athena_filter2_time_PPP = ROOT.TH1F("h_athena_finder_time_SSS", "", 25, 0.0, -100)

h_acts_filter2_time_SSS = ROOT.TH1F("h_acts_finder_time_SSS", "", 50, 0.0, 17)
h_athena_filter2_time_SSS = ROOT.TH1F("h_athena_finder_time_SSS", "", 50, 0.0, 17)

h_acts_tri_time_PPP = ROOT.TH1F("h_acts_finder_time_SSS", "", 25, 0.0, 2300)
h_athena_tri_time_PPP = ROOT.TH1F("h_athena_finder_time_SSS", "", 25, 0.0, 2300)

h_acts_tri_time_SSS = ROOT.TH1F("h_acts_finder_time_SSS", "", 25, 0.0, -500)
h_athena_tri_time_SSS = ROOT.TH1F("h_athena_finder_time_SSS", "", 25, 0.0, -500)

for file in [acts_values, athena_values]:
  detector = ''
  a = 0
  b = 0
  event = 0
  for line in file:
    if event == 101:
      break
    if 'events processed so far' in line:
      print(event)
      event += 1
    #print(line)
    if 'This is PPP' in line:
      detector = 'PPP'
      #h_acts_finder_time_PPP.Fill(a/1000)
      #print(a/1000)
      a = 0
    if 'This is SSS' in line:
      detector = 'SSS'
      #h_acts_finder_time_SSS.Fill(b/1000)
      #print(b/1000)
      b = 0
    if 'duplets' in line:
      if file == acts_values:
        if detector == 'PPP':
          #print("h_acts_grid_time_PPP")
          h_acts_grid_time_PPP.Fill(float(line[line.find('duplets:'):].replace('duplets:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_acts_grid_time_SSS")
          h_acts_grid_time_SSS.Fill(float(line[line.find('duplets:'):].replace('duplets:', '').strip().split(" ")[0])/1000)
      elif file == athena_values:
        if detector == 'PPP':
          #print("h_athena_grid_time_PPP")
          h_athena_grid_time_PPP.Fill(float(line[line.find('duplets:'):].replace('duplets:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_athena_grid_time_SSS")
          h_athena_grid_time_SSS.Fill(float(line[line.find('duplets:'):].replace('duplets:', '').strip().split(" ")[0])/1000)
    elif 'filter 1' in line and 'triplets' not in line:
      if file == acts_values:
        if detector == 'PPP':
          #print("h_acts_finder_time_PPP")
          #print(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
          h_acts_finder_time_PPP.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_acts_finder_time_SSS")
          h_acts_finder_time_SSS.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
      elif file == athena_values:
        if detector == 'PPP':
          #print("h_athena_finder_time_PPP")
          #print(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
          h_athena_finder_time_PPP.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_athena_finder_time_SSS")
          h_athena_finder_time_SSS.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
    elif 'triplets + filter 1' in line:
      if file == acts_values:
        if detector == 'PPP':
          #print("h_acts_finder_time_PPP")
          #print(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
          h_acts_tri_time_PPP.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_acts_finder_time_SSS")
          h_acts_tri_time_SSS.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
      elif file == athena_values:
        if detector == 'PPP':
          #print("h_athena_finder_time_PPP")
          #print(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
          h_athena_tri_time_PPP.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_athena_finder_time_SSS")
          h_athena_tri_time_SSS.Fill(float(line[line.find('filter 1:'):].replace('filter 1:', '').strip().split(" ")[0])/1000)
    elif 'filter 2' in line:
      if file == acts_values:
        if detector == 'PPP':
          #print("h_acts_finder_time_PPP")
          #print(float(line[line.find('filter 2:'):].replace('filter 2:', '').strip().split(" ")[0])/1000)
          h_acts_filter2_time_PPP.Fill(float(line[line.find('filter 2:'):].replace('filter 2:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_acts_finder_time_SSS")
          h_acts_filter2_time_SSS.Fill(float(line[line.find('filter 2:'):].replace('filter 2:', '').strip().split(" ")[0])/1000)
      elif file == athena_values:
        if detector == 'PPP':
          #print("h_athena_finder_time_PPP")
          #print(float(line[line.find('filter 2:'):].replace('filter 2:', '').strip().split(" ")[0])/1000)
          h_athena_filter2_time_PPP.Fill(float(line[line.find('filter 2:'):].replace('filter 2:', '').strip().split(" ")[0])/1000)
        elif detector == 'SSS':
          #print("h_athena_finder_time_SSS")
          h_athena_filter2_time_SSS.Fill(float(line[line.find('filter 2:'):].replace('filter 2:', '').strip().split(" ")[0])/1000)

def setLegend(acts, athena, filter, dec_name):
  legend = ROOT.TLegend(0.6,0.57,0.99,0.70)
  legend.AddEntry(acts ,"ACTS")
  legend.AddEntry(athena ,"Athena")
  legend.SetLineWidth(0)
  legend.SetFillStyle(0)
  legend.Draw("same")
  latex = ROOT.TLatex()
  latex.SetNDC()
  latex.SetTextSize(0.035)
  latex.DrawText(0.61, 0.78, "{} space points".format(dec_name))
  latex.DrawText(0.61, 0.83, event_name)
  latex.DrawText(0.61, 0.73, filter)
  return legend

def setLegend2(h1, h2, name1, name2, filter):
  legend2 = ROOT.TLegend(0.6,0.57,0.99,0.70)
  legend2.AddEntry(h1 , name1)
  legend2.AddEntry(h2 , name2)
  legend2.SetLineWidth(0)
  legend2.SetFillStyle(0)
  legend2.Draw("same")
  latex2 = ROOT.TLatex()
  latex2.SetNDC()
  latex2.SetTextSize(0.035)
  latex2.DrawText(0.61, 0.83, event_name)
  latex2.DrawText(0.61, 0.73, filter)
  return legend2

def plotOptions(h1, h2, y_label):
  h1.GetYaxis().SetTitle(y_label)
  h1.GetYaxis().SetLabelSize(0.);
  h1.SetLineColor(95)
  h2.SetLineColor(60)
  h1.SetLineWidth(2)
  h1.GetYaxis().SetTitleSize(20)
  h1.GetYaxis().SetTitleFont(43)
  h1.GetYaxis().SetTitleOffset(3)
  h1.GetYaxis().SetLabelFont(43)
  h1.GetYaxis().SetLabelSize(15)
  h1.GetXaxis().SetLabelFont(43)
  h1.GetXaxis().SetLabelSize(15)
  h1.SetStats(0)
  h2.SetLineWidth(2)
  return h1, h2

def createPad1():
  pad1 = ROOT.TPad("pad1", "pad1", 0, 0.3, 1, 1.0);
  pad1.SetBottomMargin(0.05)
#  pad1.SetGridx()i
  pad1.SetLogy(1)
  pad1.Draw()
  pad1.cd()
  return pad1

def createPad2():
  pad2 = ROOT.TPad("pad2", "pad2", 0, 0.08, 1, 0.3)
  pad2.SetTopMargin(0)
  pad2.SetBottomMargin(0.3)
#  pad2.SetGridx()
  pad2.Draw()
  pad2.cd()
  return pad2

def createCanvasPads():
  c = ROOT.TCanvas("c", "canvas", 800, 800)
  # Upper histogram plot is pad1
  pad1 = createPad1()
        # Lower ratio plot is pad2
  c.cd()
  pad2 = createPad2()
  return c, pad1, pad2

def plotRatio(h1, h2, x_label):

  # Define the ratio plot
  h3 = h1.Clone("h3")
  h3.SetTitle("")
  h3.SetLineColor(1)
  h3.SetMinimum(0.8)
  h3.SetMaximum(1.35)
  h3.SetMarkerStyle(21)
  h3.Sumw2()
  h3.SetStats(0)
  h3.Divide(h2)

  # Y axis h1 plot settings
  h1.GetYaxis().SetTitleSize(20)
  h1.GetYaxis().SetTitleFont(43)
  h1.GetYaxis().SetTitleOffset(1.6)

  # Y axis ratio plot settings
  h3.GetYaxis().SetTitle("")
  h3.GetYaxis().SetNdivisions(505)
  h3.GetYaxis().SetTitleSize(20)
  h3.GetYaxis().SetTitleFont(43)
  h3.GetYaxis().SetTitleOffset(1.6)
  h3.GetYaxis().SetLabelFont(43)
  h3.GetYaxis().SetLabelSize(15)

  # X axis ratio plot settings
  h3.GetXaxis().SetTitle(x_label)
  h3.GetXaxis().SetTitleSize(20)
  h3.GetXaxis().SetTitleFont(43)
  h3.GetXaxis().SetTitleOffset(4)
  h3.GetXaxis().SetLabelFont(43)
  h3.GetXaxis().SetLabelSize(15)

  return h3

canvas = ROOT.TCanvas()
canvas.Print("time_plots.pdf[")
canvas.Clear()

h1, h2 = plotOptions(h_acts_grid_time_PPP, h_athena_grid_time_PPP, "Events")
h3 = plotRatio(h1, h2, "Time (\mu s)")
canvas, pad1, pad2 = createCanvasPads()
pad1.cd()
h1.Draw("he")
h2.Draw("he same")
legend = setLegend(h1, h2, "duplets", "PPP")
pad2.cd()
h3.Draw("he")
canvas.Print("time_plots.pdf")
canvas.Print("time_duplets.root")
canvas.Clear()
'''
# GRID SSS
h1, h2 = plotOptions(h_acts_grid_time_SSS, h_athena_grid_time_SSS, "Events")
h3 = plotRatio(h1, h2, "Time (\mu s)")
canvas, pad1, pad2 = createCanvasPads()
pad1.cd()
h1.Draw("he")
h2.Draw("he same")
legend = setLegend(h1, h2, "duplets", "SSS")
pad2.cd()
h3.Draw("he")
canvas.Print("time_plots.pdf")
canvas.Print("time_grid_SSS.png")
canvas.Clear()
'''
# FINDER PPP
h1, h2 = plotOptions(h_acts_finder_time_PPP, h_athena_finder_time_PPP, "Events")
h3 = plotRatio(h1, h2, "Time (\mu s)")
canvas, pad1, pad2 = createCanvasPads()
pad1.cd()
h1.Draw("he")
h2.Draw("he same")
legend = setLegend(h1, h2, "newOneSeedWithCurvaturesComparisonPPP", "PPP")
pad2.cd()
h3.Draw("he")
canvas.Print("time_plots.pdf")
canvas.Print("time_filter1.root")
canvas.Clear()
'''
# FINDER SSS
h1, h2 = plotOptions(h_acts_finder_time_SSS, h_athena_finder_time_SSS, "Events")
h3 = plotRatio(h1, h2, "Time (\mu s)")
canvas, pad1, pad2 = createCanvasPads()
pad1.cd()
h1.Draw("he")
h2.Draw("he same")
legend = setLegend(h1, h2, "newOneSeedWithCurvaturesComparisonPPP", "SSS")
pad2.cd()
h3.Draw("he")
canvas.Print("time_plots.pdf")
canvas.Print("time_finder_SSS.png")
canvas.Clear()
'''
h1, h2 = plotOptions(h_acts_tri_time_PPP, h_athena_tri_time_PPP, "Events")
h3 = plotRatio(h1, h2, "Time (\mu s)")
canvas, pad1, pad2 = createCanvasPads()
pad1.cd()
h1.Draw("he")
h2.Draw("he same")
legend = setLegend(h1, h2, "triplets + newOneSeedWithCurvaturesComparisonPPP", "PPP")
pad2.cd()
h3.Draw("he")
canvas.Print("time_plots.pdf")
canvas.Print("time_triplets_filter1.root")
canvas.Clear()

h1, h2 = plotOptions(h_acts_filter2_time_PPP, h_athena_filter2_time_PPP, "Events")
h3 = plotRatio(h1, h2, "Time (\mu s)")
canvas, pad1, pad2 = createCanvasPads()
pad1.cd()
h1.Draw("he")
h2.Draw("he same")
legend = setLegend(h1, h2, "fillSeeds", "PPP")
pad2.cd()
h3.Draw("he")
canvas.Print("time_plots.pdf")
canvas.Print("time_filter2.root")
canvas.Clear()

canvas.Print("time_plots.pdf]")


import sys

n, m, r, c, k = map(int, sys.stdin.readline().split())
board = [list(map(int, sys.stdin.readline().split())) for r in range(n)]
move_list = list(map(int, sys.stdin.readline().split()))
dice = [0, 0, 0, 0, 0, 0]

def roll(dice, direction):
	if direction == 1:
		temp = dice[5]
		dice[5] = dice[3]
		dice[2:4] = dice[1:3]
		dice[1] = temp
	elif direction == 2:
		temp = dice[5]
		dice[5] = dice[1]
		dice[1:3] = dice[2:4]
		dice[3] = temp
	elif direction == 3:
		temp = dice[0]
		dice[0] = dice[2]
		dice[2] = dice[4]
		dice[4] = dice[5]
		dice[5] = temp
	elif direction == 4:
		temp = dice[5]
		dice[5] = dice[4]
		dice[4] = dice[2]
		dice[2] = dice[0]
		dice[0] = temp
	# return top and bottom of the dice
	return dice[2], dice[5]

directions = ((), (0, 1), (0, -1), (-1, 0), (1, 0))
cur = (r, c)
for move in move_list:
	next_r = cur[0] + directions[move][0]
	next_c = cur[1] + directions[move][1]

	# skip this movement
	if next_r < 0 or next_r >= n or next_c < 0 or next_c >= m:
		continue

	# roll the dice
	roll(dice, move)
	if board[next_r][next_c] == 0:
		board[next_r][next_c] = dice[5]
	else:
		dice[5] = board[next_r][next_c]
		board[next_r][next_c] = 0
	print(dice[2])
	cur = (next_r, next_c)


import os
import argparse
import torch
from torch import nn
import torch.backends.cudnn as cudnn
from torch.utils.data.distributed import DistributedSampler
from torch.utils.data import DataLoader
import numpy as np
import cv2
from seg_metric import SegmentationMetric
import random
import shutil
import setproctitle
import time
import logging

from dataset import potsdam
from custom_transforms import Mixup, edge_contour
from loss import CrossEntropyLoss, Edge_loss, Edge_weak_loss

class FullModel(nn.Module):

    def __init__(self, model, args2):
        super(FullModel, self).__init__()
        self.model = model
        self.use_mixup = args2.use_mixup
        self.use_edge = args2.use_edge

        # self.ce_loss = Edge_weak_loss()
        self.ce_loss = CrossEntropyLoss()

        self.edge_loss = Edge_loss()

        if self.use_mixup:
            self.mixup = Mixup(use_edge=args2.use_edge)

    def forward(self, input, label=None, train=True):

        if train and self.use_mixup and label is not None:
            if self.use_edge:
                loss = self.mixup(input, label, [self.ce_loss, self.edge_loss], self.model)
            else:
                loss = self.mixup(input, label, self.ce_loss, self.model)
            return loss

        output = self.model(input)
        if train:
            losses = 0
            if isinstance(output, (list, tuple)):
                if self.use_edge:
                    for i in range(len(output) - 1):
                        loss = self.ce_loss(output[i], label)
                        losses += loss
                    losses += self.edge_loss(output[-1], edge_contour(label).long())
                else:
                    for i in range(len(output)):
                        loss = self.ce_loss(output[i], label)
                        losses += loss
            else:
                losses = self.ce_loss(output, label)
            return losses
        else:
            if isinstance(output, (list, tuple)):
                return output[0]
            else:
                return output

def get_world_size():
    if not torch.distributed.is_initialized():
        return 1
    return torch.distributed.get_world_size()

def get_rank():
    if not torch.distributed.is_initialized():
        return 0
    return torch.distributed.get_rank()

class params():
    def __init__(self, args2):
        if args2.dataset in ['potsdam', 'vaihingen']:
            self.number_of_classes = 6
        models = args2.models
        if models == 'HRNet_32':
            self.STAGE2 = {'NUM_MODULES': 1,
                           'NUM_BRANCHES': 2,
                           'NUM_BLOCKS': [4, 4],
                           'NUM_CHANNELS': [32, 64],
                           'BLOCK': 'BASIC',
                           'FUSE_METHOD': 'SUM'}
            self.STAGE3 = {'NUM_MODULES': 4,
                           'NUM_BRANCHES': 3,
                           'NUM_BLOCKS': [4, 4, 4],
                           'NUM_CHANNELS': [32, 64, 128],
                           'BLOCK': 'BASIC',
                           'FUSE_METHOD': 'SUM'}
            self.STAGE4 = {'NUM_MODULES': 3,
                           'NUM_BRANCHES': 4,
                           'NUM_BLOCKS': [4, 4, 4, 4],
                           'NUM_CHANNELS': [32, 64, 128, 256],
                           'BLOCK': 'BASIC',
                           'FUSE_METHOD': 'SUM'}
        elif models == 'HRNet_48':
            "hrnet48"
            self.STAGE2 = {'NUM_MODULES': 1,
                            'NUM_BRANCHES': 2,
                            'NUM_BLOCKS': [4, 4],
                            'NUM_CHANNELS': [48, 96],
                            'BLOCK':'BASIC',
                            'FUSE_METHOD': 'SUM'}
            self.STAGE3 = {'NUM_MODULES': 4,
                           'NUM_BRANCHES': 3,
                           'NUM_BLOCKS': [4, 4, 4],
                           'NUM_CHANNELS': [48, 96, 192],
                           'BLOCK': 'BASIC',
                           'FUSE_METHOD': 'SUM'}
            self.STAGE4 = {'NUM_MODULES': 3,
                           'NUM_BRANCHES': 4,
                           'NUM_BLOCKS': [4, 4, 4, 4],
                           'NUM_CHANNELS': [48, 96, 192, 384],
                           'BLOCK': 'BASIC',
                           'FUSE_METHOD': 'SUM'}

def get_model(args2, device, models='DANet'):
    if models in ['swinT', 'resT']:
        print(models, args2.head)
    else:
        print(models)
    if args2.dataset in ['potsdam', 'vaihingen']:
        nclass = 6
    assert models in ['danet', 'bisenetv2', 'pspnet', 'segbase', 'swinT',
                      'deeplabv3', 'fcn', 'fpn', 'unet', 'resT']
    if models == 'danet':
        from models.danet import DANet
        model = DANet(nclass=nclass, backbone='resnet50', pretrained_base=True)
    if models == 'bisenetv2':
        from models.bisenetv2 import BiSeNetV2
        model = BiSeNetV2(nclass=nclass)
    if models == 'pspnet':
        from models.pspnet import PSPNet
        model = PSPNet(nclass=nclass, backbone='resnet50', pretrained_base=True)
    if models == 'segbase':
        from models.segbase import SegBase
        model = SegBase(nclass=nclass, backbone='resnet50', pretrained_base=True)
    if models == 'swinT':
        from models.swinT import swin_tiny as swinT
        model = swinT(nclass=nclass, pretrained=True, aux=True, head=args2.head, edge_aux=args2.use_edge)
    if models == 'resT':
        from models.resT import rest_tiny as resT
        model = resT(nclass=nclass, pretrained=True, aux=True, head=args2.head, edge_aux=args2.use_edge)
    if models == 'deeplabv3':
        from models.deeplabv3 import DeepLabV3
        model = DeepLabV3(nclass=nclass, backbone='resnet50', pretrained_base=True)
    if models == 'fcn':
        from models.fcn import FCN16s
        model = FCN16s(nclass=nclass)
    if models == 'fpn':
        from models.fpn import FPN
        model = FPN(nclass=nclass)
    if models == 'unet':
        from models.unet import UNet
        model = UNet(nclass=nclass)

    model = FullModel(model, args2)
    model = nn.SyncBatchNorm.convert_sync_batchnorm(model)
    model = model.to(device)
    model = nn.parallel.DistributedDataParallel(
        model, device_ids=[args2.local_rank], output_device=args2.local_rank, find_unused_parameters=True)
    return model

def reduce_tensor(inp):
    """
    Reduce the loss from all processes so that
    process with rank 0 has the averaged results.
    """
    world_size = get_world_size()
    if world_size < 2:
        return inp
    with torch.no_grad():
        reduced_inp = inp
        torch.distributed.reduce(reduced_inp, dst=0)
    return reduced_inp

class AverageMeter(object):
    """Computes and stores the average and current value"""

    def __init__(self):
        self.initialized = False
        self.val = None
        self.avg = None
        self.sum = None
        self.count = None

    def initialize(self, val, weight):
        self.val = val
        self.avg = val
        self.sum = val * weight
        self.count = weight
        self.initialized = True

    def update(self, val, weight=1):
        if not self.initialized:
            self.initialize(val, weight)
        else:
            self.add(val, weight)

    def add(self, val, weight):
        self.val = val
        self.sum += val * weight
        self.count += weight
        self.avg = self.sum / self.count

    def value(self):
        return self.val

    def average(self):
        return self.avg

def parse_args():
    parser = argparse.ArgumentParser(description='Train segmentation network')
    parser.add_argument("--dataset", type=str, default='vaihingen', choices=['potsdam', 'vaihingen'])
    parser.add_argument("--end_epoch", type=int, default=200)
    parser.add_argument("--warm_epochs", type=int, default=5)
    parser.add_argument("--lr", type=float, default=0.01)
    parser.add_argument("--train_batchsize", type=int, default=1)
    parser.add_argument("--val_batchsize", type=int, default=1)
    parser.add_argument("--crop_size", type=int, nargs='+', default=[512, 512], help='H, W')
    parser.add_argument("--information", type=str, default='RS')
    parser.add_argument("--models", type=str, default='danet',
                        choices=['danet', 'bisenetv2', 'pspnet', 'segbase', 'resT',
                                 'swinT', 'deeplabv3', 'fcn', 'fpn', 'unet'])
    parser.add_argument("--head", type=str, default='seghead')
    parser.add_argument("--seed", type=int, default=6)
    parser.add_argument("--save_dir", type=str, default='./work_dir')
    parser.add_argument("--use_edge", type=int, default=0)
    parser.add_argument("--use_mixup", type=int, default=0)
    parser.add_argument("--local_rank", type=int, default=0)
    parser.add_argument('opts',
                        help="Modify config options using the command-line",
                        default=None,
                        nargs=argparse.REMAINDER)
    args2 = parser.parse_args()
    return args2

def save_model_file(save_dir, save_name):
    save_dir = os.path.join(save_dir, save_name)
    if not os.path.exists(save_dir):
        os.makedirs(save_dir + '/weights/')
        os.makedirs(save_dir + '/outputs/')
    for file in os.listdir('.'):
        if os.path.isfile(file):
            shutil.copy(file, save_dir)
    if not os.path.exists(os.path.join(save_dir, 'models')):
        shutil.copytree('./models', os.path.join(save_dir, 'models'))
    logging.basicConfig(filename=save_dir + '/train.log', level=logging.INFO)

def train():

    """###############  Notice  ###############"""
    distributed = True
    args2 = parse_args()
    if distributed:
        torch.cuda.set_device(args2.local_rank)
        torch.distributed.init_process_group(
            backend="nccl", init_method="env://",
        )
    torch.manual_seed(args2.seed)
    torch.cuda.manual_seed(args2.seed)
    random.seed(args2.seed)
    np.random.seed(args2.seed)

    save_name = "{}_lr{}_epoch{}_batchsize{}_{}".format(args2.models, args2.lr, args2.end_epoch,
                                                        args2.train_batchsize * get_world_size(), args2.information)
    save_dir = args2.save_dir
    if args2.local_rank == 0:
        save_model_file(save_dir=save_dir, save_name=save_name)
    device = torch.device(('cuda:{}').format(args2.local_rank))

    model = get_model(args2, device, models=args2.models)
    potsdam_train = potsdam(train=True, dataset=args2.dataset, crop_szie=args2.crop_size)
    if distributed:
        train_sampler = DistributedSampler(potsdam_train)
    else:
        train_sampler = None
    dataloader_train = DataLoader(
        potsdam_train,
        batch_size=args2.train_batchsize,
        shuffle=True and train_sampler is None,
        num_workers=4,
        pin_memory=True,
        drop_last=True,
        sampler=train_sampler)

    potsdam_val = potsdam(train=False, dataset=args2.dataset, crop_szie=args2.crop_size)
    if distributed:
        val_sampler = DistributedSampler(potsdam_val)
    else:
        val_sampler = None
    dataloader_val = DataLoader(
        potsdam_val,
        batch_size=args2.val_batchsize,
        shuffle=False,
        num_workers=4,
        pin_memory=True,
        sampler=val_sampler)

    # optimizer = torch.optim.SGD([{'params':
    #                                   filter(lambda p: p.requires_grad,
    #                                          model.parameters()),
    #                                   'lr': args2.lr}],
    #                                 lr=args2.lr,
    #                                 momentum=0.9,
    #                                 weight_decay=0.0005,
    #                                 nesterov=False,
    #                                 )

    optimizer = torch.optim.AdamW([{'params':
                                      filter(lambda p: p.requires_grad,
                                             model.parameters()),
                                  'lr': args2.lr}],
                                lr=args2.lr,
                                betas=(0.9, 0.999),
                                weight_decay=0.01,
                                )

    start = time.time()
    miou = 0
    acc = 0
    f1 = 0
    precision = 0
    recall = 0
    best_miou = 0
    best_acc = 0
    best_f1 = 0
    last_epoch = 0
    test_epoch = args2.end_epoch - 3
    ave_loss = AverageMeter()
    world_size = get_world_size()

    weight_save_dir = os.path.join(save_dir, save_name + '/weights')
    model_state_file = weight_save_dir + "/{}_lr{}_epoch{}_batchsize{}_{}.pkl.tar" \
        .format(args2.models, args2.lr, args2.end_epoch, args2.train_batchsize * world_size, args2.information)
    if os.path.isfile(model_state_file):
        print('loaded successfully')
        logging.info("=> loading checkpoint '{}'".format(model_state_file))
        checkpoint = torch.load(model_state_file, map_location=lambda storage, loc: storage)
        checkpoint = {k: v for k, v in checkpoint.items() if not 'loss' in k}
        best_miou = checkpoint['best_miou']
        best_acc = checkpoint['best_acc']
        best_f1 = checkpoint['best_f1']
        last_epoch = checkpoint['epoch']
        model.load_state_dict(checkpoint['state_dict'])
        optimizer.load_state_dict(checkpoint['optimizer'])
        logging.info("=> loaded checkpoint '{}' (epoch {})".format(
           model_state_file, checkpoint['epoch']))

    for epoch in range(last_epoch, args2.end_epoch):
        if distributed:
            train_sampler.set_epoch(epoch)
        model.train()
        setproctitle.setproctitle("xzy:" + str(epoch) + "/" + "{}".format(args2.end_epoch))

        for i, sample in enumerate(dataloader_train):
            image, label = sample['image'], sample['label']
            image, label = image.to(device), label.to(device)
            label = label.long().squeeze(1)
            losses = model(image, label)

            loss = losses.mean()
            ave_loss.update(loss.item())

            lenth_iter = len(dataloader_train)
            lr = adjust_learning_rate(optimizer,
                                      args2.lr,
                                      args2.end_epoch * lenth_iter,
                                      i + epoch * lenth_iter,
                                      args2.warm_epochs * lenth_iter
                                      )

            if i % 50 == 0:
                reduced_loss = ave_loss.average()
                print_loss = reduce_tensor(torch.from_numpy(np.array(reduced_loss)).to(device)).cpu() / world_size
                print_loss = print_loss.item()

                if args2.local_rank == 0:

                    time_cost = time.time() - start
                    start = time.time()
                    print("epoch:[{}/{}], iter:[{}/{}], loss:{:.4f}, time:{:.4f}, lr:{:.4f}, "
                          "best_miou:{:.4f}, miou:{:.4f}, acc:{:.4f}, f1:{:.4f}, precision:{:.4f}, recall:{:.4f}".
                          format(epoch,args2.end_epoch,i,len(dataloader_train),print_loss,time_cost,lr,
                                 best_miou,miou, acc, f1, precision, recall))
                    logging.info(
                        "epoch:[{}/{}], iter:[{}/{}], loss:{:.4f}, time:{:.4f}, lr:{:.4f}, "
                        "best_miou:{:.4f}, miou:{:.4f}, acc:{:.4f}, f1:{:.4f}, precision:{:.4f}, recall:{:.4f}".
                            format(epoch, args2.end_epoch, i, len(dataloader_train), print_loss, time_cost, lr,
                                   best_miou, miou, acc, f1, precision, recall))
            model.zero_grad()
            loss.backward()
            optimizer.step()

        if epoch > test_epoch:
            miou, acc, f1, precision, recall = validate(dataloader_val, device, model, args2)
            miou = (reduce_tensor(miou).cpu() / world_size).item()
            acc = (reduce_tensor(acc).cpu() / world_size).item()
            f1 = (reduce_tensor(f1).cpu() / world_size).item()
            precision = (reduce_tensor(precision).cpu() / world_size).item()
            recall = (reduce_tensor(recall).cpu() / world_size).item()

        if args2.local_rank == 0:
            if epoch > test_epoch and epoch != 0:
                print('miou:{}, acc:{}, f1:{}, precision:{}, recall:{}'.format(miou, acc, f1, precision, recall))
                torch.save(model.state_dict(),
                           weight_save_dir + '/{}_lr{}_epoch{}_batchsize{}_{}_xzy_{}.pkl'
                           .format(args2.models, args2.lr, args2.end_epoch, args2.train_batchsize * world_size, args2.information, epoch))

            if miou >= best_miou and miou != 0:
                best_miou = miou
                best_acc, best_f1 = acc, f1
                best_weight_name = weight_save_dir + '/{}_lr{}_epoch{}_batchsize{}_{}_best_epoch_{}.pkl'.format(
                    args2.models, args2.lr, args2.end_epoch, args2.train_batchsize * world_size, args2.information, epoch)
                torch.save(model.state_dict(), best_weight_name)
                torch.save(model.state_dict(), weight_save_dir + '/best_weight.pkl')

            torch.save({
                'epoch': epoch + 1,
                'best_miou': best_miou,
                'best_acc': best_acc,
                'best_f1':best_f1,
                'state_dict': model.state_dict(),
                'optimizer': optimizer.state_dict(),
            }, weight_save_dir + '/{}_lr{}_epoch{}_batchsize{}_{}.pkl.tar'
                .format(args2.models, args2.lr, args2.end_epoch, args2.train_batchsize * world_size, args2.information))
    if args2.local_rank == 0:
        torch.save(model.state_dict(),
                       weight_save_dir + '/{}_lr{}_epoch{}_batchsize{}_{}_xzy_{}.pkl'
                   .format(args2.models, args2.lr, args2.end_epoch, args2.train_batchsize * world_size, args2.information, args2.end_epoch))
        try:
            print("epoch:[{}/{}], iter:[{}/{}], loss:{:.4f}, time:{:.4f}, lr:{:.4f}, best_miou:{:.4f}, "
                  "miou:{:.4f}, acc:{:.4f} f1:{:.4f}, precision:{:.4f}, recall:{:.4f}".
                  format(epoch, args2.end_epoch, i, len(dataloader_train),
                         print_loss, time_cost, lr, best_miou, miou, acc, f1, precision, recall))
            logging.info(
                "epoch:[{}/{}], iter:[{}/{}], loss:{:.4f}, time:{:.4f}, lr:{:.4f}, best_miou:{:.4f}, "
                  "miou:{:.4f}, acc:{:.4f} f1:{:.4f}, precision:{:.4f}, recall:{:.4f}".
                    format(epoch, args2.end_epoch, i, len(dataloader_train),
                           print_loss, time_cost, lr, best_miou, miou, acc, f1, precision, recall))
        except:
            pass

        logging.info("***************super param*****************")
        logging.info("dataset:{} information:{} lr:{} epoch:{} batchsize:{} best_miou:{} best_acc:{} best_f1:{}"
                     .format(args2.dataset, args2.information, args2.lr, args2.end_epoch, args2.train_batchsize *
                             world_size, best_miou, best_acc, best_f1))
        logging.info("***************end*************************")

        print("***************super param*****************")
        print("dataset:{} information:{} lr:{} epoch:{} batchsize:{} best_miou:{} best_acc:{} best_f1:{}"
              .format(args2.dataset, args2.information, args2.lr, args2.end_epoch, args2.train_batchsize * world_size,
                      best_miou, best_acc, best_f1))
        print("***************end*************************")

def adjust_learning_rate(optimizer, base_lr, max_iters,
        cur_iters, warmup_iter=None, power=0.9):
    if warmup_iter is not None and cur_iters < warmup_iter:
        lr = base_lr * cur_iters / (warmup_iter + 1e-8)
    elif warmup_iter is not None:
        lr = base_lr*((1-float(cur_iters - warmup_iter) / (max_iters - warmup_iter))**(power))
    else:
        lr = base_lr * ((1 - float(cur_iters / max_iters)) ** (power))
    optimizer.param_groups[0]['lr'] = lr
    return lr

def validate(dataloader_val, device, model, args2):
    model.eval()
    MIOU = [0]
    ACC = [0]
    F1 = [0]
    Precision = [0]
    Recall = [0]
    nclass = 6
    metric = SegmentationMetric(nclass)
    with torch.no_grad():
        for i, sample in enumerate(dataloader_val):
            image, label = sample['image'], sample['label']
            image, label = image.to(device), label.to(device)
            label = label.long().squeeze(1)
            logit = model(image, label, train=False)
            logit = logit.argmax(dim=1)
            logit = logit.cpu().detach().numpy()
            label = label.cpu().detach().numpy()
            metric.addBatch(logit, label)

    iou = metric.IntersectionOverUnion()
    acc = metric.Accuracy()
    precision = metric.Precision()
    recall = metric.Recall()
    miou = np.nanmean(iou[0:5])
    mprecision = np.nanmean(precision[0:5])
    mrecall = np.nanmean(recall[0:5])

    MIOU = MIOU + miou
    ACC = ACC + acc
    Recall = Recall + mrecall
    Precision = Precision + mprecision
    F1 = F1 + 2 * Precision * Recall / (Precision + Recall)

    MIOU = torch.from_numpy(MIOU).to(device)
    ACC = torch.from_numpy(ACC).to(device)
    F1 = torch.from_numpy(F1).to(device)
    Recall = torch.from_numpy(Recall).to(device)
    Precision = torch.from_numpy(Precision).to(device)

    return MIOU, ACC, F1, Precision, Recall

if __name__ == '__main__':

    # os.environ["CUDA_VISIBLE_DEVICES"] = "0,1,2,3"
    # os.environ.setdefault('RANK', '0')
    # os.environ.setdefault('WORLD_SIZE', '1')
    # os.environ.setdefault('MASTER_ADDR', '127.0.0.1')
    # os.environ.setdefault('MASTER_PORT', '29556')

    cudnn.benchmark = True
    cudnn.enabled = True

    # don't use cudnn
    #cudnn.benchmark = False
    #cudnn.deterministic = True

    train()


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

import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 350, 100)
        self.setWindowTitle('Drawing rectangles')
        self.show()

    # 绘图是在paintEvent()方法中完成。
    # QPainter 对象放在begin()方法和end()方法之间，它执行部件上的低层次的绘画和其他绘图设备。
    # 实际的绘画我们委托给drawText()方法。
    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        self.drawRectangles(event, painter)
        painter.end()

    def drawRectangles(self, event, painter):
        color = QColor(0, 0, 0)
        color.setNamedColor('#d4d4d4')
        painter.setPen(color)

        painter.setBrush(QColor(200, 0, 0))
        painter.drawRect(10, 15, 90, 60)

        painter.setBrush(QColor(255, 80, 0, 160))
        painter.drawRect(130, 15, 90, 60)

        painter.setBrush(QColor(25, 0, 90, 200))
        painter.drawRect(250, 15, 90, 60)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MainWindow()
    sys.exit(app.exec_())


from typing import Dict, Callable

from src.dialog.common.manage_entity.ManageEntityDialogMode import ManageEntityDialogMode
from src.property.Property import Property
from src.session.common.Session import Session
from src.storage.common.entity.Entity import Entity
from src.storage.common.entity.EntityStorage import EntityStorage

class ManageEntityContainerSaver:

    def __init__(
            self,
            session: Session,
            storage: EntityStorage,
            close_dialog: Callable[[], None],
            show_error: Callable[[str], None]
    ):
        self.__session = session
        self.__storage = storage
        self.__close_dialog = close_dialog
        self.__show_error = show_error

    def save_entity(self, key: str, props: Dict[str, Property]):
        if self.__session.get_manage_entity_mode() == ManageEntityDialogMode.CREATE:
            self.handle_new_entity(key, props)
        elif self.__session.get_manage_entity_mode() == ManageEntityDialogMode.EDIT and \
                self.__session.get_edit_entity_key() != key:
            self.handle_edit_entity_key_changed(key, props)
        elif self.__session.get_manage_entity_mode() == ManageEntityDialogMode.EDIT and \
                self.__session.get_edit_entity_key() == key:
            self.handle_edit_entity_key_unchanged(key, props)

    def handle_new_entity(self, key: str, props: Dict[str, Property]):
        if not self.__storage.check_entity_exists(key):
            self.put_entity_close_dialog(key, props)
        else:
            self.report_entity_exists(key)

    def handle_edit_entity_key_changed(self, key: str, props: Dict[str, Property]):
        if not self.__storage.check_entity_exists(key):
            self.remove_session_entity()
            self.put_entity_close_dialog(key, props)
        else:
            self.report_entity_exists(key)

    def handle_edit_entity_key_unchanged(self, key: str, props: Dict[str, Property]):
        self.put_entity_close_dialog(key, props)

    def put_entity_close_dialog(self, key: str, props: Dict[str, Property]):
        self.__storage.put_entity(
            Entity(key, props)
        )
        self.__close_dialog()

    def remove_session_entity(self):
        self.__storage.remove_entity(self.__session.get_edit_entity_key())

    def report_entity_exists(self, key: str):
        self.__show_error("Дело об АП с номером" + key + " уже существует")