#!/usr/bin/env python

"""
Bin codons according to structural features of the corresponding residues.

File outputs:
	- Multiple fasta files for each binning of the codons
	- Multiple files containing average RSA values in different bins
	- csv files of protein and interface properties
"""
import os
from collections import Counter
import pickle
import numpy as np
import pandas as pd
from modeled_PPIs import PPI,Protein,Interface,Residue
from pathlib import Path
import warnings
from tqdm import tqdm

pd.set_option("display.max_rows", 20, "display.max_columns", 20)

def save_averages_for_bins(df,varName,saveDir):
	""" Saves a file with the average monomer and complex RSA value for each bin in binEdges"""
	if not os.path.exists(saveDir):
		os.makedirs(saveDir)

	rsaPath = os.path.join(saveDir,'averages_for_' + varName + '.csv')

	if not os.path.exists(rsaPath):
		with open(rsaPath,"w") as f:
			df.to_csv(rsaPath,index= False,na_rep='NaN')

	return

def bin_codons_two_bins(bin1,name1, bin2, name2, saveDir, strains,RSA_DIR,saveRSA = False,plot=False):
	''' Bin codons into 2 bins, writes a README.txt file with details of the binning, creates a fasta file for each bin
	bin1,name1 	: codons in the first bin and name of first bin
	bin2,name2 	: codons in the second bin and name of second bin
	strains 	: closely related species to use for the dN/dS calculations
	saveDir 	: directory where to save the fasta a readme files
	'''
	bins=[(name1,bin1),(name2,bin2)]

	properties = pd.DataFrame(columns=['bin_name','num_of_residues','RSA_monomer', 'RSA_complex', 'deltaRSA',
							   'interRRC', 'dCenter','dEdges','consurfDB_score','consurfDB_std','consurfDB_resNum','consurfRate4Site_score','consurfRate4Site_std','consurfRate4Site_resNum'])

	# Write the summary text file for all bins
	for name,bin in bins:

		row={}
		row['bin_name']			= name
		row['num_of_residues']		= len(bin)
		row['RSA_monomer']			= float((np.nanmean([float(r.rsaMonomer) for r in bin])))
		row['RSA_complex']			= float((np.nanmean([float(r.rsaComplex) for r in bin])))
		row['deltaRSA']				= float((np.nanmean([float(r.dRsa) for r in bin])))
		row['interRRC']				= float((np.nanmean([float(r.interRRC) for r in bin])))
		row['dCenter']				= float((np.nanmean([float(r.dCenter) for r in bin])))
		row['dEdges']				= float((np.nanmean([float(r.dEdges) for r in bin])))
		row['consurfDB_score']		= float((np.nanmean([float(r.consurfDB_score) for r in bin])))
		row['consurfDB_std']		= float((np.nanstd([float(r.consurfDB_score) for r in bin])))
		row['consurfDB_resNum']		= len([float(r.consurfDB_score) for r in bin if not np.isnan(r.consurfDB_score)])
		row['consurfRate4Site_score']	= float((np.nanmean([float(r.consurf_score) for r in bin])))
		row['consurfRate4Site_std']		= float((np.nanstd([float(r.consurf_score) for r in bin])))
		row['consurfRate4Site_resNum']	= len([float(r.consurf_score) for r in bin if not np.isnan(r.consurf_score)])
		properties = properties.append(row, ignore_index=True)

	properties = properties.astype({"num_of_residues": int})
	properties = properties.astype({"consurfDB_resNum": int})
	properties = properties.astype({"consurfRate4Site_resNum": int})

	df= properties[['consurfDB_score','consurfDB_std','consurfDB_resNum','consurfRate4Site_score','consurfRate4Site_std','consurfRate4Site_resNum']]

	readmeTxT="#All residues in modeled S.cerevisiae PPIs split into two bins: \n#"+name1 +" bin (" +str(len(bin1))+" residues) \n#"+name2+" bin (" +str(len(bin2))+" residues)\n#\nSummary:\n"+str(properties.to_string())
	if not readmeTxT==None:
		ofile = os.path.join(saveDir,'README.txt')
		if not os.path.exists(ofile):
			with open(ofile, 'w') as f:
				f.write(readmeTxT)

	# Write the fasta file for each bin
	for name,bin in bins:
		if len(bin) == 0:
			raise UserWarning('Empty bin: ',varName + '_' + str(dn) + '_to_' + str(up)+".fasta")
			return
		fasta_name = os.path.join(saveDir,str(name)+".fasta")
		if not os.path.exists(fasta_name):
			with open(fasta_name, 'w') as f:
				for strain in strains:
					f.write('>' + strain + '\n')
					f.write(''.join([r.codons[strain] for r in bin]) + '\n')

	# Save RSA
	if saveRSA:
		save_averages_for_bins(properties,"interfacial_vs_nonInterfacial",RSA_DIR)

	# # Visualize the binning
	# if plot:
	# 	barPlots(buckets,binEdges,varName,saveDir)

	return df

def bin_interf_vs_nonInterf(modeledPPIs,FASTA_DIR,strains,RSA_DIR,saveRSA = False,plot=False):
	''' Creates directory structure and run the binning for interfacial vs non-interfacial residues in multiple report PPIs

	'''
	fasta_path = os.path.join(FASTA_DIR,"interfacial_vs_non_interfacial")
	if not os.path.exists(fasta_path):
		os.makedirs(fasta_path)

	interf= [res for ppi in modeledPPIs.values() for prot in ppi.proteins for res in prot.residues if res.interfacial == True ]
	noninterf =[res for ppi in modeledPPIs.values() for prot in ppi.proteins for res in prot.residues if res.interfacial == False ]

	df = bin_codons_two_bins(interf,"interfacial",noninterf,"non_interfacial",fasta_path,strains,RSA_DIR,saveRSA = saveRSA,plot=plot)

	return df

def bin_codons(residueVar, binEdges, modeledPPIs, varName, strains, saveDir,RSA_DIR,residueType,
			   saveRSA=False,readmeTxT=None,plot=False):
	"""Bin codons by a single continuous residue-level variable and save them.

	Saves the bins for each of the protein and residue level categories.

	Args:
		residueVar (function): call to access value of residue variable.
		binEdges (list(float)): edges of the bins.
		modeledPPIs (dict(modeledPPIs))
		varName (str): name of variable that is binned on.
		strains: yeast strains to use in evolutionary rate calculations
		saveDir
		fNames (str): overwrite file name.
		saveRSA (bool): also save the average RSA of each bin
		rsaDir
		residueType (str): type of residues binned (ex: all, interfacial...)

	"""
	print("> Binning by: ",varName)
	if not os.path.exists(saveDir):
		os.makedirs(saveDir)

	if len(binEdges) < 2:
		raise ValueError('Expected at least 2 bin edges')

	residues = [res for ppi in modeledPPIs.values() for prot in ppi.proteins for res in prot.residues]
	bins = [(varName+"_"+str(dn) + '_to_' + str(up),[]) for (dn, up) in zip(binEdges[:-1], binEdges[1:])]
	# Put residues into respective bins
	for r in tqdm(residues):
		val = residueVar(r)
		if val == np.nan or type(val)== str:
			continue
		if val > binEdges[-1]:
			raise UserWarning('Overflow from bin')
		for i, (dn, up) in enumerate(zip(binEdges[:-1], binEdges[1:])):
			if (val <= up and val > dn) or (dn == up and val == dn):
				bins[i][1].append(r)

	properties = pd.DataFrame(columns=['bin_name','num_of_residues','RSA_monomer', 'RSA_complex', 'deltaRSA',
				'interRRC', 'dCenter','dEdges','consurfDB_score','consurfDB_std','consurfDB_resNum','consurfRate4Site_score','consurfRate4Site_std','consurfRate4Site_resNum'])

	# Write the summary text file for all bins
	for name,bin in bins:

		row={}
		row['bin_name']			= name
		row['num_of_residues']		= len(bin)
		row['RSA_monomer']			= float((np.nanmean([float(r.rsaMonomer) for r in bin])))
		row['RSA_complex']			= float((np.nanmean([float(r.rsaComplex) for r in bin])))
		row['deltaRSA']				= float((np.nanmean([float(r.dRsa) for r in bin])))
		row['interRRC']				= float((np.nanmean([float(r.interRRC) for r in bin])))
		row['dCenter']				= float((np.nanmean([float(r.dCenter) for r in bin])))
		row['dEdges']				= float((np.nanmean([float(r.dEdges) for r in bin])))
		row['consurfDB_score']		= float((np.nanmean([float(r.consurfDB_score) for r in bin])))
		row['consurfDB_std']		= float((np.nanstd([float(r.consurfDB_score) for r in bin])))
		row['consurfDB_resNum']		= len([float(r.consurfDB_score) for r in bin if not np.isnan(r.consurfDB_score)])
		row['consurfRate4Site_score']	= float((np.nanmean([float(r.consurf_score) for r in bin])))
		row['consurfRate4Site_std']		= float((np.nanstd([float(r.consurf_score) for r in bin])))
		row['consurfRate4Site_resNum']	= len([float(r.consurf_score) for r in bin if not np.isnan(r.consurf_score)])
		properties = properties.append(row, ignore_index=True)

	properties = properties.astype({"num_of_residues": int})
	properties = properties.astype({"consurfDB_resNum": int})
	properties = properties.astype({"consurfRate4Site_resNum": int})

	df= properties[['consurfDB_score','consurfDB_std','consurfDB_resNum','consurfRate4Site_score','consurfRate4Site_std','consurfRate4Site_resNum']]

	readmeTxT="#"+residueType+" residues in modeled S.cerevisiae PPIs split into "+str(len(bins))+" bins of "+varName+"\n#\n#Summary:\n"+str(properties.to_string())

	if not readmeTxT==None:
		ofile = os.path.join(saveDir,'README.txt')
		if not os.path.exists(ofile):
			with open(ofile, 'w') as f:
				f.write(readmeTxT)

	# Write the fasta file for each bin
	for name,bin in tqdm(bins):
		if len(bin) == 0:
			raise UserWarning('Empty bin: ',varName + '_' + str(dn) + '_to_' + str(up)+".fasta")
			return
		fasta_name = os.path.join(saveDir,str(name)+".fasta")
		if not os.path.exists(fasta_name):
			with open(fasta_name, 'w') as f:
				for strain in strains:
					f.write('>' + strain + '\n')
					f.write(''.join([r.codons[strain] for r in bin]) + '\n')

	# Save RSA
	if saveRSA:
		save_averages_for_bins(properties,varName+"_bins",RSA_DIR)

	# # Visualize the binning
	# if plot:
	# 	barPlots(buckets,binEdges,varName,saveDir)

	return df

def bin_structure(modeledPPIs,FASTA_DIR,strains,RSA_DIR,saveRSA = False,plot=False):
	'''Creates directory structure and run the binning for structural properties '''
	# 1) Directory set up
	if not os.path.exists(FASTA_DIR):
		os.makedirs(FASTA_DIR)
	# fasta_path = os.path.join(FASTA_DIR,"interfacial_vs_non_interfacial")
	# if not os.path.exists(fasta_path):
	# 	os.makedirs(fasta_path)

	# 2) Define the edges of the bins for all categories
	# The value val is included in bin ]dn,up] if (val <= up and val > dn) or (dn == up and val == dn)
	binEdgesRSA_interface = np.arange(0.00, 1.01, 0.05)			# [0,0] bin is empty for interfaces
	binEdgesRSA = np.insert(binEdgesRSA_interface, 0, 0.00) 	# adding a [0,0] bin for all residues
	binEdgesDeltaRSA= np.arange(0.00, 1.01, 0.1)
	binEdgesDeltaRSA= np.insert(binEdgesDeltaRSA, 0, 0.00) 		# adding a [0,0] bin
	binEdgesContacts = [0, 0, 2, 4, 6, 8, 10, 12, 14, 30]
	binEdgesDistance_from_center = [0,10,15,20,25,30,40,50,65,93]
	binEdgesDistance_from_edges = [0,10,15,20,25,30,35,45,65,100]

	# 3) Check numbers and print disclaimer
	allProteins = [prot for ppi in modeledPPIs.values() for prot in ppi.proteins]
	proteinsWithInterface = [prot for prot in allProteins if len(prot.interface)>0]
	proteinsWithoutInterface = [prot for prot in allProteins if len(prot.interface)==0]
	print(len(proteinsWithInterface),"/" ,len(allProteins),"proteins have a modeled interface.")
	print(len(proteinsWithoutInterface),"/" ,len(allProteins),"proteins do not have a modeled interface. Discarded from the interface involvement analysis")

	# 4) Start binning
# - RSA (monomer)
	# All residues
	bin_codons(lambda r: r.rsaMonomer, binEdgesRSA, modeledPPIs, 'rsa_monomer_all', strains,
				saveDir= os.path.join(FASTA_DIR,"rsa_monomer","rsa_monomer_all"),RSA_DIR=RSA_DIR,residueType="All",saveRSA = True,
				readmeTxT = "Monomer RSA, for all residues in all proteins.", plot=False)
	# Only interfacial residues (drsa != 0)
	bin_codons(lambda r: r.rsaMonomer if (r.dRsa > 0.0) else (np.nan), binEdgesRSA_interface, modeledPPIs, 'rsa_monomer_interfacial', strains,
				saveDir= os.path.join(FASTA_DIR,"rsa_monomer","rsa_monomer_interfacial"),RSA_DIR=RSA_DIR,residueType="Interfacial",saveRSA = True,
				readmeTxT = "Monomer RSA, for all interfacial residues in all proteins.", plot=False)
	# Only non-interfacial residues (drsa == 0)
	bin_codons(lambda r: r.rsaMonomer if (r.dRsa == 0.0) else (np.nan), binEdgesRSA, modeledPPIs, 'rsa_monomer_non_interfacial',strains,
				saveDir= os.path.join(FASTA_DIR,"rsa_monomer","rsa_monomer_non_interfacial"),RSA_DIR=RSA_DIR,residueType="Non-interfacial",saveRSA = True,
				readmeTxT = "Monomer RSA, for all non-interfacial residues in all proteins.", plot=False)

# - RSA (complex)
	# All residues
	bin_codons(lambda r: r.rsaComplex, binEdgesRSA, modeledPPIs, 'rsa_complex_all', strains,
				saveDir= os.path.join(FASTA_DIR,"rsa_complex","rsa_complex_all"),RSA_DIR=RSA_DIR,residueType="All",saveRSA = True,
				readmeTxT="Complex RSA, for all residues in all proteins.",plot=False)
	# Only interfacial residues (drsa != 0)
	bin_codons(lambda r: r.rsaComplex if (r.dRsa > 0.0) else (np.nan), binEdgesRSA, modeledPPIs, 'rsa_complex_interfacial' , strains,
				saveDir= os.path.join(FASTA_DIR,"rsa_complex","rsa_complex_interfacial"),RSA_DIR=RSA_DIR,residueType="Interfacial",saveRSA = True,
				readmeTxT="Complex RSA, for all interfacial residues in all proteins.",plot=False)
	# # Only non-interfacial residues (drsa == 0)
	bin_codons(lambda r: r.rsaComplex if (r.dRsa == 0.0) else (np.nan), binEdgesRSA, modeledPPIs, 'rsa_complex_non_interfacial', strains,
				saveDir= os.path.join(FASTA_DIR,"rsa_complex","rsa_complex_non_interfacial"),RSA_DIR=RSA_DIR,residueType="Non-interfacial",saveRSA = True,
				readmeTxT="Complex RSA, for all non-interfacial residues in all proteins.",plot=False)

# - Measures of interface involvement
	# - Delta RSA
	bin_codons(lambda r: r.dRsa, binEdgesDeltaRSA, modeledPPIs,'drsa', strains,
				saveDir= os.path.join(FASTA_DIR,"drsa"),RSA_DIR=RSA_DIR,residueType="All",saveRSA = True,
				readmeTxT='deltaRSA (Difference in solvent accessible surface between complex and monomer state) for all residues in all proteins. [0,0] bin represents non-interfacial residues.',
				plot=False)
	# - Residue contacts
	bin_codons(lambda r: r.interRRC, binEdgesContacts, modeledPPIs,'residueContacts', strains,
				saveDir= os.path.join(FASTA_DIR,"residueContacts"),RSA_DIR=RSA_DIR,residueType="All",saveRSA = True,
				readmeTxT='Residue contacts (Number of contacts with residues in partner protein) for all residues in all proteins. We only have residue contact values for interfacial residues in proteins with a modeled interface',
				plot=False)
	# - Distance from center
	bin_codons(lambda r: r.dCenter, binEdgesDistance_from_center, modeledPPIs,'distance_from_center', strains,
				saveDir= os.path.join(FASTA_DIR,"distance_from_center"), RSA_DIR=RSA_DIR,residueType="All",saveRSA = True,
				readmeTxT='Binning by distance to geometric center of the interface for all residues in all proteins. We only have distance from center values for interfacial residues in proteins with a modeled interface',
				plot=False)
	# - distance from edges
	bin_codons(lambda r: r.dEdges, binEdgesDistance_from_edges, modeledPPIs,'distance_from_edges',strains,
				saveDir= os.path.join(FASTA_DIR,"distance_from_edges"), RSA_DIR=RSA_DIR,residueType="All",saveRSA = True,
				readmeTxT='Binning by distance to edges (most exposed surface in complex state) of the interface for all residues in all proteins. We only have distance from edges values for interfacial residues in proteins with a modeled interface',
				plot=False)

	return

def write_dir_list(FASTA_DIR,parallelize = False):
	'''
	FASTA_DIR: binned_codons directory
	TO EDIT
	NOT WORKING
	'''

	# TODO: Add and check NOT parallelized
	dirs = []
	subdirs = [os.path.join(FASTA_DIR,dir) for dir in os.listdir(FASTA_DIR) if os.path.isdir(os.path.join(FASTA_DIR,dir))]
	subsubdirs = [os.path.join(subdir,subsubdir) for subdir in subdirs for subsubdir in os.listdir(subdir) if os.path.isdir(os.path.join(subdir,subsubdir))]
	subsubdirs = subdirs + subsubdirs

	files= []
	for dir in subsubdirs:
		files = files+[os.path.join(dir,file) for file in os.listdir(dir) if file[0:6] != "README"]
	print(files)
	print(len(files))
	exit()
	if parallelize:
		for i,k,fileNum in zip(files[0::2], files[1::2],range(len(files))):
			fileName = os.path.join(FASTA_DIR,"dir_list"+str(fileNum)+".txt")
			with open(fileName, 'w') as f:
				f.write(i+"\n")
				f.write(k+"\n")
	else:
		# Check?
		for dir,filenum in zip(subsubdirs,range(len(subsubdirs))):
			fileName = os.path.join(FASTA_DIR,"dir_list"+str(fileNum)+".txt")
			with open(fileName, 'w') as f:
				f.write(dir+"\n")

	return

def main():

	path_closely_related = '../data/processed/modeled_ppis.pkl'
	path_additional_closely_related = '../data/processed/modeled_ppis_additional_closely_related.pkl'
	path_additional_distantly_related = '../data/processed/modeled_ppis_additional_distantly_related.pkl'

	closely_related = ['Scer','Sbay', 'Smik', 'Spar','Ncas','Cgla','Agos','Klac','Calb']
	additional_closely_related = ['Scer','Sbay', 'Smik', 'Spar','Ncas','Cgla','Agos','Klac','Calb','Ctro', 'Tpha','Cfab','Ndai','Zrou']
	additional_distantly_related = ['Scer','Sbay', 'Smik', 'Spar','Ncas','Cgla','Agos','Klac','Calb','Fgra','Ncra','Anid','Spom','Nirr','Plac','Pjir','Pmur']

	names= ["","_AdditionalCloseSpecies","_AdditionalDistantSpecies"]
	# Run binning once per model
	for name,modelPath,strains in zip(names,[path_closely_related,path_additional_closely_related,path_additional_distantly_related],[closely_related,additional_closely_related,additional_distantly_related]):
		# Set up
		OUT_DIR = '../data/evolutionary_rates'+name
		FASTA_DIR = os.path.join(OUT_DIR, 'binned_codons')
		RSA_DIR = os.path.join(OUT_DIR, 'RSA_distributions')
		if not os.path.exists(FASTA_DIR):
			os.makedirs(FASTA_DIR)
		# # Load model
		# print ("loading protein models")
		# with open(modelPath, 'rb') as f:
		# 	modeledPPIs = pickle.load(f)
		# print ("protein models loaded")

		# Ignore "RuntimeWarning: Mean of empty slice" due to non-interfacial residues not having some structural prooperties computed
		with warnings.catch_warnings():
			warnings.simplefilter("ignore")

			# # 1) Bin interfacial vs. non interfacial residues
			# df1 = bin_interf_vs_nonInterf(modeledPPIs,FASTA_DIR,strains,RSA_DIR,saveRSA = True,plot=True)

			# # 2) Bin by structural properties
			# bin_structure(modeledPPIs,FASTA_DIR,strains,RSA_DIR,saveRSA = True,plot=True)
			# # bin_all(modeledPPIs,FASTA_DIR,RSA_DIR,strains)

			# 3) Write the directory list
			write_dir_list(FASTA_DIR,parallelize = False)

	# TODO:
	# Visualize the binning?
	# Summary?

	# 	# # 4) Write dir_list files to run dN/dS calculations
	# 	# # 1 file / folder if parallelize = True
	# 	# write_dir_list(parallelize = True)

	# 	# 5) Save summary
	# 	save_summary(scerMult1,scerMult2,scerMult3,scerMult4,scerMult5,spomMult1,spomMult2,spomMult3,spomMult4,spomMult5,scer1,scer2,scer3,scer4,scer5,spom1,spom2,spom3,spom4,spom5)

if __name__ == '__main__':
	main()


from google.cloud import speech
from google.cloud.speech import enums
from google.cloud.speech import types
from os import environ
environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'google-cloud-creds.json'

client = speech.SpeechClient()

# InvalidArgument: 400 Request payload size exceeds the limit: 10485760 bytes.
# tmp $ ffmpeg -i full-audio.wav -ss 00:00:02 -t 00:00:07 -ar 16000 -ac 1 audio.wav

with open('audio.wav', 'rb') as sf:
    soundbytes = sf.read()
    audio = types.RecognitionAudio(content=soundbytes)

auconfig = types.RecognitionConfig(
                enable_word_time_offsets=True,
                language_code='en-US')

response = client.recognize(auconfig, audio)

# for result in response.results:
print('Transcript: {}'.format(result.alternatives[0].transcript))


"""library for DQN utilities and classes"""
import os
import math
from typing import Tuple
from datetime import datetime
import logging
import numpy as np
import torch
from torch import nn
from torchsummary import summary
from pygame.math import Vector2
import matplotlib.pyplot as plt

import ai_wars.constants
from ..constants import (
	MODEL_PATH,
	MAX_NUM_PROJECTILES,
	NUM_PLAYERS,
	DQN_PARAMETER_DICT,
    HIDDEN_NEURONS,
	MAX_ITERS,
	LOG_EVERY
)
from .dqn_models import DQNModelLinear, DQNModelLSTM, DQNModelCNN

UP = Vector2(0, -1)

def gamestate_to_tensor(
	own_name: str,
	players: list[dict[str, any]],
	projectiles: list[dict[str, any]],
	device: str = "cpu"
) -> torch.Tensor:
	"""
	Converts the gamestate to a  torch.Tensor. The tensor consists out of 4-tuples
	of the form (x, y, x_direction, y_direction) for every entity (like ships and bullets).

	Parameters:
		players: The players with their coordinates and directions
		projectiles: The projectiles with their coordinates and directions
		scoreboard: The scoreboard dictionary with the scores of the players
		device: The device the tensor should be stored on (cpu or cuda:0)

	Return:
		gamestate_tensor: the gamestate, converted to a torch.Tensor
	"""
	gamestate_tensor = torch.zeros(
		size=(NUM_PLAYERS + MAX_NUM_PROJECTILES, 4),
		dtype=torch.float32,
		device=device
	)

	# iterate over all players and save their position as well as their direction as 4-tuples
	# the own player is always at index 0
	players_copy = players.copy()
	for i, player in enumerate(players_copy):
		if player["player_name"] == own_name:
			gamestate_tensor[0, 0] = player["position"].x
			gamestate_tensor[0, 1] = player["position"].y
			gamestate_tensor[0, 2] = player["direction"].x
			gamestate_tensor[0, 3] = player["direction"].y
			# remove the own player from the list
			del players_copy[i]
			break

	# iterate over the remaining players
	for i, player in enumerate(players_copy):
		gamestate_tensor[i+1, 0] = player["position"].x
		gamestate_tensor[i+1, 1] = player["position"].y
		gamestate_tensor[i+1, 2] = player["direction"].x
		gamestate_tensor[i+1, 3] = player["direction"].y

	# iterate over all projectiles and save their position as well as their direction as 4-tuples
	# a maximum of MAX_NUM_PROJECTILES can be stored, while the rest is ignored
	# if there are less projectiles, the remaining indices stay filled with zeros
	for i, projectile in enumerate(filter(lambda p: p["owner"] != own_name, projectiles)):
		if i < MAX_NUM_PROJECTILES:
			gamestate_tensor[NUM_PLAYERS + i, 0] = projectile["position"].x
			gamestate_tensor[NUM_PLAYERS + i, 1] = projectile["position"].y
			gamestate_tensor[NUM_PLAYERS + i, 2] = projectile["direction"].x
			gamestate_tensor[NUM_PLAYERS + i, 3] = projectile["direction"].y

	#return torch.round(gamestate_tensor, decimals=-1)
	return gamestate_tensor

def gamestate_to_tensor_relative(
	own_name: str,
	players: list[dict[str, any]],
	projectiles: list[dict[str, any]],
	device: str = "cpu"
) -> torch.Tensor:
	"""
	Converts the gamestate to a  torch.Tensor. The tensor consists out of 4-tuples
	of the form (x, y, x_direction, y_direction) for every entity (like ships and bullets).

	Parameters:
		players: The players with their coordinates and directions
		projectiles: The projectiles with their coordinates and directions
		scoreboard: The scoreboard dictionary with the scores of the players
		device: The device the tensor should be stored on (cpu or cuda:0)

	Return:
		gamestate_tensor: the gamestate, converted to a torch.Tensor
	"""
	gamestate_tensor = torch.zeros(
		size=(NUM_PLAYERS-1 + MAX_NUM_PROJECTILES, 4),
		dtype=torch.float32,
		device=device
	)

	players_copy = players.copy()

	own_player = next(player for player in players_copy if player["player_name"] == own_name)
	position = own_player["position"]
	angle = own_player["direction"].angle_to(UP)

	# iterate over the remaining players
	for i, player in enumerate(filter(lambda p: p["player_name"] != own_name, players_copy)):
		relative_position = (player["position"] - position).rotate(angle)
		relative_direction = player["direction"].rotate(angle)

		gamestate_tensor[i, 0] = relative_position.x
		gamestate_tensor[i, 1] = relative_position.y
		gamestate_tensor[i, 2] = relative_direction.x
		gamestate_tensor[i, 3] = relative_direction.y

	for i, projectile in enumerate(filter(lambda p: p["owner"] != own_name, projectiles)):
		if i < MAX_NUM_PROJECTILES:
			relative_position = (projectile["position"] - position).rotate(angle)
			relative_direction = projectile["direction"].rotate(angle)

			gamestate_tensor[NUM_PLAYERS-1 + i, 0] = relative_position.x
			gamestate_tensor[NUM_PLAYERS-1 + i, 1] = relative_position.y
			gamestate_tensor[NUM_PLAYERS-1 + i, 2] = relative_direction.x
			gamestate_tensor[NUM_PLAYERS-1 + i, 3] = relative_direction.y

	return gamestate_tensor

def save_model(model: nn.Sequential, name: str) -> None:
	"""
	Helper function to save a pytorch model to a specific path.

	Arguments:
		model: Pytorch Sequential Model
		path:  Path-string where the model should be saved

	Returns:
		None
	"""
	path = MODEL_PATH + name

	# check if the path already exists, if not create it
	if not os.path.exists(os.path.split(path)[0]):
		os.mkdir(os.path.split(path)[0])

	# extract the state_dict from the model to save it
	model_state = {
		"model": model.state_dict()
	}

	torch.save(model_state, path)

	# logging.info("Saved target network with name %s", name)

def get_model_linear(device: str, input_dim: int, output_dim: int, player_name: str) -> nn.Module:
	"""
	Helper function to create a new model and copy it onto a specific device.

	Arguments:
		device: device string
		input_dim: input dimension of the model
		output_dim: output dimension of the model
		player_name: name of the network

	Returns:
		model: Pytorch Sequential Model
	"""
	loading_path = MODEL_PATH+player_name
	if ai_wars.constants.PARAM_SEARCH:
		hidden_neurons = DQN_PARAMETER_DICT[player_name]["hidden_neurons"]
	else:
		hidden_neurons = HIDDEN_NEURONS

	# create an empty new model
	model = DQNModelLinear(input_dim, hidden_neurons, output_dim)
	logging.debug("Created new model on %s", device)

	# check if a model with the player_name already exists and load it
	if os.path.isfile(loading_path):
		model_state = torch.load(loading_path, map_location=lambda storage, loc: storage)
		model.load_state_dict(model_state["model"], strict=True)
		logging.debug("Loaded model from %s", loading_path)

	logging.debug(summary(model, (input_dim,), device="cpu"))

	return model.to(device)

def get_model_cnn(device: str, input_dim: int, output_dim: int, player_name: str) -> nn.Module:
	"""
	Helper function to create a new model and copy it onto a specific device.

	Arguments:
		device: device string
		input_dim: input dimension of the model
		output_dim: output dimension of the model
		player_name: name of the network

	Returns:
		model: Pytorch Sequential Model
	"""
	loading_path = MODEL_PATH+player_name

	# create an empty new model
	model = DQNModelCNN(input_dim, output_dim)
	logging.debug("Created new model on %s", device)

	# check if a model with the player_name already exists and load it
	if os.path.isfile(loading_path):
		model_state = torch.load(
			loading_path, map_location=lambda storage, loc: storage)
		model.load_state_dict(model_state["model"], strict=True)
		logging.debug("Loaded model from %s", loading_path)

	logging.debug(summary(model, (1, 75, 100), device="cpu"))

	return model.to(device)

def get_model_lstm(device: str, num_features: int, sequence_length: int,
				   output_dim: int, player_name: str) -> nn.Module:
	"""
	Helper function to create a new model and copy it onto a specific device.

	Arguments:
		device: device string
		input_dim: input dimension of the model
		output_dim: output dimension of the model
		player_name: name of the network

	Returns:
		model: Pytorch Sequential Model
	"""
	loading_path = MODEL_PATH+player_name

	# create an empty new model
	model = DQNModelLSTM(num_features, sequence_length, output_dim)
	logging.debug("Created new model on %s", device)

	# check if a model with the player_name already exists and load it
	if os.path.isfile(loading_path):
		model_state = torch.load(loading_path, map_location=lambda storage, loc: storage)
		model.load_state_dict(model_state["model"], strict=True)
		logging.debug("Loaded model from %s", loading_path)

	return model.to(device)

def get_nearest_neighbour(own_name: str, players: dict) -> Tuple[float, float, float, float]:
	"""
	Iterates over every enemy and returns the coords and rotation of the nearest neighbour

	Parameters:
		torch.tensor: Gamestate

	Returns:
		(float, float, float, float): (x, y, x_direction, y_direction)
	"""
	players_copy = players.copy()
	best_distance = float("inf")
	nearest_player = torch.tensor([0., 0.], dtype=torch.float)
	own_player = next(player for player in players_copy if player["player_name"] == own_name)
	own_player_pos = torch.tensor([own_player["position"].x,
								   own_player["position"].y],
								   dtype=torch.float)

	# iterate over every other "player" tensor in the whole gamestate
	for player in players_copy:
		if player["player_name"] != own_name:
			tmp_player_vec = torch.tensor([player["position"].x,
                                  		   player["position"].y],
										   dtype=torch.float)

			tmp_distance = (own_player_pos - tmp_player_vec).pow(2).sum().sqrt()
			if tmp_distance < best_distance:
				nearest_player = torch.tensor([player["position"].x, player["position"].y])

	return nearest_player

def get_ordered_neighbours(own_name: str, players: dict) -> Tuple[float, float, float, float]:
	"""
	Iterates over every enemy and returns the coords and rotation of the nearest neighbour as an
	ordered Sequence.

	Parameters:
		torch.tensor: Gamestate

	Returns:
		list[players]: ordered list of players according to their distance.
	"""
	ordered_players = []
	players_copy = players.copy()
	own_player = next(player for player in players_copy if player["player_name"] == own_name)
	own_player_pos = torch.tensor([own_player["position"].x,
								   own_player["position"].y],
								   dtype=torch.float)

	# iterate over every other "player" tensor in the whole gamestate
	for player in players_copy:
		if player["player_name"] != own_name:
			tmp_player_vec = torch.tensor([player["position"].x,
                                  		   player["position"].y],
										   dtype=torch.float)

			distance = (own_player_pos - tmp_player_vec).pow(2).sum().sqrt()
			# calculate the distance to every player and append them to the list
			ordered_players.append((player, distance))
	# sort the player with descending distance (so lowest distance is on top) and return without dist
	ordered_players.sort(key=lambda x: x[1])
	return [player[0] for player in ordered_players]

def get_dist(own_player: torch.tensor, player: torch.tensor) -> float:
	"""
	Returns the distance between the own ship and the given player

	Parameters:
		torch.tensor([float, float, float, float]): own_player with(x, y, x_dir, y_dir)
		torch.tensor([float, float, float, float]): player with(x, y, x_dir, y_dir)

	Returns:
		float: distance
	"""
	own_player_vec = torch.tensor(
		[own_player[0], own_player[1]], dtype=torch.float)
	player_vec = torch.tensor([player[0], player[1]], dtype=torch.float)

	return (own_player_vec - player_vec).pow(2).sum().sqrt()

def get_angle(own_player: torch.tensor, player: torch.tensor):
	"""
	Returns the angle between the own ship and the given player

	Parameters:
		torch.tensor([float, float, float, float]): own_player with(x, y, x_dir, y_dir)
		torch.tensor([float, float, float, float]): player with(x, y, x_dir, y_dir)

	Returns:
		float: angle
	"""
	player_coords = torch.tensor([player[0], player[1]], dtype=torch.float)
	own_coords = torch.tensor([own_player[0], own_player[1]], dtype=torch.float)
	vector_between_player = player_coords-own_coords
	own_direction = torch.tensor([own_player[2], own_player[3]], dtype=torch.float)

	inner_product = torch.inner(vector_between_player, own_direction)
	player_norm = torch.linalg.vector_norm(vector_between_player)
	own_norm = torch.linalg.vector_norm(own_direction)

	# prevent zero division
	if player_norm == 0.0:
		player_norm += 1e-8
	if own_norm == 0.0:
		own_norm += 1e-8

	cos = inner_product / (player_norm * own_norm)
	angle = torch.acos(torch.clamp(cos, -1+1e-8, 1-1e-8))

	assert math.isnan(angle) is False, "Player angle is NaN"
	return angle

def get_oriented_angle(own_player: torch.tensor, player: torch.tensor):
	"""
	Returns the angle between the own ship and the given player but with a sign for orientation

	Parameters:
		torch.tensor([float, float, float, float]): own_player with(x, y, x_dir, y_dir)
		torch.tensor([float, float, float, float]): player with(x, y, x_dir, y_dir)

	Returns:
		float: angle
	"""
	player_coords = torch.tensor([player[0], player[1]], dtype=torch.float)
	own_coords = torch.tensor([own_player[0], own_player[1]], dtype=torch.float)
	vector_between_player = player_coords-own_coords
	own_direction = torch.tensor([own_player[2], own_player[3]], dtype=torch.float)

	dot = torch.dot(own_direction, vector_between_player)
	det = own_direction[0]*vector_between_player[1] - vector_between_player[0]*own_direction[1]

	return torch.rad2deg(torch.atan2(det, dot))

def normalize_vals(
	val1: float,
	limit1: float,
	val2: float,
	limit2: float
) -> Tuple[float, float]:
	"""
	Normalizes two values to a new range of [MAX, 0]

	Parameters:
		val1: first value
		val2: second value

	Returns:
		Tuple[float, float]: (val1, val2)
	"""
	new_val1 = ((100-0)*(val1-0) / limit1-0)+0  # distance
	new_val2 = ((100-0)*(val2-0) / limit2-0)+0  # angle

	return new_val1, new_val2

def plot_metrics(scores: torch.Tensor, losses: torch.Tensor, model_name: str) -> None:
	"""
	Plots score and loss for a model over epochs and saves the plot under ./plots/

	Parameters:
		scores: torch.Tensor with the current scores and their associated epochs of a given model
		losses: torch.Tensor with the current loss the associated epochs of a given model
		epoch: current epoch
		model_name: the name of the model

	Returns:
		None
	"""
	if not os.path.exists("plots/"):
		os.mkdir("plots/")

	# plot the scores
	x_labels = np.arange(0, len(scores)*LOG_EVERY, step=LOG_EVERY)
	plt.plot(x_labels, scores)
	plt.title(f"{model_name} Score Metrics")
	plt.ylabel("Score")
	plt.xlabel("Epochs")
	plt.savefig(f"./plots/{model_name}_score.png")
	plt.close()

	# plot the losses
	plt.plot(x_labels, losses)
	plt.title(f"{model_name} Loss Metrics")
	plt.ylabel("Loss")
	plt.xlabel("Epochs")
	plt.savefig(f"./plots/{model_name}_loss.png")
	plt.close()

def log_metrics(score: torch.Tensor, loss: torch.Tensor, epoch: int, model_name: str) -> None:
	"""
	Logs score and loss for a model over epochs and saves the log under ./logs/model_name.log

	Parameters:
		scores: torch.Tensor with the current scoreof a given model
		loss: torch.Tensor with the current loss of a given model
		epoch: current epoch
		model_name: the name of the model

	Returns:
		None
	"""
	if epoch <= MAX_ITERS:
		if not os.path.exists("logs/"):
			os.mkdir("logs/")

		try:
			with open(f"./logs/{model_name}.log", encoding="utf-8", mode="a") as log_file:
				log_file.write(f"{datetime.now().strftime('%A, %d. %B %Y %I:%M%p')} - epoch: {epoch} " \
							f"- score: {score} - loss: {loss:.2f}\n")
		except OSError as error:
			logging.error("Could not write logs into /logs/%s.log - error: %s", model_name, error)


"""
URL configuration for Universitet project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

from .settings import STATIC_ROOT, STATIC_URL, MEDIA_ROOT, MEDIA_URL
from django.conf.urls.static import static

from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_view = get_schema_view(
    openapi.Info(
        title="Universitet Api",
        default_version='v1',
        license=openapi.License(name="BSD License"),
    ),
    public=True,
    permission_classes=[permissions.AllowAny],
)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('auth/', include('users.urls')),
    path('student/', include('student.urls')),
    path('moderator/', include('moderator.urls')),

    path('documentation/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
    path('re_documentation/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),

]

urlpatterns += static(STATIC_URL, document_root=STATIC_ROOT)
urlpatterns += static(MEDIA_URL, document_root=MEDIA_ROOT)


import logging
import requests

class ProxyMiddleware():
    def __init__(self, proxy_url):
        self.logger = logging.getLogger(__name__)
        self.proxy_url = proxy_url

    def get_random_proxy(self):
        try:
            response = requests.get(self.proxy_url)
            if response.status_code == 200:
                proxy = response.text
                return proxy
        except requests.ConnectionError:
            return False

    def process_request(self, request, spider):
        if request.meta.get('retry_times'):
            proxy = self.get_random_proxy()
            if proxy:
                uri = 'http://{proxy}'.format(proxy=proxy)
                self.logger.debug('使用代理 ' + proxy)
                request.meta['proxy'] = uri

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(
            proxy_url=settings.get('PROXY_URL')
        )


from tkinter import *
import PIL
from PIL import Image, ImageDraw
import requests
import io
API_HOST = 'http://10.20.1.216:8787/hr_test'

def get_image_text():
    global image_number
    file_object1 = io.BytesIO()
    file_object2 = io.BytesIO()
    file_object3 = io.BytesIO()
    file_object4 = io.BytesIO()

    image1.save(file_object1, 'png')
    image2.save(file_object2, 'png')
    image3.save(file_object3, 'png')
    image4.save(file_object4, 'png')

    file_object1.seek(0)
    file_object2.seek(0)
    file_object3.seek(0)
    file_object4.seek(0)
    data = {'img_file1': file_object1, 'img_file2': file_object2, 'img_file3': file_object3, 'img_file4': file_object4}
    print(data)
    url = API_HOST
    result = requests.post(url, files=data)
    print(result.text)
    image_number += 1

def activate_paint(e):
    global lastx, lasty
    cv.bind('<B1-Motion>', paint)
    lastx, lasty = e.x, e.y

def activate_paint1(e):
    global lastx1, lasty1
    cv1.bind('<B1-Motion>', paint1)
    lastx1, lasty1 = e.x, e.y

def activate_paint2(e):
    global lastx2, lasty2
    cv2.bind('<B1-Motion>', paint2)
    lastx2, lasty2 = e.x, e.y

def activate_paint3(e):
    global lastx3, lasty3
    cv3.bind('<B1-Motion>', paint3)
    lastx3, lasty3 = e.x, e.y

def paint(e):
    global lastx, lasty
    x, y = e.x, e.y
    cv.create_line((lastx, lasty, x, y), width=1)
    #  --- PIL
    draw.line((lastx, lasty, x, y), fill='black', width=2)
    lastx, lasty = x, y

def paint1(e):
    global lastx1, lasty1
    x, y = e.x, e.y
    cv1.create_line((lastx1, lasty1, x, y), width=1)
    #  --- PIL
    draw1.line((lastx1, lasty1, x, y), fill='black', width=2)
    lastx1, lasty1 = x, y

def paint2(e):
    global lastx2, lasty2
    x, y = e.x, e.y
    cv2.create_line((lastx2, lasty2, x, y), width=1)
    #  --- PIL
    draw2.line((lastx2, lasty2, x, y), fill='black', width=2)
    lastx2, lasty2 = x, y

def paint3(e):
    global lastx3, lasty3
    x, y = e.x, e.y
    cv3.create_line((lastx3, lasty3, x, y), width=1)
    #  --- PIL
    draw3.line((lastx3, lasty3, x, y), fill='black', width=2)
    lastx3, lasty3 = x, y

root = Tk()

lastx, lasty = None, None
lastx1, lasty1 = None, None
lastx2, lasty2 = None, None
lastx3, lasty3 = None, None
image_number = 0

cv = Canvas(root, width=224, height=224, bg='white')
cv1 = Canvas(root, width=224, height=224, bg='white')
cv2 = Canvas(root, width=224, height=224, bg='white')
cv3 = Canvas(root, width=224, height=224, bg='white')

# --- PIL
image1 = PIL.Image.new('RGB', (224, 224), 'white')
image2 = PIL.Image.new('RGB', (224, 224), 'white')
image3 = PIL.Image.new('RGB', (224, 224), 'white')
image4 = PIL.Image.new('RGB', (224, 224), 'white')

draw = ImageDraw.Draw(image1)
draw1 = ImageDraw.Draw(image2)
draw2 = ImageDraw.Draw(image3)
draw3 = ImageDraw.Draw(image4)

cv.bind('<1>', activate_paint)
cv1.bind('<1>', activate_paint1)
cv2.bind('<1>', activate_paint2)
cv3.bind('<1>', activate_paint3)

cv.pack(expand=YES, fill=BOTH)
cv1.pack(expand=YES, fill=BOTH)
cv2.pack(expand=YES, fill=BOTH)
cv3.pack(expand=YES, fill=BOTH)

btn_save = Button(text="GetImageText", command=get_image_text)
btn_save.pack()

root.mainloop()


#!/export/b18/ssadhu/tools/python/bin/python3
# -*- coding: utf-8 -*-
"""

@author: samiksadhu
"""

'Computing Joint Histogram of features and Labels'

import argparse
import numpy as np
import bisect
import os
import kaldi_io
import pickle as pkl

def get_minmax(feat_dict):
    feat_min = +np.inf
    feat_max = -np.inf
    for key in feat_dict:
        one_max = np.max(feat_dict[key])
        one_min = np.min(feat_dict[key])
        if one_max > feat_max:
            feat_max = one_max
        if one_min < feat_min:
            feat_min = one_min

    return feat_min, feat_max

def get_signal_label_joint_distribution(alis, feats, minmax_ali, minmax_feat, feat_dim=80, num_bins=100):
    mnx_a = pkl.load(open(minmax_ali, 'rb'))
    mnx_f = pkl.load(open(minmax_feat, 'rb'))
    mn_a, mx_a = mnx_a['min'], mnx_a['max']
    mn_f, mx_f = mnx_f['min'], mnx_f['max']
    sig_bins = np.linspace(mn_f, mx_f, num_bins + 1)
    dist = np.zeros((feat_dim, num_bins, mx_a))
    nums = len(list(feats.keys()))
    count = 0
    for key in feats:
        count += 1
        print('Processing {:f} % of files'.format(count * 100 / nums))
        # print('min_ali={:d} and max_ali={:d}'.format(np.min(alis[key]), np.max(alis[key])))
        # print('min_f={:f} and max_f={:f}'.format(np.min(feats[key]), np.max(feats[key])))
        for idx, label in enumerate(alis[key]):
            f = feats[key][idx, :]
            for r in range(feat_dim):
                ii = int(bisect.bisect_left(sig_bins, f[r]))
                jj = label - 1
                # print('mn_f={:f} and mx_f={:f}'.format(mn_f, mx_f))
                # print('ii={:d} and jj={:d}'.format(ii,jj))
                if ii == 0:
                    ii = 1
                if ii == num_bins + 1:
                    ii = num_bins
                ii = ii - 1
                dist[r, ii, jj] += 1

    return dist

def get_signal_trans_joint_distribution(alis, feats, minmax_ali, minmax_feat, feat_dim=80, num_bins=100):
    mnx_f = pkl.load(open(minmax_feat, 'rb'))
    mn_f, mx_f = mnx_f['min'], mnx_f['max']
    sig_bins = np.linspace(mn_f, mx_f, num_bins + 1)
    dist = np.zeros((feat_dim, num_bins, 2))
    nums = len(list(feats.keys()))
    count = 0
    for key in feats:
        count += 1
        print('Processing {:f} % of files'.format(count * 100 / nums))
        for idx, label in enumerate(alis[key]):
            f = feats[key][idx, :]
            for r in range(feat_dim):
                ii = int(bisect.bisect_left(sig_bins, f[r]))
                jj = int(label)
                if ii == 0:
                    ii = 1
                if ii == num_bins + 1:
                    ii = num_bins
                ii = ii - 1
                dist[r, ii, jj] += 1

    return dist

def get_phoneme_labels(ali_dir):
    ali_files = []
    all_ali_dirs = ali_dir.split(',')
    for ali_dir in all_ali_dirs:
        ali_files.extend([os.path.join(ali_dir, f) for f in os.listdir(ali_dir) if f.startswith('ali.')])

    pdf_ali_dict = {}

    for file in ali_files:
        pdf_ali_file = "ark:ali-to-phones --per-frame {} ark:'gunzip -c {} |' ark:- |".format(
            os.path.join(ali_dir, "final.mdl"),
            file)
        pdf_ali_dict.update({u: d for u, d in kaldi_io.read_vec_int_ark(pdf_ali_file)})

    return pdf_ali_dict

def get_transitions(alis):
    trans_dict = {}
    for utt in alis:
        one_ali = alis[utt]
        r_prev = 2222222
        one_trans = np.zeros(one_ali.shape[0])
        for idx, r in enumerate(one_ali):
            if idx > 0:
                if r_prev != r:
                    # There is a transition here
                    one_trans[idx] = 1
                    one_trans[idx - 1] = 1
                    one_trans[idx + 1] = 1
            r_prev = r
        trans_dict[utt] = one_trans

    return trans_dict

def get_feats(feat_scp):
    return {uttid: feats for uttid, feats in kaldi_io.read_mat_scp(feat_scp)}

if __name__ == '__main__':
    parser = argparse.ArgumentParser('Compute Signal-Label Histogram')
    parser.add_argument('scp', help='Feature scp file')
    parser.add_argument('phoneme_ali_dir', help='Phoneme alignment directory')
    parser.add_argument('minmax_ali', help='Alignmnet minmax file')
    parser.add_argument('minmax_feat', help='Feature minmax file')
    parser.add_argument('out_file', help='Output file')
    parser.add_argument("--feat_size", type=int, default=80, help="Feature size")
    parser.add_argument("--analyze_transitions", action="store_true", help="Set to compute MI at transitions")
    args = parser.parse_args()

    all_alis = get_phoneme_labels(args.phoneme_ali_dir)
    if args.analyze_transitions:
        all_alis = get_transitions(all_alis)
    feats = get_feats(args.scp)

    if args.analyze_transitions:
        dist = get_signal_trans_joint_distribution(all_alis, feats, args.minmax_ali, args.minmax_feat,
                                                   feat_dim=args.feat_size, num_bins=100)
    else:
        dist = get_signal_label_joint_distribution(all_alis, feats, args.minmax_ali, args.minmax_feat,
                                                   feat_dim=args.feat_size, num_bins=100)
    pkl.dump(dist, open(args.out_file + '.pkl', 'wb'))


"""
==============================================================
Quantile regression vs. standard and oblique regression forest
==============================================================

An example to generate quantile predictions using an oblique random forest
instance on a synthetic, right-skewed dataset.

"""

from collections import defaultdict

import matplotlib.pyplot as plt
import numpy as np
import scipy as sp
from sklearn.model_selection import train_test_split
from sklearn.utils.validation import check_random_state

from sktree.ensemble import ObliqueRandomForestRegressor

rng = check_random_state(0)

# %%
# Generate the data
# -----------------
# We use a synthetic dataset with 2 features and 5000 samples. The target is
# generated from a skewed normal distribution. (The mean of the distribution
# is to the right of the median.)

n_samples = 5000
a, loc, scale = 5, -1, 1
skewnorm_rv = sp.stats.skewnorm(a, loc, scale)
skewnorm_rv.random_state = rng
y = skewnorm_rv.rvs(n_samples)
X = rng.randn(n_samples, 2) * y.reshape(-1, 1)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)

regr_orf = ObliqueRandomForestRegressor(n_estimators=10, random_state=0)

regr_orf.fit(X_train, y_train)

y_pred_orf = regr_orf.predict(X_test)
# %%
# Generate Quantile Predictions
# -----------------------------
# The idea is for each prediction, the training samples that fell into the same leaf nodes
# are collected then used to generate the quantile statistics for the desired prediction.

# Get the leaf-nodes the training samples fall into
leaf_ids = regr_orf.apply(X_train)
# create a list of dictionary that maps node to samples that fell into it
# for each tree
node_to_indices = []
for tree in range(leaf_ids.shape[1]):
    d = defaultdict(list)
    for id, leaf in enumerate(leaf_ids[:, tree]):
        d[leaf].append(id)
    node_to_indices.append(d)
# drop the X_test to the trained tree and
# get the indices of leaf nodes that fall into it
leaf_ids_test = regr_orf.apply(X_test)
# for each samples, collect the indices of the samples that fell into
# the same leaf node for each tree
y_pred_quantile = []
for sample in range(leaf_ids_test.shape[0]):
    li = [
        node_to_indices[tree][leaf_ids_test[sample][tree]] for tree in range(leaf_ids_test.shape[1])
    ]
    # merge the list of indices into one
    idx = [item for sublist in li for item in sublist]
    # get the y_train for each corresponding id
    y_pred_quantile.append(y_train[idx])
# get the quatile preditions for each predicted sample
y_pred_quantile = [np.quantile(y_pred_quantile[i], 0.5) for i in range(len(y_pred_quantile))]

# %%
# Plot the results
# ----------------
# The plot shows the distribution of the actual target values and the predicted median
# (i.e. 0.5 quantile), and the mean prediction by the regular random forest regressor.
# In this skewed dataset, the median prediction using the quantile method works better at
# predicting the off-centered target distribution than the regular mean prediction.

colors = ["#c0c0c0", "#a6e5ff", "#e7a4f5"]
names = ["Actual", "QRF (Median)", "ORF (Mean)"]
plt.hist([y_test, y_pred_quantile, y_pred_orf], bins=50, color=colors, label=names)
plt.xlabel("Actual and Predicted Target Values")
plt.ylabel("Counts")
plt.legend()
plt.show()


from __future__ import unicode_literals

from django.conf import settings
from django.contrib.auth.models import AnonymousUser

from jobboard.models import Transaction

def hints(request):
    ctx = {
        "hints_enabled": settings.HINTS_ENABLED,
    }
    return ctx

def txns(request):
    ctx = {}
    if not isinstance(request.user, AnonymousUser):
        ctx.update({
            'txns': Transaction.objects.filter(user=request.user.id)
        })
    return ctx


__all__ = [
    'XMLValidator',
    'RelaxNGValidator',
    ]

import os
from tempfile import NamedTemporaryFile

from lp.services.helpers import simple_popen2

class XMLValidator:
    """A validator for XML files against a schema."""

    SCHEMA_ARGUMENT = 'schema'

    def __init__(self, schema_filename):
        """Create a validator instance.

        :param schema_filename: The name of a file containing the schema.
        """
        self.schema_filename = schema_filename
        self._errors = ''

    def validate(self, xml):
        """Validate the string xml

        :return: True, if xml is valid, else False.
        """
        # XXX Abel Deuring, 2008-03-20
        # The original implementation of the validation used the lxml
        # package. Unfortunately, running lxml's Relax NG validator
        # caused segfaults during PQM test runs, hence this class uses
        # an external validator.

        # Performance penalty of the external validator:
        # Using the lxml validator, the tests in this module need ca.
        # 3 seconds on a 2GHz Core2Duo laptop.
        # If the xml data to be validated is passed to xmllint via
        # lp.services.helpers.simple_popen2, the run time
        # of the tests is 38..40 seconds; if the validation input
        # is not passed via stdin but saved in a temporary file,
        # the tests need 28..30 seconds.

        xml_file = NamedTemporaryFile()
        xml_file.write(xml)
        xml_file.flush()
        command = ['xmllint', '--noout', '--nonet',
                   '--%s' % self.SCHEMA_ARGUMENT,
                   self.schema_filename, xml_file.name]
        local_catalog_path = os.path.abspath(
            os.path.join(os.path.dirname(__file__), "tests", "testfiles",
                         "catalog", "catalog"))
        catalogs = " ".join(
            [local_catalog_path, "/etc/xml/catalog"])
        env = {"XML_CATALOG_FILES": catalogs}
        result = simple_popen2(command, '', env=env).strip()

        # The output consists of lines describing possible errors; the
        # last line is either "(file) fails to validate" or
        # "(file) validates".
        parts = result.rsplit('\n', 1)
        if len(parts) > 1:
            self._errors = parts[0]
            status = parts[1]
        else:
            self._errors = ''
            status = parts[0]
        if status == xml_file.name + ' fails to validate':
            return False
        elif status == xml_file.name + ' validates':
            return True
        else:
            raise AssertionError(
                'Unexpected result of running xmllint: %s' % result)

    @property
    def error_log(self):
        """A string with the errors detected by the validator.

        Each line contains one error; if the validation was successful,
        error_log is the empty string.
        """
        return self._errors

class RelaxNGValidator(XMLValidator):
    """A validator for Relax NG schemas."""

    SCHEMA_ARGUMENT = 'relaxng'


"""
 Simple JSON-RPC Client

"""

import socket
import json

def invoke(method, params):
    req = {
        'method': method,
        'params': params
    }
    if json.dumps(req) == 'Error':
        raise AttributeError('Remote method unavailable')
    else:
        return json.dumps(req)

class JSONRPCClient:
    """The JSON-RPC client."""

    def __init__(self, host, port):
        self.sock = socket.socket()
        self.sock.connect((host, port))

    def send(self, msg):
        """Sends a message to the server."""
        self.sock.sendall(msg.encode())
        return self.sock.recv(1024).decode()

    # def add(self, a, b):
    #     return self.send(invoke('add', [a, b]))

    def __getattr__(self, name):
        """Invokes a generic function."""
        def inner(*params):
            return self.send(invoke(name, params))
        return inner

if __name__ == "__main__":

    #while True:
        # Test the JSONRPCClient class
        client = JSONRPCClient('127.0.0.1', 8000)
        #msg = input('> ')
        #res = client.send('{"method": "add", "params": [2, 3]}')
        #res = client.send('{"method": "hello", "params": []}')
        #res = client.send('{"method": "greet", "params": ["Manuel"]}')
        #res = client.send('{"method": "qwe", "params": [2, 3]}')
        #res = client.send('{"method": "mul", "params": [2, 3]}')
        #res = client.send(invoke('add', [2, 3]))
        res = client.add(2, 3)
        print(res)


import os
import numpy
import scipy.spatial

def countrapid():
    path_to_dir = 'C:/Verification/'
    folder = os.walk(path_to_dir)
    for i in folder:
        if i[1]:
            folders = i[1]
    best_rapid = 0
    best_accuracy = 0
    for rapid in range(0, 100):
        TP = 0
        FP = 0
        TN = 0
        FN = 0
        for i in range(0, len(folders)):
            path = path_to_dir + folders[i]
            with open(path + '/etalon.txt') as fin:
                flag = True
                for line in fin:
                    if flag:
                        data = (line.rstrip('\n')).split(' ')
                        flag = False
                    else:
                        data = numpy.vstack((data, (line.rstrip('\n')).split(' ')))
                data = data.astype(float)

            for j in range(0, len(folders)):
                path = path_to_dir + folders[j]
                with open(path + '/etalon.txt') as fin:
                    flag = True
                    for line in fin:
                        if flag:
                            process = (line.rstrip('\n')).split(' ')
                            flag = False
                        else:
                            process = numpy.vstack((process, (line.rstrip('\n')).split(' ')))
                    process = process.astype(float)

                for k in range(data.shape[0]):
                    for curr in range(process.shape[0]):
                        dist = scipy.spatial.distance.correlation(data[k], process[curr])
                        if i == j and k != curr and dist < rapid*0.01:
                            TP += 1
                        elif i == j and k != curr and dist > rapid*0.01:
                            FN += 1
                        elif i != j and dist < rapid * 0.01:
                            FP += 1
                        elif i != j and dist > rapid*0.01:
                            TN += 1
        n = TP + TN + FP + FN
        if TP + FP == 0:
            Precision = 0
        else:
            Precision = TP / (TP + FP)
        if Precision > best_accuracy:
            best_accuracy = TP
            best_rapid = rapid
            Accuracy = (TP + TN) / n
            print("TP "+TP.__str__()+" TN "+TN.__str__()+" FP "+FP.__str__()+" FN "+FN.__str__()+" Accuracy "+ \
                  Accuracy.__str__()+" rapid "+rapid.__str__()+" Precision "+Precision.__str__())
    return best_accuracy, best_rapid

accuracy, rapid = countrapid()
print(accuracy)
print(rapid*0.01)


import sys
import threading
import time

from PyQt5 import QtWidgets
import pomodoro_gui

class App(QtWidgets.QMainWindow, pomodoro_gui.ui_pomodoro):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.stopped = False
        self.skipped = False
        self.timer = True
        self.pomodoros = 1
        self.pushButton.clicked.connect(self.start_timer_thread)
        self.pushButton_2.clicked.connect(self.stop_timer)

    def start_timer_thread(self):
        self.t = threading.Thread(target=self.start_timer())
        self.t.start()

    def stop_timer(self):
        self.t.stop()

    def start_timer(self):
        if self.pomodoros % 4 == 0:
            full_seconds = 60 * 2 # 60 * 15
        else:
            full_seconds = (60 * 3 if self.timer == True else 60 * 1)
        while full_seconds > 0 and not self.stopped:
            minutes, seconds = divmod(full_seconds, 60)
            print("{0:02d}:{1:02d}".format(minutes, seconds))
            #self.label.setText("{0:02d}:{1:02d}".format(minutes, seconds))
            time.sleep(1)
            full_seconds -= 1
        if self.timer:
            self.pomodoros += 1
        self.timer = not self.timer
        self.start_button()

def main():
    app = QtWidgets.QApplication(sys.argv)
    window = App()
    window.show()
    app.exec_()

if __name__ == '__main__':
    main()


import os
import typing

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

def open_img(path: str) -> np.ndarray:
    img = Image.open(path)
    return np.array(img)

def save_img(img: np.ndarray, path: str):
    Image.fromarray(img).save(path)

def count_pixel_level(img: np.ndarray) -> typing.Tuple[np.ndarray, int]:
    level = int(2 ** (8 * img.nbytes / img.size))
    pr = np.zeros(shape=(level,), dtype=int)
    elements, counts = np.unique(img, return_counts=True)
    pr[elements] = counts  # 统计每个灰度值的个数
    return pr, level

def draw_histogram(img: np.ndarray, ax):
    level = int(2 ** (8 * img.nbytes / img.size))
    ax.hist(img.flatten(), bins=level, range=[0, level - 1], density=True, histtype='stepfilled')
    ax.xlim(0, level - 1)

def histogram_equalize(img: np.ndarray, step: int) -> np.ndarray:
    assert len(img.shape) == 2
    pr, level = count_pixel_level(img)
    # 映射到 [0,255] 整数区间
    sk = pr.cumsum() / img.size
    # 映射到 [-0.5, step-0.5] 的区间，再取 round
    sk = sk * step - 0.5
    sk = sk.round()
    sk[sk == step] = step - 1
    # 映射回 [0,255] 整数区间
    sk *= (level - 1) / (step - 1)
    return sk[img].round().astype(np.uint8)

# 使用 CNN 的 im2col 技巧并行化计算
def im2col(im: np.ndarray, kernel_size, stride, inner_stride=(1, 1)) -> np.ndarray:
    kh, kw = kernel_size
    sh, sw = stride
    ish, isw = inner_stride
    h, w = im.shape[0:2]
    assert (h - kh * ish) % sh == 0
    assert (w - kw * isw) % sw == 0
    out_h = (h - kh * ish) // sh + 1
    out_w = (w - kw * isw) // sw + 1
    out_shape = (out_h, out_w, kh, kw) + im.shape[2:]
    s = im.strides
    out_stride = (s[0] * sh, s[1] * sw, s[0] * ish, s[1] * isw) + s[2:]
    col_img = np.lib.stride_tricks.as_strided(im, shape=out_shape, strides=out_stride)
    return col_img

def mean_filter(img: np.ndarray, n: int = 1) -> np.ndarray:
    for i in range(n):
        img = np.pad(img, [(1, 1), (1, 1)] + [(0, 0)] * (len(img.shape) - 2), mode='edge')
        img_im2col = im2col(img, kernel_size=(3, 3), stride=(1, 1))
        img = img_im2col.mean(axis=(2, 3))
    return img.round().astype(np.uint8)

def median_filter(img: np.ndarray, n: int = 1) -> np.ndarray:
    extra_dim_num = img.ndim - 2
    for i in range(n):
        img_pad = np.pad(img, [(1, 1), (1, 1)] + [(0, 0)] * extra_dim_num, mode='edge')
        img2col = im2col(img_pad, kernel_size=(3, 3), stride=(1, 1))
        img = np.median(img2col, axis=(2, 3))
    return img.round().astype(np.uint8)

def sharpen(img: np.ndarray) -> np.ndarray:
    extra_dim_num = img.ndim - 2
    operand = np.array([
        [-1, -1, -1],
        [-1, 8, -1],
        [-1, -1, -1],
    ]).reshape((1, 1, 3, 3) + (1,) * extra_dim_num)
    img_pad = np.pad(img, [(1, 1), (1, 1)] + [(0, 0)] * extra_dim_num, mode='edge')
    img2col = im2col(img_pad, kernel_size=(3, 3), stride=(1, 1))
    img = img + (img2col.astype(np.int16) * operand).sum(axis=(2, 3))
    img = np.clip(img, 0, 255)
    return img.astype(np.uint8)

if __name__ == '__main__':
    img = open_img('img/bridge.jpg')
    name, ext = os.path.splitext('bridge.jpg')
    fig, axes = plt.subplots(4, 2, figsize=(15, 20))
    axes[0, 0].imshow(img, cmap='gray')
    axes[0, 0].set_title('Origin')
    draw_histogram(img, axes[0, 1])
    for i, n in enumerate([2, 64, 256]):
        img_hist_eq = histogram_equalize(img, n)
        axes[i + 1, 0].imshow(img_hist_eq, cmap='gray')
        axes[i + 1, 0].set_title(f'n={n}')
        draw_histogram(img_hist_eq, axes[i + 1, 1])
        save_img(
            img_hist_eq,
            os.path.join('result', f'{name}_hist_eq_{n}{ext}')
        )
    fig.tight_layout()
    fig.savefig('pic/bridge_show.jpg')

    img = open_img('img/circuit.jpg')
    name, ext = os.path.splitext('circuit.jpg')
    print('waiting filtering...')
    fig, axes = plt.subplots(4, 5, figsize=(20, 16))
    axes = axes.reshape(2, 10)
    axes[0, 0].imshow(img, cmap='gray')
    axes[0, 0].set_title('Origin')
    axes[1, 0].imshow(img, cmap='gray')
    axes[1, 0].set_title('Origin')
    for i, n in enumerate([1, 2, 5, 10, 50, 100, 500, 1000, 10000]):
        img_mean = mean_filter(img, n=n)
        img_median = median_filter(img, n=n)
        axes[0, i + 1].imshow(img_mean, cmap='gray')
        axes[0, i + 1].set_title(f'n={n}')
        axes[1, i + 1].imshow(img_median, cmap='gray')
        axes[1, i + 1].set_title(f'n={n}')
        save_img(
            img_mean,
            os.path.join('result', f'{name}_mean_filtering_{n}{ext}')
        )
        save_img(
            img_median,
            os.path.join('result', f'{name}_median_filtering_{n}{ext}')
        )
    fig.tight_layout()
    fig.savefig('pic/circuit_show.jpg')

    img = open_img('img/moon.jpg')
    name, ext = os.path.splitext('moon.jpg')
    fig, axes = plt.subplots(1, 2, figsize=(20, 8))
    img_sharpen = sharpen(img)
    axes[0].imshow(img, cmap='gray')
    axes[0].set_title('Origin')
    axes[1].imshow(img_sharpen, cmap='gray')
    save_img(
        img_sharpen,
        os.path.join('result', f'{name}_sharpen{ext}')
    )
    fig.tight_layout()
    fig.savefig('pic/moon_show.jpg')


#!/usr/bin/env python3
# coding: utf-8
__author__ = 'Yee_172'
__data__ = '2017/9/4'

import io
import sys

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# change encoding into utf-8 for correctly printing

POINTS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 101, 102]
POINTS_SHOW = {3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: '10', 11: 'J',\
               12: 'Q', 13: 'K', 14: 'A', 15: '2', 101: 'Joker', 102: '\033[1;31mJoker\033[0m'}
POINTS_FULL = {3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine',\
               10: 'ten', 11: 'jack', 12: 'queen', 13: 'king', 14: 'ace', 15: 'two',\
               101: 'joker', 102: '\033[1;31mjoker\033[0m'}
SUITS = ['D', 'C', 'H', 'S']
SUITS_SHOW = {'D': '\033[1;31m♦\033[0m', 'C': '♣', 'H': '\033[1;31m♥\033[0m', 'S': '♠'}
SUITS_FULL = {'D': 'diamond', 'C': 'club', 'H': 'heart', 'S': 'spade'}

class Card:
    """ Card class """
    def __init__(self, point, suit=None):
        if point not in POINTS:
            raise Exception('Point must in %s!' % str(POINTS))
        if point in POINTS[-2:] and suit is not None:
            raise Exception('Joker has no suit!')
        if point in POINTS[:-2] and suit.upper() not in SUITS:
            raise Exception('Suit must in %s!' % str(SUITS).replace('\'', ''))

        suit = suit if suit is None else suit.upper()
        self.suit = suit
        self.point = point

    def __str__(self, mode='SHOW'):
        """ Return a string represent itself """
        mode = mode.upper()
        if mode not in ['SHOW', 'FULL']:
            raise Exception('Mode must in [SHOW, FULL]!')

        if mode == 'SHOW':
            return POINTS_SHOW[self.point] if self.suit is None\
                else SUITS_SHOW[self.suit] + POINTS_SHOW[self.point]
        if mode == 'FULL':
            return POINTS_FULL[self.point] if self.suit is None\
                else 'the ' + POINTS_FULL[self.point] + ' of ' + SUITS_FULL[self.suit]

    def __eq__(self, other):
        """ Judge if two cards are equal """
        if not isinstance(other, Card):
        	raise Exception('Must compare with Card!')

        return True if self.suit == other.suit and self.point == other.point else False

    def __ne__(self, other):
        """ Judge if two cards are not equal """
        return False if self == other else True


import json
import os
from datetime import datetime
from typing import Union

import boto3
import six
from google.cloud import translate_v2 as translate
from lambda_decorators import cors_headers

@cors_headers
def main(event, context):
    data = json.loads(event['body'])

    required_parameters = ['values', 'target_language']
    for parameter in required_parameters:
        if parameter not in data or not data[parameter]:
            return {
                "statusCode": 422,
                "body": json.dumps({"message": "'" + parameter + "' is required."})
            }
    if isinstance(data['values'], six.string_types) is not True:
        return {
            "statusCode": 422,
            "body": json.dumps({"message": "'values' should be string."})
        }

    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table(os.environ['DB_TRANSLATIONS'])

    result = table.get_item(Key={
        'text': data['values'],
        'targetLanguage': data['target_language']
    }).get('Item')

    if result is None or data.get('force') is True:
        translate_client = translate.Client()
        if isinstance(data['values'], six.binary_type):
            data['values'] = data['values'].decode('utf-8')
        try:
            response: Union[str, list, dict] = translate_client.translate(
                values=data['values'],
                target_language=data['target_language'],
                format_=data.get('format_'),
                source_language=data.get('source_language'),
                customization_ids=data.get('customization_ids'),
                model=data.get('model'))
        except ValueError:
            return {
                "statusCode": 422,
                "body": json.dumps({"message": "the number of values and translations differ"})
            }
        except:
            return {
                "statusCode": 500,
                "body": json.dumps({"message": "Failed to get translation."})
            }

        if result is None:
            timestamp = str(datetime.utcnow().timestamp())
            item = {
                'text': data['values'],
                'targetLanguage': data['target_language'],
                'detectedSourceLanguage': data.get('source_language') if response.get('detectedSourceLanguage') is None else response.get('detectedSourceLanguage'),
                'translatedText': response.get('translatedText'),
                'model': data.get('model'),
                'createdAt': timestamp,
                'updatedAt': timestamp
            }
            table.put_item(Item=item)

            result = item
        else:
            expression_attribute_names = {}
            expression_attribute_values = {}
            update_expression_items = []
            response['detectedSourceLanguage'] = data.get('source_language') if response.get('detectedSourceLanguage') is None else response.get('detectedSourceLanguage')
            for key in ['detectedSourceLanguage', 'translatedText', 'model']:
                if key in response and response.get(key) is not None:
                    result[key] = response.get(key)
                    expression_attribute_names['#k' + key] = key
                    expression_attribute_values[':v' + key] = response[key]
                    update_expression_items.append('#k' + key + ' = ' + ':v' + key)
            update_expression = 'SET ' + ','.join(update_expression_items)

            if len(update_expression_items) > 0:
                timestamp = str(datetime.utcnow().timestamp())
                expression_attribute_values[':updatedAt'] = timestamp
                update_expression = update_expression + ', updatedAt = :updatedAt'
                table.update_item(
                    Key={
                        'text': data['values'],
                        'targetLanguage': data['target_language']
                    },
                    ExpressionAttributeNames=expression_attribute_names,
                    ExpressionAttributeValues=expression_attribute_values,
                    UpdateExpression=update_expression,
                    ReturnValues='ALL_NEW',
                )

    return {
        "statusCode": 200,
        "body": json.dumps(result)
    }


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jul  1 11:18:29 2019

# temp and humidity
# https://tutorials-raspberrypi.com/raspberry-pi-measure-humidity-temperature-dht11-dht22/
# https://www.raspberrypi-spy.co.uk/2017/09/dht11-temperature-and-humidity-sensor-raspberry-pi/

@author: alexander
"""
from __future__ import print_function

from time import sleep
import Adafruit_DHT
from common import CONFIGURATION
p = CONFIGURATION()

#%% temp and humidity
def dht11(correct=[0,0]):
    "returns (temperature, humidity)"
    "correct is (0,0) - for adjusting TEMP and HUMIDITY"

    humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT11, p.pins.DHT11)
    while temperature is None:
        sleep (0.02)
        humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT11, p.pins.DHT11)

    # overwriting correct for temp / hum
    if hasattr(p,'temperature'):
        correct = [int(p.temperature.adjustment_temp) if hasattr(p.temperature,'adjustment_temp') else correct[0],
                   int(p.temperature.adjustment_hum) if hasattr(p.temperature,'adjustment_hum') else correct[1]]

    return (int(temperature + correct[0]), int(humidity + correct[1])) # dht is accurate to 1

def Temp():
    "compatibility"
    return dht11()[0]

def Humidity():
    "compatibility"
    return dht11()[1]

#%%
if __name__ == '__main__':
    print (dht11())


# This project is licensed under the MIT License.

"""
.. module:: pkgbuild
   :synopsis: Represent local or AUR-based PKGBUILDs.

.. moduleauthor:: James Reed <jcrd@tuta.io>
"""

from collections import namedtuple
from enum import Enum, auto
from pathlib import Path
from shutil import rmtree
from subprocess import run
import logging
import os

from srcinfo.parse import parse_srcinfo
from parse import parse

from .aur import Aur, GitRepo
from .utils import synctree

log = logging.getLogger('pkgbuilder.pkgbuild')

Restriction = namedtuple('Restriction', ['compare', 'version'])

def parse_restriction(pkg):
    """
    Parse package name and version Restriction string.

    :return: A tuple of the package name and a version Restriction tuple
    """
    for c in ['>=', '<=', '>', '<', '=']:
        p = parse('{name}' + c + '{version}', pkg)
        if p:
            return (p.named['name'], Restriction(c, p.named['version']))

    return (pkg, None)

class LocalDir:
    """
    A directory containing local PKGBUILDs.

    :param path: Path to directory
    :param builddir: Path to package build directory
    :param makepkg_conf: Path to makepkg configuration file
    """
    class ProviderNotFoundError(Exception):
        """
        An exception raised when no provider is found for the package name.
        """
        pass

    Package = namedtuple('Package', ['name', 'version'])

    def __init__(self, path, builddir, makepkg_conf=None):
        self.path = path
        self.builddir = builddir
        self.makepkg_conf = makepkg_conf
        self.check_update = True
        self.packages = {}

    def update(self, force=False):
        """
        Parse PKGBUILDs in the directory.

        :param force: Force checking for updates
        :return: A dictionary mapping Package tuples to lists of Pkgbuild \
        objects
        """
        if not self.path:
            return {}
        if not (self.check_update or force):
            return self.packages

        def add_package(pkg, pkgbuild):
            if pkg in self.packages:
                self.packages[pkg].append(pkgbuild)
            else:
                self.packages[pkg] = [pkgbuild]

        with os.scandir(self.path) as dir:
            for entry in dir:
                if not entry.is_dir():
                    continue
                try:
                    pkgbuild = Pkgbuild.new(entry.name, self.builddir,
                                            self.path, Pkgbuild.Source.Local,
                                            self.makepkg_conf)
                except Pkgbuild.NoPkgbuildError:
                    continue
                srcinfo = pkgbuild.srcinfo
                if 'provides' in srcinfo:
                    for p in srcinfo['provides']:
                        s = p.split('=')
                        if len(s) < 2:
                            s.append(srcinfo['pkgver'])
                        add_package(LocalDir.Package(*s), pkgbuild)
                else:
                    add_package(LocalDir.Package(srcinfo['pkgbase'],
                                                 srcinfo['pkgver']),
                                pkgbuild)

        self.check_update = False
        return self.packages

    def providers(self, name, restrictions=[]):
        """
        Get providers for a package with version Restrictions.

        :param name: Package name
        :param restrictions: A list of version Restrictions
        :raises ProviderNotFoundError: Raised when no provider can be found \
        for name
        :return: A list of Pkgbuild objects providing the package
        """
        def restrict_version(v, restrictions):
            for r in restrictions:
                if (r.compare == '>' and not v > r.version) \
                or (r.compare == '<' and not v < r.version) \
                or (r.compare == '=' and not v == r.version) \
                or (r.compare == '>=' and not v >= r.version) \
                or (r.compare == '<=' and not v <= r.version):
                    return False

            return True

        err = {'message': 'Provider for {} not found'.format(name),
               'source': Pkgbuild.Source.Local,
               'version_restrictions': restrictions}

        if not self.packages or not self.path:
            raise LocalDir.ProviderNotFoundError(err)
        for pkg, pkgbuilds in self.packages.items():
            if pkg.name == name \
                    and restrict_version(pkg.version, restrictions):
                return pkgbuilds
        raise LocalDir.ProviderNotFoundError(err)

class Pkgbuild:
    """
    This class represents a local or AUR-based PKGBUILD. It creates the
    directory needed to build the package.
    """
    aur = Aur()

    class NoPkgbuildError(Exception):
        """
        An exception raised when a local directory exists but does not \
        contain a PKGBUILD file.
        """
        pass

    class SourceNotFoundError(Exception):
        """
        An exception raised when no source is found for the package name.
        """
        pass

    class ParseSrcinfoError(Exception):
        """
        An exception raised when parsing a PKGBUILD's srcinfo fails.
        """
        pass

    class Source(Enum):
        """
        Enumeration for local or AUR sources.
        """
        Local = auto()
        Aur = auto()

    @classmethod
    def new(cls, name, builddir, localdir=None, source=None, makepkg_conf=None):
        """
        Create a new LocalPkgbuild or AurPkgbuild.

        :param name: Package name
        :param builddir: Path to package build directory
        :param localdir: Path to directory of local PKGBUILDs
        :param source: PKGBUILD source - one of Pkgbuild.Source.Local or \
        Pkgbuild.Source.Aur
        :param makepkg_conf: Path to makepkg configuration file
        :raises SourceNotFoundError: Raised when no source can be found for \
        name
        :raises NoPkgbuildError: Raised when a local directory exists but \
        does not contain a PKGBUILD file
        :return: LocalPkgbuild or AurPkgbuild
        """
        err = {'message': 'Directory does not contain a PKGBUILD file'}
        dir = None
        try:
            dir = Path(localdir, name).resolve(True)
            if not Path(dir, 'PKGBUILD').exists():
                err['directory'] = str(dir)
                raise cls.NoPkgbuildError(err)
        except FileNotFoundError:
            pass

        err = {'message': 'Source for {} not found'.format(name)}

        if dir and source != cls.Source.Aur:
            return LocalPkgbuild(name, builddir, dir, makepkg_conf)
        elif source == cls.Source.Local:
            err['source'] = cls.Source.Local
            raise cls.SourceNotFoundError(err)
        else:
            aurpkg = Pkgbuild.aur.get_package(name)
            if aurpkg:
                return AurPkgbuild(name, builddir, aurpkg, makepkg_conf)
            else:
                err['source'] = cls.Source.Aur
                raise cls.SourceNotFoundError(err)

    def __init__(self, name, buildpath, sourcedir, makepkg_conf=None):
        self.name = name
        self.buildpath = Path(buildpath, sourcedir)
        self.makepkg_conf = makepkg_conf
        self.builddir = Path(self.buildpath, self.name)
        self.pkgbuildpath = Path(self.builddir, 'PKGBUILD')
        self.check_update = True
        self._packagelist = []
        self._srcinfo = {}
        self._depends = {}
        self._makedepends = {}

    def remove(self):
        """
        Remove build directory.
        """
        if not self.builddir.exists():
            return
        log.info('%s: Removing build dir... [%s]', self.name, self.builddir)
        rmtree(self.builddir)
        self.check_update = True

    def update(self, force=False):
        """
        Update the build directory. Local sources are synchronized and AUR
        sources are updated via git pull.

        :param force: Force checking for updates
        """
        if not (self.check_update or force):
            return
        if not self.buildpath.exists():
            self.buildpath.mkdir(parents=True)
        if self._update():
            log.info('%s: PKGBUILD [%s -> %s]', self.name, self.uri,
                     self.builddir)
        self.check_update = False

    @property
    def packagelist(self):
        """
        Get a list of paths to packages this PKGBUILD will produce when built.

        :return: A list of paths to packages
        :raises CalledProcessError: Raised if the makepkg command fails
        """
        if self._packagelist:
            return self._packagelist
        self.update()
        cmd = ['makepkg', '--packagelist']
        if self.makepkg_conf:
            cmd += ['--config', self.makepkg_conf]
        r = run(cmd, cwd=self.builddir, capture_output=True, text=True,
                check=True)
        self._packagelist = r.stdout.splitlines()
        return self._packagelist

    @property
    def srcinfo(self):
        """
        Get a srcinfo dictionary corresponding to makepkg --printsrcinfo output.

        :return: The srcinfo dictionary
        :raises CalledProcessError: Raised if the makepkg command fails
        :raises ParseSrcinfoError: Raised if parsing the srcinfo fails
        """
        if self._srcinfo:
            return self._srcinfo

        self.update()
        file = Path(self.builddir, '.SRCINFO')

        mtime = os.path.getmtime
        if file.exists() and not mtime(self.pkgbuildpath) > mtime(file):
            with open(file) as f:
                info = f.read()
        else:
            cmd = ['makepkg', '--printsrcinfo']
            if self.makepkg_conf:
                cmd += ['--config', self.makepkg_conf]
            log.info('%s: Generating .SRCINFO... [%s]', self.name,
                     self.builddir)
            r = run(cmd, cwd=self.builddir, capture_output=True, text=True,
                    check=True)
            info = r.stdout
            with open(file, 'w') as f:
                f.write(info)

        srcinfo, errors = parse_srcinfo(info)

        if errors:
            err = {'message': 'Failed to parse PKGBUILD srcinfo',
                   'errors': errors}
            raise ParseSrcinfoError(err)

        self._srcinfo = srcinfo
        return self._srcinfo

    def _get_depends(self, type):
        """
        Get a given type of package dependencies with Restrictions.

        :param type: One of `depends` or `makedepends`
        :return: A dictionary mapping package names to a list of Restriction \
        objects.
        """
        srcinfo_deps = []
        deps = {}

        try:
            srcinfo_deps += self.srcinfo[type]
        except KeyError:
            pass

        for pkg in srcinfo_deps:
            name, r = parse_restriction(pkg)
            if r:
                if name in deps:
                    if r not in deps[name]:
                        deps[name].append(r)
                else:
                    deps[name] = [r]
            else:
                deps[pkg] = []

        return deps

    @property
    def depends(self):
        """
        Get package dependencies and Restrictions.

        :return: A dictionary mapping package names to a list of Restriction \
        objects.
        """
        if not self._depends:
            self._depends = self._get_depends('depends')

        return self._depends

    @property
    def makedepends(self):
        """
        Get package build dependencies and Restrictions.

        :return: A dictionary mapping package names to a list of Restriction \
        objects.
        """
        if not self._makedepends:
            self._makedepends = self._get_depends('makedepends')

        return self._makedepends

    def dependency_type(self, name):
        """
        Get type of dependency.

        :param name: The package name
        :return: One of `depends` or `makedepends`
        """
        if name in self.depends:
            return 'depends'
        if name in self.makedepends:
            return 'makedepends'

    def dependency_restrictions(self, name):
        """
        Get dependency Restrictions for a package by name.

        :param name: The package name
        :return: A list of Restriction objects
        """
        if name in self.depends:
            return self.depends[name]
        if name in self.makedepends:
            return self.makedepends[name]

        return []

class LocalPkgbuild(Pkgbuild):
    """
    A locally sourced PKGBUILD.

    :param name: Package name
    :param buildpath: Path to build directory
    :param localdir: Path to the directory containing PKGBUILD
    :param makepkg_conf: Path to makepkg configuration file
    """
    def __init__(self, name, buildpath, localdir, makepkg_conf=None):
        super().__init__(name, buildpath, 'local', makepkg_conf)
        self.uri = localdir.as_uri()
        self.localdir = localdir

    def _update(self):
        """
        Synchronize the local PKGBUILD directory with the build directory.

        :return: `True` if the builddir was updated, `False` otherwise
        """
        return synctree(self.localdir, self.builddir)

class AurPkgbuild(Pkgbuild):
    """
    An AUR-based PKGBUILD.

    :param name: Package name
    :param buildpath: Path to build directory
    :param aurpkg: AurPackage for the given package name
    :param makepkg_conf: Path to makepkg configuration file
    """
    def __init__(self, name, buildpath, aurpkg, makepkg_conf=None):
        super().__init__(name, buildpath, 'aur', makepkg_conf)
        self.uri = aurpkg.giturl
        self.aurpkg = aurpkg

    def _update(self):
        """
        Clone the AUR package's git repository to the build directory or update
        it via git pull.

        :return: `True` if the builddir was updated, `False` otherwise
        """
        if self.builddir.exists():
            repo = GitRepo(self.builddir)
            if repo.is_repo():
                if repo.up_to_date():
                    return False
                repo.pull()
            else:
                self.remove()
                self.aurpkg.git_clone(self.builddir)
        else:
            self.aurpkg.git_clone(self.builddir)

        return True


"""
Test script for scheduled_tasks/non_active_tasks
"""

import logging
logger = logging.getLogger('scheduled_tasks_non_active_tasks_test')

import os
import sys
import shutil
import tempfile
import unittest
from functools import partial
from unittest.mock import patch, MagicMock

from tornado.testing import AsyncTestCase
from rest_tools.client import RestClient

from tests.util import unittest_reporter, glob_tests

from iceprod.server.modules.schedule import schedule
from iceprod.server.scheduled_tasks import non_active_tasks

class non_active_tasks_test(AsyncTestCase):
    def setUp(self):
        super(non_active_tasks_test,self).setUp()
        self.test_dir = tempfile.mkdtemp(dir=os.getcwd())
        def cleanup():
            shutil.rmtree(self.test_dir)
        self.addCleanup(cleanup)

        self.cfg = {
            'queue':{
                'init_queue_interval':0.1,
                'submit_dir':self.test_dir,
                '*':{'type':'Test1','description':'d'},
            },
            'master':{
                'url':False,
            },
            'site_id':'abcd',
        }

    @unittest_reporter
    async def test_200_run(self):
        rc = MagicMock(spec=RestClient)
        pilots = {}
        dataset_summaries = {'processing':['foo']}
        task = {'status':'processing','status_changed':'2000-01-01T00:00:00'}
        tasks = {}
        pilots = {}
        async def client(method, url, args=None):
            logger.info('REST: %s, %s', method, url)
            if url.startswith('/dataset_summaries'):
                return dataset_summaries
            elif url.startswith('/pilots'):
                return pilots
            elif url.startswith('/datasets/foo/task_summaries'):
                return tasks
            elif url == '/datasets/foo/tasks/bar' and method == 'GET':
                return task
            elif url == '/datasets/foo/tasks/bar/status' and method == 'PUT':
                client.called = True
                return {}
            elif url.startswith('/logs'):
                return {}
            else:
                raise Exception()
        client.called = False
        rc.request = client

        await non_active_tasks.run(rc, debug=True)
        self.assertFalse(client.called)

        tasks['processing'] = ['bar']
        await non_active_tasks.run(rc, debug=True)
        self.assertTrue(client.called)

        client.called = False
        del dataset_summaries['processing']
        dataset_summaries['truncated'] = ['foo']
        pilots['a'] = {'tasks':['bar']}
        await non_active_tasks.run(rc, debug=True)
        self.assertFalse(client.called)

    @unittest_reporter(name='run() - error')
    async def test_201_run(self):
        rc = MagicMock(spec=RestClient)
        pilots = {'a':{}}
        # try tasks error
        async def client(method, url, args=None):
            logger.info('REST: %s, %s', method, url)
            if url.startswith('/dataset_summaries'):
                return {'processing':['foo']}
            elif url.startswith('/pilots'):
                return pilots
            else:
                raise Exception()
        rc.request = client
        with self.assertRaises(Exception):
            await non_active_tasks.run(rc, debug=True)

        # check it normally hides the error
        await non_active_tasks.run(rc, debug=False)

        # try dataset level error
        async def client(method, url, args=None):
            raise Exception()
        rc.request = client
        with self.assertRaises(Exception):
            await non_active_tasks.run(rc, debug=True)

        # check it normally hides the error
        await non_active_tasks.run(rc, debug=False)

def load_tests(loader, tests, pattern):
    suite = unittest.TestSuite()
    alltests = glob_tests(loader.getTestCaseNames(non_active_tasks_test))
    suite.addTests(loader.loadTestsFromNames(alltests,non_active_tasks_test))
    return suite


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Load the dataset
data = pd.read_csv(r"C:\Users\matt9\Documents\Sublime Text\Machine Learning Practice\household_power_consumption.txt", delimiter=";")

# Explore the dataset
print(data.head())  # Print the first few rows of the dataset

# Perform further analysis or visualization with the dataset
# Example: Plotting a line graph of global active power
plt.plot(data['Global_active_power'])
plt.xlabel('Time')
plt.ylabel('Global Active Power')
plt.title('Household Power Consumption')
plt.show()


import logging
from PyQt5 import QtWidgets
# Importing Search Window - User Interface (created with QtDesigner)
from searchCDFWindow import Ui_Dialog as dialogSearchWind
import os

class searchCDFWindow(QtWidgets.QDialog,dialogSearchWind):
    '''
    This class creates a specific window to look for CDFs and save their paths.
    '''
    def __init__(self, parent = None):

        super(searchCDFWindow,self).__init__(parent)
        self.setupUi(self)

        '''
        Signals of the window
        '''
        self.buttonOneCDF.clicked.connect(self.findOneCDF)
        self.buttonMultipleCDF.clicked.connect(self.findMultipleCDF)
        self.buttonDeletePath.clicked.connect(self.deleteRow)
        self.buttonAccept.clicked.connect(self.returnValue)
        if self.checkSameSampleYes.isChecked():
            self.boolSameSampleRate = True
        else:
            self.boolSameSampleRate = False
        if self.checkReadUnitsYes.isChecked():
            self.boolReadUnits = True
        else:
            self.boolReadUnits = False

        self.checkSameSampleYes.clicked.connect(self.checkRadioButtons)
        self.checkSameSampleNo.clicked.connect(self.checkRadioButtons)
        self.checkReadUnitsYes.clicked.connect(self.checkRadioButtons)
        self.checkReadUnitsNo.clicked.connect(self.checkRadioButtons)
        '''
        Atributes of this class.
        '''
        # List used to return all paths of the CDFs that the user has looked for
        self.listPathCDF = []

    def checkRadioButtons(self):
        if self.checkSameSampleYes.isChecked():
            self.boolSameSampleRate = True
        else:
            self.boolSameSampleRate = False
        if self.checkReadUnitsYes.isChecked():
            self.boolReadUnits = True
        else:
            self.boolReadUnits = False

    def findOneCDF(self):
        '''
        When user does not use any input TXT to look for the CDF. He looks in the specific folder where are located.
        '''
        listPath = QtWidgets.QFileDialog.getOpenFileNames(self, 'Search CDFs', os.getenv('HOME'),
                                           filter='Text files (*.cdf)')[0]

        # Inserting the paths in QListWidget
        for path in listPath:
            if path != '':
                self.listPathCDFWidget.insertItem(0, QtWidgets.QListWidgetItem(path))

    def findMultipleCDF(self):
        '''
        When user looks all CDFs using a specific input TXT
        '''
        logger = logging.getLogger('__main__')
        pathTXT = QtWidgets.QFileDialog.getOpenFileName(self, 'Search TXT with CDF information', os.getenv('HOME'),
                                           filter='Text files (*.txt)')[0]

        if pathTXT != '':
            fileTXT = open(pathTXT, 'r')

            # Reading input TXT
            listNameCDF = []
            listPathCDF = []
            for fileLine in fileTXT.readlines():
                fileLine = fileLine.strip()
                if fileLine == 'CDF_FILES':
                    pass
                elif fileLine == '[end]':
                    break
                else:
                    if fileLine[-3:] == 'cdf':
                        listNameCDF.append(fileLine)
                    else:
                        listPathCDF.append(fileLine)

            if len(listNameCDF) == len(listPathCDF):
                # Inserting the paths in QListWidget
                for index in range(len(listNameCDF)):
                    path = '{}{}{}'.format(listPathCDF[index],os.path.sep, listNameCDF[index])
                    self.listPathCDFWidget.insertItem(0, QtWidgets.QListWidgetItem(path))

            else:
                logger.info('User forgot to write one or more directories of some CDFs in the input...')
                logger.info('Please, check it')
                logger.info('****************************************')

    def deleteRow(self):
        '''
        Delete selected items of QListWidget.
        '''
        listSelectedItems = self.listPathCDFWidget.selectedItems()
        if not listSelectedItems:
            pass
        else:
            for selectedItem in self.listPathCDFWidget.selectedItems():
                self.listPathCDFWidget.takeItem(self.listPathCDFWidget.row(selectedItem))

    def returnValue(self):
        '''
        Return all the paths that are written in the QListWidget
        '''
        for row in range(self.listPathCDFWidget.count()):
            self.listPathCDF.append(self.listPathCDFWidget.item(row).text())
        # Closing the window
        self.close()


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

from torch.nn import BCEWithLogitsLoss, MSELoss
from torch.nn.modules.module import Module

class softCrossEntropy(Module):
    """
    Soft label Cross Entropy Loss
    """
    def __init__(self):
        super(softCrossEntropy, self).__init__()
        return

    def forward(self, inputs, target, weights = None):
        """
        :param inputs: predictions: N * C
        :param target: target labels: N * C
        :param weights: weight: N * C
        :return: loss
        """
        log_likelihood = - F.log_softmax(inputs, dim=1)
        sample_num, class_num = target.shape
        loss = torch.mul(log_likelihood, target)
        if weights is not None:
            loss = torch.mul(loss, weights)
        loss = torch.sum(loss)/sample_num

        return loss

class WeightedMultiLabelBinaryClassification(Module):
    """
    Soft label Multiple binary Classification Loss
    """
    def __init__(self):
        super(WeightedMultiLabelBinaryClassification, self).__init__()
        self.bce = BCEWithLogitsLoss(reduction='none')
        return

    def forward(self, inputs, target, weights = None):
        """
        :param inputs: predictions: N * C
        :param target: target labels: N * C
        :param weights: weight: N * C
        :return: loss
        """
        loss = self.bce(inputs, target)
        sample_num, class_num = target.shape
        if weights is not None:
            loss = torch.mul(loss, weights)
        loss = torch.sum(loss) / sample_num
        return loss

class WeightedMeanSquareError(Module):
    """
    Weighted Mean Square Error
    """
    def __init__(self):
        super(WeightedMeanSquareError, self).__init__()
        self.mse = MSELoss(reduction='none')
        return

    def forward(self, inputs, target, weights = None):
        loss = self.mse(inputs, target)
        sample_num, class_num = target.shape
        if weights is not None:
            loss = torch.mul(loss, weights)
        loss = torch.sum(loss) / sample_num
        return loss

class WeightedNLLLoss(Module):
    """
    Hard Label Cross Entropy Loss
    """
    def __init__(self):
        super(WeightedNLLLoss, self).__init__()
        self.nll = torch.nn.CrossEntropyLoss(reduction='none')
        return

    def forward(self, inputs, target, weights = None):
        target = target.squeeze() if target.dim() == 2 else target
        loss = self.nll(inputs, target)
        sample_num  = target.shape[0]
        if weights is not None:
            weights = self.generate_weights(inputs, weights)
            weights = weights.cuda()
            loss = torch.dot(loss, weights)
        loss = loss / sample_num
        return loss

    def generate_weights(self, outputs, run_time, exp=2.0):
        outputs = torch.nn.functional.log_softmax(outputs, dim=1)
        idx = torch.argmax(outputs, dim=1)
        idx, run_time = idx.cpu().numpy(), run_time.cpu().numpy()

        weights = np.zeros(shape=(idx.shape[0]), dtype=np.float32)
        for i in range(idx.shape[0]):  # iterate for batch
            wei = np.power(run_time[i], exp)  # weight normalization by classes
            wei = wei / np.sum(wei)
            weights[i] = wei[idx[i]]
            # weights[i] = pow(run_time[i][idx[i]], exp)
        # weights = weights / np.sum(weights)
        # print(weights)
        weights = torch.FloatTensor(weights)
        return weights


from flask import Flask, render_template, g,  jsonify, request

import sqlite3

app = Flask(__name__)

DATADB = 'data.db'

@app.route('/')
def index():
    return render_template('index.html')
    db = sqlite3.connect(DATADB)
    print(db)

    colours = []
    cur = db.execute('SELECT id,colours FROM films')
    for row in cur:
        colours.append(list(row))

    db.close()

@app.route('/colourdata', methods=['GET'])
def colours_list():
    #return jsonify('data')

    con = sqlite3.connect(DATADB)
    numbers = []
    cur = con.execute('SELECT percentage FROM films')

    for row in cur:
        numbers.append(list(row))
    con.close()
    print(numbers)
    return (numbers)

# def colours_list():
#     con = sqlite3.connect(DATASDB)
#     colours = []
#     cur = con.execute('SELECT id, colours FROM films')
#
#     rows = cur.fetchall()
#
#     for row in rows:
#         print(row)
#         colours.append(list(row))
#     con.close()
#     return (colours)
#     print(colours)