import os
import pathlib

import pytest
import requests

from unstructured.documents.elements import NarrativeText
from unstructured.partition.api import partition_via_api

DIRECTORY = pathlib.Path(__file__).parent.resolve()

class MockResponse:
    def __init__(self, status_code):
        self.status_code = status_code

    @property
    def text(self):
        return """[
    {
        "element_id": "f49fbd614ddf5b72e06f59e554e6ae2b",
        "text": "This is a test email to use for unit tests.",
        "type": "NarrativeText",
        "metadata": {
            "date": "2022-12-16T17:04:16-05:00",
            "sent_from": [
                "Matthew Robinson <mrobinson@unstructured.io>"
            ],
            "sent_to": [
                "Matthew Robinson <mrobinson@unstructured.io>"
            ],
            "subject": "Test Email",
            "filename": "fake-email.eml"
        }
    }
]"""

def test_partition_via_api_from_filename(monkeypatch):
    monkeypatch.setattr(
        requests,
        "post",
        lambda *args, **kwargs: MockResponse(status_code=200),
    )
    filename = os.path.join(DIRECTORY, "..", "..", "example-docs", "fake-email.eml")
    elements = partition_via_api(filename=filename, api_key="FAKEROO")
    assert elements[0] == NarrativeText("This is a test email to use for unit tests.")

def test_partition_via_api_from_file(monkeypatch):
    monkeypatch.setattr(
        requests,
        "post",
        lambda *args, **kwargs: MockResponse(status_code=200),
    )
    filename = os.path.join(DIRECTORY, "..", "..", "example-docs", "fake-email.eml")

    with open(filename, "rb") as f:
        elements = partition_via_api(file=f, file_filename=filename, api_key="FAKEROO")
    assert elements[0] == NarrativeText("This is a test email to use for unit tests.")

def test_partition_via_api_raises_with_bad_response(monkeypatch):
    monkeypatch.setattr(
        requests,
        "post",
        lambda *args, **kwargs: MockResponse(status_code=500),
    )
    filename = os.path.join(DIRECTORY, "..", "..", "example-docs", "fake-email.eml")

    with pytest.raises(ValueError):
        partition_via_api(filename=filename, api_key="FAKEROO")


import logging

class LOG(object):

    def __init__(self, level, only='off'):
        self.only = only
        self.level = level
        self.LOG_FILENAME = 'file.log'

    def message(self, message):
        if self.level == 'debug' and self.only == 'debug':
            logging.basicConfig(filename=self.LOG_FILENAME, level=logging.DEBUG, format='[%(asctime)s] %(levelname)-4s:  %(message)s', datefmt='%a, %d/%b/%Y %I:%M:%S %p')
            logging.debug(message)

        elif self.level == 'info' and self.only == 'info':
            logging.basicConfig(filename=self.LOG_FILENAME, level=logging.INFO, format='[%(asctime)s] %(levelname)-4s:  %(message)s', datefmt='%a, %d/%b/%Y %I:%M:%S %p')
            logging.info(message)


#! /usr/bin/env python3
import logging
from typing import cast

from core.app import App
from player_ui import PlayerUI

logger = logging.getLogger('player')

class PlayerApp(App):

    def setup(self):
        self.ui = PlayerUI(self)
        self.injector.provide(PlayerUI, lambda: self.ui)

    @classmethod
    def get_instance(cls) -> 'PlayerApp':
        return cast(PlayerApp, cls._instance)

if __name__ == '__main__':
    PlayerApp().run_forever()


import os

def metric_flatten(func):
    def inner(y1, y2, *args, **kwargs):
        mask = y1[:,1] > 0

        y1 = y1[:,0]
        y2 = y2[:,0]
        y1 = y1[mask]
        y2 = y2[mask]
        return func(y1, y2, *args, **kwargs)
    inner.__name__ = "f_"+func.__name__
    return inner

def new_log(catchment_dict, base_path, base_name, args=None):

    folder_path = os.path.join(base_path, args.data)
    if not os.path.isdir(folder_path):
        os.mkdir(folder_path)

    folder_path = os.path.join(folder_path, base_name)
    if not os.path.isdir(folder_path):
        os.mkdir(folder_path)

    previous_runs = os.listdir(folder_path)
    n_exp = len(previous_runs)

    experiment_folder = os.path.join(folder_path, "experiment_{}".format(n_exp))

    os.mkdir(experiment_folder)

    if args is not None:
        args_dict = args.__dict__
        args_dict.update(catchment_dict)
        with open(os.path.join(experiment_folder, "args" + '.txt'), 'w') as f:
            sorted_names = sorted(args_dict.keys(), key=lambda x: x.lower())
            for key in sorted_names:
                value = args_dict[key]
                f.write('%s:%s\n' % (key, value))

    return experiment_folder

def to_device(sample, device=None):

    import torch

    if device is None:
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    sampleout = {}
    sampleout['gt'] = sample[1].to(device=device, dtype=torch.float)
    sampleout['mask'] = sample[0][1].to(device=device, dtype=torch.float)
    sampleout['data'] = sample[0][0].to(device=device, dtype=torch.float)

    return sampleout

def to_device_eval(sample, device= None):

    import torch

    if device is None:
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    sample = sample.to(device=device, dtype=torch.float)

    return sample


import nltk
import re
from pickle import load
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

def cleaning_one(stri):

    stri = stri.split(" ")
    for i in range(len(stri)):
        for j in ['@', '#']:
            if j in stri[i]:
                stri[i] = stri[i].replace(stri[i], "")
    stri = " ".join(stri)
    stri = re.sub(r"[\W+0-9+]", " ", stri)
    stri = re.findall(r"[A-Za-z]+", stri)
    stri = " ".join(stri)
    stri = stri.lower()

    return stri

def nltk_processing(stri):

    stop_words = set(stopwords.words('english'))
    ps = PorterStemmer()
    stri = stri.split(" ")
    stri = [ps.stem(i) for i in stri if i not in stop_words]
    stri = " ".join(stri)

    return stri

def tf_processing(corpus):

    with open('tokenizer.pkl', 'rb') as file:
        tokenizer = load(file)
    sequences = tokenizer.texts_to_sequences(corpus)
    maxlen = 115
    sequences = pad_sequences(sequences, maxlen=maxlen)

    return sequences


import paddle
import paddle.nn as nn
import paddle.nn.functional as F

def upfirdn2d_native(input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1,
                     pad_y0, pad_y1):
    _, channel, in_h, in_w = input.shape
    input = input.reshape((-1, in_h, in_w, 1))

    _, in_h, in_w, minor = input.shape
    kernel_h, kernel_w = kernel.shape

    out = input.reshape((-1, in_h, 1, in_w, 1, minor))
    out = out.transpose((0, 1, 3, 5, 2, 4))
    out = out.reshape((-1, 1, 1, 1))
    out = F.pad(out, [0, up_x - 1, 0, up_y - 1])
    out = out.reshape((-1, in_h, in_w, minor, up_y, up_x))
    out = out.transpose((0, 3, 1, 4, 2, 5))
    out = out.reshape((-1, minor, in_h * up_y, in_w * up_x))

    out = F.pad(
        out, [max(pad_x0, 0),
              max(pad_x1, 0),
              max(pad_y0, 0),
              max(pad_y1, 0)])
    out = out[:, :,
              max(-pad_y0, 0):out.shape[2] - max(-pad_y1, 0),
              max(-pad_x0, 0):out.shape[3] - max(-pad_x1, 0), ]

    out = out.reshape(
        ([-1, 1, in_h * up_y + pad_y0 + pad_y1, in_w * up_x + pad_x0 + pad_x1]))
    w = paddle.flip(kernel, [0, 1]).reshape((1, 1, kernel_h, kernel_w))
    out = F.conv2d(out, w)
    out = out.reshape((
        -1,
        minor,
        in_h * up_y + pad_y0 + pad_y1 - kernel_h + 1,
        in_w * up_x + pad_x0 + pad_x1 - kernel_w + 1,
    ))
    out = out.transpose((0, 2, 3, 1))
    out = out[:, ::down_y, ::down_x, :]

    out_h = (in_h * up_y + pad_y0 + pad_y1 - kernel_h) // down_y + 1
    out_w = (in_w * up_x + pad_x0 + pad_x1 - kernel_w) // down_x + 1

    return out.reshape((-1, channel, out_h, out_w))

def upfirdn2d(input, kernel, up=1, down=1, pad=(0, 0)):
    out = upfirdn2d_native(input, kernel, up, up, down, down, pad[0], pad[1],
                           pad[0], pad[1])

    return out

def make_kernel(k):
    k = paddle.to_tensor(k, dtype='float32')

    if k.ndim == 1:
        k = k.unsqueeze(0) * k.unsqueeze(1)

    k /= k.sum()

    return k

class Upfirdn2dUpsample(nn.Layer):
    def __init__(self, kernel, factor=2):
        super().__init__()

        self.factor = factor
        kernel = make_kernel(kernel) * (factor * factor)
        self.register_buffer("kernel", kernel)

        p = kernel.shape[0] - factor

        pad0 = (p + 1) // 2 + factor - 1
        pad1 = p // 2

        self.pad = (pad0, pad1)

    def forward(self, input):
        out = upfirdn2d(input,
                        self.kernel,
                        up=self.factor,
                        down=1,
                        pad=self.pad)

        return out

class Upfirdn2dDownsample(nn.Layer):
    def __init__(self, kernel, factor=2):
        super().__init__()

        self.factor = factor
        kernel = make_kernel(kernel)
        self.register_buffer("kernel", kernel)

        p = kernel.shape[0] - factor

        pad0 = (p + 1) // 2
        pad1 = p // 2

        self.pad = (pad0, pad1)

    def forward(self, input):
        out = upfirdn2d(input,
                        self.kernel,
                        up=1,
                        down=self.factor,
                        pad=self.pad)

        return out

class Upfirdn2dBlur(nn.Layer):
    def __init__(self, kernel, pad, upsample_factor=1):
        super().__init__()

        kernel = make_kernel(kernel)

        if upsample_factor > 1:
            kernel = kernel * (upsample_factor * upsample_factor)

        self.register_buffer("kernel", kernel, persistable=False)

        self.pad = pad

    def forward(self, input):
        out = upfirdn2d(input, self.kernel, pad=self.pad)

        return out


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@Description     :
@Date            :2022/05/22 20:16:55
@Author          :xbMa
'''

'''
QToolButton属性
ToolButtonIconOnly	        只显示图标
ToolButtonTextOnly	        只显示文字
ToolButtonTextBesideIcon	文字出现在图标旁边
ToolButtonTextUnderIcon	    文字出现在图标下方
ToolButtonFollowStyle	    遵循QStyle.StyleHint

QToolButton.DelayedPopup	按下按钮一定时间后，显示菜单。一个典型案例：浏览器中工具栏的“后退”按钮。
QToolButton.MenuButtonPopup	这种模式下，工具按钮显示一个特殊的箭头以指示菜单是否存在，按下按钮的箭头部分时显示菜单。
QToolButton.InstantPopup	按下工具按钮时菜单显示，无延迟。这种模式下，按钮自身的动作不触发。
'''

from PyQt5.QtWidgets import QWidget, QApplication, QToolButton, QMenu, QAction
from PyQt5.QtGui import QDesktopServices, QIcon
from PyQt5.QtCore import QUrl, Qt
import sys

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(500, 200, 500, 500)
        # 新建一个QToolButton对象。
        tb = QToolButton(self)
        # 该属性保持工具按钮是仅显示图标，仅显示文本，还是显示图标旁边/下方的文本
        tb.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        # tb.setArrowType(Qt.DownArrow)
        # 这个很好理解，就是一个小贴士，当鼠标移动到按钮的时候就会显示信息。
        tb.setToolTip('选择适合你的支付方式')
        # 描述了弹出式菜单与工具按钮一起使用的方式:
        tb.setPopupMode(QToolButton.MenuButtonPopup)
        # 设置图标和文字。
        tb.setText('支付方式')
        tb.setIcon(QIcon('icon/bank.ico'))
        # 此属性保持是否启用自动升起。默认是禁用的（即False）。
        # 当使用QMacStyle时，此属性在macOS上当前被忽略。
        tb.setAutoRaise(True)
        tb.setGeometry(150, 100 ,200, 50)

        menu = QMenu(self)
        self.alipayAct = QAction(QIcon('icon/alipay.ico'),'支付宝支付', self)
        self.wechatAct = QAction(QIcon('icon/wechat.ico'),'微信支付', self)
        self.visaAct = QAction(QIcon('icon/visa.ico'),'Visa卡支付', self)
        self.master_cardAct = QAction(QIcon('icon/master_card.ico'),'万事达卡支付', self)

        menu.addAction(self.alipayAct)
        menu.addAction(self.wechatAct)
        menu.addSeparator()
        menu.addAction(self.visaAct)
        menu.addAction(self.master_cardAct)

        tb.setMenu(menu)
        self.show()

        self.alipayAct.triggered.connect(self.on_click)
        self.wechatAct.triggered.connect(self.on_click)
        self.visaAct.triggered.connect(self.on_click)
        self.master_cardAct.triggered.connect(self.on_click)

    def on_click(self):
        if self.sender() == self.alipayAct:
            QDesktopServices.openUrl(QUrl('https://www.alipay.com/'))
        elif self.sender() == self.wechatAct:
            QDesktopServices.openUrl(QUrl('https://pay.weixin.qq.com/index.php'))
        elif self.sender() == self.visaAct:
            QDesktopServices.openUrl(QUrl('https://www.visa.com.cn/'))
        else:
            QDesktopServices.openUrl(QUrl('https://www.mastercard.com.cn/zh-cn.html'))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


import numpy as np

from scipy.io import loadmat

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import matplotlib.transforms as transforms

########################################################################################################################################################################################################################################################################################

def DataFormatting (path, moth_database, moth, neurons, stimuli):

    data = loadmat(f'{path}{moth_database[0][moth]}_{moth_database[1][moth]}_AnnotatedToShare_v3.mat')
    AdditionalVars = loadmat(f'{path}{moth_database[0][moth]}_{moth_database[1][moth]}_AdditionalInfo.mat')

    No_trials = AdditionalVars['No_trials_perNeuronStimulus'].tolist()

    spike_times_ALL = [None] * len(neurons)
    targets_ALL = [None] * len(neurons)

    for neuron in neurons:

        spike_times_perNEURON = [None] * len(stimuli)
        targets_perNEURON = [None] * len(stimuli)

        for stimulus in stimuli:

            spike_times = data['{}_times'.format(neuron)][0,stimulus]

            if AdditionalVars['MissingData'][neurons.index(neuron),stimuli.index(stimulus)] == 0:

                spike_times_perNEURON[stimuli.index(stimulus)] = spike_times
                targets_perNEURON[stimuli.index(stimulus)] = stimulus*np.ones((spike_times.shape[0],1))

            elif AdditionalVars['MissingData'][neurons.index(neuron),stimuli.index(stimulus)] == 1:

                spike_times_perNEURON[stimuli.index(stimulus)] = np.empty((AdditionalVars['No_trials'][stimuli.index(stimulus),1],1))
                spike_times_perNEURON[stimuli.index(stimulus)][:] = np.NaN
                targets_perNEURON[stimuli.index(stimulus)] = stimulus*np.ones((AdditionalVars['No_trials'][stimuli.index(stimulus),1],1))

            print('(Moth-{}, Neuron-{}, stim-{}) In: orig-{} / Out: targ-{}({})'.format(moth+1, neuron, stimulus, spike_times_perNEURON[stimuli.index(stimulus)].shape, targets_perNEURON[stimuli.index(stimulus)].shape, targets_perNEURON[stimuli.index(stimulus)][0,0]))

        print(125*'-')
        spike_times_ALL[neurons.index(neuron)] = spike_times_perNEURON
        targets_ALL[neurons.index(neuron)] = targets_perNEURON

    return spike_times_ALL, targets_ALL, No_trials

########################################################################################################################################################################################################################################################################################

def GaussianKernelFiltering ( spike_times_ALL, targets_ALL, No_trials, neurons, stimuli, dur, f_s, sigma ):

    time, T = np.arange(0,dur,1/f_s), int(dur*f_s)
    gauss_kernel_response_ALL = [None] * len(neurons)
    spike_counts_ALL = [None] * len(neurons)

    for neuron in neurons:

        gauss_kernel_response_perNEURON = [None] * len(stimuli)
        spike_counts_perNEURON = [None] * len(stimuli)

        for stimulus in stimuli:

            spike_times_neuron_stimulus = spike_times_ALL[neurons.index(neuron)][stimuli.index(stimulus)]
            gauss_kernel_response = np.zeros( ( spike_times_neuron_stimulus.shape[0], T ) )
            spike_counts = np.zeros( ( spike_times_neuron_stimulus.shape[0], 1 ) )

            for trial in range(spike_times_neuron_stimulus.shape[0]):
                for i in range(spike_times_neuron_stimulus.shape[1]):
                    if ~np.isnan(spike_times_neuron_stimulus[trial,i]):
                        if spike_times_neuron_stimulus[trial,i] <= (dur*1e3):
                            gauss_kernel_response[trial,:] += np.exp( - ((time - 1e-3*spike_times_neuron_stimulus[trial,i])*(time - 1e-3*spike_times_neuron_stimulus[trial,i]))/(2*sigma*sigma) )
                            spike_counts[trial,:] += 1

            gauss_kernel_response_perNEURON[stimuli.index(stimulus)] = gauss_kernel_response
            spike_counts_perNEURON[stimuli.index(stimulus)] = spike_counts

        gauss_kernel_response_ALL[neurons.index(neuron)] = gauss_kernel_response_perNEURON
        spike_counts_ALL[neurons.index(neuron)] = spike_counts_perNEURON

    signals = np.empty((No_trials,len(neurons),T))
    signals_maxvalpos = np.empty((No_trials,len(neurons),2))
    counts = np.empty((No_trials,len(neurons),1))
    targets = np.empty((No_trials,1))

    for neuron in neurons:
        idx = 0
        for stimulus in stimuli:
            count = 0
            for trial in range( targets_ALL[neurons.index(neuron)][stimuli.index(stimulus)].shape[0] ):
                signals[idx,neurons.index(neuron),:] = gauss_kernel_response_ALL[neurons.index(neuron)][stimuli.index(stimulus)][count,:]
                signals_maxvalpos[idx,neurons.index(neuron),0] = np.argmax( gauss_kernel_response_ALL[neurons.index(neuron)][stimuli.index(stimulus)][count,:] )
                signals_maxvalpos[idx,neurons.index(neuron),1] = gauss_kernel_response_ALL[neurons.index(neuron)][stimuli.index(stimulus)][count,int(signals_maxvalpos[idx,neurons.index(neuron),0])]
                counts[idx,neurons.index(neuron),:] = spike_counts_ALL[neurons.index(neuron)][stimuli.index(stimulus)][count,:]
                targets[idx,:] = targets_ALL[neurons.index(neuron)][stimuli.index(stimulus)][count,:]
                idx, count = idx+1, count+1

    return signals, signals_maxvalpos, counts, targets


import logging

# This will be a demonstration of passing variables to your log file
# This assumes you have looked at example 1 and example 2 first

# Creating logger
l1 = logging.getLogger('example3')
l1.setLevel(logging.DEBUG)

# Creating handler

fh = logging.FileHandler('example3.log')
fh.setLevel(logging.DEBUG)

# Creating formatter

form = logging.Formatter('%(asctime)s, %(message)s')

# Add formatter to handler

fh.setFormatter(form)

# Add handler to logger

l1.addHandler(fh)

# Test logs
v1=5
v2='I\'m a single pringle'
v3=10.5
v4=False
v5='C'

l1.debug(v1)
l1.info(v2)
l1.warn(v3)
l1.error(v4)
l1.critical(v5)


# -*- coding: utf-8 -*-
"""
Created on Fri Mar  9 18:01:48 2018

@author: andersson
"""

from tkinter import *
import pyaudio
import scipy.io.wavfile as wavfile
import matplotlib.pylab as plt
import wave
from scipy.fftpack import fft
import numpy as np
#from tkFileDialog import *
from scipy.fftpack import fft
from PIL import Image, ImageTk

from scipy import signal

ventana=Tk()
ventana.geometry("1200x800+100+100")
ventana.title("FILTROS")

def periodo():

    #definir funcion saludar del boton
    def grabar():
            global  fs, data, w, h, filtrado
            periodo.destroy()
            periododemuestreo=entradaper.get()
            tiempodegraba=entradatime.get()
            chunk=1024
            FORMAT = pyaudio.paInt16
            CHANNELS = 1
            fs = periododemuestreo
            tiempo = tiempodegraba
            samples = (fs/1024)*tiempo
            p = pyaudio.PyAudio()

            stream = p.open(format=FORMAT,channels=CHANNELS,rate =fs,input=True,frames_per_buffer=chunk)
            stream1 = p.open(format=FORMAT,channels=CHANNELS,rate =fs,output=True,frames_per_buffer=chunk)

            print ("*grabando")
            arreglo = []
            for i in range(0, samples):
                data = stream.read(chunk)
                arreglo.append(data)

            stream.stop_stream()
            stream.close()
            stream1.stop_stream()
            stream1.close()

            wf = wave.open('audio1.wav', 'wb')
            wf.setnchannels(CHANNELS)
            wf.setframerate(fs)
            wf.setsampwidth(p.get_sample_size(FORMAT))
            wf.writeframes(b''.join(arreglo))
            wf.close()
            print ("*fin de la grabacion")
            fs, data = wavfile.read("audio1.wav")
            print(data.size)
            a=len(data)
            t=np.linspace(0,(a-1)*1.0/fs,a)
            plt.figure(1).clf()
            plt.figure(1)
            plt.plot(t,data)
            plt.savefig("imagentiempo1.png")

    #definir funcion despedir del boton

    #creando la ventana
    periodo=Toplevel(ventana)
    periodo.geometry("400x200+450+200")
    periodo.focus_set()
    periodo.grab_set()
    periodo.transient(master=ventana)
    periodo.title("SELECCION PARAMETROS DE GRABACION")
    lblperiodo=Label(periodo,text="Ingrese periodo de muestreo",fg="black",font=("Agency FB",14) ).place(x=80,y=10)
    entradaper=IntVar()
    entradaper.set("16000")
    txtperiodo=Entry(periodo,textvariable=entradaper).place(x=90,y=40)

    lbltime=Label(periodo,text="Ingrese tiempo de grabacion",fg="black",font=("Agency FB",14) ).place(x=80,y=70)
    entradatime=IntVar()
    entradatime.set("3")
    txttime=Entry(periodo,textvariable=entradatime).place(x=90,y=100)
    btnper=Button(periodo,text="Aceptar",command=grabar,font=("Agency FB",14)).place(x=100,y=130)
    periodo.wait_window(periodo)

    print ("*fin de la grabacion")

    #plt.show()

def pintar_imagen():
    ancho=300
    alto=200
    img = Image.open('imagentiempo1.png', "rb")
    img.thumbnail((ancho,alto), Image.ANTIALIAS)
    imagen1 = ImageTk.PhotoImage(img)
    label1=Label(ventana, image=imagen1, width=ancho, height=alto).place(x=1, y=75)

    img2 = Image.open('imagenfreq.png', "rb")
    img2.thumbnail((ancho,alto), Image.ANTIALIAS)
    imagen2 = ImageTk.PhotoImage(img2)
    label2=Label(ventana, image=imagen2, width=ancho, height=alto).place(x=310, y=75)

    img3 = Image.open('imagenbode.png', "rb")
    img3.thumbnail((ancho,alto), Image.ANTIALIAS)
    imagen3 = ImageTk.PhotoImage(img3)
    label3=Label(ventana, image=imagen3, width=ancho, height=alto).place(x=620, y=75)

    img4 = Image.open('filtrado.png', "rb")
    img4.thumbnail((ancho,alto), Image.ANTIALIAS)
    imagen4 = ImageTk.PhotoImage(img4)
    label4=Label(ventana, image=imagen4, width=ancho, height=alto).place(x=620, y=280)

    img5 = Image.open('filtradoFFT.png', "rb")
    img5.thumbnail((ancho,alto), Image.ANTIALIAS)
    imagen5 = ImageTk.PhotoImage(img5)
    label5=Label(ventana, image=imagen5, width=ancho, height=alto).place(x=620, y=490)

    Image.show()

def t1():

    pintar_imagen()

def t2():
    global dataf

    plt.figure(1).clf()
    plt.figure(2)
    plt.plot(dataf)
    plt.show()

def f1():
    global data, fs
    N = len(data)

     # sample spacing
    T = 1.0 / fs

    x = np.linspace(0.0, N*T, N)

    yf = fft(data)
    xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
    plt.figure().clf()
    plt.figure()
    plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
    plt.grid()
    plt.savefig("imagenfreq.png")
    pintar_imagen()

def f2():
    global dataf, fs
    N = len(dataf)

     # sample spacing
    T = 1.0 / fs

    x = np.linspace(0.0, N*T, N)

    yf = fft(data)
    xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
    plt.figure().clf()
    plt.figure()

    plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
    plt.grid()
    plt.show()

def play1():

    rf1 = wave.open("audio1.wav", 'rb')
   # fs, rf1 = wavfile.read("audio1.wav")
    prof1 = rf1.getsampwidth()
    channels1 = rf1.getnchannels()
    rate1 = rf1.getframerate()
    audioN1 = pyaudio.PyAudio()
    stream2  = audioN1.open(format=audioN1.get_format_from_width(prof1), channels=channels1, rate=rate1, output=True)
    datos1 = rf1.readframes(1024)
    #rate1, data1 = wavfile.read(root.filename)

    while datos1 != '':
        stream2.write(datos1)
        datos1 = rf1.readframes(1024)

    rf1.close()

def play2():
    rf = wave.open('filtro.wav', 'rb')

    prof = rf.getsampwidth()
    channels = rf.getnchannels()
    rate = rf.getframerate()
    audioN = pyaudio.PyAudio()
    stream1  = audioN.open(format=audioN.get_format_from_width(prof), channels=channels, rate=rate, output=True)
    datos = rf.readframes(1024)

    while datos != '':
        stream1.write(datos)
        datos = rf.readframes(1024)

    rf.close()

def aplicar():
    global b, a, data, fs, filtrado
    filtrado=signal.lfilter(b, a, data)
    wavfile.write('filtro.wav', fs, filtrado)
    plt.figure(4).clf()
    plt.figure(4)
    plt.plot(filtrado)
    plt.savefig("filtrado.png")
    N = len(filtrado)
    T = 1.0 / fs
    x = np.linspace(0.0, N*T, N)
    yf = fft(filtrado)
    xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
    plt.figure(4).clf()
    plt.figure(4)
    plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
    plt.savefig("filtradoFFT.png")

    pintar_imagen()

def eventos():
    global b, a
    nyq = fs * 0.5
    s=selec.get()
    s1=selec1.get()
    if s==1 and s1==1:
        print ("Pasa Altos Butterworth")
        cutoff= highcut
        stopfreq = float(cutoff)
        cornerfreq = 0.4 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(wp, ws, orden, 40) # (?)
        b, a = signal.butter(N1, wn, btype='high')
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==1 and s1==2:
        print("Pasa Altos Chevichev I")
        cutoff= highcut
        rp=(riso*0.1)
        stopfreq = float(cutoff)
        cornerfreq = 0.4 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(wp, ws, orden, 40) # (?)
        b, a = signal.cheby1(N1, rp, wn, btype='highpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==1 and s1==3:
        print("Pasa Altos Chevichev II")
        cutoff= highcut
        rp=riso*5
        stopfreq = float(cutoff)
        cornerfreq = 0.4 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(wp, ws, orden, 40) # (?)
        b, a = signal.cheby2(N1, rp, wn, btype='highpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==1 and s1==4:
        print("Pasa Altos Eliptico")
        cutoff= highcut
        rp=riso*0.1
        rse=rs*5
        stopfreq = float(cutoff)
        cornerfreq = 0.4 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(wp, ws, orden, 40) # (?)
        b, a = signal.ellip(N1, rp, rse, wn, btype='highpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    if s==2 and s1==1:
        print (" Pasa bajo Butterworth")
        cutoff= lowcut
        stopfreq = float(cutoff)
        cornerfreq = 0.7 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(wp, ws, orden, 40) # (?)
        b, a = signal.butter(N1, wn, btype='lowpass')
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==2 and s1==2:
        print(" Pasa bajo Chevichev I")
        cutoff= lowcut
        rp=(riso*0.1)
        stopfreq = float(cutoff)
        cornerfreq = 0.7 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(ws, wp, orden, 40) # (?)
        b, a = signal.cheby1(N1, rp, wn, btype='lowpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==2 and s1==3:
        print("Pasa bajo Chevichev II")
        cutoff= lowcut
        rp=(riso*5)
        stopfreq = float(cutoff)
        cornerfreq = 0.7 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(ws, wp, orden, 40) # (?)
        b, a = signal.cheby2(N1, rp, wn, btype='lowpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==2 and s1==4:
        print("Pasa bajo Eliptico")
        cutoff= lowcut
        rp=(riso*0.1)
        rse=rs*5
        stopfreq = float(cutoff)
        cornerfreq = 0.7 * stopfreq # (?)
        ws = cornerfreq/nyq
        wp = stopfreq/nyq
        N1, wn =signal.buttord(ws, wp, orden, 40) # (?)
        b, a = signal.ellip(N1, rp, rse, wn, btype='lowpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    if s==3 and s1==1:
        print (" Pasa Banda Butterworth")
        low = lowcut / nyq
        high = highcut / nyq
        b, a = signal.butter(orden, [low, high], btype='band')
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==3 and s1==2:
        print(" Pasa Banda Chevichev I")
        low = lowcut / nyq
        high = highcut / nyq
        rp=(riso*0.1)
        N1= orden
        b, a = signal.cheby1(N1, rp, [low, high], btype='bandpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==3 and s1==3:
        print("Pasa Banda Chevichev II")
        low = lowcut / nyq
        high = highcut / nyq
        rp=(riso*5)
        N1= orden
        b, a = signal.cheby2(N1, rp, [low, high], btype='bandpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==3 and s1==4:
        print("Pasa Banda Eliptico")
        low = lowcut / nyq
        high = highcut / nyq
        rp=(riso*0.1)
        rse=rs*5
        N1= orden
        b, a = signal.ellip(N1, rp, rse, [low, high], btype='bandpass') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    if s==4 and s1==1:
        print (" Rechazabanda Butterworth")
        low = lowcut / nyq
        high = highcut / nyq
        b, a = signal.butter(orden, [low, high], btype='bandstop')
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==4 and s1==2:
        print(" Rechazabanda Chevichev I")
        low = lowcut / nyq
        high = highcut / nyq
        rp=(riso*0.1)
        N1= orden
        b, a = signal.cheby1(N1, rp, [low, high], btype='bandstop') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==4 and s1==3:
        print("Rechazabanda Chevichev II")
        low = lowcut / nyq
        high = highcut / nyq
        rp=(riso*5)
        N1= orden
        b, a = signal.cheby2(N1, rp, [low, high], btype='bandstop') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

    elif s==4 and s1==4:
        print("Rechazabanda Eliptico")
        low = lowcut / nyq
        high = highcut / nyq
        rp=(riso*0.1)
        rse=rs*5
        N1= orden
        b, a = signal.ellip(N1, rp, rse, [low, high], btype='bandstop') #N es el numero de orden, rp=el rizo maximo permitido, Wn= frecuencias de corte y stop
        w,h = signal.freqz(b,a)
        plt.figure(3).clf()
        plt.figure(3)
        plt.plot(w, abs(h))
        plt.grid()
        plt.savefig("imagenbode.png")
        pintar_imagen()

def LC(event):
    global lowcut, highcut, orden, fs, riso, rs
    lowcut= Throttle.get()
    print(lowcut)
    eventos()

def HC(event):
    global lowcut, highcut, orden, fs, riso, rs
    highcut= Throttle1.get()
    print(highcut)
    eventos()

def Ord(event):
    global lowcut, highcut, orden, fs, riso, rs
    orden= Throttle2.get()
    print(orden)
    eventos()

def Riso(event):
    global lowcut, highcut, orden, fs, riso, rs
    riso= Throttle3.get()
    print(riso)
    eventos()

def rs(event):
    global lowcut, highcut, orden, fs, riso, rs
    nyq = fs * 0.5
    rs= Throttle4.get()
    print(rs)
    eventos()

Throttle = Scale(ventana,label="LowCut",orient=VERTICAL,length=350, width=25,from_=1,to=8000,tickinterval=1, command=LC,bg='#f0f0ff')
Throttle.set(0)
Throttle.pack()
Throttle.place(x=20,y=320)

Throttle1 = Scale(ventana,label="Highcut",orient=VERTICAL,length=350, width=25,from_=1,to=8000,tickinterval=1, command=HC,bg='#f0f0ff')
Throttle1.set(0)
Throttle1.pack()
Throttle1.place(x=160,y=320)

Throttle2 = Scale(ventana,label="Orden",orient=VERTICAL,length=350, width=25,from_=1,to=20,tickinterval=1, command=Ord,bg='#f0f0ff')
Throttle2.set(0)
Throttle2.pack()
Throttle2.place(x=310,y=320)

Throttle3 = Scale(ventana,label="Riso",orient=VERTICAL,length=350, width=25,from_=0,to=10,tickinterval=1, command=Riso,bg='#f0f0ff')
Throttle3.set(0)
Throttle3.pack()
Throttle3.place(x=450,y=320)

Throttle4 = Scale(ventana,label="Rs-Ell",orient=VERTICAL,length=350, width=25,from_=0,to=10,tickinterval=1, command=rs,bg='#f0f0ff')
Throttle4.set(0)
Throttle4.pack()
Throttle4.place(x=1000,y=320)
#sldbarra=Scale(ventana,label="Lowcut",orient=VERTICAL,length=350,width=20,from_=0,to=8000,tickinterval=10,variable=valor0,bg='#f0f0ff').place(x=10,y=130)

selec=IntVar()

rd1=Radiobutton(ventana,text="Pasa Alto",
                     value=1,variable=selec,bg='#f0f0ff').place(x=10,y=10)
rd2=Radiobutton(ventana,text="Pasa Bajo",
                     value=2,variable=selec,bg='#f0f0ff').place(x=10,y=25)
rd3=Radiobutton(ventana,text="Pasa Banda",
                     value=3,variable=selec,bg='#f0f0ff').place(x=10,y=40)
rd4=Radiobutton(ventana,text="Rechaza Banda",
                     value=4,variable=selec,bg='#f0f0ff').place(x=10,y=55)

selec1=IntVar()
rd5=Radiobutton(ventana,text="Butterworth",value=1,variable=selec1,bg='#f0f0ff').place(x=150,y=10)
rd6=Radiobutton(ventana,text="Chebyshev I",value=2,variable=selec1,bg='#f0f0ff').place(x=150,y=25)
rd7=Radiobutton(ventana,text="Chebyshev II",value=3,variable=selec1,bg='#f0f0ff').place(x=150,y=40)
rd8=Radiobutton(ventana,text="Eliptico",value=4,variable=selec1,bg='#f0f0ff').place(x=150,y=55)

btnplay1=Button(ventana,text="Play1",command=play1,height=1,activebackground=('green'),width=4,font=("Agency FB",12)).place(x=1000,y=1)
btnapply=Button(ventana,text="Aplicar",command=aplicar,height=1,activebackground=('green'),width=5,font=("Agency FB",12)).place(x=1000,y=35)

btnp2=Button(ventana,text="play2",command=play2,height=1,activebackground=('green'),width=4,font=("Agency FB",12)).place(x=1000,y=70)

barramenu=Menu(ventana)

#paso 2 crear los menus

mnuarchivo=Menu(barramenu)

mnugrafi=Menu(barramenu)

mnutiempo=Menu(mnugrafi)
mnufrec=Menu(mnugrafi)

#paso 3 crear los comandos de los menus

mnuarchivo.add_command(label="Grabar",command=periodo)

mnuarchivo.add_separator()
mnuarchivo.add_command(label="Salir",command=ventana.destroy)

#####

mnutiempo.add_command(label="1",command=t1)

#paso 4 agergar los menus a la barra de menus
barramenu.add_cascade(label="Archivo",menu=mnuarchivo)

barramenu.add_cascade(label="Graficas",menu=mnugrafi)

mnugrafi.add_cascade(label="Tiempo",menu=mnutiempo)

ventana.config(menu=barramenu, bg='#f0f0ff')

ventana.mainloop()


# Libararies used for spark_session.py
import pyspark
import re
from pyspark.sql import SparkSession
from pyspark.sql.types import StructType, StructField, IntegerType, StringType
from google.cloud import storage

class Create_Spark_Session:
    '''
    Class --> Create_Spark_Session:
                This class is in charge of creating the spark session that will be passed into the file called dataproc_spark_commands.py
                which will read in the spark dataframe that is created here called df and the spark session called spark.

                Input Variables
                    None
    '''

    def create_spark_df(self):
        '''
        Function --> create_spark_df:
                        This function uses the schema created below, starts a Spark Session with no configurations inputs to let
                        GCP do that for us and maximize all nodes and compute instances. Using this Spark Session we are able to read
                        in a file at a given GCS bucket to create a PySpark dataframe.
                        Input Variables
                            1. data_location: The location of the plane.csv dataset in the GCS bucket.
                        Output Variables
                            1. spark_df: The spark dataframe that was created based on the schema below and the data read in from the GCS bucket.
                            2. spark: This is an SparkSession() global values that is created.
        '''
        # Schema that was created for the plane.csv data set.
        schema = StructType([StructField("YEAR", StringType(), False),
                             StructField("MONTH", StringType(), False),
                             StructField("DAY", StringType(), False),
                             StructField("DAY_OF_WEEK", StringType(), False),
                             StructField("AIRLINE", StringType(), False),
                             StructField("FLIGHT_NUMBER", StringType(), True),
                             StructField("TAIL_NUMBER", StringType(), True),
                             StructField("ORIGIN_AIRPORT", StringType(), False),
                             StructField("DESTINATION_AIRPORT", StringType(), False),
                             StructField("SCHEDULED_DEPARTURE", IntegerType(), False),
                             StructField("DEPARTURE_TIME", IntegerType(), True),
                             StructField("DEPARTURE_DELAY", IntegerType(), True),
                             StructField("TAXI_OUT", IntegerType(), True),
                             StructField("WHEELS_OFF", IntegerType(), True),
                             StructField("SCHEDULED_TIME", IntegerType(), True),
                             StructField("ELAPSED_TIME", IntegerType(), True),
                             StructField("AIR_TIME", IntegerType(), True),
                             StructField("DISTANCE", IntegerType(), True),
                             StructField("WHEELS_ON", IntegerType(), True),
                             StructField("TAXI_IN", IntegerType(), True),
                             StructField("SCHEDULED_ARRIVAL", IntegerType(), True),
                             StructField("ARRIVAL_TIME", IntegerType(), True),
                             StructField("ARRIVAL_DELAY", IntegerType(), True),
                             StructField("DIVERTED", StringType(), True),
                             StructField("CANCELLED", StringType(), True),
                             StructField("CANCELLATION_REASON", StringType(), True),
                             StructField("AIR_SYSTEM_DELAY", IntegerType(), True),
                             StructField("SECURITY_DELAY", IntegerType(), True),
                             StructField("AIRLINE_DELAY", IntegerType(), True),
                             StructField("LATE_AIRCRAFT_DELAY", IntegerType(), True),
                             StructField("WEATHER_DELAY", StringType(), True),
                            ])

        # Spark session created, do not add any instances so DataProc can create efficiencies in the configuration.
        spark = SparkSession.builder.getOrCreate()

        # Pyspark dataframe type using the schema specified above and the GCS bucket location of the flights data.
        spark_df_flights = spark.read.csv("gs://plane-pyspark-run/flight-delays/flights.csv",
                                  header=True,
                                  schema = schema)

        spark_df_airports = spark.read.csv("gs://plane-pyspark-run/flight-delays/airports.csv",
                                  header=True,
                                  inferSchema = True)

        spark_df_airlines = spark.read.csv("gs://plane-pyspark-run/flight-delays/airlines.csv",
                                  header=True,
                                  inferSchema = True)

        # Returns a spark dataframe: spark_df and a Spark Session: spark
        return spark_df_flights, spark_df_airports, spark_df_airlines, spark

    def create_model_spark_df(self):
        # Spark session created, do not add any instances so DataProc can create efficiencies in the configuration.
        spark = SparkSession.builder.getOrCreate()

        client = storage.Client()
        bucket = client.get_bucket("plane-pyspark-run")
        blobs = bucket.list_blobs()
        for blob in blobs:
            if re.match(r'\.*{}*'.format('Spark_Data_Output/model_df.csv/part'),blob.name):
                model_df_name = blob.name

        print(model_df_name)
        model_df = spark.read.csv("gs://plane-pyspark-run/{}".format(model_df_name),
                                  header=True,
                                  inferSchema = True)

        return model_df, spark


# -*- coding: utf-8 -*-
# @Time     :2020/5/27 21:33
# @Author   :12257
# @SoftWare :PyCharm
from django.conf import settings
from django.utils.safestring import mark_safe

class MyPagenation():

    def __init__(self, page, total_count, per_page_num, page_num_show, base_url, get_data=None):
        """

        :param page: 当前页
        :param total_count: 数据总数量
        :param per_page_num: 每页数据
        :param page_num_show: 显示的页码数
        :param base_url: 基本路径
        :param get_data: 查询数据_Query_dict?
        """
        self.base_url = base_url
        self.get_data = get_data
        per_page_num = settings.PER_PAGE_NUM  # 每页显示多少数据
        page_num_show = settings.PAGE_NUM_SHOW  # 显示的页码数
        customer_count = total_count
        div, mod = divmod(customer_count, per_page_num)
        if mod:
            page_num_count = div + 1
        else:
            page_num_count = div
        try:
            self.page = int(page)
        except Exception as e:
            self.page = 1
        if self.page <= 0:
            self.page = 1
        elif self.page > page_num_count:
            self.page = page_num_count
        self.page_num_count = page_num_count
        start_num = (self.page - 1) * per_page_num
        end_num = self.page * per_page_num
        page_num_half_show = page_num_show // 2
        page_num_start_show = self.page - page_num_half_show
        page_num_end_show = self.page + page_num_half_show + 1
        if page_num_start_show <= 0:  # 异常分页判断
            page_num_start_show = 1
            page_num_end_show = page_num_show + 1
        elif page_num_end_show > page_num_count:
            page_num_start_show = page_num_count - page_num_show + 1
            page_num_end_show = page_num_count + 1
        if page_num_count < page_num_end_show:
            page_num_end_show = page_num_count + 1
        self.start_num = start_num
        self.end_num = end_num
        self.page_num_start_show = page_num_start_show
        self.page_num_end_show = page_num_end_show

    @property
    def start_num_show(self):
        return self.start_num

    @property
    def end_num_show(self):
        return self.end_num

    def page_html(self):
        page_num_range = range(self.page_num_start_show, self.page_num_end_show)
        page_html = ''
        first_page_html = f'

首页
'
        page_html += first_page_html
        page_pre = ''
        page_html += page_pre
        if self.page <= 1:
            pre_page = f'
«
'
        else:
            pre_page = f'
«
'
        page_html += pre_page
        for i in page_num_range:
            if i == self.page:
                page_html += f'
{i}
'
            else:
                page_html += f'
{i}
'
        if self.page >= self.page_num_count:
            page_next_html = f'
»
 '
        else:
            page_next_html = f'
»
'
        page_html += page_next_html
        last_page_html = f'
尾页

'
        page_html += last_page_html
        return mark_safe(page_html)


import argparse
import torch
import os
from dataloader.transform.transform_cfg import transforms_list

def parse_option():
    parser = argparse.ArgumentParser('argument for training')
    parser.add_argument("--mode", type=str, choices=["bml", "global", "local"], default="bml")
    parser.add_argument('--backbone', type=str, choices=["Res12", "Res18"], default="Res12")
    parser.add_argument('--eval_freq', type=int, default=20, help='meta-eval frequency')
    parser.add_argument('--print_freq', type=int, default=100, help='print frequency')
    parser.add_argument('--save_freq', type=int, default=20, help='save frequency')
    parser.add_argument('--batch_size', type=int, default=128, help='batch_size')
    parser.add_argument('--num_workers', type=int, default=8, help='num of workers to use')
    parser.add_argument('--epochs', type=int, default=100, help='number of training epochs')

    # optimization
    parser.add_argument('--weight_decay', type=float, default=5e-4, help='weight decay')
    parser.add_argument('--momentum', type=float, default=0.9, help='momentum')
    parser.add_argument("--decay_step", type=int, default=40)
    parser.add_argument('--optim', type=str, choices=["adam", "SGD"], default="SGD")
    # dataset
    parser.add_argument('--dataset', type=str, default='miniImageNet', choices=['miniImageNet', 'tieredImageNet',
                                                                                'CIFAR-FS', 'FC100', "CUB"])
    parser.add_argument('--transform', type=str, default='A', choices=transforms_list)
    # meta setting
    parser.add_argument('--n_ways', type=int, default=5, metavar='N',
                        help='Number of classes for doing each classification run')
    parser.add_argument('--n_shots', type=int, default=5, metavar='N',
                        help='Number of shots in test')
    parser.add_argument('--n_queries', type=int, default=15, metavar='N',
                        help='Number of query in test')
    parser.add_argument('--n_train_ways', type=int, default=15, metavar='N',
                        help='Number of classes for doing each classification run')
    parser.add_argument('--n_train_shots', type=int, default=5, metavar='N',
                        help='Number of shots during train')
    parser.add_argument('--n_train_queries', type=int, default=7, metavar='N',
                        help='Number of query in test')
    parser.add_argument('--episodes', default=2000, help="test episode num")
    # bml setting
    parser.add_argument("--weights", type=str, default="2_1_0.5")
    parser.add_argument("--alpha_1", type=float, default=5.5)  # 2.5
    parser.add_argument("--alpha_2", type=float, default=0.1)
    parser.add_argument("--T", type=float, default=4.0)
    # spatial for single view training
    parser.add_argument("--spatial", action="store_true")
    # continue train
    parser.add_argument("--is_continue", action="store_true")
    # eval
    parser.add_argument("--is_eval", action="store_true")
    parser.add_argument("--ckp_path", type=str, default="")
    # save setting
    parser.add_argument('-s', '--save_folder', type=str, default='params')

    # DistributedDataParallel
    parser.add_argument("--local_rank", type=int, required=True, default=0, help='local rank for DistributedDataParallel')

    parser.add_argument('--amp_opt_level', type=str, default='O0', choices=['O0', 'O1', 'O2'],
                        help='mixed precision opt level, if O0, no amp is used')
    parser.add_argument("--seed", default='0', type=str)

    opt = parser.parse_args()
    opt.w = [float(i) for i in opt.weights.split('_')]
    assert (opt.transform == "A" and opt.dataset == "miniImageNet") or \
           (opt.transform == "B" and opt.dataset == "tieredImageNet") or \
           (opt.transform == "C" and opt.dataset == "FC100") or \
           (opt.transform == "D" and opt.dataset == "CIFAR-FS") or \
           (opt.transform == "E" and opt.dataset == "CUB")
    if opt.dataset == "miniImageNet" or opt.dataset == "CIFAR-FS":
        opt.n_cls = 64
    elif opt.dataset == "tieredImageNet":
        opt.n_cls = 351 + 97
    elif opt.dataset == 'FC100':
        opt.n_cls = 60
    elif opt.dataset == "CUB":
        opt.n_cls = 100
    else:
        raise ValueError("wrong dataset")
    if opt.mode == "global":
        opt.model_name = '{}_{}_{}_Trans_{}_bs{}_Optim_{}_SIM_{}'.format(
            opt.mode, opt.backbone, opt.dataset, opt.transform, opt.batch_size,
            opt.optim, opt.spatial)
    elif opt.mode == "local":
        opt.model_name = '{}_{}_{}_Trans_{}_N{}Q{}S{}_Optim_{}_SIM_{}'.format(
            opt.mode, opt.backbone, opt.dataset, opt.transform, opt.n_train_ways, opt.n_train_queries, opt.n_train_shots,
            opt.optim, opt.spatial)
    else:
        opt.model_name = '{}_{}_{}_Trans_{}_N{}Q{}S{}_Optim_{}_a1_{}_a2_{}_w_{}_T_{}'.format(
            opt.mode, opt.backbone, opt.dataset, opt.transform, opt.n_train_ways, opt.n_train_queries, opt.n_train_shots,
            opt.optim, opt.alpha_1, opt.alpha_2, opt.weights, opt.T)
    # if not opt.is_eval:
    os.makedirs(os.path.join(opt.save_folder, opt.model_name), exist_ok=True)
    opt.save_folder = os.path.join(opt.save_folder, opt.model_name)
    opt.SEED = 0
    if opt.is_eval:
        assert len(opt.ckp_path)
    if opt.optim == 'SGD':
        opt.initial_lr = 1e-1
    else:
        opt.initial_lr = 1e-3

    return opt


import torch
from lstm_autoencoder import CompositeModel
from data import GraspDataset
from torch.utils.data import DataLoader

def train():

    device = torch.device('cuda')

    model = CompositeModel(
        input_size=5,
        hidden_size=256,
        sequence_length=375,
        num_layers=1,
        batch_first=True,
        loss_path='./loss/loss_032019.csv'
    ).to(device)

    train_set = GraspDataset('train')
    valid_set = GraspDataset('valid')

    data_loader_train = DataLoader(
        dataset=train_set,
        batch_size=128,
        shuffle=False,
        num_workers=4,
        drop_last=True
    )

    data_loader_valid = DataLoader(
        dataset=valid_set,
        batch_size=250,
        shuffle=False,
        num_workers=2,
        drop_last=False
    )

    model.train_model(
        num_epochs=1500,
        data_loader_train=data_loader_train,
        data_loader_valid=data_loader_valid,
        checkpoint_path='./checkpoints/checkpoint_032019.pt',
        lr=1e-3,
        weight_decay=0.000001,
        sparsity_weight=0.01,
        device=device
    )

if __name__ == '__main__':
    train()


import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

# import
folder = './data'
folder_out = './results/Supplementary'
# PROCESSED DATA
file_in1 = 'mixedDS_IR_Binder/TCRex_processed/MetaForPlotting_viralTCRexPreds_withCounts_mixedDS_perSpecificity_Pt.tsv'
file_in2 = 'splitDS_IMSEQ/TCRex_processed/MetaForPlotting_viralTCRexPreds_withCounts_splitDS_intersected2x_meta_perSpecificity.tsv'

# IR-Binder public mixed dataset, patient data
tcr_per_virus_pt = pd.read_csv(f'{folder}/{file_in1}', sep='\t')
# IMSEQ in-house split dataset, only TCRs that occurred in at least 2 repeats
tcr_per_virus_inter = pd.read_csv(f'{folder}/{file_in2}', sep='\t')
# all patients are active in this dataset, adding a column to match mixedDS
tcr_per_virus_inter['disease_status'] = 'active'
# separating CD8 TCRs which will undergo further analysis
imseq_cd8 = tcr_per_virus_inter[tcr_per_virus_inter['T-cell_type'] == 'cd8']

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# merging CD8+ split and mixed datasets,
# keeping only relevant for further analysis columns
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
df1 = imseq_cd8[['study_patient_id', 'disease_severity', 'disease_status',
                 'critical_disease', 'day', 'week',
                 'total_count', 'unique_TCRs', 'Frac_CoV_TCRs',
                 'Frac_SARS-CoV-2_TCRs', 'Frac_SARS-CoV-2_only_TCRs',
                 'N_CoV_TCRs', 'N_SARS-CoV-2_only_TCRs', 'N_SARS-CoV-2_TCRs',
                 'N_SARS-CoV-2_Eps', 'N_SARS-CoV-2_only_Eps', 'N_CoV_Eps',
                 'all_SARS-CoV-2_epitopes']].copy()
df1.rename(columns={'study_patient_id': 'patient_id'}, inplace=True)
df1['source'] = 'IMSEQ'
df2 = tcr_per_virus_pt[
    ['patient_id', 'disease_severity', 'disease_status', 'critical_disease',
     'day', 'week',
     'total_count', 'unique_TCRs',
     'Frac_CoV_TCRs', 'Frac_SARS-CoV-2_TCRs', 'Frac_SARS-CoV-2_only_TCRs',
     'N_CoV_TCRs', 'N_SARS-CoV-2_only_TCRs', 'N_SARS-CoV-2_TCRs',
     'N_SARS-CoV-2_Eps', 'N_SARS-CoV-2_only_Eps',
     'N_CoV_Eps', 'all_SARS-CoV-2_epitopes']].copy()

# severe in this paper corresponds to critical in WHO grading
# (wasn't available yet when they were classifying patients)
df2.loc[df2['disease_severity'] == 'severe', 'disease_severity'] = 'critical'
df2['source'] = 'IR'

all_data = df1.append(df2)
# we are not interested in asymptomatic patients
all_data = all_data[all_data['disease_severity'] != 'asymptomatic']
all_data.sort_values(
    by=['critical_disease', 'disease_severity', 'day', 'patient_id'],
    inplace=True)
# clean up epitope column to remove [] and '' and transform epitopes per person
# to actual lists instead of list-looking strings
all_data['all_SARS-CoV-2_epitopes'] = all_data[
    'all_SARS-CoV-2_epitopes'].str.strip('[]').str.replace("'", "").str.split(
    ', ')
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# rescaling to [0:1] by subtracting min(value) and dividing by max(value)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# discussion about ways of rescaling
# https://stackoverflow.com/questions/703924/correct-way-to-standardize-scale-normalize-multiple-variables-following-power-la
df1['Frac_CoV_TCRs'] = (df1['Frac_CoV_TCRs'] - df1['Frac_CoV_TCRs'].min())\
                       / df1['Frac_CoV_TCRs'].max()
df1['Frac_SARS-CoV-2_TCRs'] = (df1['Frac_SARS-CoV-2_TCRs']
                               - df1['Frac_SARS-CoV-2_TCRs'].min())\
                              / df1['Frac_SARS-CoV-2_TCRs'].max()
df1['Frac_SARS-CoV-2_only_TCRs'] = (df1['Frac_SARS-CoV-2_only_TCRs']
                                    - df1['Frac_SARS-CoV-2_only_TCRs'].min())\
                                   / df1['Frac_SARS-CoV-2_only_TCRs'].max()

df2['Frac_CoV_TCRs'] = (df2['Frac_CoV_TCRs'] - df2['Frac_CoV_TCRs'].min())\
                       / df2['Frac_CoV_TCRs'].max()
df2['Frac_SARS-CoV-2_TCRs'] = (df2['Frac_SARS-CoV-2_TCRs']
                               - df2['Frac_SARS-CoV-2_TCRs'].min())\
                              / df2['Frac_SARS-CoV-2_TCRs'].max()
df2['Frac_SARS-CoV-2_only_TCRs'] = (df2['Frac_SARS-CoV-2_only_TCRs']
                                    - df2['Frac_SARS-CoV-2_only_TCRs'].min())\
                                   / df2['Frac_SARS-CoV-2_only_TCRs'].max()
all_data_scaled = df1.append(df2)

# we are not interested in asymptomatic patients (-1 row from 'mixed' DS)
all_data_scaled = all_data_scaled[
    all_data_scaled['disease_severity'] != 'asymptomatic']
all_data_scaled.sort_values(by=['critical_disease', 'patient_id', 'day'],
                            inplace=True)

all_data_scaled['%unique_TCRs'] = (all_data_scaled['unique_TCRs'] /
                                   all_data_scaled['total_count']) * 100

# calculating Epitope proportion out of uniqueTCRs
all_data_scaled['%CoV-common_Eps'] = 100 * all_data_scaled['N_CoV_Eps']\
                                     / all_data_scaled['unique_TCRs']
all_data_scaled['%SC2-unique_Eps'] = 100 * all_data_scaled[
    'N_SARS-CoV-2_only_Eps'] / all_data_scaled['unique_TCRs']

# rescaling of N of epitopes to median repertoire size
median_TCRs = all_data_scaled['unique_TCRs'].median()  # 6394
all_data_scaled['scaled_N_CoV-common_Eps'] = all_data_scaled['N_CoV_Eps']\
                                             * median_TCRs\
                                             / all_data_scaled['unique_TCRs']
all_data_scaled['scaled_N_SC2-unique_Eps'] = all_data_scaled[
                                                 'N_SARS-CoV-2_only_Eps'] \
                                             * median_TCRs \
                                             / all_data_scaled['unique_TCRs']

# calculating proportion of different specific TCRs out of uniqueTCRs
all_data_scaled['%CoV-common_TCRs'] = 100 * all_data_scaled['N_CoV_TCRs'] / \
                                      all_data_scaled['unique_TCRs']
all_data_scaled['%SC2-unique_TCRs'] = 100 * all_data_scaled[
    'N_SARS-CoV-2_only_TCRs'] / all_data_scaled['unique_TCRs']
all_data_scaled['%allSC2_TCRs'] = 100 * all_data_scaled['N_SARS-CoV-2_TCRs'] / \
                                  all_data_scaled['unique_TCRs']

all_data_scaled = all_data_scaled[['patient_id', 'disease_status',
                                   'disease_severity', 'critical_disease',
                                   'day', 'week',
                                   'total_count', 'unique_TCRs',
                                   '%unique_TCRs',
                                   'Frac_CoV_TCRs',
                                   'Frac_SARS-CoV-2_only_TCRs',
                                   'N_CoV_TCRs', '%CoV-common_TCRs',
                                   'N_SARS-CoV-2_only_TCRs',
                                   '%SC2-unique_TCRs',
                                   'N_SARS-CoV-2_TCRs', '%allSC2_TCRs',
                                   'N_CoV_Eps', 'scaled_N_CoV-common_Eps',
                                   '%CoV-common_Eps',
                                   'N_SARS-CoV-2_only_Eps',
                                   'scaled_N_SC2-unique_Eps',
                                   '%SC2-unique_Eps',
                                   'Frac_SARS-CoV-2_TCRs', 'N_SARS-CoV-2_Eps',
                                   'all_SARS-CoV-2_epitopes', 'source']]
all_data_scaled.reset_index(drop=True, inplace=True)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# FigS2-c number of days sampled per patient
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mpl.rcParams['font.family'] = 'Arial'
fig = plt.figure(figsize=(6.6, 5))
ax = sns.histplot(all_data_scaled.groupby('patient_id')['day'].nunique(),
                  stat="count", discrete=True, color='tab:green')
ax.set(xlabel='No. of data points per patient', ylabel='No. of patients')
plt.tight_layout()
plt.savefig(f'{folder_out}/FigS2c_N_dataPoints_perPerson.jpg', dpi=600)
plt.close()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# FigS4extra - longitudinal dynamics per person (in case I need form the whole DS)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
long_data_only = all_data_scaled[all_data_scaled.duplicated(subset='patient_id',
                                                            keep=False)].copy()
for parameter in ['Frac_CoV_TCRs', 'Frac_SARS-CoV-2_only_TCRs']:
    mpl.rcParams['font.family'] = 'Arial'
    fig = plt.figure(figsize=(6.6, 5))
    sns.lineplot(x='week', y=parameter, data=long_data_only,
                 hue_order=['Yes', 'No'], hue='critical_disease',
                 palette={'No': 'tab:blue', 'Yes': 'tab:orange'},
                 style='patient_id', markers=True, dashes=False)
    plt.ylabel(parameter)
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.2), ncol=6)
    plt.tight_layout()
    plt.savefig(f'{folder_out}/FigS4_PersonDyn_{parameter}.png')
    plt.close()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# TCR to Epitope ratio for Fig7abc
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_data_scaled['CoV-common_TCR-Ep_ratio'] = all_data_scaled['N_CoV_TCRs'] \
                                                      / all_data_scaled['N_CoV_Eps']
all_data_scaled['SC2-unique_TCR-Ep_ratio'] = all_data_scaled['N_SARS-CoV-2_only_TCRs'] \
                                                      / all_data_scaled['N_SARS-CoV-2_only_Eps']
# for statistics
crit = all_data_scaled[
    (all_data_scaled['critical_disease'] == 'Yes')]
noncrit = all_data_scaled[(all_data_scaled['critical_disease'] == 'No') &
                          (all_data_scaled['disease_status'] == 'recovered')]
noncrit_active = all_data_scaled[(all_data_scaled['critical_disease'] == 'No') &
                                 (all_data_scaled['disease_status'] == 'active')]

print(f"Median TCR/SC2-unique_Epitope ratio in critical patients: "
      f"{crit['SC2-unique_TCR-Ep_ratio'].describe()[5]}; "
      f"range=[{crit['SC2-unique_TCR-Ep_ratio'].describe()[3]}-"
      f"{crit['SC2-unique_TCR-Ep_ratio'].describe()[7]}]")
print(f"Median TCR/CoV-common_Epitope ratio in critical patients: "
      f"{crit['CoV-common_TCR-Ep_ratio'].describe()[5]}; "
      f"range=[{crit['CoV-common_TCR-Ep_ratio'].describe()[3]}-"
      f"{crit['CoV-common_TCR-Ep_ratio'].describe()[7]}]")

print(f"Median TCR/SC2-unique_Epitope ratio in non-critical active patients: "
      f"{noncrit_active['SC2-unique_TCR-Ep_ratio'].describe()[5]}; "
      f"range=[{noncrit_active['SC2-unique_TCR-Ep_ratio'].describe()[3]}-"
      f"{noncrit_active['SC2-unique_TCR-Ep_ratio'].describe()[7]}]")
print(f"Median TCR/CoV-common_Epitope ratio in non-critical active patients: "
      f"{noncrit_active['CoV-common_TCR-Ep_ratio'].describe()[5]}; "
      f"range=[{noncrit_active['CoV-common_TCR-Ep_ratio'].describe()[3]}-"
      f"{noncrit_active['CoV-common_TCR-Ep_ratio'].describe()[7]}]")

print(f"Median TCR/SC2-unique_Epitope ratio in non-critical recovered patients: "
      f"{noncrit['SC2-unique_TCR-Ep_ratio'].describe()[5]}; "
      f"range=[{noncrit['SC2-unique_TCR-Ep_ratio'].describe()[3]}-"
      f"{noncrit['SC2-unique_TCR-Ep_ratio'].describe()[7]}]")
print(f"Median TCR/CoV-common_Epitope ratio in non-critical recovered patients: "
      f"{noncrit['CoV-common_TCR-Ep_ratio'].describe()[5]}; "
      f"range=[{noncrit['CoV-common_TCR-Ep_ratio'].describe()[3]}-"
      f"{noncrit['CoV-common_TCR-Ep_ratio'].describe()[7]}]")

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# keeping only max of a week for each person for further week Max analysis
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_data_scaled_week_max = all_data_scaled.copy()
# assign to all days of the same week of the same patient
# the maximum values of the parameter for this week
for parameter in ['total_count', 'unique_TCRs', '%unique_TCRs',
                  'Frac_CoV_TCRs', 'Frac_SARS-CoV-2_only_TCRs',
                  'N_CoV_TCRs', '%CoV-common_TCRs', 'N_SARS-CoV-2_only_TCRs',
                  '%SC2-unique_TCRs',
                  'N_CoV_Eps', 'scaled_N_CoV-common_Eps', '%CoV-common_Eps',
                  'N_SARS-CoV-2_only_Eps', 'scaled_N_SC2-unique_Eps',
                  '%SC2-unique_Eps',
                  'Frac_SARS-CoV-2_TCRs', 'N_SARS-CoV-2_Eps',
                  'N_SARS-CoV-2_TCRs', '%allSC2_TCRs']:
    if parameter == 'N_SARS-CoV-2_Eps':
        # to keep the maximum of recognized epitopes from the same week
        all_data_scaled_week_max.sort_values(['patient_id', 'week', parameter],
                                             ascending=False, inplace=True)
        all_data_scaled_week_max['all_SARS-CoV-2_epitopes'] = \
            all_data_scaled_week_max.loc[
                all_data_scaled_week_max.groupby(['patient_id', 'week'])[
                    parameter].idxmax(), 'all_SARS-CoV-2_epitopes']
        all_data_scaled_week_max['all_SARS-CoV-2_epitopes'].fillna(
            method='ffill', inplace=True)
        all_data_scaled_week_max[parameter] = \
            all_data_scaled_week_max.groupby(['patient_id', 'week'])[
                parameter].transform('max')
    else:
        all_data_scaled_week_max[parameter] = \
            all_data_scaled_week_max.groupby(['patient_id', 'week'])[
                parameter].transform('max')

# sort so active is before recovered because
# if there are two data points in one week when one point is from active
# and another from recovered state, we want to keep the active record
all_data_scaled_week_max.sort_values(
    by=['critical_disease', 'patient_id', 'week', 'disease_status'],
    ascending=True, inplace=True, ignore_index=True)
# keep only 1 record with the highest value of the week
all_data_scaled_week_max.drop_duplicates(['patient_id', 'week'],
                                         keep='first', inplace=True)
all_data_scaled_week_max.to_csv(
    f'{folder}/SplitMixed_mergedCD8_scaled_weekMax.tsv', sep='\t', index=False)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# FigS2-a hist of merged data distribution per disease severity as is
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mpl.rcParams['font.family'] = 'Arial'
fig = plt.figure(figsize=(6.6, 5))
sns.countplot(x='week', hue='disease_severity', data=all_data_scaled_week_max,
              palette={'mild': 'tab:cyan', 'moderate': 'tab:blue',
                       'severe': 'tab:grey',
                       'critical': 'tab:orange', 'fatal': 'tab:red'},
              hue_order=['mild', 'moderate', 'severe', 'critical', 'fatal'],
              dodge=True)  # palette='gist_heat_r')
plt.legend(loc='upper right', title='Disease severity')
plt.xlabel('week')
plt.ylabel('No. of patients')
plt.savefig(f'{folder_out}/FigS2a_severity_distribution.jpg', dpi=600)
plt.close()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# FigS2-b hist of merged data distribution per patient group - critical/non-critical
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mpl.rcParams['font.family'] = 'Arial'
fig = plt.figure(figsize=(6.6, 5))
sns.countplot(x='week', hue='critical_disease', data=all_data_scaled_week_max,
              hue_order=['No', 'Yes'],
              dodge=True, palette={'No': 'tab:blue', 'Yes': 'tab:orange'})
plt.legend(loc='upper right', title='Patient group',
           labels=['Non-critical', 'Critical'])
plt.xlabel('week')
plt.ylabel('No. of patients')
plt.savefig(f'{folder_out}/FigS2b_criticals_distribution.jpg', dpi=600)
plt.close()


import video_maker
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras

# Create initial model
def create_model(function_name, layers, neurons):
    # Define the model architecture
    model = keras.Sequential([
        keras.layers.Dense(neurons, activation="sigmoid", input_shape=(1,)),
    ])

    for _ in range(layers - 1):
        model.add(keras.layers.Dense(neurons, activation="sigmoid"))

    model.add(keras.layers.Dense(1))
    model.save(f"models/{function_name}_model.h5")

    model.compile(optimizer="adam", loss="mean_squared_error")

    return model

# Create train/test data for the model
def create_data(function_name, length):
    # Generate sine data
    if function_name == "sine":
        x = np.linspace(0, length * np.pi, length * 100)
        y = np.sin(x)

    elif function_name == "cosine":
        x = np.linspace(0, length * np.pi, length * 100)
        y = np.cos(x)

    elif function_name == "tangent":
        x = np.linspace(-(length / 2) * np.pi, (length / 2) * np.pi, length * 100)
        y = np.tan(x)

    elif function_name == "cotangent":
        x = np.linspace(-(length / 2) * np.pi, (length / 2) * np.pi, length * 100)
        y = 1 / np.tan(x)

    return x, y

# Train the model. Return a video if desired
def use_model(model, x, y, cycles, function_name, update_label_text, video_check):
    if video_check == 1:
        frame_writer = video_maker.create_video_formatter(function_name)

    # Train the model
    for cycle in range(cycles):
        model.fit(x, y, epochs=100, verbose=1)
        y_pred = model.predict(x)

        fig, ax = plt.subplots()
        ax.plot(x, y, label="Original")
        ax.plot(x, y_pred, label="Predicted")
        ax.set_title(f"{function_name.capitalize()} Wave Prediction")
        ax.legend()

        if function_name == "sine" or function_name == "cosine":
            ax.set_ylim(-1.2, 1.2)

        elif function_name == "tangent" or function_name == "cotangent":
            ax.set_ylim(-5, 5)

        # Save the current plot as an image file
        fig.savefig(f"plot_images/plot_{str(cycle)}.png")
        plt.close(fig)

        if video_check == 1:
            video_maker.add_frame(frame_writer, cycle)

        update_label_text(f"{cycle + 1} / {cycles} Cycles")

    if video_check == 1:
        video_maker.release_video(frame_writer)

    history = model.fit(x, y, epochs=100, verbose=1)
    final_loss = history.history["loss"][-1]

    if final_loss > 999999999:
        return "A lot"

    else:
        return str("{:.8f}".format(final_loss))


from django.shortcuts import render, redirect, HttpResponseRedirect
from django.contrib import auth
from django.contrib.auth.forms import AuthenticationForm
from django.core.urlresolvers import reverse
from information.views import teacher_subject_list, speciality_list

# Create your views here.

def login(request):
	form = AuthenticationForm(request, request.POST or None)
	if request.POST:
		if form.is_valid():
			auth.login(request, form.get_user())
			return HttpResponseRedirect(reverse("teacher_subject_list"))
		else:
			return render(request, 'login.html', {'form': form})
	else:
		return render(request, 'login.html', {'form': form})

def logout(request):
	auth.logout(request)
	return HttpResponseRedirect(reverse('speciality_list'))


#!/usr/bin/python3 -B
# -*- coding: utf-8 -*- line endings: unix -*-
__author__ = 'quixadhal'

import os
import sys
import datetime
sys.path.append(os.path.join(os.getcwd(), "Mud"))

# Normally, we always import logging and initialize it BEFORE anything
# else, but in this case, we first need to add to our module search
# path, so we'll trust nothing will explode in os or sys at the top
# level here.

from Mud.log_system import Logger
logger = Logger()

from Mud.cli_args import CLI_Args
from Mud.signals import setup_signals
from Mud.game_data import Game_Data

def changedir(pathname):
    if pathname is not None:
        try:
            os.chdir(pathname)
        except FileNotFoundError as err:
            logger.critical('Invalid directory: %s', err)
            sys.exit(2)
        except PermissionError as err:
            logger.critical('Invalid directory: %s', err)
            sys.exit(2)
    return True

def makepid(pathname):
    if pathname is not None:
        try:
            f = open(pathname, 'w')
            f.write(str(os.getpid()))
            f.close()
        except FileNotFoundError as err:
            logger.critical('Invalid PID file: %s', err)
            sys.exit(2)
        except PermissionError as err:
            logger.critical('Invalid PID file: %s', err)
            sys.exit(2)
    return True

def removefile(pathname):
    if pathname is not None:
        try:
            os.unlink(pathname)
        except FileNotFoundError as err:
            return True
        except PermissionError as err:
            logger.critical('Invalid file: %s', err)
            sys.exit(2)
    return True

if __name__ == '__main__':
    logger.boot('System initializing.')
    start_time = datetime.datetime.utcnow()
    args = CLI_Args()

    changedir(args.directory)
    makepid(args.pidfile)
    removefile(args.logfile)
    logger.start_filelog(args.logfile)

    logger.boot('System booting.')
    logger.info(args)
    logger.info("Player port is %d" % args.port)

    # Here is where we call the outer game loop
    # In wiley's comm.c, that would be run_the_game()

    # set descriptor list to empty
    setup_signals()
    # s = init_socket(port) # Main socket connection
    gameData = Game_Data()
    gameData.import_wileymud()
    # load_db()
    # init_whod(port) # web server who daemon
    # i3_startup(false, 3000, false)
    # game_loop()
    # i3_shutdown()
    # close_sockets(s)
    # close_whod()
    # unload_db()
    # if reboot message about rebooting, return reboot code
    # else message about shutdown, return shutdown code

    # And here we'd be done with that...

    run_length = datetime.datetime.utcnow() - start_time
    logger.info('System was up for %s' % run_length)

    logger.critical('System halting.')
    removefile(args.pidfile)
    logger.stop_filelog()
    logger.critical('System halted.')


"""This module initializes the app"""

import sys
import logging
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication

from controllers.main_controller import MainWindowController
from views.main_view import MainWindowView
from model.main_model import Model

class App(QApplication):
    """
    A class used to represent applicationa

    Attributes
    ----------
    sys_argv: command lines argument

    Methods
    -------
    close_event(self)
    """

    def __init__(self, sys_argv):
        super().__init__(sys_argv)

        test_mode = False
        if sys_argv[1] == "--test_config":
            test_mode = True
        self.app = QApplication(sys_argv)
        self.model = Model()
        self.controller = MainWindowController(self.model)
        self.main_view = MainWindowView(self.controller, test_mode)

        self.controller.on_start_up()

        self.main_view.show()

        if sys_argv[1] == "--test_config":
            print(f"Got our argument from command line: {sys_argv[1]}")

        self.app.aboutToQuit.connect(self.close_event)

    def close_event(self):
        """Call the function clean from model.py"""
        self.model.clean()

if __name__ == "__main__":
    logging.basicConfig(filename='todolist.log', encoding='utf-8', level=logging.DEBUG)
    app = App(sys.argv)
    app.setWindowIcon(QtGui.QIcon("app_icon.png"))

    SSH_FILE = "/Users/katestepanova/repos/to_do_list_app/style.qss"
    with open(SSH_FILE, "r", encoding='utf-8') as fh:
        _style = fh.read()
        print("Style is loaded")
        app.setStyleSheet(_style)

    sys.exit(app.exec())


import numpy as np
from keras.models import model_from_json

def num_captured(board):
	return 12 - np.sum(board < 0)

def num_branches(board, x, y):
	count = 0
	if (board[x, y] >= 1 and x < 6):
		if (y < 6):
			if (board[x+1, y+1] < 0 and board[x+2, y+2] == 0):
				board[x+2, y+2] = board[x, y]
				board[x, y] = 0
				temp = board[x+1, y+1]
				board[x+1, y+1] = 0
				count += num_branches(board, x+2, y+2) + 1
				board[x+1, y+1] = temp
				board[x, y] = board[x+2, y+2]
				board[x+2, y+2] = 0
		if (y > 1):
			if (board[x+1, y-1] < 0 and board[x+2, y-2] == 0):
				board[x+2, y-2] = board[x, y]
				board[x, y] = 0
				temp = board[x+1, y-1]
				board[x+1, y-1] = 0
				count += num_branches(board, x+2, y-2) + 1
				board[x+1, y-1] = temp
				board[x, y] = board[x+2, y-2]
				board[x+2, y-2] = 0
	if (board[x, y] == 3 and x > 0):
		if (y < 6):
			if (board[x-1, y+1] < 0 and board[x-2, y+2] == 0):
				board[x-2, y+2] = board[x, y]
				board[x, y] = 0
				temp = board[x-1, y+1]
				board[x-1, y+1] = 0
				count += num_branches(board, x-2, y+2) + 1
				board[x-1, y+1] = temp
				board[x, y] = board[x-2, y+2]
				board[x-2, y+2] = 0
		if (y > 1):
			if (board[x-1, y-1] < 0 and board[x-2, y-2] == 0):
				board[x-2, y-2] = board[x, y]
				board[x, y] = 0
				temp = board[x-1, y-1]
				board[x-1, y-1] = 0
				count += num_branches(board, x-2, y-2) + 1
				board[x-1, y-1] = temp
				board[x, y] = board[x-2, y-2]
				board[x-2, y-2] = 0
	return count

def possible_moves(board):
	count = 0
	for i in range(0, 8):
		for j in range(0, 8):
			if (board[i, j] > 0):
				count += num_branches(board, i, j)
	if (count > 0):
		return count
	for i in range(0, 8):
		for j in range(0, 8):
			if (board[i, j] >= 1 and i < 7):
				if (j < 7):
					count += (board[i+1, j+1] == 0)
				if (j > 0):
					count += (board[i+1, j-1] == 0)
			if (board[i, j] == 3 and i > 0):
				if (j < 7):
					count += (board[i-1, j+1] == 0)
				elif (j > 0):
					count += (board[i-1, j-1] == 0)
	return count

def game_winner(board):
	if (np.sum(board < 0) == 0):
		return 1
	elif (np.sum(board > 0) == 0):
		return -1
	if (possible_moves(board) == 0):
		return -1
	elif (possible_moves(reverse(board)) == 0):
		return 1
	else:
		return 0

def at_enemy(board):
	count = 0
	for i in range(5, 8):
		count += np.sum(board[i] == 1) + np.sum(board[i] == 3)
	return count

def at_middle(board):
	count = 0
	for i in range(3, 5):
		count += np.sum(board[i] == 1) + np.sum(board[i] == 3)
	return count

def num_men(board):
	return np.sum(board == 1)

def num_kings(board):
	return np.sum(board == 3)

def capturables(board): # possible number of unsupported enemies
	count = 0
	for i in range(1, 7):
		for j in range(1, 7):
			if (board[i, j] < 0):
				count += (board[i+1, j+1] >= 0 and board[i+1, j-1] >= 0 and  board[i-1, j+1] >= 0 and board[i-1, j-1] >= 0)
	return count

def semicapturables(board): # number of own units with at least one support
	return (12 - uncapturables(board) - capturables(reverse(board)))

def uncapturables(board): # number of own units that can't be captured
	count = 0
	for i in range(1, 7):
		for j in range(1, 7):
			if (board[i, j] > 0):
				count += ((board[i+1, j+1] > 0 < board[i+1, j-1]) or (board[i-1, j+1] > 0 < board[i-1, j-1]) or (board[i+1, j+1] > 0 < board[i-1, j+1]) or (board[i+1, j-1] > 0 < board[i-1, j-1]))
	count += np.sum(board[0] == 1) + np.sum(board[0] == 3) + np.sum(board[1:7, 0] == 1) + np.sum(board[1:7, 0] == 3) + np.sum(board[7] == 1) + np.sum(board[7] == 3) + np.sum(board[1:7, 7] == 1) + np.sum(board[1:7, 7] == 3)
	return count

def reverse(board):
	b = -board
	b = np.fliplr(b)
	b = np.flipud(b)
	return b

def get_metrics(board): # returns [label, 10 labeling metrics]
	b = expand(board)

	capped = num_captured(b)
	potential = possible_moves(b) - possible_moves(reverse(b))
	men = num_men(b) - num_men(-b)
	kings = num_kings(b) - num_kings(-b)
	caps = capturables(b) - capturables(reverse(b))
	semicaps = semicapturables(b)
	uncaps = uncapturables(b) - uncapturables(reverse(b))
	mid = at_middle(b) - at_middle(-b)
	far = at_enemy(b) - at_enemy(reverse(b))
	won = game_winner(b)

	score = capped + potential + men + kings + caps + semicaps + uncaps + mid + far + won
	if (score < 0):
		return np.array([-1, capped, potential, men, kings, caps, semicaps, uncaps, mid, far, won])
	else:
		return np.array([1, capped, potential, men, kings, caps, semicaps, uncaps, mid, far, won])

def np_board():
	return np.array(get_board())

def get_board():
	return [1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  0, 0, 0, 0,  0, 0, 0, 0,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1]

def expand(board):
	b = np.zeros((8, 8), dtype='b')
	for i in range(0, 8):
		if (i%2 == 0):
			b[i] = np.array([0, board[i*4], 0, board[i*4 + 1], 0, board[i*4 + 2], 0, board[i*4 + 3]])
		else:
			b[i] = np.array([board[i*4], 0, board[i*4 + 1], 0, board[i*4 + 2], 0, board[i*4 + 3], 0])
	return b

def compress(board):
	b = np.zeros((1,32), dtype='b')
	for i in range(0, 8):
		if (i%2 == 0):
			b[0, i*4 : i*4+4] = np.array([board[i, 1], board[i, 3], board[i, 5], board[i, 7]])
		else:
			b[0, i*4 : i*4+4] = np.array([board[i, 0], board[i, 2], board[i, 4], board[i, 6]])
	return b

def generate_branches(board, x, y):
	bb = compress(board)
	if (board[x, y] >= 1 and x < 6):
		temp_1 = board[x, y]
		if (y < 6):
			if (board[x+1, y+1] < 0 and board[x+2, y+2] == 0):
				board[x+2, y+2] = board[x, y]
				if (x+2 == 7):
					board[x+2, y+2] = 3
				temp = board[x+1, y+1]
				board[x+1, y+1] = 0
				if (board[x, y] != board[x+2, y+2]):
					board[x, y] = 0
					bb = np.vstack((bb, compress(board)))
				else:
					board[x, y] = 0
					bb = np.vstack((bb, generate_branches(board, x+2, y+2)))
				board[x+1, y+1] = temp
				board[x, y] = temp_1
				board[x+2, y+2] = 0
		if (y > 1):
			if (board[x+1, y-1] < 0 and board[x+2, y-2] == 0):
				board[x+2, y-2] = board[x, y]
				if (x+2 == 7):
					board[x+2, y-2] = 3
				temp = board[x+1, y-1]
				board[x+1, y-1] = 0
				if (board[x, y] != board[x+2, y-2]):
					board[x, y] = 0
					bb = np.vstack((bb, compress(board)))
				else:
					board[x, y] = 0
				bb = np.vstack((bb, generate_branches(board, x+2, y-2)))
				board[x+1, y-1] = temp
				board[x, y] = temp_1
				board[x+2, y-2] = 0
	if (board[x, y] == 3 and x > 0):
		if (y < 6):
			if (board[x-1, y+1] < 0 and board[x-2, y+2] == 0):
				board[x-2, y+2] = board[x, y]
				board[x, y] = 0
				temp = board[x-1, y+1]
				board[x-1, y+1] = 0
				bb = np.vstack((bb, generate_branches(board, x-2, y+2)))
				board[x-1, y+1] = temp
				board[x, y] = board[x-2, y+2]
				board[x-2, y+2] = 0
		if (y > 1):
			if (board[x-1, y-1] < 0 and board[x-2, y-2] == 0):
				board[x-2, y-2] = board[x, y]
				board[x, y] = 0
				temp = board[x-1, y-1]
				board[x-1, y-1] = 0
				bb = np.vstack((bb, generate_branches(board, x-2, y-2)))
				board[x-1, y-1] = temp
				board[x, y] = board[x-2, y-2]
				board[x-2, y-2] = 0
	return bb

def generate_next(board):
	bb = np.array([get_board()])
	for i in range(0, 8):
		for j in range(0, 8):
			if (board[i, j] > 0):
				bb = np.vstack((bb, generate_branches(board, i, j)[1:]))
	if (len(bb) > 1):
		return bb[1:]
	for i in range(0, 8):
		for j in range(0, 8):
			if (board[i, j] >= 1 and i < 7):
				temp = board[i, j]
				if (j < 7):
					if (board[i+1, j+1] == 0):
						board[i+1, j+1] = board[i, j]
						if (i+1 == 7):
							board[i+1, j+1] = 3
						board[i, j] = 0
						bb = np.vstack((bb, compress(board)))
						board[i, j] = temp
						board[i+1, j+1] = 0
				if (j > 0):
					if (board[i+1, j-1] == 0):
						board[i+1, j-1] = board[i, j]
						if (i+1 == 7):
							board[i+1, j-1] = 3
						board[i, j] = 0
						bb = np.vstack((bb, compress(board)))
						board[i, j] = temp
						board[i+1, j-1] = 0
			if (board[i, j] == 3 and i > 0):
				if (j < 7):
					if (board[i-1, j+1] == 0):
						board[i-1, j+1] = board[i, j]
						board[i, j] = 0
						bb = np.vstack((bb, compress(board)))
						board[i, j] = board[i-1, j+1]
						board[i-1, j+1] = 0
				elif (j > 0):
					if (board[i-1, j-1] == 0):
						board[i-1, j-1] = board[i, j]
						board[i, j] = 0
						bb = np.vstack((bb, compress(board)))
						board[i, j] = board[i-1, j-1]
						board[i-1, j-1] = 0
	return bb[1:]

json_file = open('rl.json', 'r') # disc = rl
disc_json = json_file.read()
json_file.close()

meta_model = model_from_json(disc_json)
meta_model.load_weights('rl.h5')
meta_model.compile(optimizer='nadam', loss='mean_squared_error')

base_model = model_from_json(disc_json)
base_model.load_weights('rl.h5')
base_model.compile(optimizer='nadam', loss='mean_squared_error')

data = np.zeros((1, 32))
labels = np.zeros(1)
win = lose = draw = 0
for gen in range(0, 150):
	for game in range(0, 200):
		temp_data = np.zeros((1, 32))
		board = expand(np_board())
		player = np.sign(np.random.random() - 0.5)
		turn = 0
		while (True):
			moved = False
			boards = np.zeros((0, 32))
			if (player == 1):
				boards = generate_next(board)
			else:
				boards = generate_next(reverse(board))

			score = meta_model.predict_on_batch(boards) if (player == 1)  else base_model.predict_on_batch(boards)

			max = [0, score[0, 0]]
			for i, x in enumerate(score[:, 0]):
				if (x >= max[1] and np.random.random() > 0.1) or not moved:
					moved = True
					max = [i, x]

			if (player == 1):
				board = expand(boards[max[0]])
				temp_data = np.vstack((temp_data, compress(board)))
			else:
				board = reverse(expand(boards[max[0]]))

			if (game == 199 and gen > 145):
				print('\nTurn player: %d - Confidence = %f' %(player, max[1]))
				print(board)
			player = -player

			# punish losers more for short games, reward winners more for longer games
			winner = game_winner(board)
			if (winner == 1):
				win = win + 1
				temp_labels = meta_model.predict_on_batch(temp_data[1:]) + (np.reshape(np.linspace(0.0001, 0.001, temp_data.shape[0] - 1), (temp_data.shape[0]-1, 1)) * (turn))
				data = np.vstack((data, temp_data[1:]))
				labels = np.vstack((labels, temp_labels))
				break
			elif (turn >= 200 or winner == -1):
				if (winner == - 1):
					lose = lose + 1
				else:
					draw = draw + 1
				temp_labels = meta_model.predict_on_batch(temp_data[1:]) - (np.reshape(np.linspace(0.0001, 0.001, temp_data.shape[0] - 1), (temp_data.shape[0]-1, 1)) * (201 - turn))
				data = np.vstack((data, temp_data[1:]))
				labels = np.vstack((labels, temp_labels))
				break
			turn = turn + 1
		print(np.array([gen*200 + game, win, lose, draw]))
		if ((game+1) % 100 == 0):
			meta_model.fit(data[1:], labels[1:], epochs=32, batch_size=256, verbose=0)
			if ((game+1) % 10 == 0 and np.random.random() > 0.5):
				data = np.zeros((1, 32))
				labels = np.zeros(1)

	meta_model.save_weights('rl.h5')

	base_model.load_weights('rl.h5')
	base_model.compile(optimizer='nadam', loss='mean_squared_error')


from django.views import View
from django.contrib import messages
from django.shortcuts import redirect, render
from littlecms.models import Article, MenuOption
from django.utils.translation import gettext_lazy as _

# Create your views here.
class BaseCmsView(View):

    def get(self, request, menu_option_slug=None):

        if not menu_option_slug:
            menu_option = MenuOption.objects.filter(order=0)
        else:
            menu_option = MenuOption.objects.filter(slug=menu_option_slug)
        if menu_option:
            menu_option = menu_option.first()
            template = 'littlecms/base.html'
            if menu_option.page:
                template = menu_option.page.template if menu_option.page.template else template
            context = {'menu_option': menu_option}
            return render(request, template, context)
        else:
            messages.error(request, _('No se encontró la opción solicitada.'+request.path))
            return redirect('/')

class ArticleDetailView(View):

    def get(self, request, menu_option_slug, article_slug):

        menu_option = MenuOption.objects.filter(slug=menu_option_slug)
        article = Article.objects.filter(slug=article_slug)
        if menu_option and article:
            menu_option = menu_option.first()
            article = article.first()
            context = {'menu_option': menu_option, 'article': article}
            return render(request, 'littlecms/article_detail.html', context)
        else:
            messages.error(request, _('No se encontró la opción solicitada'))
            return render(request, 'littlecms/article_detail.html')


import sys
from unittest import TestCase
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO  # doesn't accept 'str' in Py2

from .. import Options
from ..CmdLine import parse_command_line

class CmdLineParserTest(TestCase):
    def setUp(self):
        backup = {}
        for name, value in vars(Options).items():
            backup[name] = value
        self._options_backup = backup

    def tearDown(self):
        no_value = object()
        for name, orig_value in self._options_backup.items():
            if getattr(Options, name, no_value) != orig_value:
                setattr(Options, name, orig_value)

    def test_short_options(self):
        options, sources = parse_command_line([
            '-V', '-l', '-+', '-t', '-v', '-v', '-v', '-p', '-D', '-a', '-3',
        ])
        self.assertFalse(sources)
        self.assertTrue(options.show_version)
        self.assertTrue(options.use_listing_file)
        self.assertTrue(options.cplus)
        self.assertTrue(options.timestamps)
        self.assertTrue(options.verbose >= 3)
        self.assertTrue(Options.embed_pos_in_docstring)
        self.assertFalse(Options.docstrings)
        self.assertTrue(Options.annotate)
        self.assertEqual(options.language_level, 3)

        options, sources = parse_command_line([
            '-f', '-2', 'source.pyx',
        ])
        self.assertTrue(sources)
        self.assertTrue(len(sources) == 1)
        self.assertFalse(options.timestamps)
        self.assertEqual(options.language_level, 2)

    def test_long_options(self):
        options, sources = parse_command_line([
            '--version', '--create-listing', '--cplus', '--embed', '--timestamps',
            '--verbose', '--verbose', '--verbose',
            '--embed-positions', '--no-docstrings', '--annotate', '--lenient',
        ])
        self.assertFalse(sources)
        self.assertTrue(options.show_version)
        self.assertTrue(options.use_listing_file)
        self.assertTrue(options.cplus)
        self.assertEqual(Options.embed, 'main')
        self.assertTrue(options.timestamps)
        self.assertTrue(options.verbose >= 3)
        self.assertTrue(Options.embed_pos_in_docstring)
        self.assertFalse(Options.docstrings)
        self.assertTrue(Options.annotate)
        self.assertFalse(Options.error_on_unknown_names)
        self.assertFalse(Options.error_on_uninitialized)

        options, sources = parse_command_line([
            '--force', 'source.pyx',
        ])
        self.assertTrue(sources)
        self.assertTrue(len(sources) == 1)
        self.assertFalse(options.timestamps)

    def test_options_with_values(self):
        options, sources = parse_command_line([
            '--embed=huhu',
            '-I/test/include/dir1', '--include-dir=/test/include/dir2',
            '--include-dir', '/test/include/dir3',
            '--working=/work/dir',
            'source.pyx',
            '--output-file=/output/dir',
            '--pre-import=/pre/import',
            '--cleanup=3',
            '--annotate-coverage=cov.xml',
            '--gdb-outdir=/gdb/outdir',
            '--directive=wraparound=false',
        ])
        self.assertEqual(sources, ['source.pyx'])
        self.assertEqual(Options.embed, 'huhu')
        self.assertEqual(options.include_path, ['/test/include/dir1', '/test/include/dir2', '/test/include/dir3'])
        self.assertEqual(options.working_path, '/work/dir')
        self.assertEqual(options.output_file, '/output/dir')
        self.assertEqual(Options.pre_import, '/pre/import')
        self.assertEqual(Options.generate_cleanup_code, 3)
        self.assertTrue(Options.annotate)
        self.assertEqual(Options.annotate_coverage_xml, 'cov.xml')
        self.assertTrue(options.gdb_debug)
        self.assertEqual(options.output_dir, '/gdb/outdir')

    def test_errors(self):
        def error(*args):
            old_stderr = sys.stderr
            stderr = sys.stderr = StringIO()
            try:
                self.assertRaises(SystemExit, parse_command_line, list(args))
            finally:
                sys.stderr = old_stderr
            self.assertTrue(stderr.getvalue())

        error('-1')
        error('-I')
        error('--version=-a')
        error('--version=--annotate=true')
        error('--working')
        error('--verbose=1')
        error('--verbose=1')
        error('--cleanup')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 22 22:56:58 2021

@author: stepianno
"""
from itertools import combinations_with_replacement
from collections import Counter
p1 = p2 = 0
s1 = 2
s2 = 1
die = 0
first = True
while p1 < 1000 and p2 < 1000:
    die += 3
    move = (die*3-3)%10
    if first:
        s1 = (s1+move)%10
        if not s1:
            p1 += 10
        else:
            p1 += s1
    else:
        s2 = (s2+move)%10
        if not s2:
            p2 += 10
        else:
            p2 += s2
    first = not first
print('part a:', min(p1,p2)*die)

ways = combinations_with_replacement([1,2,3], 3)
paths = Counter([sum(way) for way in ways])
start = (2,1,True,0,0)
dim_cache = {}
def dirac(s1, s2, first=True, p=0):
    turn = (s1,s2,first,p)
    if turn in dim_cache:
        return dim_cache[turn]
    if p.real >= 21:
        return 1
    elif p.imag >= 21:
        return 1j
    w = 0
    for a in range(1,4):
        for b in range(1,4):
            for c in range(1,4):
                k = a+b+c
                if first:
                    s1n = (s1 + k)%10
                    if not s1n:
                        pn = p + 10
                    else:
                        pn = p + s1n
                    w += dirac(s1n,s2,False,pn)
                else:
                    s2n = (s2 + k)%10
                    if not s2n:
                        pn = p + 10j
                    else:
                        pn = p + (s2n*1j)
                    w += dirac(s1,s2n,True,pn)
    dim_cache[turn] = w
    return dim_cache[turn]

dirac(2,1)
p1 = int(dim_cache[(2,1,True,0)].real)
p2 = int(dim_cache[(2,1,True,0)].imag)
print('part b:', max(p1,p2))