# -*- coding: utf-8 -*-
"""
@ Instituto Tecnologico y de Estudios Superiores de Occidente
@author: Adrian Ramos Perez

"""
from matplotlib import pyplot as plt
import numpy as np
from scipy import signal as sig

from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.metrics import r2_score,mean_squared_error,make_scorer

# Audio library imports:
import librosa as lb
import librosa.display
import soundfile as sf
from IPython.display import Audio

# Deep Learning imports:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation
from tensorflow.keras.optimizers import Adam, SGD
#from TDNN_Layer import TDNNLayer

#%% Lectura de archivos de audio
samples, sampling_rate= lb.load("../Data/Train/ADS_train_audio_44kHz.wav", sr=None, mono=True,offset=0.0,duration=None)
# Duración en segundos:
duration = len(samples)/sampling_rate
# Escuchar el audio:
Audio("../Data/Train/ADS_train_audio_22kHz.wav")
# Cargar respuesta al impulso:
ir_samples, ir_sampling_rate= lb.load("../Data/Train/ir_golpe22_short.wav", sr=None, mono=True,offset=0.0,duration=None)
ir_duration = len(ir_samples)/ir_sampling_rate

ts_samples, ts_sampling_rate = lb.load("../Data/Train/QueenWatch1.wav", sr=22050, mono=True,offset=0.0,duration=None)
ts_duration = len(ts_samples)/ts_sampling_rate
#%% Plot Audio Signals

# Original Speech Signal:
# fig = plt.figure(figsize=(20,10))
# plt.title(f'ADS Speech Signal (original) sr={sampling_rate}',fontsize=30)
# plt.grid()
# lb.display.waveplot(y=samples,sr=sampling_rate)
# plt.show()
# fig.savefig(f'../Figures/Original_signal_sr={sampling_rate}')

# Impulse Response Signal:
fig = plt.figure(figsize=(20,10))
plt.title(f'Impulse Response sr={ir_sampling_rate}', fontsize=30)
plt.grid()
lb.display.waveplot(y=ir_samples,sr=ir_sampling_rate)
plt.show()
#fig.savefig(f'../Figures/Impulse_Response_sr={ir_sampling_rate}')

# Test Audio Signal:
# fig = plt.figure(figsize=(20,10))
# plt.title(f'Test Audio Signal sr={ts_sampling_rate}', fontsize=30)
# plt.grid()
# lb.display.waveplot(y=ts_samples,sr=ts_sampling_rate)
# plt.show()
# Audio("../Data/QueenWatch1.wav")
# fig.savefig(f'../Figures/Test_audio_signal_Queen_sr={ts_sampling_rate}')
#%% PREPROCESSING

# Scaling
# samples = preprocessing.scale(samples)
# ir_samples = preprocessing.scale(ir_samples)

#%% Convolution between train signals and impulse response.

conv_signal = np.convolve(samples, ir_samples, mode='same')
# Plot the resulting singal:
fig = plt.figure(figsize=(20,10))
plt.title('Convolved signal (Impulse Response * Original Speech Signal)',fontsize=20)
plt.grid()
lb.display.waveplot(y=conv_signal,sr=sampling_rate)
plt.show()
#fig.savefig(f'../Figures/Convolved_signal')
# signal.astype(np.int16).tofile('../Data/conv_signal.wav')
#sf.write('../Data/Train/convolved_signal.wav',conv_signal, sampling_rate, subtype=None)
#%% Delayed Signal (Lags) Matrix generation

n_lag = 5
n_lag_range = np.array([i for i in range(0,n_lag)])
dim_conv_signal = np.shape(conv_signal)
# Lag matrix of dimmensions: convolved signal - lag number (rows) x lag number (columns)
lag_matrix = np.zeros((dim_conv_signal[0]-n_lag, n_lag))
for i in range(n_lag):
        lag_matrix[:,i] = conv_signal[i : dim_conv_signal[0]-n_lag+i]
# del_sig = conv_signal[2:-1]
# del_sig2 = conv_signal[1:-2]
# del_sig3 = conv_signal[:-3]

# del_sig = conv_signal[:-7]
# del_sig2 = conv_signal[1:-6]
# del_sig3 = conv_signal[2:-5]
# del_sig4 = conv_signal[3:-4]
# del_sig5 = conv_signal[4:-3]
# del_sig6 = conv_signal[5:-2]
# del_sig7 = conv_signal[6:-1]
# matrix = np.c_[del_sig, del_sig2, del_sig3]
# matrix7 = np.c_[del_sig, del_sig2, del_sig3, del_sig4, del_sig5, del_sig6, del_sig7]

# Random plot one of the lagged signals:
r_int = np.random.randint(0,n_lag)
fig = plt.figure(figsize=(20,10))
plt.title(f'{r_int} lags sample of the Lagged Signals Matrix : ',fontsize=20)
plt.grid()
lb.display.waveplot(y=lag_matrix[r_int],sr=sampling_rate)
plt.show()

#%% Train dataset and Test dataset split
X_train = lag_matrix
Y_train = samples[n_lag:]

#%% Time-Delay Neural Network model

# Hyperparameters:
Epochs = 200
Learning_rate = 0.05
Decay_rate = Learning_rate/Epochs
Momentum = 0.8
Batch_size = 200

# Model definition:
model = Sequential()

nn_i, nn_h1, nn_h2 = 10,5,5
# Layer(s) definition:
model.add(Dense(nn_i, input_shape=(n_lag,), activation="tanh", name="input_layer_2"))
model.add(Dense(nn_h1, activation="tanh", name="hidden_layer_1"))
# model.add(Dense(nn_h2, activation="tanh", name="hidden_layer_2"))
# model.add(TDNNLayer([-5,2],True, input_shape=(45053,1), activation="tanh"))
model.add(Dense(1, activation='linear', name="output_layer"))

# Compile model:
model.compile(optimizer=Adam(learning_rate =Learning_rate), loss='MeanSquaredError', metrics=['mse'])
xtrain = lag_matrix
# xtrain = preprocessing.scale(xtrain)
ytrain = samples[n_lag:]

# Train model:
m_hist = model.fit(xtrain, ytrain, epochs=Epochs, batch_size=Batch_size, verbose=1)

#%% Plot the loss function and the metrics
fig, axs = plt.subplots(2, 1, figsize=(20,12))
fig.subplots_adjust(hspace=0.3)
axs[0].set_title(f'Loss: {n_lag} lags, Neurons: {nn_i}i, {nn_h1}h, {nn_h2}h2, Epochs:{Epochs}, Batch:{Batch_size}, LR:{Learning_rate}', fontsize=20, fontname="Times New Roman", fontweight='bold')
axs[0].plot(m_hist.history['loss'], 'r', label='train')
# ax.plot(m_hist.history['val_loss'], 'b' ,label='val')
axs[0].set_xlabel(r'Epoch', fontsize=20)
axs[0].set_ylabel(r'Loss', fontsize=20)
axs[0].grid(True)
axs[0].legend()
axs[0].tick_params(labelsize=20)

# Plot the Mean-Square Error
# fig, ax = plt.subplots(2, 2, figsize=(10,6))
# ax.plot(np.sqrt(m_hist.history['mean_squared_error']), 'r', label='train')
# ax.plot(np.sqrt(m_hist.history['val_mean_squared_error']), 'b' ,label='val')
axs[1].set_title(f'MSE: {n_lag} lags, Neurons: {nn_i}i, {nn_h1}h, {nn_h2}h2, Epochs:{Epochs}, Batch:{Batch_size}, LR:{Learning_rate}', fontsize=20, fontname="Times New Roman", fontweight='bold')
axs[1].plot(np.sqrt(m_hist.history['mse']), 'r', label='train')
# ax.plot(np.sqrt(m_hist.history['val_mse']), 'b' ,label='val')
axs[1].set_xlabel(r'Epoch', fontsize=20)
axs[1].set_ylabel(r'MSE', fontsize=20)
axs[1].grid(True)
axs[1].legend()
axs[1].tick_params(labelsize=20)
fig.savefig(f'../Figures/Loss_MSE_{n_lag}lags_{nn_i}i_{nn_h1}h1_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{Learning_rate}lr.png')
#%% View model
from keras.utils.vis_utils import plot_model
plot_model(model, to_file='../Figures/model.png', show_shapes = True)
#%% Prediction

y_pred = model.predict(xtrain)

# Plotting original signal:
fig, axs = plt.subplots(2, 1, figsize=(30,12))
fig.subplots_adjust(hspace=0.4)
# plt.tight_layout(pad=0.7)
axs[0].set_title(f'Original Signal', fontsize=30, fontname="Times New Roman", fontweight='bold')
axs[0].plot(samples,c='b')
axs[0].set_xlabel('Samples', fontsize=30)
axs[0].set_ylabel('Amplitude', fontsize=30)
axs[0].grid(True)

# Plotting predicted signal (y hat):
# fig = plt.figure(figsize=(20,10))
axs[1].set_title(f'Y_hat: {n_lag} lags, Neurons: {nn_i}i, {nn_h1}h, {nn_h2}h2, Epochs:{Epochs}, Batch:{Batch_size}, LR:{Learning_rate}', fontsize=30, fontname="Times New Roman", fontweight='bold')
axs[1].plot(y_pred,c='g')
axs[1].set_xlabel('Samples', fontsize=30)
axs[1].set_ylabel('Amplitude', fontsize=30)
axs[1].grid(True)
plt.show()
fig.savefig(f'../Figures/y_hat_{n_lag}lags_{nn_i}i_{nn_h1}h_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{Learning_rate}lr.png', dpi=450 )

# Save to sound file:
sf.write(f'../Data/predicted_signal_{n_lag}lags_{nn_i}i_{nn_h1}h1_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{Learning_rate}lr.wav',y_pred, sampling_rate, subtype=None)
#%% Evaluate performance:

R2_score = r2_score(ytrain,y_pred)
# Plotting R2_Score
xmin,xmax = min(ytrain),max(ytrain)
xline = np.linspace(xmin,xmax)
fig = plt.figure(figsize=(20,15))
plt.scatter(ytrain,y_pred,label='Estimation')
plt.plot(xline,xline,'k--',label='Perfect estimation')
plt.xlabel('Real output', fontsize=35, fontname="Times New Roman",)
plt.ylabel('Estimation output', fontsize=35, fontname="Times New Roman",)
plt.suptitle('R^2=%0.4f'%R2_score, fontsize=40, fontname="Times New Roman", fontweight='bold')
plt.title(f'{n_lag}lags_{nn_i}i_{nn_h1}h1_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{Learning_rate}lr', fontsize=30,fontname="Times New Roman" )
plt.legend()
plt.grid()
plt.show()
fig.savefig(f'../Figures/R2_{n_lag}lags_{nn_i}i_{nn_h1}h1_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{Learning_rate}lr.png', dpi=450)

#%%  Test

# Queen_y_pred = model.predict(ts_samples)
# sf.write('../Data/queen_predicted_signal.wav',Queen_y_pred, ts_sampling_rate, subtype=None)
# plt.show()
# plt.figure()
# plt.title('Queen Predicted Signal')
# plt.plot(Queen_y_pred,c='r')

# score = model.evaluate(matrix, samples[3:])
# print('Test loss:', score[0])
# print('Test mse:', score[1])

# corr = sig.correlate(y_pred, y_pred)

# plt.figure()
# plt.title('Signals Correlation')
# plt.plot(corr)
# plt.show()

#%% Hyperparameter tunning
from sklearn.model_selection import GridSearchCV

# RandomSearchCV

#%% XGBoost Model Approach

import xgboost as xgb
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_squared_error, mean_absolute_error, mean_absolute_percentage_error, r2_score

xgb_model = xgb.XGBRegressor()
# parameter definitions
param_grid = {
    'n_estimators': range(100, 200, 10), # De 50 hasta 250 estimadores en aumentos de 50
    'learning_rate': [0.05, 0.1, 0.3, 1], # Eta
    'max_depth': range(2, 5, 1),
    'subsample': [0.2, 0.5, 0.7, 1] # Submuestreo aleatorio para prevenir overfitting
}

grid_search = GridSearchCV(estimator=xgb_model,
                  param_grid=param_grid,
                  #scoring='neg_mean_squared_error',
                  scoring='r2',
                  n_jobs=-1, # All procesors
                  cv=5,
                  verbose=4)

#grid_search.fit(X_train, Y_train)

print("Mejores parámetros:",grid_search.best_params_)

# Dictionary of best parameters:
best_params = {
    'n_estimators': 100, # De 50 hasta 250 estimadores en aumentos de 50
    'learning_rate': 0.1, # Eta
    'max_depth': 5,
    'subsample': 0.5
    }

# Create model with best params:
xgb_model_best_params = xgb.XGBRegressor(
                             n_estimators = best_params['n_estimators'],
                             max_depth = best_params['max_depth'],
                             eval_metric = 'r2',
                             learning_rate = best_params['learning_rate'],
                             verbosity = 4,
                             n_jobs = -1,
                             gamma = 1,)
#%%
xgb_best_model = grid_search.best_estimator_
# Save model for model persistence:
xgb_best_model.save_model("../Models/xgb_best_model.json")

# Realizar predicción sobre la señal original:
xgb_best_Yhat = xgb_best_model.predict(conv_signal)

# Calcular scores de la predicción del modelo:
xgb_best_rmse = (mean_squared_error(samples, xgb_best_Yhat)**0.5)
xgb_best_mae = mean_absolute_error(samples, xgb_best_Yhat)
xgb_best_mape = mean_absolute_percentage_error(samples, xgb_best_Yhat)
xgb_best_r2 = r2_score(samples, xgb_best_Yhat)
print('RMSE: {0:.3f}'.format(xgb_best_rmse))
print('MAE: {0:.3f}'.format(xgb_best_mae))
print('MAPE: {0:.3f}'.format(xgb_best_mape))
print('R^2: {0:.3f}'.format(xgb_best_r2))

# Graph and save the predicted signal:
xgb_best_Yhat = xgb_best_model.predict(conv_signal)

# Plotting original signal:
fig, axs = plt.subplots(2, 1, figsize=(30,12))
fig.subplots_adjust(hspace=0.4)
# plt.tight_layout(pad=0.7)
axs[0].set_title(f'Original Signal', fontsize=30, fontname="Times New Roman", fontweight='bold')
axs[0].plot(samples,c='b')
axs[0].set_xlabel('Samples', fontsize=30)
axs[0].set_ylabel('Amplitude', fontsize=30)
axs[0].grid(True)

# Plotting predicted signal (y hat):
# fig = plt.figure(figsize=(20,10))
axs[1].set_title(f'Y_hat: {n_lag} lags, Neurons: {nn_i}i, {nn_h1}h, {nn_h2}h2, Epochs:{Epochs}, Batch:{Batch_size}, LR:{Learning_rate}', fontsize=30, fontname="Times New Roman", fontweight='bold')
axs[1].plot(xgb_best_Yhat ,c='g')
axs[1].set_xlabel('Samples', fontsize=30)
axs[1].set_ylabel('Amplitude', fontsize=30)
axs[1].grid(True)
plt.show()
fig.savefig(f'../Figures/xgb_yhat_{n_lag}lags_{n_estimators}estimators_{max_depth}mdepth_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{xgb_learning_rate}lr.png', dpi=450 )

# Save to sound file:
sf.write(f'../Data/Test/xgb_predicted_signal_{n_lag}lags_{nn_i}i_{nn_h1}h1_{nn_h2}h2_{Epochs}e_{Batch_size}bs_{Learning_rate}lr.wav',y_pred, sampling_rate, subtype=None)

#%% Save a model to JSON

# serialize model to JSON
model_json = model.to_json()

with open("../Figures/TDNN_model.json", "w") as json_file:
    json_file.write(model_json)

# save weights to HDF5
model.save_weights("../Figures/TDNN_model.h5")
print("Model saved")

#%% Retrieve the model: load json and create model
# from keras.models import model_from_json
# json_file = open('../Figures/TDNN_model.json', 'r')
# saved_model = json_file.read()
# close the file as good practice:
# json_file.close()
# model_ = model_from_json(saved_model)
# load weights into new model:
# model_.load_weights("../Figures/TDNN_model.h5")
# print("Model loaded")


# -*- coding: utf-8 -*-

"""
Crie um programa que inverta a ordem das linhas do arquivo
pares.txt. A primeira linha deve conter o maior número: e a ultima,
o menor.
"""

print(60 * "=")

pares = open("pares.txt", "r")
saida = open("paresInvertidos.txt", "w")

l = pares.readlines()
l.reverse()

for linha in l:
	saida.write(linha)

pares.close()
saida.close()

print(60 * "=")


import time

import numpy as np
import pymongo
import matplotlib.pyplot as plt

from env.core import AircraftAgentSet
from env.load import load_data_set, load_and_split_data
from env.model import Routing, FlightPlan, Aircraft
from env.render import plot_line, make_random_color, make_color, draw
from env.utils import pnpoly

# --------------------------------------------
# -- Generate Continuous Conflict Scenarios --
# --------------------------------------------

"""
 1. 找到所有经过武汉扇区（vertices）的航路 → wh_routing_list；
 2. 截取wh_routing_list航路中在武汉扇区（vertices）里的航段；
 3. 随机抽取120个routing，构建飞行计划和AgentSet；
 4. 运行AgentSet，并进行冲突探测；
 5. 剔除冲突时间-起飞时间<=600的飞行计划，并重建AgentSet；
 6. 运行AgentSet，并进行冲突探测；
 7. 记录冲突信息和飞行计划；
 8. 记录各个冲突信息和飞行计划；
"""

shift = 360

vertices = ((109.51666666666667, 31.9),
            (110.86666666666666, 33.53333333333333),
            (114.07, 32.125),
            (115.81333333333333, 32.90833333333333),
            (115.93333333333334, 30.083333333333332),
            (114.56666666666666, 29.033333333333335),
            (113.12, 29.383333333333333),
            (109.4, 29.516666666666666),
            (109.51666666666667, 31.9),
            (109.51666666666667, 31.9))

data_set = load_data_set()
flight_level = {i - 20: i * 300.0 + int(i >= 29) * 200.0 for i in range(20, 41)}  # 6000~12500

# step 1和2
def search_routing_in_wuhan():
    import simplekml

    kml = simplekml.Kml()
    folder = kml.newfolder(name='Polygons')
    plot_line(folder,
              (p + (8100.0,) for p in vertices),
              name='border')

    folder = kml.newfolder(name='Lines')
    inner_routes, route_id = [], []
    for r_id, routing in data_set.rou_dict.items():
        wpt_list = routing.wpt_list

        plot_line(folder,
                  (wpt.location.tuple() + (8100.0,) for wpt in wpt_list),
                  name=r_id,
                  color=make_random_color())

        i, idx = 0, []
        for i, wpt in enumerate(wpt_list):
            if pnpoly(vertices, wpt.location.tuple()):
                idx.append(i)

        if len(idx) > 0:
            min_v, max_v = min(idx), max(idx)
            if min_v == 0:
                mode = 'start'
            elif max_v == i:
                mode = 'end'
            else:
                mode = 'part'

            wpt_list_part = wpt_list[max(0, min_v - 1): min(i + 1, max_v + 2)]
            inner_routes.append([r_id, wpt_list_part, mode])
            route_id.append(r_id)

            plot_line(folder,
                      (wpt.location.tuple() + (8100.0,) for wpt in wpt_list_part),
                      name=r_id + '_part',
                      color=make_color(255, 0, 0))
    kml.save('wuhan.kml')

    count = 0
    for fpl in data_set.fpl_dict.values():
        if fpl.routing.id in route_id:
            count += 1
    print(count)

    return inner_routes

# step 3
def get_fpl_random(routes, interval=30, number=100, max_time=43200):
    fpl_set = list(data_set.fpl_dict.values())
    np.random.shuffle(fpl_set)

    count = 0
    fpl_list, candi = [], {}
    for j in range(0, max_time, interval):
        np.random.shuffle(routes)
        candi[j] = []

        for [r_id, wpt_list, mode] in routes[:number]:
            fpl_template = fpl_set[count % len(fpl_set)]

            # routing
            routing = Routing(id=r_id, wpt_list=wpt_list)
            # aircraft
            aircraft = fpl_template.aircraft
            # min_alt
            if mode == 'start':  # 在扇区内起飞的航班，上升后平飞
                min_alt = 6000.0
            else:
                min_alt = flight_level[np.random.randint(0, len(flight_level) - 1)]
            # max_alt
            if mode == 'end':  # 在扇区内落地的航班，下降
                max_alt = 6000.0
            elif np.random.randint(0, 60) % 2 == 0:  # 1/2的航班起始高度等于目标高度
                max_alt = flight_level[np.random.randint(0, len(flight_level) - 1)]
            else:
                max_alt = min_alt
            # flight plan
            fpl = FlightPlan(id=str(count),
                             routing=routing,
                             aircraft=aircraft,
                             startTime=j,
                             min_alt=min_alt,
                             max_alt=max_alt)
            fpl_list.append(fpl)
            candi[j].append(fpl.id)
            count += 1

    return fpl_list, candi

# step 4
def run_scenario(fpl_list, candi):
    print('\t>>>', len(fpl_list))
    agent_set = AircraftAgentSet(fpl_list=fpl_list, candi=candi)

    all_conflicts, record = [], {'flow': [], 'conflict': []}
    shift_list, check_list = [], []
    start = time.time()
    while True:
        agent_set.step(duration=1)
        conflicts = []
        for c in agent_set.detect():
            c_id = c.id
            [a0_id, a1_id] = c_id.split('-')
            c_id_reverse = a1_id + '-' + a0_id
            if c_id in check_list or c_id_reverse in check_list:
                continue

            check_list.append(c_id)
            check_list.append(c_id_reverse)
            fpl0 = agent_set.agents[a0_id].fpl
            fpl1 = agent_set.agents[a1_id].fpl
            if c.time - fpl0.startTime < shift and a0_id not in shift_list:
                shift_list.append(a0_id)
            if c.time - fpl1.startTime < shift and a1_id not in shift_list:
                shift_list.append(a1_id)
            conflicts.append(c)

        if len(conflicts) > 0:
            all_conflicts += conflicts

        now = agent_set.time
        if now % 1000 == 0:
            print('\t>>>', now, len(agent_set.agent_id_en), len(all_conflicts))
        record['flow'].append([now, len(agent_set.agent_id_en)])
        record['conflict'].append([now, len(conflicts)])

        if agent_set.is_done():
            print('场景运行结束：', now, len(conflicts), time.time() - start)
            break

    return all_conflicts, record, shift_list

# Step 7
def write_in_db(name, conflict_info, fpl_info, col='scenarios_meta'):
    database = pymongo.MongoClient('localhost')['admin']
    collection = database[col]

    c_times = [c.time for c in conflict_info]
    conflicts = [c.to_dict() for c in conflict_info]
    fpl_list = [fpl.to_dict() for fpl in fpl_info]
    collection.insert_one(dict(id=name, start=min(c_times) - 301, conflicts=conflicts, fpl_list=fpl_list))

def analysis(record, new_record, candi, new_candi, name):
    fig, axes = plt.subplots(3, 1)
    x, y = [], []
    for [t, flow, *_] in record['flow']:
        x.append(t)
        y.append(flow)
    axes[0].plot(x, y, label='before')
    x, y = [], []
    for [t, flow, *_] in new_record['flow']:
        x.append(t)
        y.append(flow)
    axes[0].plot(x, y, label='after')
    axes[0].set_xlabel('Time Axis')
    axes[0].set_ylabel('Flow')
    axes[0].legend()

    x, y = [], []
    for [t, flow, *_] in record['conflict']:
        x.append(t)
        y.append(flow)
    axes[1].plot(x, y, label='before')
    x, y = [], []
    for [t, flow, *_] in new_record['conflict']:
        x.append(t)
        y.append(flow)
    axes[1].plot(x, y, label='after')
    axes[1].set_xlabel('Time Axis')
    axes[1].set_ylabel('Conflict')
    axes[1].legend()

    x, y = [], []
    for key in sorted(candi.keys()):
        x.append(key)
        y.append(len(candi[key]))
    axes[2].plot(x, y, label='before')
    x, y = [], []
    for key in sorted(new_candi.keys()):
        x.append(key)
        y.append(len(new_candi[key]))
    axes[2].plot(x, y, label='after')
    axes[2].set_xlabel('Time Axis')
    axes[2].set_ylabel('Candi')
    axes[2].legend()

    plt.subplots_adjust(hspace=0.5)
    fig.savefig('stats_{}.pdf'.format(name))
    # plt.show()

def make_random_scenario(num_start=0, num_end=10):
    # np.random.seed(1234)
    inner_routes = search_routing_in_wuhan()
    print('>>> 一共找到{}条经过武汉扇区的Routing（Step 1和2）'.format(len(inner_routes)))

    for i in range(num_start, num_end):
        print('No.{}/{}'.format(i+1, num_end))
        print('>>> 随机加载航空器（Step 3)')
        fpl_list, candi = get_fpl_random(inner_routes[:], interval=10, number=3, max_time=1000)

        print('>>> 开始运行场景，并进行冲突探测（Step 4和5）')
        conflicts, record, shift_list = run_scenario(fpl_list, candi)

        print(len(shift_list))
        new_fpl_list, new_candi = [], {}
        for fpl in fpl_list:
            if fpl.id not in shift_list:
                new_fpl_list.append(fpl)
                start = fpl.startTime
                if start in new_candi.keys():
                    new_candi[start].append(fpl.id)
                else:
                    new_candi[start] = [fpl.id]

        print('>>> 重新运行场景，并进行冲突探测（Step 5和6）')
        new_conflicts, new_record, shift_list = run_scenario(new_fpl_list, new_candi)
        assert len(shift_list) == 0
        analysis(record, new_record, candi, new_candi, str(i + 1))

        print('>>> 记录冲突信息和飞行计划（Step 7）\n')
        write_in_db(i, new_conflicts, new_fpl_list)

# ------------------------------------------
# -- Generate Episodic Conflict Scenarios --
# ------------------------------------------
def run_scenario_1(fpl_list, candi):
    print('fpl_list:', len(fpl_list))
    agent_set = AircraftAgentSet(fpl_list=fpl_list, candi=candi)

    check_list, shift_list = [], []
    conflicts, structure = [], {}
    while not agent_set.is_done():
        agent_set.step(1)
        for c in agent_set.detect():
            c_id = c.id
            [a0_id, a1_id] = c_id.split('-')
            c_id_reverse = a1_id + '-' + a0_id
            if c_id in check_list or c_id_reverse in check_list:
                continue
            check_list.append(c_id)
            check_list.append(c_id_reverse)

            if a0_id in structure.keys():
                structure[a0_id].append((c.time, a1_id))
            else:
                structure[a0_id] = [(c.time, a1_id)]

            if a1_id in structure.keys():
                structure[a1_id].append((c.time, a0_id))
            else:
                structure[a1_id] = [(c.time, a0_id)]

            fpl0 = agent_set.agents[a0_id].fpl
            fpl1 = agent_set.agents[a1_id].fpl
            if c.time - fpl0.startTime < shift and a0_id not in shift_list:
                shift_list.append(a0_id)
            if c.time - fpl1.startTime < shift and a1_id not in shift_list:
                shift_list.append(a1_id)

            # c.printf()
            conflicts.append(c)

        now = agent_set.time
        if now % 1000 == 0:
            print('\t>>>', now, len(agent_set.agent_id_en))

    print(len(shift_list) > 0, shift_list)

    shift_list = []
    for key, value in structure.items():
        if len(value) <= 1:
            continue

        print(key, value)
        base = None
        for v in value:
            if base is None:
                base = v
                continue

            if abs(v[0] - base[0]) <= 360:
                shift_list.append(v[1])
                print('\t>>>', base, v, shift_list)
            else:
                base = v
    print(list(set(shift_list)))
    return shift_list, conflicts

def split_individual_conflict():
    train_set, _ = load_and_split_data(col='scenarios_meta', ratio=1.0)
    count, s_name = 1, 1
    for info in train_set[100:]:
        fpl_list = info['fpl_list']
        shift_list, _ = run_scenario_1(fpl_list=fpl_list, candi=info['candi'])

        new_fpl_list, new_candi = [], {}
        for fpl in fpl_list:
            fpl_id, start = fpl.id, fpl.startTime
            if fpl_id not in shift_list:
                new_fpl_list.append(fpl)
                if start in new_candi.keys():
                    new_candi[start].append(fpl_id)
                else:
                    new_candi[start] = [fpl_id]

        new_shift_list, new_conflicts = run_scenario_1(fpl_list=new_fpl_list, candi=new_candi)
        assert len(new_shift_list) <= 0

        for c in new_conflicts:
            c.printf()
            write_in_db('{}_{}'.format(count, s_name), [c, ], new_fpl_list, col='scenarios_dqn')
            s_name += 1

        count += 1

# ---------------------------------------
# -- Check Episodic Conflict Scenarios --
# ---------------------------------------

def check_conflict(col='scenarios_gail'):
    train_set, _ = load_and_split_data(col=col, ratio=1.0)

    count = 0
    for info in train_set:
        print(info['id'])
        conflict_ac, start = info['conflict_ac'], info['start']
        print('{}/{}'.format(count + 1, len(train_set)), info['id'], conflict_ac, start)
        print(info['conflict'])

        agent_set = AircraftAgentSet(fpl_list=info['fpl_list'], candi=info['candi'])
        agent_set.step(duration=start, basic=True)
        end_time = agent_set.time + 601

        check_list, conflicts = [], []
        while not agent_set.is_done():
            agent_set.step(1)

            for c in agent_set.detect(search=conflict_ac):
                c_id = c.id
                [a0_id, a1_id] = c_id.split('-')
                c_id_reverse = a1_id + '-' + a0_id
                if c_id in check_list or c_id_reverse in check_list:
                    continue
                check_list.append(c_id)
                check_list.append(c_id_reverse)
                conflicts.append(c)
                c.printf()

            if end_time is not None and agent_set.time > end_time:
                break

if __name__ == '__main__':
    # make_random_scenario(num_start=100, num_end=200)
    # split_individual_conflict()
    check_conflict()


import functools
import glob
import json
import os

import mock
import pytest

from google.protobuf import text_format
from google.cloud.firestore_v1beta1.proto import firestore_pb2
from google.cloud.firestore_v1beta1.proto import test_pb2
from google.cloud.firestore_v1beta1.proto import write_pb2

_UNIMPLEMENTED_FEATURES = [
    #  tests having to do with the ArrayUnion, ArrayRemove, and Delete
    # transforms
    'create-all-transforms.textproto',
    'create-arrayremove-multi.textproto',
    'create-arrayremove-nested.textproto',
    'create-arrayremove-noarray-nested.textproto',
    'create-arrayremove-noarray.textproto',
    'create-arrayremove.textproto',
    'create-arrayunion-multi.textproto',
    'create-arrayunion-nested.textproto',
    'create-arrayunion-noarray-nested.textproto',
    'create-arrayunion-noarray.textproto',
    'create-arrayunion.textproto',
    'set-all-transforms.textproto',
    'set-arrayremove-multi.textproto',
    'set-arrayremove-nested.textproto',
    'set-arrayremove-noarray-nested.textproto',
    'set-arrayremove-noarray.textproto',
    'set-arrayremove.textproto',
    'set-arrayunion-multi.textproto',
    'set-arrayunion-nested.textproto',
    'set-arrayunion-noarray-nested.textproto',
    'set-arrayunion-noarray.textproto',
    'set-arrayunion.textproto',
    'set-del-merge-alone.textproto',
    'set-del-merge.textproto',
    'set-del-mergeall.textproto',
    'set-del-nomerge.textproto',
    'update-all-transforms.textproto',
    'update-arrayremove-alone.textproto',
    'update-arrayremove-multi.textproto',
    'update-arrayremove-nested.textproto',
    'update-arrayremove-noarray-nested.textproto',
    'update-arrayremove-noarray.textproto',
    'update-arrayremove.textproto',
    'update-arrayunion-alone.textproto',
    'update-arrayunion-multi.textproto',
    'update-arrayunion-nested.textproto',
    'update-arrayunion-noarray-nested.textproto',
    'update-arrayunion-noarray.textproto',
    'update-arrayunion.textproto',
    'update-del-alone.textproto',
    'update-del-dot.textproto',
    'update-del-nested.textproto',
    'update-del-noarray-nested.textproto',
    'update-del-noarray.textproto',
    'update-del.textproto',
    ]

def _load_testproto(filename):
    with open(filename, 'r') as tp_file:
        tp_text = tp_file.read()
    test_proto = test_pb2.Test()
    text_format.Merge(tp_text, test_proto)
    shortname = os.path.split(filename)[-1]
    test_proto.description = (
        test_proto.description + ' (%s)' % shortname
        )
    return test_proto

_UNIMPLEMENTED_FEATURE_TESTPROTOS = [
    _load_testproto(filename) for filename in sorted(
        glob.glob('tests/unit/testdata/*.textproto'))
    if os.path.split(filename)[-1] in _UNIMPLEMENTED_FEATURES
]

IMPLEMENTED_FEATURE_TESTPROTOS = [
    _load_testproto(filename) for filename in sorted(
        glob.glob('tests/unit/testdata/*.textproto'))
    if not os.path.split(filename)[-1] in _UNIMPLEMENTED_FEATURES
]

_CREATE_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'create']

_GET_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'get']

_SET_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'set']

_UPDATE_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'update']

_UPDATE_PATHS_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'update_paths']

_DELETE_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'delete']

_LISTEN_TESTPROTOS = [
    test_proto for test_proto in IMPLEMENTED_FEATURE_TESTPROTOS
    if test_proto.WhichOneof('test') == 'listen']

def _mock_firestore_api():
    firestore_api = mock.Mock(spec=['commit'])
    commit_response = firestore_pb2.CommitResponse(
        write_results=[write_pb2.WriteResult()],
    )
    firestore_api.commit.return_value = commit_response
    return firestore_api

def _make_client_document(firestore_api, testcase):
    from google.cloud.firestore_v1beta1 import Client
    from google.cloud.firestore_v1beta1.client import DEFAULT_DATABASE
    import google.auth.credentials

    _, project, _, database, _, doc_path = testcase.doc_ref_path.split('/', 5)
    assert database == DEFAULT_DATABASE

    # Attach the fake GAPIC to a real client.
    credentials = mock.Mock(spec=google.auth.credentials.Credentials)
    client = Client(project=project, credentials=credentials)
    client._firestore_api_internal = firestore_api
    return client, client.document(doc_path)

def _run_testcase(testcase, call, firestore_api, client):
    if getattr(testcase, 'is_error', False):
        # TODO: is there a subclass of Exception we can check for?
        with pytest.raises(Exception):
            call()
    else:
        call()
        firestore_api.commit.assert_called_once_with(
            client._database_string,
            list(testcase.request.writes),
            transaction=None,
            metadata=client._rpc_metadata)

@pytest.mark.parametrize('test_proto', _CREATE_TESTPROTOS)
def test_create_testprotos(test_proto):
    testcase = test_proto.create
    firestore_api = _mock_firestore_api()
    client, document = _make_client_document(firestore_api, testcase)
    data = convert_data(json.loads(testcase.json_data))
    call = functools.partial(document.create, data)
    _run_testcase(testcase, call, firestore_api, client)

@pytest.mark.parametrize('test_proto', _GET_TESTPROTOS)
def test_get_testprotos(test_proto):
    testcase = test_proto.get
    # XXX this stub currently does nothing because no get testcases have
    # is_error; taking this bit out causes the existing tests to fail
    # due to a lack of batch getting
    try:
        testcase.is_error
    except AttributeError:
        return
    else:  # pragma: NO COVER
        testcase = test_proto.get
        firestore_api = _mock_firestore_api()
        client, document = _make_client_document(firestore_api, testcase)
        call = functools.partial(document.get, None, None)
        _run_testcase(testcase, call, firestore_api, client)

@pytest.mark.parametrize('test_proto', _SET_TESTPROTOS)
def test_set_testprotos(test_proto):
    testcase = test_proto.set
    firestore_api = _mock_firestore_api()
    client, document = _make_client_document(firestore_api, testcase)
    data = convert_data(json.loads(testcase.json_data))
    if testcase.HasField("option"):
        merge = convert_set_option(testcase.option)
    else:
        merge = False
    call = functools.partial(document.set, data, merge=merge)
    _run_testcase(testcase, call, firestore_api, client)

@pytest.mark.parametrize('test_proto', _UPDATE_TESTPROTOS)
def test_update_testprotos(test_proto):
    testcase = test_proto.update
    firestore_api = _mock_firestore_api()
    client, document = _make_client_document(firestore_api, testcase)
    data = convert_data(json.loads(testcase.json_data))
    if testcase.HasField("precondition"):
        option = convert_precondition(testcase.precondition)
    else:
        option = None
    call = functools.partial(document.update, data, option)
    _run_testcase(testcase, call, firestore_api, client)

@pytest.mark.skip(
    reason="Python has no way to call update with a list of field paths.")
@pytest.mark.parametrize('test_proto', _UPDATE_PATHS_TESTPROTOS)
def test_update_paths_testprotos(test_proto):  # pragma: NO COVER
    pass

@pytest.mark.parametrize('test_proto', _DELETE_TESTPROTOS)
def test_delete_testprotos(test_proto):
    testcase = test_proto.delete
    firestore_api = _mock_firestore_api()
    client, document = _make_client_document(firestore_api, testcase)
    if testcase.HasField("precondition"):
        option = convert_precondition(testcase.precondition)
    else:
        option = None
    call = functools.partial(document.delete, option)
    _run_testcase(testcase, call, firestore_api, client)

@pytest.mark.skip(reason="Watch aka listen not yet implemented in Python.")
@pytest.mark.parametrize('test_proto', _LISTEN_TESTPROTOS)
def test_listen_paths_testprotos(test_proto):  # pragma: NO COVER
    pass

@pytest.mark.skip(reason="Feature not yet implemented in Python.")
@pytest.mark.parametrize('test_proto', _UNIMPLEMENTED_FEATURE_TESTPROTOS)
def test_unimplemented_features_testprotos(test_proto):  # pragma: NO COVER
    pass

def convert_data(v):
    # Replace the strings 'ServerTimestamp' and 'Delete' with the corresponding
    # sentinels.
    from google.cloud.firestore_v1beta1 import SERVER_TIMESTAMP, DELETE_FIELD

    if v == 'ServerTimestamp':
        return SERVER_TIMESTAMP
    elif v == 'Delete':
        return DELETE_FIELD
    elif isinstance(v, list):
        return [convert_data(e) for e in v]
    elif isinstance(v, dict):
        return {k: convert_data(v2) for k, v2 in v.items()}
    else:
        return v

def convert_set_option(option):
    from google.cloud.firestore_v1beta1 import _helpers

    if option.fields:
        return [
            _helpers.FieldPath(*field.field).to_api_repr()
            for field in option.fields
        ]

    assert option.all
    return True

def convert_precondition(precond):
    from google.cloud.firestore_v1beta1 import Client

    if precond.HasField('exists'):
        return Client.write_option(exists=precond.exists)

    assert precond.HasField('update_time')
    return Client.write_option(last_update_time=precond.update_time)


import numpy as np
import matplotlib.pyplot as plt
import mopc as mop

'''choose halo redshift and mass [Msun]
'''
z = 0.57
m = 2e13

'''choose radial range (x = r/rvir)
'''
x = np.logspace(np.log10(0.1),np.log10(10),100)

'''choose angular range [eg. arcmin]
'''
theta = np.arange(100)*0.05 + 0.5
theta = np.linspace(0.5,5.5,50)
sr2sqarcmin = 3282.8 * 60.**2

'''
choose observing frequency [GHz]
'''
nu = 150.

'''
read beam profile
'''
theta_rad, beam = np.loadtxt('data/beam_example.txt',unpack=True)
def f_beam(tht):
    tht_in = theta_rad
    return np.interp(tht, tht_in, beam, period=np.pi)

##########################################################################################
'''project a gNFW density profile [cgs unit] from Battaglia 2016
into a T_kSZ profile [muK arcmin^2]
'''
rho0 = np.log10(4e3 * (m/1e14)**0.29 * (1+z)**(-0.66))
xc = 0.5
bt = 3.83 * (m/1e14)**0.04 * (1+z)**(-0.025)
a2h= 1.1
par_rho = [rho0,xc,bt,a2h]
rho_gnfw = mop.rho_gnfw1h(x,m,z,par_rho[:3])
temp_ksz_gnfw = mop.make_a_obs_profile_sim_rho(theta,m,z,par_rho,f_beam)

plt.figure(0,figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.loglog(x, rho_gnfw, lw=3, label='gNFW density')
plt.xlabel(r'x',size=14)
plt.ylabel(r"$\rho_{gas}(x) [g/cm^3]$ ",size=14)
plt.subplot(1, 2, 2)
plt.plot(theta, temp_ksz_gnfw*sr2sqarcmin,lw=3)
plt.xlabel(r'$\theta$ [arcmin]',size=14)
plt.ylabel(r'$T_{kSZ} [\mu K \cdot arcmin^2]$',size=14)
plt.tight_layout()
plt.savefig('fig/rho_gnfw.pdf')

##########################################################################################
'''project a gNFW profile of the thermal Pressure [cgs unit] from Battaglia et al. 2012
into a T_tSZ profile [muK arcmin^2]
'''

P0 = 18.1 * (m/1e14)**0.154 * (1+z)**(-0.758)
al = 1.
bt = 4.35 * (m/1e14)**0.0393 * (1+z)**0.415
a2h = 0.7
par_pth = [P0, al,bt,a2h]
pth_gnfw = mop.Pth_gnfw1h(x,m,z,par_pth[:3])
temp_tsz_gnfw = mop.make_a_obs_profile_sim_pth(theta,m,z,par_pth,nu,f_beam)

plt.figure(1,figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.loglog(x, pth_gnfw,lw=3, label='gNFW pressure')
plt.xlabel(r'x',size=14)
plt.ylabel(r"$P_{th}(x) [dyne/cm^2]$",size=14)
plt.subplot(1, 2, 2)
plt.plot(theta, temp_tsz_gnfw*sr2sqarcmin,lw=3)
plt.xlabel(r'$\theta$ [arcmin]',size=14)
plt.ylabel(r'$T_{tSZ} [\mu K \cdot arcmin^2]$',size=14)
plt.tight_layout()
plt.savefig('fig/pth_gnfw.pdf')


# -----------------------------------------------------------
# Need Review
# Runtime: 64 ms, faster than 50.51% of Python3 online submissions for ZigZag Conversion.
# Memory Usage: 12.8 MB, less than 100.00% of Python3 online submissions for ZigZag Conversion.
# Comment: NA
# -----------------------------------------------------------

def convert(s: str, numRows: int) -> str:
    if numRows == 1: return s
    rows = {idx: '' for idx in range(min(len(s), numRows))}
    i = 0
    direction = False
    for c in s:
        rows[i] += c
        if ((i==0) | (i==numRows-1)):
            direction = not direction
        if direction:
            i += 1
        else:
            i += -1
    answer = ''
    for idx in range(len(rows)):
        answer += rows[idx]
    return answer


from flask import session
from models.users import Users
from flask.json import jsonify
from auth.auth import is_authenticated, is_admin
from models.users import db

def get_dashboard_data():

    user_id = session.get("user_id")
    # Check if session exist
    if not is_authenticated(user_id):
        return jsonify({"error": "Unauthorized"}), 401

    # Check if role is admin
    if not is_admin(user_id):
        return jsonify({"error": "Unauthorized"}), 401

    totalUser = Users.query.filter_by(role="user", is_deleted=0).count()
    distinctRole = db.session.query(Users.role).distinct().count()
    deletedUsers = Users.query.filter_by(is_deleted=1, role="user").count()
    updatedUsers = Users.query.filter(
        Users.updated_at.isnot(None)).filter(Users.role == "user").filter(Users.is_deleted == 0).count()

    return jsonify({
        "totalUsers": totalUser,
        "distinctRoles": distinctRole,
        "deletedUsers": deletedUsers,
        "updatedUsers": updatedUsers
    })


import random
import heapq
import datetime
import networkx as nx
import math
import argparse
import matplotlib.pyplot as plt
import time
import pickle
import numpy as np
import operator

save_dir = '../datasets/Flickr/'
def featureUniform(dimension, scale):
	vector = np.array([random.random() for i in range(dimension)])
	l2_norm = np.linalg.norm(vector, ord =2)

	vector = vector/l2_norm

	gau = np.random.normal(0.5, 0.5, 1)[0]
	while gau < 0 or gau > 1:
		gau = np.random.normal(0.5, 0.5, 1)[0]

	vector = vector / scale * gau * 1.5

	return vector

dimension = 4
nodeDic = {}
edgeDic = {}
degree = []
G = pickle.load(open(save_dir+'Small_Final_SubG.G', 'rb'))
for u in G.nodes():
	s = len(G.edges(u))
	nodeDic[u] = [featureUniform(dimension, 1), featureUniform(dimension, s)]
for u in G.nodes():
	d = 0
	for v in G[u]:
		prob = np.dot(nodeDic[u][1], nodeDic[v][0]) * 4
		if prob > 1:
			prob = 1
		if prob < 0:
			prob = 0
		edgeDic[(u,v)] = prob
		d += prob
	degree.append(d)
pickle.dump(nodeDic, open(save_dir+'Small_nodeFeatures.dic', "wb" ))
pickle.dump(edgeDic, open(save_dir+'Probability.dic', "wb" ))

plt.hist(degree)
plt.show()


Q = 3
V = 2
M = 120.45
a = 'D'
b = 'R'
soma =0

nome = input("Qual o seu nome: ")
num_leiloes = int(input("Quantos leilões já participou antes: "))

if num_leiloes>=0:
    num_lances = int(input("Quantos lances você já venceu: "))

    if num_lances>=V:
        for i in range(2):
            print(f"Lance vencedor {i+1}: ",end = '')
            lance = float(input())
            soma += lance

        if ((soma/num_lances) >= M) or (num_leiloes>=Q) or (nome[0] == a) or (nome[0] == b):
            print("Parabéns! Você pode se inscrever.")

        else:
            print("Infelizmente, você não poderá participar nesse ano.")

    elif (num_leiloes>=Q):
        print("Parabéns! Você pode se inscrever.")

    elif (nome[0] == a) or (nome[0] == b):
            print("Parabéns! Você pode se inscrever.")

    elif num_lances<V:
        print("Infelizmente, você não poderá participar nesse ano.")

else:
    print("Infelizmente, você não poderá participar nesse ano.")


#날짜/시간과 관련된 기능 가져오기
import datetime

#현재 날짜/시간 구하기
now = datetime.datetime.now()

#오전 구분
if now.hour < 12 :
    print("현재 시각은 {}시로 오전입니다.".format(now.hour))

#오후 구분
if now.hour >=12 :
    print("현재 시각은 {}시로 오후입니다.".format(now.hour))


# number of "virtual" elements
numElements=14

# number of samples from ADC
numSamples=320

# FFT Size for ADC to IQ
NFFT = 2048

# FFT Size for Range-Angle
NFFT_ANGLE = 128

# (m) 2.5/2 inch phase center spacing
delta_x = 2.5*(1/12.)*0.3048

# (Hz) LFM start frequency
fStart = 2400e6

# (Hz) LFM stop frequency
fStop = 2480e6

# (Hz) carrier frequency
fc = (fStart + fStop)/2

# (Hz) transmit bandwidth
BW = fStop - fStart

# (m) range resolution
delta_r = 3e8 / (2*BW)


import time

import tensorflow as tf

def training_routine_SimpleRNN(model, loss, l_rate, epochs, input_tr, target_tr, feat):
    """
    Training routine to update weights of SimpleRNN through gradient descent.

    Args:
      - model: model to train;
      - loss: type of loss function;
      - l_rate: learning rate;
      - epochs: n. of epochs of training;
      - input_tr: training dataset;
      - target_tr: target values for training;
      - feat: name of feature to train; either "nodes" or "edges".
    """
    optimizer = tf.optimizers.Adam(learning_rate=l_rate)
    for i in range(epochs):
        start = time.time()
        with tf.GradientTape() as tape:
            output_tr = model(input_tr)
            loss_tr = loss(target_tr, output_tr)
        params = model.trainable_weights()
        grads = tape.gradient(loss_tr, params)
        optimizer.apply_gradients(list(zip(grads, params)))
        end = time.time() - start
        if i%10 == 0:
            print(f"Epoch {i} :\n"
              f"MSE {feat} : {loss_tr:.10f}\n"
              f"time taken: {end:.2f} s"
              )

def training_routine_RecGraphNet(model, loss, l_rate_n, l_rate_e,
                        epochs_n, epochs_e, input_tr, target_tr):
    """
    Training routine to update weights of RecGraphNetwork through gradient descent.

    Args:
      - model: model to train;
      - loss: type of loss function;
      - l_rate_n: learning rate for nodes;
      - l_rate_e: learning rate for edges;
      - epochs_n: n. of epochs of training for nodes;
      - epochs_e: n. of epochs of training for edges;
      - input_tr: training dataset;
      - target_tr: target values for training.
    """

    optimizer_nodes = tf.optimizers.Adam(learning_rate=l_rate_n)
    optimizer_edges = tf.optimizers.Adam(learning_rate=l_rate_e)

    for i in range(max((epochs_n, epochs_e))):
        start = time.time()
        with tf.GradientTape() as tape:
            output_tr = model(input_tr)
            loss_nodes_tr = loss(target_tr[0].nodes, output_tr.nodes)
        params_nodes = model.trainable_weights_nodes
        grads_nodes = tape.gradient(loss_nodes_tr, params_nodes)
        optimizer_nodes.apply_gradients(list(zip(grads_nodes, params_nodes)))

        with tf.GradientTape() as tape:
            output_tr = model(input_tr)
            loss_edges_tr = loss(target_tr[0].edges, output_tr.edges)
        params_edges = model.trainable_weights_edges
        grads_edges = tape.gradient(loss_edges_tr, params_edges)
        optimizer_edges.apply_gradients(list(zip(grads_edges, params_edges)))

        end = time.time() - start
        print(f"Epoch {i} :\n"
              f"MSE nodes : {loss_nodes_tr:.10f}\n"
              f"MSE edges : {loss_edges_tr:.10f}\n"
              f"time taken: {end:.0f} s"
              )


#simplification of a fraction
def simplify(n):
    for i in range(len(n)):
        if n[i] == '/':
            numer = int(n[:i])
            denom = int(n[i+1:])
    if numer > denom:
        if numer % denom == 0:
            return str(int(numer/denom))
        else:
            whole = numer//denom
            numer = numer-(whole*denom)
            largest = denom
    else:
        whole = "Nothing"
        largest = numer
    for divisor in range(largest+1, 0, -1):
        if denom % divisor == 0 and numer % divisor == 0 and whole == "Nothing":
            numer = int(numer/divisor)
            denom = int(denom/divisor)
            result = str(numer) + '/' + str(denom)
            return result
        if denom % divisor == 0 and numer % divisor == 0:
            numer = int(numer/divisor)
            denom = int(denom/divisor)
            result = str(numer) + '/' + str(denom)
            return str(whole) + '/' + result

# print(simplify("4/6"))
# print(simplify("10/11"))
# print(simplify("100/400"))
# print(simplify("8/4"))
# print(simplify("800/300"))


import csv

from django.core.management.base import BaseCommand
from recipes.models import Ingredient

class Command(BaseCommand):
    DATA = {
        Ingredient: "ingredients.csv",
    }

    def add_arguments(self, parser):
        parser.add_argument("--data_directory", type=str)

    def handle(self, *args, **options):
        dirname = options["data_directory"] or './data/'
        for model, filename in self.DATA.items():
            with open(
                f"{dirname}/{filename}",
                newline="",
                encoding="utf-8"
            ) as csvfile:
                reader = csv.reader(csvfile, delimiter=",")
                for row in reader:
                    model.objects.update_or_create(
                        name=row[0],
                        measurement_unit=row[1]
                    )
            print(f"{filename} successfully added to DB")
        print("DB successfully filled")


# client2.py
import socket
import stun

server = 'stun.l.google.com', 19302
client_port = 8001
client_addr = stun.get_ip_info()[0]

s = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((client_addr, client_port))

nat_type, _, host, port = stun.get_ip_info(s, server)
print(f'NAT Type: {nat_type}, Public IP: {host}, Public Port: {port}')

s.settimeout(10)
while True:
    try:
        data, remote_addr = s.recvfrom(1024)
        print(f'Received from {remote_addr}: {data.decode()}')
        s.sendto(f'hello from {client_addr}:{client_port}'.encode(), remote_addr)
    except socket.timeout:
        break
s.close()


# This script is used to submit jobs to compute Pk from different realizations/cosmologies
import numpy as np
import sys,os

################################## INPUT #############################################
step    = 500   #number of realizations each cpu will do
offset  = 0    #the count will start from offset
######################################################################################

# do a loop over the different cosmologies
for folder in ['w_p/', 'w_m/']:
#['Om_p/', 'Ob_p/', 'Ob2_p/', 'h_p/', 'ns_p/', 's8_p/',
#'Om_m/', 'Ob_m/', 'Ob2_m/', 'h_m/', 'ns_m/', 's8_m/',
#'Mnu_p/', 'Mnu_pp/', 'Mnu_ppp/',
#'w_p/', 'w_m/',
#'fiducial_ZA/', 'fiducial/',
#'fiducial_LR/', 'fiducial_HR/',
#'latin_hypercube/']:

    # do a loop over the different smoothing scales
    for smoothing in [5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0]:

        # do a loop over the different redshifts
        for snapnum in [0,1,2,3,4]:

            if   folder=='fiducial/':         nodes = int(15000/step)
            elif folder=='latin_hypercube/':  nodes = int(2000/step)
            elif folder=='fiducial_HR/':      nodes = int(100/step)
            elif folder=='fiducial_LR/':      nodes = int(1000/step)
            else:                             nodes = int(500/step)

            # do a loop over the different realizations
            for i in range(nodes):

                a = """#!/bin/bash
#SBATCH -J pdf
#SBATCH --exclusive
#SBATCH -t 1-00:00
#SBATCH --nodes=1
#####SBATCH --ntasks-per-node=16
#SBATCH --ntasks-per-node=48
#SBATCH --partition=general
#SBATCH --export=ALL

source ~/Pylians3

srun -n 20 --mpi=pmi2 python3 pdf_matter.py %d %d %s %d %s\n
                """%(i*step+offset, (i+1)*step+offset, folder, snapnum, smoothing)
                #srun -n 2 --mpi=pmi2 python pdf_matter_LH_high_resolution.py %d %d %s %d\n
                #srun -n 35 --mpi=pmi2 python variance_pdf.py %d %d %s %d\n
                #srun -n 35 --mpi=pmi2 python pdf_matter.py %d %d %s %d\n
                #srun -n 35 --mpi=pmi2 python Pk_halos.py %d %d %s %d\n

                # create the script.sh file, execute it and remove it
                f = open('script.sh','w');  f.write(a);  f.close()
                os.system('sbatch script.sh');  os.system('rm script.sh')


import re

class Md2html:
    def __init__(self, file):
        self.file = file
        with open(self.file, 'r') as file:
            self.content = file.read()
        self.convert_content()

    def convert_content(self):
        self.content = list_conversion(self.content)

        lines = self.content.splitlines()
        self.content = ''
        for line in lines:
            self.content += line_conversion(line)

def list_conversion(text):
    #convert text to
 html tag

    text = text.splitlines()
    result = ''
    il = 0
    for line in text:
        res = re.match('\s*' + r'(\* |\+ |- )', line)
        if res:
            if il+2 == res.span()[1]:
                result += '
' + '\n'
                result += line.replace(res.group(),'
 ', 1) + '
' + '\n'
                il += 2
            elif il > res.span()[1]:
                result += '
' + '\n'
                result += line.replace(res.group(),'
 ', 1) + '
' + '\n'
                il -= 2
            else:
                result += line.replace(res.group(),'
 ', 1) + '
' + '\n'
        else:
            if il > 0:
                for i in range(0, il, 2): result += '
' + '\n'
                result += line + '\n'
                il = 0
            else:
                result += line + '\n'
    return result

def line_conversion(line):
    # convert text line to html

    line = heading_conversion(line)
    line = link_conversion(line)
    line = text_conversion(line)
    return line

def heading_conversion(line):
    #convert to <h> html tag

    res = re.match('#{1,6} ', line)
    if res :
        tag = 'h' + str(res.span(0)[1] - 1)
        return line.replace(res.group(), f'<{tag}> ', 1) + f' </{tag}> '
    else:
        return line

def link_conversion(line):
    #convert to  html tag

    res = re.search('\[.*?\]\(.*?\)', line)
    while res :
        href = re.search('\(.*?\)', line)
        anchor = re.search('\[.*?\]', line)
        line = line.replace(res.group(0), f' {anchor.group(0)[1:-1]} ', 1)
        res = re.search('\[.*?\]\(.*?\)', line)
    return line

def text_conversion(line):
    #convert to  and  html tag

    res = re.search('(\*\*|__)[^\*].*?(\*\*|__)', line)
    while res :
        line =  line.replace(res.group(0), f' {res.group(0)[2:-2]} ', 1)
        res = re.search('(\*\*|__)[^\*].*?(\*\*|__)', line)

    res = re.search(' (\*|_)[^\*].*?(\*|_) ', line)
    while res :
        line =  line.replace(res.group(0), f' {res.group(0)[2:-2]} ', 1)
        res = re.search(' (\*|_)[^\*].*?(\*|_) ', line)
    if not line.startswith('<'): line = f'
 {line}
'
    return line


import arcpy
import os
import csv

def readSDE(path):
    arcpy.env.workspace = path
    csvfile.writerow(["The current file Geodatabase is " + path])

    featureclass = arcpy.ListFeatureClasses()
    print(featureclass)
    raster = arcpy.ListRasters()
    print(raster)
    tables = arcpy.ListTables()
    print(tables)

    csvfile.writerow([""])
    csvfile.writerow(["The Feature Classes in " + path + " are listed below"])
    for fc in featureclass:
        desc = arcpy.Describe(fc)
        try:
            csvfile.writerow(
                [desc.name, "Feature Class", arcpy.env.workspace + "\\" + fc, desc.featureType + " " + desc.shapeType,
                 desc.spatialreference.name, arcpy.GetCount_management(fc)])
        except:
            print(fc + " did not seem to be able to be opened")
            continue

    csvfile.writerow([""])
    csvfile.writerow(["The Rasters in " + path + " are listed below"])
    for ras in raster:

        try:
            desc = arcpy.Describe(ras)
            csvfile.writerow([desc.name, desc.format, arcpy.env.workspace + "\\" + ras, desc.compressionType,
                              desc.spatialreference.name])
        except:
            print(ras + " did not seem to be able to be opened")
            continue

    csvfile.writerow([""])
    csvfile.writerow(["The tables in " + path + " are listed below"])
    for table in tables:
        desc = arcpy.Describe(table)
        try:
            csvfile.writerow([desc.name, "Table"])
        except:
            print (table + " Did not seem to be able to be opened")

    csvfile.writerow([""])
    csvfile.writerow([""])

file = open("C:\\Users\\hstgeorge\\Desktop\\testsde.csv",'w')
csvfile = csv.writer(file,csv.excel,lineterminator = '\n')

startpath = r'C:\Users\hstgeorge\AppData\Roaming\ESRI\Desktop10.6\ArcCatalog\Connection to LEA-304752 (2).sde'
arcpy.env.workspace = startpath

file.flush()
readSDE(startpath)
file.close()


"""
LanguageParser is a rudimentary natural language parser for forming SQL-like queries
for use against Pandas dataframe objects.

The language parser takes input as such that:

`my column value is greater than another column value and my column is not equal yet another column`

This would then be parsed and become:

`my_column > another_column & my_column != yet_another_column`
"""
import re
import time
from collections import namedtuple
from itertools import chain
from itertools import combinations
from itertools import permutations
import pandas as pd
import numpy as np

from pyccata.core.decorators import accepts
from pyccata.core.threading import Threadable
from pyupset.resources import ExtractedData

class _Query(object):
    """
    Private class - does the actual parsing
    """
    # pylint: disable=too-few-public-methods
    # Struct type object require only a few methods

    _original = None
    _real = None
    _fields = None

    @accepts(str, list)
    def __init__(self, query, fields):
        """
        Initialise a new _Query item

        @param query string
        @param fields list
        """
        self._original = query
        self._fields = fields
        self._real = self.parse(query)

    @accepts(str)
    def parse(self, query):
        """
        Parse the provided query into an SQL-like query

        @param query string

        This method is expensive to call as it uses a number of regex-matches.
        """
        query = re.subn(r' and ', ' & ', query, flags=re.IGNORECASE)[0]
        query = re.subn(r' or ', ' | ', query, flags=re.IGNORECASE)[0]
        for operator, operation_list in LanguageParser.OPERATIONS:
            for operate in operation_list:
                query = re.subn(operate, operator, query, re.IGNORECASE)[0]

        for field in self._fields:
            query = re.subn(field.replace('_', ' '), field, query, flags=re.IGNORECASE)[0]

        return query

    def __equals__(self, what):
        """
        Is the current item the same as the comparison item?

        Compares string input against the queries stored
        """
        return self._original == what or self._real == what

    def __str__(self):
        """
        String representation of the final query
        """
        return self._real

class _Operator(object):
    """
    Private class for handling operation replacement values
    """
    # pylint: disable=too-few-public-methods

    def __init__(self, operation=None, replacement=None, replaced_in_query=False):
        self.operation = operation
        self.replacement = replacement
        self.replaced_in_query = replaced_in_query

class ExtractedResults(ExtractedData):
    """
    Override class for ExtractedData to allow for extra `query` parameter
    """
    _lock = False
    def __init__(self):
        super().__init__(None, None, None, None)
        self._options = {
            '_in_sets': None,
            '_out_sets': None,
            '_results': None,
            '_filter_config': None,
            '_query': None,
            '_logic': None
        }

    def append_results(self, results):
        """
        Sleep for THREAD_SLEEP then append results
        """
        while ExtractedResults._lock:
            time.sleep(Threadable.THREAD_SLEEP)
        ExtractedResults._lock = True
        # pylint: disable=access-member-before-definition,attribute-defined-outside-init
        # self.results is identified on the parent __getattr__ method
        if self.results is None:
            self.results = pd.DataFrame(results, copy=True).drop_duplicates()
        else:
            self._options['_results'] = self.results.append(results, ignore_index=True).drop_duplicates()
        ExtractedResults._lock = False

    def flatten_results(self, unique_keys):
        """ Takes a multi-frame dataset and flattens it into a single dataframe """
        if not isinstance(unique_keys, list):
            unique_keys = [unique_keys]
        dataframe = None
        for frame in self.in_sets:
            columns = [column for column in self.results.columns if column.endswith(frame)]

            interim = pd.DataFrame(self.results[unique_keys + columns], copy=True)
            interim.columns = unique_keys + [column[:-len('_{0}'.format(frame))] for column in columns]

            if dataframe is None:
                dataframe = pd.DataFrame(interim, copy=True).reset_index(drop=True)
            else:
                dataframe = dataframe.append(interim, ignore_index=True)
        return dataframe.drop_duplicates()

class LanguageParser(object):
    """
    Parse human readable strings into SQL-like queries
    """
    # pylint: disable=too-few-public-methods
    # Not many methods required here
    OPERATIONS = [
        (' >= ', [' is greater than or equal to ', ' is not less than ', ' not less than ', ' >= ']),
        (' <= ', [' is less than or equal to ', ' is not greater than ', ' not greater than ', ' <= ']),
        (' != ', [' is not equal to ', ' not equals ', ' != ']),
        (' == ', [' is equal to ', ' equals ', 'equal', ' = ', ' <> ', ' == ']),
        (' > ', [' is greater than ', ' greater than ', ' > ']),
        (' < ', [' is less than ', ' less than ', ' < '])
    ]

    INVERSIONS = [
        ('>=', '<'), ('<=', '>'),
        ('>', '<'), ('<', '>'),
        ('==', '!='), ('!=', '==')
    ]

    LIMIT_DEFAULT = 200

    _queries = []

    @accepts(str, list)
    def parse(self, query, fields):
        """
        Returns a parsed query

        Loop over all stored queries and return a previously parsed version of
        the query or a new one if the query has not been previously parsed.

        @param query string
        @param fields list
        """
        return str(self[query]) if query in self else self.append(_Query(query, fields))

    def __contains__(self, what):
        for item in self._queries:
            if item == what:
                return True
        return False

    def __getitem__(self, key):
        if isinstance(key, int):
            return self._queries[key]

        for item in self._queries:
            if key == item:
                return item
        raise IndexError('Invalid index {0} for LanguageParser'.format(key))

    def combination(self, query, replacements, fields):
        """
        Loops over the replacements list and creates an instance of the query for each item

        @param query string
        @param replacements list
        @param fields list

        @return list
        """
        queries = []
        for left_name in replacements:
            sections = []
            for right_name in replacements:
                if left_name != right_name:
                    copy = query.replace('_x', '_{0}'.format(left_name))
                    copy = copy.replace('_y', '_{0}'.format(right_name))
                    sections.append(str(self[copy]) if copy in self else self.append(_Query(copy, fields)))
            queries.append('(' + ') | ('.join(sections) + ')')

        return queries

    def combinatorics(self, inclusive_query, exclusive_query, names, limits):
        """
        Loops over the replacements list and creates an instance query for each item

        :param string inclusive_query
        :param string exclusive_query
        :param list   limits
        :param list   names

        Similar to :meth:`LanguageParser.combination`, this method will loop over each item in replacements and create
        a query for each entry.

        The difference here is that for each dataset, an inverse entry will also be written.

        This is such that, for the dataframes::

            dataframe_one
            dataframe_two
            dataframe_three
            dataframe_four

        combinations would be written such that::

            (dataframe_one)
            (dataframe_two)
            (dataframe_three)
            (dataframe_four)
            (dataframe_one, dataframe_two)
            (dataframe_one, dataframe_three)
            (dataframe_one, dataframe_four)
            ...
            (dataframe_one, dataframe_two, dataframe_three, dataframe_four)

        An inverse set would then be provided in the form that "A not in B" giving::

            (dataframe_two, dataframe_three, dataframe_four),
            ...
            (dataframe_three, dataframe_four)
            (dataframe_two, dataframe_four)
            ...

        The query is then re-written such that:

            A == B & A != [C | D] & B != [C | D]

        For this method, it is important that the query does not include hard ranges and in fact value_range is instead
        provided. value_range is a tuple such that ``(value_lower, value_upper)``

        Example::

            query = 'start_x >= (start_y - value_lower) and end_x <= (end_y + value_upper)'

        would be re-written as:

            (dataframe_one, dataframe_two)
            values = (200, 200)
            query = '(start_dataframe_one >= (start_dataframe_two - values[0]) OR (start_dataframe_two >= \
                         (start_dataframe_one - values[0]))) AND \
                         (end_dataframe_one <= (end_end_dataframe_two + values[1]) OR \
                         (end_dataframe_two <= (end_datafrane_one + values[1])))'

        This query is fairly straightforward and the example will bring back all instances where start and end overlap
        by +- 200

        The complexity with pandas arises here in that on a full cartesian product of n-sets, when building a
        combination graph of the data such as those provided by `py-upset`, the data for the combination of
        `dataframe_one` and `dataframe_two` will include data from other set combinations which include one or more of
        these datasets.

        Because pandas does not provide the mechanism to carry out set operations on dataframes, it would be
        incredibly inefficient to attempt to subtract different combination results from each other. Instead it is
        more efficient to limit the amount of data returned for each combination to contain information about other
        sets which explicitly fall outside of the acceptance criteria.

        Therefore in the example, for dataframe_one and dataframe_two, we explicitly include sets which "overlap"
        whilst for `dataframe_three` and `dataframe_four` we exclude these overlaps by explicitly including
        non-overlapping values, then discarding the values within these columns.

        This makes the query considerably more complicated::

            inclusive_query = '(start_dataframe_one >= (start_dataframe_two - 200) OR \
                   (start_dataframe_two >= (start_dataframe_one - 200))) AND \
                   (end_dataframe_one <= (end_end_dataframe_two + 200) OR \
                   (end_dataframe_two <= (end_datafrane_one + 200)))'

            exclusive_queries = [
                '(start_dataframe_one < (start_dataframe_three - 200) OR \
                 (start_dataframe_three < (start_dataframe_one - 200))) AND \
                 (end_dataframe_one > (end_end_dataframe_three + 200) OR \
                 (end_dataframe_three > (end_datafrane_one + 200)))',

                '(start_dataframe_one < (start_dataframe_four - 200) OR \
                 (start_dataframe_four < (start_dataframe_one - 200))) AND \
                 (end_dataframe_one > (end_end_dataframe_four + 200) OR \
                 (end_dataframe_four > (end_datafrane_one + 200)))',

                '(start_dataframe_two < (start_dataframe_three - 200) OR \
                 (start_dataframe_three < (start_dataframe_two - 200))) AND \
                 (end_dataframe_two > (end_end_dataframe_three + 200) OR \
                 (end_dataframe_three > (end_datafrane_two + 200)))',

                '(start_dataframe_two < (start_dataframe_four - 200) OR \
                 (start_dataframe_four < (start_dataframe_two - 200))) AND \
                 (end_dataframe_two > (end_end_dataframe_four + 200) OR \
                 (end_dataframe_four > (end_datafrane_two + 200)))',

                '(start_dataframe_three < (start_dataframe_four - 200) OR \
                 (start_dataframe_four < (start_dataframe_three - 200))) AND \
                 (end_dataframe_three > (end_end_dataframe_four + 200) OR \
                 (end_dataframe_four > (end_datafrane_three + 200)))'
            ]

            query = '(' + inclusive_query + ') AND ~(' + ' AND '.join(exclusive_queries) + ')'

        Combinations containing a single dataframe as the inclusion are excluded from the results when calculating
        combinations in this manner as the values they would contain count as non-overlapping data.
        """
        # pylint: disable=too-many-locals
        # This method is prime for refactoring, however it's complexity means
        # that for now, it's not straight forward. We live with having overcrowding.

        limits = limits._asdict() if limits is not None else {}
        name_combinations = chain.from_iterable(
            combinations(names, i) for i in np.arange(1, len(names) + 1)
        )
        sets = [tuple(frozenset(inset)) for inset in name_combinations]
        queries = []
        query = namedtuple('Query', 'inclusive exclusive')

        for in_sets in sets:
            out_sets = list(set(names) - set(in_sets))

            inclusive_queries = []
            exclusive_queries = []

            start_frame_permutations = [p for p in permutations(list(in_sets))]
            end_frame_permutations = [p for p in permutations(list(out_sets)) if p]

            for current_permutation in start_frame_permutations:
                inclusive_queries.append(
                    self._inclusive_query(inclusive_query, current_permutation, limits)
                )

                # pylint: disable=expression-not-assigned
                # List comprehension result is not required for any reason.
                [
                    exclusive_queries.append(
                        self._inclusive_query(exclusive_query, permutation, limits, left_name=current_permutation[0])
                    )
                    for permutation in end_frame_permutations if end_frame_permutations[0]
                ]

            # pylint: disable=attribute-defined-outside-init
            # Attributes on the ExtractedResults object are initialised through
            # __getattr__ and __setattr methods on the parent `pyupset.resources.ExtractedData` object
            extracted = ExtractedResults()
            extracted.in_sets = in_sets
            extracted.out_sets = out_sets
            extracted.query = query(
                inclusive='(' + ' and '.join(inclusive_queries) + ')',
                exclusive=(
                    '~(' + ' and '.join(exclusive_queries) + ')'
                    if exclusive_queries and exclusive_queries[0] != ''
                    else None
                )
            )
            queries.append(extracted)
        return queries

    @staticmethod
    def _inclusive_query(query, sets, limits, left_name=None):
        """
        Write out and group queries
        """
        queries = []
        sections = []
        if query == '' or query is None:
            return ''

        left_name = sets[0] if left_name is None  else left_name

        left_limit = [
            limit
            for limit in limits
            if left_name.lower().startswith(limit.lower()) or left_name.lower().endswith(limit.lower())
        ][0]

        left_limit = 250
        for right_name in sets:
            if left_name != right_name:
                right_limit = [
                    limit
                    for limit in limits
                    if right_name.lower().startswith(limit.lower()) or right_name.lower().endswith(limit.lower())
                ][0]
                right_limit = left_limit

                copy = query.replace('_x', '_{0}'.format(left_name))
                copy = copy.replace('_y', '_{0}'.format(right_name))
                reversed_copy = query.replace('_x', '_{0}'.format(right_name))
                reversed_copy = reversed_copy.replace('_y', '_{0}'.format(left_name))

                new_query = '(' + copy + ' or ' + reversed_copy + ')'
                new_query = new_query.replace('{left_limit}', str(left_limit))
                new_query = new_query.replace('{right_limit}', str(right_limit))
                sections.append(new_query)

        queries.append('(' + ' and '.join(sections) + ')')
        return '(' + ' and '.join(queries) + ')'

    @accepts(_Query)
    def append(self, query):
        """
        Append a new query to the list and return a string representation of it.

        @param query _Query

        @return string
        """
        self._queries.append(query)
        return str(self._queries[-1])


from config.config import ALPHABET, Wiring
from config.pygame_config import (
    COMPONENT_BORDER_RADIUS,
    COMPONENT_LETTERS_COLOR,
    COMPONENT_BORDER_COLOR,
    COMPONENT_BORDER_WIDTH,
)
import pygame

class Reflector:
    def __init__(self, wiring: Wiring, name: str) -> None:
        self.left = ALPHABET
        self.right = wiring.wiring
        self.name = name

    def reflect(self, signal: int) -> int:
        letter = self.right[signal]
        return self.left.find(letter)

    def draw(self, screen: pygame.surface.Surface, x: int, y: int, w: int, h: int, font: pygame.font.Font):
        r = pygame.Rect(x, y, w, h)
        pygame.draw.rect(screen, COMPONENT_BORDER_COLOR, r, width=COMPONENT_BORDER_WIDTH, border_radius=COMPONENT_BORDER_RADIUS)
        for i in range(26):
            letter = font.render(self.left[i], True, COMPONENT_LETTERS_COLOR)
            text_box = letter.get_rect(center=(x + w / 4, y + (i + 1) * h / 27))

            screen.blit(letter, text_box)

            letter = font.render(self.right[i], True, COMPONENT_LETTERS_COLOR)
            text_box = letter.get_rect(center=(x + w * 3 / 4, y + (i + 1) * h / 27))
            screen.blit(letter, text_box)


from __future__ import absolute_import, division, print_function

import os
import skimage.transform
import numpy as np
import PIL.Image as pil

from .mono_dataset import MonoDataset

class NYUv2Dataset(MonoDataset):
	def __init__(self, *args, **kwargs):
		super(NYUv2Dataset, self).__init__(*args, **kwargs)

		self.K = np.array([[0.8107, 0, 0.5087, 0],
                           [0, 1.0822, 0.5286, 0],
                           [0, 0, 1, 0],
                           [0, 0, 0, 1]], dtype=np.float32)

		self.full_res_shape = (640, 480)

	def get_image_path(self, folder, frame_index, side):
		f_str = "img_{}{}".format(frame_index, self.img_ext)
		image_path = os.path.join(
			self.data_path,
			folder,
			f_str)
		return image_path

	def get_depth(self, folder, frame_index, side, do_flip):
		f_str = "gt_{}{}".format(frame_index, self.img_ext)
		depth_path = os.path.join(
			self.data_path,
			"depths/",
			f_str)

		depth_gt = pil.open(depth_path)
		depth_gt = depth_gt.resize(self.full_res_shape, pil.NEAREST)
		depth_gt = np.array(depth_gt).astype(np.float32) / 256

		if do_flip:
		    depth_gt = np.fliplr(depth_gt)

		return depth_gt

	def get_color(self, folder, frame_index, side, do_flip):
		color = self.loader(self.get_image_path(folder, frame_index, side))

		if do_flip:
			color = color.transpose(pil.FLIP_LEFT_RIGHT)

		return color

	def check_depth(self):
		line = self.filenames[0].split()
		scene_name = line[0]
		frame_index = int(line[1])

		depth_filename = os.path.join(
			self.data_path,
			"depths/",
			"gt_{}.jpg".format(int(frame_index)))


import torch

import numpy as np
import torch.nn as nn

from code.config import Hyper

class SampleDropout:
    def __init__(self, hyper: Hyper):
        self.p = hyper.prob
        self.dropout_ratio = nn.Embedding(hyper.n, 1)
        self.dropout_ratio = self.dropout_ratio.cuda(hyper.gpu)
        self._init_dropout()

    def _init_dropout(self):
        np_prob = np.array(self.p)
        np_prob = np_prob.reshape(-1, 1)
        weight = torch.from_numpy(np_prob)
        self.dropout_ratio.weight.data.copy_(weight)
        self.dropout_ratio.weight.requires_grad = False

    def __call__(self, x, label):
        ratio, mask = self._generate_mask(x, label)
        x *= mask

        amplification = torch.reciprocal(1 -  ratio)
        amplification = amplification.detach()
        x *= amplification
        return x

    def _generate_mask(self, input, label):
        ratio = self.dropout_ratio(label)

        mask = torch.rand_like(input)
        mask = mask > ratio
        mask = mask.float()
        mask.requires_grad = False
        return ratio, mask


class Solution:
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        left = self.__find_lower_bound(nums, target)
        if left == -1:
            return [-1, -1]

        right = self.__find_up_bound(nums, target)
        return [left, right]

    def __find_lower_bound(self, nums, target):
        # 找到大于等于 target 的第 1 个元素的索引
        size = len(nums)
        if size == 0:
            return -1
        l = 0
        r = size - 1
        while l < r:
            mid = l + (r - l) // 2
            if nums[mid] < target:
                l = mid + 1
            else:
                assert nums[mid] >= target
                r = mid
        # 最后还要单独判断一下
        if nums[l] != target:
            return -1
        return l

    def __find_up_bound(self, nums, target):
        # 找到大于等于 target 的最后 1 个元素的索引
        size = len(nums)
        if size == 0:
            return -1
        l = 0
        r = size - 1
        while l < r:
            mid = l + (r - l + 1) // 2
            if nums[mid] > target:
                r = mid - 1
            else:
                assert nums[mid] <= target
                l = mid
        # 最后还要单独判断一下
        if nums[l] != target:
            return -1
        return l

if __name__ == '__main__':
    solution = Solution()
    nums = [5, 7, 7, 8, 8, 10]
    target = 8
    result = solution.searchRange(nums, target)
    print(result)


import numpy as np
import math
#df = np.array([1.1,.85,.8,.75],[0.5,0.7,0.6,1.5],[0.4,0.8,0.3,1.9],[0.6,0.7,0.8,2.0],[0.4,0.6,0.5,1.7],[0.4,0.8,0.6,1.5])
#Average_T = np.average(times)
P_rating = 1.1
Normal_T = lambda A_T,P_r: A_T*P_r
Standard_T = lambda N_T,A_f: N_T/(1-A_f)
Requires_Sample_Size = lambda z,s,x_bar,h: ((z*s)/(h*x_bar))**2
def S(xlst):
    sm = []
    x_bar = np.average(xlst)
    for x in xlst:
        sm.append((x-x_bar)**2)
    return x_bar,sum(sm)
Bob = lambda Obs,TObs: (Obs/TObs)*100
Ss = lambda z,p,h: ((z**2)*p*(1-p))/(h**2)
#print(Average_T)
#print(Normal_T(Average_T,P_rating))
#print(Normal_T(12,1.1))
#print(Standard_T(Normal_T(12,1.1),0.18))
P_r_df = [1.25,1.15,0.95,0.90]
df = [[34,41,34,43,40],[13,11,15,13],[3,3,4,6,3],[16,17,22,16]]
df_whl = df[1]+df[2]+df[0]+df[3]
allowance = 0.18
#print(dft[0][2:])
average_df = [round(np.average(x), ndigits=2) for x in df]
normal_df = [round(Normal_T(average_df[x],P_r_df[x]),ndigits=2) for x in range(0,len(P_r_df))]
s,x_b = S(df_whl)
#print(average_df)
#print(normal_df)
#print(Standard_T(sum(normal_df),.18))
#print(df_whl)
#print(Requires_Sample_Size(1.96,x_b,18.56,.05))
av = 384/(160-(160*.2))
norm = Normal_T((av),.8)
stand = Standard_T(norm,.08)
print(Ss(1.96,))


# coding: utf-8
# author = popwin

def bubble(x,low,high):
    """冒泡算法主体，返回最后一次比较的位置
       避免重复比较已排序部分
    """
    last = low
    while(low<high):
        if x[low]>x[low+1]:
            last = low + 1
            temp = x[low+1]
            x[low+1] = x[low]
            x[low] = temp
        low += 1
    return last

def BubbleSort(x,low,hi):
    """无论如何，冒泡算法的最坏复杂度都是O（n2）
    """
    while(low<hi):
        hi=bubble(x,low,hi)


def longeur(list):
    compt=0
    for i in list:
        compt +=1
    return compt

def trie(list = [2,5,12,1,7]):

    taille = longeur(list)

    for i in range(1,taille):

        valeur = list[i]
        j = i-1
        while j >= 0 and valeur < list[j] :
            list[j+1] = list[j]
            j -=1
        list[j+1] = valeur
    return list

def arrondi(list = [22.4, 4.0, 16.22, 9.10, 11.60, 12.22, 14.20, 5.20, 17.50]):

    for index,value in enumerate(list):
        txt =""
        chiffreConvertie = str(value)
        apresVirgule = ""
        indice = 0

        for key,val in enumerate(chiffreConvertie):

            if val =='.':
                indice = key
                continue

            if indice == 0:
                if(apresVirgule !=""):
                    continue
                txt +=str(val)

            if indice + 1 == key:
                apresVirgule = ""
                apresVirgule += val

            indice=0

        if(int(apresVirgule) >= 5 ):
            txt = int(txt)
            list[index] = txt + 1
        else:
            txt = int(txt)
            list[index] = txt

    return trie(list)

print(arrondi())


import numpy as np
import torch

from .base import FactorCollection
from .base import VideoWrapper
from .factor import TensorFactor

class Video(VideoWrapper):
    """ Manages Unrolled Tensor and multiplication with a Full Video """
    def __init__(self,
                 video_shape,
                 device='cuda'):
        """ Allocate required tensors on device

        Parameter:
            video_shape: shape of video
            device: computation device

        """
        super().__init__(video_shape[1], device=device)
        self.mov = TensorFactor(video_shape[0],
                                scratch=False,
                                device=self.device,
                                dtype=torch.float32)

    @property
    def fov(self):
        """ Shape of the field of view in pixels/voxels """
        return self.mov.shape[:-1]

    @property
    def frames(self):
        """ Length of the video in frames """
        return self.mov.shape[-1]

    def _resize(self, num_components):
        """ Resize each factor axis inplace to represent N components """
        return None

    def permute(self, permutation):
        """ Reorder component in factors according to provided permutation """
        return None

    def set(self, h_mov):
        """ Initializes Factors From ndarrays on host

        Parameter:
            h_mov: movie on host

        """
        self.mov.data.copy_(h_mov)

    def forward(self, spatial, temporal, **kwargs):
        """ Computes temporal.scratch = matmul(spatial.data, mov.t())

        Parameter:
            spatial: spatial components
            temporal: temporal components
            **kwargs: optional additional input arguments

        """

        torch.matmul(spatial.data, self.mov.data, out=temporal.scratch)

    def backward(self, temporal, spatial, **kwargs):
        """ Computes spatial.scratch = matmul(temporal.data, mov.t())

        Parameter:
            temporal: temporal components
            spatial: spatial components
            **kwargs: optional additional input arguments

        """
        torch.matmul(temporal.data, self.mov.data.t(), out=spatial.scratch)

class LowRankVideo(VideoWrapper):
    """ Manages Tensors and multiplication with a Low-Rank Factored Video """

    def __init__(self,
                 video_shape,
                 spatial_scratch=False,
                 temporal_scratch=False,
                 device='cuda'):
        """ Allocate required tensors on device

        Parameter:
            video_shape: video matrix shape
            spatial_scratch:
            temporal_scratch:
            device: computation device
        """

        super().__init__(video_shape[1], device=device)
        self.spatial = TensorFactor((self.num_components, video_shape[0]),
                                    scratch=spatial_scratch,
                                    device=self.device,
                                    dtype=torch.float32)
        self.temporal = TensorFactor((self.num_components, video_shape[2]),
                                     scratch=temporal_scratch,
                                     device=self.device,
                                     dtype=torch.float32)

    @property
    def fov(self):
        """ Shape of the field of view in pixels/voxels """
        return self.spatial.shape[1:]

    @property
    def frames(self):
        """ Length of the video in frames """
        return self.temporal.shape[1:]

    def _resize(self, num_components):
        """ Resize each factor axis inplace to represent N components

        Parameter:
            num_components: number of components

        """

        self.spatial.resize_axis_(0, num_components)
        self.temporal.resize_axis_(0, num_components)

    def permute(self, permutation):
        """ Reorder component in factors according to provided permutation

        Parameter:
            permutation:

        """

        self.spatial.permute_(permutation)
        self.temporal.permute_(permutation)

    def set(self, h_spatial, h_temporal):
        """ Initializes Factors From ndarrays on host

        Parameter:
            h_spatial: spatial video component
            h_temporal: temporal video component
        """

        self.spatial.data.copy_(h_spatial)
        self.temporal.data.copy_(h_temporal)

    def forward(self, spatial, temporal, **kwargs):
        """ Computes temporal.scratch = matmul(spatial.data, mov.t())

        Parameter:
            spatial: spatial video components
            temporal: temporal video components
            **kwargs: optional additional input arguments

        """

        if 'intermediate' not in kwargs:
            raise TypeError(
                "Missing 1 required keyword argument: 'intermediate'"
            )
        torch.matmul(self.spatial.data,
                     spatial.data.t(),
                     out=kwargs['intermediate'].data)
        torch.matmul(kwargs['intermediate'].data.t(),
                     self.temporal.data,
                     out=temporal.scratch)

    def backward(self, temporal, spatial, **kwargs):
        """ Computes spatial.scratch = matmul(temporal.data, mov.t())

        Parameter:
            temporal: temporal video components
            spatial: spatial video components
            **kwargs: optional additional input arguments

        """

        if 'intermediate' not in kwargs:
            raise TypeError(
                "Missing 1 required keyword argument: 'intermediate'"
            )
        torch.matmul(self.temporal.data,
                     temporal.data.t(),
                     out=kwargs['intermediate'].data)
        torch.matmul(kwargs['intermediate'].data.t(),
                     self.spatial.data,
                     out=spatial.scratch)

class RegionMetadata(FactorCollection):
    """ Manages Metadata For Each Region In Localized Semi-NMF """

    def __init__(self, max_num_components, region_shape, device='cuda'):
        """ Allocate required tensors on device

        Parameter:
            max_num_components: maximum number of components
            region_shape: region shape
            device: computation device

        """

        super().__init__(max_num_components, device)
        self.support = TensorFactor((max_num_components, region_shape[0]),
                                    device=device,
                                    dtype=torch.uint8)
        self.distance = TensorFactor((max_num_components, region_shape[0]),
                                     device=device,
                                     dtype=torch.float32)
        self.labels = TensorFactor((max_num_components,),
                                   device=device,
                                   dtype=torch.long)

    def _resize(self, num_components):
        """ Resize each factor axis inplace to represent N components

        Parameter:
            num_components: number of components

        """

        self.support.resize_axis_(0, num_components)
        self.distance.resize_axis_(0, num_components)
        self.labels.resize_axis_(0, num_components)

    def permute(self, permutation):
        """ Reorder component in factors according to provided permutation

        Parameter:
            permutation:

        """

        self.support.permute_(permutation)
        self.distance.permute_(permutation)
        self.labels.permute_(permutation)

    def set(self, h_support, h_distance, h_labels):
        """ Initializes Factors From ndarrays on host

        Parameter:
            h_support: the mask of each region
            h_distance: the distance penalty of each region
            h_labels: area code

        Each input parameter comes from LocaNMF.extract_region_metadata fcn
        output.

        """

        self.support.data.copy_(h_support)
        self.distance.data.copy_(h_distance)
        self.labels.data.copy_(h_labels)


# -*- coding: utf-8 -*-

import re
from datetime import timedelta

from pyload.core.utils.convert import to_bytes

from ..base.simple_downloader import SimpleDownloader

class FastshareCz(SimpleDownloader):
    __name__ = "FastshareCz"
    __type__ = "downloader"
    __version__ = "0.45"
    __status__ = "testing"

    __pattern__ = r"https?://(?:www\.)?fastshare\.cz/\d+/.+"
    __config__ = [
        ("enabled", "bool", "Activated", True),
        ("use_premium", "bool", "Use premium account if available", True),
        ("fallback", "bool", "Fallback to free download if premium fails", True),
        ("chk_filesize", "bool", "Check file size", True),
        ("max_wait", "int", "Reconnect if waiting time is greater than minutes", 10),
    ]

    __description__ = """FastShare.cz downloader plugin"""
    __license__ = "GPLv3"
    __authors__ = [
        ("Walter Purcaro", "vuolter@gmail.com"),
        ("GammaC0de", "nitzo2001[AT]yahoo[DOT]com"),
        ("ondrej", "git@ondrej.it"),
    ]

    URL_REPLACEMENTS = [("#.*", "")]

    COOKIES = [("fastshare.cz", "lang", "en")]

    NAME_PATTERN = r'<h2 title="(.+?)" class="section_title'
    SIZE_PATTERN = r' (?P<S>\d+) (?P[\w^_]+)'
    TEMP_OFFLINE_PATTERN = r"[^\w](503\s|[Mm]aint(e|ai)nance|[Tt]emp([.-]|orarily))"
    OFFLINE_PATTERN = r">(The file has been deleted|Requested page not found|This file is no longer available)"

    LINK_FREE_PATTERN = r'form .*target="iframe_dwn" .*action=([^>]+)'
    LINK_PREMIUM_PATTERN = r"(https?://\w+\.fastshare\.cz/download\.php\?id=\d+&)"

    SLOT_ERROR = "> 100% of FREE slots are full"
    CREDIT_ERROR = " credit for "

    def check_errors(self):
        if self.SLOT_ERROR in self.data:
            errmsg = self.info["error"] = self._("No free slots")
            self.retry(12, 60, errmsg)

        if self.CREDIT_ERROR in self.data:
            errmsg = self.info["error"] = self._("Not enough traffic left")
            self.log_warning(errmsg)
            self.restart(premium=False)

        self.info.pop("error", None)

    def handle_free(self, pyfile):
        m = re.search(self.LINK_FREE_PATTERN, self.data)
        if m is None:
            self.error(self._("LINK_FREE_PATTERN not found"))

        self.link = self.fixurl(m.group(1))

    def check_download(self):
        check = self.scan_download(
            {
                "parallel-dl": re.compile(
                    rb"<title>FastShare.cz</title>|


import numpy as np
input = np.array([[0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9,10, 11]
])
# print(len(input))
row, column = input.shape
def xValue(x):
    list = []
    for i in range(row):
        for j in range(column):
            if input[i][j] > 5:
                list.append(input[i][j])
    return list
print(xValue(input))


import tensorflow as tf
import numpy as np
from datetime import datetime
from sys import stdout
import shutil
import os

from data_reader import AsyncReader, ReaderOpts
from transformations import make_transformation_matrix, concat_images
from loss import LossLayer
from models import build_depth_net, build_pose_net
from drawing import display_training_basic
from metrics import compute_metrics

# TODO: Data augmentation

img_height = 192
img_width = 640

kitti_path = '/home/xian/kitti_data'
train_list = os.path.join(os.path.dirname(__file__), 'splits', 'train_files.txt')
val_list = os.path.join(os.path.dirname(__file__), 'splits', 'val_files.txt')
batch_size = 8
nworkers = 6
train_reader_opts = ReaderOpts(kitti_path, train_list, batch_size, img_height, img_width, nworkers)
val_reader_opts = ReaderOpts(kitti_path, val_list, batch_size, img_height, img_width, nworkers)

nepochs = 20

K = np.array([[0.58 * img_width, 0, 0.5 * img_width],
              [0, 1.92 * img_height, 0.5 * img_height],
              [0, 0, 1]], dtype=np.float32)

pretrained_weights_path = '/home/xian/ckpts/resnet18_fully_trained/ckpt'

depth_net = build_depth_net(img_height, img_width, pretrained_weights_path)
pose_net = build_pose_net(img_height, img_width)

trainable_weights = depth_net.trainable_weights
trainable_weights.extend(pose_net.trainable_weights)

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4)

loss_layer = LossLayer(K, img_height, img_width, batch_size)

log_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'logs')
if os.path.exists(log_dir):
    shutil.rmtree(log_dir)
train_summary_writer = tf.summary.create_file_writer(os.path.join(log_dir, 'train'))
val_summary_writer = tf.summary.create_file_writer(os.path.join(log_dir, 'val'))

save_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ckpts')

@tf.function
def compute_and_log_metrics(disp_pred, depth_gt, step_count):
    # disp_pred: (batch_size, height, width, 1)
    # depth_gt: (batch_size, depth_height, depth_width)
    abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 = compute_metrics(disp_pred, depth_gt)
    with train_summary_writer.as_default():
        tf.summary.scalar('abs_rel', abs_rel, step=step_count)
        tf.summary.scalar('sq_rel', sq_rel, step=step_count)
        tf.summary.scalar('rmse', rmse, step=step_count)
        tf.summary.scalar('rmse_log', rmse_log, step=step_count)
        tf.summary.scalar('a1', a1, step=step_count)
        tf.summary.scalar('a2', a2, step=step_count)
        tf.summary.scalar('a3', a3, step=step_count)

@tf.function
def train_step(batch_imgs, step_count):
    # batch_imgs: (batch_size, height, width, 9) Three images concatenated on the channels dimension
    img_before = batch_imgs[:, :, :, :3]
    img_target = batch_imgs[:, :, :, 3:6]
    img_after = batch_imgs[:, :, :, 6:]

    with tf.GradientTape() as tape:
        disps = depth_net(img_target)  # disparities at different scales, in increasing resolution
        # TODO: I can spare one of this concatenations, but for now this is clearer:
        T_before_target = pose_net(concat_images(img_before, img_target))  # (bs, 6)
        T_target_after = pose_net(concat_images(img_target, img_after))  # (bs, 6)
        matrixT_before_target = make_transformation_matrix(T_before_target, False)  # (bs, 4, 4)
        matrixT_after_target = make_transformation_matrix(T_target_after, True)  # (bs, 4, 4)
        loss_value, image_from_before, image_from_after =\
            loss_layer(disps, matrixT_before_target, matrixT_after_target, img_before, img_target, img_after)

    grads = tape.gradient(loss_value, trainable_weights)
    optimizer.apply_gradients(zip(grads, trainable_weights))

    with train_summary_writer.as_default():
        tf.summary.scalar('loss', loss_value, step=step_count)

    return loss_value, disps, image_from_before, image_from_after

@tf.function
def eval_step(batch_imgs, depth_gt):
    # batch_imgs: (batch_size, height, width, 9) Three images concatenated on the channels dimension
    # depth_gt: (batch_size, height, width)

    img_before = batch_imgs[:, :, :, :3]
    img_target = batch_imgs[:, :, :, 3:6]
    img_after = batch_imgs[:, :, :, 6:]

    disps = depth_net(img_target)  # disparities at different scales, in increasing resolution

    # Loss:
    T_before_target = pose_net(concat_images(img_before, img_target))  # (bs, 6)
    T_target_after = pose_net(concat_images(img_target, img_after))  # (bs, 6)
    matrixT_before_target = make_transformation_matrix(T_before_target, False)  # (bs, 4, 4)
    matrixT_after_target = make_transformation_matrix(T_target_after, True)  # (bs, 4, 4)
    loss_value, image_from_before, image_from_after = \
        loss_layer(disps, matrixT_before_target, matrixT_after_target, img_before, img_target, img_after)

    metrics = compute_metrics(disps[-1], depth_gt)

    return loss_value, metrics, disps, image_from_before, image_from_after

def evaluation_loop(val_reader, step_count):
    print('Evaluating...')
    eval_start = datetime.now()
    accum_loss = 0.0
    accum_metrics = np.zeros((7), np.float32)
    for batch_idx in range(val_reader.nbatches):
        batch_imgs, batch_depth_gt = val_reader.get_batch()
        loss_value, metrics, disps, image_from_before, image_from_after = eval_step(batch_imgs, batch_depth_gt)
        loss_value = loss_value.numpy()
        accum_loss += loss_value
        assert len(metrics) == len(accum_metrics)
        for i in range(len(accum_metrics)):
            accum_metrics[i] += metrics[i]
    metrics = accum_metrics / float(val_reader.nbatches)
    average_loss = accum_loss / float(val_reader.nbatches)
    with val_summary_writer.as_default():
        tf.summary.scalar('loss', average_loss, step=step_count)
        tf.summary.scalar('abs_rel', metrics[0], step=step_count)
        tf.summary.scalar('sq_rel', metrics[1], step=step_count)
        tf.summary.scalar('rmse', metrics[2], step=step_count)
        tf.summary.scalar('rmse_log', metrics[3], step=step_count)
        tf.summary.scalar('a1', metrics[4], step=step_count)
        tf.summary.scalar('a2', metrics[5], step=step_count)
        tf.summary.scalar('a3', metrics[6], step=step_count)
    print('Evaluation computed in ' + str(datetime.now() - eval_start))

with AsyncReader(train_reader_opts) as train_reader, AsyncReader(val_reader_opts) as val_reader:
    step_count = 0
    for epoch in range(nepochs):
        print("\nStart epoch ", epoch + 1)
        epoch_start = datetime.now()
        if epoch == 15:
            optimizer.learning_rate = 1e-5
            print('Changing learning rate to: %.2e' % optimizer.learning_rate)
        for batch_idx in range(train_reader.nbatches):
            batch_imgs, batch_depth_gt = train_reader.get_batch()
            step_count_tf = tf.convert_to_tensor(step_count, dtype=tf.int64)
            batch_imgs_tf = tf.convert_to_tensor(batch_imgs, dtype=tf.float32)
            loss_value, disps, image_from_before, image_from_after = train_step(batch_imgs_tf, step_count_tf)
            depth_gt_tf = tf.convert_to_tensor(batch_depth_gt, dtype=tf.float32)
            compute_and_log_metrics(disps[-1], depth_gt_tf, step_count_tf)
            train_summary_writer.flush()
            stdout.write("\rbatch %d/%d, loss: %.2e    " % (batch_idx + 1, train_reader.nbatches, loss_value.numpy()))
            stdout.flush()
            if (batch_idx + 1) % 10 == 0:
                display_training_basic(batch_imgs, disps, batch_depth_gt)
            step_count += 1
        stdout.write('\n')
        print('Epoch computed in ' + str(datetime.now() - epoch_start))

        evaluation_loop(val_reader, step_count)

        # Save models:
        print('Saving models')
        pose_net.save_weights(os.path.join(save_dir, 'pose_net_' + str(epoch), 'weights'))
        depth_net.save_weights(os.path.join(save_dir, 'depth_net_' + str(epoch), 'weights'))