# -*- coding: utf-8 -*-
# This file is part of Viper - https://github.com/viper-framework/viper
# See the file 'LICENSE' for copying permission.

import re
import os
import sys

try:
    from unittest import mock
except ImportError:
    # Python2
    import mock

from viper.core.plugins import load_commands
from viper.core.database import Database
from viper.core.project import Project
from viper.core.session import __sessions__
from tests.conftest import FIXTURE_DIR

class TestCommands:
    cmd = load_commands()

    def setup_class(cls):
        cmd = load_commands()
        cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe"))
        cmd['store']['obj']()

    def teardown_method(self):
        self.cmd['close']['obj']()

    def test_help(self, capsys):
        self.cmd['help']['obj']()
        self.cmd['clear']['obj']()
        out, err = capsys.readouterr()
        assert re.search(r".* Commands.*", out)
        assert re.search(r".* Modules.*", out)

    def test_notes(self, capsys):
        self.cmd['notes']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: notes \[-h\] .*", out)

        self.cmd['notes']['obj']('-l')
        out, err = capsys.readouterr()
        assert re.search(".*No notes available for this file or.*", out)

    def test_open(self, capsys):
        self.cmd['open']['obj']('-h')
        self.cmd['open']['obj']('-u', 'https://github.com/viper-framework/viper-test-files/raw/master/test_files/cmd.exe')
        out, err = capsys.readouterr()
        assert re.search(r"usage: open \[-h\] .*", out)
        assert re.search(".*Session opened on /tmp/.*", out)

    def test_open_tor(self, capsys):
        self.cmd['open']['obj']('-h')
        self.cmd['open']['obj']('-t', '-u', 'https://github.com/viper-framework/viper-test-files/raw/master/test_files/cmd.exe')
        out, err = capsys.readouterr()
        assert re.search(r"usage: open \[-h\] .*", out)
        assert re.search(".*Session opened on /tmp/.*", out)

    def test_notes_existing(self, capsys):
        self.cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe"))
        Database().add_note(__sessions__.current.file.sha256, 'Note test', 'This is the content')
        self.cmd['notes']['obj']('-l')
        self.cmd['notes']['obj']('-v', '1')
        self.cmd['notes']['obj']('-d', '1')
        out, err = capsys.readouterr()
        assert re.search(".*1  | Note test.*", out)
        assert re.search(".*This is the content.*", out)

    def test_analysis(self, capsys):
        self.cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe"))
        self.cmd['analysis']['obj']('-h')
        self.cmd['analysis']['obj']('-l')
        self.cmd['analysis']['obj']('-v', '1')
        out, err = capsys.readouterr()
        assert re.search(r"usage: analysis \[-h\] .*", out)
        assert re.search(".*Saved On.*", out)
        assert re.search(".*Cmd Line.*", out)

    def test_store(self, capsys):
        self.cmd['store']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: store \[-h\] .*", out)

    def test_delete(self, capsys):
        self.cmd['delete']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: delete \[-h\] .*", out)

    def test_find(self, capsys):
        self.cmd['find']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: find \[-h\] .*", out)

        self.cmd['find']['obj']('all')
        out, err = capsys.readouterr()
        assert re.search(".*chromeinstall-8u31.exe.*", out)

    def test_tags(self, capsys):
        self.cmd['tags']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: tags \[-h\] .*", out)

    def test_tags_use(self, capsys):
        self.cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe"))
        self.cmd['tags']['obj']('-a', 'mytag')
        self.cmd['tags']['obj']('-d', 'mytag')
        out, err = capsys.readouterr()
        lines = out.split('\n')
        assert re.search(".*Tags added to the currently opened file.*", lines[1])
        assert re.search(".*Refreshing session to update attributes....*", lines[2])

    def test_sessions(self, capsys):
        self.cmd['sessions']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: sessions \[-h\] .*", out)

        self.cmd['sessions']['obj']('-l')
        out, err = capsys.readouterr()
        assert re.search(".*Opened Sessions.*", out)

    def test_projects(self, capsys):
        self.cmd['projects']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: projects \[-h\] .*", out)

        p = Project()
        p.open("project_switch_test1")

        self.cmd['projects']['obj']('-l')
        out, err = capsys.readouterr()
        assert re.search(".*Projects Available.*", out)
        assert re.search(".*project_switch_test1.*", out)
        assert not re.search(".*not_there.*", out)

        self.cmd['projects']['obj']('-s', 'project_switch_test1')
        out, err = capsys.readouterr()
        lines = out.split('\n')
        assert re.search(".*Switched to project.*", lines[0])

        # return to default
        p.open("default")

    def test_export(self, capsys):
        self.cmd['export']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: export \[-h\] .*", out)

    def test_stats(self, capsys):
        self.cmd['stats']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: stats \[-h\] .*", out)

    def test_parent(self, capsys):
        self.cmd['parent']['obj']('-h')
        out, err = capsys.readouterr()
        assert re.search(r"usage: parent \[-h\] .*", out)

    def test_rename(self, capsys):
        self.cmd['find']['obj']("all")
        out, err = capsys.readouterr()
        assert out == ""

        self.cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe"))
        self.cmd['store']['obj']()
        _, _ = capsys.readouterr()

        if sys.version_info <= (3, 0):
            in_fct = 'builtins.raw_input'
        else:
            in_fct = 'builtins.input'

        with mock.patch(in_fct, return_value='chromeinstall-8u31.exe.new'):
            self.cmd['rename']['obj']()

        out, err = capsys.readouterr()
        lines = out.split('\n')

        assert re.search(r".*Current name is.*1mchromeinstall-8u31.exe.*", lines[0])
        assert re.search(r".*Refreshing session to update attributes.*", lines[1])

    def test_copy(self, capsys):
        self.cmd['projects']['obj']('-s', 'copy_test_dst')
        out, err = capsys.readouterr()
        lines = out.split('\n')
        assert re.search(r".*Switched to project.*", lines[0])

        self.cmd['find']['obj']('all')
        out, err = capsys.readouterr()
        assert out == ""

        self.cmd['projects']['obj']('-s', 'copy_test_src')
        out, err = capsys.readouterr()
        lines = out.split('\n')
        assert re.search(r".*Switched to project.*", lines[0])

        self.cmd['find']['obj']('all')
        out, err = capsys.readouterr()
        assert out == ""

        self.cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe"))
        self.cmd['store']['obj']()
        out, err = capsys.readouterr()
        lines = out.split('\n')
        assert re.search(r".*Session opened on.*", lines[0])
        assert re.search(r".*Stored file.*", lines[1])

        self.cmd['find']['obj']('all')
        out, err = capsys.readouterr()
        assert re.search(r".*\| 1 \| chromeinstall-8u31.exe.*", out)
        assert not re.search(r".*\| 2 \|.*", out)

        self.cmd['copy']['obj']('-d', 'copy_test_dst')
        out, err = capsys.readouterr()
        lines = out.split('\n')
        assert re.search(r".*Copied:.*", lines[0])
        assert re.search(r".*Deleted:.*", lines[1])
        assert re.search(r".*Successfully copied sample.*", lines[2])

        self.cmd['find']['obj']('all')
        out, err = capsys.readouterr()
        assert out == ""
        assert not re.search(r".*\| 1 \| chromeinstall-8u31.exe.*", out)
        assert not re.search(r".*\| 2 \|.*", out)

        self.cmd['projects']['obj']('-s', 'copy_test_dst')
        out, err = capsys.readouterr()
        assert re.search(r".*Switched to project.*", out)

        self.cmd['find']['obj']('all')
        out, err = capsys.readouterr()
        assert re.search(r".*\| 1 \| chromeinstall-8u31.exe.*", out)
        assert not re.search(r".*\| 2 \|.*", out)


# -*- coding: utf-8 -*-
"""
Created on Thu Dec 29 11:08:08 2022

@author: Shalom
"""

import numpy as np
import pickle
import streamlit as st
from PIL import Image
image =Image.open('C:/Users\HP/Desktop/Streamlit App/image.JPG')

#loading the saved model
loaded_model= pickle.load(open('C:/Users\HP/Desktop/Streamlit App/trained_mode.sav', 'rb'))

#creating a functon for prediction

def diabetes_prediction(input_data):

    #changing the input data to a numpy array
    input_data_as_numpy_arrary= np.asarray(input_data)

    #reshape the np as we predict for one instance
    input_data_reshape = input_data_as_numpy_arrary.reshape(1,-1)

    prediction = loaded_model.predict(input_data_reshape)
    print(prediction)

    if(prediction[0] == 0):
        return 'The person is not diabetic'
    else:
        return 'the person is diabetic'
st.image(image)

def main():

 #giving a title

 st.title('Diabetes Prediction Web App')

 #getting the input data from the user

 Pregnancies = st.text_input('Number of Pregnancies')
 Glucose = st.text_input('Gluecose Level')
 BloodPressure= st.text_input('Your Blood Pressure')
 SkinThickness = st.text_input('Skin Thickness Value')
 Insulin= st.text_input('Insuline Level')
 BMI= st.text_input('BMI Value')
 DiabetesPedigreeFunction= st.text_input('DiabetesPedigreeFunction')
 Age= st.text_input('Your Age')

 #code for prediction

 diagnosis = ''

 #creating a button

 if st.button('Diabetes Test Results'):
     diagnosis=diabetes_prediction([Pregnancies, Glucose, BloodPressure, SkinThickness,
                                    Insulin,BMI, DiabetesPedigreeFunction, Age])

 st.success(diagnosis)

if __name__ == '__main__':
    main()
st.text('BUILT BY SHALOM WITH 80% ACCURACY PERFORMANCE')


from tkinter import  *

def callback():
    var.set("那也不行")
    pass
root = Tk()

frame1 = Frame(root)# 加了两个框架 分开窗口
frame2 = Frame(root)

var = StringVar()
var.set('您没有\n权限')

# textLabel = Label(root,text = '您没有\n权限',justify = LEFT,padx = 10)
#                 # justify 对齐
# textLabel.pack(side = LEFT)
#
# photo = PhotoImage(file='GUI.gif')# 不支持jpg png
# imgLabel = Label(root,image=photo)
# imgLabel.pack()

# 图片做背景

photo = PhotoImage(file='GUI.gif')
theLabel = Label(root,
                  # text = '您没有\n权限',
                  textvariable = var,
                 # 与上行区别在于 textvariable是个变量
                  justify = LEFT,

                  image = photo,
                  compound = CENTER,
                  font = ('宋体',20),
                  fg = 'blue')
                # compound 字体显示位置 font 字体 字号
theLabel.pack()
theButton = Button(frame2,text = '我就',command = callback)
theButton.pack()
frame1.pack(padx = 10,pady = 15)
frame2.pack(padx = 10,pady = 15)

mainloop()


import nibabel as nib
import numpy as np
import os
import json
import nibabel.processing as nip
import nibabel.orientations as nio
from scipy.interpolate import interp1d, RegularGridInterpolator
from scipy.signal import savgol_filter
import matplotlib.pyplot as plt
import PIL
from io import BytesIO
from matplotlib.colors import ListedColormap, Normalize
from matplotlib.patches import Circle
import matplotlib as mpl
import warnings
from pathlib import Path
import pandas as pd
import math
import time
from copy import deepcopy
from skimage.transform import resize

mpl.rcParams['savefig.pad_inches'] = 0
v_dict = {1: 'C1', 2: 'C2', 3: 'C3', 4: 'C4', 5: 'C5', 6: 'C6', 7: 'C7',
    8: 'T1', 9: 'T2', 10: 'T3', 11: 'T4', 12: 'T5', 13: 'T6', 14: 'T7',
    15: 'T8', 16: 'T9', 17: 'T10', 18: 'T11', 19: 'T12', 20: 'L1',
    21: 'L2', 22: 'L3', 23: 'L4', 24: 'L5', 25: 'L6', 26: 'Sacrum',
    27: 'Cocc', 28: 'T13'
}

colors_itk = (1/255)*np.array([
    [255,  0,  0], [  0,255,  0], [  0,  0,255], [255,255,  0], [  0,255,255],
    [255,  0,255], [255,239,213],  # Label 1-7 (C1-7)
    [  0,  0,205], [205,133, 63], [210,180,140], [102,205,170], [  0,  0,128],
    [  0,139,139], [ 46,139, 87], [255,228,225], [106, 90,205], [221,160,221],
    [233,150,122], [165, 42, 42],  # Label 8-19 (T1-12)
    [255,250,250], [147,112,219], [218,112,214], [ 75,  0,130], [255,182,193],
    [ 60,179,113], [255,235,205],  # Label 20-26 (L1-6, sacrum)
    [255,235,205], [255,228,196],  # Label 27 cocc, 28 T13,
    [218,165, 32], [  0,128,128], [188,143,143], [255,105,180],
    [255,  0,  0], [  0,255,  0], [  0,  0,255], [255,255,  0], [  0,255,255],
    [255,  0,255], [255,239,213],  # 29-39 unused
    [  0,  0,205], [205,133, 63], [210,180,140], [102,205,170], [  0,  0,128],
    [  0,139,139], [ 46,139, 87], [255,228,225], [106, 90,205], [221,160,221],
    [233,150,122],   # Label 40-50 (subregions)
    [255,250,250], [147,112,219], [218,112,214], [ 75,  0,130], [255,182,193],
    [ 60,179,113], [255,235,205], [255,105,180], [165, 42, 42], [188,143,143],
    [255,235,205], [255,228,196], [218,165, 32], [  0,128,128] # rest unused
    ])
cm_itk = ListedColormap(colors_itk)
cm_itk.set_bad(color='w', alpha=0)

wdw_sbone = Normalize(vmin=-500, vmax=1300, clip=True)
wdw_hbone = Normalize(vmin=-200, vmax=1000, clip=True)

cm_sr = (1/255)*np.array([
        [104,159,56], [ 216,67,28]
        ])

cm_sr = ListedColormap(cm_sr)
cm_sr.set_bad(color='w', alpha=0)

cm_bmd_co = (1/255)*np.array([
        [0,0,0],[104,159,56], [255,179,0], [ 216,67,28], [183,28,28], # green, yellow, red, dark red for >120, >80, >50, <50
        ])

cm_bmd = ListedColormap(cm_bmd_co)
cm_bmd.set_bad(color='w', alpha=0)

colors_labels = (1/255)*np.array([
    [  0,  0,  0],  #
    [230,255,  0],  #   "Label 1"
    [255,247,  0],  #   "Label 3"
    [255,162,  0],  #   "Label 5"
    [255,  0, 12],  #   "Label 4"
    [166,  0,255],  #   "Label 5"
    [  0,  0,255],  #   "Label 6"
    [ 20,108,  0],  #   "Label 7"
    [104,159, 56], #   "Label 8"
    [255,179,  0], #   "Label 9"
    [216, 67, 28], #   "Label 10"
    [183, 28, 28]  #   "Label 11"
    ])

cm_labl = ListedColormap(colors_labels)
cm_labl.set_bad(color='w', alpha=0)  # set NaN to full opacity for overlay

def plot_bmd_label(axs, ctd, zms, bmd_val, size=3, text=True):
    # requires v_dict = dictionary of mask labels and a pd dataframe with labels "bmd_val"
    try:
        bmd_val = float(bmd_val)

        if bmd_val > 120:
            bmd = 1
        elif bmd_val > 80:
            bmd = 2
        elif bmd_val > 50:
            bmd = 3
        else:
            bmd = 4
#         print('bmd ', bmd)
        for v in ctd[1:]:
            if v[0] ==22:
                axs.add_patch(Circle((v[2]*zms[1], v[1]*zms[0]), size, color=cm_bmd_co[bmd]))
                if text:
                    axs.text(v[2]*zms[1]- 40, v[1]*zms[0]+2, str(bmd_val), fontdict={'color': cm_bmd(bmd), 'weight': 'bold'}, backgroundcolor='black')
    except Exception as e:
        pass

def initialize_database(rater):
    csv_path = 'CTFU_Fx_{}.csv'.format(rater)
    if not os.path.isfile(csv_path):
        columns = ['ID', 'type', 'ce',
                   'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7',
                   'T1', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10', 'T11', 'T12',
                   'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'T13']
        df = pd.DataFrame(columns= columns)
        df.to_csv(csv_path, index=False)
    return csv_path

def populate_database(database_path, fx_dict, img_path, typ):
    print(database_path)
    df = pd.read_csv(database_path)
    fx_dict['ID'] = str(os.path.basename(img_path).replace('_ct.nii.gz', ''))
    if fx_dict['ID'] in df.ID.values:
        idx = df.index[df['ID']==fx_dict['ID']].tolist()
        df = df.drop(index=idx, axis=0)# = fx
    fx_dict['ce'] = get_ce(img_path)
    fx_dict['type'] = typ
    df = df.append(fx_dict, ignore_index=True)
    df.to_csv(database_path, index=False)
    return True

def get_ce(pth):
    try:
        ce = str(pth).split('ce-')[1].split('_')[0]
    except Exception:
        ce = ''
    return ce

def reorient_to(img, axcodes_to=('P', 'I', 'R'), verb=False, msk=True):

    # Note: nibabel axes codes describe the direction not origin of axes
    # direction PIR+ = origin ASL
    aff = img.affine
    if msk:
        arr = np.asanyarray(img.dataobj, dtype=img.dataobj.dtype)
    else:
        arr = img.get_fdata()
    ornt_fr = nio.io_orientation(aff)
    ornt_to = nio.axcodes2ornt(axcodes_to)
    ornt_trans = nio.ornt_transform(ornt_fr, ornt_to)
    arr = nio.apply_orientation(arr, ornt_trans)
    aff_trans = nio.inv_ornt_aff(ornt_trans, arr.shape)
    newaff = np.matmul(aff, aff_trans)
    newimg = nib.Nifti1Image(arr, newaff)
    if verb:
        print("[*] Image reoriented from", nio.ornt2axcodes(ornt_fr), "to", axcodes_to)
    return newimg

def get_paddings(msk1, msk2, ctd1, ctd2):

    rat_pad_1_1, rat_pad_1_2 = 0, 0
    rat_pad_2_1, rat_pad_2_2 = 0, 0

    ctd_dict1 = {x[0] : [x[1], x[2], x[3]] for x in ctd1[1:]}
    ctd_dict2 = {x[0] : [x[1], x[2], x[3]] for x in ctd2[1:]}

    if msk2.shape[1] > msk1.shape[1]:
        rat_pad_1_1 = len([x for x in ctd_dict2.keys() if x<min(list(ctd_dict1.keys()))])
        rat_pad_1_2 = len([x for x in ctd_dict2.keys() if x>max(list(ctd_dict1.keys()))])

        to_pad_tot = msk2.shape[1] - msk1.shape[1]
        rat_pad_1_1 = (rat_pad_1_1/(rat_pad_1_1 + rat_pad_1_2+1e-7)) * to_pad_tot
        rat_pad_1_2 = (rat_pad_1_2/(rat_pad_1_1 + rat_pad_1_2+1e-7)) * to_pad_tot

    if msk1.shape[1] > msk2.shape[1] > 0:
        to_pad_tot = msk1.shape[1] - msk2.shape[1]
        rat_pad_2_1 = len([x for x in ctd_dict1.keys() if x<min(list(ctd_dict2.keys()))])
        rat_pad_2_2 = len([x for x in ctd_dict1.keys() if x>max(list(ctd_dict2.keys()))])

        rat_pad_2_1 = (rat_pad_2_1/(rat_pad_2_1 + rat_pad_2_2+1e-7)) * to_pad_tot
        rat_pad_2_2 = (rat_pad_2_2/(rat_pad_2_1 + rat_pad_2_2+1e-7)) * to_pad_tot

    if msk2.shape[0] > msk1.shape[0]:
        to_pad_rl_1 = msk2.shape[0] - msk1.shape[0]
        to_pad_rl_2 = 0
    elif msk1.shape[0]>  msk2.shape[0]:
        to_pad_rl_2 = msk1.shape[0] - msk2.shape[0]
        to_pad_rl_1 = 0
    else:
        to_pad_rl_1,  to_pad_rl_2= 0, 0

    if msk2.shape[2] > msk1.shape[2]:
        to_pad_io_1 = msk2.shape[2] - msk1.shape[2]
        to_pad_io_2 = 0
    elif msk1.shape[2]>  msk2.shape[2]:
        to_pad_io_2 = msk1.shape[2] - msk2.shape[2]
        to_pad_io_1 = 0
    else:
        to_pad_io_1,  to_pad_io_2= 0, 0

    return int(rat_pad_1_1), int(rat_pad_1_2), int(rat_pad_2_1), int(rat_pad_2_2), int(to_pad_rl_1), int(to_pad_rl_2), int(to_pad_io_1),  int(to_pad_io_2)

def pad_arr(arr1, arr2, pads, msk=False):
    if not msk:
        cnst = (-1024)
    else:
        cnst = (0)

    new_arr1 = np.pad(
        arr1,
        [(0, int(pads[4])), (int(pads[0]), int(pads[1])), (0, int(pads[6]))],
        mode='constant',
        constant_values = cnst
    )
    new_arr2 = np.pad(
        arr2,
        [(0, pads[5]), (pads[2], pads[3]), (0, pads[7])],
        mode='constant',
        constant_values = cnst
    )
    return new_arr1, new_arr2

def pad_ctds(ctd1, ctd2, pads):
    new_ctd1 = [[x[0], x[1], x[2]+pads[0], x[3]] if isinstance(x,list) else x for x in  ctd1]

    new_ctd2 = [[x[0], x[1], x[2]+pads[2], x[3]] if isinstance(x,list) else x for x in  ctd2]
    return new_ctd1, new_ctd2

def pad_niftis(bimg, bmsk,sr, fimg, fmsk, res, bctd, fctd):
    bimg_data = bimg.get_fdata()
    bmsk_data = np.asanyarray(bmsk.dataobj, dtype=bmsk.dataobj.dtype)
    fimg_data = fimg.get_fdata()
    fmsk_data = np.asanyarray(fmsk.dataobj, dtype=fmsk.dataobj.dtype)

    res_data = np.asanyarray(res.dataobj, dtype=res.dataobj.dtype)
    sr_arr = np.asanyarray(sr.dataobj, dtype=sr.dataobj.dtype)

    pads = get_paddings(bmsk_data,fmsk_data,bctd,fctd)

    bimg_data, fimg_data =  pad_arr(bimg_data, fimg_data, pads, msk=False)

    bmsk_data, fmsk_data =  pad_arr(bmsk_data, fmsk_data, pads, msk=True)
    sr_arr, _ = pad_arr(sr_arr, sr_arr, pads, msk=True)
    res_data, _ = pad_arr(res_data, res_data, pads, msk=True)

    bctd1, fctd1 = pad_ctds(bctd, fctd, pads)

    bimg1 = nib.Nifti1Image(bimg_data,bimg.affine)
    bmsk1 = nib.Nifti1Image(bmsk_data,bmsk.affine)
    res1 = nib.Nifti1Image(res_data,res.affine)
    sr1 = nib.Nifti1Image(sr_arr,sr.affine)
    fimg1 = nib.Nifti1Image(fimg_data,fimg.affine)
    fmsk1 = nib.Nifti1Image(fmsk_data,fmsk.affine)
    return bimg1, bmsk1,sr1, fimg1, fmsk1, res1, bctd1, fctd1

def get_labels_from_csv(dataframe, case_id, exclude_cervical=False):
    verts = ['C2', 'C3', 'C4', 'C5', 'C6', 'C7',
                   'T1', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10', 'T11', 'T12',
                   'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'T13']
    try:
        all_entries = dataframe[dataframe['ID']==case_id].to_dict(orient='records')[0]
        v_bmd = all_entries.get('vBMD_L3')
        if np.isnan(v_bmd):
            v_bmd = ''

    except:
        return pd.DataFrame,0
    return dataframe[dataframe['ID']==case_id], v_bmd

def get_labels_from_imp(dataframe, img_path):
    verts = ['C2', 'C3', 'C4', 'C5', 'C6', 'C7',
                   'T1', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'T8', 'T9', 'T10', 'T11', 'T12',
                   'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'T13']
    try:
        case_id =  get_csv_entry(img_path)
        all_entries = dataframe[dataframe['ID']==case_id].to_dict(orient='records')[0]
        labels_dict = {x:y for x,y in all_entries.items() if 'def_' in x and not np.isnan(y)}

    except:
        return {}

    return labels_dict

def process_data_snp_sub(rater_dict, labels, dpi=120):
    img_pth = rater_dict['b_img_pth']
    fimg_pth = rater_dict['f_img_pth']
    sub_path = rater_dict['sub_pth']
    # img_pth, msk_pth, sr_pth, ctd_pth,fimg_pth, fmsk_pth, fctd_pth, sub_path, labels, dpi=120
    msk_pth, sr_pth, ctd_pth = get_derivative_path_from_raw_ct(img_pth)
    fmsk_pth, fsr_pth, fctd_pth = get_derivative_path_from_raw_ct(fimg_pth)

    b_labels, bbmd = get_labels_from_csv(labels, get_csv_entry(img_pth))
    f_labels, fbmd = get_labels_from_csv(labels, get_csv_entry(fimg_pth))

    bimg = nib.load(img_pth)
    bmsk = nib.load(msk_pth)
    bctd = load_centroids(ctd_pth)
    sub = nib.load(sub_path)
    sr = nib.load(sr_pth)
    b_ex_cents = [x[0] for x in bctd[1:] if isinstance(x[0], int)]

    fimg = nib.load(fimg_pth)
    fmsk = nib.load(fmsk_pth)
    fctd = load_centroids(fctd_pth)
    f_ex_cents = [x[0] for x in fctd[1:] if isinstance(x[0], int)]

    to_remove_bs = [x for x in b_ex_cents if x not in f_ex_cents]

    bimg, bmsk,sr, fimg, fmsk, sub, bctd, fctd = pad_niftis(bimg, bmsk,sr, fimg, fmsk, sub, bctd, fctd)

    to_ax = ('I', 'A', 'L')
    bimg = reorient_to(bimg, axcodes_to=to_ax, msk=False)
    bmsk = reorient_to(bmsk, axcodes_to=to_ax)
    sr = reorient_to(sr, axcodes_to=to_ax)
    sub = reorient_to(sub, axcodes_to=to_ax, msk=False)
    bctd = reorient_centroids_to(bctd, bimg)

    fimg = reorient_to(fimg, axcodes_to=to_ax, msk=False)
    fmsk = reorient_to(fmsk, axcodes_to=to_ax)
    fctd = reorient_centroids_to(fctd, fimg)

    zms = (1,1,1)
    bzms = (1,1,1)
    fzms = (1,1,1)

    bimg_data = np.asanyarray(bimg.dataobj, dtype=np.int16)
    bmsk_data = np.asanyarray(bmsk.dataobj, dtype=bmsk.dataobj.dtype)

    fimg_data = fimg.get_fdata()
    fmsk_data = np.asanyarray(fmsk.dataobj, dtype=fmsk.dataobj.dtype)

    res_data = np.asanyarray(sub.dataobj, dtype=sub.dataobj.dtype)

    try:
        bsag_img, bcor_img, _, _, _ = sag_cor_curveprojection(bctd, bimg_data)
        bsag_msk, bcor_msk, y_cord, z_cord, x_ctd = sag_cor_curveprojection(bctd, bmsk_data)
        res_im, res_cor, _, _, _ = sag_cor_curveprojection(bctd, res_data)

        bsag_img, res_im, new_bctd = create_interpolated_im(bsag_img,res_im,x_ctd,z_cord,30,bctd)
        _, bsag_msk, _ = create_interpolated_im(bsag_img,bsag_msk,x_ctd,z_cord,30,bctd)
        bcor_img, res_cor, new_bcent_cor = create_interpolated_im(bcor_img,res_cor,x_ctd,y_cord,30,bctd)
        _, bcor_msk, _ = create_interpolated_im(bcor_img,bcor_msk,x_ctd,y_cord,30,bctd)

    except Exception as e:
        if len(bctd)==2:
            l = 1
        else:
            l = int(len(bctd)/2)
        bsag_img = bimg_data[:,:,int(bctd[l][3])]
        bsag_msk = bmsk_data[:,:,int(bctd[l][3])]
        bcor_img = bimg_data[:,int(bctd[l][2]),:]
        bcor_msk = bmsk_data[:,int(bctd[l][2]),:]
        res_cor = res_data[:,int(bctd[l][2]),:]
        new_bctd = bctd
        new_bcent_cor = bctd
        res_im = res_data[:,int(bctd[l][2]),:]

    try:
        fsag_img, fcor_img,y_cord, z_cord, x_ctd = sag_cor_curveprojection(fctd, fimg_data)
        fsag_img, _, new_fctd = create_interpolated_im(fsag_img,fsag_img,x_ctd,z_cord,30,fctd)
        fcor_img, _, new_fcent_cor = create_interpolated_im(fcor_img,fcor_img,x_ctd,y_cord,30,fctd)
    except Exception as e:
        if len(fctd)==2:
            l = 1
        else:
            l = int(len(fctd)/2)
        fsag_img = fimg_data[:,:,int(fctd[l][3])]
        fcor_img = fimg_data[:,int(fctd[l][2]),:]
        new_fctd = fctd
        new_fcent_cor = fctd

    bdrr_iso = deepcopy(bimg_data.astype(float))
    bdrr_iso[bmsk_data==0] = np.nan
    drr_b = np.nansum(bdrr_iso,2)

    fdrr_iso = deepcopy(fimg_data.astype(float))
    fdrr_iso[fmsk_data==0] = np.nan
    drr_f = np.nansum(fdrr_iso,2)

    for x in to_remove_bs:
        bsag_msk[bsag_msk==x] = 0
        bcor_msk[bcor_msk==x] = 0

    fig, axs, size = create_figure_1(dpi,drr_b,None)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(drr_b, cmap=plt.cm.gray, interpolation='lanczos')

    plot_sag_centroids(axs, bctd, zms)
    plot_bmd_label(axs,bctd,zms, bbmd)
    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    b_sag_drr = np.asarray(image)
    buffer_.close()
    plt.close()

    fig, axs,_ = create_figure_1(dpi,drr_f,size)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(drr_f, cmap=plt.cm.gray, interpolation='lanczos')
    plot_sag_centroids(axs, fctd, zms)
    plot_bmd_label(axs,fctd,zms, fbmd)
    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    f_sag_drr = np.asarray(image)
    buffer_.close()
    plt.close()

    bsag_msk[bsag_msk>0] = 2
    res_im[res_im>0] = 1

    bsag_msk
    bsag_msk[res_im>0]  = np.nan

    bsag_msk[bsag_msk==0] = np.nan
    res_im[res_im==0] = np.nan
    bsag_msk[0,0] = 1
    res_im[0,0] = 2

    fig, axs, size = create_figure_1(dpi,bsag_img,size)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(bsag_img, cmap=plt.cm.gray, norm=wdw_sbone)
    axs.imshow(bsag_msk, cmap=cm_sr, alpha=0.7)
    axs.imshow(res_im, cmap=cm_sr, alpha=0.2)

    plot_sag_centroids(axs, new_bctd, zms)
    if not b_labels.empty:
        plot_sag_labels(axs, new_bctd, zms, b_labels, size=2, text=True)

    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    bsag_img_ = np.asarray(image)
    buffer_.close()
    plt.close()

    fig, axs,fsize = create_figure_1(dpi,fsag_img,size)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(fsag_img, cmap=plt.cm.gray, norm=wdw_sbone)
    plot_sag_centroids(axs, new_fctd, fzms)
    if not f_labels.empty:
        plot_sag_labels(axs, new_fctd, zms, f_labels, size=2, text=True)
    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    fsag_img_ = np.asarray(image)

    buffer_.close()
    plt.close()
    ###################################

    bcor_msk[bcor_msk>0] = 2
    res_cor[res_cor>0] = 1

    bcor_msk[res_cor>0]  = np.nan

    bcor_msk[bcor_msk==0] = np.nan
    res_cor[res_cor==0] = np.nan
    bcor_msk[0,0] = 1
    res_cor[0,0] = 2

    fig, axs,fsize = create_figure_1(dpi,bcor_img,size)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(bcor_img, cmap=plt.cm.gray, norm=wdw_sbone)
    axs.imshow(bcor_msk, cmap=cm_sr, alpha=0.7)
    axs.imshow(res_cor, cmap=cm_sr, alpha=0.2)
    plot_cor_centroids(axs, new_bcent_cor, fzms)

    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    bcor_img_ = np.asarray(image)

    buffer_.close()
    plt.close()

    fig, axs,fsize = create_figure_1(dpi,fcor_img,size)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(fcor_img, cmap=plt.cm.gray, norm=wdw_sbone)
    plot_cor_centroids(axs, new_fcent_cor, fzms)

    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    fcor_img_ = np.asarray(image)

    buffer_.close()
    plt.close()

    return bimg, b_sag_drr, f_sag_drr, bctd, fimg, bsag_img_,fsag_img_, fctd, bcor_img_, fcor_img_,bzms,fzms, size, fsize

def plot_sag_labels(axs, ctd, zms, ctd_labels, size=2, text=True):
    # requires v_dict = dictionary of mask labels and a pd dataframe with labels "ctd_labels"
    for v in ctd[1:]:
        if v[0] < 8 or v[0] >28:
            continue
        if not ('def_'+v_dict[v[0]] in ctd_labels):
            continue
        if ctd_labels['def_'+v_dict[v[0]]].values > 0:            # handle non-existing labels
            vert_label = int(ctd_labels['def_'+v_dict[v[0]]])
        else:
            vert_label = 0
        if vert_label > 0:
            axs.add_patch(Circle((v[2]*zms[1], v[1]*zms[0]), size, color=colors_labels[vert_label]))
            if text:
                axs.text(v[2]*zms[1]- 11, v[1]*zms[0]+2, vert_label, fontdict={'color': cm_labl(vert_label), 'weight': 'bold'})

def sag_cor_curveprojection(ctd_list, arr):
    # Sagittal and coronal projections of a curved plane defined by centroids
    # Note: Pass centoids (ctd_list) and image (img) in IAL direction!
    # if x-direction (=S/I) is not fully incremental, a straight, not an interpolated plane will be returned
    new_ctd=[]              # handle T13 = label 28
    [new_ctd.append([19.5,x[1],x[2],x[3]]) if x[0]==28 else new_ctd.append(x) for x in ctd_list[1:]]
    new_ctd.sort()
    out =[ctd_list[0]]
    [out.append(x) for x in new_ctd[1:]]
    ctd_arr = np.transpose(np.asarray(out[1:]))[1:]
    shp = arr.shape
    x_ctd = np.rint(ctd_arr[0]).astype(int)
    y_ctd = np.rint(ctd_arr[1]).astype(int)
    z_ctd = np.rint(ctd_arr[2]).astype(int)
    cor_plane = np.zeros((shp[0], shp[2]))
    sag_plane = np.zeros((shp[0], shp[1]))
    x_ctd_unique = np.unique(x_ctd)
    if (len(ctd_list) <= 3) or ((not np.array_equal(x_ctd, sorted(x_ctd_unique))) and (not  np.array_equal(x_ctd,sorted(x_ctd_unique, reverse=True)))):
        y_cord = np.rint(np.mean(y_ctd)).astype(int)
        z_cord = np.rint(np.mean(z_ctd)).astype(int)
        cor_plane = arr[:, y_cord, :]
        sag_plane = arr[:, :, z_cord]
        y_cord = np.array([y_cord]*shp[1])
        z_cord = np.array([z_cord]*shp[2])
    else:
        f_sag = interp1d(x_ctd, y_ctd, kind='quadratic')
        f_cor = interp1d(x_ctd, z_ctd, kind='quadratic')
        window_size, poly_order = int((max(x_ctd)-min(x_ctd))/2), 3
        if  window_size % 2 == 0:
            window_size+=1
        y_cord = np.array([np.rint(f_sag(x)).astype(int) for x in range(min(x_ctd), max(x_ctd))])
        y_cord = np.rint(savgol_filter(y_cord, window_size, poly_order)).astype(int)
        z_cord = np.array([np.rint(f_cor(x)).astype(int) for x in range(min(x_ctd), max(x_ctd))])
        z_cord = np.rint(savgol_filter(z_cord, window_size, poly_order)).astype(int)
        y_cord[y_cord <  0]= 0                      #handle out-of-volume interpolations
        y_cord[y_cord >= shp[1]] = shp[1] - 1
        z_cord[z_cord < 0] = 0
        z_cord[z_cord >= shp[2]] = shp[2] - 1
        for x in range(0, shp[0] - 1):
            if x < min(x_ctd):
                cor_plane[x, :] = arr[x, y_cord[0], :]
                sag_plane[x, :] = arr[x, :, z_cord[0]]
            elif x >= max(x_ctd):
                cor_plane[x, :] = arr[x, y_cord[-1], :]
                sag_plane[x, :] = arr[x, :, z_cord[-1]]
            else:
                cor_plane[x, :] = arr[x, y_cord[x - min(x_ctd)], :]
                sag_plane[x, :] = arr[x, :, z_cord[x - min(x_ctd)]]
    return sag_plane, cor_plane, y_cord, z_cord, x_ctd

def reorient_centroids_to(ctd_list, img, decimals=1, verb=False):
    # reorient centroids to image orientation
    # todo: reorient to given axcodes (careful if img ornt != ctd ornt)
    ctd_arr = np.transpose(np.asarray(ctd_list[1:]))
    if len(ctd_arr) == 0:
        print("[#] No centroids present")
        return ctd_list
    v_list = ctd_arr[0].astype(int).tolist()  # vertebral labels
    ctd_arr = ctd_arr[1:]
    ornt_fr = nio.axcodes2ornt(ctd_list[0])  # original centroid orientation
    axcodes_to = nio.aff2axcodes(img.affine)
    ornt_to = nio.axcodes2ornt(axcodes_to)
    trans = nio.ornt_transform(ornt_fr, ornt_to).astype(int)
    perm = trans[:, 0].tolist()
    shp = np.asarray(img.dataobj.shape)
    ctd_arr[perm] = ctd_arr.copy()
    for ax in trans:
        if ax[1] == -1:
            size = shp[ax[0]]
            ctd_arr[ax[0]] = np.around(size - ctd_arr[ax[0]], decimals)
    out_list = [axcodes_to]
    ctd_list = np.transpose(ctd_arr).tolist()
    for v, ctd in zip(v_list, ctd_list):
        out_list.append([v] + ctd)
    if verb:
        print("[*] Centroids reoriented from", nio.ornt2axcodes(ornt_fr), "to", axcodes_to)
    return out_list

def load_centroids(ctd_path):
    with open(ctd_path) as json_data:
        dict_list = json.load(json_data)
        json_data.close()
    ctd_list = []
    for d in dict_list:
        if 'direction' in d:
            ctd_list.append(tuple(d['direction']))
        elif 'nan' in str(d):            #skipping NaN centroids
            continue
        else:
            ctd_list.append([d['label'], d['X'], d['Y'], d['Z']])
    return ctd_list

def create_interpolated_im(img,msk,x_ctd,y_cord,inter,ctd):
    #interpolates a given 2D image 'img' along with its mask 'msk' to an interpolation interval 'inter' using the distance dictionart l_dict

    #create a dictionary of euclidean distances between each slice
    xcords = range(x_ctd[0],x_ctd[-1],1)
    distances = {}
    co = 0
    cx = 0
    cy = 0
    for x,y in zip(xcords,y_cord):

        if co>0:
            d =math.sqrt((x -cx)**2 + (y -cy)**2)
            distances[x] = d
        else:
            distances[x] = 1
        co+=1
        cx = x
        cy = y
    interp_ctd = []

    ks = list(sorted(distances.keys()))
    #split the spine into chunks depending on the value of inter
    chunks = [ks[x:x+inter] for x in range(0, len(ks), inter)]

    n_d = {}
    n_d1 = {}
    for iii,ch in enumerate(chunks):

        n_d[ch[0]+inter] = sum([distances[y] for y in ch])
    #calculate new centroids

    new_cent = deepcopy(ctd)

    for cent in new_cent:
        if type(cent) is list:
            su =sum([distances[i]-1 for i in distances if i<cent[1]])
            cent[1]+= su
    l_dict = n_d

    x = l_dict.values()
    h,w = img.shape

    first_o=0
    ixx_img =None
    ixx_msk = None
    for k in sorted(l_dict.keys()):
        new_slices = 0
        val = l_dict[k]

        if val >= inter:
            new_slices = int(round(val-inter))
        if new_slices > 0:
            hh = k-first_o+new_slices

            nimg = resize(img[first_o:k,:],(hh,w),order = 3,preserve_range=True, mode='constant',anti_aliasing=False)
            nmsk = resize(msk[first_o:k,:],(hh,w),order = 0,preserve_range=True, mode='constant',anti_aliasing=False)

            if ixx_img is None:
                ixx_img = nimg
                ixx_msk= nmsk
            else:
                ixx_img = np.concatenate((ixx_img,nimg),axis = 0)
                ixx_msk = np.concatenate((ixx_msk,nmsk),axis = 0)
            first_o = k
        else:
            if ixx_img is None:
                ixx_img = img[first_o:k,:]
                ixx_msk= msk[first_o:k,:]
            else:
                ixx_img = np.concatenate((ixx_img,img[first_o:k,:]),axis = 0)
                ixx_msk = np.concatenate((ixx_msk,msk[first_o:k,:]),axis = 0)
            first_o = k
    ixx_img = np.concatenate((ixx_img,img[k:,:]),axis=0)
    ixx_msk=np.concatenate((ixx_msk,msk[k:,:]),axis=0)
    return ixx_img,ixx_msk,new_cent

def create_figure_1(dpi, planes, size=None):
    fig_h = round(2 * planes.shape[0] / dpi, 2)
    fig_w = round(2 * planes.shape[1] / dpi, 2)
    if size:
        s = size
    else:
        s=(fig_w, fig_h)
    fig, axs = plt.subplots(1, 1,figsize=s )
    axs.axis('off')
    return fig, axs, (fig_w,fig_h)

def plot_sag_centroids(axs, ctd, zms):
    # requires v_dict = dictionary of mask labels
    for v in ctd[1:]:
        axs.add_patch(Circle((v[2]*zms[1], v[1]*zms[0]), 1, color=colors_itk[v[0]-1]))
        axs.text(4, v[1]*zms[0], v_dict[v[0]], fontdict={'color': cm_itk(v[0]-1), 'weight': 'bold'})

def plot_cor_centroids(axs, ctd, zms):
    # requires v_dict = dictionary of mask labels
    for v in ctd[1:]:
        axs.add_patch(Circle((v[3]*zms[2], v[1]*zms[0]), 1, color=colors_itk[v[0]-1]))
        axs.text(4, v[1]*zms[0], v_dict[v[0]], fontdict={'color': cm_itk(v[0]-1), 'weight': 'bold'})

def save_json(out_dict, out_path):
    def convert(o):
        if isinstance(o, np.int64):
            return int(o)
        raise TypeError
    with open(out_path, 'w') as f:
        json.dump(out_dict, f, indent=4, default=convert)
    print("[*] Json saved:", out_path)

def sag_i(x,sag):

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
    fig = plt.figure(figsize=(3, 12))
    ax_neu = fig.add_subplot(1,1,1)
    plt.axis('off')

    ax_neu.imshow(sag)
    fig.canvas.draw()

def sag_drr(x,drr):

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
    fig = plt.figure(figsize=(3, 12))
    ax_neu = fig.add_subplot(1,1,1)
    plt.axis('off')

    ax_neu.imshow(drr,  cmap=plt.cm.gray, interpolation='lanczos')
    fig.canvas.draw()

def cor_i(x,cor):

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
    fig = plt.figure(figsize=(3, 12))
    fig.patch.set_facecolor('black')
    ax_neu = fig.add_subplot(1,1,1)
    plt.axis('off')

    ax_neu.imshow(cor)
    fig.canvas.draw()

def cor_f(slc,img,zms,size):

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        img_median = img.get_fdata()[:,slc,:]

    fig, axs,_ = create_figure_1(120,img_median,size)
    fig.subplots_adjust(bottom=0, top=1, left=0, right=1)
    axs.imshow(img_median, cmap=plt.cm.gray, norm=wdw_sbone)
    buffer_ = BytesIO()
    plt.savefig(buffer_, format = "png")
    buffer_.seek(0)
    image = PIL.Image.open(buffer_)
    img_median = np.asarray(image)
    buffer_.close()
    plt.close()

    fig = plt.figure(figsize=(3, 12))
    ax_neu = fig.add_subplot(1,1,1)
    plt.axis('off')

    ax_neu.imshow(img_median)
    fig.canvas.draw()

def sag_f(slc,img,zms):

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        img_median = img.get_fdata()[:,:,slc]
    fig = plt.figure(figsize=(3, 12))
    ax_neu = fig.add_subplot(1,1,1)
    plt.axis('off')

    ax_neu.imshow(img_median, cmap="gray", norm=wdw_sbone)
    fig.canvas.draw()
#     display(fig)

v_dict = {
    1: 'C1', 2: 'C2', 3: 'C3', 4: 'C4', 5: 'C5', 6: 'C6', 7: 'C7',
    8: 'T1', 9: 'T2', 10: 'T3', 11: 'T4', 12: 'T5', 13: 'T6', 14: 'T7',
    15: 'T8', 16: 'T9', 17: 'T10', 18: 'T11', 19: 'T12', 20: 'L1',
    21: 'L2', 22: 'L3', 23: 'L4', 24: 'L5', 25: 'L6', 28: 'T13'
}
def get_raw_ct_paths(directory):
    im_paths = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith("_ct.nii.gz"):
                im_paths.append(os.path.join(root, file))
    return im_paths

def get_derivative_path_from_raw_ct(img_path):
    drv = str(img_path).replace("rawdata", "derivatives")

    msk_path = drv.replace('_ct.nii.gz', '_seg-vert_msk.nii.gz')
    sr_path = drv.replace('_ct.nii.gz', '_seg-subreg_msk.nii.gz')
    ctd_path = sr_path.replace('_msk.nii.gz', '_ctd.json')
    return msk_path, sr_path, ctd_path

def get_baseline_fu_ses(unique_sessions):
    ses1 = int(unique_sessions[0][4:])
    ses2 = int(unique_sessions[1][4:])

    if ses1 > ses2:
        baseline_ses = unique_sessions[1]
        followup_ses = unique_sessions[0]
    else:
        baseline_ses = unique_sessions[0]
        followup_ses = unique_sessions[1]
    return baseline_ses, followup_ses

def get_study_dict(fold, baseline_ses, followup_ses):

    baseline_dir = os.path.join(fold, baseline_ses)
    followup_dir = os.path.join(fold, followup_ses)

    baseline_ims = [os.path.join(baseline_dir, x) for x in os.listdir(baseline_dir) if x.endswith('_ct.nii.gz')]
    followup_ims = [os.path.join(followup_dir, x)  for x in os.listdir(followup_dir) if x.endswith('_ct.nii.gz')]

    study_dict = {'baselines': baseline_ims, 'followups': followup_ims}
    return study_dict

def get_sub_nifti_path(baseline_path, followup_path):
    sub_dir = os.path.join(os.path.dirname(os.path.dirname(baseline_path)).replace('rawdata','derivatives'), 'subtraction')
    baseline_ses = os.path.basename(os.path.dirname(baseline_path))
    followup_ses = os.path.basename(os.path.dirname(followup_path))
    spl_b, spl_f = '', ''
    if 'split' in baseline_path:
        spl_b = '_split-{}'.format(baseline_path.split('split-')[1].split('_')[0])
    if 'split' in followup_path:
        spl_f = '_split-{}'.format(followup_path.split('split-')[1].split('_')[0])

    sub_name = os.path.basename(baseline_path).split('_')[0] + '_sesb-{}{}'.format(baseline_ses.split('-')[1],spl_b) + '_sesf-{}{}'.format(followup_ses.split('-')[1],spl_f) + '_msk.nii.gz'
    sub_path = os.path.join(sub_dir, sub_name)

    return sub_path

def create_evaluation_path(results_folder, sub_path, rater):
    return os.path.join(results_folder,os.path.basename(sub_path).replace('_ref.nii.gz', '_rater-{}_eval.json'.format(rater)))

def get_paths_followup(dataset_folder, ex, rater,chunks=None, results_folder='./results'):
    main_fold = os.path.join(dataset_folder, 'rawdata')
    folders = [os.path.join(main_fold,x) for x in os.listdir(main_fold) if 'sub-ctfu' in x]
    folders.sort()
    if chunks is not None:
        pointer1 = chunks * 20
        pointer2 = pointer1 + 20
    else:
        pointer1 = 0
        pointer2 = len(folders)
    paths = []
    for fold in folders[pointer1:pointer2]:
        unique_sessions = [x for x in os.listdir(fold) if 'ses' in x]
        if len(unique_sessions) != 2:
            continue
        baseline_ses, followup_ses = get_baseline_fu_ses(unique_sessions)
        print('dataset_folder ', fold)
        print('baseline: ', baseline_ses)
        print('fu: ', followup_ses)

        study_dict = get_study_dict(fold, baseline_ses, followup_ses)
        print(study_dict)

        for baseline_path in study_dict['baselines']:
            for followup_path in study_dict['followups']:
                sub_path = get_sub_nifti_path(baseline_path, followup_path)
                print('subpath ', sub_path)
                eval_path = create_evaluation_path(results_folder, sub_path, rater)
                if ex:
                    if os.path.isfile(eval_path):
                        print('continued')
                        continue

                b_msk_path, b_sr_path, b_ctd_path = get_derivative_path_from_raw_ct(baseline_path)
                f_msk_path, f_sr_path, f_ctd_path = get_derivative_path_from_raw_ct(followup_path)

                if os.path.isfile(sub_path):
                    print(baseline_path)
                    ps = [baseline_path, b_msk_path,b_sr_path,b_ctd_path,followup_path,f_msk_path,f_sr_path,f_ctd_path,sub_path]
                    paths.append(ps)
                else:
                    print('stoopid')
            print('#############')
    return paths

def load_json(json_path):
    name = Path(json_path).name
    name = str(name).split('_')[0]
    with open(json_path) as json_data:
        js = json.load(json_data)
        js['name'] = name
        json_data.close()
    return js

def get_results_fu(path,vert):
    try:
        entry = get_csv_entry(path)
        labels = pd.read_csv('./labels.csv')

        label  = labels[vert][labels['ID']==entry]

        if label.values > 0:            # handle non-existing labels
            vert_label = str(int(label))
        else:
            vert_label = ""
    except Exception as e:
        print('error ', str(e))
        vert_label = ""
    return vert_label

def get_csv_entry(img_path):
    csv_name = str(os.path.basename(img_path).replace('_ct.nii.gz', ''))
    return csv_name

def get_paths_from_case(case_path):
    cases = []
    unique_sessions = [x for x in os.listdir(case_path) if 'ses' in x]
    baseline_ses, followup_ses = get_baseline_fu_ses(unique_sessions)
    study_dict = get_study_dict(case_path, baseline_ses, followup_ses)
    for baseline_path in study_dict['baselines']:
        for followup_path in study_dict['followups']:
            sub_path = get_sub_nifti_path(baseline_path, followup_path)

            if os.path.isfile(sub_path):
                p_dict = {
                    'b_img_pth': baseline_path,
                    'f_img_pth': followup_path,
                    'sub_pth'  : sub_path,
                }
                cases.append(p_dict)
    return cases

def get_rater_cases_from_csv(data_frame, dataset_path,rater=None, load_all=False, exclude_rated=False):
    labelled_IDs = pd.read_csv('./CTFU_Fx_{}.csv'.format(str(rater)))['ID'].tolist()

    rater_cases = []
    for idx, row in data_frame.iterrows():

        if load_all:
            rater_cases.append(row['case_name'])

        else:
            if row['rater'] == rater or row['multirater'] ==1:
                rater_cases.append(row['case_name'])
    rater_cases= list(set(rater_cases))
    rater_cases.sort()
    cases_paths = []
    for case in rater_cases:
        cs_pth = os.path.join(os.path.join(dataset_path,'rawdata'), case)
        if not os.path.isdir(cs_pth):
            continue
        case_p = get_paths_from_case(os.path.join(os.path.join(dataset_path,'rawdata'), case))
        if not case_p:
            continue
        if exclude_rated:
            for idx,c in enumerate(case_p):
                ID_b = os.path.basename(c['b_img_pth']).replace('_ct.nii.gz', '')
                ID_f = os.path.basename(c['f_img_pth']).replace('_ct.nii.gz', '')
                if ID_b in labelled_IDs and ID_f in labelled_IDs:
                    case_p.pop(idx)
        cases_paths = cases_paths + case_p
    return cases_paths


from django.shortcuts import render
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.db.models import Q
from .models import Voter, Scope, Person
import random
from .forms import VoterForm
from django.core.mail import EmailMessage
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.views import View
from django.contrib import messages

class Home(View):

    def get(self, request, *args, **kwargs):
        persons = list(Person.objects.filter(voted=False).values_list("name", flat=True))
        return render(request, "home.html", {"persons":sorted(persons)})

    def post(self, request):
        form = VoterForm(request.POST)

        if form.is_valid():
            userIP = request.META.get('HTTP_X_FORWARDED_FOR')
            ip = userIP.split(',')[0] if userIP else request.META.get('REMOTE_ADDR')

            email = request.POST["email"]
            name = request.POST["name"]

            scope = list(Scope.objects.filter(Q(isChosen=False) & ~Q(name__icontains=name)).values_list("name", flat=True).order_by("?"))

            #handle case if scope is empty
            try:
                chosen = random.choice(scope)
            except IndexError:
                alreadyVoted = "Brak osób do wylosowania!"
                persons = list(Person.objects.filter(voted=False).values_list("name", flat=True))
                return render(request, "home.html", {"persons":sorted(persons), "alreadyVoted":alreadyVoted})

            chosen_obj = Scope.objects.get(name=chosen)

            #get Person object and handle exception if doesnt exists
            try:
                person_obj = Person.objects.get(name=name, voted=False)
            except ObjectDoesNotExist:
                alreadyVoted = "Ta osoba już wylosowała!"
                persons = list(Person.objects.filter(voted=False).values_list("name", flat=True))
                return render(request, "home.html", {"persons":sorted(persons), "alreadyVoted":alreadyVoted})

            #create and save voter with proper data
            voter_obj = Voter(name=name,email=email, ip_address=ip, chosen_person=chosen_obj)
            voter_obj.save()

            #mark scope person as chosen
            chosen_obj.isChosen = True
            chosen_obj.save()

            # mark voting person as voted
            person_obj.voted = True
            person_obj.save()

            #send email confirmation
            email = EmailMessage(
                f"Świąteczne losowanie",
                f"Cześć {name},
 Wylosowana przez Ciebie osoba to: {chosen}.
"
                "Wesołych Świąt!",
                settings.DEFAULT_FROM_EMAIL,
                [email]
            )
            email.content_subtype="html"
            email.send()

            #request.session["chosen"] = chosen
            messages.info(request, chosen)
            return HttpResponseRedirect(request.path)


from fastapi import FastAPI, Request, Form
import pandas as pd
import numpy as np
from flask import Flask, request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.responses import JSONResponse
from fastapi.exceptions import HTTPException
from typing import Optional
'''
#------------>>>> Abrimos consola, ejecutamos uvicorn main:app --reload      <<<----------
#------------>>>>Esto hará que cada ctrl+s que hagamos, el server se carge y actualice    <<<-----------
#------------>>>>Los enlaces de cada consulta se encuentran en el archivo ipynb "funciones_para_app   <<<-----------
'''

# Creamos la aplicación FastAPI y cargamos la base de datos

app = FastAPI(tiitle='Proyecto Individual',
              title='Consulta de peliculas en las plataformas de streaming: Amazon, Disney+, Hulu y Netflix')

df_api = pd.read_csv('base_datos_completa_api.csv', sep=',')

# Definimos el método
@app.get('/about')
async def read_intro():
    return 'API creada con FastAPI y Uvicorn'

# Aplicamos las consutlas que fueron solicitadas:
'''
1. Cantidad de veces que aparece una keyword en el título de peliculas/series, por plataforma.
'''

@app.get("/get_max_duration/")
async def get_max_duration(anio: int, plataforma: str, duracion: str, ):
        plataformas_df = df_api.copy()  # Copiamos el DataFrame original
        if plataforma == "amazon":
                df1 = plataformas_df[(plataformas_df["type"] == "movie") & (plataformas_df["release_year"] == anio) & (
                    plataformas_df["duration_type"] == duracion) & (plataformas_df["id"].str.findall("a"))]
        elif plataforma == "disney":
                df1 = plataformas_df[(plataformas_df["type"] == "movie") & (plataformas_df["release_year"] == anio) & (
                    plataformas_df["duration_type"] == duracion) & (plataformas_df["id"].str.findall("d"))]
        elif plataforma == "hulu":
                df1 = plataformas_df[(plataformas_df["type"] == "movie") & (plataformas_df["release_year"] == anio) & (
                    plataformas_df["duration_type"] == duracion) & (plataformas_df["id"].str.findall("h"))]
        elif plataforma == "netflix":
                df1 = plataformas_df[(plataformas_df["type"] == "movie") & (plataformas_df["release_year"] == anio) & (
                    plataformas_df["duration_type"] == duracion) & (plataformas_df["id"].str.findall("n"))]
        else:
                print("No contamos con la base de datos de dicha plataforma")

        df2 = df1[df1["duration_int"] == (df1["duration_int"].max())]
        return f'Peliculas de {plataforma} del año {anio} con mayor duracion en {duracion}: {df2.iloc[0, 2]}'

'''
2. Cantidad de películas por plataforma con un puntaje mayor a XX en determinado año.
'''

@app.get("/get_score_count/")
def get_score_count(platform: str, scored: int, year: int):
    plataformas_df = df_api.copy()  # Copiamos el DataFrame original
    df5 = plataformas_df[(plataformas_df["score_mean"] > scored) & (
        plataformas_df["release_year"] == year)]  # Filtro de busqueda por Score y Año
    if platform == "amazon":
        # ------->>>>>> Generamos un dataframe general con filtros especificos segun busqueda
        df_gsc = df5[(df5["type"] == "movie") & (df5["id"].str.findall("a"))]
    elif platform == "disney":
        df_gsc = df5[(df5["type"] == "movie") & (df5["id"].str.findall("d"))]
    elif platform == "hulu":
        df_gsc = df5[(df5["type"] == "movie") & (df5["id"].str.findall("h"))]
    elif platform == "netflix":
        df_gsc = df5[(df5["type"] == "movie") & (df5["id"].str.findall("n"))]
    else:
        print("Try again")

    return "Peliculas de {} del año {} con puntaje mayor en score a {} es: {}".format(platform, year, scored, df_gsc.shape[0])

'''
3. Cantidad de peliculas por plataforma.
'''

@app.get("/get_count_platform/")
def get_count_plaform(platform: str):
    plataformas_df = df_api.copy()  # Copiamos el DataFrame original
    if platform == "amazon":
       df1 = plataformas_df[(plataformas_df["type"] == "movie") & (
           plataformas_df["id"].str.contains("a"))]
    elif platform == "disney":
       df1 = plataformas_df[(plataformas_df["type"] == "movie") & (
           plataformas_df["id"].str.contains("d"))]
    elif platform == "hulu":
       df1 = plataformas_df[(plataformas_df["type"] == "movie") & (
           plataformas_df["id"].str.contains("h"))]
    elif platform == "netflix":
       df1 = plataformas_df[(plataformas_df["type"] == "movie") & (
           plataformas_df["id"].str.contains("n"))]
    else:
        print("No contamos con esta plataforma")
    df2 = len(df1)
    return f'La cantidad de películas de de la paltaforma {platform} es {df2}'

'''
4. Actor que más se repite según plataforma.
'''

@app.get("/get_actor/")
def get_actor(platform: str, year: int):
     plataformas_df = df_api.copy()  # Copiamos el DataFrame original
     if platform == "amazon":
       df1 = plataformas_df[(plataformas_df["release_year"] == year) & (plataformas_df["id"].str.contains("a"))]
     elif platform == "disney":
        df1 = plataformas_df[(plataformas_df["release_year"] == year) & (plataformas_df["id"].str.contains("d"))]
     elif platform == "hulu":
        df1 = plataformas_df[(plataformas_df["release_year"] == year) & (plataformas_df["id"].str.contains("h"))]
     elif platform == "netflix":
        df1 = plataformas_df[(plataformas_df["release_year"] == year ) & (plataformas_df["id"].str.contains("n"))]
     else:
           print("No contamos con esta plataforma")
           return
     if df1["cast"].isna().all():
        return "No hay información de actores para la plataforma y año seleccionados"

     actors = df1["cast"].str.split(",", expand=True).stack().str.strip().reset_index(level=1, drop=True)
     top_actor = actors.value_counts().index[0]
     return f'El actor que más aparece en la plataforma {platform} y en el año {year} es {top_actor}'


from __future__ import print_function, division
import numpy as np

def rebinatt(atttime, attra, attdec, attres):
	'''
	The function to rebinning the attitude file
	#dist -- not used for now.
	Rebin the ATT array according to the new attres.
	Based on this scipy coockbook:
	https://scipy-cookbook.readthedocs.io/items/Rebinning.html
	'''
	a = np.vstack((atttime, attra, attdec))
	oldres = atttime[1] - atttime[0]
	if oldres == attres:
		return a
	else:
		k = int(oldres / attres)
		newlen = len(atttime) * k
		newshape = (3, newlen)
		assert len(a.shape) == len(newshape)
		slices = [slice(0, old, float(old) / new) for old, new in zip(a.shape, newshape)]
		coordinates = np.mgrid[slices]
		indices = coordinates.astype('i')  # choose the biggest smaller integer index
		newatttime, newattra, newattdec = a[tuple(indices)]
		newatttime = np.linspace(newatttime[0], newatttime[-1], len(newatttime))
		for raid in range(len(attra) - 1):
			newattra[raid * k:(raid + 1) * k] = \
			np.linspace(attra[raid], attra[raid + 1], k)
		for decid in range(len(attdec) - 1):
			newattdec[decid * k:(decid + 1) * k] = \
			np.linspace(attdec[decid], attdec[decid + 1], k)
		return newatttime, newattra, newattdec


import torch
import torch.nn.functional as F
from torch.nn import ModuleList
from torch_geometric.nn import PNAConv, BatchNorm, global_mean_pool
from .Base import Base

class PNAStack(Base):
    def __init__(
        self,
        deg: list,
        edge_dim: int,
        *args,
        **kwargs,
    ):

        self.aggregators = ["mean", "min", "max", "std"]
        self.scalers = [
            "identity",
            "amplification",
            "attenuation",
            "linear",
        ]
        self.deg = torch.Tensor(deg)
        self.edge_dim = edge_dim

        super().__init__(*args, **kwargs)

    def get_conv(self, input_dim, output_dim):
        return PNAConv(
            in_channels=input_dim,
            out_channels=output_dim,
            aggregators=self.aggregators,
            scalers=self.scalers,
            deg=self.deg,
            edge_dim=self.edge_dim,
            pre_layers=1,
            post_layers=1,
            divide_input=False,
        )

    def __str__(self):
        return "PNAStack"


def procurador(x,y):
    if len(x) == 0 or len(y) == 0:
        return 0
    else:
        posicao = y.find(x)
        return y[posicao:posicao + len(x)]

suspeito = str(input())
analisados = str(input()).lower()

suspeito_minusc = suspeito.lower()

if procurador(suspeito_minusc, analisados) == suspeito.lower():
  print(f'Encontrei, o culpado é o {suspeito}!')
else:
  print(f'Não era o {suspeito}, tenho que continuar procurando.')


import streamlit as st
import random
from dataclasses import dataclass
import pandas as pd

WORKABLE_DAYS = 220

st.title('Why your project drags on so long..')
st.markdown("""
# Simple Delay Calculator
This calculator conducts a simple simulation based on parameters you provide.
It may have too many assumptions, simplifications and omissions to be accurate
but it can help you gain awareness of some forces that conspire against
your roadmap which people often claim they know about, but forget
when giving lead time estimates for their planned projects.
""")
st.header("First about your dev team")
st.markdown("""
- Devs are perfectly fungible (anyone can pick any task, no specialization)
- no difference in performance
""")
devs = st.slider('How many devs work on it?', 1, 10, 2)
st.header("Then about your task")
st.markdown("""
**Bufferless and Accurate Estimate**

The estimate you give here is assumed to be perfect - it will really take as long
in this simulation to complete the project. This simulation is mostly about all
factors other than just wrong estimates that contribute to delays.
""")
total_mandays_estimate = st.slider('What is the initial time estimate (total man-work-days) you extracted from devs?', 1, 100, 10)
leadtime_estimate = total_mandays_estimate / devs
st.markdown("""
**Is The Task Really Well Defined?**

Some tasks, like fixing a bug or completing a routine process require no iteration
and are not subject to uncertainty. Software development however, is famous for vague and shifting
requirements, or misunderstanding thereof. If you select that the task is well defined,
the team will finish the task after they rack up enough productive days (your estimate from above).
If the task is not well defined, you will need to specify when is the check-in point, imagine
for instance a demo to the stakeholder or end-to-end tests, this is the point when
the progress is reset to zero to simulate how the **real** requirements were discovered.
""")
well_defined = st.checkbox('The task is really well defined and understood')
if not well_defined:
    checkin_moment = 100
    last_moment_change = st.checkbox("Only at the end of the project we will know if it is the right thing to build", value=True)
    if not last_moment_change:
        checkin_moment = st.slider("What % of the project must be complete before you can verify if it is the right thing to build?", 1, 99, 80)
st.markdown("""
**Waiting on review**

If this task/project requires a team member to review before work can proceed, check the following box.
The review can only take place when the reviewer is available, same probabilities will be used
for determining if the reviewer is available for review as for the rest of the team (see later section "Availability")
""")
review_needed = st.checkbox("Is there any sort of review involved? e.g. Pull Request review.", value=True)
if review_needed:
    review_frequency = st.slider("The (PR) review happens every X days (1=every day)", 1, 10, 5)
st.markdown("Requirement of an approval or input from some external stakeholder can also be a cause for waiting. Approval is simulated the exact same way as review.")
approval_needed = st.checkbox("Is there an external stakeholder who needs to approve anything?", value=True)
if approval_needed:
    approval_frequency = st.slider("Approval/input from an external stakeholder happens every X days (1=every day)", 1, 30, 10)
st.header("Availability stats for the team")
st.write("Spillover means that your devs are still preoccupied with leftovers from the previous project")
spillover = st.slider('spillover % time spent on previous unfinished work', 0, 100, 50)
st.write("Is your project team in any capacity involved in solving production issues? What % of the time more or less?")
emergencies = st.slider('% time spent on emergencies', 0, 100, 25)
st.write("Devs will leave your team, when it happens it is very disruptive. What was the turnover over the last 12 months?")
turnover = st.slider('turnover per year (% quitting per year)', 0, 100, 33)
st.write("What gap (in days) should the simulation use for the time between a leaving dev's last day and the new one starting?")
replacement = st.slider('time (days) till new hire starts', 0, 300, 60)
st.write("How long till an experienced dev on your team picks up their first independent ticket?")
onboarding = st.slider('time (days) it takes new hire to become productive', 0, 300, 15)
st.write("For sake of simplicity devs's chance of taking holidays increases with every day, but the total will never exceed the specified max PTOs")
holidays = st.slider('number of holidays in a year (PTO)', 0, 40, 25)
st.write("People get sick, devs too. Use % chance (per working day) of a dev calling in sick.")
sickness = st.slider('sickness %', 0, 100, 1)
st.write("Add up recurring meetings devs are involved in (not related to the project).")
meetings = st.slider('meetings %', 0, 100, 10)
st.write("Specify % of time a mentor / buddy spends when onboarding a new dev")
helps_onbording = st.slider('% Time spent helping onboarded devs (when there are new devs)', 0, 100, 10)
st.write("How time consuming is your recruiting process for your own devs? This will kick in only when recruiting.")
helps_recruiting = st.slider('% Time spent participating in interviews (when looking for new devs)', 0, 100, 5)

# st.subheader('Multitasking - how many different projects run at the same time')
# multitasking = st.slider('multitasking', 0, 10, 3)
@dataclass
class Contributor:
    name: str
    not_filled: bool = False
    onboarded: bool = True
    days_till_replacement:int = 0
    days_till_productive: int = 0

    worked_days: int = 0
    other_work: int = 0
    sick_days: int = 0
    used_pto: int = 0
    days_recruiting: int = 0
    days_onboarding: int = 0
    days_firefighting: int = 0
    days_notfilled:int = 0
    days_meetings:int = 0
    days_waiting:int = 0

    def report(self) -> dict:
        return {
            "Role": self.name,
            "Productive": self.worked_days,
            "Other work": self.other_work,
            "Firefighting": self.days_firefighting,
            "Sick": self.sick_days,
            "PTO": self.used_pto,
            "Onboarding": self.days_onboarding,
            "Recruiting": self.days_recruiting,
            "Meetings": self.days_meetings,
            "Absent (Role Not Filled)": self.days_notfilled,
            "Waiting": self.days_waiting,
        }

def sick(contr: Contributor) -> bool:
    return random.randint(1, 100) <= sickness

def on_holidays(contr: Contributor) -> bool:
    if contr.used_pto >= holidays:
        return False
    return random.randint(1, 100) <= contr.worked_days

def on_emergency(contr: Contributor) -> bool:
    return random.randint(1, 100) <= emergencies

def last_day(contr: Contributor) -> bool:
    daily_chance = turnover / WORKABLE_DAYS
    fractionized_roll = (random.randint(1, 10000) / 100)
    return  fractionized_roll <= daily_chance

def in_meeting(contr: Contributor) -> bool:
    return random.randint(1, 100) <= meetings

def is_helping_onboard(contr) -> bool:
    return random.randint(1, 100) <= helps_onbording

def is_helping_recruit(contr) -> bool:
    return random.randint(1, 100) <= helps_recruiting

def busy_prev_work(contr) ->bool:
    return random.randint(1, 100) <= spillover

def is_productive(contr: Contributor, onbording_needed:bool, recruitment_in_progress:bool) -> bool:
    if contr.not_filled:
        contr.days_notfilled += 1
        return False
    if not contr.onboarded:
        contr.days_onboarding += 1
        False
    if sick(contr):
        contr.sick_days += 1
        return False
    if on_holidays(contr):
        contr.used_pto += 1
        return False
    if on_emergency(contr):
        contr.days_firefighting += 1
        return False
    if in_meeting(contr):
        contr.days_meetings += 1
        return False
    if onbording_needed and is_helping_onboard(contr):
        contr.days_onboarding += 1
        return False
    if recruitment_in_progress and is_helping_recruit(contr):
        contr.days_recruiting += 1
        return False
    if busy_prev_work(contr):
        contr.other_work += 1
        return False
    return True

worked_days = 0
lead_days = 0
_devs = [Contributor("dev") for _ in range(devs)]
reviewer = Contributor("reviewer")
ext_stakeholder = Contributor("external stakeholder")
perc_complete = 0
scope_change_waste = 0
while (worked_days < total_mandays_estimate) or not well_defined:
    perc_complete = (worked_days / total_mandays_estimate) * 100
    if not well_defined and perc_complete > checkin_moment:
        well_defined = True
        scope_change_waste = worked_days
        worked_days = 0
    recruiting_in_progress = any([dev.not_filled for dev in _devs])
    onboarding_in_progress = any([not dev.onboarded for dev in _devs])
    reviewer_available = is_productive(reviewer, onboarding_in_progress, recruiting_in_progress)
    stakeholder_available = is_productive(ext_stakeholder, onboarding_in_progress, recruiting_in_progress)
    for dev in _devs:
        if is_productive(dev, onboarding_in_progress, recruiting_in_progress):
            if review_needed and (lead_days % review_frequency) == 0 and not reviewer_available:
                dev.days_waiting += 1
            elif approval_needed and (lead_days % approval_frequency) == 0 and not stakeholder_available:
                dev.days_waiting += 1
            else:
                dev.worked_days += 1
                worked_days += 1
        if not dev.onboarded and dev.days_till_productive < 1:
            dev.onboarded = True
        if not dev.onboarded:
            dev.days_till_productive -= 1
        if dev.not_filled and dev.days_till_replacement < 1:
            dev.not_filled = False
            dev.days_till_productive = onboarding
        if dev.not_filled:
            dev.days_till_replacement -= 1
        if not dev.not_filled and last_day(dev):
            dev.days_till_replacement = replacement
            dev.not_filled = True
    lead_days += 1
late_by = round(lead_days - leadtime_estimate, 1)
st.markdown("""
# Results
- Lead time means: how many working days from the start till finish the project took.
In real life situation this would be calendar days, but this work obsessed simulation does not know weekends..
- Waste is any activity that did not progress the project (recruiting, onboarding, emergencies, PTO, sickness)
- Scope Change waste: component of the overall waste corresponding to the uncertainty / spec change
""")
col1, col2  = st.columns(2)
col3, col4 = st.columns(2)
col1.metric(label="Lead time", value=f"{lead_days} days", delta=f"{late_by} days", delta_color="inverse")
waste = (lead_days * devs) -(leadtime_estimate * devs)
col2.metric(label="Waste (multitasking/unavailable)", value=f"{waste} days")
col3.metric(label="Scope Change Waste", value=f"{scope_change_waste} days")
total_wait = sum([d.days_waiting for d in _devs])
col4.metric(label="Waiting", value=f"{total_wait} days")
report = [d.report() for d in _devs]
report = pd.DataFrame(report)
st.header("Individual Time Breakdown per Contributor")
st.dataframe(report)


from tensorflow.keras.models import Sequential
from tensorflow.keras.models import load_model
import numpy as np
import gym
import time

# 신경망 모델을
model = load_model("./cartpole_by_DQN.h5")

env = gym.make("CartPole-v1", render_mode="human")
long_reward = 0

# CartPole 플레이
s = env.reset()
while True:
    if isinstance(s, tuple):
        s = s[0]
    q = model.predict(np.reshape(s, [1, 4]))  # 신경망이 예측한 행동
    a = np.argmax(q[0])
    s1, r, done, info, _ = env.step(a)
    s = s1
    long_reward += r

    env.render()
    time.sleep(0.05)

    if done:
        print("에피소드 점수:", long_reward)
        break

env.close()


#! /usr/bin/env python

from Random import Random
import sys
import numpy as np
import matplotlib.pyplot as plt

class Create_Histogram:

    def __init__(self, file_name):
        self.file_name= file_name

    def Plot(self):
        with open(self.file_name, 'r') as file:
            n = [float(x) for x in file.read().split()]

        plt.hist(n,  10, density=True, facecolor='r', alpha=0.75, label='Random Numbers')

        # plot formating options
        plt.xlabel('x')
        plt.ylabel('Probability')
        plt.title('Uniform random number')
        plt.grid(True)
        plt.legend()
        #ax = plt.gca()
        #ax.set_ylim([0.8, 1.2])
        # show figure (program only ends once closed
        plt.show()
        plt.savefig("Binomial.png")

if __name__ == "__main__":
    # if the user includes the flag -h or --help print the options
    if '-h' in sys.argv or '--help' in sys.argv:
        print ("Usage: %s [-seed number]" % sys.argv[0])
        print
        sys.exit(1)

    # default seed
    seed = 5555

    # read the user-provided seed from the command line (if there)
    if '-seed' in sys.argv:
        p = sys.argv.index('-seed')
        seed = sys.argv[p+1]

    # set random seed for numpy
    np.random.seed(seed)

    # class instance of our Random class using seed

    Binomial = Random()

    # create some random data
    N = 300

    # an array of random numbers from numpy
    x = np.random.rand(N)

    # an array of random numbers using our Random class
    myx = []
    # Write the numbers to a file
    file_read = "Number_list.txt"
    f = open(file_read,'w')
    for i in range(0,N):
        numb = Binomial.Binomial(N,0.35)
        myx.append(numb)
        f.write(str(numb)+" ")

    f.close()

    hist = Create_Histogram(file_read)
    hist.Plot()


from django.shortcuts import render,redirect
from .models import Post,Classify
from django.http import JsonResponse,HttpResponse
from my_core.jianshu import *
from threading import  Thread
from django.core.paginator import Paginator
from w_auth.user_decorator import is_login
# Create your views here.
def index(request):
    return render(request, 'post/index.html')

def get_post(request,slug):
    post = Post.my_objects.get_active_one(slug)
    context={'post':post,
             'title':post.title}
    return render(request,'post/detail.html',context)

@is_login
def write_post(request):
    uid = request.session.get('uid')
    try:
        cid = Classify.objects.filter(owner_id=int(uid)).first().id
    except:
        cid = None
    context = {'title':'写文章',
               'cid':cid}
    return render(request,'post/write.html',context)

def add_classify(request):
    uid = request.session.get('uid')
    if request.method=='GET':
        context={'title':'新建分类'}
        return render(request, 'post/new_classify.html',context)
    if request.method=='POST':
        title = request.POST.get('ctitle','')
        if title == '':
            return HttpResponse('不能为空')
        else:
            classify = Classify()
            classify.title =  title
            classify.owner_id = uid
            classify.save()
            return redirect('/write')

def add_post(request):
    uid = int(request.session.get('uid'))
    if request.method=='GET':
        c_l = Classify.objects.filter(owner_id=uid)
        context={'title':'新建分类',
                 'c_l':c_l}
        return render(request, 'post/new_post.html',context)
    if request.method=='POST':
        title = request.POST.get('ptitle','')
        cid = request.POST.get('cid','')
        if title == '' or cid =='':
            return HttpResponse('不能为空')
        else:
            post = Post()
            post.my_init(title,uid,'新文章内容',int(cid))
            post.save()
            return redirect('/write')

def update_post(request):
    if request.method == 'POST':
        id = int(request.POST.get('pid'))
        body = request.POST.get('body')
        post = Post.my_objects.get(id=id)
        if post.author_id == request.session.get('uid'):
            post.body=body
            post.save()
            context = {'title':'发布成功',
                       'post':post}
            return render(request,'post/success_post.html',context)

def splider_post(request):
    if request.method =='GET':
        return render(request,'post/splider.html')

    if request.method == 'POST':
        kw = request.POST.get('kw')
        start = int(request.POST.get('start'))
        end = int(request.POST.get('end'))
        t = Thread(target=manage,args=(start,end,kw))
        t.start()
        return redirect('/')

def jianshu(requst):
    try:
        kw = requst.GET.get('q')
        pindex = int(requst.GET.get('p'))
    except:
        kw = 'python'
        pindex =2
    kws = JianShuPost.objects.values('keyword').distinct()

    posts = JianShuPost.objects.filter(keyword=kw).all()
    try:
        paginator =Paginator(posts,10)
        page = paginator.page(pindex)
    except:
        paginator = None
        page = None
    context ={
        'title':'简书文章',
        'page':page,
        'paginator':paginator,
        'kw':kw,
        'kws':kws
    }
    return render(requst,'post/jianshu.html',context)

def jianshu_detail(request,slug):
    post = JianShuPost.objects.filter(slug=slug)[0]

    context = {
        'title':post.title,
        'post':post
    }
    return render(request,'post/jianshu_detail.html',context)


"""
CS510: Deep Learning
Winter 2021, Portland State University
Assignment #1: FashionMNIST

Steve Braich

Assignment Description:
https://web.cecs.pdx.edu/~singh/courses/winter21/dl/a1w21.pdf
The goal here is to implement a fully connected NN to classify images and basically learn how its performance is
affected by choices of different parameters and data.

Sources:
 - "Explore NN with PyTorch" by Grecnik on Kaggle:
   https://www.kaggle.com/nikitagrec/explore-nn-with-pytorch

 - "The curious case of the vanishing & exploding gradient" by Emma Amor
   https://medium.com/ml-cheat-sheet/how-to-avoid-the-vanishing-exploding-gradients-problem-f9ccb4446c5a
"""
import numpy as np
import pandas as pd
import torch
from torch import nn
from torch.utils.data import Dataset
from torchvision import transforms
from PIL import Image
from typing import List, Any

# Normalize the data
data = pd.read_csv('fashion-mnist_test.csv')
mean = np.array(data.iloc[:,1:]).flatten().mean()
std = np.array(data.iloc[:,1:]).flatten().std()
transf = transforms.Compose([transforms.ToTensor(), transforms.Normalize((mean / 225,), (std / 225,))])

class FashionWear(Dataset):
    """
    Class object inherited from Dataset used to transform Fashing MNIST data
    """

    def __init__(self, data, transform=None):
        self.transform = transform
        self.labels = data.label.values
        self.images = data.iloc[:, 1:].values.astype('uint8').reshape(-1, 28, 28)

    def __len__(self):
        return len(self.images)

    def __getitem__(self, idx):
        label = self.labels[idx]
        img = Image.fromarray(self.images[idx])

        if self.transform:
            img = self.transform(img)

        return img, label

class FashionNetwork(torch.nn.Module):
    """
    FashionNetwork is the class object used to propagate thru our network
    """

    def __init__(self, hidden_size: List, activation):
        super().__init__()

        # These aren't going to change
        self.INPUT_SIZE = 784
        self.hidden_size = hidden_size
        self.OUTPUT_SIZE = 10

        self.activation = activation

        # define modules in our Fully Connect (FC) Layers
        modules = []
        modules.append(nn.Linear(in_features=self.INPUT_SIZE, out_features=hidden_size[0]))
        modules.append(self.activation)

        for i in range(len(hidden_size) - 1):
            modules.append(nn.Linear(in_features=hidden_size[i], out_features=hidden_size[i + 1]))
            modules.append(self.activation)

        modules.append(nn.Linear(in_features=hidden_size[len(hidden_size) - 1], out_features=self.OUTPUT_SIZE))

        self.module_list = nn.ModuleList(modules=modules)

    def forward(self, x):

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

        for f in self.module_list:
            x = x.to(device)
            x = f(x)

        x = x.to(device)
        return x

class FashionModel():
    """
    FashionModel is the class object that encapsulates our model
    """

    def __init__(self, data_train, data_test, batch_size: int ) -> None:
        self.model = None
        self.params = []
        self.train_accuracy = []
        self.test_accuracy = []
        self.loss_train = []
        self.loss_test = []
        self.batch_size = batch_size
        self.criterion = nn.CrossEntropyLoss()
        self.data_train = data_train
        self.data_test = data_test

    def test(self) -> None:
        """
        Evaluate a model
        """

        batch_length = len(self.test_loader)
        with torch.no_grad():
            correct = 0
            total = 0
            for batch_id, (image, label) in enumerate(self.test_loader, start=1):
                image = image.view(image.shape[0], -1)
                device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
                image = image.to(device)
                label = label.to(device)
                outputs = self.model(image)

                if (batch_id / batch_length == 1):
                    loss = self.criterion(outputs, label)
                    self.loss_test.append(loss.item())
                    print(f"Testing Loss: {loss.item():.4f}   ", end=' ')

                predicted = torch.argmax(input=outputs, dim=1)
                total += label.size(0)
                correct += (predicted == label).sum().item()

        accuracy = 100 * correct / total
        self.test_accuracy.append(accuracy)
        print(f"Testing Accuracy: {accuracy}%")

    def train(self, hidden_size: List, activation: Any, learn_rate: float, momentum: float, epochs: int) -> None:
        """
        Train a fully connected neural network classifier on a dataset of fashion images
        """
        device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        self.model = FashionNetwork(hidden_size=hidden_size, activation=activation)
        self.model.to(device)

        # Print Training Parameters
        print(f"Hidden Layers: {hidden_size}")
        print(f"Learning Rate: {learn_rate}")
        print(f"Activation:    {activation.__str__()}")
        print(f"Batch Size:    {self.batch_size}")
        print(f"Epochs:        {epochs}")
        print("------------------------------------------------------------------------------------------")

        self.train_loader = torch.utils.data.DataLoader(dataset=self.data_train, batch_size=self.batch_size, shuffle=True)
        self.test_loader = torch.utils.data.DataLoader(dataset=self.data_test, batch_size=self.batch_size, shuffle=True)

        optimizer = torch.optim.SGD(params=self.model.parameters(), lr=learn_rate, momentum=momentum)

        for epoch in range(1, epochs + 1):
            for batch_id, (image, label) in enumerate(self.train_loader):

                image = image.view(image.shape[0],-1)
                device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
                image = image.to(device)
                label = label.to(device)

                # Forward pass
                output = self.model(image)

                loss = self.criterion(output, label)
                loss = loss.to()
                # Initializing a gradient as 0 so there is no mixing of gradient among the batches
                optimizer.zero_grad()

                # Propagating the error backward
                loss.backward()

                # Prevent Gradient Explosion
                nn.utils.clip_grad_norm_(parameters=self.model.parameters(), max_norm=2.0, norm_type=2)
                # nn.utils.clip_grad_value_(model.parameters(), clip_value=1.0)

                # Optimizing the parameters
                optimizer.step()

            print(f"Epoch {epoch}/{epochs}  Training Loss: {loss.item():.4f}   ", end=' ')
            # print(f"Epoch {epoch}/{epochs}  Train Loss: {loss.item():.4f}   Train Accuracy: {accuracy:.2f}%   ", end=' ')
            self.loss_train.append(loss.item())
            self.test()

        for i in self.model.parameters():
            self.params.append(i)


import numpy as np
import pandas as pd
import pickle
import streamlit as st

load_model = pickle.load(open('migraine_trained_model.sav' ,'rb'))

def migrain_prediction(data_to_test):
    knn_predict_test = load_model.predict(data_to_test)[0]
    print("KNN:", knn_predict_test)
    return knn_predict_test

def main():
    st.title("Migrain Prediction")

    st.write("This is a web app to predict whether a person has migrain or not")

    st.write("Please fill the form below")

    global Age,Duration,Frequency,Location,Character,Intensity,Nausea,Vomit,Phonophobia,Photophobia,Visual,Sensory,Dysphasia,Dysarthria,Vertigo,Tinnitus,Hypoacusis,Diplopia,Defect,Ataxia,Conscience,Paresthesia,DPF

    Age = st.number_input("Age", min_value=0, max_value=100, value=0)
    Duration = st.number_input("Duration", min_value=0, max_value=10, value=0)
    Frequency = st.number_input("Frequency", min_value=0, max_value=10, value=0)
    Location = st.number_input("Location", min_value=0, max_value=10, value=0)
    Character = st.number_input("Character", min_value=0, max_value=10, value=0)
    Intensity = st.number_input("Intensity", min_value=0, max_value=10, value=0)
    Nausea = st.number_input("Nausea", min_value=0, max_value=10, value=0)
    Vomit = st.number_input("Vomit", min_value=0, max_value=10, value=0)
    Phonophobia = st.number_input("Phonophobia", min_value=0, max_value=10, value=0)
    Photophobia = st.number_input("Photophobia", min_value=0, max_value=10, value=0)
    Visual = st.number_input("Visual", min_value=0, max_value=10, value=0)
    Sensory = st.number_input("Sensory", min_value=0, max_value=10, value=0)
    Dysphasia = st.number_input("Dysphasia", min_value=0, max_value=10, value=0)
    Dysarthria = st.number_input("Dysarthria", min_value=0, max_value=10, value=0)
    Vertigo = st.number_input("Vertigo", min_value=0, max_value=10, value=0)
    Tinnitus = st.number_input("Tinnitus", min_value=0, max_value=10, value=0)
    Hypoacusis = st.number_input("Hypoacusis", min_value=0, max_value=10, value=0)
    Diplopia = st.number_input("Diplopia", min_value=0, max_value=10, value=0)
    Defect = st.number_input("Defect", min_value=0, max_value=10, value=0)
    Ataxia = st.number_input("Ataxia", min_value=0, max_value=10, value=0)
    Conscience = st.number_input("Conscience", min_value=0, max_value=10, value=0)
    Paresthesia = st.number_input("Paresthesia", min_value=0, max_value=10, value=0)
    DPF = st.number_input("DPF", min_value=0, max_value=10, value=0)

    migrain = ''

    if st.button("Predict"):
        migrain = migrain_prediction([[Age,Duration,Frequency,Location,Character,Intensity,Nausea,Vomit,Phonophobia,Photophobia,Visual,Sensory,Dysphasia,Dysarthria,Vertigo,Tinnitus,Hypoacusis,Diplopia,Defect,Ataxia,Conscience,Paresthesia,DPF]])
        st.success(migrain)

if __name__ == '__main__':
    main()


"""
Portfolio.py

Author: Brian McKenna

This file defines a Portfolio class which is meant to represent a basket portfolio of
arbritrary amounts of shares of different stocks. This class also allows a variety
of calculations/ analytics to be performed on said portfolio.

A Portfolio object takes multiple parameters: a dictionary of stock tickers and their shares:
"basket", a start and end date as DateTime objects, and an index ticker to serve as a benchmark
index.
"""
# Make necessary imports
import numpy as np
import pandas as pd
import pandas_datareader.data as web
import datetime as dt

class Portfolio:
    """A basket portfolio of select stocks, over the timeframe from start to end
    using index indx as a benchmark"""
    def __init__(self, basket, start, end, indx):
        self.sharedyct = basket
        self.start = start
        self.end = end
        self.indx = indx

        # Creating pandas dataframe "data" which contains the daily price of the total portfolio as well
        # as the daily total price amount of each respective stock in the portfolio
        keys = list(self.sharedyct.keys())
        data = pd.DataFrame(web.DataReader(keys[0], "yahoo", start, end)["Close"]) * self.sharedyct[keys[0]]
        data[keys[0]] = data["Close"]
        for count in range(1, len(self.sharedyct)):
            data1 = web.DataReader(keys[count], "yahoo", start, end)["Close"] * self.sharedyct[keys[count]]
            data["Close"] += data1
            data[keys[count]] = data1
        self.data = data

        # Creating pandas dataframes "data1" and "data2",
        # "data1" replicates "data" but instead of closing price, it
        # contains daily logarithmic returns of the total portfolio and each stock. "data1" also contains an
        # additional column "Weighted Return" which is the weighted average of each stocks returns relative to
        # that stock's weight in the portfolio that dat

        # data2 is a two-column dataframe with the closing price of the selected benchmark index as well as its
        # daily returns

        data1 = self.data.copy().reset_index(drop = True)

        data2 = pd.DataFrame(web.DataReader(self.indx, "yahoo", self.start, self.end)["Close"])
        data2 = data2.reset_index(drop = True)

        data2["Index Daily Return"] = 0.0
        data1["Daily Return"] = 0.0
        for i in self.sharedyct.keys():
            data1[i + " Daily Return"] = 0.0
        data1["Weighted Return"] = 0.0

        for count in range(1, len(data1)):
            curTotal = data1.iloc[count]["Close"]
            prevTotal = data1.iloc[count - 1]["Close"]
            data1.at[count, "Daily Return"] = np.log((curTotal / prevTotal))

            curTotal2 = data2.iloc[count]["Close"]
            prevTotal2 = data2.iloc[count - 1]["Close"]
            data2.at[count, "Index Daily Return"] = np.log((curTotal2 / prevTotal2))

            for i in self.sharedyct.keys():
                curStock = data1.iloc[count][i]
                prevStock = data1.iloc[count - 1][i]
                dlyRtrn = np.log((curStock / prevStock))
                data1.at[count, i + " Daily Return"] = dlyRtrn
                weight = curStock / curTotal
                data1.at[count, "Weighted Return"] += (weight * dlyRtrn)

        lyst = list(self.sharedyct.keys())
        lyst.append("Close")
        data1 = data1.drop(columns = lyst)

        #"data1" and "data2" are made attributes of the Portfolio objects as
        # "retData" and "indxData" respectively
        self.retData = data1
        self.indxData = data2

    def averageDailyReturn(self):
        """Calculates the geometric average return iteratively"""
        time = (self.end - self.start).days
        geoprod = 1
        for count in range(1, len(self.retData)):
            geoprod *= (1 + self.retData.at[count, "Daily Return"])
        geomean = (geoprod ** (1 / time)) - 1
        return geomean

    def volatility(self):
        """Calculates volatility by taking standard deviation of weighted returns"""
        vol = np.std(self.retData["Weighted Return"])
        return vol

    def riskRatio(self):
        """Calculates ratio of (portfolio volatility / benchmark volatility)"""
        indxVol = np.std(self.indxData["Index Daily Return"])
        return self.volatility() / indxVol

    def marginalVolatility(self, ticker, shares):
        """Creates a new portfolio with "shares" additional shares of "ticker" stock,
        finds its volatility, and subtracts the original portfolio volatility from
        the new"""
        newDyct = self.sharedyct.copy()
        if ticker in list(self.sharedyct.keys()):
            newDyct[ticker] += shares
        else:
            newDyct[ticker] = shares

        newPort = Portfolio(newDyct, self.start, self.end, self.indx)
        newVol = newPort.volatility()
        volDiff = newVol - self.volatility()

        return volDiff

    def maxDrawDown(self):
        """Calculates the maximum distance of a stock price from its running maximum"""
        priceMax = 0
        distMax = 0
        for count in range(len(self.data)):
            date = self.data.index.tolist()[count]
            priceMax = max(priceMax, self.data.at[date, "Close"])
            dist = priceMax - self.data.at[date, "Close"]
            distMax = max(distMax, dist)
        return distMax


import urwid

window_stack = []
window_names = []

header = urwid.Text( "" )
footer = urwid.Text( "" )

ui = urwid.curses_display.Screen()

ui.register_palette([
    # name, foreground, background, mono
    ('banner', 'light gray', 'default', None),
    ('menu', 'light gray', 'default', 'bold'),
    ('selected', 'black', 'light gray', 'bold'),
])

top = urwid.Frame( urwid.SolidFill(), header, footer )

def push_window( frame, name=None ):
    window_stack.append( frame )
    window_names.append( name )
    update_top()

def pop_window():
    if len(window_stack) == 1:
       return False
    window_stack.pop()
    window_names.pop()
    update_top()
    clear_status()
    return True

def update_top():
    names = [ n for n in window_names if n ]
    header.set_text(" - ".join( names ) + "\n")
    top.set_body( window_stack[-1] )

def set_status(message):
    footer.set_text(message)

def clear_status():
    footer.set_text("")

class Abort(Exception):
    pass

class Back(Exception):
    pass

def raise_abort(*args, **kwargs):
    raise Abort()

def raise_back(*args, **kwarg):
    raise Back()

def redraw():
   cols, rows = ui.get_cols_rows()
   canvas = top.render( (cols, rows), focus=True )
   ui.draw_screen( (cols, rows), canvas )
   return cols, rows

def event_loop(ui):
    while True:
        try:
           cols, rows = redraw()

           keys = ui.get_input()
           for k in keys:
              if k == "esc":
                 if not pop_window():
                     break
              elif k == "window resize":
                 (cols, rows) = ui.get_cols_rows()
              else:
                 top.keypress( (cols, rows), k )
        except Back:
            pop_window()
        except (Abort, KeyboardInterrupt):
            return


import sys
input = lambda: sys.stdin.readline().rstrip()

def resolve():
    n = int(input())

    fib = [0]*(n+1)
    fib[0] = 1
    fib[1] = 1
    for i in range(2, n+1):
        fib[i] = fib[i-1]+fib[i-2]

    print(fib[n])

if __name__ == '__main__':
    resolve()


import torch
import torchvision

def create_custom_densenet161(class_nb: int,
                              pretrained: bool = False,
                              checkpointing: bool = True) -> torchvision.models.DenseNet:
    """
    Create a DenseNet-161 and modify its last layer to fit with the class number
    Args:
        class_nb: Amount of class
        pretrained: If the network needs ot be pretrained on ImageNet
        checkpointing: If true, enable gradient checkpointing

    Returns:
        A fully initialised Densenet-161
    """
    learner = torchvision.models.densenet161(pretrained=pretrained, memory_efficient=checkpointing)
    num_features = learner.classifier.in_features
    learner.classifier = torch.nn.Linear(num_features, class_nb)

    return learner

def create_custom_resnet50(class_nb: int,
                           pretrained: bool = False) -> torchvision.models.ResNet:
    """
    Create a ResNet-50 and modify its last layer to fit with the class number
    Args:
        class_nb: Amount of class
        pretrained:If the network needs ot be pretrained on ImageNet

    Returns:
        A fully initialised ResNet-50
    """
    learner = torchvision.models.resnet50(pretrained=pretrained)
    num_features = learner.fc.in_features
    learner.fc = torch.nn.Linear(num_features, class_nb)

    return learner

def create_custom_resnet152(class_nb: int,
                            pretrained: bool = False) -> torchvision.models.ResNet:
    """
       Create a ResNet-151 and modify its last layer to fit with the class number
       Args:
           class_nb: Amount of class
           pretrained:If the network needs ot be pretrained on ImageNet

       Returns:
           A fully initialised ResNet-151
   """
    learner = torchvision.models.resnet152(pretrained=pretrained)
    num_features = learner.fc.in_features
    learner.fc = torch.nn.Linear(num_features, class_nb)

    return learner

def create_classifier(name: str,
                      class_nb: int,
                      pretrained: bool = False,
                      checkpointing: bool = True):
    """
    Wrapper function to ease classifier creation
    Args:
        name: Name of the classifier
        class_nb: Amount of class
        pretrained: If the network needs to be pretrained on ImageNet
        checkpointing: If true, enables gradient checkpointing

    Returns:
        A fully initialised classifier
    """
    if name == 'densenet161':
        return create_custom_densenet161(class_nb, pretrained, checkpointing)
    elif name == 'resnet50':
        return create_custom_resnet50(class_nb, pretrained)
    elif name == 'resnet152':
        return create_custom_resnet152(class_nb, pretrained)
    raise NotImplementedError(f'The model {name} is not currently supported. Please add its loading to this file.')


Q = int(input())

n = 2 ** 20
A = [-1] * n
par = [i for i in range(n)]

def find(x):
    if par[x] == x:
        return x
    par[x] = find(par[x])
    return par[x]

for i in range(Q):
    t, x = map(int, input().split())
    if t == 1:
        h = find(x%n)
        A[h] = x
        par[h] = (h+1) % n
    elif t == 2:
        print(A[x%n])


import os
import numpy as np

def load_st_dataset(dataset):
    #output B, N, D
    if dataset == 'PEMSD4':
        data_path = os.path.join('../data/PEMS04/PEMS04.npz')
        # data_path = os.path.join('../data/PeMSD4/pems04.npz')
        data = np.load(data_path)['data'][:, :, 0]  #onley the first dimension, traffic flow data
    elif dataset == 'PEMSD8':
        data_path = os.path.join('../data/PEMS08/PEMS08.npz')
        data = np.load(data_path)['data'][:, :, 0]  #onley the first dimension, traffic flow data
    elif dataset == 'PEMSD3':
        data_path = os.path.join('../data/PEMS03/PEMS03.npz')
        data = np.load(data_path)['data'][:, :, 0]  #onley the first dimension, traffic flow data
    elif dataset == 'PEMSD7':
        data_path = os.path.join('../data/PEMS07/PEMS07.npz')
        data = np.load(data_path)['data'][:, :, 0]  #onley the first dimension, traffic flow data
    elif dataset == 'PEMSD7M':
        data_path = os.path.join('../data/PEMS07M/PEMS07M.npz')
        data = np.load(data_path)['data'][:, :, 0]  #onley the first dimension, traffic flow data
    elif dataset == 'PEMSD7L':
        data_path = os.path.join('../data/PEMS07L/PEMS07L.npz')
        data = np.load(data_path)['data'][:, :, 0]  #onley the first dimension, traffic flow data
    elif dataset == 'Decentraland':
        data_path = os.path.join('../token_data/Decentraland_node_features.npz')
        data = np.load(data_path)['arr_0'][:, :, 0]  #1 dimension, degree
    elif dataset == 'Bytom':
        data_path = os.path.join('../token_data/Bytom_node_features.npz')
        data = np.load(data_path)['arr_0'][:, :, 0]  #1 dimension, degree
    else:
        raise ValueError
    if len(data.shape) == 2:
        data = np.expand_dims(data, axis=-1)
    print('Load %s Dataset shaped: ' % dataset, data.shape, data.max(), data.min(), data.mean(), np.median(data))
    return data


import socket
import sys

hote = "localhost"
if sys.argv[1]:
	hote = sys.argv[1]
port = int(sys.argv[2])

print(hote)

connexion_avec_serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
	connexion_avec_serveur.connect((hote, port))
except Exception as e:
	sys.stderr.write("Salut terence {}\n".format(e))
print("Connexion établie avec le serveur sur le port {}".format(port))

msg_a_envoyer = b""
while msg_a_envoyer != b"fin":
    msg_a_envoyer = input("> ")
    # Peut planter si vous tapez des caractères spéciaux
    msg_a_envoyer = msg_a_envoyer.encode()
    # On envoie le message
    connexion_avec_serveur.send(msg_a_envoyer)
    msg_recu = connexion_avec_serveur.recv(1024)
    print(msg_recu.decode()) # Là encore, peut planter s'il y a des accents

print("Fermeture de la connexion")
connexion_avec_serveur.close()