from HGB import *
from CoreGrids import *
from Evaluation import *
from Grid import *
from GDCF import *
from Kdist import *
from Plot import *
from DataSet import *
from make_Hex import *
from Make_Square import *
from NeighbourGridQuery import *
from NeighbourHex import *
import time
import threading
from sklearn.datasets import make_circles
from sklearn.metrics import pairwise
from sklearn.decomposition import PCA
from sklearn.cluster import DBSCAN
#from sklearn.metrics import rand_score
from sklearn.metrics import adjusted_rand_score
from sklearn.metrics import r2_score
from sklearn.metrics import adjusted_mutual_info_score
from sklearn.metrics import calinski_harabasz_score
from sklearn import metrics
from sklearn.metrics.cluster import normalized_mutual_info_score
import time
import warnings

import numpy as np
import matplotlib.pyplot as plt

from sklearn import cluster, datasets
from sklearn.preprocessing import StandardScaler
from itertools import cycle, islice
import getopt, sys
import pandas as pd
import os
from sklearn.manifold import LocallyLinearEmbedding
from sklearn.cluster import DBSCAN
# from numpyencoder import NumpyEncoder
# --------------------------------------save code--------------------------------------------------
'''countg=0
grid=0
a = None
Neighbour = None
forest = None
cluster_num = 0
gprim=0
Forest=[]
Alltime=0
r1=0
rdb=0
s_obj = {

        "count_g" : countg,
        "neighbour" : Neighbour,
        "a" : a,
        "forest" : forest,
        "cluster_number" : cluster_num,
        "count_gprim" : gprim,
        "forest" : Forest,
        "alltime" : Alltime,
        "rand_index" : r1,
        "rand_indexdb" : rdb

}
save_object = json.dumps(s_obj)

with open("/content/drive/MyDrive/Colab Notebooks/saveobject.json", "w") as outfile:
    outfile.write(save_object)'''

#------------------------------------------------------------------------------------------
# n_samples =1000000

#noisy_circles = datasets.make_circles(n_samples=n_samples, factor=0.5, noise=0.05)

# moons = datasets.make_moons (n_samples=n_samples, shuffle=False, noise=0.05, random_state=None)

# blobs = datasets.make_blobs(n_samples=n_samples, n_features = 2,
#                   centers = 3,cluster_std = 0,random_state=42)

#no_structure = np.random.rand(n_samples, 2), None

# Anisotropicly distributed data
#random_state = 170
#X, y = datasets.make_blobs(n_samples=n_samples, random_state=random_state)
#transformation = [[0.6, -0.6], [-0.4, 0.8]]
#X_aniso = np.dot(X, transformation)
#aniso = (X_aniso, y)

# blobs with varied variances
# varied = datasets.make_blobs(
#    n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state
# )

Dataset = "blob"
Mode = 2
Number_Data = 38000
Noise = 0.05
Random_state = 42
features = 2
Centers = 3
Epsilon = 0.07
Minpoints = 3
argumentList = sys.argv[1:]
i = 0
SortGrids = "LDF"
# Options
options = "d:M:n:N:r:f:c:e:m:i:s:"

# Long options
long_options = ["Dataset", "Mode", "Number_Data", "Noise", "Random_state", "features", "Centers", "Epsilon", "Minpoints","i","SortGrids"]

arguments, values = getopt.getopt(argumentList, options, long_options)

for currentArgument, currentValue in arguments:

    if currentArgument in ("-d", "--Dataset"):
        Dataset = currentValue

    elif currentArgument in ("-M", "--Mode"):
        Mode = currentValue

    elif currentArgument in ("-n", "--Number_Data"):
        Number_Data = currentValue

    elif currentArgument in ("-N", "--Noise"):
        Noise = currentValue

    elif currentArgument in ("-r", "--Random_state"):
        Random_state = currentValue

    elif currentArgument in ("-f", "--features"):
        features = currentValue

    elif currentArgument in ("-c", "--Centers"):
        Centers = currentValue

    elif currentArgument in ("-e", "--Epsilon"):
        Epsilon = currentValue

    elif currentArgument in ("-m", "--Minpoints"):
        Minpoints = currentValue

    elif currentArgument in ("-i", "--i"):
        i = currentValue

    elif currentArgument in ("-s", "--SortGrids"):
        SortGrids = currentValue

Obj = {

    "data" : Dataset,
    "mode_grid" : Mode,
    "n_samples" : Number_Data,
    "noise" : Noise,
    "random_state" : Random_state,
    "features" : features,
    "centers" : Centers,
    "Eps" : Epsilon,
    "Minpts" : Minpoints,
    "i" : i,
    "sort_grids" : SortGrids
}

print(f"mode : {Mode}")
json_object = json.dumps(Obj, indent = 9)
with open("/content/drive/MyDrive/Colab Notebooks/inputobject.json", "w") as outfile:
    outfile.write(json_object)
# --------------------------------------------------------------------------------------------------
with open('/content/drive/MyDrive/Colab Notebooks/inputobject.json', 'r') as openfile:

    # Reading from json file
    json_object = json.load(openfile)

# print(f"mode : {Mode}")
#----------------------moons,blobs,circle----------------------------------
# m = DataSet.data()
# True_label = m[1]
# m = m[0].Data
#----------------------generate random data without label for test---------
# print(f"type(data)1 : {type(m)}")
# m = np.random.RandomState(0).randn( int(json_object["n_samples"]), 2)
# print(f"type(data)2 : {type(m)}")
# print(f"data : {m[0]}")
# print(f"data : {m[1]}")

#------------------------------test data curet-----------------------------
# print("start upload dataset")
# df = pd.DataFrame(pd.read_excel(f'/content/drive/MyDrive/Colab Notebooks/datawithnoise.xlsx'))
# print(df)
# print(type(df))
# records = df.to_numpy()
# result = list(records)
# True_label=[]
# m=[]
# for i in range(len(result)):
#     True_label.append(result[i][2])
#     m.append([result[i][0],result[i][1]])

# print(f"m :{m}")
# print(True_label)
# Data=np.transpose(np.array(m))#type of Data is array and Data is transpose of m
# print(f"Data :{Data}")

# Experiment 1

# for n in [ 2000,  5000 ]:
#     Evaluate(n)

# def Evaluate(n):
#     db = CreateDatabase(n)
#     data = datasets.make_moons(n_samples=n,noise=Noise,random_state=R)
#     result =  RunMethod(db)  # recall , precisiion, ...
#     SaveResult(result)

# file
# n =20000, precision = 0.34 , recall = 0.99, ...

# Experiment 1

dim = int(json_object["features"])
m = DataSet.data()
True_label = m[1]
m = m[0].Data#type of m and True_labels is List
Data=np.transpose(np.array(m))#type of Data is array and Data is transpose of m
print(m)
clustering = DBSCAN(eps= float(json_object["Eps"]), min_samples=int(json_object["Minpts"])).fit(m)
R1 = adjusted_rand_score(True_label, clustering.labels_)
print(R1)
#-----------------------------------start iris---------------------------------------------
# m=[[5.1,3.5,1.4,0.2],
# [4.9,3,1.4,0.2],
# [4.7,3.2,1.3,0.2],
# [4.6,3.1,1.5,0.2],
# [5,3.6,1.4,0.2],
# [5.4,3.9,1.7,0.4],
# [4.6,3.4,1.4,0.3],
# [5,3.4,1.5,0.2],
# [4.4,2.9,1.4,0.2],
# [4.9,3.1,1.5,0.1],
# [5.4,3.7,1.5,0.2],
# [4.8,3.4,1.6,0.2],
# [4.8,3,1.4,0.1],
# [4.3,3,1.1,0.1],
# [5.8,4,1.2,0.2],
# [5.7,4.4,1.5,0.4],
# [5.4,3.9,1.3,0.4],
# [5.1,3.5,1.4,0.3],
# [5.7,3.8,1.7,0.3],
# [5.1,3.8,1.5,0.3],
# [5.4,3.4,1.7,0.2],
# [5.1,3.7,1.5,0.4],
# [4.6,3.6,1,0.2],
# [5.1,3.3,1.7,0.5],
# [4.8,3.4,1.9,0.2],
# [5,3,1.6,0.2],
# [5,3.4,1.6,0.4],
# [5.2,3.5,1.5,0.2],
# [5.2,3.4,1.4,0.2],
# [4.7,3.2,1.6,0.2],
# [4.8,3.1,1.6,0.2],
# [5.4,3.4,1.5,0.4],
# [5.2,4.1,1.5,0.1],
# [5.5,4.2,1.4,0.2],
# [4.9,3.1,1.5,0.1],
# [5,3.2,1.2,0.2],
# [5.5,3.5,1.3,0.2],
# [4.9,3.1,1.5,0.1],
# [4.4,3,1.3,0.2],
# [5.1,3.4,1.5,0.2],
# [5,3.5,1.3,0.3],
# [4.5,2.3,1.3,0.3],
# [4.4,3.2,1.3,0.2],
# [5,3.5,1.6,0.6],
# [5.1,3.8,1.9,0.4],
# [4.8,3,1.4,0.3],
# [5.1,3.8,1.6,0.2],
# [4.6,3.2,1.4,0.2],
# [5.3,3.7,1.5,0.2],
# [5,3.3,1.4,0.2],
# [7,3.2,4.7,1.4],
# [6.4,3.2,4.5,1.5],
# [6.9,3.1,4.9,1.5],
# [5.5,2.3,4,1.3],
# [6.5,2.8,4.6,1.5],
# [5.7,2.8,4.5,1.3],
# [6.3,3.3,4.7,1.6],
# [4.9,2.4,3.3,1],
# [6.6,2.9,4.6,1.3],
# [5.2,2.7,3.9,1.4],
# [5,2,3.5,1],
# [5.9,3,4.2,1.5],
# [6,2.2,4,1],
# [6.1,2.9,4.7,1.4],
# [5.6,2.9,3.6,1.3],
# [6.7,3.1,4.4,1.4],
# [5.6,3,4.5,1.5],
# [5.8,2.7,4.1,1],
# [6.2,2.2,4.5,1.5],
# [5.6,2.5,3.9,1.1],
# [5.9,3.2,4.8,1.8],
# [6.1,2.8,4,1.3],
# [6.3,2.5,4.9,1.5],
# [6.1,2.8,4.7,1.2],
# [6.4,2.9,4.3,1.3],
# [6.6,3,4.4,1.4],
# [6.8,2.8,4.8,1.4],
# [6.7,3,5,1.7],
# [6,2.9,4.5,1.5],
# [5.7,2.6,3.5,1],
# [5.5,2.4,3.8,1.1],
# [5.5,2.4,3.7,1],
# [5.8,2.7,3.9,1.2],
# [6,2.7,5.1,1.6],
# [5.4,3,4.5,1.5],
# [6,3.4,4.5,1.6],
# [6.7,3.1,4.7,1.5],
# [6.3,2.3,4.4,1.3],
# [5.6,3,4.1,1.3],
# [5.5,2.5,4,1.3],
# [5.5,2.6,4.4,1.2],
# [6.1,3,4.6,1.4],
# [5.8,2.6,4,1.2],
# [5,2.3,3.3,1],
# [5.6,2.7,4.2,1.3],
# [5.7,3,4.2,1.2],
# [5.7,2.9,4.2,1.3],
# [6.2,2.9,4.3,1.3],
# [5.1,2.5,3,1.1],
# [5.7,2.8,4.1,1.3],
# [6.3,3.3,6,2.5],
# [5.8,2.7,5.1,1.9],
# [7.1,3,5.9,2.1],
# [6.3,2.9,5.6,1.8],
# [6.5,3,5.8,2.2],
# [7.6,3,6.6,2.1],
# [4.9,2.5,4.5,1.7],
# [7.3,2.9,6.3,1.8],
# [6.7,2.5,5.8,1.8],
# [7.2,3.6,6.1,2.5],
# [6.5,3.2,5.1,2],
# [6.4,2.7,5.3,1.9],
# [6.8,3,5.5,2.1],
# [5.7,2.5,5,2],
# [5.8,2.8,5.1,2.4],
# [6.4,3.2,5.3,2.3],
# [6.5,3,5.5,1.8],
# [7.7,3.8,6.7,2.2],
# [7.7,2.6,6.9,2.3],
# [6,2.2,5,1.5],
# [6.9,3.2,5.7,2.3],
# [5.6,2.8,4.9,2],
# [7.7,2.8,6.7,2],
# [6.3,2.7,4.9,1.8],
# [6.7,3.3,5.7,2.1],
# [7.2,3.2,6,1.8],
# [6.2,2.8,4.8,1.8],
# [6.1,3,4.9,1.8],
# [6.4,2.8,5.6,2.1],
# [7.2,3,5.8,1.6],
# [7.4,2.8,6.1,1.9],
# [7.9,3.8,6.4,2],
# [6.4,2.8,5.6,2.2],
# [6.3,2.8,5.1,1.5],
# [6.1,2.6,5.6,1.4],
# [7.7,3,6.1,2.3],
# [6.3,3.4,5.6,2.4],
# [6.4,3.1,5.5,1.8],
# [6,3,4.8,1.8],
# [6.9,3.1,5.4,2.1],
# [6.7,3.1,5.6,2.4],
# [6.9,3.1,5.1,2.3],
# [5.8,2.7,5.1,1.9],
# [6.8,3.2,5.9,2.3],
# [6.7,3.3,5.7,2.5],
# [6.7,3,5.2,2.3],
# [6.3,2.5,5,1.9],
# [6.5,3,5.2,2],
# [6.2,3.4,5.4,2.3],
# [5.9,3,5.1,1.8]]
# Data=np.transpose(np.array(m))#type of Data is array and Data is transpose of m
#------------------------------------------Normalized----------------------------------------------------
# m = NormalizeData(m)#normalize
# Data=np.transpose(np.array(m))#type of Data is array and Data is transpose of m
# def NormalizeData(data):
#     return (data - np.min(data)) / (np.max(data) - np.min(data))
#--------------------------------------------------------------------------------------------------------

#---------------------------------LL---------------------------------------------------------------------

# t1=time.time()
# x = LocallyLinearEmbedding(n_components=2)
# X_transformed = x.fit_transform(m[:150])
# t2=time.time()-t1
# print(f"Data : {X_transformed}")
# print(f"t-LLE : {t2}")

# m=X_transformed
# Data=np.transpose(np.array(m))#type of Data is array and Data is transpose of m
# dim=2
#--------------------------------------------------------------------------------------------------------
# print(f"data : {m}")
# True_label=[
# 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
# ,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
# 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
#------------------------------------end iris--------------------------------------------------------------------
# m = DataSet.data()
# True_label = m[1]
# m = m[0].Data#type of m and True_labels is List
# Data=np.transpose(np.array(m))#type of Data is array and Data is transpose of m
# ------Read Data another way---------
# m = DataSet.dataclutot()
# True_label = m[1]
# m = m[0].Data#type of m and True_labels is List
# Data=np.transpose(np.array(m))

# True_label = moons[1]
# m=moons[0]

# np.savetxt('/content/drive/MyDrive/Colab Notebooks/data.csv',Data,delimiter=',')
# print(f"Data : {Data,len(Data),len(Data[0])}")
# print("load Data")

# ---------for first preprocess dataset-----
# Data=blobs
# D=[[] for i in range(len(Data[0][0]))]
# for dim in range(len(Data[0][0])):
#    for data in Data[0]:
#        D[dim].append(data[dim])

# np.savetxt("/content/drive/MyDrive/Colab Notebooks/moonsData38.csv",
#           m,
#           delimiter =",",
#           fmt ='% s')

# np.savetxt("/content/drive/MyDrive/Colab Notebooks/moonsLabels38.csv",
#           True_label,
#           delimiter =",",
#           fmt ='% s')
# print("Save Data")
# np.savetxt("blobsData150.csv",
#   Data[0],
#   delimiter =",",
#   fmt ='% s')

# np.savetxt("blobsDataLabels150.csv",
#   Data[1],
#   delimiter =",",
#   fmt ='% s')

# ---------------run dbscan--------------
# start_time1 = time.time()
# db = DBSCAN(eps=5, min_samples=5).fit(m)
# # core = db.core_sample_indices_
# R2=adjusted_rand_score(True_label, db.labels_)
# MinPts = 5

# ------------------------------Find the best of Epsilon & MinPoints------------------------------------------
# all=np.zeros([10000,3])
# i=0
# for e in np.arange(0.01,5,0.01):
#    for min in range(2,20):
#        db = DBSCAN(eps=e, min_samples=min).fit(m)
#        R2=adjusted_rand_score(True_label, db.labels_)
#        all[i][0]=R2
#        all[i][1]=e
#        all[i][2]=min
#        i+=1

# indx=np.where(all==max(all[:,0]))
# best=all[indx[0]]
# -------------------------------------End----------------------------------------------------

# --------------------------------------plot data--------------------------------------------
# fig = plt.figure()
# ax = fig.add_subplot(1, 1, 1)
# # Major ticks every 20, minor ticks every 5
# major_ticks = np.arange(0, 4.5, 0.17)
# minor_ticks = np.arange(0, 4.5, 0.17)
# ax.set_xticks(major_ticks)
# ax.set_xticks(minor_ticks, minor=True)
# ax.set_yticks(major_ticks)
# ax.set_yticks(minor_ticks, minor=True)
# ax.set_xlim([0,5])
# ax.set_ylim([0,5])
# # And a corresponding grid
# ax.grid(which='both')
# plt.grid()
# p=Plot(Data,0)
# p2=p.plotClusters()
# plt.show()

# ------------------------------------------------------------------------------

# ------------------------------Kdist for find Eps-------------------------------------------------------
# kdist=Kdist(Data,3)
# kd=kdist.calculate_kn_distance()
# kdist2=Kdist(Data[1],4)
#eps_dist = kdist.calculate_kn_distance()
# p=plt.hist(eps_dist,bins=30)
# plt.ylabel('n');
#plt.xlabel('Epsilon distance')
# plt.show()
# ------------------------------------------------------------------------------------------------------

# ----------------------------------Kinds of Grid--------------------------------------------------------
#

# print(Data,True_label)
Eps = float(json_object["Eps"])
MinPts = int(json_object["Minpts"])
print(f"dim :{dim}")
G = []
start_time = time.time()
# ---------------Hex Grids-----------
modeGrid = int(json_object["mode_grid"])
# Hexagonal
start_time_grid = time.time()
print(modeGrid,int(1))
if modeGrid == int(1):
    print("Hex mode")
    parts=make_Hex(Data,Eps)
    Grids,gridData,numGrid_dim=parts.GridHex()

    # with open('/content/drive/MyDrive/Colab Notebooks/saveobject.json', 'r') as openfile:

    #     # Reading from json file
    #     save_object = json.load(openfile)

    # s_obj["datagrid"] = gridData
    # save_object = json.dumps(s_obj)
    # with open("/content/drive/MyDrive/Colab Notebooks/saveobject.json", "w") as outfile:
    #         outfile.write(save_object)

    print("run grid")

# -------------Square Grids----------
if modeGrid == int(2):
    print("square mode")
    parts = Make_Square(Data,Eps,dim)
    # print(Data)
    # Grids, gridData = parts.GridHex()
    Grids, gridData,numGrid_dim = parts.GridSqn()
    # Grids, gridData,numGrid_dim = parts.GridHex()
    print("run grid")
print(f"time_grid = {time.time() - start_time_grid}")
# -----------------------Recalling Saved Cores-------------------
#path = '/content/drive/MyDrive/Colab Notebooks/CoreGrids.csv'
#df = pd.read_csv(path)
#CoreGrid = df.values.tolist()

#path = '/content/drive/MyDrive/Colab Notebooks/CoreObjects.csv'
#df = pd.read_csv(path)
#CoreObject = df.values.tolist()

#path = f'..\\GDCFalg\\CoreGrids.csv'
#df = pd.read_csv(path)
#CoreGrid = df.values.tolist()

#path = f'..\\GDCFalg\\CoreObjects.csv'
#df = pd.read_csv(path)
#CoreObject = df.values.tolist()

core = CoreGrids(Grids, gridData, Data, Eps, MinPts, m)
CoreGrid, CoreObject = core.Find_CoreGrids()
# print(f"core:{CoreGrid,CoreObject}")
print("run core")

# for i in range(len(gridData)):
#    if len(gridData[i])>=MinPts:
#        G.append(Grids[i])
#    else:
#        G.append([])

# ----------------------------------------HGB--------------------------------------------------------------
start_time_hgb=time.time()
HGBmatrix = HGB(Grids,dim,numGrid_dim)
B = HGBmatrix.BuildHGB()
print("run HGB")
print(f"time_hgb = {time.time() - start_time_hgb}")

# _______________________________________GDCF________________________________________________________________-
start_time_gdcf=time.time()
gdcf = GDCF(CoreGrid, CoreObject, dim, B, MinPts, Eps)
if modeGrid == int(1):
    ClusterForest = gdcf.BuildGDCF(json_object["sort_grids"],"Hex", gridData, m, Grids)
if modeGrid == int(2):
    ClusterForest = gdcf.BuildGDCF(json_object["sort_grids"],"Square", gridData, m, Grids)
print("run GDCF")
print(f"time_gdcf = {time.time() - start_time_gdcf}")

Pred_label = []
for i in range(len(ClusterForest)):
    Pred_label.append(ClusterForest[i][-1])
# print(f"pred:{Pred_label}")
alltime = time.time() - start_time
R1 = adjusted_rand_score(True_label, Pred_label)
f1 = metrics.f1_score(True_label, Pred_label,average='micro')
nmi = normalized_mutual_info_score(True_label, Pred_label)
print(f"R1,alltime : {R1,nmi,f1,alltime}")

excel_name_label = f'/content/drive/MyDrive/Colab Notebooks/mylabels.xlsx'
df_plabels = pd.DataFrame(Pred_label)
df_plabels.to_excel(excel_name_label,index=False)
print("Labels saved")

# f2 = metrics.f1_score(True_label, db.labels_, average='weighted')

#----------------------------------------file for find best Eps,cols=90;rows=eps,R1------------------------------------------
namefile = str(json_object["data"]) + str(json_object["n_samples"]) + str(json_object["sort_grids"]) + str(json_object["mode_grid"])

ls = []
ls.append(json_object["Eps"])
ls.append(R1)
ls.append(alltime)
df = pd.DataFrame(ls)

excel_name = f'/content/drive/MyDrive/Colab Notebooks/{namefile}"R1"agg.xlsx'
print(excel_name)
df_source = None
if os.path.exists(excel_name):
    print("os.path.exists(excel_name)")
    df_source = pd.DataFrame(pd.read_excel(excel_name))
    print("os if is ok")

if df_source is not None:
    print("df_source is not None")
    df_source[json_object["i"]]=ls
    df_dest = df_source
    print("df_source if is ok")

else:
    print("not exist")
    df_dest = df
    print("ok if not exist")

df_dest.to_excel(excel_name,index=False)
print("Save excel")

#----------------------------------------file for presentaion results------------------------------------------------------------------
cols=['DataSize','Mode_Grid','Time','Improvment','SortWay','DataSetType','ARI','F1-Score','Purity','Precision']
df = pd.DataFrame(columns=cols)

# ls = []
# ls.append(json_object["Eps"])
# ls.append(f1)
# ls.append(alltime)
# df = pd.DataFrame(ls)
excel_name = f'/content/drive/MyDrive/Colab Notebooks/resultfile.xlsx'
print(excel_name)
df_source = None
if os.path.exists(excel_name):
    print("os.path.exists(excel_name)")
    df_source = pd.DataFrame(pd.read_excel(excel_name))
    print("os if is ok")

if df_source is not None:
    print("df_source is not None")
    df_source.at[json_object["i"],'DataSize'] = json_object["n_samples"]
    df_source.at[json_object["i"],'Mode_Grid'] = json_object["mode_grid"]
    df_source.at[json_object["i"],'Time'] = alltime
    # if int(json_object["mode_grid"]) == 2:
    #     print("sqsqsq")
    #     df_source.at[int(json_object["i"])-1,'Improvment'] = (df_source.iloc[int(json_object["i"])]['Time']-df_source.iloc[int(json_object["i"]-1)]['Time'])/df_source.iloc[int(json_object["i"])]['Time']
    df_source.at[json_object["i"],'SortWay'] = json_object["sort_grids"]
    df_source.at[json_object["i"],'DataSetType'] = json_object["data"]
    df_source.at[json_object["i"],'ARI'] = R1
    df_dest = df_source
    print("df_source if is ok")

else:
    print("not exist")
    df_dest = df
    print("ok if not exist")

df_dest.to_excel(excel_name,index=False)
print("Save excel")
# db = DBSCAN(eps=Eps, min_samples=MinPts).fit(m)
# db.labels_ = list(np.float_(db.labels_))

#plt.subplot(1, 3, 1)
# Getting unique labels
# label=list(map(int,Pred_label))
#u_labels = np.unique(label)
# m=np.array(m)
# plotting the results:

# for i in u_labels:
#    plt.scatter(m[label == i,0] , m[label == i,1 ] , label = i)
# plt.legend()
# plt.title("Grid")

#plt.subplot(1, 3, 2)
# label=list(map(int,db.labels_))
#u_labels = np.unique(label)
# m=np.array(m)
# plotting the results:

# for i in u_labels:
#    plt.scatter(m[label == i,0] , m[label == i,1 ] , label = i)
# plt.legend()
# plt.title("DBSCAN")

#plt.subplot(1, 3, 3)
# label=list(map(int,True_label))
#u_labels = np.unique(label)
# m=np.array(m)
# plotting the results:

# for i in u_labels:
#    plt.scatter(m[label == i,0] , m[label == i,1 ] , label = i)
# plt.legend()
#plt.title("True Label")

# plt.show()

# --------------------------------------Evaluation-----------------------------------------------------------
# print(True_label)
# print(Pred_label)
# print(db.labels_)
print("End Run")

# R1 = adjusted_rand_score(True_label, Pred_label)
# R2 = adjusted_rand_score(True_label, db.labels_)

# print(R1, R2, f"alltime:{alltime}")

# M1 = adjusted_mutual_info_score(True_label, Pred_label)
# M2 = adjusted_mutual_info_score(True_label, db.labels_)

# Calinski_Harabasz1 = calinski_harabasz_score(m, Pred_label)
# Calinski_Harabasz1 = calinski_harabasz_score(m, db.labels_)

# FM1 = metrics.fowlkes_mallows_score(True_label, Pred_label)
# FM1 = metrics.fowlkes_mallows_score(True_label, db.labels_)

# S1 = metrics.silhouette_score(m, Pred_label)
# S2 = metrics.silhouette_score(m, db.labels_)

# ss1 = metrics.silhouette_samples(m, Pred_label)
# ss2 = metrics.silhouette_samples(m, db.labels_)

# db1 = metrics.davies_bouldin_score(m, Pred_label)
# db2 = metrics.davies_bouldin_score(m, db.labels_)

# per1 = metrics.precision_score(True_label, Pred_label, average='weighted')
# per2 = metrics.precision_score(
#     True_label, db.labels_, average='weighted')  # error

# v1 = metrics.v_measure_score(True_label, Pred_label)
# v1 = metrics.v_measure_score(True_label, db.labels_)

# pu = Evaluation(True_label, Pred_label)
# pu1 = pu.purity_score()
# p = Evaluation(True_label, db.labels_)
# pu2 = p.purity_score()

# f1 = metrics.f1_score(True_label, Pred_label, average='weighted')
# f2 = metrics.f1_score(True_label, db.labels_, average='weighted')
# alltime = time.time() - start_time
# # p=Plot(D,0)

# print(alltime)


n = int (input())
f = list ()
m = list ()
for i in range (0,n):
    a = input ()
    b = a.split ('.')
    b [1] = b [1][0].upper () + b [1][1:].lower ()
    if b [0] == 'f':
        f.append (b)
    else:
        m.append (b)

ff = sorted (f,key = lambda x: str(x[1]))
mm = sorted (m,key = lambda x: str(x[1]))
for i in range (0,len(ff)):
    print ('%s %s %s'%(ff[i][0], ff[i][1], ff[i][2]))

for j in range (0,len(mm)):
    print ('%s %s %s'%(mm[j][0], mm[j][1], mm[j][2]))


import binascii
import hashlib
import base58
import sys
import os
import secrets
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '.')))
from utils import *

class PrivateKey:
    def __init__(self, privKey=None, net="main"):
        if privKey == None:
            privKey = self.generatePrivateKey()
        if not self.isValid(privKey):
            raise BaseException("Incorrect private key %s"%(privKey))
        self.privKey = self.parse(privKey)
        self.netCode = self.getNetID(net)

    def isValid(self, privKey):
        hex_number=0
        if self.isWIFUncompressed(privKey):
            hex_number=binascii.hexlify(base58.b58decode(privKey)[1:-4])
        elif self.isWIFCompressed(privKey):
            hex_number=binascii.hexlify(base58.b58decode(privKey)[1:-5])
        elif self.isRawHexa(privKey):
            hex_number=privKey
        else:
            raise Exception("The private key %s is not in one of the following supported formats: WIF Uncompressed, WIF compressed or raw hexadecimal number"%(privKey))

        return int(hex_number, 16) > 0 and int(hex_number, 16) < 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140

    def isWIFUncompressed(self, privKey):
        return privKey[0] == "5" and len(privKey) != 64

    def isWIFCompressed(self, privKey):
        if len(privKey) == 64:
            return False
        return privKey[0] == "L" or privKey[0] == "K"

    def isRawHexa(self, privKey):
        if len(privKey) != 64:
            return False
        int_privKey = int(privKey, 16)
        return int_privKey > 0 and int_privKey <= int("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", 16)

    def parse(self, privKey):
        if self.isWIFUncompressed(privKey):
            return binascii.hexlify(base58.b58decode(privKey)[1:-4])
        if self.isWIFCompressed(privKey):
            return binascii.hexlify(base58.b58decode(privKey)[1:-5])
        if self.isRawHexa(privKey):
            return privKey
        raise BaseException("Incorrect private key %s"%(privKey))

    def getNetID(self, long_format):
        if long_format == "main":
            return "80"
        else:
            raise BaseException("Incorrect network identifier %s"%(long_format))

    def get(self, format="RAW-HEXA"):
        if format.upper() == "WIF-UNCOMPRESSED":
            return self.WIFUncompressedFormat()
        elif format.upper() == "WIF-COMPRESSED":
            return self.WIFCompressedFormat()
        elif format.upper() == "RAW-HEXA":
            return self.rawHexaFormat()
        else:
            raise BaseException("Error: PrivateKey format %s is not valid."%(format))

    def rawHexaFormat(self):
        return self.privKey

    def WIFUncompressedFormat(self):
        formated_privKey = binascii.unhexlify(self.netCode) + binascii.unhexlify(self.privKey)
        checksum = doubleSHA256(formated_privKey).digest()[:4]
        return formated_privKey + checksum

    def WIFCompressedFormat(self):
        formated_privKey = binascii.unhexlify(self.netCode) + binascii.unhexlify(self.privKey) + binascii.unhexlify("01")
        checksum = doubleSHA256(formated_privKey).digest()[:4]
        return formated_privKey + checksum

    def generatePrivateKey(self):
        number = int(secrets.randbelow(1 << 256))
        while number < 1 or number > 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140:
            number = secrets.randbelow(1 << 256)
        return binascii.hexlify(number.to_bytes(32, byteorder='big'))


from PyQt5 import QtCore, QtWidgets
import numpy as np
import seaborn as sns

from plot_manager import PlotManager
from plots.plot_widget import PlotWidget
from utility.channel_utility import ChannelUtility

class HeatmapTab(QtWidgets.QWidget):
    def __init__(self, parent, reader, mcs_labels, mcs_channel_ids, settings):
        super().__init__(parent)
        self.reader = reader
        self.settings = settings
        self.ch_ids = mcs_channel_ids
        self.labels = mcs_labels

        self.mea_file_view = parent

        self.colors = ['#749800', '#006d7c']
        self.single_heatmap = []

        self.spiketimes = self.reader.spiketimes
        # embed()

        self.plot_thread = None

        main_layout = QtWidgets.QVBoxLayout(self)
        main_layout.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter)

        tool_button_layout = QtWidgets.QVBoxLayout()
        self.save_button = QtWidgets.QPushButton("Save results...")
        self.save_button.clicked.connect(self.on_save_button_clicked)
        self.save_button.setEnabled(False)  # will be enabled after plotting
        tool_button_layout.addWidget(self.save_button)
        main_layout.addLayout(tool_button_layout)

        plot_name = 'Heatmap_' + self.reader.filename

        self.plot_widget = PlotWidget(self, plot_name)
        self.figure = self.plot_widget.figure
        main_layout.addWidget(self.plot_widget)
        self.plot(self.figure, self.spiketimes)

    def on_save_button_clicked(self):
        file_dialog = QtWidgets.QFileDialog(self)
        file_dialog.setFileMode(QtWidgets.QFileDialog.AnyFile)
        file_dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptSave)
        file_dialog.setNameFilter("CSV files (*.csv)")
        file_dialog.setDefaultSuffix(".csv")
        file_dialog_result = file_dialog.exec()
        if file_dialog_result:
            # user selected file:
            selected_file = file_dialog.selectedFiles()[0]
            self.mea_file_view.results.save_spikecount_data_to(selected_file)

    def plot(self, fig, spike_mat):
        self.mea_file_view.results.clear_spikecounts()
        ax = fig.add_subplot(111)
        self.single_heatmap = []
        old_heatmap = self.settings.heatmap_for_normalizing
        for raw_index in self.ch_ids:
            print(raw_index)
            # raw index simply corresponds to all channels (0 = A2, 1 = A3, ...) even if some are dead channels
            # if idx not in self.reader.dead_channels and
            # len(spike_mat[sc_channel_counter])/self.reader.duration >= 0.05:
            if self.reader.dead_channels:
                if raw_index not in self.reader.dead_channels:
                    sc_index = ChannelUtility.get_sc_index(raw_index, self.reader.dead_channels)
                    self.single_heatmap.append(len(spike_mat[sc_index]))
                    self.mea_file_view.results.get_spike_counts_from_heatmap(self.labels[raw_index],
                                                                             len(spike_mat[sc_index]))
                else:
                    # raw index is pointing at dead channel
                    self.single_heatmap.append(0)
                    self.mea_file_view.results.get_spike_counts_from_heatmap(self.labels[raw_index], 0)
            else:
                # no dead channels -> raw index is sc channel index (all channels were recorded)
                self.single_heatmap.append(len(spike_mat[raw_index]))
                self.mea_file_view.results.get_spike_counts_from_heatmap(self.labels[raw_index],
                                                                         len(spike_mat[raw_index]))

        self.single_heatmap.insert(0, 0)
        self.single_heatmap.insert(15, 0)
        self.single_heatmap.insert(15 * 16, 0)
        self.single_heatmap.append(0)
        self.single_heatmap = np.reshape(self.single_heatmap, (16, 16)).transpose()
        # if old_heatmap is not None:
        #     self.single_heatmap = self.single_heatmap / np.array(old_heatmap)
        #     self.single_heatmap = np.nan_to_num(self.single_heatmap)
        y_labels = range(1, 17)
        x_labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R']
        xticks = np.arange(0.5, 16.5, 1)
        if old_heatmap is not None:
            sns.heatmap(self.single_heatmap, cmap='hot_r', vmin=0, vmax=np.max(old_heatmap), ax=ax,
                        cbar_kws={'label': 'spike count'})
            # sns.heatmap(self.single_heatmap, cmap='PuBuGn', vmin=0, vmax=np.max(old_heatmap), ax=ax,
            #             cbar_kws={'label': 'spike count'})
        else:
            sns.heatmap(self.single_heatmap, cmap='hot_r', vmin=0, vmax=np.max(self.single_heatmap), ax=ax,
                        cbar_kws={'label': 'spike count'})
            # sns.heatmap(self.single_heatmap, cmap='PuBuGn', vmin=0, vmax=np.max(self.single_heatmap),
            #             ax=ax, cbar_kws={'label': 'spike count'})
        yticks = np.arange(0.5, 16.5, 1)
        ax.set_xticks(xticks)
        ax.set_yticks(yticks)
        ax.set_yticklabels(y_labels)
        ax.set_xticklabels(x_labels)
        ax.set_ylabel('MEA rows')
        ax.set_xlabel('MEA columns')

        PlotManager.instance.add_plot(self.plot_widget)
        self.save_button.setEnabled(True)

    def can_be_closed(self):
        # plot is not running a thread => can be always closed
        return True


d=input()
n=len(d)
k=int(input())
l=[]
l1=[]
for i in range(n):
    y=[]
    for j in range(i,n):
        y.append(j)
        if len(y)==n-k:break
    l.append(y)
print(l)
def remove(s,a):
    return ''.join(x for x in s if s.index(x)!=a)
for i in l:
    d1=d
    for j in i:
        d1=remove(d1,j)
    l1.append(d1)
print(l1)


import cv2
import numpy as np
from matplotlib import pyplot as plt

# read in the image
image = cv2.imread('apple.jpg')

# get the height and width of the image
height = image.shape[0]
Width  = image.shape[1]

# shift the image down by 10%
roll = np.roll(image, height // 10, axis=0)
plt.imshow(roll)

# shift the image up by 10%
roll = np.roll(image, -(height // 10), axis=0)
plt.imshow(roll)

# shift the image right by 10%
roll = np.roll(image, width // 10, axis=1)
plt.imshow(roll)

# shift the image left by 10%
roll = np.roll(image, -(width // 10), axis=1)
plt.imshow(roll)


# Alexandra Hickman (azh5kn) and Amara Vo (av2jf)

# keywords
animal = input('An animal: ')
country = input('A country: ')
disney_character = input('Disney character: ')
color = input('A color: ')
fastfood_restaurant = input('A fastfood place: ')

print()     # printing space to organize

print('\tOnce upon a time, there was a(n) '+animal+' that lived in '+country+'.'+
      ' It was very lonely, so it decided to use its tinder app.\n After waiting two weeks, it matched with '+disney_character+', who had '+color+' hair.'
    +' They met up at '+fastfood_restaurant+', and it was love\n at first sight for the '+animal+' and '+disney_character+'.'+"\n\n They didn't live happily ever after, but tinder was still an option.")


from collections import namedtuple
from fractions import Fraction

StRec = namedtuple('StRec', 'pearls, step, w_taken, b_taken')

def checkio(pearls: str, steps: int) -> float:
    lst = []
    n = 1
    p = pearls.count('w')
    lst.append(StRec(pearls,
                     n,
                     Fraction(p, len(pearls)),
                     Fraction(len(pearls) - p,  len(pearls))
                     )
               )

    while n < steps:
        for l in lst:
            if l.step == n:
                if l.w_taken > 0:
                    new_p = l.pearls.replace('w', 'b', 1)
                    p = new_p.count('w')
                    lst.append(StRec(new_p,
                                     n + 1,
                                     l.w_taken * Fraction(p, len(pearls)),
                                     l.w_taken * Fraction(len(pearls) - p,  len(pearls))
                                     )
                               )
                if l.b_taken > 0:
                    new_p = l.pearls.replace('b', 'w', 1)
                    p = new_p.count('w')
                    lst.append(StRec(new_p,
                                     n + 1,
                                     l.b_taken * Fraction(p, len(pearls)),
                                     l.b_taken * Fraction(len(pearls) - p,  len(pearls))
                                     )
                               )
        n += 1

    for l in lst:
        print(l)

    r = Fraction(0, 1)
    for l in lst:
        if l.step == steps:
            r += l.w_taken

    print(round(r.numerator / r.denominator, 2))
    return(round(r.numerator / r.denominator, 2))

# These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
    # print("Example:")
    # print(checkio('bbw', 3))

    # # assert checkio('bbw', 3) == 0.48, "1st example"
    # # assert checkio('wwb', 3) == 0.52, "2nd example"
    # # assert checkio('www', 3) == 0.56, "3rd example"
    # # assert checkio('bbbb', 1) == 0, "4th example"
    # # assert checkio('wwbb', 4) == 0.5, "5th example"
    # # assert checkio('bwbwbwb', 5) == 0.48, "6th example"
    assert checkio('bbb', 5) == 0.48, "7th example"
    print("Coding complete? Click 'Check' to earn cool rewards!")


from test_modules.mathematical_operations import fibonacci_sequence_func, locate_func

commands = input()

fibonacci = []

while not commands == 'Stop':
    commands = commands.split()
    command, number = commands[0], int(commands[-1])
    if command == 'Create':
        fibonacci = fibonacci_sequence_func(number)
        print(f"{' '.join(str(x) for x in fibonacci)}")
    elif command == 'Locate':
        print(locate_func(fibonacci, number))
    commands = input()


import os, sys, os.path as op
import numpy as np
import cv2
import logging
from ast import literal_eval
from pprint import pformat
import imageio

from lib.utils import util
from lib.backend import backendDb
from lib.backend import backendMedia

def add_parsers(subparsers):
    examineImagesParser(subparsers)
    examineObjectsParser(subparsers)
    labelObjectsParser(subparsers)
    examineMatchesParser(subparsers)
    labelMatchesParser(subparsers)

class KeyReader:
    '''
    A mapper from keyboard buttons to actions.
    '''
    def __init__(self, keysmap_str):
        '''
        Args:
          key_dict: a string that can be parsed as dict Key->Action, where:
                    Key - a string of one char or a an int for ASCII
                    Action - a string.
                    Actions 'exit', 'previous', and 'next' must be specified.
        Returns:
          Parsed dict.
        '''
        logging.debug('Got keys map string as: %s' % keysmap_str)
        keysmap = literal_eval(keysmap_str)
        logging.info('Keys map was parsed as: %s' % pformat(keysmap))
        for value in ['exit', 'previous', 'next']:
            if not value in keysmap.values():
                raise ValueError('"%s" must be in the values of keysmap, '
                                 'now the values are: %s' %
                                 (value, keysmap.values()))
        for key in keysmap:
            if not isinstance(key, int) and not (isinstance(key, str)
                                                 and len(key) == 1):
                raise ValueError(
                    'Each key in key_dict must be an integer (for ASCII code) '
                    'or a string of a single character. Got key: %s' % key)
        self.keysmap = keysmap

    def parse(self, button):
        ''' Get the corresponding action for a pressed button. '''

        if button == -1:  # cv2 code for no press.
            #logging.debug('No key was pressed')
            return None

        if chr(button) in self.keysmap:
            # Get the character from ASCII, since character is in the keymap.
            logging.info('Found char "%s" for pressed ASCII %d in the table.' %
                         (chr(button), button))
            button = chr(button)

        if button in self.keysmap:
            logging.info('Value for pressed "%s" is "%s".' %
                         (str(button), self.keysmap[button]))
            return self.keysmap[button]
        else:
            logging.info('No value for pressed "%s".' % str(button))
            return None

def examineImagesParser(subparsers):
    parser = subparsers.add_parser(
        'examineImages',
        description='Loop through images. Possibly, assign names to images.')
    parser.set_defaults(func=examineImages)
    parser.add_argument('--where_image',
                        default='TRUE',
                        help='the SQL "where" clause for the "images" table.')
    parser.add_argument('--mask_mapping_dict',
                        help='A mapping to display values in maskfile. '
                        'E.g. "{\'[1,254]\': [0,0,0], 255: [128,128,30]}"')
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--mask_aside',
                       action='store_true',
                       help='Image and mask side by side.')
    group.add_argument('--mask_alpha',
                       type=float,
                       help='Mask will be overlayed on the image.'
                       'Transparency to overlay the label mask with, '
                       '1 means cant see the image behind the mask.')
    parser.add_argument('--shuffle', action='store_true')
    parser.add_argument('--with_objects',
                        action='store_true',
                        help='draw all objects on top of the image.')
    parser.add_argument('--with_score',
                        action='store_true',
                        help='draw image score on top of the image.')
    parser.add_argument('--with_imagefile',
                        action='store_true',
                        help='draw imagefile on top of the image.')
    parser.add_argument('--winsize', type=int, default=1000)
    parser.add_argument(
        '--key_dict',
        default=
        '{"-": "previous", "=": "next", " ": "snapshot", 127: "delete", 27: "exit"}'
    )
    parser.add_argument(
        '--snapshot_dir',
        help='If provided, snapshots will be written to "snapshot_dir".')

def examineImages(c, args):
    cv2.namedWindow("examineImages")

    c.execute('SELECT * FROM images WHERE (%s)' % args.where_image)
    image_entries = c.fetchall()
    logging.info('%d images found.' % len(image_entries))
    if len(image_entries) == 0:
        logging.error('There are no images. Exiting.')
        return

    if args.shuffle:
        np.random.shuffle(image_entries)

    if args.snapshot_dir and not op.exists(args.snapshot_dir):
        os.makedirs(args.snapshot_dir)

    imreader = backendMedia.MediaReader(rootdir=args.rootdir)

    # For parsing keys.
    key_reader = KeyReader(args.key_dict)

    # For overlaying masks.
    labelmap = literal_eval(
        args.mask_mapping_dict) if args.mask_mapping_dict else None
    logging.info('Parsed mask_mapping_dict to %s' % pformat(labelmap))

    index_image = 0

    while True:  # Until a user hits the key for the "exit" action.

        image_entry = image_entries[index_image]
        imagefile = backendDb.imageField(image_entry, 'imagefile')
        maskfile = backendDb.imageField(image_entry, 'maskfile')
        imname = backendDb.imageField(image_entry, 'name')
        imscore = backendDb.imageField(image_entry, 'score')
        logging.info('Imagefile "%s"' % imagefile)
        logging.debug('Image name="%s", score=%s' % (imname, imscore))
        image = imreader.imread(imagefile)

        # Overlay the mask.
        if maskfile is not None:
            mask = imreader.maskread(maskfile)
            if args.mask_aside:
                image = util.drawMaskAside(image, mask, labelmap=labelmap)
            elif args.mask_alpha is not None:
                image = util.drawMaskOnImage(image,
                                             mask,
                                             alpha=args.mask_alpha,
                                             labelmap=labelmap)
        else:
            logging.info('No mask for this image.')

        # Put the objects on top of the image.
        if args.with_objects:
            c.execute('SELECT * FROM objects WHERE imagefile=?', (imagefile, ))
            object_entries = c.fetchall()
            logging.info('Found %d objects for image %s' %
                         (len(object_entries), imagefile))
            for object_entry in object_entries:
                objectid = backendDb.objectField(object_entry, 'objectid')
                roi = backendDb.objectField(object_entry, 'roi')
                score = backendDb.objectField(object_entry, 'score')
                name = backendDb.objectField(object_entry, 'name')
                logging.info('objectid: %d, roi: %s, score: %s, name: %s' %
                             (objectid, roi, score, name))
                c.execute('SELECT * FROM polygons WHERE objectid=?',
                          (objectid, ))
                polygon_entries = c.fetchall()
                if len(polygon_entries) > 0:
                    logging.info('showing object with a polygon.')
                    polygon = [(int(backendDb.polygonField(p, 'x')),
                                int(backendDb.polygonField(p, 'y')))
                               for p in polygon_entries]
                    util.drawScoredPolygon(image,
                                           polygon,
                                           label=name,
                                           score=score)
                elif roi is not None:
                    logging.info('showing object with a bounding box.')
                    util.drawScoredRoi(image, roi, label=name, score=score)
                else:
                    logging.warning(
                        'Neither polygon, nor bbox is available for objectid %d'
                        % objectid)

        # Display an image, wait for the key from user, and parse that key.
        scale = float(args.winsize) / max(list(image.shape[0:2]))
        scaled_image = cv2.resize(image, dsize=(0, 0), fx=scale, fy=scale)
        # Overlay imagefile.
        if args.with_imagefile:
            util.drawTextOnImage(
                scaled_image,
                op.basename(backendMedia.normalizeSeparators(imagefile)))
        # Overlay score.
        # TODO: add y offset, if necessary
        if args.with_score:
            util.drawTextOnImage(scaled_image, '%.3f' % imscore)
        # Display
        cv2.imshow('examineImages', scaled_image[:, :, ::-1])
        action = key_reader.parse(cv2.waitKey(-1))
        if action is None:
            # User pressed something which does not have an action.
            continue
        elif action == 'snapshot':
            if args.snapshot_dir:
                snaphot_path = op.join(args.snapshot_dir,
                                       '%08d.png' % index_image)
                logging.info('Making a snapshot at path: %s' % snaphot_path)
                imageio.imwrite(snaphot_path, image)
            else:
                logging.warning(
                    'The user pressed a snapshot key, but snapshot_dir is not '
                    'specified. Will not write a snapshot.')
        elif action == 'delete':
            backendDb.deleteImage(c, imagefile)
            del image_entries[index_image]
            if len(image_entries) == 0:
                logging.warning('Deleted the last image.')
                break
            index_image += 1
        elif action == 'exit':
            break
        elif action == 'previous':
            index_image -= 1
        elif action == 'next':
            index_image += 1
        else:
            # User pressed something else which has an assigned action, assume it is a new name.
            logging.info('Setting name "%s" to imagefile "%s"' %
                         (action, imagefile))
            c.execute('UPDATE images SET name=? WHERE imagefile=?' (action,
                                                                    imagefile))
        index_image = index_image % len(image_entries)

    cv2.destroyWindow("examineImages")

def examineObjectsParser(subparsers):
    parser = subparsers.add_parser('examineObjects',
                                   description='Loop through objects.')
    parser.set_defaults(func=examineObjects)
    parser.add_argument('--shuffle', action='store_true')
    parser.add_argument('--where_object',
                        default='TRUE',
                        help='the SQL "where" clause for the "objects" table.')
    parser.add_argument('--winsize', type=int, default=1000)
    parser.add_argument(
        '--key_dict',
        default=
        '{"-": "previous", "=": "next", 27: "exit", 127: "delete", " ": "unname"}'
    )
    # TODO: add display of mask.

def examineObjects(c, args):
    cv2.namedWindow("examineObjects")

    c.execute('SELECT COUNT(*) FROM objects WHERE (%s) ' % args.where_object)
    logging.info('Found %d objects in db.' % c.fetchone()[0])

    c.execute('SELECT DISTINCT imagefile FROM objects WHERE (%s) ' %
              args.where_object)
    image_entries = c.fetchall()
    logging.info('%d images found.' % len(image_entries))
    if len(image_entries) == 0:
        logging.error('There are no images. Exiting.')
        return

    if args.shuffle:
        np.random.shuffle(image_entries)

    imreader = backendMedia.MediaReader(rootdir=args.rootdir)

    # For parsing keys.
    key_reader = KeyReader(args.key_dict)

    index_image = 0
    index_object = 0

    # Iterating over images, because for each image we want to show all objects.
    while True:  # Until a user hits the key for the "exit" action.

        (imagefile, ) = image_entries[index_image]
        logging.info('Imagefile "%s"' % imagefile)
        image = imreader.imread(imagefile)
        scale = float(args.winsize) / max(image.shape[0:2])
        image = cv2.resize(image, dsize=(0, 0), fx=scale, fy=scale)

        c.execute(
            'SELECT * FROM objects WHERE imagefile=? AND (%s)' %
            args.where_object, (imagefile, ))
        object_entries = c.fetchall()
        logging.info('Found %d objects for image %s' %
                     (len(object_entries), imagefile))

        # Put the objects on top of the image.
        if len(object_entries) > 0:
            assert index_object < len(object_entries)
            object_entry = object_entries[index_object]
            objectid = backendDb.objectField(object_entry, 'objectid')
            roi = backendDb.objectField(object_entry, 'roi')
            score = backendDb.objectField(object_entry, 'score')
            name = backendDb.objectField(object_entry, 'name')
            scaledroi = [int(scale * r)
                         for r in roi]  # For displaying the scaled image.
            logging.info('objectid: %d, roi: %s, score: %s, name: %s' %
                         (objectid, roi, score, name))
            c.execute('SELECT * FROM polygons WHERE objectid=?', (objectid, ))
            polygon_entries = c.fetchall()
            if len(polygon_entries) > 0:
                logging.info('showing object with a polygon.')
                polygon = [(backendDb.polygonField(p, 'x'),
                            backendDb.polygonField(p, 'y'))
                           for p in polygon_entries]
                logging.debug('nonscaled polygon: %s' % pformat(polygon))
                polygon = [(int(scale * x), int(scale * y))
                           for x, y in polygon]
                logging.debug('scaled polygon: %s' % pformat(polygon))
                util.drawScoredPolygon(image, polygon, label=None, score=score)
            elif roi is not None:
                logging.info('showing object with a bounding box.')
                util.drawScoredRoi(image, scaledroi, label=None, score=score)
            else:
                raise Exception(
                    'Neither polygon, nor bbox is available for objectid %d' %
                    objectid)
            c.execute('SELECT key,value FROM properties WHERE objectid=?',
                      (objectid, ))
            properties = c.fetchall()
            if name is not None:
                properties.append(('name', name))
            if score is not None:
                properties.append(('score', score))
            for iproperty, (key, value) in enumerate(properties):
                cv2.putText(image, '%s: %s' % (key, value),
                            (scaledroi[3] + 10,
                             scaledroi[0] - 10 + util.SCALE * (iproperty + 1)),
                            util.FONT, util.FONT_SIZE, (0, 0, 0),
                            util.THICKNESS)
                cv2.putText(image, '%s: %s' % (key, value),
                            (scaledroi[3] + 10,
                             scaledroi[0] - 10 + util.SCALE * (iproperty + 1)),
                            util.FONT, util.FONT_SIZE, (255, 255, 255),
                            util.THICKNESS - 1)
                logging.info('objectid: %d. %s = %s.' % (objectid, key, value))

        # Display an image, wait for the key from user, and parse that key.
        cv2.imshow('examineObjects', image[:, :, ::-1])
        action = key_reader.parse(cv2.waitKey(-1))
        if action is None:
            # User pressed something which does not have an action.
            continue
        elif action == 'exit':
            break
        elif action == 'previous':
            index_object -= 1
            if index_object < 0:
                index_image -= 1
                index_object = 0
        elif action == 'next':
            index_object += 1
            if index_object >= len(object_entries):
                index_image += 1
                index_object = 0
        elif action == 'delete' and len(object_entries) > 0:
            backendDb.deleteObject(c, objectid)
            del object_entries[index_object]
            if index_object >= len(object_entries):
                index_image += 1
                index_object = 0
        elif action == 'unname' and len(object_entries) > 0:
            logging.info('Remove the name from objectid "%s"' % objectid)
            c.execute('UPDATE objects SET name=NULL WHERE objectid=?',
                      (objectid, ))
        index_image = index_image % len(image_entries)

    cv2.destroyWindow("examineObjects")

def labelObjectsParser(subparsers):
    parser = subparsers.add_parser(
        'labelObjects',
        description='Loop through objects and manually label them, '
        'i.e. assign the value of user-defined property.')
    parser.set_defaults(func=labelObjects)
    parser.add_argument('--shuffle', action='store_true')
    parser.add_argument('--where_object',
                        default='TRUE',
                        help='the SQL "where" clause for the "objects" table.')
    parser.add_argument('--winsize', type=int, default=1000)
    parser.add_argument('--property',
                        required=True,
                        help='name of the property being labelled')
    parser.add_argument(
        '--key_dict',
        default=
        '{"-": "previous", "=": "next", 27: "exit", 127: "delete_label", '
        ' "r": "red", "g": "green", "b": "blue"}')

def labelObjects(c, args):
    cv2.namedWindow("labelObjects")

    c.execute('SELECT COUNT(*) FROM objects WHERE (%s) ' % args.where_object)
    logging.info('Found %d objects in db.' % c.fetchone()[0])

    c.execute('SELECT * FROM objects WHERE (%s)' % args.where_object)
    object_entries = c.fetchall()
    logging.info('Found %d objects in db.' % len(object_entries))
    if len(object_entries) == 0:
        return

    if args.shuffle:
        np.random.shuffle(object_entries)

    imreader = backendMedia.MediaReader(rootdir=args.rootdir)

    # For parsing keys.
    key_reader = KeyReader(args.key_dict)

    button = 0
    index_object = 0
    another_object = True
    while button != 27:
        go_next_object = False

        if another_object:
            another_object = False

            logging.info(' ')
            logging.info('Object %d out of %d' %
                         (index_object, len(object_entries)))
            object_entry = object_entries[index_object]
            objectid = backendDb.objectField(object_entry, 'objectid')
            bbox = backendDb.objectField(object_entry, 'bbox')
            roi = backendDb.objectField(object_entry, 'roi')
            imagefile = backendDb.objectField(object_entry, 'imagefile')
            logging.info('imagefile: %s' % imagefile)
            image = imreader.imread(imagefile)

            # Display an image, wait for the key from user, and parse that key.
            scale = float(args.winsize) / max(image.shape[0:2])
            logging.debug('Will resize image and annotations with scale: %f' %
                          scale)
            image = cv2.resize(image, dsize=(0, 0), fx=scale, fy=scale)

            logging.info('objectid: %d, roi: %s' % (objectid, roi))
            c.execute('SELECT * FROM polygons WHERE objectid=?', (objectid, ))
            polygon_entries = c.fetchall()
            if len(polygon_entries) > 0:
                logging.info('showing object with a polygon.')
                polygon = [(backendDb.polygonField(p, 'x'),
                            backendDb.polygonField(p, 'y'))
                           for p in polygon_entries]
                logging.debug('nonscaled polygon: %s' % pformat(polygon))
                polygon = [(int(scale * p[0]), int(scale * p[1]))
                           for p in polygon]
                logging.debug('scaled polygon: %s' % pformat(polygon))
                util.drawScoredPolygon(image, polygon, label=None, score=None)
            elif roi is not None:
                logging.info('showing object with a bounding box.')
                logging.debug('nonscaled roi: %s' % pformat(roi))
                roi = [int(scale * r)
                       for r in roi]  # For displaying the scaled image.
                logging.debug('scaled roi: %s' % pformat(roi))
                util.drawScoredRoi(image, roi, label=None, score=None)
            else:
                raise Exception(
                    'Neither polygon, nor bbox is available for objectid %d' %
                    objectid)
            c.execute(
                'SELECT key,value FROM properties WHERE objectid=? AND key=?',
                (objectid, args.property))
            # TODO: Multiple properties are possible because there is no
            #       contraint on uniqueness on table properties(objectid,key).
            #       Change when the uniqueness constraint is added to the
            #       database schema. On the other hand, it's a feature.
            properties = c.fetchall()
            if len(properties) > 1:
                logging.warning(
                    'Multiple values for object %s and property %s. '
                    'If reassigned, both will be changed' %
                    (objectid, args.property))

            for iproperty, (key, value) in enumerate(properties):
                cv2.putText(image, '%s: %s' % (key, value),
                            (10, util.SCALE * (iproperty + 1)), util.FONT,
                            util.FONT_SIZE, (0, 0, 0), util.THICKNESS)
                cv2.putText(image, '%s: %s' % (key, value),
                            (10, util.SCALE * (iproperty + 1)), util.FONT,
                            util.FONT_SIZE, (255, 255, 255),
                            util.THICKNESS - 1)
                logging.info('objectid: %d. %s = %s.' % (objectid, key, value))

        cv2.imshow('labelObjects', image[:, :, ::-1])
        action = key_reader.parse(cv2.waitKey(-1))
        if action == 'exit':
            break
        elif action == 'delete_label' and any_object_in_focus:
            logging.info('Remove label from objectid "%s"' % objectid)
            c.execute('DELETE FROM properties WHERE objectid=? AND key=?',
                      (objectid, args.property))
            go_next_object = True
        elif action is not None and action not in ['previous', 'next']:
            # User pressed something else which has an assigned action,
            # assume it is a new value.
            logging.info('Setting label "%s" to objectid "%s"' %
                         (action, objectid))
            if len(properties) > 0:
                c.execute('DELETE FROM properties WHERE objectid=? AND key=?',
                          (objectid, args.property))
            c.execute(
                'INSERT INTO properties(objectid,key,value) VALUES (?,?,?)',
                (objectid, args.property, str(action)))
            go_next_object = True
        # Navigation.
        if action == 'previous':
            logging.debug('previous object')
            another_object = True
            if index_object > 0:
                index_object -= 1
            else:
                logging.warning('Already at the first object.')
        elif action == 'next' or go_next_object == True:
            logging.debug('next object')
            another_object = True
            if index_object < len(object_entries) - 1:
                index_object += 1
            else:
                logging.warning(
                    'Already at the last object. Press Esc to save and exit.')

    cv2.destroyWindow("labelObjects")

def examineMatchesParser(subparsers):
    parser = subparsers.add_parser(
        'examineMatches',
        description=
        '''Browse through database and see car bboxes on top of images.
                   Any key will scroll to the next image.''')
    parser.set_defaults(func=examineMatches)
    parser.add_argument('--shuffle', action='store_true')
    parser.add_argument('--winsize', type=int, default=1000)
    parser.add_argument(
        '--key_dict',
        default='{"-": "previous", "=": "next", " ": "next", 27: "exit"}')

def examineMatches(c, args):
    cv2.namedWindow("examineMatches")

    c.execute('SELECT DISTINCT(match) FROM matches')
    match_entries = c.fetchall()

    if args.shuffle:
        np.random.shuffle(match_entries)

    imreader = backendMedia.MediaReader(rootdir=args.rootdir)

    # For parsing keys.
    key_reader = KeyReader(args.key_dict)

    index_match = 0

    # Iterating over images, because for each image we want to show all objects.
    while True:  # Until a user hits the key for the "exit" action.

        (match, ) = match_entries[index_match]
        c.execute(
            'SELECT * FROM objects WHERE objectid IN '
            '(SELECT objectid FROM matches WHERE match=?)', (match, ))
        object_entries = c.fetchall()
        logging.info('Found %d objects for match %d' %
                     (len(object_entries), match))

        images = []
        for object_entry in object_entries:
            imagefile = backendDb.objectField(object_entry, 'imagefile')
            objectid = backendDb.objectField(object_entry, 'objectid')
            roi = backendDb.objectField(object_entry, 'roi')
            score = backendDb.objectField(object_entry, 'score')

            image = imreader.imread(imagefile)
            util.drawScoredRoi(image, roi, score=score)

            scale = float(args.winsize) / max(image.shape[0:2])
            image = cv2.resize(image, dsize=(0, 0), fx=scale, fy=scale)
            images.append(image)

        # Assume all images have the same size for now.
        # Assume there are not so many matches.
        image = np.hstack(images)

        # Display an image, wait for the key from user, and parse that key.
        cv2.imshow('examineMatches', image[:, :, ::-1])
        action = key_reader.parse(cv2.waitKey(-1))
        if action is None:
            # User pressed something which does not have an action.
            continue
        elif action == 'exit':
            break
        elif action == 'previous':
            index_match -= 1
        elif action == 'next':
            index_match += 1
        else:
            # User pressed something else which has an assigned action,
            # assume it is a new name.
            logging.info('Setting name "%s" to imagefile "%s"' %
                         (action, imagefile))
            c.execute('UPDATE images SET name=? WHERE imagefile=?' (action,
                                                                    imagefile))
        index_match = index_match % len(match_entries)

    cv2.destroyWindow("examineMatches")

# Helper global vars for mouse callback _monitorPressRelease.
xpress, ypress = None, None
mousePressed = False
mouseReleased = False

def _monitorPressRelease(event, x, y, flags, param):
    ''' A mouse callback for labelling matches. '''

    global xpress, ypress, mousePressed, mouseReleased

    if event == cv2.EVENT_LBUTTONDOWN:
        logging.debug('Left mouse button pressed at %d,%d' % (x, y))
        xpress, ypress = x, y
        assert not mouseReleased
        mousePressed = True

    elif event == cv2.EVENT_LBUTTONUP:
        xpress, ypress = x, y
        logging.debug('Left mouse button released at %d,%d' % (x, y))
        assert not mousePressed
        mouseReleased = True

def _drawMatch(img, roi1, roi2, yoffset):
    def _getCenter(roi):
        return int(0.5 * roi[1] + 0.5 * roi[3]), int(0.25 * roi[0] +
                                                     0.75 * roi[2])

    roi2[0] += yoffset
    roi2[2] += yoffset
    util.drawScoredRoi(img, roi1)
    util.drawScoredRoi(img, roi2)
    center1 = _getCenter(roi1)
    center2 = _getCenter(roi2)
    cv2.line(img, center1, center2, [0, 0, 255], thickness=2)

def _findPressedObject(x, y, cars):
    for i in range(len(cars)):
        roi = backendDb.objectField(cars[i], 'roi')
        if x >= roi[1] and x < roi[3] and y >= roi[0] and y < roi[2]:
            return i
    return None

def labelMatchesParser(subparsers):
    parser = subparsers.add_parser(
        'labelMatches',
        description=
        'Loop through sequential image pairs and label matching objects '
        'on the two images of each pair. '
        'At the start you should see a window with two images one under another. '
        'Press and hold the mouse at a Bbox in the top, and release at a Bbox in the bottom. '
        'That will add a match between this pair of Bboxes. '
        'If one of the two boxes were matched to something already, match will not be added. '
        'Clicking on a box in the top image, and press DEL '
        'will remove a match if the top box was matched. '
        'Pressing "prev" (key "-" by default) takes you to the previous image. '
        'Pressing "next" (key "=" by default) takes you to the next image. '
        'Press "exit" (key "Esc" by default) to save changes and exit. '
        'Pass "min_imagefile" to start with a certain image pair.')
    parser.set_defaults(func=labelMatches)
    parser.add_argument('--where_image',
                        default='TRUE',
                        help='the SQL "where" clause for the "images" table.')
    parser.add_argument('--shuffle', action='store_true')
    parser.add_argument('--winsize', type=int, default=1000)
    parser.add_argument(
        '--key_dict',
        default=
        '{"-": "previous", "=": "next", 127: "delete_match", 27: "exit"}')

def labelMatches(c, args):
    cv2.namedWindow("labelMatches")
    cv2.setMouseCallback('labelMatches', _monitorPressRelease)
    global mousePressed, mouseReleased, xpress, ypress

    c.execute('SELECT imagefile FROM images WHERE %s' % args.where_image)
    image_entries = c.fetchall()
    logging.debug('Found %d images' % len(image_entries))
    if len(image_entries) < 2:
        logging.error('Found only %d images. Quit.' % len(image_entries))
        return

    imreader = backendMedia.MediaReader(rootdir=args.rootdir)

    # For parsing keys.
    key_reader = KeyReader(args.key_dict)

    index_image = 1
    action = None
    while action != 'exit' and index_image < len(image_entries):
        (imagefile1, ) = image_entries[index_image - 1]
        (imagefile2, ) = image_entries[index_image]

        img1 = imreader.imread(imagefile1)
        img2 = imreader.imread(imagefile2)
        # offset of the 2nd image, when they are stacked
        yoffset = img1.shape[0]

        # Make sure images have the same width, so that we can stack them.
        # That will happen when the video changes, so we'll skip that pair.
        if img1.shape[1] != img2.shape[1]:
            logging.warning('Skipping image pair "%s" and "%s" '
                            'since they are of different width.' %
                            (imagefile1, imagefile2))
            index_image += 1

        # get objects from both images
        c.execute('SELECT * FROM objects WHERE imagefile=? ', (imagefile1, ))
        objects1 = c.fetchall()
        logging.info('%d objects found for %s' % (len(objects1), imagefile1))
        c.execute('SELECT * FROM objects WHERE imagefile=? ', (imagefile2, ))
        objects2 = c.fetchall()
        logging.info('%d objects found for %s' % (len(objects2), imagefile2))

        # draw cars in both images
        for object_ in objects1:
            util.drawScoredRoi(img1, backendDb.objectField(object_, 'roi'))
        for object_ in objects2:
            util.drawScoredRoi(img2, backendDb.objectField(object_, 'roi'))

        i1 = i2 = None  # Matches selected with a mouse.

        selectedMatch = None
        needRedraw = True
        action = None
        # Stay in side the loop until a key is pressed.
        while action is None:

            img_stack = np.vstack((img1, img2))

            if needRedraw:

                # find existing matches, and make a map
                matchesOf1 = {}
                matchesOf2 = {}
                for j1 in range(len(objects1)):
                    object1 = objects1[j1]
                    for j2 in range(len(objects2)):
                        object2 = objects2[j2]
                        c.execute(
                            'SELECT match FROM matches WHERE objectid = ? INTERSECT '
                            'SELECT match FROM matches WHERE objectid = ?',
                            (backendDb.objectField(object1, 'objectid'),
                             backendDb.objectField(object2, 'objectid')))
                        matches = c.fetchall()
                        if len(matches) > 0:
                            assert len(matches) == 1  # No duplicate matches.
                            roi1 = backendDb.objectField(object1, 'roi')
                            roi2 = backendDb.objectField(object2, 'roi')
                            _drawMatch(img_stack, roi1, roi2, yoffset)
                            matchesOf1[j1] = matches[0][0]
                            matchesOf2[j2] = matches[0][0]

                # draw image
                scale = float(args.winsize) / max(img_stack.shape[0:2])
                img_show = cv2.resize(img_stack,
                                      dsize=(0, 0),
                                      fx=scale,
                                      fy=scale)
                cv2.imshow('labelMatches', img_show[:, :, ::-1])
                logging.info('Will draw %d matches found between the pair' %
                             len(matchesOf1))
                needRedraw = False

            # process mouse callback effect (button has been pressed)
            if mousePressed:
                i2 = None  # reset after the last unsuccessful match
                logging.debug('Pressed  x=%d, y=%d' % (xpress, ypress))
                xpress /= scale
                ypress /= scale
                i1 = _findPressedObject(xpress, ypress, objects1)
                if i1 is not None:
                    logging.debug('Found pressed object: %d' % i1)
                mousePressed = False

            # process mouse callback effect (button has been released)
            if mouseReleased:
                logging.debug('released x=%d, y=%d' % (xpress, ypress))
                xpress /= scale
                ypress /= scale
                i2 = _findPressedObject(xpress, ypress - yoffset, objects2)
                if i2 is not None:
                    logging.debug('Found released object: %d' % i2)
                mouseReleased = False

            # If we could find pressed and released objects, add match
            if i1 is not None and i2 is not None:

                # If one of the objects is already matched in this image pair, discard.
                if i1 in matchesOf1 or i2 in matchesOf2:
                    logging.warning(
                        'One or two connected objects is already matched')
                    i1 = i2 = None

                else:
                    # Add the match to the list.
                    objectid1 = backendDb.objectField(objects1[i1], 'objectid')
                    objectid2 = backendDb.objectField(objects2[i2], 'objectid')
                    logging.debug('i1 = %d, i2 = %d' % (i1, i2))

                    # Check if this object already in the matches.
                    c.execute('SELECT match FROM matches WHERE objectid=?',
                              (objectid1, ))
                    matches1 = c.fetchall()
                    c.execute('SELECT match FROM matches WHERE objectid=?',
                              (objectid2, ))
                    matches2 = c.fetchall()

                    if len(matches1) > 1 or len(matches2) > 1:
                        logging.error(
                            'One of the objectids %d, %d is in several matches.'
                            % (objectid1, objectid2))
                        continue

                    elif len(matches1) == 1 and len(matches2) == 1:
                        logging.info(
                            'Will merge matches of objectids %d and %d' %
                            (objectid1, objectid2))
                        c.execute('UPDATE matches SET match=? WHERE match=?',
                                  (matches1[0][0], matches2[0][0]))

                    elif len(matches1) == 1 and len(matches2) == 0:
                        logging.info('Add objectid %d to match %d' %
                                     (objectid2, matches1[0][0]))
                        c.execute(
                            'INSERT INTO matches(match, objectid) VALUES (?,?)',
                            (matches1[0][0], objectid2))

                    elif len(matches1) == 0 and len(matches2) == 1:
                        logging.info('Add objectid %d to match %d' %
                                     (objectid1, matches2[0][0]))
                        c.execute(
                            'INSERT INTO matches(match, objectid) VALUES (?,?)',
                            (matches2[0][0], objectid1))

                    elif len(matches1) == 0 and len(matches2) == 0:
                        logging.info(
                            'Add a new match between objectids %d and %d.' %
                            (objectid1, objectid2))

                        # Find a free match index
                        c.execute('SELECT MAX(match) FROM matches')
                        maxmatch = c.fetchone()[0]
                        match = int(
                            maxmatch) + 1 if maxmatch is not None else 1

                        c.execute(
                            'INSERT INTO matches(match, objectid) VALUES (?,?)',
                            (match, objectid1))
                        c.execute(
                            'INSERT INTO matches(match, objectid) VALUES (?,?)',
                            (match, objectid2))

                    else:
                        assert False

                    # Reset when a new match is made.
                    needRedraw = True
                    i1 = i2 = None

            # Stay inside the loop inside one image pair until some button is pressed
            action = key_reader.parse(cv2.waitKey(50))

        # Process pressed key (all except exit)
        if action == 'previous':
            logging.info('Previous image pair')
            if index_image == 1:
                logging.warning('already the first image pair')
            else:
                index_image -= 1
        elif action == 'next':
            logging.info('Next image pair')
            index_image += 1  # exit at last image pair from outer loop
        elif action == 'delete_match':
            # if any car was selected, and it is matched
            if i1 is not None and i1 in matchesOf1:
                match = matchesOf1[i1]
                objectid1 = backendDb.objectField(objects1[i1], 'objectid')
                logging.info('deleting match %d' % match)
                c.execute(
                    'DELETE FROM matches WHERE match = ? AND objectid = ?',
                    (match, objectid1))
            else:
                logging.debug('delete is pressed, but no match is selected')

    cv2.destroyWindow("labelMatches")


#!/usr/bin/python

TEST = """\
5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
"""
INPUT = """\
1564524226
1384554685
7582264835
8812672272
1161463137
7831762344
2855527748
6141737874
8611458313
8215372443
"""

def get_input(inp=TEST):
    data = {}
    for y, line in enumerate(inp.strip().split('\n')):
        for x, level in enumerate(line):
            data[(x, y)] = int(level)
    return data

def increase_level(data):
    for key in data.keys():
        data[key] += 1
    return data

def increase_adjacents(x, y, data):
    adjacents = (
        (x-1, y-1), (x, y-1), (x+1, y-1),
        (x-1, y), (x+1, y),
        (x-1, y+1), (x, y+1), (x+1, y+1),
    )
    for pos in adjacents:
        try:
            data[pos] += 1
        except KeyError:
            pass
    return data

def flash(data):
    flashed = []
    new = True
    while new:
        new = False
        new_flashed = []
        for key in data.keys():
            if data[key] > 9 and key not in flashed:
                flashed.append(key)
                new_flashed.append(key)
                new = True
        for x, y in new_flashed:
            data = increase_adjacents(x, y, data)
    for key in flashed:
        data[key] = 0
    return data, len(flashed)

def a():
    data = get_input(INPUT)
    sum_ = 0
    for i in range(100):
        print('Step', i+1, end=' ')
        data = increase_level(data)
        data, flashed = flash(data)
        print(flashed)
        sum_ += flashed
    print(sum_)

def b():
    data = get_input(INPUT)
    step = 0
    while True:
        print('Step', step+1, end=' ')
        data = increase_level(data)
        data, flashed = flash(data)
        step += 1
        print(flashed)
        if flashed == len(data):
            break
    print(step)

def main():
    a()
    b()

if __name__ == '__main__':
    main()


# https://atcoder.jp/contests/abc088/submissions/10568858
from collections import deque
from sys import setrecursionlimit

setrecursionlimit(10 ** 9)

H, W = map(int, input().split())
field = [list(input()) for i in range(H)]

queue = deque([])
seen = [[0] * W for _ in range(H)]
prev_x = [[0] * W for _ in range(H)]
prev_y = [[0] * W for _ in range(H)]
direction = [[1, 0], [-1, 0], [0, -1], [0, 1]]

def bfs(y, x):
    queue.append([y, x])
    seen[y][x] = 1
    prev_x[y][x] = -1
    prev_y[y][x] = -1

    while queue:
        y, x = queue.popleft()

        for dy, dx in direction:
            next_x = x + dx
            next_y = y + dy

            if 0 <= next_x < W and 0 <= next_y < H and field[next_y][next_x] == "." and seen[next_y][next_x] == 0:
                seen[next_y][next_x] = 1
                prev_x[next_y][next_x] = x
                prev_y[next_y][next_x] = y
                queue.append([next_y, next_x])

shortest_path = [[0] * W for i in range(H)]


class Solution():
	def subarray(self, nums:[], k:int):
		n =len (nums )
		if n<2:
			return False
		dp =[0]* (n+1)
		total =0
		for i in range (n):
			total+= nums[i]
			dp[i+1] = total
		print ("dp...:",dp)

		for j in range (n+1):
			for m in range (j-1):
				if k==0:
					return True
				print (dp[j]-dp[m])
				if (dp[j]-dp[m])% k==0:
					print ("sum:...",dp[j]-dp[m])
					return True

		return False

test =[23,2,4,6,7]
k= 42
so =Solution()
print (so.subarray(test,k))


# coding: utf-8
from django.test import TestCase
from eventex.subscriptions.models import Subscription
from datetime import datetime
from django.db import IntegrityError

class SubscriptionTest(TestCase):
    def setUp(self):
        self.obj = Subscription(
            name='Mauricio Sipmann',
            cpf='12',
            email='email@email.com',
            phone='55-99999999'
        )

    def test_create(self):
        'Subscription deve salvar'
        self.obj.save()
        self.assertEqual(1, self.obj.id)

    def test_has_created_at(self):
        'Subscription deve ter o campo created_at automaticamente'
        self.obj.save()
        self.assertIsInstance(self.obj.created_at, datetime)

    def test_unicode(self):
        self.assertEqual(u'Mauricio Sipmann', unicode(self.obj))

    def test_paid_default_value_is_False(self):
        'Por default pago deve ser false'
        self.assertEqual(False, self.obj.paid)

class SubscriptionUniqueTest(TestCase):
    def setUp(self):
        Subscription.objects.create(name='Mauricio Sipmann', cpf='12345678901',
                                    email='email@email.com', phone='55-99999999')

    def test_cpf_unique(self):
        'CPF deve ser unico'
        s = Subscription(name='Mauricio Sipmann',
            cpf='12345678901',
            email='contato@email.com',
            phone='55-99999999')
        self.assertRaises(IntegrityError, s.save)

    def test_email_can_repeat(self):
        'Email não é unico'
        s = Subscription.objects.create(name='Mauricio Sipmann', cpf='12345678902',
                                        email='email@email.com')
        self.assertEqual(2, s.pk)

#    def test_email_unique(self):
#        'Email deve ser unico'
#        s = Subscription(name='Mauricio Sipmann',
#            cpf='23456789012',
#            email='email@email.com',
#            phone='55-99999999')
#        self.assertRaises(IntegrityError, s.save)
#


import Unity
import tools
import os
import threading
import queue

def main(url, numbreOfThreads):
    unityBT = Unity.Unity(url)
    dataDirName = "data"
    print("1 - getAllLinks")
    if not os.path.exists("./" + dataDirName):
        os.makedirs("./" + dataDirName)
    listLinks = tools.getQueueLinks(unityBT, url)
    queueLock = threading.Lock()
    workQueue = queue.Queue(len(listLinks))
    tools.startScrapingLinks(listLinks, numbreOfThreads, queueLock, workQueue, unityBT, dataDirName)
    print("Exiting Main Thread")

if __name__ == '__main__':
    main(url='https://stackoverflow.com/questions', numbreOfThreads=120)