## import ##
## openCV ##
import cv2
import numpy as np
import pandas as pd
import pylab as pl
import os
import glob
import ntpath
import xlrd
from matplotlib import pyplot as plt
from PIL import Image

## PyWavelet ##
import pywt

from skimage import io
from sklearn import datasets, svm
from sklearn.feature_selection import SelectPercentile, f_classif ,SelectKBest, f_regression, SelectFromModel
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn import preprocessing
from sklearn.pipeline import make_pipeline
from sklearn.metrics import classification_report

# Importing the Keras libraries and packages
import keras
from keras.models import Sequential
from keras.layers import Dense
# Making the Confusion Matrix
from sklearn.metrics import confusion_matrix

## Scipy ##
from scipy import stats

def loadImagesFromFolder(folder):
	images = []
	fileName = []
	for filename in glob.glob(folder):
		# img = np.float32(cv2.imread(filename))
		img = io.imread(filename)
		if img is not None:
			images.append(img)
			# name = ntpath.basename(filename).split("_")
			# fileName.append(name[0])
			fileName.append(ntpath.basename(filename))
			# print(filename)
	return images , fileName

def img_to_matrix(img, verbose=False):
	"""
	takes a filename and turns it into a numpy array of RGB pixels
	"""
	widthBase = 700.0 / img.shape[1]
	dim = (700, int(img.shape[0] * widthBase))
	img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
	# STANDARD_SIZE = (300, 167)
	# img = Image.open(filename)
	# if verbose==True:
		# print "changing size from %s to %s" % (str(img.size), str(STANDARD_SIZE))
	# img = img.resize(STANDARD_SIZE)
	# img = list(img)
	# img = map(list, img)
	img = np.array(img)
	# img2 = np.asarray(img)

	# print (img)
	# plt.imshow(img)
	# plt.show()
	return img

def flatten_image(data):
	"""
	takes in an (m, n) numpy array and flattens it
	into an array of shape (1, m * n)
	"""
	# print(img.shape[0])
	# print(img.shape[1])
	# cv2.imshow('image',img)
	# gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
	# plt.imshow(gray)
	# plt.show()
	# X_normalized = preprocessing.normalize(img, norm='l2')

	# s = img.shape[0] * img.shape[1]
	# img_wide = img.reshape((1, s,-1))
	# img_wide = np.rollaxis(X_normalized, axis=1, start=0)
	# plt.imshow(img_wide[0])
	# plt.show()
	# print(X_normalized)
	nsamples, nx, ny = data.shape
	d2_train_dataset = data.reshape((nsamples,nx*ny))
	return d2_train_dataset

def svmTraining(img) :
	cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]

	# First half is trainData, remaining is testData
	train_cells = [ i[:50] for i in cells ]
	test_cells = [ i[50:] for i in cells]

	######     Now training      ########################

	deskewed = [map(deskew,row) for row in train_cells]
	hogdata = [map(hog,row) for row in deskewed]
	trainData = np.float32(hogdata).reshape(-1,64)
	responses = np.float32(np.repeat(np.arange(10),250)[:,np.newaxis])

	svm = cv2.SVM()
	svm.train(trainData,responses, params=svm_params)
	svm.save('svm_data.dat')

	######     Now testing      ########################

	deskewed = [map(deskew,row) for row in test_cells]
	hogdata = [map(hog,row) for row in deskewed]
	testData = np.float32(hogdata).reshape(-1,bin_n*4)
	result = svm.predict_all(testData)

	#######   Check Accuracy   ########################
	mask = result==responses
	correct = np.count_nonzero(mask)
	print (correct*100.0/result.size)

def cornerDetect(img):
	gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
	corners = cv2.goodFeaturesToTrack(gray,20,0.01,10)
	corners = np.int0(corners)

	for i in corners:
		x,y = i.ravel()
		cv2.circle(img,(x,y),3,255,-1)

	# plt.imshow(img)
	# plt.show()
	# cv2.waitKey(1)
	return corners

def getTrainingData():
	address = "G:/My Drive/ICTES/Thesis/Code/od_roi/DataMining/training"
	labels = []
	trainingData = []
	for items in os.listdir(address):
		## extracts labels
		name = address + "/" + items
		print (items)
		for it in os.listdir(name):
			path = name + "/" + it
			print (path)
			img = cv.imread(path, cv.CV_LOAD_IMAGE_GRAYSCALE)
			d = np.array(img, dtype = np.float32)
			q = d.flatten()
			trainingData.append(q)
			labels.append(items)
			######DEBUG######

			#cv.namedWindow(path,cv.WINDOW_NORMAL)
			#cv.imshow(path,img)

	return trainingData, labels

# def pca(X):
	# # Principal Component Analysis
	# # input: X, matrix with training data as flattened arrays in rows
	# # return: projection matrix (with important dimensions first),
	# # variance and mean

	# #get dimensions
	# num_data,dim = X.shape

	# #center data
	# mean_X = X.mean(axis=0)
	# for i in range(num_data):
		# X[i] -= mean_X
	# X = X.reshape(-1, 3)

	# if dim>100:
		# print ('PCA - compact trick used')
		# M = np.dot(X,X.T) #covariance matrix
		# e,EV = np.linalg.eigh(M) #eigenvalues and eigenvectors
		# tmp = np.dot(X.T,EV).T #this is the compact trick
		# V = tmp[::-1] #reverse since last eigenvectors are the ones we want
		# # print(EV)
		# S = np.sqrt(e)[::-1] #reverse since eigenvalues are in increasing order
	# else:
		# print ('PCA - SVD used')
		# U,S,V = np.linalg.svd(X)
		# V = V[:num_data] #only makes sense to return the first num_data

	# #return the projection matrix, the variance and the mean
	# return V,S,mean_X

def PCAs(X_train, X_test, components):
	# pca = PCA(n_components=components, svd_solver='randomized')
	pca = PCA(n_components=components)
	train_x = pca.fit_transform(X_train)
	test_x = pca.transform(X_test)
	print("pca coeffs")
	print (train_x)
	print (test_x)
	# df = pd.DataFrame({"x": test_x[:, 0], "y": test_x[:, 1], "label":np.where(Y_test==1, "Glaucoma test", "Normal test")})
	# colors = ["blue", "green"]
	# for label, color in zip(df['label'].unique(), colors):
	# mask = df['label']==label
	# pl.scatter(df[mask]['x'], df[mask]['y'], c=color, label=label)
	# pl.legend()
	# pl.show()
	# io.imshow(train_x)
	# plt.show()

	return train_x , test_x

def KNN(train_x, test_x, train_y, test_y, kernels):
	target_names = ['Normal', 'Glaucoma']
	knn = KNeighborsClassifier(kernels)
	knn.fit(train_x, train_y)
	y_pred = knn.predict(test_x)
	print("KNN")
	# print(pd.crosstab(test_y, knn.predict(test_x), rownames=["Actual"], colnames=["Predicted"]))
	print(classification_report(test_y, y_pred,target_names=target_names))
	print("label test_x")
	print(test_y)
	print("predict test_x")
	print(knn.predict(test_x))

def SVM(train_x, test_x, train_y, test_y, kernels):
	# ANOVA SVM-C
	# 1) anova filter, take 3 best ranked features
	anova_filter = SelectKBest(f_regression, k=kernels)
	# 2) svm
	clf = svm.SVC(kernel='linear')

	anova_svm = make_pipeline(anova_filter, clf)
	anova_svm.fit(train_x, train_y)
	# clf.fit(train_x, Y_train)
	y_pred = anova_svm.predict(test_x)
	target_names = ['Normal', 'Glaucoma']
	print("SVM")
	print(classification_report(test_y, y_pred,target_names=target_names))
	print("label test_x")
	print(test_y)
	print("predict test_x")
	print(y_pred)

def Wavelet(data):
	coeffs = pywt.dwt2(data, 'sym3')
	cA, (cH, cV, cD) = coeffs

	cA, cD = pywt.dwt(data, 'sym3')

	# wp = pywt.WaveletPacket2D(data=train_x, wavelet='sym3', mode='symmetric')
	# print(wp['va'].data)
	# print([node.path for node in wp.get_level(2)])
	re = pywt.idwt2(coeffs, 'sym3')
	print(re)

	## plot ##
	# plt.figure(1)
	# plt.subplot(211)
	# plt.plot(data)
	# plt.title('input')
	# plt.subplot(212)
	# plt.plot(re)
	# plt.title('reconstructs')
	# plt.show()
	# plt.imshow(re)
	# plt.show()
	# print(train_cA)
	# print(train_cV)
	# print(train_cD)
	return re

# def Wavelet_avg(data,ans):
	# coeffs = pywt.dwt2(data, 'sym3')
	# cA, (cH, cV, cD) = coeffs

	# # cA, cD = pywt.dwt(data, 'sym3')

	# # wp = pywt.WaveletPacket2D(data=train_x, wavelet='sym3', mode='symmetric')
	# # print(wp['va'].data)
	# # print([node.path for node in wp.get_level(2)])
	# # re = pywt.idwt2(coeffs, 'sym3')
	# # print(re)

	# # print(cH.shape)
	# # print(data.shape)
	# p , q = data.shape
	# avg_cH = sum(abs(cH))/p*q
	# avg_cV = sum(abs(cV))/p*q
	# avg_cD = sum(abs(cD))/p*q

	# enegy =  pow(sum(abs(cV)),2)/pow(p*q,2)

	# # print("avg_cH")
	# # # print(avg_cH)
	# # print(avg_cH.shape)

	# # print("avg_cV")
	# # # print(avg_cV)
	# # print(avg_cV.shape)

	# # print("enegy")
	# # # print(enegy)
	# # print(enegy.shape)

	# ans_return = {
	# 'cH': avg_cH,
	# 'cV': avg_cV,
	# 'cD': avg_cD,
	# 'enegy': enegy}[ans]

	# return ans_return

def Wavelet_avg(data):
	## db3 ##
	sum_cH_db3 = 0
	sum_cV_db3 = 0
	sum_cD_db3 = 0

	coeffs_db3 = pywt.dwt2(data, 'db3')
	cA_db3, (cH_db3, cV_db3, cD_db3) = coeffs_db3

	p , q = cH_db3.shape
	for x in range(0,p):
		for y in range(0,q):
			sum_cH_db3 += abs(cH_db3[x][y])
			sum_cV_db3 += abs(cV_db3[x][y])
			sum_cD_db3 += abs(cD_db3[x][y])

	avg_cH_db3 = sum_cH_db3/p*q
	avg_cV_db3 = sum_cV_db3/p*q
	avg_cD_db3 = sum_cD_db3/p*q

	enegy_cH_db3 =  pow(sum_cH_db3,2)/pow(p*q,2)
	enegy_cV_db3 =  pow(sum_cV_db3,2)/pow(p*q,2)
	enegy_cD_db3 =  pow(sum_cD_db3,2)/pow(p*q,2)

	## sym3 ##
	sum_cH_sym3 = 0
	sum_cV_sym3 = 0
	sum_cD_sym3 = 0

	coeffs_sym3 = pywt.dwt2(data, 'sym3')
	cA_sym3, (cH_sym3, cV_sym3, cD_sym3) = coeffs_sym3

	p , q = cH_sym3.shape
	for x in range(0,p):
		for y in range(0,q):
			sum_cH_sym3 += abs(cH_sym3[x][y])
			sum_cV_sym3 += abs(cV_sym3[x][y])
			sum_cD_sym3 += abs(cD_sym3[x][y])
	# print(sum_cH)
	# print(sum_cV)
	# print(sum_cD)
	avg_cH_sym3 = sum_cH_sym3/p*q
	avg_cV_sym3 = sum_cV_sym3/p*q
	avg_cD_sym3 = sum_cD_sym3/p*q

	enegy_cH_sym3 =  pow(sum_cH_sym3,2)/pow(p*q,2)
	enegy_cV_sym3 =  pow(sum_cV_sym3,2)/pow(p*q,2)
	enegy_cD_sym3 =  pow(sum_cD_sym3,2)/pow(p*q,2)

	## rbio3.3 ##
	sum_cH_rbio33 = 0
	sum_cV_rbio33 = 0
	sum_cD_rbio33 = 0

	coeffs_rbio33 = pywt.dwt2(data, 'rbio3.3')
	cA_rbio33, (cH_rbio33, cV_rbio33, cD_rbio33) = coeffs_rbio33

	p , q = cH_rbio33.shape
	for x in range(0,p):
		for y in range(0,q):
			sum_cH_rbio33 += abs(cH_rbio33[x][y])
			sum_cV_rbio33 += abs(cV_rbio33[x][y])
			sum_cD_rbio33 += abs(cD_rbio33[x][y])

	avg_cH_rbio33 = sum_cH_rbio33/p*q
	avg_cV_rbio33 = sum_cV_rbio33/p*q
	avg_cD_rbio33 = sum_cD_rbio33/p*q

	enegy_cH_rbio33 =  pow(sum_cH_rbio33,2)/pow(p*q,2)
	enegy_cV_rbio33 =  pow(sum_cV_rbio33,2)/pow(p*q,2)
	enegy_cD_rbio33 =  pow(sum_cD_rbio33,2)/pow(p*q,2)

	## rbio3.5 ##
	sum_cH_rbio35 = 0
	sum_cV_rbio35 = 0
	sum_cD_rbio35 = 0

	coeffs_rbio35 = pywt.dwt2(data, 'rbio3.5')
	cA_rbio35, (cH_rbio35, cV_rbio35, cD_rbio35) = coeffs_rbio35

	p , q = cH_rbio35.shape
	for x in range(0,p):
		for y in range(0,q):
			sum_cH_rbio35 += abs(cH_rbio35[x][y])
			sum_cV_rbio35 += abs(cV_rbio35[x][y])
			sum_cD_rbio35 += abs(cD_rbio35[x][y])

	avg_cH_rbio35 = sum_cH_rbio35/p*q
	avg_cV_rbio35 = sum_cV_rbio35/p*q
	avg_cD_rbio35 = sum_cD_rbio35/p*q

	enegy_cH_rbio35 =  pow(sum_cH_rbio35,2)/pow(p*q,2)
	enegy_cV_rbio35 =  pow(sum_cV_rbio35,2)/pow(p*q,2)
	enegy_cD_rbio35 =  pow(sum_cD_rbio35,2)/pow(p*q,2)

	## rbio3.7 ##
	sum_cH_rbio37 = 0
	sum_cV_rbio37 = 0
	sum_cD_rbio37 = 0

	coeffs_rbio37 = pywt.dwt2(data, 'rbio3.7')
	cA_rbio37, (cH_rbio37, cV_rbio37, cD_rbio37) = coeffs_rbio35

	p , q = cH_rbio37.shape
	for x in range(0,p):
		for y in range(0,q):
			sum_cH_rbio37 += abs(cH_rbio37[x][y])
			sum_cV_rbio37 += abs(cV_rbio37[x][y])
			sum_cD_rbio37 += abs(cD_rbio37[x][y])

	avg_cH_rbio37 = sum_cH_rbio37/p*q
	avg_cV_rbio37 = sum_cV_rbio37/p*q
	avg_cD_rbio37 = sum_cD_rbio37/p*q

	enegy_cH_rbio37 =  pow(sum_cH_rbio37,2)/pow(p*q,2)
	enegy_cV_rbio37 =  pow(sum_cV_rbio37,2)/pow(p*q,2)
	enegy_cD_rbio37 =  pow(sum_cD_rbio37,2)/pow(p*q,2)

	# enegy =  np.sqrt(np.sum(np.array(coeffs[cD]) ** 2)) / len(coeffs[-k])

	# print("avg_cH")
	# # print(avg_cH)
	# print(avg_cH)

	# print("avg_cV")
	# # print(avg_cV)
	# print(avg_cV)

	# print("enegy")
	# # print(enegy)
	# print(enegy)

	# avg_all_cH = np.array([avg_cH_db3,avg_cH_sym3,avg_cH_rbio33,avg_cH_rbio35,avg_cH_rbio37])
	# ans_zscroce = stats.zscore(avg_all_cH)
	ans_return = np.array([avg_cH_db3,
	enegy_cV_db3,
	avg_cH_sym3,
	enegy_cV_sym3,
	avg_cH_rbio33,
	enegy_cV_rbio33,
	enegy_cD_rbio33,
	avg_cH_rbio35,
	enegy_cV_rbio35,
	enegy_cD_rbio35,
	avg_cH_rbio37,
	enegy_cH_rbio37,
	enegy_cV_rbio37,
	enegy_cD_rbio37])
	# ans_return = {
	# 'cH': avg_cH,
	# 'cV': avg_cV,
	# 'cD': avg_cD,
	# 'enegy': enegy}[ans]
	# df = (ans_return - ans_return.mean())/ans_return.std(ddof=0)
	# ans_zscroce = stats.zscore(ans_return)
	# print(ans_return)
	# print(ans_zscroce)
	# print(df)

	return ans_return

def ann(train_x, test_x, train_y, test_y,input):
	# Initialising the ANN
	classifier = Sequential()

	# Adding the input layer and the first hidden layer
	classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu', input_dim = input))

	# Adding the second hidden layer
	classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu'))

	# Adding the output layer
	classifier.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))

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

	# Fitting the ANN to the Training set
	classifier.fit(train_x, train_y, batch_size = 10, epochs = 1000)

	# Part 3 - Making predictions and evaluating the model

	# Predicting the Test set results
	y_pred = classifier.predict(test_x)
	y_pred = (y_pred > 0.5)

	cm = confusion_matrix(test_y, y_pred)
	print(y_pred)
	# plt.plot(cm)
	# plt.show()

def Aj_ODdectiect(img,fileName):
	# b,g,r = cv2.split(img)

	p = 0.970

	width, height = img.shape
	num = width*height

	Y = np.ravel(img)
	Y = sorted(Y)

	top20 = int(round(p*len(Y)))
	threshold = Y[top20]

	print(threshold*100)

	indices = np.argwhere(img >= threshold)
	print ("indices : ",len(indices))
	Z = np.zeros((width,height,3), np.uint8)
	# print ("Z : ",Z.shape)

	for i in range(len(indices)) :
		# print ("i : ",indices[i])
		Z[indices[i][0],indices[i][1]] = (255,255,255)

	ZC = cv2.erode(Z,np.ones((3,3),np.uint8),iterations = 1)
	ZCE = cv2.morphologyEx(ZC, cv2.MORPH_CLOSE, np.ones((5,5),np.uint8))

	minX = np.min(indices[:,0])
	minY = np.min(indices[:,1])
	maxX = np.max(indices[:,0])
	maxY = np.max(indices[:,1])
	# print("minX",minX)
	# print("minY",minY)
	# print("maxX",maxX)
	# print("maxY",maxY)
	#print(ZCE)
	#cv2.imshow(fileName, ZCE)
	ret,th1 = cv2.threshold(img,threshold,255,cv2.THRESH_BINARY)
	# cv2.imshow(fileName, th1)
	# print(th1)
	return th1

## import image ##
# address = "..//ICTES//Thesis//Code//od_roi//DataMining//training"
imgs , fileName = loadImagesFromFolder('G:/My Drive/ICTES/Thesis/Code/od_roi/DataMining/training/*jpg')
book = xlrd.open_workbook('G:/My Drive/ICTES/Thesis/Code/od_roi/DataMining/BiomisaData.xlsx')
sheet = book.sheet_by_name('all')

fileData = [[sheet.cell_value(r, c) for c in range(sheet.ncols)] for r in range(sheet.nrows)]
trainData = []
train_w_cH = []
test_w_cH = []
data = []
target = []

i = 0
for image in imgs:
	# cv2.imshow('image',image)
	# ## split BGR layer ##
	b,g,r = cv2.split(image)
	gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
	# img = img_to_matrix(r)
	# img = flatten_image(r)
	# X_normalized = preprocessing.normalize(g, norm='l1', axis=0)
	X_normalized = preprocessing.normalize(g, norm='l2')
	# io.imshow(X_normalized)
	# plt.show()
	print("X_normalized data")
	print (g)
	print (X_normalized)

	data.append(X_normalized)

	name = fileName[i].split(".")
	name2 = name[0].split("_")
	if name2[3] == "g":
		target.append(1)
		print(name2[3])
	else:
		target.append(0)
		print(name2[3])

	## send normalization image to optic detection ##
	# trainData.append(cornerDetect(image))
	trainData.append(Aj_ODdectiect(X_normalized,fileName[i]))

	i+=1
# training, labels = getTrainingData()

# data = np.ravel(trainData)

y  = np.array(target)
# labelsMat  = np.array(fileData[1:])
data = np.array(trainData)
# print (data)
print (y)

## split into training and test part ##
# labelsMatData = labelsMat[:,1].ravel()
# is_train = np.random.uniform(0, 1, len(data)) <= 0.8
# y = np.where(np.array(labelsMatData)=="Glaucoma", 1, 0)
X_train, X_test, Y_train, Y_test = train_test_split(data, y, test_size = 0.2)
print("X_train data")
print (X_train)

d2_train_dataset = flatten_image(X_train)
d2_test_dataset = flatten_image(X_test)
# print("2D data")
# print (d2_train_dataset)
# print (Y_train)
# print (Y_test)
# plt.imshow(data)
# plt.show()

# x_train, y_train = data[is_train], y[is_train]
# x_test, y_test = data[is_train==False], y[is_train==False]
# print("data")
# print (x_train)
# print (y_train)
# print (y_test)

train_y, test_y = Y_train, Y_test

## pca ##
# V,S,mean_X = pca(X_train)
# print("V")
# print(V)
# print("S")
# print(S)
# print("mean_X")
# print(mean_X)

train_x , test_x = PCAs(d2_train_dataset,d2_test_dataset,7)

## wavelet ##
for train_dataset in X_train:
	# print("train_dataset")
	# print(train_dataset)
	# train_w_cH.append(Wavelet_avg(train_dataset,'enegy'))
	train_w_cH.append(Wavelet_avg(train_dataset))

for test_dataset in X_test:
	# print("test_dataset")
	# print(test_dataset)
	# test_w_cH.append(Wavelet_avg(test_dataset,'enegy'))
	test_w_cH.append(Wavelet_avg(test_dataset))

# print("train_w_cH")
# print(train_w_cH)
train_w = stats.zscore(train_w_cH)
# train_w = Wavelet(d2_train_dataset)
test_w = stats.zscore(test_w_cH)
# test_w = Wavelet(d2_test_dataset)
# train_w = np.array(train_w)
# test_w = np.array(test_w)
# print("wavelet")
# print(test_w)

## KNN ##
print("pca")
KNN(train_x , test_x, train_y, test_y, 3)
print("wavelet")
KNN(train_w , test_w, train_y, test_y, 3)

############################
## SVM ##
print("pca")
SVM(train_x , test_x, train_y, test_y, 3)
print("wavelet")
SVM(train_w , test_w, train_y, test_y, 3)

############################
## ANN ##
# print("pca")
# ann(train_x , test_x, train_y, test_y, 5)
# print("wavelet")
# ann(train_w , test_w, train_y, test_y, 352)
cv2.waitKey(0)


import torch
import torch.nn as nn
import torch.nn.functional as F

class DICELoss(nn.Module):
    #DICE Loss Function

    def __init__(self, weights):
        #weights(tensor): weights for every class when calculating dice loss
        super(DICELoss, self).__init__()
        self.weights = weights

    def forward(self, scores, target):
        """DICE Loss
        Args:
            scores (tensor):  Predicted scores for every class on the image,
                shape: [batch_size,num_classes,w,h]
            targets (tensor): Ground truth labels,
                shape: [batch_size,]
        """
        scores = F.softmax(scores, dim=1)
        number_of_classes = scores.shape[1]
        target_one_hot = torch.zeros_like(scores)
        target_one_hot.scatter_(1, target.view(scores.shape[0],1,scores.shape[2],scores.shape[3]), 1)
        smooth = 1e-7
        loss = 0
        for cl in range(number_of_classes):
            iflat = scores[:,cl,:,:].contiguous().view(-1)
            tflat = target_one_hot[:,cl,:,:].contiguous().view(-1)
            intersection = (iflat * tflat).sum()
            loss += (1 - ((2. * intersection) / (iflat.sum() + tflat.sum() + smooth)))*self.weights[cl]
        return loss/self.weights.sum(), scores, target_one_hot

def label_accuracy(probas, true_1_hot):
    """Computes the accuracy.
    Args:
        probas: a tensor of shape [B, C, H, W] of probabilities
        true_1_hot: a tensor of shape [B, C, H, W]. Corresponds to the true label
    Returns:
        tp: [C] true positive of c classes
        fp: [C] false positive
        fn: [C] false negative
    """
    num_class = probas.shape[1]
    num_batch = probas.shape[0]

    pred = torch.max(probas,dim=1)[1]
    pred_1_hot = torch.eye(num_class)[pred.squeeze(1)]
    pred_1_hot = pred_1_hot.permute(0, 3, 1, 2).float()

    # sum all except class axis
    tp = torch.mul(pred_1_hot, true_1_hot).sum(dim=3).sum(dim=2).sum(dim=0)
    fp = pred_1_hot.sum(dim=3).sum(dim=2).sum(dim=0) - tp
    fn = true_1_hot.sum(dim=3).sum(dim=2).sum(dim=0) - tp

    return tp, fp, fn

if __name__ == "__main__":
    x = torch.rand([1,3,2,2])
    gt = torch.tensor([[[1,2],[2,0]]])
    weights = torch.tensor([1.0,1,1])
    DICE = DICELoss(weights)
    print(diceloss(x, gt)[0])#, diceloss(x, gt)[1], diceloss(x, gt)[2])
    print(DICE(x, gt)[0])#, DICE(x, gt)[1], DICE(x, gt)[2])
# # test functions
# x = torch.tensor([[[0.1,0.2],[0.3,0.4]],[[0.2,0.3],[0.3,0.4]],[[0.3,0.4],[0.4,0.5]]]).reshape(1,3,2,2)
# print('x\n',x)
# gt = torch.tensor([[[1,2],[2,0]]])
# print('gt\n',gt)
# loss,probas,true_1_hot = dice_loss(x,gt.squeeze(1))
# print ('loss\n',loss)
# print('probability\n',probas)
# print('true_1_hot\n',true_1_hot)
# tp, fp,fn = label_accuracy(probas,true_1_hot)
# print('tp\n',tp)
# print('fp\n',fp)
# print('fn\n',fn)


class Employee:
    def __init__(self, fun):
        self.emp = []
        self.f = -1
        self.g = -1
        self.fun = fun

# g(i) - najlepsza impreza, na którą i nie idzie
# f(i) - najlepsza impreza zrobiona z i i wszystkich podpracowników
# (podrzewo o root = i)
# rozw f(root)

def g(v):
    if v.g >= 0:
        return v.g
    v.g = 0
    for employee in v.emp:
        v.g += f(employee)
    return v.g

def f(v):
    if v.f >= 0:
        return v.f
    v.f = 0
    for employee in v.emp:
        v.f += g(employee)
    v.f = max(v.f, v.g)
    return v.f


def onesided_2_twosided(data):
    """Convert a two-sided PSD to a one-sided PSD

    In order to keep the power in the twosided PSD the same
    as in the onesided version, the twosided values are 2 times
    lower than the input data (except for the zero-lag and N-lag
    values).

    ::

        >>> twosided_2_onesided([10, 4, 6, 8])
        array([ 10.,   2.,   3.,   3., 2., 8.])

    """
    psd = np.concatenate((data[0:-1], cshift(data[-1:0:-1], -1)))/2.
    psd[0] *= 2.
    psd[-1] *= 2.
    return psd


#write a program  which accpet one number  from user
#and check whether number is prime or not.

#CheckPrime function

def CheckPrime(iNo):
    iCnt=1
    flag=0
    No2=iNo // 2
    for iCnt in range(2,No2):
        if iNo % iCnt == 0:
            flag=1

    if flag==1:
        return False
    else:
        return True

#Main Function.
def main():
    bRet=False
    iNo=int(input("Enter the number:"))
    bRet = CheckPrime(iNo)

    if bRet ==True :
        print("Number is Prime.")
    else:
        print("Number is not Prime")

#Starter.
if __name__ == "__main__":
    main()


from __future__ import absolute_import
import torch
from torch import nn
from torch.autograd import Variable
import numpy as np
import warnings
from .LOSSES import LOSSES

class DRO_TOPK(nn.Module):
    # Truncated DRO for p_choice = 1

    ####TODO: finish two methods, the third methods need to be done.
    def __init__(self, alpha=40, margin=0.5, beta=0,  K = 5,
                 select_TOPK_all = 1, loss = "margin_loss", **kwargs):

        # self.choose = 1, DRO over batch
        # self.choose = 2, DRO over class
        # self.choose = 3, DRO over each anchor.
        super(DRO_TOPK, self).__init__()
        self.margin = margin
        self.alpha = alpha
        self.beta = beta
        self.select_TOPK_all = select_TOPK_all
        self.K = K
        self.loss = loss
        self.LOSSES = LOSSES(alpha = self.alpha, beta = self.beta, margin = self.margin)
        print("loss:", self.loss, 'alpha:', self.alpha, 'beta:', self.beta,
              "margin:", self.margin, 'K', self.K)

    def forward(self, inputs, targets):
        n = inputs.size(0)
        sim_mat = torch.matmul(inputs, inputs.t())
        targets = targets.cuda()

        eyes_ = Variable(torch.eye(n, n)).cuda()

        #print("eyes_.dtype, targets.dtype:", eyes_.dtype, targets.dtype)

        pos_mask = targets.expand(n,n).eq(targets.expand(n,n).t())
        neg_mask = eyes_.eq(eyes_) - pos_mask # negative pairs index mat
        pos_mask = pos_mask - eyes_.eq(1) # positive pairs index mat

        pos_sim = torch.masked_select(sim_mat, pos_mask)
        neg_sim = torch.masked_select(sim_mat, neg_mask)

        #method_to_call = ,
        #result = method_to_call()

        myloss = getattr(self.LOSSES, self.loss)
        #print("function call", myloss)
        pos_loss, neg_loss = myloss(pos_sim, neg_sim)

        all_loss = torch.cat((pos_loss, neg_loss), 0)
        num_of_zeros = torch.sum(torch.eq(all_loss, 0))

        if self.select_TOPK_all == 1:

            if self.K * 4 > all_loss.size()[0]:
                loss = torch.mean(all_loss)
                warnings.warn("K larger than the total number of pairs in the batch. The loss is calculated using all the pairs by default.")
            else:
                top_loss, _ = torch.topk(all_loss, self.K * 4, largest=True)
                loss = torch.mean(top_loss)

        else:
            if self.K * 2 <= pos_loss.size()[0] and self.K * 2 <= neg_loss.size()[0]:
                top_pos_loss, _ = torch.topk(pos_loss, self.K * 2, largest=True)
                top_neg_loss, _ = torch.topk(neg_loss, self.K * 2, largest=True)
                loss = (torch.sum(top_pos_loss)+torch.sum(top_neg_loss))/(self.K*4)
            else:
                top_neg_loss, _ = torch.topk(neg_loss, pos_loss.size()[0], largest=True)
                loss = (torch.sum(pos_loss) + torch.sum(top_neg_loss)) / (2*pos_loss.size()[0])
                warnings.warn("K either larger than the number of positive pairs or larger than negative pairs. The loss is calculated using all the positive pairs and the same number amount of negative pairs which have the largest losses by default.")

        mean_neg_sim = torch.mean(pos_sim).item()
        mean_pos_sim = torch.mean(neg_sim).item()

        return loss, num_of_zeros.item(), mean_neg_sim, mean_pos_sim

    # def calibration_check_p(self, p):
    #     # remove nan, all o p, and make sure sum(p) = 1
    #
    #     if (torch.sum(torch.isnan(p)) != 0): # remove nan
    #         p[torch.isnan(p)] == 1 / torch.sum(torch.isnan(p))
    #     if (torch.sum(p) != 0):  # make sure the sum of p equal to 1.
    #         p = p / (torch.sum(p))
    #     return p
    #
    #
    # def truncate_p(self, np_p, K_thresh):
    #     order_np_p = -np.sort(-np_p)  # ordering from large to small
    #     np_p[np_p < order_np_p[K_thresh]] = 0
    #     np_p = np_p / sum(np_p)
    #     return np_p
def main():
    data_size = 32
    input_dim = 3
    output_dim = 2
    num_class = 4
    # margin = 0.5
    x = Variable(torch.rand(data_size, input_dim), requires_grad=False)
    # print(x)
    w = Variable(torch.rand(input_dim, output_dim), requires_grad=True)
    inputs = x.mm(w)
    y_ = 8*list(range(num_class))
    targets = Variable(torch.IntTensor(y_))

    DRO_TOPK(K = 1000, select_TOPK_all=2)(inputs, targets)

if __name__ == '__main__':
    main()
    print(LOSSES.__dict__.items())
    print('Congratulations to you!')


input_str = input()
count_1 = count_2 = count_3 = 0
for i in range(0, len(input_str), 2):
    if input_str[i] == '1':
        count_1 += 1
    elif input_str[i] == '2':
        count_2 += 1
    else:
        count_3 += 1
result = "1+" * count_1 + "2+" * count_2 + "3+" * count_3
print(result[:-1])

# https://codeforces.com/problemset/problem/339/A


#big018_hovedoppg01

#Oppgave 1.)
#math.pi kun oppgir 15 desimaler, derav maks 15.

import math

def pi(d):
    if d <= 15:
        return("%.{}f".format(d, d) % math.pi)
    else:
        return('For mange desimaler.', "%.2f" % (math.pi))

#Oppgave 2
#Bruker skriver inn 'temperaturKonvertering(grader, 'C'/'F')'.
def temperaturKonvertering(grader, enhet=None):
    if enhet == 'C':
        return(grader * (9/5)) + 32
    elif enhet == 'F':
        return(grader - 32.0) * (5/9)
    else:
        return(grader * (9/5)) + 32

#Oppgave 3a.) #Eneste måten jeg kom fram til å løse denne oppgaven, jeg vet vi ikke har gått gjennom __init__(self), men programmet fungerer og kjører slikt som det skal i henhold til oppgaven.
class konto():

    def __init__(self, saldo=0): #Constructor
        self.saldo = saldo

    def innskudd(self, innmengde): #Bruker skriver inn 'saldo.innskudd()', og sum inne i parantesene.
        self.saldo += innmengde
        print('{} kr er lagt til i saldoen.'.format(innmengde))

    def uttak(self, utmengde): #Bruker skriver inn 'saldo.uttak()', og sum inne i parantesene.
        if self.saldo >= utmengde:
            self.saldo -= utmengde
            print('Uttak på {}.'.format(utmengde),'kr.')
        else:
            print('Ingen dekning.')

    def beregn_rente(self): #Bruker skriver 'saldo.beregn_rente()'.
        if self.saldo < 1000000:
            rente = self.saldo * 0.01
            print(rente, 'kr.')
        else:
            bonus = self.saldo * 0.02
            print(bonus, 'kr.')

    def beregn_oppgjor(self): #Bruker skriver 'saldo.beregn_oppgjor()'.
        if self.saldo < 1000000:
            vanligrente = self.saldo * 0.01
            print('Saldo med ordinær rente: ',(self.saldo + vanligrente), 'kr')
            self.saldo = self.saldo + vanligrente
        else:
            bonusrente = self.saldo * 0.02
            print('Saldo med bonusrente:',(self.saldo + bonusrente), 'kr')
            self.saldo = self.saldo + bonusrente

    def __str__(self): #Forenkeling slik at bruker kan skrive: saldo.innskudd/saldo.uttak osv.
        return f'Saldo: {self.saldo}'

saldo = konto(500) #Bruker skriver 'print(saldo)' for å få oppgitt saldo.

#Oppgave 3b.)
#Bruker start prosessen ved å skrive 'velg()'.
class konto():

    def __init__(self, saldo=0):
        self.saldo = saldo

    def innskudd(self):
        self.saldo += float(input('Innskuddssum: '))
        print('Saldoen er nå {} kr.'.format(self.saldo))

    def uttak(self):
        utmengde = float(input('Uttakssum: '))

        if self.saldo >= utmengde:
            self.saldo -= utmengde
            print('Uttak på {}.'.format(utmengde))
        else:
            print('Ingen dekning.')

    def beregn_rente(self):
        if self.saldo < 1000000:
            rente = self.saldo * 0.01
            print(rente, 'kr.')
        else:
            bonus = self.saldo * 0.02
            print(bonus, 'kr.')

    def beregn_oppgjor(self):
        if self.saldo < 1000000:
            vanligrente = self.saldo * 0.01
            print('Saldo med ordinær rente: ',(self.saldo + vanligrente), 'kr')
            self.saldo = self.saldo + vanligrente
        else:
            bonusrente = self.saldo * 0.02
            print('Saldo med bonusrente:',(self.saldo + bonusrente), 'kr')
            self.saldo = self.saldo + bonusrente

    def __str__(self):
        return f'Saldo: {self.saldo}'

saldo = konto(500)

def velg():
    while True:
        velg = int(input('1 for saldo\n2 for innskudd\n3 for uttak\n4 for renteberegning\n5 for renteoppgjør\nVelg handling: '))
        if velg == 1:
            print(saldo)
        if velg == 2:
            saldo.innskudd()
        if velg == 3:
            saldo.uttak()
        if velg == 4:
            saldo.beregn_rente()
        if velg == 5:
            saldo.beregn_oppgjor()

#Oppgave 3c.)
#Stoff får å kunne løse 3c er for lite gjennomgått for å kunne løse syntes jeg, jeg er ikke den eneste som syntes det heller.
#Har heller ikke vært borti en slik oppgave i lab eller lignende før, så det kommer som et sjokk.
#Har veldig lite å kunne bidra med her for at du som retter skal kunne gi en tilbakemelding til dette i det hele tatt.

#Har en viss ide om at man må bruke .append og lister.

        if velg == 6: #Legge til dette på listen av velg()
            siste_endringer #funksjonen kommer til å hele siste_endringer. Må man bruke def(?)

historie [self.saldo, saldo.innskudd(), saldo.uttak(), saldo.beregn_rente(), saldo.beregn_oppgjor()]

#En liste av funksjonene av noe slag, og bruke append for å resultatene til slutt? Kanskje *parametere?
#Håper på gode tilbakemeldinger slik at jeg kan løse denne oppgaven til slutt, for det er veldig vanskelig å løse denne iht. det vi har lært.

#Oppgave 4.)
import random

def tre_tilfeldige(): #Bruker skriver inn 'tre_tilfeldige()'
    nummer1 = random.randint(1, 9)
    nummer2 = random.randint(1, 9)
    nummer3 = random.randint(1, 9)

    minst = min(nummer1, nummer2, nummer3)
    stoerst = max(nummer1, nummer2, nummer3)
    midten = (nummer1 + nummer2 + nummer3 - minst - stoerst)
    return (minst, midten, stoerst)


import os

import docker

from babysage.utils import find_project_root, get_input_dir, get_output_dir
from babysage.config import get_config

def run_local(dockerfile):
    client = docker.from_env()

    project_root = find_project_root()

    if project_root:
        dockerfile = dockerfile or 'Dockerfile'
        tag = f"babysage-{get_config('experiment_name')}",
        client.images.build(
            path=project_root,
            quiet=False,
            rm=True,
            tag=tag,
            dockerfile=dockerfile)
        client.containers.run(
            tag,
            'train',
            volumes={
                os.path.join(project_root, 'input'): {
                    'bind': get_input_dir(), 'mode': 'rw'},
                os.path.join(project_root, 'output'): {
                    'bind': get_output_dir(), 'mode': 'rw'}})
    else:
        raise Exception('''
        Current directry is not a babysage project directry (could not find `babysage.yml` file''')


from sprites import *
from bullets import *

class Hero(GameSprite):
    """英雄飞机类，继承自GameSprite"""
    def __init__(self):
        # 设置速度为0
        super().__init__("./images/me1.png", speed=0)
        # 位于游戏主窗口的中央
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.height - 10
        # 创建子弹精灵组
        self.bullet_group = pygame.sprite.Group()

    def update(self):
        # 英雄飞机在水平方向移动且不能移动出边界
        if self.rect.x < 0:
            self.rect.x = 0
        elif self.rect.right > SCREEN_RECT.width:
            self.rect.right = SCREEN_RECT.width
        else:
            self.rect.x += self.speed

    def fire(self):
        """英雄飞机发射子弹"""
        for i in (0, 1, 2):
            # 创建子弹精灵
            bullet = Bullet()
            # 设定子弹精灵的位置，应该在英雄飞机的正上方发射
            bullet.rect.y = self.rect.y - 2 * i * bullet.rect.height
            bullet.rect.centerx = self.rect.centerx
            # 子弹精灵加入精灵组
            self.bullet_group.add(bullet)


# Local search based on select a max value first
# Compared to V1, searches will be based on a nearby utility value

from math import sqrt
import math
import operator
import random

from animate import animate_print

incremental_step_value = 1

def solve(height, length, arr, quota):
    print("Algo: Max Local Search 3.0")
    max_value = max([max(val) for val in arr])
    dict_max = {}

    # get max values list
    for i in range(height):
        for j in range(length):
            if arr[i][j] == max_value:
                dict_max[(i,j)] = 0

    chosen_node = best_node_chooser(arr, dict_max, min(height, length, int(math.sqrt(quota))))
    animate_print(length, height, arr, [chosen_node])
    return solve_local_based(height, length, arr, quota, chosen_node)

def solve_local_based(height, length, arr, quota, chosenStart):
    visitedMap, pq = {}, {}
    visitedMap[chosenStart] = 1
    score = int(arr[chosenStart[0]][chosenStart[1]])

    pq = check_visited(height, length, chosenStart, pq, visitedMap, arr)

    for i in range(quota - 1):

        maxKey = max(pq.keys())
        newSelected = best_node_chooser(arr, convert_dict_zero(pq[maxKey]), int(math.sqrt(i)))

        pq[maxKey].remove(newSelected)
        if pq[maxKey] == []:
            del pq[maxKey]

        animate_print(length, height, arr, visitedMap, create_list_dict(pq), [newSelected])

        visitedMap[newSelected] = i + 2

        score += int(maxKey)

        pq = check_visited(height, length, newSelected, pq, visitedMap, arr)

    return visitedMap, score

def check_visited(height, length, chosen, pq, visitedMap, arr):
    x, y = chosen
    for a, b in [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]:
        if a in range(0, height) and b in range(0, length) and (a, b) not in visitedMap and (arr[a][b] not in pq or (a, b) not in pq[arr[a][b]]):
            if arr[a][b] in pq:
                pq[arr[a][b]].append((a, b))
            else:
                pq[arr[a][b]] = [(a, b)]

    return pq

def convert_dict_zero(l):
    d = {}

    for item in l:
        d[item] = 0

    return d

def best_node_chooser(arr, node_list, start_val_step = incremental_step_value, step_val = incremental_step_value):
    max_range = start_val_step

    while (1):
        for x, y in node_list:
            for item_x in range(len(arr)):
                for item_y in range(len(arr[0])):
                    distance = sqrt(pow((x - item_x), 2) + pow((y - item_y), 2))
                    if distance <= max_range:
                        node_list[(x, y)] += int(arr[item_x][item_y])

        max_item_val = max(node_list.values())
        list_max = [key for key in node_list if node_list[key] == max_item_val]

        if len(list_max) == 1:
            return list_max[0]

        max_range += step_val

    return None

def create_list_dict(d):
    l = []
    for key in d.keys():
        l += d[key]

    return l


# baek 13913 숨바꼭질 4

import sys
input=sys.stdin.readline

paths=[[1,1],[-1,1],[0,2]]
MAX=100001
soobin,sis= map(int ,input().split())
dp=[[0,0] for _ in range(MAX)]   #dp[i] = [i까지의 최단경로, i칸 이전 위치]

dp[soobin]=[1,-1]        # 시작점 설정
que=[soobin]                  # que 초기화

_max=min(max(soobin,sis)*2,MAX)
while(len(que)!=0):
    x= que.pop(0)
    _cnt=dp[x][0]
    for i in range(3):
        a=(x+paths[i][0])*paths[i][1]
        if 0<=a<_max:
            if dp[a][0] ==0:
                dp[a]=[_cnt+1,x]
                que.append(a)
                if a==sis:
                    que=[]

answer =dp[sis][0]-1
ans_path=dp[sis][1]

print(answer)
ans_paths=[sis]
x=sis
while x != soobin:
    x=dp[x][1]
    ans_paths.append(x)
for i in range(len(ans_paths)-1,-1,-1):
    print(ans_paths[i],end= ' ')


from decor_timetable import *
import json
n = input('Для просмотра расписания гр. 18704 введите 1: ')
if n == '1':
    lst = []
    with open('time.txt', encoding='utf-8') as f:
        for line in f.readlines():
            a = Day(json.loads(line))
            lst.append(str(a).split(', '))
    print('|{:^20}|{:^20}|{:^20}|{:^20}|{:^20}|'.format('1 пара', '3 пара',
                                                        '2 пара', '4 пара', '5 пара'))
    print('-' *106)
    for i in lst:
        a = Lesson(i)
        print(a)
    print('-' * 106)
else:
    print('До свидания!')


#!/usr/bin/env python

from torch.nn import Linear
import torch
import numpy as np
from json_plus import Serializable

class LinearExtended(Linear, Serializable):
    """Implementation of a linear neural net with sensitivity analysis."""

    def __init__(self, in_features, out_features, bias=None):
        super(LinearExtended, self).__init__(
            in_features, out_features, bias=True
        )

    def overall_sensitivity(self):
        """Returns the sensitivity to adversarial examples of the layer."""
        if self.mod1:
            s = torch.max(torch.max(self.weight, -1)[0], -1)[0].item()
        else:
            s = torch.max(torch.sqrt(torch.sum(self.weight * self.weight, -1)))[0].item()
        s *= np.sqrt(2. / np.e)
        return s

    def interval_forward(self, x_min, x_max):
        w_pos = (self.weight > 0.).float() * self.weight
        w_neg = (self.weight < 0.).float() * self.weight
        y_min = x_min.matmul(w_pos.t()) + x_max.matmul(w_neg.t()) + self.bias
        y_max = x_max.matmul(w_pos.t()) + x_min.matmul(w_neg.t()) + self.bias
        return y_min, y_max

    def sensitivity(self, previous_layer):
        """Given the sensitivity of the previous layer (a vector of length equal
        to the number of inputs), it computes the sensitivity to adversarial examples
         of the current layer, as a vector of length equal to the output size of the
         layer.  If the input sensitivity of the previous layer is None, then unit
         sensitivity is assumed."""
        if previous_layer is None:
            previous_layer = self.weight.new(1, self.in_features)
            previous_layer.fill_(1.)
        else:
            previous_layer = previous_layer.view(1, self.in_features)
        w = previous_layer * self.weight
        s = torch.sum(torch.abs(w), -1)
        return s

    def dumps(self):
        d = dict(
            in_features=self.in_features,
            out_features=self.out_features,
            weight=self.weight.data.cpu().numpy(),
            bias=None if self.bias is None else self.bias.data.cpu().numpy(),
        )
        return Serializable.dumps(d)

    @staticmethod
    def loads(s, device):
        d = Serializable.loads(s)
        m = LinearExtended(
            d['in_features'],
            d['out_features'],
            bias=d['bias'] is not None
        )
        m.weight.data = torch.from_numpy(d['weight']).to(device)
        if d['bias'] is not None:
            m.bias.data = torch.from_numpy(d['bias']).to(device)
        return m


from lxml import etree
import sys
"""
Find missing audio files in each lesson and print outline showing their location.

Author: Carolyn Anderson          Last Modified: 5/12/2015
"""

#Create xsl transformation functions
audio_xsl_raw = etree.parse("audio_find.xsl")
audio_xsl = etree.XSLT(audio_xsl_raw)

def processLessonSet(level, lessonset):
  f = open("../audio.html", "w") #create new file
  f.write(str(audio_xsl(lessonset))) #apply xslt transformation and write to file
  f.close()

doc = etree.parse(sys.argv[1]) #parse the xml doc
lessonset = doc.xpath("/lessonset")[0]#get lessonset
processLessonSet(0, lessonset)#process lessonset


import random
import rstr
import string
from loguru import logger
from scripts.utils.xml_utils import get_value_from_facet
from scripts.utils.types import Fake_

class SPDULType():
    name: str = 'СПДУЛТип'

    def value(self, node_type, sync_attr=None):
        value = get_spdul(node_type)
        return value

def get_spdul(node_type):
    length = node_type.get('length', None)
    length = node_type.get('max_length', None) if node_type.get('max_length', None) is not None else length
    value = None
    if node_type['enumeration'] is not None:
        index = Fake_.random_int(min=0, max=len(node_type['enumeration']) - 1)
        if length is not None:
            value = node_type['enumeration'][index][:node_type['length']]
        else:
            value = node_type['enumeration'][index]
    if value is None and node_type['patterns'] is not None:
        value = rstr.xeger(node_type['patterns'][0])
    if value is None and length is not None:
        value = ''.join(random.choices(string.ascii_letters, k=length))
    if value is None:
        pattern = "#" * 2
        value = Fake_.numerify(text=pattern)
    return value

class SPDULschType():
    name: str = 'СПДУЛШТип'

    def value(self, node_type, sync_attr=None):
        value = get_spdul(node_type)
        return value


#!/usr/bin/env python3
# pylint: disable=unused-argument
import sys
import argparse
import argcomplete
import mmpm.consts
from typing import List

# subcommand names. These could go in mmpm.consts.py, but for the sake of mnemonics
# for mmpm.py, they'll stay (ie, opts.INSTALL, opts.LIST, etc)
INSTALL: str = 'install'
SEARCH: str = 'search'
REMOVE: str = 'remove'
DATABASE: str = 'db'
LIST: str = 'list'
MM_CTL: str = 'mm-ctl'
OPEN: str = 'open'
ADD_EXT_PKG: str = 'add-ext-pkg'
LOG: str = 'log'
UPDATE: str = 'update'
UPGRADE: str = 'upgrade'
ENV: str = 'env'
SHOW: str = 'show'

SINGLE_OPTION_ARGS: List[str] = [INSTALL, DATABASE, LIST, OPEN]

def get_user_args() -> object:
    '''
    Wrapper method around ArgumentParser.parse_args()

    Parameters:
        None

    Returns:
        ArgumentParser objects
    '''

    arg_parser = argparse.ArgumentParser(
        prog='mmpm',
        usage='mmpm <subcommand> [option(s)]',
        epilog=f'Visit {mmpm.consts.MMPM_WIKI_URL} for more details',
        description='''
            The MagicMirror Package Manager CLI simplifies the
            installation, removal, and general maintenance of MagicMirror packages
            '''
    )

    subparsers = arg_parser.add_subparsers(
        title='MMPM subcommands',
        description='use `mmpm <subcommand> --help` to see more details',
        dest='subcmd',
    )

    # SEARCH PARSER
    search_parser = subparsers.add_parser(
        SEARCH,
        usage='\n  mmpm search <query> [--case-sensitive] [--exclude-local]',
        help='search for MagicMirror packages'
    )

    search_parser.add_argument(
        '-t',
        '--title-only',
        action='store_true',
        help='only show the title of the packages matching the search results',
        dest='title_only'
    )

    search_parser.add_argument(
        '-c',
        '--case-sensitive',
        action='store_true',
        help='search for packages using a case-sensitive query',
        dest='case_sensitive'
    )

    search_parser.add_argument(
        '-e',
        '--exclude-local',
        action='store_true',
        help='exclude locally installed packages from search results',
        dest='exclude_local'
    )

    # INSTALL PARSER
    install_parser = subparsers.add_parser(
        INSTALL,
        usage='\n  mmpm install <package(s)> [--yes]\n  mmpm install [--magicmirror] [--autocomplete] [--gui] [--as-module]',
        help='install MagicMirror packages'
    )

    install_parser.add_argument(
        '-y',
        '--yes',
        action='store_true',
        default=False,
        help='assume yes for user response and do not show prompt',
        dest='assume_yes'
    )

    install_parser.add_argument(
        '--magicmirror',
        action='store_true',
        default=False,
        help='install MagicMirror, if not already installed',
        dest='magicmirror'
    )

    install_parser.add_argument(
        '--autocomplete',
        action='store_true',
        help='install autocompletion for the MMPM CLI',
        dest='autocomplete'
    )

    install_parser.add_argument(
        '--gui',
        action='store_true',
        help='install the MMPM GUI. Asks for sudo permissions',
        dest='gui'
    )

    install_parser.add_argument(
        '--as-module',
        action='store_true',
        help='install the MMPM MagicMirror helper module in your MagicMirror modules directory to enable hide/show functionality',
        dest='as_module'
    )

    # REMOVE PARSER
    remove_parser = subparsers.add_parser(
        REMOVE,
        usage='\n  mmpm remove <package(s)> [--yes]',
        help='remove locally installed packages'
    )

    remove_parser.add_argument(
        '-y',
        '--yes',
        action='store_true',
        default=False,
        help='assume yes for user response and do not show prompt',
        dest='assume_yes'
    )

    remove_parser.add_argument(
        '--gui',
        action='store_true',
        default=False,
        help='remove the MMPM GUI. Asks for sudo permissions',
        dest='gui'
    )

    # UPDATE PARSER
    subparsers.add_parser(
        UPDATE,
        usage='\n  mmpm update',
        help='check for updates for installed packages, MMPM, and MagicMirror'
    )

    # UPGRADE SUBCOMMANDS
    upgrade_parser = subparsers.add_parser(
        UPGRADE,
        usage='\n  mmpm upgrade [--yes]\n  mmpm upgrade <package(s)> <application(s)> [--yes]',
        help='upgrade packages, MMPM, and/or MagicMirror, if available'
    )

    upgrade_parser.add_argument(
        '-y',
        '--yes',
        action='store_true',
        default=False,
        help='assume yes for user response and do not show prompt',
        dest='assume_yes'
    )

    # DATABASE SUBCOMMANDS
    database_parser = subparsers.add_parser(
        DATABASE,
        usage='\n  mmpm db [--refresh] [--details]',
        help='refresh or display basic details about the database'
    )

    database_parser.add_argument(
        '-r',
        '--refresh',
        action='store_true',
        help='forces a refresh of the packages database',
        dest='refresh'
    )

    database_parser.add_argument(
        '-d',
        '--details',
        action='store_true',
        help='display details about the most recent MagicMirror packages database',
        dest='details'
    )

    database_parser.add_argument(
        '--dump',
        action='store_true',
        help='dump the database JSON contents to stdout',
        dest='dump'
    )

   # LIST SUBCOMMANDS
    list_parser = subparsers.add_parser(
        LIST,
        usage='\n  mmpm list [--all] [--exclude-local] [--categories] [--gui-url]',
        help='list items such as installed packages, packages available, available upgrades, etc'
    )

    list_parser.add_argument(
        '-a',
        '--all',
        action='store_true',
        help='list all available packages in the marketplace',
        dest='all'
    )

    list_parser.add_argument(
        '-e',
        '--exclude-local',
        action='store_true',
        help='list all available packages in the marketplace, excluding locally installed packages',
        dest='exclude_local'
    )

    list_parser.add_argument(
        '-i',
        '--installed',
        action='store_true',
        help='list all locally installed packages',
        dest='installed'
    )

    list_parser.add_argument(
        '-c',
        '--categories',
        action='store_true',
        help='list all available package categories',
        dest='categories'
    )

    list_parser.add_argument(
        '-t',
        '--title-only',
        action='store_true',
        help='display the title only of packages (used with -c, -a, -e, or -i)',
        dest='title_only'
    )

    list_parser.add_argument(
        '-g',
        '--gui-url',
        action='store_true',
        help='list the URL of the MMPM GUI',
        dest='gui_url'
    )

    list_parser.add_argument(
        '--upgradable',
        action='store_true',
        help='list packages that have available upgrades',
        dest='upgradable'
    )

    # OPEN SUBCOMMANDS
    open_parser = subparsers.add_parser(
        OPEN,
        usage='\n  mmpm open [--config] [--css] [--gui] [--mm-wiki] [--mmpm-wiki]',
        help='quickly open config files, documentation, wikis, and MagicMirror itself'
    )

    open_parser.add_argument(
        '--config',
        action='store_true',
        help='open MagicMirror config/config.js file in your $EDITOR',
        dest='config'
    )

    open_parser.add_argument(
        '--css',
        action='store_true',
        help='open MagicMirror css/custom.css file (if it exists) in your $EDITOR',
        dest='custom_css'
    )

    open_parser.add_argument(
        '--gui',
        action='store_true',
        help='open the MMPM GUI in your default browser',
        dest='gui'
    )

    open_parser.add_argument(
        '--magicmirror',
        action='store_true',
        help='open MagicMirror in your default browser (uses the MMPM_MAGICMIRROR_URI address)',
        dest='magicmirror'
    )

    open_parser.add_argument(
        '--mm-wiki',
        action='store_true',
        help='open the MagicMirror GitHub wiki in your default browser',
        dest='mm_wiki'
    )

    open_parser.add_argument(
        '--mm-docs',
        action='store_true',
        help='open the MagicMirror documentation in your default browser',
        dest='mm_docs'
    )

    open_parser.add_argument(
        '--mmpm-wiki',
        action='store_true',
        help='open the MMPM GitHub wiki in your default browser',
        dest='mmpm_wiki'
    )

    open_parser.add_argument(
        '--env',
        action='store_true',
        help='open the MMPM run-time environment variables JSON configuration file in your $EDITOR',
        dest='mmpm_env'
    )

    # show_parser
    show_parser = subparsers.add_parser(
        SHOW,
        usage='\n  mmpm show <package(s)> [--verbose]',
        help='show details about one or more packages'
    )

    show_parser.add_argument(
        '-r',
        '--remote',
        action='store_true',
        help='display remote detail for package(s) from GitHub/GitLab/Bitbucket APIs',
        dest='remote'
    )

    # ADD EXTERNAL PACKAGE SUBCOMMANDS
    add_ext_package_parser = subparsers.add_parser(
        ADD_EXT_PKG,
        usage='\n  mmpm add-ext-package [--title=<title>] [--author=<author>] [--repo=<repo>] [--desc=<description>]\n  mmpm add-ext-package --remove <package> [--yes]',
        help='manually add MagicMirror packages to your local database'
    )

    add_ext_package_parser.add_argument(
        '-t',
        '--title',
        type=str,
        help='title of external package (will be prompted if not provided)',
        dest='title'
    )

    add_ext_package_parser.add_argument(
        '-a',
        '--author',
        type=str,
        help='author of external package (will be prompted if not provided)',
        dest='author'
    )

    add_ext_package_parser.add_argument(
        '-r',
        '--repo',
        type=str,
        help='repo URL of external package (will be prompted if not provided)',
        dest='repo'
    )

    add_ext_package_parser.add_argument(
        '-d',
        '--desc',
        type=str,
        help='description of external package (will be prompted if not provided)',
        dest='desc'
    )

    add_ext_package_parser.add_argument(
        '--remove',
        nargs='+',
        help='remove external package (similar to `add-apt-repository` --remove)',
        dest='remove'
    )

    add_ext_package_parser.add_argument(
        '-y',
        '--yes',
        action='store_true',
        default=False,
        help='assume yes for user response and do not show prompt (used with --remove)',
        dest='assume_yes'
    )

    # LOGS SUBCOMMANDS
    log_parser = subparsers.add_parser(
        LOG,
        usage='\n  mmpm log [--cli] [--web] [--tail]',
        help='display, tail, or zip the MMPM log files'
    )

    log_parser.add_argument(
        '-c',
        '--cli',
        action='store_true',
        help='cat the MMPM CLI log files',
        dest='cli'
    )

    log_parser.add_argument(
        '-g',
        '--gui',
        action='store_true',
        help='cat the MMPM GUI (Gunicorn) log files',
        dest='gui'
    )

    log_parser.add_argument(
        '-t',
        '--tail',
        action='store_true',
        help='tail the log file(s) in real time',
        dest='tail'
    )

    log_parser.add_argument(
        '--zip',
        action='store_true',
        help='compress the MMPM log file(s), and save them in your current directory',
        dest='zip'
    )

    # MM_CTL SUBCOMMANDS
    mm_ctl_parser = subparsers.add_parser(
        MM_CTL,
        usage='\n  mmpm mm-ctl [--status] [--restart] [--start] [--stop]\n  mmpm mm-ctl [--rotate] {0, 90, 180, 270}\n  mmpm mm-ctl [--hide] [--show] <key(s)>',
        help='commands to control the MagicMirror'
    )

    mm_ctl_parser.add_argument(
        '--status',
        action='store_true',
        help='show the hidden/visible status and key(s) of module(s) on your MagicMirror',
        dest='status'
    )

    mm_ctl_parser.add_argument(
        '--hide',
        nargs='+',
        help='hide module(s) on your MagicMirror via provided key(s)',
        dest='hide'
    )

    mm_ctl_parser.add_argument(
        '--show',
        nargs='+',
        help='show module(s) on your MagicMirror via provided key(s)',
        dest='show'
    )

    mm_ctl_parser.add_argument(
        '--start',
        action='store_true',
        help='start MagicMirror; works with pm2 and docker-compose',
        dest='start'
    )

    mm_ctl_parser.add_argument(
        '--stop',
        action='store_true',
        help='stop MagicMirror; works with pm2 and docker-compose',
        dest='stop'
    )

    mm_ctl_parser.add_argument(
        '--restart',
        action='store_true',
        help='restart MagicMirror; works with pm2 and docker-compose',
        dest='restart'
    )

    mm_ctl_parser.add_argument(
        '--rotate',
        choices=[0, 90, 180, 270],
        type=int,
        help='rotate MagicMirror screen to 0, 90, 180, or 270 degrees',
        dest='rotate'
    )

    # ENV SUBCOMMANDS
    subparsers.add_parser(
        ENV,
        usage='\n  mmpm env',
        help='display the MMPM environment variables and their value(s)'
    )

    # MMPM AND GLOBAL OPTIONS
    arg_parser.add_argument(
        '-v',
        '--version',
        action='store_true',
        help='display MMPM version number',
        dest='version'
    )

    arg_parser.add_argument(
        '--guided-setup',
        action='store_true',
        help='run the guided setup/installation of the GUI, environment variables, and other features',
        dest='guided_setup'
    )

    arg_parser.add_argument(
        '--migrate',
        action='store_true',
        help='migrate legacy file names and database keys. Only required once if prior version of MMPM is < 1.25',
        dest='migrate'
    )

    # hidden argument used for the GUI interface
    arg_parser.add_argument(
        '--GUI',
        action='store_true',
        default=False,
        help=argparse.SUPPRESS,
        dest='GUI'
    )

    argcomplete.autocomplete(arg_parser)

    if len(sys.argv) < 2:
        arg_parser.print_help()
        sys.exit(0)

    return arg_parser


from itertools import product

suits = {
    'буби': 'бубен',
    'пики': 'пик',
    'трефы': 'треф',
    'черви': 'червей'
}

def insp(trio):
    if trio[0] == trio[2] and trio[1] == trio[3]:
        return False
    elif trio[0] == trio[4] and trio[1] == trio[5]:
        return False
    elif trio[2] == trio[4] and trio[3] == trio[5]:
        return False
    else:
        return True

nom = [str(i) for i in range(2, 11)] + ['валет', 'дама', 'король', 'туз']
suit = input()
nom.remove(input())
nom.sort()

count = 0
for trio in product(nom, suits.values(), repeat=3):
    if suits[suit] in trio and insp(trio):
        if count < 10:
            print(f'{trio[0]} {trio[1]}, {trio[2]} {trio[3]}, {trio[4]} {trio[5]}')
            count += 1


import cv2
import numpy as np

#Import image
source = cv2.imread('tools-black.jpg', cv2.IMREAD_GRAYSCALE)
final = cv2.imread("tools-black.jpg")
ret, thresh = cv2.threshold(source, 180, 240, 0)

#Use median blur to remove even more noise.
median = cv2.medianBlur(thresh,3)

#Opening on the threshold against noise.
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
erosion = cv2.erode(median,kernel,1)
opening = cv2.dilate(erosion,kernel,1)

#closing
kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (30, 30))
dilation2 = cv2.dilate(opening,kernel2,1)
erosion2 = cv2.erode(dilation2,kernel2,1)

#contours, hierachy = cv2.findContours(source, 1, 2)
contours, hierarchy = cv2.findContours(erosion2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

cnt = contours[0]
M = cv2.moments(cnt)
area = cv2.contourArea(cnt)

# FILL ALL THE CONTOURS
cv2.drawContours(final, contours, -1, (0,255,255), cv2.FILLED)

cv2.imshow("Source",source)
cv2.imshow("Final", final)
#cv2.imshow("Thresh",thresh)
#cv2.imshow("Opening",opening)
#cv2.imshow("Median", median)

# Quit program is 'q' is pressed
if cv2.waitKey(0) & 0xFF == ord('q'):
    cv2.destroyAllWindows()


from rdkit import Chem
from rdkit.Chem.rdchem import HybridizationType, ChiralType
import torch
from torch_geometric.data import Dataset, Data, DataLoader
import numpy as np
import os
import networkx as nx
import torch.nn as nn
from torch_geometric.nn import SAGEConv, global_mean_pool, global_add_pool, global_max_pool
from torch.utils.data import random_split
import pickle
import random
from torch_geometric.utils import from_networkx
from sklearn.metrics import roc_auc_score, accuracy_score
import nni
from nni.utils import merge_parameter
import argparse
import logging

logger = logging.getLogger('subgraphclassification')

class SubGraph(Dataset):

    def __init__(self, root, filename, test=False,transform=None, pre_transform=None, pre_filter=None):
        self.filename = filename
        self.test = test
        super().__init__(root, transform, pre_transform, pre_filter)

    @property
    def raw_file_names(self):
        return self.filename

    @property
    def processed_file_names(self):
        self.raws = pickle.load(open(self.raw_paths[0], 'rb'))
        if self.test:
            return [f'data_test_{i}' for i in range(len(self.raws))]
        else:
            return [f'data_{i}.pt' for i in range(len(self.raws))]

    def download(self):
        pass

    def process(self):
        self.raws = pickle.load(open(self.raw_paths[0], 'rb'))
        for idx, mol in enumerate(self.raws):
            subgraph, label = mol
            # create data object
            data = from_networkx(subgraph)
            label = torch.tensor(label, dtype=torch.int64)
            data['target'] = label
            if self.test:
                torch.save(data, os.path.join(self.processed_dir, \
                f'data_test_{idx}.pt'))
            else:
                torch.save(data, os.path.join(self.processed_dir, \
                f'data_{idx}.pt'))

    def len(self):
        return len(self.raws)

    def get(self, idx):
        if self.test:
            data = torch.load(os.path.join(self.processed_dir, f'data_test_{idx}.pt'))
        else:
            data = torch.load(os.path.join(self.processed_dir, f'data_{idx}.pt'))
        return data

train_dataset = SubGraph('./subgraphdataset/', 'train.pkl')
test_dataset = SubGraph('./subgraphdataset/', 'test.pkl', test=True)
training_set, validation_set  = random_split(train_dataset, [int(len(train_dataset) * 0.8), len(train_dataset) - int(len(train_dataset) * 0.8)], generator=torch.Generator().manual_seed(42))

class Model(nn.Module):
    def __init__(self, args):
        super(Model, self).__init__()
        num_classses = 2

        tmp = {
            0: global_mean_pool,
            1: global_add_pool,
            2: global_max_pool,
        }
        conv_hidden = args['conv_hidden']
        cls_hidden = args['cls_hidden']
        self.n_layers = args['n_layers']
        cls_drop = args['cls_drop']

        self.conv_layers = nn.ModuleList([])

        self.conv1 = SAGEConv(26, conv_hidden)

        for i in range(self.n_layers):
            self.conv_layers.append(
                SAGEConv(conv_hidden, conv_hidden)
            )

        self.linear1 = nn.Linear(conv_hidden, cls_hidden)
        self.linear2 = nn.Linear(cls_hidden, num_classses)
        self.relu = nn.ReLU()
        self.drop1 = nn.Dropout(p=cls_drop)
        self.readout = tmp[args['readout']]

    def forward(self, mol):

        res = self.conv1(mol.x, mol.edge_index)
        for i in range(self.n_layers):
            res = self.conv_layers[i](res, mol.edge_index)

        res = self.readout(res, mol.batch)
        res = self.linear1(res)
        res = self.relu(res)
        res = self.drop1(res)
        res = self.linear2(res)

        return res

def seed_torch(seed=42):
	random.seed(seed)
	os.environ['PYTHONHASHSEED'] = str(seed)
	np.random.seed(seed)
	torch.manual_seed(seed)
	torch.cuda.manual_seed(seed)
	torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.

def train(args, model, device, training_set, optimizer, criterion, epoch):
    model.train()
    sf = nn.Softmax(dim=1)
    total_loss = 0
    all_pred = []
    all_pred_raw = []
    all_labels = []
    for sub_mol in training_set:
        sub_mol = sub_mol.to(device)
        sub_mol.x = sub_mol.x.to(torch.float32)
        target = sub_mol.target
        optimizer.zero_grad()
        output= model(sub_mol)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
        # tracking
        all_pred.append(np.argmax(output.cpu().detach().numpy(), axis=1))
        all_pred_raw.append(sf(output)[:, 1].cpu().detach().numpy())
        all_labels.append(target.cpu().detach().numpy())

    all_pred = np.concatenate(all_pred).ravel()
    all_pred_raw = np.concatenate(all_pred_raw).ravel()
    all_labels = np.concatenate(all_labels).ravel()

    logger.info(f'Train Epoch: {epoch}, Ave Loss: {total_loss / len(training_set)} ACC: {accuracy_score(all_labels, all_pred)}  AUC: {roc_auc_score(all_labels, all_pred_raw)}')

def val(args, model, device, val_set, optimizer, criterion, epoch):
    model.eval()
    sf = nn.Softmax(dim=1)
    total_loss = 0
    all_pred = []
    all_pred_raw = []
    all_labels = []
    for sub_mol in val_set:
        sub_mol = sub_mol.to(device)
        sub_mol.x = sub_mol.x.to(torch.float32)
        target = sub_mol.target
        optimizer.zero_grad()
        output= model(sub_mol)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()

        # tracking
        all_pred.append(np.argmax(output.cpu().detach().numpy(), axis=1))
        all_pred_raw.append(sf(output)[:, 1].cpu().detach().numpy())
        all_labels.append(target.cpu().detach().numpy())

    all_pred = np.concatenate(all_pred).ravel()
    all_pred_raw = np.concatenate(all_pred_raw).ravel()
    all_labels = np.concatenate(all_labels).ravel()
    logger.info(f'validation Epoch: {epoch}, Ave Loss: {total_loss / len(val_set)} ACC: {accuracy_score(all_labels, all_pred)}  AUC: {roc_auc_score(all_labels, all_pred_raw)}')
    return accuracy_score(all_labels, all_pred)

def test(model, device, test_set):
    model.eval()
    sf = nn.Softmax(dim=1)
    all_pred = []
    all_pred_raw = []
    all_labels = []
    subgraph_num = 0
    with torch.no_grad():
        for sub_mol in test_set:
            sub_mol = sub_mol.to(device)
            sub_mol.x = sub_mol.x.to(torch.float32)
            target = sub_mol.target
            output= model(sub_mol)
            # tracking
            all_pred.append(np.argmax(output.cpu().detach().numpy(), axis=1))
            all_pred_raw.append(sf(output)[:, 1].cpu().detach().numpy())
            all_labels.append(target.cpu().detach().numpy())

    all_pred = np.concatenate(all_pred).ravel()
    all_pred_raw = np.concatenate(all_pred_raw).ravel()
    all_labels = np.concatenate(all_labels).ravel()

    print(f'ACC: {accuracy_score(all_labels, all_pred)} AUC: {roc_auc_score(all_labels, all_pred_raw)}')
    return accuracy_score(all_labels, all_pred)

def main(args):
    batch_size = args['batch_size']
    train_loader = DataLoader(training_set, batch_size, shuffle=True)
    val_loader = DataLoader(validation_set, batch_size, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size, shuffle=False)
    seed_torch(args['seed'])
    device = "cuda" if torch.cuda.is_available() else "cpu"

    model = Model(args).to(device)
    print(model)
    # weights = torch.tensor([1, args['pos_weight']], dtype=torch.float32).to(device)
    # loss_fn = torch.nn.CrossEntropyLoss(weight=weights)
    loss_fn = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.SGD(model.parameters(), lr=args['lr'])
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.95)
    max_acc = 0
    for epoch in range(1, args['epoch'] + 1):
        train(args, model, device, train_loader, optimizer, loss_fn, epoch)
        acc = val(args, model, device, val_loader, optimizer, loss_fn, epoch)
        nni.report_intermediate_result(acc)
        scheduler.step()
        if acc > max_acc:
            max_acc = acc
            print('Saving model (epoch = {:4d}, max_acc = {:.4f})'
                .format(epoch, max_acc))
            torch.save(model.state_dict(), args['save_path'])
    # final result
    model.load_state_dict(torch.load(args['save_path']))
    final_acc = test(model, device, test_loader)
    nni.report_final_result(final_acc)

def get_params():
    # Training settings
    parser = argparse.ArgumentParser(description='atombasedmodel')
    parser.add_argument("--conv_hidden", type=int, default=1024, metavar='CH',
                        help='conv hidden size (default: 1024)')
    parser.add_argument('--lr', type=float, default=0.01, metavar='LR',
                        help='learning rate (default: 0.01)')
    parser.add_argument('--epoch', type=int, default=300, metavar='E',
                        help='number of epochs to train (default: 300)')
    parser.add_argument('--seed', type=int, default=42, metavar='S',
                        help='random seed (default: 42)')
    parser.add_argument('--n_layers', type=int, default=2, metavar='NL',
                        help='conv layer num (default: 2)')
    parser.add_argument('--cls_drop', type=float, default=0.3, metavar='D',
                        help='classification dropout (default: 0.3)')
    parser.add_argument("--readout", type=int, default=0, metavar='P',
                        help='select which readout function (default: 0)')
    parser.add_argument('--save_path', type=str, default='./model', metavar='SP',
                        help='save_path (default: ./model)')
    parser.add_argument('--cls_hidden', type=int, default=1024, metavar='H',
                        help='Linear hidden size defaule 1024')
    parser.add_argument('--batch_size', type=int, default=32, metavar='BN',
                        help='batch size (default: 32)')
    args, _ = parser.parse_known_args()
    return args

if __name__ == "__main__":
    try:
        tuner_params = nni.get_next_parameter()
        logger.debug(tuner_params)
        params = vars(merge_parameter(get_params(), tuner_params))
        logger.info(params)
        params['save_path'] = './model/model_' + nni.get_trial_id()
        main(params)
    except Exception as exception:
        logger.exception(exception)
        raise


import pytest
from pidgin.app import *
from pidgin.errors import NoCoreMetadataException

def test_translate_dict_to_bibtex():
    input = {"object_id": "object_id_test", "key2": "value2", "key3": "value3"}
    output = translate_dict_to_bibtex(input)
    expected = '@misc {object_id_test, object_id = "object_id_test", key2 = "value2", key3 = "value3"}'
    assert output == expected

def test_flatten_dict():
    input = {"data": {"data_type_test": [{"core_metadata_collections": [{"creator": "creator_test", "description": "description_test"}], "file_name_test": "file_name", "object_id": "object_id_test"}]}}
    output = flatten_dict(input)
    expected = {"creator": "creator_test", "description": "description_test", "file_name_test": "file_name", "object_id": "object_id_test"}
    assert output == expected

def test_flatten_dict_without_core_metadata():
    """
    An exception should be raised if the core_metadata_collections field does not contain any data.
    """
    input1 = {'data': {'data_type_test': [{'core_metadata_collections': [], "file_name_test": "file_name", "object_id": "object_id_test"}]}}
    output = flatten_dict(input1)
    expected = {"file_name_test": "file_name", "object_id": "object_id_test"}
    assert output == expected

    input2 = {'data': {'data_type_test': [{"file_name_test": "file_name", "object_id": "object_id_test"}]}}
    output = flatten_dict(input2)
    assert output == expected

def test_flatten_dict_raises_exception():
    """
    An exception should be raised if a requested field was not found for this file. The details of the error should be in the exception message.
    """
    input = {"data": "null", "errors": ["error_details_test"]}
    with pytest.raises(NoCoreMetadataException) as e:
        flatten_dict(input)
    assert 'error_details_test' in e.value.args[0]


from setuptools import setup, find_packages
import os
import re

def read_version():
    # importing gpustat causes an ImportError :-)
    __PATH__ = os.path.abspath(os.path.dirname(__file__))
    with open(os.path.join(__PATH__, 'nomeroff_net/__init__.py')) as f:
        version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                                  f.read(), re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find __version__ string")

# get project version
__version__ = read_version()

# get project long description
with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

# get project requirements list
with open("requirements.txt", "r", encoding="utf-8") as fh:
    requirements = fh.read()
    required_pkgs, required_repos = requirements.split('# git repos')
    required_pkgs = required_pkgs.split()
    required_repos = required_repos.split()

setup(name='nomeroff-net',
      version=__version__,
      description='Automatic numberplate recognition system',
      long_description=long_description,
      long_description_content_type="text/markdown",
      classifiers=[
        'Programming Language :: Python :: 3',
        'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
        "Operating System :: OS Independent",
        'Topic :: Scientific/Engineering :: Artificial Intelligence',
      ],
      keywords='ai nomeroffnet yolov5 craft ocr rnn opensource license number plate recognition '
               'licenseplate numberplate license-plate number-plate ria-com ria.com ria',
      url='https://github.com/ria-com/nomeroff-net',
      author='Dmytro Probachay, Oleg Cherniy',
      author_email='dimabendera@gmail.com, oleg.cherniy@ria.com',
      license='GNU General Public License v3.0',
      packages=find_packages(),
      install_requires=required_pkgs,
      dependency_links=required_repos,
      include_package_data=True,
      python_requires='>=3.7',
      zip_safe=False)


"""
the data server providing the main functionality

author: Martin Weigert
email: mweigert@mpi-cbg.de
"""

from __future__ import absolute_import
from __future__ import print_function
import socket
import six.moves.queue
import threading
import time

from pyclearvolume._serialize import _serialize_data

######   logging stuff
import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.setLevel(logging.INFO)

######

__all__ = ["DataServer"]

class DataServer:
    """
    The main data serving object.

    Basic usage:

    d = DataServer()

    d.start()

    data = linspace(0,100,100**3).reshape((100,100,100))

    d.sendData(data.astype(uint16))

    d.stop()

    """

    _DEFAULT_ADDRESS = ""
    _DEFAULT_PORT = 9140

    _TIMEOUT = .001

    FullQueueError = Exception("Data queue is full and policy was not set to drop!")

    def __init__(self,
                 address = _DEFAULT_ADDRESS,
                 port = _DEFAULT_PORT,
                 maxVolumeNumber = 20,
                 dropVolumeOnFull = True,
                 blocking = True):
        print("creating a server at address '%s' and port '%s'"%(address,port))

        self.sock = socket.socket()
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.setblocking(True)

        self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        self.dataQueue = six.moves.queue.Queue(maxsize = max(1,maxVolumeNumber))
        self.dataThread = _DataServerThread(self.sock, self.dataQueue)
        self.dropVolumeOnFull = dropVolumeOnFull
        self._bind(address,port)

    def _bind(self, address = _DEFAULT_ADDRESS, port = _DEFAULT_PORT):
        logger.debug("binding with address %s at port %s "%(address,port))
        try:
            self.sock.bind((address,port))
        except Exception as e:
            print(e)

        self.sock.listen(10)

    def sendData(self, data, **kwargs):
        """sends array data to the server

        data : a 3d uint16 numpy array

        supported keyword arguments with its defaults:

          "index":0,
          "time": 0,
          "channel": 0,
          "channelname": "python source",
          "color": "1. 1. 1. 1.",
          "viewmatrix": "1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.",
          "dim": 3,
          "type": "Unsigned Byte",
          "bytespervoxel":1,
          "elementsize": 1,
          "voxelwidth": 1,
          "voxelheight": 1,
          "voxeldepth": 1,
          "realunit":1

        """

        logger.debug("put data of shape %s in queue"%str(data.shape))
        logger.debug("meta: %s"%kwargs)

        if self.dataQueue.full():
            if self.dropVolumeOnFull:
                while self.dataQueue.full():
                    self.dataQueue.get(block=True,timeout = self._TIMEOUT)
            else:
                raise self.FullQueueError

        self.dataQueue.put((data, kwargs))

    def is_connected(self):
        return self.dataThread.isconnected

    def client_address(self):
        if self.dataThread.clientAddress:
            try:
                clientIP = self.dataThread.clientAddress
                clientName = socket.gethostbyaddr(clientIP)[0]
                return clientIP, clientName
            except Exception as e:
                print(e)
        return None, None

    def start(self):
        logger.debug("starting server")
        self.dataThread.start()

    def stop(self,blocking = False):
        self.dataThread.stop(blocking = blocking)
        self.sock.close()

    def serveUntilEmpty(self):
        while not self.dataThread.isempty:
            logger.debug("waiting until empty")
            time.sleep(.5)

    def __del__(self):
        self.stop()

class _DataServerThread(threading.Thread):
    """
    """
    _TIMEOUT = 0.001
    def __init__(self, sock, dataQueue):
        threading.Thread.__init__ (self)
        self.sock = sock
        self.dataQueue  = dataQueue
        self.setDaemon(True)
        self.isempty = False
        self.isconnected = False
        self.clientAddress = None

    def run(self):
        self.isRunning = True
        while self.isRunning:
            logger.debug("[thread] waiting for connection...")
            self.isconnected = False
            conn, addr = self.sock.accept()
            self.isconnected = True
            self.clientAddress = addr[0]
            logger.debug("...connected!")

            logger.debug("[thread] now serving the data...")
            while True:
                try:
                    self.isempty = False
                    data, meta = self.dataQueue.get(block = True, timeout = self._TIMEOUT)
                    logger.debug("[thread] got data in thread...")
                    self.send_data(conn,data, meta)
                    self.dataQueue.task_done()
                except six.moves.queue.Empty:
                    logger.debug("[thread] Queue empty")
                    self.isempty = True
                    # logger.debug("no data :(")
                    # if not self.isRunning:
                    #     break
                except socket.error:
                    logger.debug("[thread] socket broken")
                    break
                time.sleep(.1)
        logger.debug("[thread] closing socket")
        self.sock.close()

    def stop(self, blocking):
        logger.debug("[thread] stopping")
        self.isRunning = False

    def send_data(self,conn,data, meta = {}):
        # print "SEEEEND ", data.shape, meta
        logger.debug("[thread] send_data()")
        conn.sendall(_serialize_data(data, meta))
        #_serialize_data

def test_full():
    import numpy as np

    d = DataServer(maxVolumeNumber=2)
    d.start()
    data = np.zeros((10,)*3)

    d.sendData(data)
    d.sendData(data)
    d.sendData(data)

def test_serve_forever():
    import numpy as np
    import time

    d = DataServer(maxVolumeNumber=2)
    d.start()
    N = 128

    data = np.linspace(0,65000,N**3).reshape((N,)*3).astype(np.uint16)

    t = 0
    while True:
        args = {}
        args["color"] = "%s %s %s 1."%tuple([str(c) for c in np.random.uniform(0,1,3)])
        args["voxelwidth"] = np.random.uniform(.2,1.6)
        args["voxelheight"] = np.random.uniform(.2,1.6)
        args["voxeldepth"] = np.random.uniform(.2,1.6)
        args["time"] = t

        print("sending...")
        print(args)
        d.sendData(data,**args)
        # d.sendData(data)
        time.sleep(2)
        t += 1

if __name__ == '__main__':

    # test_full()

    test_serve_forever()


from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from pagetree.models import Section, PageBlock
from django.template.defaultfilters import slugify

def reorder_pageblocks(request, section_id, id_prefix="pageblock_id_"):
    if request.method != "POST":
        return HttpResponse("only use POST for this")
    section = get_object_or_404(Section, id=section_id)
    keys = list(request.GET.keys())
    keys.sort(key=lambda x: int(x.split('_')[-1]))
    pageblocks = [int(request.GET[k]) for k in keys if k.startswith(id_prefix)]
    section.update_pageblocks_order(pageblocks)
    return HttpResponse("ok")

def reorder_section_children(request, section_id, id_prefix="section_id_"):
    if request.method != "POST":
        return HttpResponse("only use POST for this")
    section = get_object_or_404(Section, id=section_id)
    keys = list(request.GET.keys())
    keys.sort(key=lambda x: int(x.split('_')[-1]))
    children = [int(request.GET[k]) for k in keys if k.startswith(id_prefix)]
    section.update_children_order(children)
    return HttpResponse("ok")

def delete_pageblock(request, pageblock_id, success_url=None):
    block = get_object_or_404(PageBlock, id=pageblock_id)
    section = block.section
    try:
        block.block().delete()
    except AttributeError:
        # if the model has been refactored, we sometimes
        # end up with 'stub' pageblocks floating around
        # that no longer have a block object associated
        # it's nice to still be able to delete them
        # without having to scrap the whole db and start over
        pass
    block.delete()
    section.renumber_pageblocks()
    if success_url is None:
        success_url = "/edit" + section.get_absolute_url()
    return HttpResponseRedirect(success_url)

def edit_pageblock(request, pageblock_id, success_url=None):
    block = get_object_or_404(PageBlock, id=pageblock_id)
    section = block.section
    block.edit(request.POST, request.FILES)
    if success_url is None:
        success_url = "/edit" + section.get_absolute_url()
    return HttpResponseRedirect(success_url)

def edit_section(request, section_id, success_url=None):
    section = get_object_or_404(Section, id=section_id)
    section.label = request.POST.get('label', '')
    section.slug = request.POST.get('slug', slugify(section.label))
    section.save()
    if success_url is None:
        success_url = "/edit" + section.get_absolute_url()
    return HttpResponseRedirect(success_url)

def delete_section(request, section_id, success_url=None):
    section = get_object_or_404(Section, id=section_id)
    if request.method == "POST":
        parent = section.get_parent()
        section.delete()
        if success_url is None:
            success_url = "/edit" + parent.get_absolute_url()
        return HttpResponseRedirect(success_url)
    return HttpResponse("""
<form action="." method="post">Are you Sure?
<input type="submit" value="Yes, delete it" /></form>
""")

def add_pageblock(request, section_id, success_url=None):
    section = get_object_or_404(Section, id=section_id)
    blocktype = request.POST.get('blocktype', '')
    # now we need to figure out which kind of pageblock to create
    for pb_class in section.available_pageblocks():
        if pb_class.display_name == blocktype:
            # a match
            block = pb_class.create(request)
            section.append_pageblock(
                label=request.POST.get('label', ''),
                content_object=block)
    if success_url is None:
        success_url = "/edit" + section.get_absolute_url()
    return HttpResponseRedirect(success_url)

def add_child_section(request, section_id, success_url=None):
    section = get_object_or_404(Section, id=section_id)
    section.append_child(request.POST.get('label', 'unnamed'),
                         request.POST.get('slug', ''))
    if success_url is None:
        success_url = "/edit" + section.get_absolute_url()
    return HttpResponseRedirect(success_url)


"""script to run closest unit tests"""
import os
from subprocess import call, check_output

def find_up(query_dir, string):
    while query_dir is not "/":
        if string in os.listdir(query_dir):
            return query_dir
        else:
            query_dir = os.path.dirname(query_dir)

def unzoom():
    flags = check_output("tmux display-message -p '#F'".split(' '))
    if "Z" in str(flags):
        call("tmux resize-pane -Z", shell=True)

def assemble_command():
    module_dir = find_up(os.getcwd(), "__init__.py")
    try:
        module_name = os.path.basename(module_dir)
        base_dir = find_up(module_dir, "manage.py")
        return "python {}/manage.py test {}".format(base_dir, module_name)
    except AttributeError:
        return None

def main():
    command = assemble_command()
    if command:
        unzoom()
    call(command, shell=True)

if __name__ == "__main__":
    main()


import RPi.GPIO as GPIO
import requests
from signal import pause

#configurando os pinos do raspberry
GPIO.setmode(GPIO.BCM)
led = 4
button = 17

GPIO.setup(led, GPIO.OUT)
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)

#corpo

url = 'http://192.168.1.110/current_state.xml'

#liga e desliga led
def led_on():
    GPIO.output(led,1)

def led_off():
    GPIO.output(led,0)

#funçao post state do botao

def botao_pressed():
    params1 = {
        'button': 0,
    }
    response = requests.post(url, params=params1)

    if response.led == 0:
        led_on()
    else:
        led_off()

def botao_unpressed():
    params1 = {
        'button': 1,
    }
    response = requests.post(url, params=params1)

    if response.led == 1:
        led_off()
    else:
        led_on()

button.when_pressed = botao_pressed()
button.when_released = botao_unpressed()

pause()


#!/usr/bin/env python

"""
Example DaVinci Resolve script:
Adds subclips [frame 0 .. 23] to current timeline for all media pool root folder clips
Example usage: 7_add_subclips_to_timeline.py
"""

from python_get_resolve import GetResolve

if __name__ == "__main__":
    resolve = GetResolve()
    projectManager = resolve.GetProjectManager()
    project = projectManager.GetCurrentProject()
    mediaPool = project.GetMediaPool()
    rootFolder = mediaPool.GetRootFolder()
    clips = rootFolder.GetClipList()

    for clip in clips:
        if clip.GetClipProperty()["Video Codec"] != "":
            subClip = {
                "mediaPoolItem": clip,
                "startFrame": 0,
                "endFrame": 23,
            }

            if mediaPool.AppendToTimeline([ subClip ]):
                print("added subclip (first 24 frames) of \"" + clip.GetName() + "\" to current timeline.")


import pandas as pd
import os
from sklearn.model_selection import StratifiedKFold

####################### cross validation #########################

def cv(dirpath, save_path, dataset, nfold):
    years = [3,5]
    name = ['id','time','status','class']
    data = pd.read_csv(dirpath+f'{dataset}_info.csv',usecols=name[:-1]).values
    for year in years:
        surv  = []
        for i,temp in enumerate(data):
            if temp[2]==-1:
                surv.append(list(data[i])+[2])
                continue
            if temp[2]==1 and int(temp[1]) < year*365:
                surv.append(list(data[i])+[1])
            elif int(temp[1]) >= year*365:
                surv.append(list(data[i])+[0])
            else:
                surv.append(list(data[i])+[2])
        df = pd.DataFrame(columns=name,data=surv)
        save_path = save_path + f'{dataset}_{year}y'
        if not os.path.exists(save_path): os.makedirs(save_path)
        df.to_csv(save_path + '.csv',index=None)

        x = df.values
        y = df['class'].values

        kf = StratifiedKFold(n_splits=nfold,random_state=23,shuffle=True)
        for i, (train_index, test_index) in enumerate(kf.split(x, y)):
            res_train = pd.DataFrame(data=x[train_index])
            res_test = pd.DataFrame(data=x[test_index])
            writer = pd.ExcelWriter(save_path+f'/data_{i}.xlsx')
            eval('res_train').to_excel(excel_writer=writer, sheet_name='train', index=False)
            eval('res_test').to_excel(excel_writer=writer, sheet_name='test', index=False)
            writer.save()
            writer.close()
    return

if __name__ == "__main__":
    dirpath = './data/clinical/'
    save_path = './splits/5_fold_cv/'
    data_list = ['BLCA','COAD','LIHC']
    for dataset in data_list:
        cv(dirpath, save_path, dataset, nfold=5)


from bs4 import BeautifulSoup as soup
from urllib.request import urlopen

def get_vacancies():
    my_url = "https://jobs.dou.ua/vacancies/?category=Python&exp=0-1"

    Client = urlopen(my_url)
    page_html = Client.read()
    Client.close()

    page_soup = soup(page_html, "html.parser")

    vacancies_list = page_soup.findAll("li", {"class": "l-vacancy"})
    vacancies = []
    for vacancy in vacancies_list:
        name = vacancy.div.div.a.get_text()
        city = vacancy.div.div.findAll("span", {"class": "cities"})[0].get_text()
        company = vacancy.div.div.strong.get_text()
        if city in ["Киев", "Київ", "Kyiv"]:
            vacancy = {}
            vacancy["name"] = name
            vacancy["company"] = company
            vacancies.append(vacancy)

    print(vacancies)

get_vacancies()


import requests
import json
import yaml
import time
import math
from tqdm.auto import tqdm

from .extractor import extract_ris
from .converter import to_ris_text, write_file

class RESTClient(object):

    BASE_URL = "https://api.clarivate.com/api/wos"
    defaults = {
        'databaseId': 'WOS',
        'lang': 'en',
        'edition': 'WOS+SCI',
        'firstRecord': 1,
        'count': 100,
        'sort': 'PY',
        'optionView': 'FR'
    }

    def __init__(self, config_fn):
        # assert isinstance(config, dict), "Give configuration as a dictionary"

        with open(config_fn, 'r') as fp:
            config = yaml.safe_load(fp)['restful_wos']
            self.config = config

        if 'wos_expanded' in config:
            self.apikey = config['wos_expanded']
        elif 'wos_lite' in config:
            self.apikey = config['wos_lite']
        else:
            raise ValueError("No valid API key could be found in given config file!")
        # End if

        self._req_header = {
            'X-ApiKey': self.apikey,
            'content-type': 'application/json',
        }

    def query(self, query_string, time_span=None, **kwargs):
        defaults = {
            'databaseId': 'WOK',
            'lang': 'en',
            'edition': 'WOS+SCI',
            'firstRecord': 1,
            'count': 100,
            'sort': 'PY',
            'optionView': 'FR'
        }

        search = kwargs if kwargs else {}
        defaults = self.defaults
        for kw in defaults:
            if kw not in kwargs:
                search.update({kw: defaults[kw]})

        search.update({
            'usrQuery': query_string,
        })

        if time_span:
            search.update({'publishTimeSpan': '{}+{}'.format(time_span[0], time_span[1])})

        # Get first 100 records
        resp_data = self.send_query(search)

        result_info = resp_data['QueryResult']
        num_records = result_info['RecordsFound']
        print("Found {} records, retrieving in batches of 100".format(num_records))

        ris_entries = []
        # Strangely, the initial request return has 'Data', but
        # subsequent requests do not.
        ris_entries = extract_ris(resp_data['Data'], ris_entries)

        REQ_MAX = search['count']
        if num_records > REQ_MAX:
            # Need to request more
            query_id = result_info["QueryID"]

            num_requests = int(math.ceil(num_records / REQ_MAX))
            resp_set = []
            with tqdm(total=num_requests, desc='requesting', unit='requests') as pbar:
                pbar.update(1)  # we've already done 1 request
                while search['firstRecord'] + REQ_MAX <= num_records:
                    search.update(
                        {'firstRecord': search['firstRecord'] + REQ_MAX})

                    # resp_data = self.send_query(search, url='{}/query/{}'.format(self.BASE_URL, query_id))
                    resp_set.append(self.send_query(search, url='{}/query/{}'.format(self.BASE_URL, query_id)))
                    pbar.update(1)
                # End while
            # End pbar

            for i, record in tqdm(enumerate(resp_set), desc='processing'):
                try:
                    resp_data = record
                except Exception as e:
                    print(e)
                    raise Exception(e)

                if 'Records' not in resp_data:
                    print("Unexpected return format:")
                    print(resp_data)
                    continue

                if 'records' not in resp_data['Records']:
                    print("No records found for request: {}".format(i))
                    continue
                ris_entries = extract_ris(resp_data, ris_entries)

        return ris_entries
    # End query()

    def send_query(self, search, url=None):
        if not url:
            url = self.BASE_URL
        response = requests.get(url, params=search, headers=self._req_header)
        status = response.status_code
        if status != 200:
            if status == 504:
                # timeout error
                response = self._handle_timeout(search, url)
            else:
                print("RAW:", str(response.headers))
                raise ValueError("Error when sending query.\nStatus Code: {}\nMessage: {}\nParams: {}".format(
                    response.status_code,
                    response.text,
                    search
                ))

        return response.json()
    # End send_query()

    def _handle_timeout(self, search, url):
        time.sleep(5)  # wait 5 seconds...
        return self.send_query(search, url)

if __name__ == '__main__':

    print("Starting!")

    with open('config.yml', 'r') as fp:
        config = yaml.safe_load(fp)['restful_wos']

    client = RESTClient('config.yml')
    resp = client.query('TS=(uncertain* AND (catchment OR watershed OR water))',
                 time_span=('2018-06-01', '2018-12-31'))

    write_file(to_ris_text(resp), 'ris_output', overwrite=True)

    print("Finished!")


"""Books readers

Revision ID: 942d122658c3
Revises: 58110040ec1b
Create Date: 2022-07-24 15:01:32.280709

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "942d122658c3"
down_revision = "58110040ec1b"
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "books_readers",
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("books", sa.Integer(), nullable=False),
        sa.Column("reader", sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(
            ["books"], ["books.id"], name="fk_books_readers_books_id_books"
        ),
        sa.ForeignKeyConstraint(
            ["reader"], ["readers.id"], name="fk_books_readers_readers_id_reader"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.drop_constraint("fk_books_readers_id_reader", "books", type_="foreignkey")
    op.drop_column("books", "reader")
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column(
        "books", sa.Column("reader", sa.INTEGER(), autoincrement=False, nullable=True)
    )
    op.create_foreign_key(
        "fk_books_readers_id_reader", "books", "readers", ["reader"], ["id"]
    )
    op.drop_table("books_readers")
    # ### end Alembic commands ###


if __name__ == '__main__':
    n = int(input())
    arr = map(int, input().split())

    arr = set(arr)
    arr = list(arr)
    length = len(arr) #cause set() removes duplicates and
                      # now our array has a new length
    arr.sort()
    print(arr[length-2])


#!/usr/bin/python2
# Testing code from https://github.com/1r0dm480/Vigenere-Cipher-Breaker
MAX_KEY_LENGTH_GUESS = 20
alphabet = 'abcdefghijklmnopqrstuvwxyz'

# Returns the Index of Councidence for the "section" of ciphertext given
def get_index_c(ciphertext):

	N = float(len(ciphertext))
	frequency_sum = 0.0

	# Using Index of Coincidence formula
	for letter in alphabet:
		frequency_sum+= ciphertext.count(letter) * (ciphertext.count(letter)-1)

	# Using Index of Coincidence formula
	ic = frequency_sum/(N*(N-1))
	return ic

# Returns the key length with the highest average Index of Coincidence
def get_key_length(ciphertext):
	ic_table=[]

	# Splits the ciphertext into sequences based on the guessed key length from 0 until the max key length guess (20)
	# Ex. guessing a key length of 2 splits the "12345678" into "1357" and "2468"
	# This procedure of breaking ciphertext into sequences and sorting it by the Index of Coincidence
	# The guessed key length with the highest IC is the most porbable key length
	for guess_len in range(MAX_KEY_LENGTH_GUESS):
		ic_sum=0.0
		avg_ic=0.0
		for i in range(guess_len):
			sequence=""
			# breaks the ciphertext into sequences
			for j in range(0, len(ciphertext[i:]), guess_len):
				sequence += ciphertext[i+j]

			ic_sum+=get_index_c(sequence)

		# obviously don't want to divide by zero
		if not guess_len==0:
			avg_ic=ic_sum/guess_len
		ic_table.append(avg_ic)

	# returns the index of the highest Index of Coincidence (most probable key length)
	best_guess = ic_table.index(sorted(ic_table, reverse = True)[0])
	second_best_guess = ic_table.index(sorted(ic_table, reverse = True)[1])
	print(sorted(ic_table, reverse = True)[0])
	print(second_best_guess)
	# Since this program can sometimes think that a key is literally twice itself, or three times itself,
	# it's best to return the smaller amount.
	# Ex. the actual key is "dog", but the program thinks the key is "dogdog" or "dogdogdog"
	# (The reason for this error is that the frequency distribution for the key "dog" vs "dogdog" would be nearly identical)
	if best_guess % second_best_guess == 0:
		return second_best_guess
	else:
		return best_guess

def main():
    f = open("./Input/out.txt","r")
    lines = f.readlines()
    ciphertext = ''.join(x.lower() for x in lines if x.isalpha())
    print("Estimated key size: " + str(get_key_length(ciphertext)))

if __name__ == '__main__':
	main()


import numpy as np
# import tifffile

def l_to_r (folder, folder2, save):
    data = {}
    with open(folder2) as file:
        for line in file:
            key, *value = line.split()
            data[key] = value

    sun = float(data['SUN_ELEVATION'][1])

    for  i in range(9):
        if i+1 != 8:
            print('Image №', i+1, ': ', end = '')
            # arr = tifffile.imread(folder + str(i+1)+'.TIF')
            # arr = np.array(arr)
            arr = np.load(folder + str(i+1)+'.npy')
            Mult = float(data['REFLECTANCE_MULT_BAND_'+str(i+1)][1])
            Add = float(data['REFLECTANCE_ADD_BAND_'+str(i+1)][1])
            c = arr*Mult + Add
            s = c/np.sin(sun)
            band = np.array(s)
            np.save(save + 'Landsat_B' + str(i+1), band)
            print('complite')