from __future__ import absolute_import
from __future__ import print_function
import os
import pandas as pd
import sys
import time
top_path=os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
# add the top-level directory of this project to sys.path so that we can import modules without error
sys.path.append(top_path)
import numpy as np
import argparse
import imp
import re
import gc
from mimic3models.in_hospital_mortality import utils
from mimic3benchmark.readers import InHospitalMortalityReader
import tensorflow as tf
from mimic3models.preprocessing import Discretizer, Normalizer
from mimic3models import metrics
from mimic3models import keras_utils
from mimic3models import common_utils
from keras.callbacks import ModelCheckpoint, CSVLogger
import random
def draw_samples(data,seed,percentage):
    positives = list(data[data['y_true'] == 1].index.values.tolist())
    negatives = list(data[data['y_true'] == 0].index.values.tolist())
    # randomly sample labels at this percentage
    n = len(data)
    np.random.seed(seed)
    if percentage > 0.05:
        samples = np.random.randint(n, size=int(n * percentage))
    else:
        np.random.seed(seed)
        positives = random.sample(positives, int(n * percentage / 2))
        np.random.seed(seed)
        negatives = random.sample(negatives, int(n * percentage / 2))
        samples = [*positives, *negatives]
    data = data[['stay','y_true']].iloc[samples, :]
    return data

#python -m mimic3models.split_train_val data/in-hospital-mortality
#   python -um mimic3models.in_hospital_mortality.main --network mimic3models/keras_models/lstm.py --dim 16 --timestep 1.0 --depth 2 --dropout 0.3 --mode train --batch_size 8 --save_every 10000 --output_dir mimic3models/in_hospital_mortality

#                   -------- argparse --------
parser = argparse.ArgumentParser()
# WTF !
common_utils.add_common_arguments(parser)
parser.add_argument('--target_repl_coef', type=float, default=0.0)

parser.add_argument('--seed', type=int, default=0)
parser.add_argument('--data', type=str, help='Path to the data of in-hospital mortality task',
                    default=os.path.abspath(os.path.join(os.path.dirname(__file__), '../../data/in-hospital-mortality/')))
parser.add_argument('--output_dir', type=str, help='Directory relative which all output files are stored',
                    default='.')
args = parser.parse_args()
physical_devices = tf.config.list_physical_devices('GPU')
# Don't pre-allocate memory; allocate as-needed
tf.config.experimental.set_memory_growth(physical_devices[0], True)

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

#                   ------ not yet realize ----
if args.small_part:   #TODO:
    args.save_every = 2**30

target_repl = (args.target_repl_coef > 0.0 and args.mode == 'train') #TODO:
#                   ---------------------------
# percentages=[0.001,0.002,0.003,0.004,0.005,0.008,0.010,0.050,0.100,0.200,0.300,0.400,0.500,0.650,0.85,1.000]
percentages=[0.005]
accs=[]
roc_tests = []
prc_tests = []
aps=[]
pses = []
train_list =pd.read_csv(os.path.join(top_path,'ref','train_listfile.csv'))
seed=args.seed
for percentage in percentages:
    temp_list_file=draw_samples(train_list,seed,percentage)
    temp_list_file.to_csv(os.path.join(args.data, 'temp.csv'),index=False)
# Build readers, discretizers, normalizers
    train_reader = InHospitalMortalityReader(dataset_dir=args.data,
                                             listfile=os.path.join(args.data, 'temp.csv'),
                                             period_length=48.0)

    # * mined that dataset_dir of it is 'train'
    val_reader = InHospitalMortalityReader(dataset_dir=args.data,
                                           listfile=os.path.join(args.data, 'val_listfile.csv'),
                                           period_length=48.0)

    # default impute strategy is 'previous' here
    # default timestep is 1.0
    discretizer = Discretizer(timestep=float(args.timestep),
                              store_masks=True,
                              impute_strategy='previous',
                              start_time='zero')

    discretizer_header = discretizer.transform(train_reader.read_example(0)["X"])[1].split(',')
    cont_channels = [i for (i, x) in enumerate(discretizer_header) if x.find("->") == -1]  # only categorical data has '->'

    normalizer = Normalizer(fields=cont_channels)  # choose here which columns to standardize
    normalizer_state = args.normalizer_state
    if normalizer_state is None:
        normalizer_state = 'ihm_ts{}.input_str:{}.start_time:zero.normalizer'.format(args.timestep, args.imputation)
        normalizer_state = os.path.join(os.path.dirname(__file__), normalizer_state)
    normalizer.load_params(normalizer_state)  # ?Need to run "create_normalizer_state.py" first

    args_dict = dict(args._get_kwargs())
    args_dict['header'] = discretizer_header
    args_dict['task'] = 'ihm'
    args_dict['target_repl'] = target_repl

    # Build the model
    print("==> using model {}".format(args.network))
    model_module = imp.load_source(os.path.basename(args.network), args.network)
    model = model_module.Network(**args_dict)
    suffix = 'percentage_%f_seed_%d'%(percentage,seed)
    model.final_name = 'lstm_'+ suffix
    print("==> model.final_name:", model.final_name)

    # Compile the model
    # print("==> compiling the model")

    optimizer_config = {'class_name': args.optimizer,
                        'config': {'learning_rate': args.lr,
                                   'beta_1': args.beta_1}}
    # NOTE: one can use binary_crossentropy even for (B, T, C) shape.
    #       It will calculate binary_crossentropies for each class
    #       and then take the mean over axis=-1. Tre results is (B, T).
    if target_repl:
        loss = ['binary_crossentropy'] * 2
        loss_weights = [1 - args.target_repl_coef, args.target_repl_coef]
    else:
        loss = 'binary_crossentropy'
        loss_weights = None

    model.compile(optimizer=optimizer_config,
                  loss=loss,
                  loss_weights=loss_weights)
    model.summary()

    # Load model weights
    n_trained_chunks = 0

    # Read data
    train_raw = utils.load_data(train_reader, discretizer, normalizer, args.small_part,percentage=1)
    val_raw = utils.load_data(val_reader, discretizer, normalizer, args.small_part)

    if target_repl:
        T = train_raw[0][0].shape[0]

        def extend_labels(data):
            data = list(data)
            labels = np.array(data[1])  # (B,)
            data[1] = [labels, None]
            data[1][1] = np.expand_dims(labels, axis=-1).repeat(T, axis=1)  # (B, T)
            data[1][1] = np.expand_dims(data[1][1], axis=-1)  # (B, T, 1)
            return data

        train_raw = extend_labels(train_raw)
        val_raw = extend_labels(val_raw)

    # Prepare training
    path = os.path.join(args.output_dir, 'keras_states/' + model.final_name + '.state')

    metrics_callback = keras_utils.InHospitalMortalityMetrics(train_data=train_raw,
                                                              val_data=val_raw,
                                                              target_repl=(args.target_repl_coef > 0),
                                                              batch_size=args.batch_size,
                                                              verbose=args.verbose)
    # make sure save directory exists
    dirname = os.path.dirname(path)
    if not os.path.exists(dirname):
        os.makedirs(dirname)
    saver = ModelCheckpoint(path, verbose=1, period=args.save_every)

    keras_logs = os.path.join(args.output_dir, 'keras_logs')
    if not os.path.exists(keras_logs):
        os.makedirs(keras_logs)
    csv_logger = CSVLogger(os.path.join(keras_logs, model.final_name +'.csv'),
                           append=True, separator=';')

    print("percentage %f==> training"%percentage)
    model.fit(x=train_raw[0],
              y=train_raw[1],
              validation_data=val_raw,
              epochs=n_trained_chunks + args.epochs,
              initial_epoch=n_trained_chunks,
              callbacks=[metrics_callback, saver, csv_logger],
              shuffle=True,
              verbose=args.verbose,
              batch_size=args.batch_size)
    # gc.collect()

#

    # ensure that the code uses test_reader
    del train_reader
    del val_reader
    del train_raw
    del val_raw

    test_reader = InHospitalMortalityReader(dataset_dir=os.path.join(args.data),
                                            listfile=os.path.join(args.data, 'test_listfile.csv'),
                                            period_length=48.0)
    ret = utils.load_data(test_reader, discretizer, normalizer, args.small_part,
                          return_names=True)

    data = ret["data"][0]
    labels = ret["data"][1]
    names = ret["names"]

    predictions = model.predict(data, batch_size=args.batch_size, verbose=1)
    predictions = np.array(predictions)[:, 0]
    results=metrics.print_metrics_binary(labels, predictions)
    auroc=results['auroc']
    auprc=results['auprc']
    minpse=results['minpse']
    ap=results['ap']
    acc=results['acc']
    roc_tests.append(auroc)
    prc_tests.append(auprc)
    pses.append(minpse)
    accs.append(acc)
    aps.append(ap)
    # path = os.path.join(args.output_dir, "test_percentage%f_seed%d"%(percentage,seed) + ".csv")
    # utils.save_results(names, predictions, labels, path)
    del temp_list_file,model
    gc.collect()

print('---------  seed = %d ---------------'%seed)
print('------ percentages = %s'%percentages)
print('acc===================')
print(acc)
print('auroc=================')
print(auroc)
print("ap=======")
print(aps)
print('auprc=================')
print(auprc)
print('pse===================')
print(pses)


import math
import statistics
import numpy as np
import pandas as pd
import scipy.stats
import backtrader as bt
import datetime as dt

data=[13589.5,13546,13566,13789.4]
print("Statistics example of fmean:",statistics.fmean(data))

class FirstStrategy(bt.Strategy):
    def log(self,txt):
        print(txt)
    def __init__(self):
        self.dataclose=self.datas[0].close
        self.candletracker=0
        self.x=len(list(self.dataclose))
    def next(self):
        self.log("Close:"+str(self.dataclose[0]))
        if len(self)==1:
            print("Previous data unavailabe for strategy")
        if len(self)==2:
            print("Previous data unavailable for strategy")
        if len(self)>=self.x-4:
            print("Strategy cannot be applied for these dates")
        if not self.position:
            if self.dataclose[0]>self.dataclose[-1]:
                if self.dataclose[-1]>self.dataclose[-2]:
                    self.order=self.buy()
                    self.log("BUY ORDER TRIGGERED:"+str(self.dataclose[0]))
                    self.candletracker=0
        else:
            self.candletracker+=1
            if self.candletracker>4:

                self.close()
                self.log("ORDER EXITED:"+str(self.dataclose[0]))
                self.candletracker=0

if __name__=='__main__':
    cerebro=bt.Cerebro()
    cerebro.addstrategy(FirstStrategy)
    datapath2 = "D:/Trading/Backtesting_Course/testdata/Nifty-1D.csv"
    datapath = "D:/Trading/Backtesting_Course/testdata/NiftyFutures-1D.csv"
    data=bt.feeds.GenericCSVData(
        dataname=datapath,
        fromdate=dt.datetime(2011,1,1),
        todate=dt.datetime(2021,1,1),
        datetime=0,
        timeframe=bt.TimeFrame.Days,
        compression=1,
        dtformat=('%Y-%m-%d'),
        open=1,
        high=2,
        low=3,
        close=4,
        volume=5,
        openinterest=None,
        reverse=False,
        header=0
    )
    data2 = bt.feeds.GenericCSVData(
        dataname=datapath2,
        fromdate=dt.datetime(2011, 1, 1),
        todate=dt.datetime(2021, 1, 1),
        datetime=0,
        timeframe=bt.TimeFrame.Days,
        compression=1,
        dtformat=('%Y-%m-%d'),
        open=1,
        high=2,
        low=3,
        close=4,
        volume=None,
        openinterest=None,
        reverse=False,
        header=0
    )
    cerebro.adddata(data)
    cerebro.adddata(data2)
    cerebro.broker.set_cash(1000000.00)
    print("Starting Portfolio value:",cerebro.broker.getvalue())
    cerebro.run()
    print("Final Portfolio value:",cerebro.broker.getvalue())


from typing import List

class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        通过双指针把数组分为3部分[0,1,2]
        遍历数组，把所有0交换到数组左边，1保持不动放在中间，2交换到右边
        遍历数组，i从左到右，p2从右到左，i超过p2时结束
        i <= p2:
            - nums[i]==0,和nums[p0]交换，p0和i前进
            - nums[i]==1,保持不动，i前进
            - nums[i]==2,和nums[p2]交换, p2前进
                - i 保持不动，因为和nums[p2]交换后，nums[i]可能还是2，所以i要进入下一轮循环
        """
        n = len(nums)
        p0, p2 = 0, n - 1
        i = 0
        while i <= p2:
            if nums[i] == 0:
                nums[i], nums[p0] = nums[p0], nums[i]
                p0 += 1
                i += 1
            elif nums[i] == 1:
                i += 1
            elif nums[i] == 2:
                nums[i], nums[p2] = nums[p2], nums[i]
                p2 -= 1

if __name__ == '__main__':
    res = Solution()
    print(res.sortColors(nums=[2, 0, 2, 1, 1, 0]))


import torch
import torch.nn as nn
from torchvision import utils

from utils.save import save_loss, save_fake_images

class EBGAN:
    def __init__(self, Generator, Discriminator, weights_init, epochs,
                 batch_size, img_size, save_epoch, dim_z, lr, beta1,
                 beta2=0.999, lambda_pt=0.1, margin=1, device='cpu'):
        self.device = device

        self.G = Generator().to(device)
        self.D = Discriminator().to(device)
        self.G.apply(weights_init)
        self.D.apply(weights_init)

        self.criterion = nn.MSELoss()

        self.d_optimizer = torch.optim.Adam(self.D.parameters(), lr=lr,
                                            betas=(beta1, beta2))
        self.g_optimizer = torch.optim.Adam(self.G.parameters(), lr=lr,
                                            betas=(beta1, beta2))

        self.epochs = epochs
        self.batch_size = batch_size
        self.img_size = img_size
        self.save_epoch = save_epoch
        self.dim_z = dim_z
        self.lambda_pt = lambda_pt
        self.margin = margin

    def train(self, train_loader, result_root='result/mnist'):
        data_size = len(train_loader)
        iters = 0
        g_losses = []
        d_losses = []
        fixed_z = torch.randn(64, self.dim_z, device=self.device)

        for epoch in range(self.epochs):
            for i, (images, _) in enumerate(train_loader):
                b_size = images.shape[0]
                ############################
                # (1) Update D network
                ###########################
                # Train with all-real batch
                # Format batch
                real_images = images.to(self.device)
                # Forward pass real batch through D
                d_real, _ = self.D(real_images)
                # Calculate loss on all-real batch
                d_loss_real = self.criterion(d_real, real_images)

                # Train with all-fake batch
                # Generate batch of latent vectors
                z = torch.randn(b_size, self.dim_z, device=self.device)
                # Generate fake image batch with G
                fake_images = self.G(z)
                # Classify all fake batch with D
                d_fake, embeddings = self.D(fake_images.detach())
                # Calculate D's loss on the all-fake batch
                d_loss_fake = self.criterion(d_fake, fake_images.detach())
                # Calculate the gradients for this batch
                self.D.zero_grad()
                d_loss = d_loss_real
                if self.margin - d_loss_fake.item() > 0:
                    d_loss += self.margin - d_loss_fake
                d_loss.backward()
                # Update D
                self.d_optimizer.step()

                ############################
                # (2) Update G network
                ###########################
                # Since we just updated D, perform another forward pass of
                # all-fake batch through D.
                d_fake, embeddings = self.D(fake_images)
                # Calculate G's loss based on this output
                g_loss = self.criterion(d_fake, fake_images) \
                         + self.lambda_pt * self.pullaway_loss(embeddings)
                # Calculate gradients for G
                self.G.zero_grad()
                g_loss.backward()
                # Update G
                self.g_optimizer.step()

                d_losses.append(d_loss.item())
                g_losses.append(g_loss.item())

                # Output training states
                if i % 50 == 0:
                    self._show_training_state(epoch, i, data_size,
                                              d_loss, g_loss)

                # Save the trained parameters
                if (epoch + 1) % self.save_epoch == 0:
                    self.save_model(epoch + 1, result_root)
                # Check the model by saving G's output on fixed_noise
                if (iters % 500 == 0) or (
                        (epoch == 100 - 1) and (i == len(train_loader) - 1)):
                    with torch.no_grad():
                        fake = self.G(fixed_z).detach().cpu()
                        fake_images = utils.make_grid(fake, padding=2,
                                                      normalize=True)
                        save_fake_images(fake_images, iters, result_root)

                iters += 1
        # Save the losses
        save_loss(d_losses, g_losses, result_root)

    @staticmethod
    def pullaway_loss(embeddings):
        norm = torch.sqrt(torch.sum(embeddings ** 2, -1, keepdim=True))
        normalized_emb = embeddings / norm
        similarity = torch.matmul(normalized_emb,
                                  normalized_emb.transpose(1, 0))
        batch_size = embeddings.size(0)
        loss_pt = (torch.sum(similarity) - batch_size) / (
                batch_size * (batch_size - 1))
        return loss_pt

    def _show_training_state(self, epoch, iteration, data_size, d_loss,
                             g_loss):
        print(f'[{epoch}/{self.epochs}][{iteration}/{data_size}]\t\
              Loss_D: {d_loss:.4f}\tLoss_G: {g_loss:.4f}')

    def save_model(self, epoch, path):
        torch.save(self.G.state_dict(),
                   f'{path}/checkpoint/generator_{epoch}.pkl')
        torch.save(self.D.state_dict(),
                   f'{path}/checkpoint/discriminator_{epoch}.pkl')
        print(f'Models save to {path}/')

    def load_model(self, discriminator_path, generator_path):
        self.D.load_state_dict(torch.load(discriminator_path))
        self.G.load_state_dict(torch.load(generator_path))
        print('Discriminator model loaded from {}-'.format(discriminator_path))
        print('Generator model loaded from {}.'.format(generator_path))


import os
import sys
import json
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class WindowClassificationMain(QtWidgets.QWidget):

    backward_main = QtCore.pyqtSignal();

    def __init__(self):
        super().__init__()
        self.title = 'Monk Classification'
        self.left = 100
        self.top = 100
        self.width = 500
        self.height = 220
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height);

        # Forward
        self.b1 = QPushButton('Next', self)
        self.b1.move(300,180)
        self.b1.clicked.connect(self.forward)
        self.b1.setEnabled(False)

        # Backward
        self.b2 = QPushButton('Back', self)
        self.b2.move(200,180)
        self.b2.clicked.connect(self.backward)

        # Quit
        self.b3 = QPushButton('Quit', self)
        self.b3.move(400,180)
        self.b3.clicked.connect(self.close)

    def forward(self):
    	pass;

    def backward(self):
    	self.backward_main.emit();


import numpy as np
import matplotlib.pyplot as pl
import matplotlib as mpl
from scipy.interpolate import interp2d,Rbf,griddata
from mpl_toolkits.axes_grid1 import make_axes_locatable
import sys

font = {'family' : 'sans-serif',
        'size'   : 15}

mpl.rcParams['xtick.major.size'] = 5
mpl.rcParams['xtick.major.width'] = 1
mpl.rcParams['xtick.minor.size'] = 3
mpl.rcParams['xtick.minor.width'] = 1
mpl.rcParams['ytick.major.size'] = 5
mpl.rcParams['ytick.major.width'] = 1
mpl.rcParams['ytick.minor.size'] = 3
mpl.rcParams['ytick.minor.width'] = 1
mpl.rc('font', **font)

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

#Use: python PlotROSATmaps.py bandID
#where bandID = 1,2,4,5,6,7 is the energy band to plot

bandID = int(sys.argv[1])

if (bandID == 1):
    colmap = "Blues"
if (bandID == 2):
    colmap = "GnBu"
if (bandID == 4):
    colmap = "Greens"
if (bandID == 5):
    colmap = "Oranges"
if (bandID == 6):
    colmap = "Reds"
if (bandID == 7):
    colmap = "Purples"

#Load Xray map
XrayMap = np.loadtxt("../maps/ROSAT_R"+str(bandID)+"_rate.txt")

#Set data ranges for the plot
minval = 1
maxval = 1e5
cticks = [0.0,1,2,3,4,5]
clabs = [r'$1$',r'$10$',r'$10^{2}$',r'$10^{3}$',r'$10^{4}$',r'$10^{5}$']

#Do some plotting
fig = pl.figure(figsize=(12,7))
ax1 = fig.add_subplot(111)

im1 = ax1.imshow(np.log10(np.abs(np.clip(XrayMap, minval,maxval)))
        , extent=[-180, 180, -90, 90],cmap=colmap, origin="lower")

divider = make_axes_locatable(ax1)
cax = divider.append_axes("right", size="5%", pad=0.1)

cb1 = pl.colorbar(im1, label=r"$10^{-6}$ counts per second per arcmin$^{2}$",\
            ticks=cticks, extend="both", cax=cax)
cb1.ax.set_yticklabels(clabs)

ax1.set_aspect(1.0)

ax1.set_xlim(-180,180)
ax1.set_ylim(-90, 90)

ax1.set_xticks([-180, -120, -60, 0, 60, 120, 180])
ax1.set_yticks([-90, -45, 0, 45, 90])

bandtext = "..."

if (bandID == 1):
    bandtext = "(Band R1: 0.11 - 0.284 keV)"
if (bandID == 2):
    bandtext = "(Band R2: 0.14 - 0.284 keV)"
if (bandID == 4):
    bandtext = "(Band R4: 0.44 - 1.01 keV)"
if (bandID == 5):
    bandtext = "(Band R5: 0.56 - 1.21 keV)"
if (bandID == 6):
    bandtext = "(Band R6: 0.73 - 1.56 keV)"
if (bandID == 7):
    bandtext = "(Band R7: 1.05 - 2.04 keV)"

ax1.set_title('ROSAT Soft X-ray Background '+bandtext, fontsize=12)

#Put a box around region 12...
#ax1.plot([-80, -80, 80, 80, -80], [+5, +15, +15, +5, +5], 'k:')

ax1.set_xlabel(r'$l$ [degrees]', labelpad=5)
ax1.set_ylabel(r'$b$ [degrees]', labelpad=5)

pl.savefig('../plots/ROSAT_R' + str(bandID) +'_fullsky.pdf', bbox_inches="tight")


from pytest import fixture
from deploy_beanstalk import previous_git_commit, parse

@fixture()
def git_log_output():
    return '''commit bc061fc755015162741eec71f1a71ea6c3fdb786
Author: j1z0 <jeremy_johnson@hms.harvard.edu>
Date:   Thu Sep 22 22:23:54 2016 -0400

    we need .aws for both master and production

    '''

def test_parse_git_commit(git_log_outpu):
    author = "j1z0 <jeremy_johnson@hms.harvard.edu>"
    msg = "we need .aws for both master and production"
    expected = "%s - %s" % (author, msg)
    actual = parse(previous_git_commit())

    print("expected result: ", expected)
    print("actual result: ", actual)
    assert expected == actual

if __name__ == "__main__":
    print(".")
    test_parse_git_commit(git_log_output())
    print("all good!")


from setuptools import setup, find_packages
import os

version = '0.3'

setup(name='z3c.recipe.mkdir',
      version=version,
      description="Buildout recipe to create directories.",
      long_description=open("README.txt").read() + "\n\n" +
                       open(os.path.join("z3c", "recipe", "mkdir",
                                         "README.txt")).read() + "\n\n" +
                       open("CHANGES.txt").read(),
      classifiers=[
        "Development Status :: 3 - Alpha",
        "Framework :: Buildout",
        "Programming Language :: Python",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "License :: OSI Approved :: Zope Public License",
        ],
      keywords='buildout directory folder mkdir',
      author='Uli Fouquet',
      author_email='grok-dev@zope.org',
      url='http://pypi.python.org/pypi/z3c.recipe.mkdir',
      license='ZPL 2.1',
      packages=find_packages(exclude=['ez_setup']),
      namespace_packages=['z3c', 'z3c.recipe' ],
      include_package_data=True,
      zip_safe=False,
      install_requires=[
          'setuptools',
          'zc.buildout',
      ],
      extras_require=dict(
        test = [
            'zope.testing',
            ]
        ),
      entry_points="""
      [zc.buildout]
      default = z3c.recipe.mkdir:Recipe
      """,
      )


import tensorflow as tf
from . import crop
from . import rnet
from . import coeffs_to_mesh

import os
RENDER_OP_LIBRARY = 'yadira_render_cpp.so'
lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
assert os.path.isdir(lib_dir), lib_dir
lib_file = os.path.join(lib_dir, RENDER_OP_LIBRARY)
assert os.path.isfile(lib_file),lib_file
render_ops = tf.load_op_library(lib_file)
assert hasattr(render_ops, 'render_colors')

class MS(tf.Module):
    def __init__(self):
        super(MS, self).__init__()
        self.crop = crop.Crop()
        self.rnet = rnet.RNet()
        self.coeffs_to_mesh = coeffs_to_mesh.CoeffsToMesh()

        self.render_colors = render_ops.render_colors

        self.get_coeffs = tf.function(
            self.get_coeffs,
            input_signature=[
                tf.TensorSpec([1, None, None, 3], tf.float32, name='images'),
                tf.TensorSpec([1, 5, 2], tf.float32, name='facial_landmarks'),
            ])

        self.get_mesh = tf.function(
            self.get_mesh,
            input_signature=[
                tf.TensorSpec([1, None, None, 3], tf.float32, name='images'),
                tf.TensorSpec([1, 5, 2], tf.float32, name='facial_landmarks'),
                tf.TensorSpec([], tf.bool),
            ])

        self.get_depthmap = tf.function(
            self.get_depthmap,
            input_signature=[
                tf.TensorSpec([1, None, None, 3], tf.float32, name='images'),
                tf.TensorSpec([1, 5, 2], tf.float32, name='facial_landmarks'),
                tf.TensorSpec([], tf.bool),
            ])

    def get_coeffs(self, b_img, b_lms2d_n5):
        """
        Returns:
            crop [b, 224, 224, 3]
            coeffs [b, 257]
        """
        img = b_img[0]
        lms2d_n5 = b_lms2d_n5[0]

        img, lms2d_n5, t, s = self.crop(img, lms2d_n5)
        coeffs = self.rnet(tf.expand_dims(img, axis=0))
        angles = coeffs[0, 224:227]  # pitch, yaw, roll
        return {
            'crop': img,
            't': t,
            's': s,
            'coeffs': coeffs,
            'angles': angles,
        }

    def get_mesh(self, b_img, b_lms2d_n5, frontalize):
        """
        Returns:
            crop [b, 224, 224, 3]
            coeffs [b, 257]
            mesh [b, N_vertices, 3]
        """
        out = self.get_coeffs(b_img, b_lms2d_n5)
        mesh = self.coeffs_to_mesh(out['coeffs'], frontalize)
        out.update({'mesh': mesh})
        return out

    def get_depthmap(self, img_bytes, b_lms2d_n5, frontalize):
        """
        Returns face info in source crop coordinates (either frontalize=True or not):
        Возвращает информацию о лице в координатах кропа (вне зависимости от frontalize=True или False)
            crop [b, 224, 224, 3]
            coeffs [b, 257]
            coeffs_251 [b, 251]
            mesh [b, N_vertices, 3]
            depthmap [b, 224, 224, 1]
        """
        out = self.get_mesh(img_bytes, b_lms2d_n5, frontalize)
        mouth = False

        def _get_depth_from_vertices_tf(vertices):
            z = vertices[:, 2:]
            z = z - tf.reduce_min(z)
            z = z / tf.reduce_max(z)
            return z

        z = _get_depth_from_vertices_tf(out['mesh'][0])
        depthmap = self.render_colors(out['mesh'][0], self.coeffs_to_mesh.get_triangles(mouth), z, 224, 224, 1)
        out.update({'depthmap': tf.expand_dims(depthmap, axis=0),})
        return out

def test():
    import os
    import cv2
    import numpy as np
    from PIL import Image
    import matplotlib.pyplot as plt
    from copy import deepcopy
    def _get_lms2d_n5_from_txt(img_file):
        txt_file = os.path.splitext(img_file)[0]+'.txt'
        lms2d_n5 = np.loadtxt(txt_file)
        assert lms2d_n5.shape == (5, 2)
        return lms2d_n5
    def _read_img_pil(img_file):
        assert os.path.isfile(img_file)
        pil_img = Image.open(img_file)
        return pil_img

    def draw_vertices(mesh_vertices, image, vertice_color=[255, 255, 255], vertice_r=1, extra_scale=3):
        mesh_vertices *= extra_scale

        h, w, _ = image.shape
        w *= extra_scale
        h *= extra_scale
        image = cv2.resize(image, (w, h))

        def draw_r_1():
            image[y, x] = vertice_color
        def draw_r():
            cv2.circle(image, (x, y), vertice_r, vertice_color, thickness=-1)

        if vertice_r == 1:
            draw_func = draw_r_1
        else:
            draw_func = draw_r

        for vertex in mesh_vertices:
            x, y = [np.round(v).astype(int) for v in vertex[:2]]
            if 0 <= x < w and 0 <= y < h:
                draw_func()
        return image
    img_file = os.path.join(os.path.dirname(__file__), 'resources/examples/000002.jpg')
    img_file = os.path.normpath(os.path.join(os.path.dirname(__file__), '../working_dir/exmp1.jpg'))
    assert os.path.isfile(img_file)
    lms2d_n5 = _get_lms2d_n5_from_txt(img_file)

    img = _read_img_pil(img_file)
    img = np.array(img)
    plt.imshow(img); plt.show()
    img_vis = draw_vertices(deepcopy(lms2d_n5), deepcopy(img), vertice_color=[0,255,0],vertice_r=6)
    plt.imshow(img_vis); plt.show()
    img = img.astype(np.float32)

    ms = MS()
    img = np.expand_dims(img, axis=0)
    lms2d_n5 = np.expand_dims(lms2d_n5, axis=0)
    out = ms.get_depthmap(img, lms2d_n5, False)

    def _show_img(image, title='', title_color='lime', title_size=20, cmap=None):
        plt.figure(figsize=(10, 10))
        plt.suptitle(title, c=title_color, fontsize=title_size)
        plt.imshow(image, cmap=cmap)
        plt.show()

    plt.imshow(out['crop'].numpy().astype(int)); plt.show()
    mesh = out['mesh'].numpy()[0]
    vis = draw_vertices(mesh, out['crop'].numpy())
    plt.imshow(vis.astype(int)); plt.show()
    print()

from ..transform import base as tb
from ..transform import hwc
from ..fan2d import Pipe_GetLms2d5n
import numpy as np
class Pipe_MsFaceReconstruction(tb.Pipe):
    KEY_CALL_IMMUT_hwc = hwc.KEY_hwc
    KEY_CALL_IMMUT_lms2d_5n = Pipe_GetLms2d5n.KEY_OUT_lms2d_5n
    KEY_OUT_mesh = 'mesh'

    """(x,y)"""
    KEY_OUT_t = 't'

    KEY_OUT_s = 's'

    """
    pitch, yaw, roll
    """
    KEY_OUT_angles = 'angles'
    def before_keys_assertions(self, **data):pass
    def after_keys_assertions(self, **data):
        mesh = data[self.KEY_OUT_mesh]
        if mesh is not None:
            assert len(mesh.shape)==2 and mesh.shape[-1]==3
            t = data[self.KEY_OUT_t]
            assert t.shape==(2,)
            s = data[self.KEY_OUT_s]
            assert s.shape==()
class MsFaceReconstruction(tb.TransformNoDataIndependentRandomness):
    PIPE_DEFAULT = Pipe_MsFaceReconstruction
    def _init_(self, **config):
        self.ms = MS()
    def transform(self, hwc, lms2d_5n):
        if lms2d_5n is not None:
            b_img = np.expand_dims(hwc, axis=0)
            b_lms2d_n5 = np.expand_dims(lms2d_5n, axis=0)
            out = self.ms.get_mesh(b_img, b_lms2d_n5, False)
            return {
                self.PIPE_DEFAULT.KEY_OUT_mesh: out['mesh'].numpy()[0],
                self.PIPE_DEFAULT.KEY_OUT_t: out['t'].numpy(),
                self.PIPE_DEFAULT.KEY_OUT_s: out['s'].numpy(),
                self.PIPE_DEFAULT.KEY_OUT_angles: out['angles'].numpy(),
            }
        else:
            return {
                self.PIPE_DEFAULT.KEY_OUT_mesh: None,
                self.PIPE_DEFAULT.KEY_OUT_t: None,
                self.PIPE_DEFAULT.KEY_OUT_s: None,
                self.PIPE_DEFAULT.KEY_OUT_angles: None,
            }


import os
import time
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import cv2

def one_hot_encode(kmeans_result):
    """
    One hot encodes an image;

    Parameters
    ----------
    kmeans_result : ndarray
        Image after applying clusterization

    Returns
    -------
    encoded_image  : ndarray
        Array with k masks: one per each binary one-hot-encode mask
    """
    unique = np.unique(kmeans_result)
    colormap = {i:unique[i] for i in range(len(unique))}
    encoded_image = np.zeros(kmeans_result.shape[:2] + (len(colormap), ), dtype=np.float32)
    for i in range(encoded_image.shape[2]):
        encoded_image[:, :, i] = np.all(kmeans_result.reshape((-1, 1)) == colormap[i],
                                        axis=1).reshape(kmeans_result.shape[:2])
    return encoded_image

def binarize_data(img=None, k=None, bilateral_filter=None,
                  d=None, sigmaColor=None, sigmaSpace=None):
    """
    Apply clusterization to segment data;

    Parameters
    ----------
    img : ndarray
        Image to segment
    k : int
        Num of clusters
    bilateral_filter : boolean
        whether to apply bilateral filter
    d, sigmaColor, sigmaSpace : int
        bilateral filter params

    Returns
    -------
    segmented_image, porosity  : ndarray
        results of prediction
    """
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, 0.99)

    #reshape to appropriate for KMeans shape
    pixel_vals = img.reshape((-1,1))

    # Convert to float type
    pixel_vals = np.float32(pixel_vals)
    if bilateral_filter:
        bilateral = cv2.bilateralFilter(pixel_vals, d, sigmaColor, sigmaSpace)
        retval, labels, centers = cv2.kmeans(bilateral, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    else:
        retval, labels, centers = cv2.kmeans(pixel_vals, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    centers = np.uint8(centers)
    segmented_data = centers[labels.flatten()]

    segmented_image = one_hot_encode(segmented_data.reshape((img.shape)))[:,:, 1]

    porosity = np.sum(segmented_image==0)/np.prod(segmented_image.shape)

    return segmented_image, porosity

def binarize_3d(img_3d, k = 2, bilateral_filter = None,
               d=None, sigmaColor=None, sigmaSpace=None):
    """
    Apply clusterization to segment 3D image;

    Parameters
    ----------
    img_3d : ndarray
        3D image to segment
    k : int
        Num of clusters
    bilateral_filter : boolean
        whether to apply bilateral filter
    d, sigmaColor, sigmaSpace : int
        bilateral filter params

    Returns
    -------
    result_3d, porosity_arr  : ndarray
        results of prediction
    """
    x_dim, y_dim, z_dim = img_3d.shape
    result_3d = np.zeros((x_dim, y_dim, z_dim))
    porosity_arr = np.zeros((x_dim,))
    for x in range(x_dim):
        result_3d[x, :, :], porosity_arr[x] = binarize_data(img = img_3d[x, :, :],
                                                            k = 2,
                                                            bilateral_filter = bilateral_filter,
                                                            d=d,
                                                            sigmaColor=sigmaColor,
                                                            sigmaSpace=sigmaSpace)
    return result_3d, porosity_arr

def plot_central_planes(image):
    """
    Plot central planes of volumetric data

    Parameters
    ----------
    img : ndarray
        3D image
    img_title : string
        plot title

    """
    n_x, n_y, n_z = image.shape
    fig, axs = plt.subplots(1,3, figsize = (15, 10))
    axs[0].imshow(image[n_x//2, :, :], cmap = 'gray'), axs[0].set_title('X central plane')
    axs[1].imshow(image[:, n_y//2, :], cmap = 'gray'), axs[1].set_title('Y central plane')
    axs[2].imshow(image[:, :, n_z//2], cmap = 'gray'), axs[2].set_title('Z central plane')
    plt.show()

def plot_3d(image, img_title=''):
    """
    Plot boundary planes of volumetric data

    Parameters
    ----------
    img : ndarray
        3D image
    img_title : string
        plot title

    """
    n_x, n_y, n_z = image.shape
    yy, zz = np.mgrid[0:n_y, 0:n_z]
    xx, zz = np.mgrid[0:n_x, 0:n_z]
    xx, yy = np.mgrid[0:n_x, 0:n_y]

    x_center_loc, y_center_loc, z_center_loc = n_x-1, 0, n_z-1

    # plot 3 orthogonal slices
    X, Y, Z = image[x_center_loc, :, :], image[:, y_center_loc, :], image[:, :, z_center_loc]

    fig = plt.figure(figsize = (25,10))
    ax1 = fig.add_subplot(121, projection='3d')
    ax1.set_title(img_title, fontsize = 17)
    ax1.contourf(X, xx, zz,  zdir='x', offset=n_x-1, cmap='gray')
    ax1.contourf(xx, Y, zz,  zdir='y', offset=y_center_loc, cmap='gray')
    ax1.contourf(xx, yy, Z,  zdir='z', offset=n_z-1, cmap='gray')
    plt.show()

def create_dir(dir_to_save):
    """
    creates folder in defined directory

    Parameters
    ----------
    dir_to_save : str
        path

    """
    if not os.path.exists(dir_to_save):
        os.makedirs(dir_to_save)

def PlotSlice(image, sliceNumber):
    plt.imshow(image[:,:,sliceNumber], cmap="gray")
    plt.gca().axes.get_yaxis().set_visible(False)
    plt.gca().axes.get_xaxis().set_visible(False)
    plt.title("Slice: " + str(sliceNumber), size=20)

def PlotImage(image):
    plt.figure(figsize=(30,10))
    plt.subplot(1,3,1)
    PlotSlice(image, 30)
    plt.subplot(1,3,2)
    PlotSlice(image, 250)
    plt.subplot(1,3,3)
    PlotSlice(image, 500)


# coding: utf-8

import StringIO
import shlex
import os
import sys
import json
import datetime
import ConfigParser
from minecraft_query import MinecraftQuery
from PIL import Image, ImageDraw, ImageFont
from subprocess import PIPE, Popen

ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__)))

#Doc
#http://www.pythonware.com/library/pil/handbook/imagedraw.htm
#http://stackoverflow.com/questions/4011705/python-the-imagingft-c-module-is-not-installed (_imaging)

"""
map = world
motd = BEST-HOSTING s.r.o.
hostname = 194.8.253.48
numplayers = 6
gametype = SMP
maxplayers = 40
hostport = 25565

map = world
motd = BEST-HOSTING s.r.o.
hostport = 25565
numplayers = 6
gametype = SMP
players = ['janice158', 'nitramek2013', 'batman', 'Fox24', 'adelka', 'HunySss']
version = 1.4.5
maxplayers = 40
plugins = ['WorldEdit 5.4.2', 'iConomy 7.0', 'HawkEye 1.1.0', 'Vault 1.2.13-b148', 'PermissionsEx 1.19.1', 'LWC 4.3.1 (b767-git-MANUAL) (November 15, 2012)', 'WorldGuard 644-6df9c36', 'Essentials 2.9.3', 'dynmap 0.70.3-1298', 'Dynmap-WorldGuard 0.30', 'EssentialsProtect 2.9.3', 'AuthMe 2.6.7b5', 'Dynmap-Essentials 0.30', 'EssentialsSpawn 2.9.3', 'DragonTravel 1.7.1', 'ChestShop 3.46', 'EssentialsChat 2.9.3']
raw_plugins = CraftBukkit on Bukkit 1.4.5-R0.2: WorldEdit 5.4.2; iConomy 7.0; HawkEye 1.1.0; Vault 1.2.13-b148; PermissionsEx 1.19.1; LWC 4.3.1 (b767-git-MANUAL) (November 15, 2012); WorldGuard 644-6df9c36; Essentials 2.9.3; dynmap 0.70.3-1298; Dynmap-WorldGuard 0.30; EssentialsProtect 2.9.3; AuthMe 2.6.7b5; Dynmap-Essentials 0.30; EssentialsSpawn 2.9.3; DragonTravel 1.7.1; ChestShop 3.46; EssentialsChat 2.9.3
game_id = MINECRAFT
hostip = 194.8.253.48
software = CraftBukkit on Bukkit 1.4.5-R0.2

"""

class MinecraftWidget(object):

    def __init__(self, data, profile="hb"):
        self.data = data
        self.profile = profile

        self.init_config()
        self.init_colors()
        self.init_sizes()

    def init_config(self):
        self.config = ConfigParser.RawConfigParser(allow_no_value=True)
        self.config.read(os.path.join(ROOT, "script.ini"))

    def _parse(self, value):
        return tuple([int(x.strip()) for x in value.split(",")])

    def init_colors(self):
        self.COLOR_BG = self._parse(self.config.get(self.profile, "color_bg"))
        self.COLOR_TEXT = self._parse(self.config.get(self.profile, "color_text"))
        self.COLOR_TEXT_VALUE = self._parse(self.config.get(self.profile, "color_text_value"))
        self.COLOR_BAR_MAX = self._parse(self.config.get(self.profile, "color_bar_max"))
        self.COLOR_BAR_VALUE = self._parse(self.config.get(self.profile, "color_bar_value"))
        self.COLOR_GRAPH_MAX = self._parse(self.config.get(self.profile, "color_graph_max"))
        self.COLOR_GRAPH_VALUE = self._parse(self.config.get(self.profile, "color_graph_value"))
        self.COLOR_GRAPH_TEXT = self._parse(self.config.get(self.profile, "color_graph_text"))
        self.COLOR_GRAPH_LINE = self._parse(self.config.get(self.profile, "color_graph_line"))

    def init_sizes(self):
        self.SIZE_NAME = self._parse(self.config.get(self.profile, "name"))
        self.SIZE_IP = self._parse(self.config.get(self.profile, "ip"))
        self.SIZE_COUNT = self._parse(self.config.get(self.profile, "count"))
        self.SIZE_LOAD = self._parse(self.config.get(self.profile, "load"))
        self.SIZE_MEMORY = self._parse(self.config.get(self.profile, "memory"))
        self.SIZE_BAR_LOAD = self._parse(self.config.get(self.profile, "bar_load"))
        self.SIZE_BAR_MEMORY = self._parse(self.config.get(self.profile, "bar_memory"))
        self.SIZE_GRAPH = self._parse(self.config.get(self.profile, "graph"))

    def draw_name(self, x ,y, two_lines=False):
        self.draw.text((x, y), unicode("Server"), font=self.font, fill=self.COLOR_TEXT)
        if two_lines:
            offset_x = 0
            offset_y = 15
        else:
            offset_x = 42
            offset_y = 0
        self.draw.text((x+offset_x, y+offset_y), unicode(self.data["name"]), font=self.font, fill=self.COLOR_TEXT_VALUE)

    def draw_ip(self, x ,y, two_lines=False):
        if two_lines:
            self.draw.text((x, y), unicode("IP"), font=self.font, fill=self.COLOR_TEXT)
        #+20
        if two_lines:
            offset_x = 0
            offset_y = 15
        else:
            offset_x = 0
            offset_y = 0
        self.draw.text((x+offset_x, y+offset_y), unicode("%s:%s" % (self.data["ip"], self.data["port"])), font=self.font, fill=self.COLOR_TEXT_VALUE)

    def draw_count(self, x ,y, two_lines=False):
        self.draw.text((x, y), unicode("Hráči"), font=self.font, fill=self.COLOR_TEXT)
        if two_lines:
            offset_x = 0
            offset_y = 15
        else:
            offset_x = 32
            offset_y = 0
        self.draw.text((x+offset_x, y+offset_y), unicode(self.data["count"]), font=self.font, fill=self.COLOR_TEXT_VALUE)

    def draw_load(self, x ,y, load, two_lines=False):
        self.draw.text((x, y), unicode("Zatížení"), font=self.font, fill=self.COLOR_TEXT)
        if two_lines:
            offset_x = 0
            offset_y = 15
        else:
            offset_x = 50
            offset_y = 0
        self.draw.text((x+offset_x, y+offset_y), unicode("%.2f %%" % load), font=self.font, fill=self.COLOR_TEXT_VALUE)

    def draw_memory(self, x ,y, two_lines=False):
        self.draw.text((x, y), unicode("Paměť"), font=self.font, fill=self.COLOR_TEXT)
        if two_lines:
            offset_x = 0
            offset_y = 15
        else:
            offset_x = 40
            offset_y = 0
        self.draw.text((x+offset_x, y+offset_y), unicode("%s/%s MB" % (self.data["memory"], self.data["memory_max"])), font=self.font, fill=self.COLOR_TEXT_VALUE)

    def draw_graphs(self, x, y, values, height=40, multiplicator=1, two_lines=False):
        width=len(values)
        ceil = max(values)*1.2
        if not ceil: ceil = 1
        self.draw.rectangle((x, y, x+width*(multiplicator+1)+2, y+height+2), fill=self.COLOR_GRAPH_MAX)
        offset = 1
        for i, value in enumerate(values):
            for offset_local in range(multiplicator):
                self.draw.line((x+1+i+offset, y+height-1, x+1+i+offset, y+height-1-(float(value)/ceil*height)), fill=self.COLOR_GRAPH_VALUE)
                offset += 1
        self.draw.text((x+2, y+height-14), unicode("0"), font=self.font, fill=self.COLOR_GRAPH_TEXT)
        self.draw.text((x+2, y+2), unicode("%.1f" % ceil), font=self.font, fill=self.COLOR_GRAPH_TEXT)
        self.draw.line((x+2, y+height, x+width+width*multiplicator, y+height), fill=self.COLOR_GRAPH_LINE)
        self.draw.line((x+2, y+2, x+width+width*multiplicator, y+2), fill=self.COLOR_GRAPH_LINE)
        #self.draw.text(((x+(width+width*multiplicator)/2-8), y+height), unicode("24h"), font=self.font, fill=self.COLOR_GRAPH_TEXT)

    def draw_bar(self, x, y, percent, width=118, two_lines=False):
        self.draw.rectangle((x, y, x+width, y+14), fill=self.COLOR_BAR_MAX)
        self.draw.rectangle((x+1, y+1, x+((width-1)/100.0)*percent, y+13), fill=self.COLOR_BAR_VALUE)

    def get_image(self):
        self.im = Image.open(os.path.join(ROOT, "bg", self.config.get(self.profile, "bg")))
        self.draw = ImageDraw.Draw(self.im)
        self.font = ImageFont.truetype(os.path.join(ROOT, "PT_Sans-Web-Regular.ttf"), 12, encoding="unicode")

        two_lines = self.config.getboolean(self.profile, "two_lines")

        self.draw_name(self.SIZE_NAME[0], self.SIZE_NAME[1], two_lines)
        self.draw_ip(self.SIZE_IP[0], self.SIZE_IP[1], two_lines)
        self.draw_count(self.SIZE_COUNT[0], self.SIZE_COUNT[1], two_lines)
        load = float(self.data["load"])/float(self.data["cpu_count"])*100
        self.draw_load(self.SIZE_LOAD[0], self.SIZE_LOAD[1], load, two_lines)
        self.draw_memory(self.SIZE_MEMORY[0], self.SIZE_MEMORY[1], two_lines)
        self.draw_bar(self.SIZE_BAR_LOAD[0], self.SIZE_BAR_LOAD[1], int(load), self.SIZE_BAR_LOAD[2])
        self.draw_bar(self.SIZE_BAR_MEMORY[0], self.SIZE_BAR_MEMORY[1], float(self.data["memory"])/float(self.data["memory_max"])*100, self.SIZE_BAR_MEMORY[2])
        if self.data["history"]:
            self.draw_graphs(self.SIZE_GRAPH[0], self.SIZE_GRAPH[1], self.data["history"], self.SIZE_GRAPH[2], self.SIZE_GRAPH[3])

        output = StringIO.StringIO()
        self.im.save(output, "PNG")
        return output.getvalue()

#def main(hostname, port):
#    collector = MinecraftWidgetCollector(hostname, port)
#    collector.save_data()
#    for profile in ('vb', 'vw', 'hb', 'hw'):
#        widget = MinecraftWidget(collector.get_last(), profile)
#        with open(os.path.join(config["data_dir"], "www", "widget_%s_%s_%d.png" % (profile, collector.addr[0], collector.addr[1])), "w") as f:
#            f.write(widget.get_image())

#if __name__ == "__main__":
#    main("194.8.253.48", 25565)


"""
This is a template for creating custom BatchExpectations.
For detailed instructions on how to use it, please see:
    https://docs.greatexpectations.io/docs/guides/expectations/creating_custom_expectations/how_to_create_custom_batch_expectations
"""

from typing import Dict, Optional

from great_expectations.core.expectation_configuration import ExpectationConfiguration
from great_expectations.exceptions import InvalidExpectationConfigurationError
from great_expectations.execution_engine import (
    ExecutionEngine,
    PandasExecutionEngine,
    SparkDFExecutionEngine,
    SqlAlchemyExecutionEngine,
)
from great_expectations.expectations.expectation import BatchExpectation
from great_expectations.expectations.metrics.metric_provider import (
    MetricConfiguration,
    metric_value,
)
from great_expectations.expectations.metrics.table_metric_provider import (
    TableMetricProvider,
)

# This class defines a Metric to support your Expectation.
# For most BatchExpectations, the main business logic for calculation will live in this class.
class BatchMeetsSomeCriteria(TableMetricProvider):
    # This is the id string that will be used to reference your Metric.
    metric_name = "METRIC NAME GOES HERE"

    # This method implements the core logic for the PandasExecutionEngine
    @metric_value(engine=PandasExecutionEngine)
    def _pandas(
        cls,
        execution_engine,
        metric_domain_kwargs,
        metric_value_kwargs,
        metrics,
        runtime_configuration,
    ):
        raise NotImplementedError

    # @metric_value(engine=SqlAlchemyExecutionEngine)
    # def _sqlalchemy(
    #         cls,
    #         execution_engine,
    #         metric_domain_kwargs,
    #         metric_value_kwargs,
    #         metrics,
    #         runtime_configuration,
    # ):
    #    raise NotImplementedError

    # @metric_value(engine=SparkDFExecutionEngine)
    # def _spark(
    #         cls,
    #         execution_engine,
    #         metric_domain_kwargs,
    #         metric_value_kwargs,
    #         metrics,
    #         runtime_configuration,
    # ):
    #    raise NotImplementedError

    @classmethod
    def _get_evaluation_dependencies(
        cls,
        metric: MetricConfiguration,
        configuration: Optional[ExpectationConfiguration] = None,
        execution_engine: Optional[ExecutionEngine] = None,
        runtime_configuration: Optional[dict] = None,
    ):
        return {
            "table.columns": MetricConfiguration(
                "table.columns", metric.metric_domain_kwargs
            ),
        }

# This class defines the Expectation itself
# The main business logic for calculation lives here.
class ExpectBatchToMeetSomeCriteria(BatchExpectation):
    """TODO: add a docstring here"""

    # These examples will be shown in the public gallery.
    # They will also be executed as unit tests for your Expectation.
    examples = []

    # This is a tuple consisting of all Metrics necessary to evaluate the Expectation.
    metric_dependencies = ("METRIC NAME GOES HERE",)

    # This a tuple of parameter names that can affect whether the Expectation evaluates to True or False.
    success_keys = ()

    # This dictionary contains default values for any parameters that should have default values.
    default_kwarg_values = {}

    def validate_configuration(
        self, configuration: Optional[ExpectationConfiguration]
    ) -> None:
        """
        Validates that a configuration has been set, and sets a configuration if it has yet to be set. Ensures that
        necessary configuration arguments have been provided for the validation of the expectation.

        Args:
            configuration (OPTIONAL[ExpectationConfiguration]): \
                An optional Expectation Configuration entry that will be used to configure the expectation
        Returns:
            None. Raises InvalidExpectationConfigurationError if the config is not validated successfully
        """

        super().validate_configuration(configuration)
        configuration = configuration or self.configuration

        # # Check other things in configuration.kwargs and raise Exceptions if needed
        # try:
        #     assert (
        #         ...
        #     ), "message"
        #     assert (
        #         ...
        #     ), "message"
        # except AssertionError as e:
        #     raise InvalidExpectationConfigurationError(str(e))

    # This method performs a validation of your metrics against your success keys, returning a dict indicating the success or failure of the Expectation.
    def _validate(
        self,
        configuration: ExpectationConfiguration,
        metrics: Dict,
        runtime_configuration: dict = None,
        execution_engine: ExecutionEngine = None,
    ):
        raise NotImplementedError

    # This object contains metadata for display in the public Gallery
    library_metadata = {
        "tags": [],  # Tags for this Expectation in the Gallery
        "contributors": [  # Github handles for all contributors to this Expectation.
            "@your_name_here",  # Don't forget to add your github handle here!
        ],
    }

if __name__ == "__main__":
    ExpectBatchToMeetSomeCriteria().print_diagnostic_checklist()


from django.views import View
from django.http import HttpResponse, JsonResponse, HttpResponseForbidden
from django_redis import get_redis_connection
from random import randint

from MD.libs.captcha.captcha import captcha
from .constants import VERIFICATION_CODE_EXPIRE
from MD.utils.response_code import RETCODE
from celery_tasks.sms.tasks import send_sms_code
import logging

logger = logging.getLogger('django')

class VerificationCodeView(View):
    """图形验证码"""

    def get(self, request, uuid):
        name, text, code_image = captcha.generate_captcha()
        # redis_conn = get_redis_connection('verification_code')
        # redis_conn.setex(uuid, VERIFICATION_CODE_EXPIRE, text)
        get_redis_connection('verification_code').setex(f'v_code_{uuid}', VERIFICATION_CODE_EXPIRE, text)
        return HttpResponse(code_image, content_type='image/png')

class SMSCodeView(View):
    """发短信验证码"""

    # url = this.host + '/verification/sms_codes/' + this.mobile + '/?v_code=' + this.image_code + '&uuid=' + this.uuid;
    def get(self, request, phone_num):
        redis_conn = get_redis_connection('verification_code')
        if redis_conn.get('send_flag_%s' % phone_num):
            return JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '频繁发送短信'})

        # 接收前端传入的数据
        x = request.GET
        v_code = x.get('v_code')
        uuid = x.get('uuid')

        # 校验
        if not all([v_code, uuid]):
            return HttpResponseForbidden('缺少参数')

        redis_v_code = redis_conn.get(f'v_code_{uuid}')
        redis_conn.delete(f'v_code_{uuid}')
        if not redis_v_code:
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '验证码已过期'})
        redis_v_code = redis_v_code.decode()

        if v_code.lower() != redis_v_code.lower():
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '验证码输入错误'})

        # 发送短信验证码
        sms_code = '%06d' % randint(0, 999999)
        logger.info(sms_code)
        # 创建redis管道
        pl = redis_conn.pipeline()
        # 将短信验证码缓存到redis
        pl.setex('sms_%s' % phone_num, 300, sms_code)
        # 当前手机号发过短信后,向redis存储一个发送过的标记
        pl.setex('send_flag_%s' % phone_num, 60, 1)
        # 执行管道
        pl.execute()
        # send_sms_code(phone_num, sms_code)
        send_sms_code.delay(phone_num, sms_code)  # 将发短信的函数内存添加到仓库中,让worker去执行
        # 响应
        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})


import re, argparse
from smartcard.System import readers
import datetime, sys
import requests
import urllib
import json
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import  CardRequest
from smartcard.util import toHexString
url_prefix="http://certificateweb.sumato.tech/api/v1/"
url_all_certs_init=url_prefix+"studentsall"
url_all_certs_complete=url_prefix+"students/print/completed"
url_cert_status=url_prefix+"print/status/"
url_cert_pdf=url_prefix+"print/pdf/"#provide certificate id
url_update_cert_complete=url_prefix+"print/complete/" #provide certificate id
COMMAND = [0xFF, 0xCA, 0x00, 0x00, 0x00] #handshake cmd needed to initiate data transfer
LOAD_AUTH_KEY=[0xFF,0x82,0x00,0x00,0x06,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]#Load authentication key
AUTHENTICATE_COMMAND=[0xFF, 0x88, 0x00, 0x04, 0x60, 0x00]#authenticate
# get all the available readers
r = readers()
print ("Available readers:", r)
reader=r[0]

def getCertificateListInit():
    r=requests.get(url_all_certs_init)
    students=r.json()
    return students
def getCertPdf(certId):
    urllib.request.urlretrieve(url_cert_pdf+certId,"cert_"+certId+".pdf")
    return 1
def updateCertComplete(certId):
    r.requests.get(url_update_cert_complete+certId)
    return 1

def authenticate():
    connection = reader.createConnection()
    status_connection = connection.connect()
    connection.transmit(COMMAND)
    #Read command [FF, B0, 00, page, #bytes]
    resp=connection.transmit(LOAD_AUTH_KEY)
    if resp[1]==144:
        print("Authentication key loaded")
    else:
        print("Problem loading auth key "+resp)
    resp=connection.transmit(AUTHENTICATE_COMMAND)
    if resp[1]==144:
        print("Authentication done")
    else:
        print("Problem while authenticating "+str(resp))

def readTag(page):
            connection = reader.createConnection()
            status_connection = connection.connect()
            connection.transmit(COMMAND)
            #Read command [FF, B0, 00, page, #bytes]
            resp = connection.transmit([0xFF, 0xB0, 0x00, 0x04, 0x04])
            if resp[1]==144:
                print(resp)
            else:
                print("Couldnt read "+resp)
           # dataCurr = stringParser(resp)

            #only allows new tags to be worked so no duplicates

def writeTag(value):
                page=4
                cardtype=AnyCardType()
                cardreq=CardRequest(timeout=100, cardType=cardtype)
                cardservice=cardreq.waitforcard()
                cardservice.connection.connect()
                print(toHexString(cardservice.connection.getATR()))
                WRITE_COMMAND = [0xFF,0xD6,0x00,0x04,0x04,int(value[0:2],16),int(value[2:4],16),int(value[4:6],16),int(value[6:8],16)]
                print(WRITE_COMMAND)
                #[0xFF, 0xD6, 0x00, int(page), 0x04, int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16), int(value[6:8], 16)]
                #Let's write a page Page 9 is usually 00000000
                #resp = cardservice.connection.transmit(AUTHENTICATE_COMMAND)
                #print(resp)
                resp = cardservice.connection.transmit(WRITE_COMMAND)
                print(resp)
                if resp[1] == 144:
                    print ("Wrote " + str(value))
                else:
                    print("Error occured during write operation")
def printToNfc(data):
    #authenticate()
    writeTag(data)

certs=getCertificateListInit()
print(certs[0]['printjob']['certificate_id'])
for cert in certs:
    cert_id=cert['printjob']['certificate_id']
    print(cert_id)
    printToNfc(cert_id)
    getCertPdf(cert['printjob']['certificate_id'])
readTag(4)
#getCertPdf('9315224')


import click
import numpy as np
import pandas as pd

from typing import Union, List
from pathlib import Path
from loguru import logger
from scipy.stats import norm, lognorm

from vivarium_public_health.risks.data_transformations import pivot_categorical

from vivarium_csu_sanofi_multiple_myeloma.constants import metadata

def len_longest_location() -> int:
    """Returns the length of the longest location in the project.

    Returns
    -------
       Length of the longest location in the project.
    """
    return len(max(metadata.LOCATIONS, key=len))

def sanitize_location(location: str):
    """Cleans up location formatting for writing and reading from file names.

    Parameters
    ----------
    location
        The unsanitized location name.

    Returns
    -------
        The sanitized location name (lower-case with white-space and
        special characters removed.

    """
    # FIXME: Should make this a reversible transformation.
    return location.replace(" ", "_").replace("'", "_").lower()

def delete_if_exists(*paths: Union[Path, List[Path]], confirm=False):
    paths = paths[0] if isinstance(paths[0], list) else paths
    existing_paths = [p for p in paths if p.exists()]
    if existing_paths:
        if confirm:
            # Assumes all paths have the same root dir
            root = existing_paths[0].parent
            names = [p.name for p in existing_paths]
            click.confirm(f"Existing files {names} found in directory {root}. Do you want to delete and replace?",
                          abort=True)
        for p in existing_paths:
            logger.info(f'Deleting artifact at {str(p)}.')
            p.unlink()

def read_data_by_draw(artifact_path: str, key : str, draw: int) -> pd.DataFrame:
    """Reads data from the artifact on a per-draw basis. This
    is necessary for Low Birthweight Short Gestation (LBWSG) data.

    Parameters
    ----------
    artifact_path
        The artifact to read from.
    key
        The entity key associated with the data to read.
    draw
        The data to retrieve.

    """
    key = key.replace(".", "/")
    with pd.HDFStore(artifact_path, mode='r') as store:
        index = store.get(f'{key}/index')
        draw = store.get(f'{key}/draw_{draw}')
    draw = draw.rename("value")
    data = pd.concat([index, draw], axis=1)
    data = data.drop(columns='location')
    data = pivot_categorical(data)
    return data

class LogNormalHazardRate:
    """Defines an instance of a lognormal hazard rate normal distribution.
    Parameters
    ----------
    hr
        mean of distribution
    hr_lower
        lower bound the lognormal distribution
    hr_upper
        upper bound of lognormal distribution
    Returns
    -------
        An object with parameters for scipy.stats.lognorm
    """

    def __init__(self, hr: float, hr_lower: float, hr_upper: float):
        self.hr = hr
        self.hr_upper = hr_upper
        q_975_stdnorm = norm().ppf(0.975)
        mu = np.log(self.hr)
        sigma = (np.log(self.hr_upper) - mu) / q_975_stdnorm
        assert sigma > 0, "look for typos"
        self.hr_distribution = lognorm(s=sigma, scale=self.hr)

    def get_random_variable(self, percentile: float) -> float:
        """Gets a single random draw from a log normal hazard rate distribution.
        Parameters
        ----------
        percentile
            Percentile for sample.
        Returns
        -------
            The random variate from the log normal hazard rate distribution.
        """
        return self.hr_distribution.ppf(percentile)


import argparse
import pandas as pd
import os
from datetime import datetime

# in progress

def setup_parser(parser):
    subparsers = parser.add_subparsers(help="description of all parsers:", dest="command")

    parser_add = subparsers.add_parser(name="add", help="""Provide task to list ,example(task2.py add -n name1 -dl 2020-02-15 -d exemplary task),
                                                        remember about proper format of date YYYY-MM-DD,and that each string having more than one word
                                                        must be inside quotation mark """)
    parser_add.set_defaults(func=add)
    parser_add.add_argument("-n", "--name", dest="name", help="name", required=True)
    parser_add.add_argument("-dl", "--deadline", dest="deadline", help="deadline YYYY-MM_DD", required=False, type=lambda d: datetime.strptime(d, '%Y-%m-%d'))
    parser_add.add_argument("-d", "--description", dest="description", help="description", required=False)

    parser_update = subparsers.add_parser(name="update", help="""Update chosen task by its  hash value(visible using list function),remember about proper format of date YYYY-MM-DD,
                                                                and that each string having more than one word must be inside quotation mark """)
    parser_update.set_defaults(func=update)
    parser_update.add_argument("-n", "--name", dest="name", help="name", required=False)
    parser_update.add_argument("-dl", "--deadline", dest="deadline", help="deadline YYYY-MM_DD", required=False, type=lambda d: datetime.strptime(d, '%Y-%m-%d'))
    parser_update.add_argument("-d", "--description", dest="description", help="description", required=False)
    parser_update.add_argument("-hs", "--hash", dest="hash", help="hash made by index value", required=True, type=int)

    parser_remove = subparsers.add_parser(name="remove", help="remove task from list using hash value(hash value "
                                                              "visible using list function)")
    parser_remove.add_argument('hash', help='hash value of the task intended for removing ')
    parser_remove.set_defaults(func=remove)

    parser_list = subparsers.add_parser(name="list", help="display tasks in list,options to choose:-all (displaying "
                                                          "all tasks),-today(displaying tasks with today's date)  ")
    parser_list.set_defaults(func=listing)
    parser_list.add_argument("-all", "--all", action='store_true')
    parser_list.add_argument("-today", "--today", action='store_true')

def add(args):
    df = pd.DataFrame({'name': [args.name], 'deadline': [args.deadline], 'description': [args.description]})
    df['hash'] = hash(str(args.name) + str(args.deadline) + str(args.description))
    df.set_index('hash', inplace=True, drop=False)
    with open('task.csv', 'a'):
        if os.path.getsize('task.csv') == 0:
            df.to_csv('task.csv', header=True, index=False)
        else:
            df.to_csv('task.csv', mode='a', header=False, index=False)

def update(args):
    df2 = pd.read_csv('task.csv')
    df2.set_index('hash', inplace=True, drop=False)
    if args.name != None:
        df2.at[args.hash, 'name'] = args.name
    if args.deadline != None:
        df2.at[args.hash, 'deadline'] = args.deadline.date()
    if args.deadline != None:
        df2.at[args.hash, 'description'] = args.description

    df2.to_csv('task.csv', header=True, index=False)

def listing(args):
    if args.all:
        print(pd.read_csv('task.csv'))
    if args.today:
        df = pd.read_csv('task.csv')
        df2 = df[(df['deadline']==str(datetime.today().date()))]
        df2.reset_index(drop=True,inplace=True)
        print(df2)

def remove(args):
    df = pd.read_csv('task.csv')
    df = df[df.hash != int(args.hash)]
    df.to_csv('task.csv',header=True, index=False)

def main():
    parser = argparse.ArgumentParser(description="List of tasks")
    setup_parser(parser)
    res = parser.parse_args()
    res.func(res)

main()


# coding = utf-8
"""
@author: zhou
@time:2019/1/31 17:42
"""

import os
from util import change_labels, get_data
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.externals import joblib
from sklearn import metrics

model_save_path = r'./model'
d = r'.\text_classification-master\text classification\stop'
txt = os.path.join(d, 'stopword.txt')

class Radish(object):
    def __init__(self, labels=None):
        self.labels = labels
        self.train_vocabulary = None
        self.clf = None
        self.stop_words = [line.strip() for line in open(txt, encoding='utf-8').readlines()]

    def train(self, traindir, labels):
        if not os.path.isdir(traindir):
            raise ValueError('The directory' + traindir + 'does not exist!')

        self.labels = change_labels.change_labels(labels)
        train_labels = change_labels.change_labels(self.labels)
        t_data, t_target = get_data.getdata(traindir, labels, self.stop_words)
        tv = TfidfVectorizer()
        train_data_features = tv.fit_transform(t_data)
        self.train_vocabulary = tv.vocabulary_
        clf = MultinomialNB(alpha=0.001)
        # print(train_data_features)
        print(train_labels)
        clf.fit(train_data_features, t_target)
        self.clf = clf
        save_path_name = os.path.join(model_save_path, "NB" + '.pkl')
        joblib.dump(clf, save_path_name)
        """测试开始"""
        """
        dirt = r'.\text_classification-master\text classification\test'
        test_data, test_target = get_data.gettestdata(dirt, '女性')
        tv = TfidfVectorizer(vocabulary=self.train_vocabulary)
        t_data_features = tv.fit_transform(test_data)
        predicted_label = clf.predict(t_data_features)
        print(metrics.accuracy_score(test_target, predicted_label))
        """
        print('Train finish!')

    def test(self, testdir, label):
        if not os.path.isdir(testdir):
            raise ValueError('The directory' + testdir + 'does not exist!')

        self.labels = change_labels.change_labels(label)
        test_data, test_target = get_data.gettestdata(testdir, label, self.stop_words)
        tv = TfidfVectorizer(sublinear_tf=True, vocabulary=self.train_vocabulary)
        t_data_features = tv.fit_transform(test_data)
        # clf = joblib.load(model_save_path + "NB" + '.pkl')
        clf = self.clf
        predicted_label = clf.predict(t_data_features)
        print("%s准确率：" % label, metrics.accuracy_score(test_target, predicted_label))

if __name__ == "__main__":
    labels = ['女性', '体育', '文学', '校园']
    dirf = r'.\text_classification-master\text classification\train'
    dirt = r'.\text_classification-master\text classification\test'
    r = Radish()
    r.train(dirf, labels)
    r.test(dirt, '女性')
    r.test(dirt, '体育')
    r.test(dirt, '文学')
    r.test(dirt, '校园')


""" Test that all TFmodels can be constructed. Some of the bigger models are omitted due to slow initialization. """
# pylint: disable=import-error, no-name-in-module, unused-import
# pylint: disable=redefined-outer-name
import pytest

from batchflow.models.tf import LinkNet, UNet, VNet, \
                                FCN8, FCN16, FCN32, \
                                DenseNetFC56, DenseNetFC67, DenseNetFC103, \
                                RefineNet, GCN, DeepLabXS, DeepLabX8, DeepLabX16, \
                                VGG16, VGG19, VGG7, \
                                ResNet18, ResNet34, ResNet50, ResNet101, ResNet152, \
                                ResNeXt18, ResNeXt34, ResNeXt50, ResNeXt101, ResNeXt152, \
                                Inception_v1, InceptionResNet_v2, Inception_v3, Inception_v4, \
                                SqueezeNet, MobileNet, MobileNet_v2, MobileNet_v3, MobileNet_v3_small, \
                                DenseNet121, DenseNet169, DenseNet201, DenseNet264, \
                                ResNetAttention56, ResNetAttention92, \
                                PyramidNet18, PyramidNet34, PyramidNet50, PyramidNet101, \
                                XceptionS, Xception41, Xception64, \
                                EfficientNetB0, EfficientNetB1, EfficientNetB2, EfficientNetB3, \
                                EfficientNetB4, EfficientNetB5, EfficientNetB6, EfficientNetB7, \
                                PSPNet18, PSPNet34, PSPNet50

MODELS_CLF = [
    VGG7, VGG16, VGG19,
    ResNet18, ResNet34, # ResNet50, ResNet101, ResNet152,
    ResNeXt18, ResNeXt34, # ResNeXt50, ResNeXt101, ResNeXt152,
    Inception_v1,
    # InceptionResNet_v2, Inception_v3, Inception_v4, # fail
    SqueezeNet,
    MobileNet, MobileNet_v2, MobileNet_v3, MobileNet_v3_small,
    DenseNet121,  # DenseNet169, DenseNet201, DenseNet264,
    ResNetAttention56, # ResNetAttention92,
    PyramidNet18, PyramidNet34, # PyramidNet50, PyramidNet101,
    XceptionS, Xception41, # Xception64
    EfficientNetB0, EfficientNetB1, # EfficientNetB2, EfficientNetB3, \
    # EfficientNetB4, EfficientNetB5, EfficientNetB6, EfficientNetB7
]

MODELS_SEG = [
    LinkNet,
    UNet,
    VNet,
    FCN8, FCN16, FCN32,
    DenseNetFC56, # DenseNetFC67, DenseNetFC103,
    RefineNet,
    GCN,
    DeepLabXS, DeepLabX8, # DeepLabX16,
    PSPNet18, # PSPNet34, PSPNet50
]

@pytest.fixture()
def base_config_clf():
    """ Fixture to hold default configuration for classification. """
    config = {'inputs/images/shape': (16, 16, 1),
              'inputs/labels/classes': 10,
              'initial_block/inputs': 'images',
              'loss': 'ce'}
    return config

@pytest.fixture()
def base_config_segment():
    """ Fixture to hold default configuration for segmentation. """
    config = {
        'inputs': {'images': {'shape': (16, 16, 1)},
                   'masks': {'name': 'targets', 'shape': (16, 16, 1)}},
        'initial_block': {'inputs': 'images'},
        'loss': 'mse'
    }
    return config

@pytest.mark.slow
@pytest.mark.parametrize('model', MODELS_CLF)
def test_clf(base_config_clf, model):
    """ Test models for classification """
    _ = model(base_config_clf)

@pytest.mark.slow
@pytest.mark.parametrize('model', MODELS_SEG)
def test_seg(base_config_segment, model):
    """ Test models for segmentation """
    _ = model(base_config_segment)


from django.forms import Form,ModelForm,widgets, ModelChoiceField,ChoiceField
from .models import *
from django.forms import IntegerField

class PostForm(ModelForm):
    class Meta:
        model=ArticleSheet
        fields=('title','content','tag','type')
        widgets={
            'title':widgets.TextInput(attrs={'placeholder':'title'}),
            'content':widgets.Textarea(attrs={'placeholder':'content'}),
            'tag':widgets.TextInput(attrs={'placeholder':'tag'}),
            'type':widgets.Select(),
        }


import os
from shutil import copyfile
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--input_dataset', help='File path of dataset.', required=True)
parser.add_argument('--output_dir', help='File path of output folder.', required=True)
args = parser.parse_args()

def create_folders(input_dir, train_output_dir, test_output_dir):
  training_classes = {}
  for class_name in os.listdir(input_dir):
      train_folder_name = os.path.join(train_output_dir, class_name)
      test_folder_name = os.path.join(test_output_dir, class_name)
      if not os.path.exists(train_folder_name):
          os.makedirs(train_folder_name)
      if not os.path.exists(test_folder_name):
          os.makedirs(test_folder_name)
      class_dir_name = os.path.join(input_dir, class_name)
      for image_name in os.listdir(class_dir_name):
          input_file_name = os.path.join(class_dir_name, image_name)
          train_output_file_name = os.path.join(train_folder_name, image_name)
          test_output_file_name = os.path.join(test_folder_name, image_name)
          if class_name in training_classes and training_classes[class_name] >= 19:
              copyfile(input_file_name, test_output_file_name)
          else:
              copyfile(input_file_name, train_output_file_name)
              if class_name not in training_classes:
                  training_classes[class_name] = 1
              else:
                  training_classes[class_name] += 1

input_dir = args.input_dataset
train_output_dir = os.path.join(args.output_dir, "Train")
test_output_dir = os.path.join(args.output_dir, "Test")
if not os.path.exists(train_output_dir):
    os.makedirs(train_output_dir)
if not os.path.exists(test_output_dir):
    os.makedirs(test_output_dir)

create_folders(input_dir, train_output_dir, test_output_dir)

#204
#210
#439


from torch.utils.data import DataLoader
from utils.constants import *
from typing import List, Tuple
from models.enums.Genre import Genre
import numpy as np
from torch.utils.data import DataLoader

from utils.constants import *

class Tester:
    # input: both network models
    # return average loss, acc; etc.

    def __init__(self,
                 model,
                 data_loader_test: DataLoader,
                 data_loader_sentence,
                 model_state_path='',
                 device='cpu'):

        # the saved network as an object
        self.model = model
        self.model_state_path = model_state_path
        self.data_loader_test = data_loader_test
        self.data_loader_sentence = data_loader_sentence
        self.device = device
        self.model.eval()

    def test(self):
        """
         main testing function
        """

        try:
            # loading saved trained weights
            if self.model_state_path:  # because if we are testing a CombinedClassifier the states are already loaded
                self.model.load_state_dict(torch.load(self.model_state_path))

            log = {'final_scores': [], 'combination': {
                'classifier_scores': [], 'vaes_scores': []},
                   'accuracies_per_batch': [],
                   'true_targets': [],
                   'length_lstm': [],
                   'length_vae': []
                   }

            for i, items in enumerate(zip(self.data_loader_test, self.data_loader_sentence)):
                (batch, targets, lengths), (batch2, targets2, lengths2) = items

                accuracy_batch = self._batch_iteration(batch, targets, lengths, log, (batch2, targets2, lengths2), i)

                log['accuracies_per_batch'].append(accuracy_batch)
                log['true_targets'].append(targets)

                # if i % 100 == 0:
                    # print('combined accuracy so far', np.mean(log['accuracies_per_batch']), i)

            return log
        except KeyboardInterrupt as e:
            print(f"Killed by user: {e}")

            return False
        except Exception as e:
            print(e)

            raise e

    def _batch_iteration(self,
                         batch: torch.Tensor,
                         targets: torch.Tensor,
                         lengths: torch.Tensor,
                         log,
                         sentencebatch, step):
        """
        runs forward pass on batch and backward pass if in train_mode
        """

        if (step % 100) == 0:
            print(step)

        batch2, targets2, lengths2 = sentencebatch
        batch = batch.to(self.device).detach()
        targets = targets.to(self.device).detach()
        lengths = lengths.to(self.device).detach()

        if batch2 is not None:
            batch2 = batch2.to(self.device).detach()
            targets2 = targets2.to(self.device).detach()
            lengths2 = lengths2.to(self.device).detach()

        output = self.model.forward(batch, targets, lengths, (batch2, targets2, lengths2), step)

        final_scores_per_class = output
        if 'Combined' in type(self.model).__name__:
            final_scores_per_class, (score_classifier, score_elbo) = output
            log['combination']['classifier_scores'].append(score_classifier.detach())
            log['combination']['vaes_scores'].append(score_elbo.detach())

        _, classifications = score_classifier.detach().max(dim=-1)
        accuracy = (targets.eq(classifications)).float().mean().item()

        log['final_scores'].append(final_scores_per_class.detach())
        log['length_lstm'].append(lengths.detach())
        log['length_vae'].append(lengths2.detach())

        return accuracy


import json
import requests
from decouple import config

series = json.load(open("series.json"))

request_url = config("SERIES_URL") + "series" + "?api-key=" + config("SERIES_API_KEY")

for serie in series:
    title = serie['title']
    data = json.dumps({
        'tvdbId': serie['tvdbId'],
        'title': serie['title'],
        'profileId': serie['profileId'],
        'titleSlug': serie['titleSlug'],
        'images': serie['images'],
        'seasons': serie['seasons'],
        'seasonFolder': serie['seasonFolder'],
        'monitored': serie['monitored'],
        'path': serie['path'],
    })
    response = requests.post(url=request_url, data=data)
    if response.status_code is not 201:
        print(f'Failed to add \'{title}\'')
        print(response.text)
    else:
        print(f'Added \'{title}\'')


import random

from marlgrid import envs
import gym
import numpy as np
from marlgrid.envs import env_from_config

# from marlgrid.envs.empty import EmptyColorMultiGrid
from marlgrid.envs.hallways import HallWaysMultiGrid

def main():
    env = gym.make(
        "MarlGrid-2AgentComms15x15-v0"
    )  # ('MarlGrid-2AgentEmptyColor15x15-v0')

    env.reset()

    obs_list = env.reset()
    env.render()
    done = False
    steps = 0
    # actions = [[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[0,5],[5,2],
    #            [2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[2,2],[0,0],
    #            [2,2],[2,2],[2,2],[2,2],[2,2],[5,2],[2,5],[5,5]]
    # actions = [[0,0],[0,0],[2,0], [0,0], [2,0], [0,0],[0,2],[2,0]]
    actions = [
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 0],
        [0, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 0],
    ]

    actions = [
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [1, 1],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [2, 2],
        [0, 0],
        [2, 2],
        [2, 0],
    ]
    # while not done:
    for action in actions:
        # OPTIONAL: render the whole scene + birds eye view
        # agent_actions = np.random.randint(env.action_space[0].n, size=len(env.action_space))
        next_obs_list, rew_list, done, _ = env.step(action)
        steps += 1
        env.render()
        print(steps, action, rew_list, done)
        print()

def main2():
    env = gym.make(
        "MarlGrid-2AgentComms15x15-v0"
    )  # 'MarlGrid-2AgentComms15x15-v0')  # ('MarlGrid-2AgentEmptyColor15x15-v0')
    env = gym.wrappers.Monitor(
        env,
        "./recording",
        video_callable=lambda episode_id: episode_id == 0,
        force=True,
    )
    env.seed(55)
    env.reset()
    for _ in range(100):
        env.render()
        action = env.action_space.sample()
        obs, reward, done, _ = env.step(action)

    print("wait")

def main3():
    env_config = {
        "env_class": "HallWaysMultiGrid",  ##"EmptyColorMultiGrid",
        "grid_size": 15,
        "goal_colors": ["blue", "red", "blue", "red"],
        "goal_coordinates": [[7, 1], [8, 1], [8, 13], [7, 13]],
        "max_steps": 250,
        "respawn": False,
        "ghost_mode": False,
        "reward_decay": False,
    }
    player_interface_config = {
        "view_size": 7,
        "view_offset": 1,
        "view_tile_size": 1,
        "observation_style": "rich",
        "see_through_walls": False,
        "observe_position": True,
        "see_color_in_view_bool": True,
        "observe_orientation": True,
        "color": "orange",
    }
    p1 = dict(player_interface_config.copy())
    p2 = dict(player_interface_config.copy())
    p1["color"] = "orange"
    p2["color"] = "yellow"
    env_config["agents"] = [p1, p2]
    env = env_from_config(env_config)
    obs = env.reset()
    env.render()
    print(obs[0])

def main4():
    # env = gym.make("MarlGrid-2AgentCommGame15x15-v0")
    env_config = {
        "env_class": "CommunicationGameEnv",
        "grid_size": 15,
        "respawn": False,
        "ghost_mode": False,
        "reward_decay": False,
        "block_coordinates": [(1, 1), (13, 1), (1, 13), (13, 13)],
        "block_colors": ["blue", "red", "cyan", "pink"],
        "comm_blocks_coordinates": [(7, 4), (7, 10)],
        "max_steps": 250,
    }
    player_interface_config = {
        "view_size": 7,
        "view_offset": 1,
        "view_tile_size": 1,
        "observation_style": "rich",
        "see_through_walls": False,
        "observe_position": True,
        "see_color_in_view_bool": True,
        "observe_orientation": True,
        "color": "green",
    }
    p1 = dict(player_interface_config.copy())
    p2 = dict(player_interface_config.copy())
    # p1["color"] = "orange"
    # p2["color"] = "yellow"
    env_config["agents"] = [p1, p2]
    env = env_from_config(env_config)

    seed = 22
    np.random.seed(seed)
    random.seed(seed)
    env.seed(seed)
    env.reset()
    env.render()

    actions = [
        (0, 2),
        (2, 2),
        (2, 2),
        (2, 2),
        (2, 2),
        (0, 1),
        (2, 2),
        (2, 2),
        (1, 2),
        (1, 2),
        (1, 2),
    ]
    actions2 = [
        (0, 1),
        (2, 2),
        (2, 2),
        (2, 1),
        (2, 2),
        (1, 0),
        (2, 2),
        (2, 2),
        (2, 2),
        (2, 1),
        (2, 2),
        (2, 2),
        (2, 2),
        (2, 2),
        (2, 2),
        (2, 2),
    ]
    print("starting")
    for action in actions2:
        # action = env.action_space.sample()
        obs, reward, done, _ = env.step(action)
        print()
        env.render()
        print(
            "obs:",
            obs[0]["see_color_in_view"],
            obs[1]["see_color_in_view"],
            "reward",
            reward,
            "done",
            done,
        )
        if done:
            break

if __name__ == "__main__":
    main4()


import uuid
from django.db import models
from django.contrib.postgres.fields import JSONField, ArrayField

class BrainLocation(models.Model):
    """Gives a brain location in stereotaxic coordinates, plus other information about location."""
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=255)
    stereotaxic_coordinates = ArrayField(models.FloatField(blank=True, null=True), size=3) # [Anterior, Right, Down], relative to bregma in µm
    description = models.TextField() # e.g. area, layer, comments on how estimated
    allen_location_ontology = models.CharField(max_length=255, null=True, blank=True) # using their vocabulary

    def __str__(self):
        return self.name

class CoordinateTransformation(models.Model):
    """
    This defines how to convert from a local coordinate system (e.g. of a silicon probe) to stereotaxic coordinates.
    It is an affine transformation:
    stereotaxic_coordinates = origin + transformation_matrix*local_coordinates.
    The decription and allen_location_ontology apply to the coordinate origin (e.g. electrode tip).
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)
    allen_location_ontology = models.CharField(max_length=1000)

    origin = ArrayField(models.FloatField(blank=True, null=True), size=3)
    transformation_matrix = ArrayField(ArrayField(models.FloatField(blank=True, null=True), size=3), size=3)

    def __str__(self):
        return self.name


import requests

url = 'https://movie.douban.com/top250'
start = range(25, 250, 25)
for i in start:
    params = {
        'start': start,
        'filter': '',
    }
    headers = {
        'User-Agent': ' Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}

    res = requests.get(url=url, params=params, headers=headers)
    print(res.text)


#%%
'''
If we use (external) classification evalutation measures like F1 or
accuracy for clustering evaluation, problems may arise.
One way to fix is to perform label matching.
Here we performs kmeans clustering on the Iris dataset and proceed to use
the Hungarian (Munkres) algorithm to correct the mismatched labeling.
'''

import sys
import numpy as np
from sklearn.cluster import KMeans
from sklearn import datasets
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import scale

from munkres import Munkres

def make_cost_matrix(c1, c2):
    """
    """
    uc1 = np.unique(c1)
    uc2 = np.unique(c2)
    l1 = uc1.size
    l2 = uc2.size
    assert(l1 == l2 and np.all(uc1 == uc2))

    m = np.ones([l1, l2])
    for i in range(l1):
        it_i = np.nonzero(c1 == uc1[i])[0]
        for j in range(l2):
            it_j = np.nonzero(c2 == uc2[j])[0]
            m_ij = np.intersect1d(it_j, it_i)
            m[i,j] =  -m_ij.size
    return m

def translate_clustering(clt, mapper):
    return np.array([ mapper[i] for i in clt ])

def accuracy(cm):
    """computes accuracy from confusion matrix"""
    return np.trace(cm, dtype=float) / np.sum(cm)

def compute():
    """entry point"""
    from sklearn.datasets import fetch_openml
    data, classes = fetch_openml('mnist_784', version=1, return_X_y=True, data_home='mnist/')
    classes = np.asarray(list(map(int, classes)))
    data = np.asarray(data.astype(float))
    data = scale(data)
    algo = KMeans(n_clusters=10, random_state = 0)
    labels = algo.fit(data).labels_ # performs the algo and get the predicted labels
    num_labels = len(np.unique(classes))
    cm = confusion_matrix(classes, labels, labels=range(num_labels)) # gets the confusion matrix
    cost_matrix = make_cost_matrix(labels, classes)
    m = Munkres()
    indexes = m.compute(cost_matrix)
    mapper = { old: new for (old, new) in indexes }
    new_labels = translate_clustering(labels, mapper)
    new_cm = confusion_matrix(classes, new_labels, labels=range(num_labels))
    acc = accuracy(new_cm)
    return acc, new_cm, mapper
#%%
acc, new_cm, mapper = compute()

# %%


from transformers import AutoModelForQuestionAnswering, AutoTokenizer

mnames = ['deepset/bert-base-cased-squad2', 'deepset/electra-base-squad2', 'twmkn9/albert-base-v2-squad2', 'deepset/roberta-base-squad2', 'Primer/bart-squad2']

def wer_score(hyp, ref, print_matrix=False):
    import numpy as np
    N = len(hyp)
    M = len(ref)
    L = np.zeros((N,M))
    for i in range(0, N):
        for j in range(0, M):
            if min(i,j) == 0:
                L[i,j] = max(i,j)
            else:
                deletion = L[i-1,j] + 1
                insertion = L[i,j-1] + 1
                sub = 1 if hyp[i] != ref[j] else 0
                substitution = L[i-1,j-1] + sub
                L[i,j] = min(deletion, min(insertion, substitution))
    if print_matrix:
        print("WER matrix ({}x{}): ".format(N, M))
        print(L)
    return int(L[N-1, M-1])

def metrics(fname):
    # BLEU
    from nltk.translate.bleu_score import sentence_bleu, corpus_bleu
    scores = []
    f = open("poc_english.txt", "r")
    f2 = open(fname, "r")
    lines = f.readlines()
    cand = f2.readlines()
    for i in range(len(cand)):
        line = lines[i]
        candidate = []
        l = cand[i].lower().strip('\n')[1:len(cand[i])-2].split(", ")
        for item in l:
            item = item.strip('.').split(" ")
            candidate.append(item)
        arr = line.strip('.\n').split(" ")
        for i in range(len(arr)):
            arr[i] = arr[i].lower()
        reference = [arr]
        for c in candidate:
            # print(reference, c, ': ', sentence_bleu(reference, c, weights=(1,0)))
            scores.append(sentence_bleu(reference, c, weights=(1,0)))

    print("BLEU: " + str(sum(scores)/(1.0*len(scores))))

    # Word2Vec Cosine Similarity
    import torch
    import torch.nn.functional as F
    from sentence_transformers import SentenceTransformer
    import nltk
    from nltk import tokenize
    def similarity(par1, par2):
        transformer = SentenceTransformer('roberta-base-nli-stsb-mean-tokens')
        transformer.eval()
        par1 = tokenize.sent_tokenize(par1)
        vec1 = torch.Tensor(transformer.encode(par1))
        vec1 = vec1.mean(0)
        par2 = tokenize.sent_tokenize(par2)
        vec2 = torch.Tensor(transformer.encode(par2))
        vec2 = vec2.mean(0)
        cos_sim = F.cosine_similarity(vec1, vec2, dim=0)
        return cos_sim.item()

    scores = []
    f = open("poc_english.txt", "r")
    f2 = open(fname, "r")
    lines = f.readlines()
    cand = f2.readlines()
    for i in range(len(cand)):
        line = lines[i]
        candidate = []
        l = cand[i].lower().strip('\n')[1:len(cand[i])-2].split(", ")
        for item in l:
            item = item.strip('.').split(" ")
            candidate.append(item)
        arr = line.strip('.\n').split(" ")
        if (len(arr) == 1):
            continue
        for i in range(len(arr)):
            arr[i] = arr[i].lower()
        reference = arr
        for c in candidate:
            scores.append(similarity(" ".join(reference), " ".join(c)))
    print("Word2Vec Cosine Similarity: " + str(sum(scores)/(1.0*len(scores))))

    # WER
    scores = []
    f = open("poc_english.txt", "r")
    f2 = open(fname, "r")
    lines = f.readlines()
    cand = f2.readlines()
    for i in range(len(cand)):
        line = lines[i]
        candidate = []
        l = cand[i].lower().strip('\n')[1:len(cand[i])-2].split(", ")
        for item in l:
            item = item.strip('.').split(" ")
            candidate.append(item)
        arr = line.strip('.\n').split(" ")
        if (len(arr) == 1):
            continue
        for i in range(len(arr)):
            arr[i] = arr[i].lower()
        reference = arr
        for c in candidate:
            scores.append(wer_score(c, reference))
    print("WER: " + str(sum(scores)/(1.0*len(scores))))

    # TER
    import pyter

    scores = []
    f = open("poc_english.txt", "r")
    f2 = open(fname, "r")
    lines = f.readlines()
    cand = f2.readlines()
    for i in range(len(cand)):
        line = lines[i]
        candidate = []
        l = cand[i].lower().strip('\n')[1:len(cand[i])-2].split(", ")
        for item in l:
            item = item.strip('.').split(" ")
            candidate.append(item)
        arr = line.strip('.\n').split(" ")
        if (len(arr) == 1):
            continue
        for i in range(len(arr)):
            arr[i] = arr[i].lower()
        reference = arr
        for c in candidate:
            scores.append(pyter.ter(reference, c))
    print("TER: " + str(sum(scores)/(1.0*len(scores))))

def run(modelname):
    model = AutoModelForQuestionAnswering.from_pretrained(modelname)
    tokenizer = AutoTokenizer.from_pretrained(modelname)

    from transformers import pipeline
    nlp = pipeline('question-answering', model=model, tokenizer=tokenizer)

    rel_and_food = "A mom is a human. A dad is a human. A mom is a parent. A dad is a parent. A son is a child. A daughter is a child. A son is a human. A daughter is a human. A mom likes cake. A daughter likes cake. A son likes sausage. A dad likes sausage. Cake is a food. Sausage is a food. Mom is a human now. Dad is a human now. Mom is a parent now. Dad is a parent now. Son is a child now. Daughter is a child now. Son is a human now. Daughter is a human now. Mom likes cake now. Daughter likes cake now. Son likes sausage now. Dad likes sausage now. Cake is a food now. Sausage is a food now. Mom was a daughter before. Dad was a son before. Mom was not a parent before. Dad was not a parent before. Mom liked cake before. Dad liked sausage before. Cake was a food before. Sausage was a food before."
    prof = "Mom is on the board of directors. Dad is on the board of directors. Son is on the board of directors. Daughter is on the board of directors. Mom writes with chalk on the board. Dad writes with chalk on the board. Son writes with chalk on the board. Daughter writes with chalk on the board. Dad wants Mom to be on the board of directors. Mom wants Dad to be on the board of directors. Dad wants his son to be on the board of directors. Mom wants her daughter to be on the board of directors. Mom writes to Dad with chalk on the board. Dad writes to Mom with chalk on the board. Son writes to Dad with chalk on the board. Daughter writes to Mom with chalk on the board."
    tools_and_pos = "Mom has a hammer. Mom has a saw. Dad has a hammer. Dad has a saw. Mom has a telescope. Mom has binoculars. Dad has a telescope. Dad has binoculars. Mom saw Dad with a hammer. Mom saw Dad with a saw. Dad saw Mom with a hammer. Dad saw Mom with a saw. Saw is a tool. Hammer is a tool. Binoculars are a tool. A telescope is a tool. Mom sawed the wood with a saw. Dad sawed the wood with a saw. Son sawed the wood with a saw. Daughter sawed the wood with a saw. Mom knocked the wood with a hammer. Dad knocked the wood with a hammer. Son knocked the wood with a hammer. Daughter knocked the wood with a hammer. Mom saw Dad with binoculars. Mom saw Dad with a telescope. Dad saw Mom with binoculars. Dad saw Mom with a telescope."

    f = open("poc_english_queries.txt", "r")
    f2name = modelname.split("/")[1] + ".txt"
    f2 = open(f2name, "w")

    for line in f:
        parts = line.split(" ")
        context = ""
        if "relationships" in parts[0]:
            context = rel_and_food
        elif "tools" in parts[0]:
            context = tools_and_pos
        else:
            context = prof
        question = ""
        for i in range(len(parts)-1):
            question = question + parts[i+1].rstrip() + " "
        question = question[0:len(question)-1] + "?"
        f2.write(nlp({'question': question, 'context': context })['answer'].replace(".",",") + "\n")

    f2.close()

    print(f2name)
    metrics(f2name)
    print('\n')

for m in mnames:
    run(m)


import xml.sax
import PreProcess
import BuildBlockDict

import os

class MyHandler(xml.sax.ContentHandler):
    def __init__(self,indexPath,indexStatsPath):
        xml.sax.ContentHandler.__init__(self)
        self.indexPath = indexPath
        self.indexStatsPath = indexStatsPath
        if not os.path.exists(indexPath):
            os.mkdir(indexPath)
        self.writeTitle = False
        self.writeId = False
        self.writeText = False
        self.insideRevision = False
        self.documentCount = 0
        self.blockCount = 0
        self.preProcess = PreProcess.Preprocess()
        self.totalWords = 0
        self.buildDict = BuildBlockDict.BuildBlockDict(self.indexPath)
        self.resetValues()

    def startElement(self, name, attrs):
        if name == "id":
            self.writeId = True
        elif name == "title":
            self.writeTitle = True
        elif name == "text":
            self.writeText = True
        elif name == "revision":
            self.insideRevision = True

    def endElement(self, name):
        if name == "id":
            self.writeId = False
        elif name == "title":
            self.writeTitle = False
            self.titleList = self.preProcess.parseTitle(self.title)
        elif name == "text":
            self.writeText = False
            self.textLists = self.preProcess.processText(self.text)
        elif name == "revision":
            self.insideRevision = False
        elif name == "page":
            self.documentCount += 1
            pageList = [self.id,self.titleList]
            pageList.append(self.textLists)
            self.buildDict.addPageToDict(pageList)
            self.resetValues()

    def resetValues(self):
        self.id = ""
        self.title = ""
        self.text = ""

    def characters(self, data):
        if self.writeId == True and self.insideRevision == False:
            self.id += data
        elif self.writeTitle == True:
            self.title += " " + data
        elif self.writeText == True:
            self.text += " " + data

    def endDocument(self):
        # writing final block to disk
        self.totalWords = self.preProcess.getTotalWordCount()
        self.blockCount = self.buildDict.writeBlockToFile()
        self.preProcess.finishingTouches()


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

__author__ = 'ipetrash'

from flask import Flask, jsonify
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

@app.route('/network', methods=['GET'])
def network():
    d = {
        'a': [1, 2, 3],
        'b': {
            'b1': [1],
            'b2': '2',
            'b3': 3,
        },
        'c': "CCC",
    }

    return jsonify(d)

if __name__ == "__main__":
    # Localhost
    app.run()

    # # Public IP
    # app.run(host='0.0.0.0')