import os
import numpy as np
from PIL import Image

class NoiseDel():
    #去除干扰噪声
    def noise_del(self,img):
        height = img.shape[0]
        width = img.shape[1]
        channels = img.shape[2]

        # 清除四周噪点
        for row in [0,height-1]:
            for column in range(0, width):
                if img[row, column, 0] == 0 and img[row, column, 1] == 0:
                    img[row, column, 0] = 255
                    img[row, column, 1] = 255
        for column in [0,width-1]:
            for row in range(0, height):
                if img[row, column, 0] == 0 and img[row, column, 1] == 0:
                    img[row, column, 0] = 255
                    img[row, column, 1] = 255

        # 清除中间区域噪点
        for row in range(1,height-1):
            for column in range(1,width-1):
                if img[row, column, 0] == 0 and img[row, column, 1] == 0:
                    a = img[row - 1, column]  # 上
                    b = img[row + 1, column]  # 下
                    c = img[row, column - 1]  # 左
                    d = img[row, column + 1]  # 右
                    ps = [p for p in [a, b, c, d] if 1 < p[1] < 255]
                    # 如果上下or左右为白色,设置白色
                    if  (a[1]== 255 and b[1]== 255) or (c[1]== 255 and d[1]== 255):
                        img[row, column, 0] = 255
                        img[row, column, 1] = 255
                    # 设置灰色

                    elif len(ps)>1:
                        kk = np.array(ps).mean(axis=0)
                        img[row, column, 0] = kk[0]
                        img[row, column, 1] = kk[1]
                        img[row, column, 2] = kk[2]
                    else:
                        img[row, column, 0] = 255
                        img[row, column, 1] = 255
        return img

    # 灰度化
    def convert2gray(self,img):
        if len(img.shape) > 2:
            gray = np.mean(img, -1)
            # 上面的转法较快，正规转法如下
            # r, g, b = img[:,:,0], img[:,:,1], img[:,:,2]
            # gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
            return gray
        else:
            return img

    # 二值化
    def binarizing(self,img,threshold, cov=False):
        w, h = img.shape
        if cov:
            for y in range(h):
                for x in range(w):
                    if img[x, y] > threshold:
                        img[x, y] = 0
                    else:
                        img[x, y] = 255
        else:
            for y in range(h):
                for x in range(w):
                    if img[x, y] < threshold:
                        img[x, y] = 0
                    else:
                        img[x, y] = 255
        return img

if __name__=="__main__":

    filepath = 'data/png'
    savepath = 'data/png_a2'
    if not os.path.exists(savepath):
        os.mkdir(savepath)

    filenames = os.listdir(filepath)
    nd = NoiseDel()
    for file in filenames:
        openname = os.path.join(filepath,file)
        image = Image.open(openname)
        image = np.array(image)

        # 去噪、灰度、二值化处理
        image = nd.noise_del(image)
        image = nd.convert2gray(image)
        image = nd.binarizing(image,threshold=190, cov=True)

        #
        image = Image.fromarray(image).convert('L')  # Image.fromarray(image)默认转换到‘F’模式，即浮点型，‘L’是整形

        savename = os.path.join(savepath,file)
        image.save(savename)


# 598. 范围求和
from typing import List

class Solution:
    # def maxCount(self, m: int, n: int, ops: List[List[int]]) -> int:
    #     if not ops:
    #         return m * n
    #     r = [float('inf'), float('inf')]
    #     for a, b in ops:
    #         if a < r[0]:
    #             r[0] = a
    #         if b < r[1]:
    #             r[1] = b
    #     return r[0] * r[1]

    def maxCount(self, m: int, n: int, ops: List[List[int]]) -> int:
        min_a, min_b = m, n
        for a, b in ops:
            min_a = min(min_a, a)
            min_b = min(min_b, b)
        return min_a * min_b

s = Solution()
m = 3
n = 3
operations = [[2,2],[3,3]]
print(s.maxCount(m, n, operations))


# Desafio 95 - Aprimorando os dicionarios

"""
Aprimore o DESAFIO 93 para que ele funcione com vários jogadores,
incluindo um sistema de visualização de DETALHES DO APROVEITAMENTO de cada jogador.
"""

from emoji import emojize

print('=' * 30)
print(f'\033[32m{"== TRANSFERMARKET 2.0 ==":^30}\033[m')
print('=' * 30)

jogador = dict()  # dicionario
partidas = []  # lista
time = list()  # lista

while True:  # laço infinito
    jogador.clear()  # Limpa o dicionario
    jogador['Nome'] = str(input(f'Nome do jogador {emojize(":trophy:")}: '))
    tot = int(input(f'Quantas partidas {jogador["Nome"]} jogou?: '))
    partidas.clear()  # lista limpada
    for c in range(0, tot):  # para contador in range 0 ate total de jogos
        partidas.append(int((input(f'-> Quantos gols{emojize(":soccer_ball:")} na {c + 1}ª partida? '))))
        # adiciona na lista partidas
    jogador['Gols'] = partidas[:]  # cria key gols com copia da lista partidas
    jogador['Total'] = sum(partidas)  # key total, soma de partidas
    time.append(jogador.copy())  # lista time adiciona copia do dicionario
    continuar = str(input('\033[34mQuer continuar [S/N]? \033[m')).upper().strip()[0]
    while continuar not in 'SN':
        continuar = str(input('\033[31mResposta invalida! Quer continuar [S/N]? \033[m')).upper().strip()[0]
    print('-' * 30)
    if continuar == 'N':
        break

print('No. ', end='')  # cabeçalho
for i in jogador.keys():  # indice na chave do dicionario
    print(f'{i:<15}', end='')
print()  # quebra linha
print('-=' * 30)
for k, v in enumerate(time):  # k = key, v = value, numerando a lista time
    print(f'{k:<5}', end='')
    for d in v.values():  # d = dado, valores da lista enumarada
        print(f'{str(d):<15}', end='')
    print()
print('-=' * 30)
while True:  # laço infinito
    busca = int(input('Buscar dados de qual jogador? (999 interrompe) '))  # variavel busca
    if busca == 999:
        break
    if busca >= len(time):  # se a variavel for maior que lenght(comprimento) da lista time
        print(f'ERRO! Não existe jogador com codigo {busca}!')
    else:
        print(f' -- Levantamento do jogador {time[busca]["Nome"]}')
        for i, g in enumerate(time[busca]['Gols']):   # i = indice, g = gols, enumerado lista times -> variavel -> gols
            print(f' No jogo {i + 1} fez {g} {"gol" if g == 1 else "gols"}')
    print('-' * 40)
print('<<< VOLTE SEMPRE >>>')


# type: ignore
import time
from collections import defaultdict

from pydavinci import davinci

resolve = davinci.Resolve()

project = resolve.project
project_manager = resolve.project_manager
media_pool = resolve.media_pool
media_storage = resolve.media_storage
ocf_folder = media_pool.add_subfolder("OCF", media_pool.root_folder)
media_pool.set_current_folder(ocf_folder)

def generate_premiere_proxies(input_dir, output_dir, proxyfactor):

    media_pool.import_media(input_dir)

    clips_res = defaultdict(list)

    for media in ocf_folder.clips:
        clips_res[media.properties["Resolution"]].append(media)

    project.set_preset("Proxy_Preset")

    render_ids = []

    for key in clips_res.keys():

        res_x, res_y = key.split("x")

        res_folder = media_pool.add_subfolder(key, ocf_folder)
        clips = clips_res[key]

        media_pool.move_clips(clips, res_folder)
        media_pool.create_timeline_from_clips(res_folder.name, res_folder.clips)

        timeline = project.timeline
        timeline.set_setting(
            "useCustomSettings", "1"
        )  # enable custom timeline size != project settings
        timeline.set_setting("timelineResolutionWidth", res_x)
        timeline.set_setting("timelineResolutionHeight", res_y)

        project.set_render_format_and_codec("mp4", "H264")
        render_settings = {
            "FormatWidth": (int(res_x) // proxyfactor),
            "FormatHeight": (int(res_y) // proxyfactor),
            "TargetDir": output_dir,
        }

        # Set Render Resolution
        project.set_render_settings(render_settings)

        render_id = project.add_renderjob()
        render_ids.append(render_id)
    return render_ids

job_ids = generate_premiere_proxies(
    "A:/path/to/my/media",
    "A:/path/to/output",
    proxyfactor=2,
)

project.render(job_ids)

for i in len(job_ids):

    render_status = project.render_status(job_ids[i])["JobStatus"]

    while render_status != "Complete":
        time.sleep(3)
        status = project.render_status(job_ids[i])
        try:
            percentage = status["CompletionPercentage"]
            time_left = status["EstimatedTimeRemainingInMs"] / 1000

        except KeyError:
            time.sleep(2)
            break

        print(
            f"Job ID {job_ids[i]} | Rendering time left: {time_left} | Percentage completed: {percentage}%\r",
            end="",
            flush=True,
        )

        render_status = status["JobStatus"]

    time_to_render = project.render_status(job_ids[i])["TimeTakenToRenderInMs"] / 1000
    print("\n")
    print(f"Job ID {job_ids[i]} | Rendering complete. | Total render time: {time_to_render}")


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:

    def __init__(self):
        self.count = 0

    def sumAndCount(self, root):
        if not root:
            return 0,0
        if not root.left and not root.right:
            self.count+=1
            return root.val, 1

        leftSum,leftCount,rightSum,rightCount = 0,0,0,0
        if root.left:
            leftSum,leftCount = self.sumAndCount(root.left)

        if root.right:
            rightSum,rightCount = self.sumAndCount(root.right)

        nodeSum = leftSum+rightSum+root.val
        nodeCount = leftCount+rightCount + 1
        # print("root",root.val,"nodeSum",nodeSum,"nodeCount",nodeCount)
        if nodeSum//nodeCount == root.val:
            self.count+=1

        return nodeSum,nodeCount

    def averageOfSubtree(self, root: Optional[TreeNode]) -> int:
        _,_ = self.sumAndCount(root)
        return self.count


import constraints
from domain_store import DomainStore
from typing import Callable
import random
from copy import deepcopy

def min_varname_selection(unassigned_variables, domain_map):
    return min(unassigned_variables)

def random_value_assignment(unassigned_variables, domain_map, variable, possible_values):
    return random.sample(possible_values, k = 1)[0]

def extract_element_helper(d: dict):
    return {k : next(iter(s)) for k, s in d.items()}

def search(
        domain_store: DomainStore,
        selection_policy: Callable,
        value_assignment_policy: Callable,
        find_all: bool = False,
    ):
    all_solutions = []
    search_history = []
    transaction_history = []
    unassigned_variables, domain_map = domain_store.get_state()
    next_var = selection_policy(unassigned_variables, domain_map)
    next_possible_values = deepcopy(domain_map[next_var])
    search_history.append((next_var, next_possible_values))
    while True:
        if len(search_history) == 0:
            break
        var, possible_values = search_history[-1]
        if len(search_history) == len(transaction_history):
            domain_store.revert_transaction(transaction_history.pop())

        while len(possible_values) > 0:
            val = value_assignment_policy(
                unassigned_variables,
                domain_map,
                var,
                possible_values
            )
            possible_values.remove(val)
            is_valid_assignment, domain_transaction = domain_store.assign_value(var, val)
            if is_valid_assignment:
                transaction_history.append(domain_transaction)
                break
        else:
            search_history.pop()
            continue
        unassigned_variables, domain_map = domain_store.get_state()
        if len(unassigned_variables) == 0:
            # Solution_found
            sln = extract_element_helper(domain_map)
            all_solutions.append(sln)
            if not find_all:
                break
        else:
            # Assign a variable to an unassigned.
            next_var = selection_policy(unassigned_variables, domain_map)
            next_possible_values = deepcopy(domain_map[next_var])
            search_history.append((next_var, next_possible_values))
    return all_solutions


from dataclasses import dataclass
from json import dumps as dump_json
from typing import Union

@dataclass(frozen=True)
class RocketStatsEvent:
    """Class to represent an event from the RocketStats websocket"""
    name: str
    type: str
    data: Union[str, dict]
    states: dict

    def __str__(self):
        tdata = '\n           '.join(dump_json(self.data, indent=4).split('\n'))
        tstates = '\n             '.join(dump_json(self.states, indent=4).split('\n'))

        return (
            f'RocketStatsEvent(\n'
            f'    name = {self.name},\n'
            f'    type = {self.type},\n'
            f'    data = {tdata},\n'
            f'    states = {tstates}\n'
            f')'
        )


import os
from pprint import pprint

import numpy
from PIL import Image

# Синтетически иметирует работу камеры микроскопа, создавая изображения со сдвигом
from numpy import array

def image_cutter(path, n_x, n_y, bias_x, bias_y,  # Симулирует фотографии микроскопа
                 is_digit=True):  # Путь, кол-во кусков по х, кол-во кусков по у, смещение по х, смещение по у, формат выведения результата
    try:
        img = Image.open(path)
        img_x, img_y = img.size
        img = img.crop((0, 0, img_x // n_x * n_x, img_y // n_y * n_y))
        if is_digit:
            images = []
        else:
            os.mkdir(path.split('/')[-1])
        count_x, count_y = 0, 0
        for i in range(0, img.size[1], img_y // n_y):
            if is_digit:
                images.append([])
            for j in range(0, img.size[0], img_x // n_x):
                new_image = img.crop((j, i, j + img_x // n_x + bias_x, i + img_y // n_y + bias_y))
                if is_digit:
                    images[-1].append(img_to_pixels(new_image))
                else:
                    new_image.save(f'{path.split("/")[-1]}/{count_x} {count_y}.jpeg')
                count_x += 1
            count_x = 0
            count_y += 1
        if is_digit:
            return images
        else:
            return f'Photo directory "{path.split("/")[-1]}" created'
    except Exception as ex:
        print('EXCEPTION!')
        print(ex)

def rgb_to_grid(images):  # Преобразует массив фотографий из RGB в L
    grid_imgs = images.copy()
    for i in range(len(images)):
        # print('i')
        for j in range(len(images[i])):
            # print('j')
            for y in range(len(images[i][j])):
                # print('y')
                for x in range(len(images[i][j][y])):
                    r, g, b = grid_imgs[i][j][y][x]
                    grid_imgs[i][j][y][x] = round(r * 299 / 1000 + g * 587 / 1000 + b * 114 / 1000)
    return grid_imgs

def img_to_pixels(img):  # Преобразует фотографию в цифру
    pixels_arr = []
    pixels = img.load()
    for a in range(img.size[1]):
        pixels_arr.append([])
        for b in range(img.size[0]):
            pixels_arr[-1].append(pixels[b, a])
    return pixels_arr

def photos_to_digits(directory):  # Преобразует фотографии из директории в цифру
    images = []
    # for i in range(len(os.listdir(directory))):
    for i in range(0, 3):
        line_images = []
        if i % 2 == 0:
            for j in range(len(os.listdir(f'{directory}/{i}'))):
                print(j)
                file_extention = os.listdir(f'{directory}/{i}')[0].split('.')[1]
                img = Image.open(f'{directory}/{i}/{i}_{j}.{file_extention}')
                line_images.append(img_to_pixels(img))
            print('dir', i)
            images.append(line_images)
        else:
            for j in range(12, -1, -1):
                print(j)
                file_extention = os.listdir(f'{directory}/{i}')[0].split('.')[1]
                img = Image.open(f'{directory}/{i}/{i}_{j}.{file_extention}')
                # img.show()
                line_images.append(img_to_pixels(img))
            print('dir', i)
            images.append(line_images)
    print(numpy.array(images).shape)
    return images


import re
import os
from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING

import doi
import click

import papis.config
import papis.pick
import papis.filetype
import papis.document
import papis.importer
import papis.downloaders.base
import papis.logging

if TYPE_CHECKING:
    import habanero

logger = papis.logging.get_logger(__name__)

KeyConversionPair = papis.document.KeyConversionPair

# NOTE: the API JSON format is maintained at
#   https://github.com/CrossRef/rest-api-doc/blob/master/api_format.md

_filter_names = frozenset([
    "has_funder", "funder", "location", "prefix", "member", "from_index_date",
    "until_index_date", "from_deposit_date", "until_deposit_date",
    "from_update_date", "until_update_date", "from_created_date",
    "until_created_date", "from_pub_date", "until_pub_date",
    "from_online_pub_date", "until_online_pub_date", "from_print_pub_date",
    "until_print_pub_date", "from_posted_date", "until_posted_date",
    "from_accepted_date", "until_accepted_date", "has_license",
    "license_url", "license_version", "license_delay",
    "has_full_text", "full_text_version", "full_text_type",
    "full_text_application", "has_references", "has_archive",
    "archive", "has_orcid", "has_authenticated_orcid",
    "orcid", "issn", "type", "directory", "doi", "updates", "is_update",
    "has_update_policy", "container_title", "category_name", "type",
    "type_name", "award_number", "award_funder", "has_assertion",
    "assertion_group", "assertion", "has_affiliation", "alternative_id",
    "article_number", "has_abstract", "has_clinical_trial_number",
    "content_domain", "has_content_domain", "has_crossmark_restriction",
    "has_relation", "relation_type", "relation_object", "relation_object_type",
    "public_references", "publisher_name", "affiliation",
])

_types_values = frozenset([
    "book-section", "monograph", "report", "peer-review", "book-track",
    "journal-article", "book-part", "other", "book", "journal-volume",
    "book-set", "reference-entry", "proceedings-article", "journal",
    "component", "book-chapter", "proceedings-series", "report-series",
    "proceedings", "standard", "reference-book", "posted-content",
    "journal-issue", "dissertation", "dataset", "book-series", "edited-book",
    "standard-series",
])

_sort_values = frozenset([
    "relevance", "score", "updated", "deposited", "indexed", "published",
    "published-print", "published-online", "issued", "is-referenced-by-count",
    "references-count",
])

_order_values = frozenset(["asc", "desc"])

type_converter = {
    "book": "book",
    "book-chapter": "inbook",
    "book-part": "inbook",
    "book-section": "inbook",
    "book-series": "incollection",
    "book-set": "incollection",
    "book-track": "inbook",
    "dataset": "misc",
    "dissertation": "phdthesis",
    "edited-book": "book",
    "journal-article": "article",
    "journal-issue": "misc",
    "journal-volume": "article",
    "monograph": "monograph",
    "other": "misc",
    "peer-review": "article",
    "posted-content": "misc",
    "proceedings-article": "inproceedings",
    "proceedings": "inproceedings",
    "proceedings-series": "inproceedings",
    "reference-book": "book",
    "report": "report",
    "report-series": "inproceedings",
    "standard-series": "incollection",
    "standard": "techreport",
}

key_conversion = [
    KeyConversionPair("DOI", [{"key": "doi", "action": None}]),
    KeyConversionPair("URL", [{"key": "url", "action": None}]),
    KeyConversionPair("author", [{
        "key": "author_list",
        "action": lambda authors: [
            {k: a.get(k) for k in ["given", "family", "affiliation"]}
            for a in authors
        ],
    }]),
    KeyConversionPair("container-title", [
        {"key": "journal", "action": lambda x: x[0]}]),
    KeyConversionPair("issue", [papis.document.EmptyKeyConversion]),
    # "issued": {"key": "",},
    KeyConversionPair("language", [papis.document.EmptyKeyConversion]),
    KeyConversionPair("abstract", [papis.document.EmptyKeyConversion]),
    KeyConversionPair("ISBN", [{"key": "isbn", "action": None}]),
    KeyConversionPair("page", [{
        "key": "pages",
        "action": lambda p: re.sub(r"(-[^-])", r"-\1", p),
    }]),
    KeyConversionPair("link", [{
        "key": str(papis.config.get("doc-url-key-name")),
        "action": lambda x: _crossref_link(x)
    }]),
    KeyConversionPair("issued", [
        {"key": "year", "action": lambda x: _crossref_date_parts(x, 0)},
        {"key": "month", "action": lambda x: _crossref_date_parts(x, 1)}
    ]),
    KeyConversionPair("published-online", [
        {"key": "year", "action": lambda x: _crossref_date_parts(x, 0)},
        {"key": "month", "action": lambda x: _crossref_date_parts(x, 1)}
    ]),
    KeyConversionPair("published-print", [
        {"key": "year", "action": lambda x: _crossref_date_parts(x, 0)},
        {"key": "month", "action": lambda x: _crossref_date_parts(x, 1)}
    ]),
    KeyConversionPair("publisher", [papis.document.EmptyKeyConversion]),
    KeyConversionPair("reference", [{
        "key": "citations",
        "action": lambda cs: [
            {key.lower(): c[key]
                for key in set(c) - {"key", "doi-asserted-by"}}
            for c in cs
        ]
    }]),
    KeyConversionPair("title", [
        {"key": None, "action": lambda t: " ".join(t)}]),
    KeyConversionPair("type", [
        {"key": None, "action": lambda t: type_converter[t]}]),
    KeyConversionPair("volume", [papis.document.EmptyKeyConversion]),
    KeyConversionPair("event", [  # Conferences
        {"key": "venue", "action": lambda x: x["location"]},
        {"key": "booktitle", "action": lambda x: x["name"]},
        {"key": "year",
         "action": (lambda x:
                    _crossref_date_parts(x["start"], 0) if "start" in x else None)},
        {"key": "month",
         "action": (lambda x:
                    _crossref_date_parts(x["start"], 1) if "start" in x else None)},
    ]),
]  # List[papis.document.KeyConversionPair]

def _crossref_date_parts(entry: Dict[str, Any],
                         i: int = 0) -> Optional[int]:
    date_parts = entry.get("date-parts")
    if date_parts is None:
        return date_parts

    assert len(date_parts) == 1
    parts, = date_parts

    # NOTE: dates can also be partial, where only the year is required
    if not (0 <= i < len(parts)):
        return None

    return int(parts[i])

def _crossref_link(entry: List[Dict[str, str]]) -> Optional[str]:
    if len(entry) == 1:
        return entry[0]["URL"]

    links = [
        # NOTE: using the 'similarity-checking' label here is just a heuristic,
        # since that seemed to be the better choice in some examples
        resource.get("URL") for resource in entry
        if resource.get("intended-application") == "similarity-checking"]

    return links[0] if links else None

def crossref_data_to_papis_data(data: Dict[str, Any]) -> Dict[str, Any]:
    global key_conversion
    new_data = papis.document.keyconversion_to_data(key_conversion, data)
    new_data["author"] = papis.document.author_list_to_author(new_data)
    return new_data

def _get_crossref_works(**kwargs: Any) -> "habanero.request_class.Request":
    import habanero
    cr = habanero.Crossref()
    return cr.works(**kwargs)

def get_data(
        query: str = "",
        author: str = "",
        title: str = "",
        dois: Optional[List[str]] = None,
        max_results: int = 0,
        filters: Optional[Dict[str, Any]] = None,
        sort: str = "score",
        order: str = "desc") -> List[Dict[str, Any]]:
    assert sort in _sort_values, "Sort value not valid"
    assert order in _order_values, "Sort value not valid"

    if dois is None:
        dois = []

    if filters is None:
        filters = {}

    if filters:
        unknown_filters = set(filters) - _filter_names
        if unknown_filters:
            raise ValueError(
                "Unknown filters '{}'. Filter keys must be one of '{}'"
                .format("', '".join(unknown_filters), "', '".join(_filter_names))
            )
    data = {
        "query": query,
        "query_author": author,
        "ids": dois,
        "query_title": title,
        "limit": max_results
        }

    kwargs = {key: data[key] for key in data if data[key]}
    if not dois:
        kwargs.update({"sort": sort, "order": order})
    try:
        results = _get_crossref_works(filter=filters, **kwargs)
    except Exception as exc:
        logger.error("Error getting works from Crossref.", exc_info=exc)
        return []

    if isinstance(results, list):
        docs = [d["message"] for d in results]
    elif isinstance(results, dict):
        if "message" not in results:
            logger.error("Error retrieving data from Crossref: incorrect message.")
            return []
        message = results["message"]
        if "items" in message:
            docs = message["items"]
        else:
            docs = [message]
    else:
        logger.error("Error retrieving data from Crossref: incorrect message.")
        return []

    logger.debug("Retrieved %s documents.", len(docs))
    return [crossref_data_to_papis_data(d) for d in docs]

def doi_to_data(doi_string: str) -> Dict[str, Any]:
    """Search through crossref and get a dictionary containing the data

    :param doi_string: Doi identificator or an url with some doi
    :returns: Dictionary containing the data
    :raises ValueError: If no data could be retrieved for the doi
    """
    doi_string = doi.get_clean_doi(doi_string)
    results = get_data(dois=[doi_string])
    if results:
        return results[0]
    raise ValueError(
        f"Could not retrieve data for DOI '{doi_string}' from Crossref")

@click.command("crossref")
@click.pass_context
@click.help_option("--help", "-h")
@click.option("--query", "-q", help="General query", default="")
@click.option("--author", "-a", help="Author of the query", default="")
@click.option("--title", "-t", help="Title of the query", default="")
@click.option(
    "--max", "-m", "_ma", help="Maximum number of results", default=20)
@click.option(
    "--filter", "-f", "_filters", help="Filters to apply", default=(),
    type=(click.Choice(list(_filter_names)), str),
    multiple=True)
@click.option(
    "--order", "-o", help="Order of appearance according to sorting",
    default="desc", type=click.Choice(list(_order_values)), show_default=True)
@click.option(
    "--sort", "-s", help="Sorting parameter", default="score",
    type=click.Choice(list(_sort_values)), show_default=True)
def explorer(
        ctx: click.core.Context,
        query: str,
        author: str,
        title: str,
        _ma: int,
        _filters: List[Tuple[str, str]],
        sort: str,
        order: str) -> None:
    """
    Look for documents on `Crossref <https://www.crossref.org/>`__.

    For example, to look for a document with the author "Albert Einstein" and
    export it to a BibTeX file, you can call

    .. code:: sh

        papis explore \\
            crossref -a 'Albert einstein' \\
            pick \\
            export --format bibtex lib.bib
    """
    logger.info("Looking up Crossref documents...")

    data = get_data(
        query=query,
        author=author,
        title=title,
        max_results=_ma,
        filters=dict(_filters),
        sort=sort,
        order=order)
    docs = [papis.document.from_data(data=d) for d in data]
    ctx.obj["documents"] += docs

    logger.info("Found %s documents.", len(docs))

class DoiFromPdfImporter(papis.importer.Importer):

    """Importer parsing a DOI from a PDF file and importing data from Crossref"""

    def __init__(self, uri: str) -> None:
        """The uri should be a filepath"""
        super().__init__(name="pdf2doi", uri=uri)
        self._doi: Optional[str] = None

    @classmethod
    def match(cls, uri: str) -> Optional[papis.importer.Importer]:
        """The uri should be a filepath"""
        filepath = uri
        if (
                os.path.isdir(filepath)
                or not os.path.exists(filepath)
                or not papis.filetype.get_document_extension(filepath) == "pdf"
                ):
            return None

        importer = DoiFromPdfImporter(filepath)
        return importer if importer.doi else None

    @property
    def doi(self) -> Optional[str]:
        if self._doi is None:
            self._doi = doi.pdf_to_doi(self.uri, maxlines=2000)
            self._doi = "" if self._doi is None else self._doi

            if self._doi:
                self.logger.info("Parsed DOI '%s' from file: '%s'.",
                                 self._doi, self.uri)
                self.logger.warning(
                    "There is no guarantee that this DOI is the correct one!")
            else:
                self.logger.debug("No DOI found in document: '%s'", self.uri)

        return self._doi

    def fetch(self) -> None:
        if self.doi:
            importer = Importer(uri=self.doi)
            importer.fetch()
            self.ctx = importer.ctx

class Importer(papis.importer.Importer):

    """Importer getting files and data from a DOI through Crossref"""

    def __init__(self, uri: str) -> None:
        super().__init__(name="doi", uri=uri)

    @classmethod
    def match(cls, uri: str) -> Optional[papis.importer.Importer]:
        try:
            doi.validate_doi(uri)
        except ValueError:
            return None
        else:
            return Importer(uri=uri)

    @classmethod
    def match_data(
            cls, data: Dict[str, Any]) -> Optional[papis.importer.Importer]:
        if "doi" in data:
            return Importer(uri=data["doi"])

        return None

    def fetch_data(self) -> None:
        data = papis.crossref.get_data(dois=[self.uri])
        if data:
            self.ctx.data = data[0]

    def fetch_files(self) -> None:
        if not self.ctx.data:
            return

        doc_url = self.ctx.data.get(
            papis.config.getstring("doc-url-key-name"),
            None)

        if doc_url is None:
            return

        self.logger.info("Trying to download document from '%s'.", doc_url)

        from papis.downloaders import download_document
        filename = download_document(doc_url)
        if filename is not None:
            self.ctx.files.append(filename)

class FromCrossrefImporter(papis.importer.Importer):

    """Importer that gets data from querying Crossref"""

    def __init__(self, uri: str) -> None:
        super().__init__(uri=uri, name="crossref")

    @classmethod
    def match(cls, uri: str) -> Optional[papis.importer.Importer]:
        # There is no way to check if it matches
        return None

    @classmethod
    def match_data(
            cls, data: Dict[str, Any]) -> Optional[papis.importer.Importer]:
        if "title" in data:
            return FromCrossrefImporter(uri=data["title"])

        return None

    def fetch_data(self) -> None:
        self.logger.info("Querying Crossref with '%s'.", self.uri)
        docs = [
            papis.document.from_data(d)
            for d in get_data(query=self.uri)]

        if not docs:
            return

        self.logger.warning(
            "Crossref query '%s' returned %d results. Picking the first one!",
            self.uri, len(docs))

        doc = docs[0]
        importer = Importer(uri=doc["doi"])
        importer.fetch()
        self.ctx.data = importer.ctx.data.copy()

class Downloader(papis.downloaders.Downloader):

    def __init__(self, uri: str) -> None:
        super().__init__(uri=uri, name="doi")
        self._doi: Optional[str] = None

    @classmethod
    def match(cls, uri: str) -> Optional[papis.downloaders.Downloader]:
        down = Downloader(uri)
        return down if down.doi else None

    @property
    def doi(self) -> Optional[str]:
        if self._doi is None:
            self._doi = doi.find_doi_in_text(self.uri)
            self._doi = "" if self._doi is None else self._doi

        return self._doi

    def fetch(self) -> None:
        if not self.doi:
            return

        importer = Importer(uri=self.doi)
        importer.fetch()
        self.ctx = importer.ctx


import logging

from odoo.exceptions import UserError
from odoo.tools.translate import _

from odoo.addons.base_rest import restapi
from odoo.addons.base_rest.components.service import skip_secure_response, to_int
from odoo.addons.component.core import Component

_logger = logging.getLogger(__name__)

class CartService(Component):
    _inherit = "shopinvader.cart.service"

    def set_carrier(self, **params):
        """
            This service will set the given delivery method to the current
            cart
        :param params: The carrier_id to set
        :return:
        """
        cart = self._get()
        if not cart:
            raise UserError(_("There is not cart"))
        else:
            self._set_carrier(cart, params["carrier_id"])
            return self._to_json(cart)

    # DEPRECATED METHODS #
    @restapi.method(
        routes=[(["/get_delivery_methods"], "GET")],
        output_param=restapi.CerberusValidator(
            "_validator_get_delivery_methods",
        ),
    )
    @skip_secure_response
    def get_delivery_methods(self):
        """
            !!!!DEPRECATED!!!!! Uses delivery_carrier.search

            This service will return all possible delivery methods for the
            current cart

        :return:
        """
        _logger.warning(
            "DEPRECATED: You should use %s in service %s",
            "search",
            "delivery_carrier",
        )
        return self.component("delivery_carrier").search(target="current_cart")["rows"]

    def apply_delivery_method(self, **params):
        """
            !!!!DEPRECATED!!!!! Uses set_carrier

            This service will apply the given delivery method to the current
            cart
        :param params: Dict containing delivery method to apply
        :return:
        """
        return self.set_carrier(carrier_id=params["carrier"]["id"])

    # Validator
    def _validator_apply_delivery_method(self):
        return {
            "carrier": {
                "type": "dict",
                "schema": {
                    "id": {
                        "coerce": int,
                        "nullable": True,
                        "required": True,
                        "type": "integer",
                    }
                },
            }
        }

    def _validator_get_delivery_methods(self):
        return {
            "country_id": {
                "coerce": to_int,
                "required": False,
                "type": "integer",
            },
            "zip_code": {"required": False, "type": "string"},
        }

    def _validator_set_carrier(self):
        return {
            "carrier_id": {
                "coerce": int,
                "nullable": True,
                "required": True,
                "type": "integer",
            }
        }

    # internal methods

    def _add_item(self, cart, params):
        res = super()._add_item(cart, params)
        self._unset_carrier(cart)
        return res

    def _update_item(self, cart, params, item=False):
        res = super()._update_item(cart, params, item)
        self._unset_carrier(cart)
        return res

    def _delete_item(self, cart, params):
        res = super()._delete_item(cart, params)
        self._unset_carrier(cart)
        return res

    def _set_carrier(self, cart, carrier_id):
        if carrier_id not in cart.shopinvader_available_carrier_ids.ids:
            raise UserError(_("This delivery method is not available for you order"))
        cart._set_carrier_and_price(carrier_id)

    def _unset_carrier(self, cart):
        cart._remove_delivery_line()

    def _get_lines_to_copy(self, cart):
        # Override. Don't copy delivery lines.
        res = super()._get_lines_to_copy(cart)
        return res.filtered(lambda l: not l.is_delivery)


from ehcmodel.common.kdl_template import *
from ehcmodel.common.data_preproc import *
from ehcmodel.common.exp_preproc import exp_preprocess, gen_save_path

import os
import inspect

from collections import defaultdict
import itertools
import pickle
import time
from pprint import pprint
from sklearn.decomposition import FastICA

exp_name = 'lab2_big_20v_10t'
_,posori_all,es_all = load_boxworld_raw(exp_name)
X_all,y_all,es_all = load_boxworld_data(exp_name);
X_all = X_all.astype("float32").astype(theano.config.floatX)
y_all = y_all.astype("int32")

cmap_name = 'hot_r'
#generate each experiment parameters and run eval_grid_point
def eval_on_grid(eval_funcs,**kwargs):
    sub_exp_num = len(glob.glob(plot_root+kwargs['dir_name']+'/eval_results*.pkl'))

    changing_param_names = [k for k in kwargs.keys() if isinstance(kwargs[k],list) and len(kwargs[k])>1]
    not_changing_param_names = [k for k in kwargs.keys() if not (isinstance(kwargs[k],list) and len(kwargs[k])>1)]
    assert 'dir_name' in not_changing_param_names

    grid_comps = []
    for k,v in kwargs.iteritems():
        if isinstance(v,list):
            grid_comps.append(v)
        else:
            grid_comps.append([v])
    print(grid_comps)
    not_changing_params = dict(kwargs)
    for k in changing_param_names:
        del not_changing_params[k]

    results =defaultdict(dict)

    for grid_vertex in itertools.product(*grid_comps):
        params = dict(zip(kwargs.keys(),grid_vertex))
        changing_params = dict(params)
        for k in not_changing_param_names:
            del changing_params[k]
        starttime = time.time()
        values = eval_grid_point(eval_funcs,**params)
        results['eval_time'][tuple(changing_params.values())] = (time.time()-starttime)
        for key in values.keys():
            results[key][tuple(changing_params.values())] = values[key]
        pprint(dict(results))
    if not os.path.isdir(plot_root+kwargs['dir_name']):
        os.makedirs(plot_root+kwargs['dir_name'])
    pprint((not_changing_params,changing_params.keys(),dict(results)),open(plot_root+kwargs['dir_name']+'/eval_results'+str(sub_exp_num)+'.txt','w'))

    pickle.dump((not_changing_params,changing_params.keys(),dict(results)),open(plot_root+kwargs['dir_name']+'/eval_results'+str(sub_exp_num)+'.pkl','w'))
    return results

def eval_grid_point(eval_methods,dir_name,description,n_code,n_coding_layer,sparsity_mode,sparsity_k,dropout_p,preprocess,
                    sampling_rate,minibatch_size,view_angle,turn_angle,reconst_mask,early_stop,n_epochs):

    frame = inspect.currentframe()
    _, _, _, values = inspect.getargvalues(frame)

    del values['frame']
    del values['eval_methods']
    random_state = np.random.RandomState(1999)
    use_cache = 'use_cache' in eval_methods
    plot_types = ['z','z_lin','z_lin_wta','bin_lin_wta','z_lin_thres','bin_lin_thres','z_lin_ll1','z_lin_ll1_bin']

    Z_PLOT_TYPE = 0
    Z_LIN_PLOT_TYPE = 1
    Z_LIN_WTA_PLOT_TYPE = 2
    FIRE_LIN_WTA_PLOT_TYPE = 3
    Z_LIN_THRES_PLOT_TYPE = 4

    if use_cache:
        save_path = gen_save_path(values)
        values = {}
    else:
        save_path, X,Y,posori,_,_,_,es  = \
                                exp_preprocess(X_all = X_all,y_all=y_all,posori_all=posori_all,es_all=es_all,
                                               split=False,random_state=random_state,**values)
        checkpoint_dict = load_checkpoint(dir_name+'/'+save_path+".pkl" )
        try:
            checkpoint_dict = load_checkpoint(dir_name+'/'+save_path+".pkl" )
        except Exception as e:
            print (dir_name+'/'+save_path+".pkl couldnt be loaded\n"+str(e))
            return {}
        if n_coding_layer== 'ica':
            fica = checkpoint_dict["fica_object"]
            z_lin_all = fica.transform(X)
            z_all = fica.transform(X)
        else:
            test_function = checkpoint_dict["test_function"]
            encode_function = checkpoint_dict["encode_function"]
            encode_linear_function = checkpoint_dict["encode_linear_function"]
            #decode_function = checkpoint_dict["decode_function"]
            #predict_function = checkpoint_dict["predict_function"]

            z_lin_all, = encode_linear_function(X)
            z_all, = encode_function(X)

        values = {}
        dead_neuron_map = np.sum(z_all>0,axis=0)<=0
        dead_neuron_count = np.sum(dead_neuron_map)

        values['dead_neuron_count'] = dead_neuron_count
        values['num_samples'] = X.shape[0]

        #xs,ys = discretize(posori,es)
        #xs = xs / sampling_rate
        #ys = ys / sampling_rate

        discr_posori = np.round(posori[:,0:2]/es['step_size']).astype(int)
        xsize,ysize = np.max(discr_posori,axis=0)+1

        angles = posori[:,2].round().astype(int)

        fit_angles = (np.arange(es['num_angles'])*360/es['num_angles'])#[::36]#[0]
        act_2d = np.zeros([len(plot_types),len(fit_angles),z_all.shape[1],xsize,ysize])
        for ai,angle in enumerate(fit_angles):
            angle_mask = angles == angle
            discr_places = discr_posori[angle_mask]
            discr_place_inv_idx = {tuple(r):i for i,r in enumerate(discr_places)}
            X_angle = X[angle_mask]

            for pi,plot_type in enumerate(plot_types):
                if plot_type in ['z'] :
                    #z, = encode_function(X_angle)
                    z = z_all[angle_mask]
                elif plot_type == 'z_lin':
                    #z, = encode_linear_function(X_angle)
                    z = z_lin_all[angle_mask]
                elif plot_type in ['z_lin_wta'] :
                    z = wta_np(z_lin_all)[angle_mask]
                elif plot_type in ['bin_lin_wta']:
                    #z = (z_all[angle_mask]>0).astype(int)
                    z = (wta_np(z_lin_all)[angle_mask]>0).astype(int)
                elif plot_type == 'z_lin_thres':
                    z = z_lin_all[angle_mask]
                    z_max = np.max(z,axis=0)
                    mask =np.kron(z_max*0.8,np.ones((z.shape[0],1)))
                    z[z<mask] = 0
                elif plot_type == 'bin_lin_thres':
                    z = z_lin_all[angle_mask]
                    z_max = np.max(z,axis=0)
                    mask =np.kron(z_max*0.5,np.ones((z.shape[0],1)))
                    z[z<mask] = 0
                    z = (z>0).astype(int)
                elif plot_type == 'z_lin_ll1':
                    z = llsparsity_np(z_lin_all,1./z.shape[1])[angle_mask]
                elif plot_type == 'z_lin_ll1_bin':
                    z = (llsparsity_np(z_lin_all,1./z.shape[1])[angle_mask]>0).astype(int)

                #pprint(discr_place_inv_idx)
                for x1 in range(0,xsize):
                    for y1 in range(0,ysize):
                        #print(x1,y1)
                        if not ((x1,y1) in discr_place_inv_idx):
                            print(str((x1,y1))+' is blocked')
                            continue
                        zxy = z[discr_place_inv_idx[(x1,y1)]]
                        act_2d[pi,ai,:,x1,y1] = zxy
        #pickle.dump([z_all,z_lin_all,yoh],open('zzzz0301.pkl','wb'))
        mins = np.min(z_lin_all,axis=0).tolist()
        maxs = np.max(z_lin_all,axis=0).tolist()
        minmax = ({'mins':mins,'maxs':maxs})
        lims = np.max(np.array([minmax['mins'],minmax['maxs']]),axis=0)
        #print(lims)

    if 'activations' in eval_methods:

        dir_path = plot_root+dir_name+'/'+save_path+"/activations/"
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)

        for ai,angle in enumerate(fit_angles):
            print(angle)
            for pi,plot_type in enumerate(plot_types[:4]):
                if not os.path.isdir(dir_path+plot_type+"/"):
                    os.makedirs(dir_path+plot_type+"/")
                fig = plt.figure()
                subplotdata = []
                for di in range(z_all.shape[1]):
                    #print(di)
                    ax = fig.add_subplot(math.ceil(math.sqrt(z_all.shape[1])),math.ceil(math.sqrt(z_all.shape[1])),di+1)
                    plt.axis('off')
                    im = ax.imshow(act_2d[pi,ai,di],interpolation='none')
                    subplotdata.append(act_2d[pi,ai,di])
                    """
                    if plot_type == 'fire_lin_wta':
                        im = ax.imshow(act_2d[pi,ai,di],interpolation='none',clim=(-1,1))
                    elif lims[di]>0:
                        im = ax.imshow(act_2d[pi,ai,di],interpolation='none',clim=(-lims[di],lims[di]))
                    else:
                        im = ax.imshow(act_2d[pi,ai,di],interpolation='none',clim=(-1,1))
                    """
                    plt.colorbar(im)

                plt.savefig(dir_path+plot_type+"/"+plot_type+"_"+str(angle).zfill(3)+'.png')
                pickle.dump(subplotdata,open(dir_path+plot_type+"/z"+plot_type+"_"+str(angle).zfill(3)+'.pkl','w'))
                #plt.show()
                plt.close()
                #print(act_2d)

    if 'summed_activations' in eval_methods:
        print('Plotting summed activations')
        dir_path = plot_root +dir_name+ "/all/"
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)

        for pi,plot_type in enumerate(plot_types):#zip([3],['sum']):#zip([0,1],['sum','firesum']):
            if not os.path.isdir(dir_path+plot_type+"/"):
                os.makedirs(dir_path+plot_type+"/")
            fig = plt.figure()
            if use_cache:
                cached_d2plot = pickle.load(open(dir_path+plot_type+"/zsum_act_"+save_path+'.pkl','r'))
            subplotdata = []
            for di in range(n_code):
                ax = fig.add_subplot(math.ceil(math.sqrt(n_code)),math.ceil(math.sqrt(n_code)),di+1)
                plt.axis('off')
                if use_cache:
                    d2plot = cached_d2plot[di]
                else:
                    d2plot = np.sum(act_2d[pi,:,di],axis=0)

                if np.max(d2plot)>0:
                    im = ax.imshow(d2plot,interpolation='none',clim=(0,np.max(d2plot)),cmap=plt.get_cmap(cmap_name))
                else:
                    im = ax.imshow(d2plot,interpolation='none',cmap=plt.get_cmap(cmap_name))
                subplotdata.append(d2plot)
                plt.colorbar(im)

            plt.savefig(dir_path+plot_type+"/sum_act_"+save_path+'.png')
            if not use_cache:
                pickle.dump(subplotdata,open(dir_path+plot_type+"/zsum_act_"+save_path+'.pkl','w'))
            plt.close()

    if 'spatial_coverage_plot' in eval_methods:
        print('Plotting spatial coverage')
        dir_path = plot_root +dir_name+"/all/"
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)
        for pi,plot_type in enumerate(plot_types):#zip([0,1],['sum','firesum']):
            if not os.path.isdir(dir_path+plot_type+"/"):
                os.makedirs(dir_path+plot_type+"/")
            fig = plt.figure()
            plt.axis('off')
            if use_cache:
                d2plot = pickle.load(open(dir_path+plot_type+"/zcov_"+save_path+'.pkl','r'))
            else:
                if plot_type == 'bin_lin_wta':
                    d2plot = np.max(np.sum(act_2d[pi,:],axis=0),axis=0)
                else:
                    d2plot = np.sum(np.sum(act_2d[pi,:],axis=0),axis=0)
            #im = plt.imshow(d2plot,interpolation='none',clim=(0,np.max(d2plot)))
            if np.max(d2plot)>0:
                im = plt.imshow(d2plot,interpolation='none',clim=(0,np.max(d2plot)),cmap=plt.get_cmap(cmap_name))
            else:
                im = plt.imshow(d2plot,interpolation='none',cmap=plt.get_cmap(cmap_name))
            plt.colorbar(im)
            plt.savefig(dir_path+plot_type+"/cov_"+save_path+".png")
            if not use_cache:
                pickle.dump(d2plot,open(dir_path+plot_type+"/zcov_"+save_path+'.pkl','w'))
            plt.close()

    if 'epoch_metrics' in eval_methods:
        dir_path = plot_root+dir_name+'/'+save_path+"/epoch_metrics/"
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)

        train_epoch_results = checkpoint_dict["train_epoch_results"]
        val_epoch_results = defaultdict(list,checkpoint_dict["val_epoch_results"])
        val_epoch_results['cost']= val_epoch_results['val_cost']

        #print (train_epoch_results.keys())
        #print (val_epoch_results.keys())
        values['last_val_cost'] = val_epoch_results['cost'][-1]
        values['last_train_cost'] = train_epoch_results['cost'][-1]
        values['num_epochs'] = len(train_epoch_results['cost'])

        for k in train_epoch_results:
            plt.figure()
            plt.plot(train_epoch_results[k],label = 'train')

            if k in val_epoch_results:
                assert len(val_epoch_results[k])-1 % len(train_epoch_results[k])
                plt.plot(range(0,len(train_epoch_results[k]),len(train_epoch_results[k])/(len(val_epoch_results[k])-1)),
                                val_epoch_results[k][1:],label = 'val')
            plt.title(str(k))
            plt.legend()
            plt.savefig(dir_path+str(k)+'.png')
            plt.close()

    return values


#Author: Eduardo Valverde

from bokeh.io import curdoc
from bokeh.layouts import column, layout
from bokeh.models import Button, CheckboxButtonGroup, RadioButtonGroup, Div, Slider, Dropdown, Select, Spacer
from afib.risk_scores import care, afriMale, afriFem, chad, poaf, npoaf

age = Slider(start=0, end=100, value=1, step=1, title="Age (y)")

care_div = Div(text="Care score: ", width=200, height=100)
afri_div = Div(text="Afri score: ", width=200, height=100)
chad_div = Div(text="Chad score: ", width=200, height=100)
poaf_div = Div(text="Poaf score: ", width=200, height=100)
npoaf_div = Div(text="Npoaf score: ", width=200, height=100)

menu = [("Stable cardiac disease, no other medical problems, undergoing noncomplex surgery","cd"),
        ("Stable cardiac disease, one or more controlled medical problems, undergoing noncomplex surgery","cdmp"),
        ("Any uncontrolled medical problem OR undergoing complex surgery","or"),
        ("Any uncontrolled medical problem AND undergoing complex surgery","and"),
        ("Chronic or advanced cardiac disease undergoing cardiac surgery as a last hope to save or improve life","lh")]

def careClick(careNum):
    if (careNum.item == "cd"):
        care_div.text = "Care score: " + str(care(True,False,False,False,False))
    elif(careNum.item == "cdmp"):
        care_div.text = "Care score: " + str(care(False,True,False,False,False))
    elif(careNum.item == "or"):
        care_div.text = "Care score: " + str(care(False,False,True,False,False))
    elif(careNum.item == "and"):
        care_div.text = "Care score: " + str(care(False,False,False,True,False))
    elif(careNum.item == "lh"):
        care_div.text = "Care score: " + str(care(False,False,False,False,True))

care_opt = Dropdown(label="Choose Description", menu=menu)
care_opt.on_click(careClick)

def afriUpd(attr, old, new):
    if (afri_sex.active == 0):
        if (afri_isPVD.active == [0, 2]):
            afri_div.text = "Afri score: " + str(afriMale(age.value, afri_wt.value, afri_ht.value, True))
        else:
            afri_div.text = "Afri score: " + str(afriMale(age.value, afri_wt.value, afri_ht.value, False))
    else:
        if (afri_isPVD.active == [0, 2]):
            afri_div.text = "Afri score: " + str(afriFem(age.value, afri_wt.value, afri_ht.value, True))
        else:
            afri_div.text = "Afri score: " + str(afriFem(age.value, afri_wt.value, afri_ht.value, False))

afri_wt = Slider(start=0, end=100, value=1, step=1, title="Weight (kg)")
afri_ht = Slider(start=0, end=250, value=1, step=1, title="Height (cm)")
afri_isPVD = CheckboxButtonGroup(labels=["Peripheral Vascular Disease?"], active=[2])
afri_sex = RadioButtonGroup(labels=["Male","Female"], active=0)
afri_wt.on_change('value',afriUpd)
afri_ht.on_change('value',afriUpd)
afri_isPVD.on_change('active',afriUpd)
afri_sex.on_change('active',afriUpd)

def updButton(button):
    if (button.active == [0,2]):
        return True
    else:
        return False

def chadUpd(attr, old, new):
    chad_div.text = "Chad score: " + str(chad(updButton(chad_chf),
                                          updButton(chad_htn),
                                          age.value,
                                          updButton(chad_dm),
                                          updButton(chad_stroke),
                                          updButton(chad_vd),
                                          updButton(chad_sex)))

chad_chf = CheckboxButtonGroup(labels=["Congestive Heart Failure?"], active=[2])
chad_htn = CheckboxButtonGroup(labels=["Hypertension?"], active=[2])
chad_dm = CheckboxButtonGroup(labels=["Diabetes Mellitus?"], active=[2])
chad_stroke = CheckboxButtonGroup(labels=["Stroke/TIA?"], active=[2])
chad_vd = CheckboxButtonGroup(labels=["Vascular Disease?"], active=[2])
chad_sex = CheckboxButtonGroup(labels=["Female?"], active=[2])
chad_chf.on_change('active',chadUpd)
chad_htn.on_change('active',chadUpd)
chad_dm.on_change('active',chadUpd)
chad_stroke.on_change('active',chadUpd)
chad_vd.on_change('active',chadUpd)
chad_sex.on_change('active',chadUpd)

def poafUpd(attr, old, new):
    poaf_div.text = "Poaf score: " + str(poaf(age.value,
                                          updButton(poaf_copd),
                                          poaf_egfr.value,
                                          updButton(poaf_emrgncy),
                                          updButton(poaf_pibp),
                                          (poaf_lvef.value/100),
                                          updButton(poaf_vs)))

poaf_copd = CheckboxButtonGroup(labels=["Chronic Obstructive Pulmonary Disease?"], active=[2])
poaf_egfr = Slider(start=0, end=120, value=1, step=1, title="Estimated Glomerular Filtration Rate")
poaf_emrgncy = CheckboxButtonGroup(labels=["Emergency?"], active=[2])
poaf_pibp = CheckboxButtonGroup(labels=["Preoperative Intra-aortic Balloon Pump?"], active=[2])
poaf_lvef = Slider(start=0, end=100, value=1, step=1, title="Left Ventricular Ejection Fraction (x/100)")
poaf_vs = CheckboxButtonGroup(labels=["Valve Surgery?"], active=[2])
poaf_copd.on_change('active', poafUpd)
poaf_egfr.on_change('value', poafUpd)
poaf_emrgncy.on_change('active', poafUpd)
poaf_pibp.on_change('active', poafUpd)
poaf_lvef.on_change('value', poafUpd)
poaf_vs.on_change('active', poafUpd)

def npoafUpd(attr, old, new):
    npoaf_div.text = "Npoaf score: " + str(npoaf(age.value,
                                            npoaf_mvd.value,
                                            updButton(npoaf_lad)))

mvd_menu = [("None","None"),("Mild","Mild"),("Moderate","Moderate"),("Severe","Severe")]
npoaf_mvd = Select(title="Mitrial Valve Disease Description:", value="None", options=["None", "Mild", "Moderate", "Severe"])
npoaf_lad = CheckboxButtonGroup(labels=["Left Atrial Dilatation?"], active=[2])
npoaf_mvd.on_change('value', npoafUpd)
npoaf_lad.on_change('active', npoafUpd)

age.on_change('value',afriUpd,chadUpd,poafUpd,npoafUpd)

afri_widgets = column(afri_wt,afri_ht,afri_isPVD,afri_sex)
chad_widgets = column(chad_chf,chad_htn,chad_dm,chad_stroke,chad_vd,chad_sex)
poaf_widgets = column(poaf_copd,poaf_egfr,poaf_emrgncy,poaf_pibp,poaf_lvef,poaf_vs)
npoaf_widgets = column(npoaf_mvd,npoaf_lad)

curdoc().add_root(layout(children=[
    [column(age)],
    [Spacer(height=100)],
    [column(care_opt), care_div],
    [Spacer(height=100)],
    [afri_widgets, afri_div],
    [Spacer(height=100)],
    [chad_widgets, chad_div],
    [Spacer(height=100)],
    [poaf_widgets, poaf_div],
    [Spacer(height=100)],
    [npoaf_widgets, npoaf_div]
], sizing_mode="fixed"))


import argparse
import logging
import os
import sys
from time import sleep

from mpi4py import MPI

sys.path.insert(0, os.path.abspath(os.path.join(os.getcwd(), "./../../../../")))
sys.path.insert(0, os.path.abspath(os.path.join(os.getcwd(), "./../../../../../")))

from fedml_core.distributed.test.test_rpc.dummy_algorithm.client_manager import RPCClientManager
from fedml_core.distributed.test.test_rpc.dummy_algorithm.server_manager import RPCServerManager

def add_args(parser):
    parser.add_argument("--rank", type=int, default=0)

    parser.add_argument("--backend", type=str, default="GRPC")

    parser.add_argument(
        "--enable_cuda_rpc",
        default=False,
        action="store_true",
        help="Enable cuda rpc (only for TRPC backend)",
    )

    parser.add_argument(
        "--gpu_mapping_file",
        type=str,
        default="gpu_mapping.yaml",
        help="the gpu utilization file for servers and clients. If there is no \
                        gpu_util_file, gpu will not be used.",
    )

    parser.add_argument(
        "--gpu_mapping_key", type=str, default="mapping_default", help="the key in gpu utilization file"
    )

    parser.add_argument(
        "--grpc_ipconfig_path",
        type=str,
        default="grpc_ipconfig.csv",
        help="config table containing ipv4 address of grpc server",
    )

    parser.add_argument(
        "--trpc_master_config_path",
        type=str,
        default="trpc_master_config.csv",
        help="config indicating ip address and port of the master (rank 0) node",
    )

    args = parser.parse_args()
    return args

def run_worker(args, rank, size):
    if rank == 0:
        server_manager = RPCServerManager(args, rank=rank, size=size, backend=args.backend)
        sleep(1)
        server_manager.send_model_params()
        server_manager.run()
    else:

        client_manager = RPCClientManager(args, rank=rank, size=size, backend=args.backend)
        client_manager.run()

if __name__ == "__main__":
    # parse python script input parameters
    parser = argparse.ArgumentParser()
    args = add_args(parser)

    rank = args.rank
    world_size = 2

    # customize the log format
    # logging.basicConfig(level=logging.INFO,
    logging.basicConfig(
        level=logging.DEBUG,
        format="rank - "
        + str(rank)
        + " - %(asctime)s.%(msecs)03d %(filename)s[line:%(lineno)d] %(levelname)s %(message)s",
        datefmt="%Y-%m-%d,%H:%M:%S",
    )

    logging.info(args)

    run_worker(args, rank, world_size)