import time

import torch

from src.utils import AttrDispatcher

fuzz_dispatcher = AttrDispatcher('fuzzer_runner')
input_indicator = False

@fuzz_dispatcher.register('tensorfuzz')
def tensorfuzz_method(_, model):

    def _hook_fn(module, finput, foutput):
        if foutput.isnan().any() or foutput.isinf().any():
            global input_indicator
            input_indicator = True

    for m in model.modules():
        m.register_forward_hook(_hook_fn)

    return model

def fuzz_model(ctx, model):
    model = fuzz_dispatcher(ctx.opt, model)

    fuzz_result = []

    elapsed_mins = 0
    start_time = time.time()
    while True:
        elapsed = (time.time() - start_time) // 60
        if elapsed > elapsed_mins:
            print('elapsed {} mins...'.format(elapsed))
            elapsed_mins = elapsed
        if elapsed > ctx.opt.timeout:
            break

        global input_indicator
        input_indicator = False
        model_input = torch.rand((1, 3, 32, 32)).to(ctx.device)
        model(model_input)
        if input_indicator is True:
            fuzz_result.append(model_input[0].cpu().numpy())

    return fuzz_result


import os

import numpy as np

from cosmopipe.lib import setup_logging
from cosmopipe.lib.data_vector import ProjectionName
from cosmopipe.lib.survey_selection import WindowFunction

def save_synthetic_window_function(window_fn):

    swin = np.linspace(1e-4,1e3,1000)
    srange = (swin[0],swin[-1])
    bwin = np.exp(-(swin/100.)**2)
    y,projs = [],[]
    for n in range(2):
        for ell in range(9):
            y_ = bwin.copy()
            if ell > 0: y_ *= np.random.uniform()/10.
            y.append(y_)
            projs.append(ProjectionName(space=ProjectionName.CORRELATION,mode=ProjectionName.MULTIPOLE,proj=ell,wa_order=n))
    window = WindowFunction(x=[swin]*len(y),y=y,proj=projs)
    window.save_auto(window_fn)

def save_power_window_function(data_fn, randoms_fn, window_fn):

    from scipy import special
    from cosmopipe.estimators.utils import prepare_survey_catalogs
    from cosmopipe.lib.catalog import Catalog
    from cosmopipe.lib import mpi

    data = Catalog.load_fits(data_fn,mpistate='scattered')
    randoms = Catalog.load_fits(randoms_fn,mpistate='scattered')
    data, randoms = prepare_survey_catalogs(data,randoms,cosmo=None,position='Position',nbar='NZ')
    data['weight'] = data['weight_fkp']*data['weight_comp']
    randoms['weight'] = randoms['weight_fkp']*randoms['weight_comp']
    alpha = data.sum('weight')/randoms.sum('weight')
    # this is the normalization factor A used in the power spectrum estimation, either computed from data or randoms
    norm = alpha * mpi.sum_array(randoms['weight']*randoms['nbar']*randoms['weight_fkp'],mpicomm=randoms.mpicomm)
    #norm = mpi.sum_array(data['weight']*data['nbar']*data['weight_fkp'],mpicomm=randoms.mpicomm)
    #exit()

    from nbodykit.lab import FKPCatalog, ConvolvedFFTPower
    # There is some dependence in both the mesh resolution and box size
    # Higher mesh resolution increases window function (more power on small scales)
    # Larger box size yields better convergence on large scales
    # There must be a correct choice, I should look again at Pat's notes
    BoxSize = 40000.
    Nmesh = 256
    ells = (0,)
    # We can try downsampling or rescaling random weights, result is the same
    #randoms = randoms.gslice(0,-1,10)
    #randoms['weight_comp'] *= 10
    randoms['weight'] = randoms['weight_fkp']*randoms['weight_comp']
    # The 3 next lines simply compute the power spectrum of the random catalog
    # The only difference w.r.t. the power spectrum estimation of data - randoms, is that the normalization A is 1.
    fkp = FKPCatalog(randoms.to_nbodykit(),None,nbar='nbar')
    mesh = fkp.to_mesh(position='position',fkp_weight='weight_fkp',comp_weight='weight_comp',nbar='nbar',BoxSize=BoxSize,Nmesh=Nmesh,resampler='tsc',interlaced=True,compensated=True)
    power = ConvolvedFFTPower(mesh,poles=ells,kmin=0.,dk=None)
    kfun = 2.*np.pi/mesh.attrs['BoxSize']
    poles = power.poles
    mask = poles['k'] > 0.
    k = poles['k'][mask]
    #volume = np.prod(kfun)*poles['modes'][mask]
    edges = poles.edges['k']
    volume = 4./3.*np.pi*(edges[1:]**3 - edges[:-1]**3)[mask]

    normwin = randoms.sum('weight')**2/data.sum('weight')**2*norm # this is 1 / alpha^2 * A
    shotnoise = mpi.sum_array(randoms['weight']**2,mpicomm=randoms.mpicomm)/normwin

    def Wk(ell):
        if ell == 0: return poles['power_{:d}'.format(ell)].real[mask]/normwin - shotnoise
        return poles['power_{:d}'.format(ell)].real[mask]/normwin

    swin = np.linspace(0,6e3,1000)
    kk,ss = np.meshgrid(k,swin,sparse=False,indexing='ij')
    ks = kk*ss

    y,projs = [],[]
    # let us compute the window function in configuration space
    for ell in ells:
        integrand = Wk(ell)[:,None]*1./(2.*np.pi)**3 * special.spherical_jn(ell,ks)
        prefactor = (1j) ** ell # this is definition of the Hankel transform
        if ell % 2 == 1: prefactor *= -1j # we provide the imaginary part of odd power spectra, so let's multiply by (-i)^ell
        prefactor = np.real(prefactor)
        y.append(prefactor * np.sum(volume[:,None]*integrand,axis=0)) # this is the multipole ell in configuration space
        projs.append(ProjectionName(space=ProjectionName.CORRELATION,mode=ProjectionName.MULTIPOLE,proj=ell,wa_order=0))
    window = WindowFunction(x=[swin]*len(y),y=y,proj=projs,attrs={'norm':norm})
    #window.save_auto(window_fn)

    from matplotlib import pyplot as plt
    for proj in window.get_projs():
        plt.plot(window.get_x(proj=proj),window.get_y(proj=proj),label=proj.get_projlabel())
    plt.axhline(1.,0.,1.,linestyle='--',color='k')
    plt.xscale('log')
    plt.legend()
    plt.show()

if __name__ == '__main__':

    setup_logging()
    base_dir = '_catalog'
    data_fn = os.path.join(base_dir,'lognormal_data.fits')
    randoms_fn = os.path.join(base_dir,'lognormal_randoms.fits')
    window_fn = os.path.join(base_dir,'window_function.txt')
    #save_synthetic_window_function(window_fn)
    save_power_window_function(data_fn,randoms_fn,window_fn)


import pokemon_list

pokemonList = pokemon_list.pokemon_make_list()
# word_frequency = pokemon_list.frequency('')
pokemonUse = [[0 for _ in range(2)] for _ in range(len(pokemonList))]
for i in range(len(pokemonList)):
  pokemonUse[i][0] = pokemonList[i]

print('Input Maximum Number of Answers.')
t = int(input())

countInput = 0
candidate = pokemon_list.pokemon_make_list()

countAns = 0

candidate = pokemon_list.pokemon_make_list()
word_frequency = pokemon_list.frequency('')

# print(*pokemonList)
# print(*word_frequency)

n = 0
# candidate = pokemonList
success = True
while t > n:
# while True:
  n += 1

  if success:
    candidate = []
    for i in range(len(pokemonList)):
      if pokemonUse[i][1] == 0:
        candidate.append(pokemonList[i])
    fre, fre_i = pokemon_list.frequency(candidate)
    score = [[0 for i in range(2)] for j in range(len(candidate))]
    i = 0
    # total = 0
    for pokemon in candidate:
      c = 0
      for j in range(len(pokemon)):
        if (pokemon[j] not in pokemon[:j]) and 0 <= ord(pokemon[j]) - ord('ァ') <= 91:
          c += fre[ord(pokemon[j]) - ord('ァ')] * fre_i[ord(pokemon[j]) - ord('ァ')][j]
      score[i][0] = c
      score[i][1] = pokemon
      i += 1
    score.sort(reverse=True)
    # print(*newCandidate)
    # print(newCandidate[0])
    # word = newCandidate[0]
    print('Remaining candidates : ' + str(len(candidate)))

    print(score[0][1])
    word = score[0][1]
    num = pokemonList.index(score[0][1])
    pokemonUse[num][1] = 1
  success = False

  print('Enter ' + str(n)+' Result')
  print('Gray > 0, Yellow > 1, Green > 2 with no spaces! ex. > 01212')
  result = list(input())
  if len(word) != len(result):
    print('You entered the wrong result!')
    exit()

  for i in range(len(word)):
    result[i] = int(result[i])

  nResult = 0
  for i in range(len(word)):
    if result[i] == 0:
      pass
    elif result[i] == 2:
      nResult += 1
  if nResult == 5:
    success = True
    countAns += 1
  newCandidate = []
  for i in range(len(candidate)):
    c = True
    for j in range(len(word)):
      if word[j] in word[:j]:
        pass
      elif result[j] == 0:
        if word[j] in candidate[i]:
          c = False
          break
      elif result[j] == 1: # yellow
        if not (word[j] in candidate[i] and word[j] != candidate[i][j]):
          c = False
          break
      else:
        if word[j] != candidate[i][j]:
          c = False
          break
    if c:
        newCandidate.append(candidate[i])
  # print(*newCandidate)
  if success:
    pass
  elif len(newCandidate) == 1:
    print('Answer is '+ newCandidate[0])
    success = True
    countAns += 1
    n += 1
  else:
    fre, fre_i = pokemon_list.frequency(newCandidate)
    score = [[0 for i in range(2)] for j in range(len(newCandidate))]
    i = 0
    # total = 0
    for pokemon in newCandidate:
      c = 0
      for j in range(len(pokemon)):
        if (pokemon[j] not in pokemon[:j]) and 0 <= ord(pokemon[j]) - ord('ァ') <= 91:
          c += fre[ord(pokemon[j]) - ord('ァ')] * fre_i[ord(pokemon[j]) - ord('ァ')][j]
      score[i][0] = c
      score[i][1] = pokemon
      i += 1
    score.sort(reverse=True)
    # print(*newCandidate)
    # print(newCandidate[0])
    # word = newCandidate[0]
    print('Remaining candidates : ' + str(len(newCandidate)))

    print(score[0][1])
    word = score[0][1]
    num = pokemonList.index(score[0][1])
    pokemonUse[num][1] = 1
  candidate = []
  for i in range(1,len(newCandidate)):
    candidate.append(score[i][1])
print(countAns)


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

import collections
import unittest

from insanity import sanity_checks as san

__author__ = "Patrick Hohenecker"
__copyright__ = (
        "Copyright (c) 2017 Patrick Hohenecker\n"
        "\n"
        "Permission is hereby granted, free of charge, to any person obtaining a copy\n"
        "of this software and associated documentation files (the \"Software\"), to deal\n"
        "in the Software without restriction, including without limitation the rights\n"
        "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n"
        "copies of the Software, and to permit persons to whom the Software is\n"
        "furnished to do so, subject to the following conditions:\n"
        "\n"
        "The above copyright notice and this permission notice shall be included in all\n"
        "copies or substantial portions of the Software.\n"
        "\n"
        "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
        "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
        "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
        "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
        "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
        "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
        "SOFTWARE."
)
__license__ = "MIT License"
__version__ = "2017.1"
__date__ = "Aug 13, 2017"
__maintainer__ = "Patrick Hohenecker"
__email__ = "mail@paho.at"
__status__ = "Development"

class SanityChecksTest(unittest.TestCase):
    """This class implements the tests for the module ``insanity.sanity_checks``."""

    @staticmethod
    def eq_mod_2(x: int, y: int) -> bool:
        """Computes whether two integers are equal modulo 2."""
        return (x - y) % 2 == 0

    @staticmethod
    def eq_mod_2_check(x, y):
        if not SanityChecksTest.eq_mod_2(x, y):
            raise ValueError("{} != {} mod 2".format(x, y))

    # noinspection PyTypeChecker
    def test_fully_qualified_name(self):
        # CHECK: providing an arg that is not a type causes a TypeError
        with self.assertRaises(TypeError):
            san._fully_qualified_name("not-a-type")

        # CHECK: legal invocations return fully qualified type names
        self.assertEqual(san._fully_qualified_name(str), "builtins.str")
        self.assertEqual(san._fully_qualified_name(type), "builtins.type")
        self.assertEqual(san._fully_qualified_name(collections.Iterable), "collections.abc.Iterable")

    # noinspection PyTypeChecker
    def test_sanitize_iterable(self):
        # CHECK: invoking the function with an arg of an illegal type causes a TypeError
        with self.assertRaises(TypeError):
            san.sanitize_iterable(0, ["some_value"], elements_type=str)
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", 0, elements_type=str)
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], elements_type=0)
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], target_length="0")
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], min_length="0")
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], max_length="0")
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], elements_type=str, none_elements_allowed=0)
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], error_msg=0)

        # CHECK: invoking the function with incompatible args causes a ValueError/TypeError
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", [0, 1, 2])
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], target_length=3, min_length=2, max_length=4)
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], min_length=5, max_length=4)

        # CHECK: providing a list with elements of illegal type causes a TypeError
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], elements_type=int)
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value"], elements_type=[int, float])
        with self.assertRaises(TypeError):
            san.sanitize_iterable("some_arg", ["some_value", None], elements_type=int, none_elements_allowed=False)

        # CHECK: providing a list of illegal length causes a ValueError
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], target_length=2)
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], target_length=4)
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], min_length=4)
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], max_length=2)

        # CHECK: providing a list that is illegal w.r.t. to a custom sanity check causes a ValueError
        with self.assertRaises(ValueError):
            san.sanitize_iterable("some_arg", [0, 1, 2], element_check_fn=(lambda x: self.eq_mod_2_check(x, 0)))

        # CHECK: providing a list with legal elements causes no error
        san.sanitize_iterable("some_arg", [0, 1, 2], elements_type=int, max_length=3)
        san.sanitize_iterable("some_arg", [0, None, 2], elements_type=int, max_length=3, none_elements_allowed=True)
        san.sanitize_iterable("some_arg", [0, 1, "2"], elements_type=[int, str], min_length=2, max_length=4)
        san.sanitize_iterable("some_arg", None, elements_type=int, none_allowed=True)
        san.sanitize_iterable("some_arg", [0, 2, 4], element_check_fn=(lambda x: self.eq_mod_2_check(x, 0)))

    # noinspection PyTypeChecker
    def test_sanitize_range(self):
        # CHECK: invoking the function with an illegal type causes a TypeError
        with self.assertRaises(TypeError):
            san.sanitize_range(0, 1, minimum=0)
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", "0", minimum=0)
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1, minimum="0")
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1, maximum="0")
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1, minimum=0, error_msg=0)
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1, minimum=0, min_inclusive=0)
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1, minimum=0, max_inclusive=0)
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1, minimum=0, complement=0)

        # CHECK: leaving both minimum and maximum unspecified causes a TypeError
        with self.assertRaises(TypeError):
            san.sanitize_range("some_arg", 1)

        # CHECK: providing a minimum > maximum causes a ValueError
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 1, minimum=2, maximum=1)

        # CHECK: providing an out-of-range value causes a ValueError
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", -1, minimum=0, maximum=2, min_inclusive=True, complement=False)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 0, minimum=0, maximum=2, min_inclusive=False, complement=False)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 3, minimum=0, maximum=2, max_inclusive=True, complement=False)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 2, minimum=0, maximum=2, max_inclusive=False, complement=False)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 0, minimum=0, maximum=2, min_inclusive=True, complement=True)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 1, minimum=0, maximum=2, min_inclusive=True, complement=True)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 2, minimum=0, maximum=2, max_inclusive=True, complement=True)
        with self.assertRaises(ValueError):
            san.sanitize_range("some_arg", 1, minimum=0, maximum=2, max_inclusive=False, complement=True)

        # CHECK: providing an in-range value causes no error
        san.sanitize_range("some_arg", 0, minimum=0, maximum=2, min_inclusive=True)
        san.sanitize_range("some_arg", 1, minimum=0, maximum=2, min_inclusive=False)
        san.sanitize_range("some_arg", 2, minimum=0, maximum=2, max_inclusive=True)
        san.sanitize_range("some_arg", 1, minimum=0, maximum=2, max_inclusive=False)

    # noinspection PyTypeChecker
    def test_sanitize_type(self):
        # CHECK: invoking the function with an arg of an illegal type causes a TypeError
        with self.assertRaises(TypeError):
            san.sanitize_type(0, "some_value", str)
        with self.assertRaises(TypeError):
            san.sanitize_type("some_arg", "some_value", 0)
        with self.assertRaises(TypeError):
            san.sanitize_type("some_arg", "some_value", str, error_msg=0)
        with self.assertRaises(TypeError):
            san.sanitize_type("some_arg", "some_value", str, none_allowed=0)

        # CHECK: perform sanity check for an illegal arg_value
        with self.assertRaises(TypeError):
            san.sanitize_type("some_arg", "some_value", int)
        with self.assertRaises(TypeError):
            san.sanitize_type("some_arg", "some_value", [int, float])
        with self.assertRaises(TypeError):
            san.sanitize_type("some_arg", None, int, none_allowed=False)

        # CHECK: perform sanity check for an admissible arg_value
        san.sanitize_type("some_arg", "some_value", str)
        san.sanitize_type("some_arg", "some_value", [int, str])
        san.sanitize_type("some_arg", None, str, none_allowed=True)

    # noinspection PyTypeChecker
    def test_sanitize_value(self):
        # CHECK: invoking the function with an arg of an illegal type causes a TypeError
        with self.assertRaises(TypeError):
            san.sanitize_value(0, "some_value", "some_target_value")
        with self.assertRaises(TypeError):
            san.sanitize_value("some_arg", "some_value", "some_target_value", complement=0)
        with self.assertRaises(TypeError):
            san.sanitize_value("some_arg", "some_value", "some_target_value", expand_target=0)
        with self.assertRaises(TypeError):
            san.sanitize_value("some_arg", "some_value", "some_target_value", error_msg=0)

        # CHECK: sanity check for an illegal arg_value causes a ValueError
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", 0, 1)
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", 0, 0, complement=True)
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", 0, [1, 2])
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", 0, [0, 1], complement=True)
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", 0, [0, 1], expand_target=False)
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", [0, 1], [0, 1])
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", None, [0, 1], none_allowed=False)

        # CHECK: sanity check with an alternative equality function works as expected
        san.sanitize_value("some_arg", 3, 1, equality_fn=self.eq_mod_2)
        with self.assertRaises(ValueError):
            san.sanitize_value("some_arg", 3, 0, equality_fn=self.eq_mod_2)

        # CHECK: sanity check for an admissible arg_value causes no errors
        san.sanitize_value("some_arg", 0, 0)
        san.sanitize_value("some_arg", 0, [0, 1])
        san.sanitize_value("some_arg", 0, 1, complement=True)
        san.sanitize_value("some_arg", 0, [1, 2], complement=True)
        san.sanitize_value("some_arg", [0, 1], [0, 1], expand_target=False)
        san.sanitize_value("some_arg", None, [0, 1], none_allowed=True)

if __name__ == "__main__":
    unittest.main()


import math
import random

import numpy as np
import matplotlib.pyplot as plt;
import networkx as nx
from matplotlib.animation import FuncAnimation
import matplotlib.colors as mcolors

# Define the distance function
def dist(u, v):
    if u is None:
        u = [0,0]
    if v is None:
        v = [0,0]

    return math.sqrt((u[0]-v[0])**2 + (u[1]-v[1])**2)

# Define the k-robot assignment algorithm
def k_robot_assignment(W, L):
    n = len(W)
    k = len(W[0])
    T = [[] for i in range(k)]
    T_dep = [None for i in range(k)]
    x_dep = [None for i in range(k)]
    for i in range(n):
        w = W[i]
        min_cost = float('inf')
        min_j = None
        for j in range(k):
            cost = dist(w, x_dep[j]) + L
            if cost < min_cost:
                min_cost = cost
                min_j = j
        T[min_j].append(W[i][0])

        if T_dep[min_j] is None or w[1] > W[T_dep[min_j]][1]:
            T_dep[min_j] = len(T[min_j])-1
            x_dep[min_j] = w
    for j in range(k):
        if T_dep[j] is None:
            return False
        T_dep[j] = T[j][T_dep[j]]
    return T, T_dep, x_dep

# Define the single-robot schedule algorithm
def single_robot_schedule(T_weights, T_subtree,T_root):
    #n = len(T_weights)
    n = len(T_subtree)
    L = 0
    print("T_weights", T_weights)
    print("T_subtree", T_subtree)
    print("T_root", T_root)
    index_of_t_root = T_subtree.index(T_root)
    #print("indexof T_root", index_of_t_root)
    for i in range(n)[index_of_t_root:]:
        w = T_weights[i][1]
        #print("w in single_robot_schedule", w)
        #L = max(L, dist(T[i][T_dep[i]], T[i][0]) + w)
        #w = T[i][0][1]
        node1 = T_weights[i]
        node2 = T_weights[(i+1) % n]
        #print("node1", node1)
        #print("node2", node2)
        #ITT kéne, hogyha a node1 node2 + w mint L akkor kirajzolni?
        L = max(L, dist(node1, node2) + w)

    return L

def attach_feature_to_node(graph, node, feature, value):
    graph.nodes[node][feature] = value

def attach_feature_to_nodes(graph, feature, values):
    nodes = graph.nodes
    for index, node in enumerate(nodes):
        attach_feature_to_node(graph, node, feature, values[index])

def attach_status_to_nodes(graph):
    nodes = graph.nodes
    values = [False] * len(nodes)
    attach_feature_to_nodes(graph, 'is_occupied', values)

#Define graph animation function
def draw_graph(graph, pos,draw, subtrees,labels ):
    if draw:
        nodes = list(graph.nodes())
        #print("nodes", nodes)
        node_colors = []
        for i,node in enumerate(nodes):
            if graph.nodes[i]["is_occupied"]:
                node_colors.append("lawngreen")
            elif node in subtrees[0]: #ehelyett bejárni
                node_colors.append("orange")
            elif node in subtrees[1]:
                node_colors.append("lightcoral")
            else:
                node_colors.append("skyblue")

        nx.draw(graph, pos, node_size=1500, cmap=mcolors.BASE_COLORS, node_color=node_colors,with_labels=True, labels=labels)

    plt.show()

def move(graph, subtree):
    H = graph.subgraph(subtree)
    occupied_node = [node[0] for node in H.nodes.data() if node[1]['is_occupied']]
    # print("occupied_node", occupied_node)
    occupied_node_index = subtree.index(occupied_node[0])

    if occupied_node_index == len(subtree)-1:
        next = subtree[0]
    else:
        next = subtree[occupied_node_index+1]

    graph.nodes[occupied_node[0]]['is_occupied'] = False
    graph.nodes[next]['is_occupied'] = True

    # print("occupied_node", occupied_node)
    # print("next", next)
    # print([node for node in graph.nodes.data()])

# Define the main function
def main(original_weights):
    # Define the weights of the nodes (node, weight)

    # Define the number of robots
    k = 2
    # Compute the smallest and largest weights
    w_min = min(original_weights, key=lambda x: x[1])[1]
    w_max = max(original_weights, key=lambda x: x[1])[1]
    # Compute the value of m
    m = math.log2(w_max/w_min)
    # Round the weights to the nearest dyadic value
    #weights = [(original_weight[0], 2**math.ceil(math.log2(original_weight[1]))) for original_weight in original_weights]
    weights = original_weights
    #create the graph
    graph = nx.complete_graph(len(weights))

    for i in range(len(weights)):
        graph.add_nodes_from(weights[i])

    labels ={}
    for i in range(len(weights)):
        #set the node key as the label key and the label (which is the coord (id+weight)) as its value
        labels[weights[i][0]] = weights[i]

    #pos
    pos = {weight[0]:weight for i,weight in enumerate((weights))}
    print("pos", pos)

    nx.draw(graph, node_size=1500, node_color="skyblue",with_labels=True, pos=pos, labels=labels)
    plt.axis("on")
    plt.savefig("output/original_graph" +  ".png",
                bbox_inches='tight', dpi = 250)
    # plt.show()
    # Run the k-robot assignment algorithm
    L = 6 # Guess an upper bound for the optimal maximum weighted latency
    T = None
    while T is None:
        T = k_robot_assignment(weights, L)
        if T is None:
            L *= 2
    # Compute the maximum weighted latency of the schedule
    max_latency = 0
    print ("T", T)
    for j in range(k):
        j_subtree = T[0][j]
        #print("j_subtree", j_subtree)
        #print("weights", weights)
        T_j_weights = []
        for i in j_subtree:
            for w in weights:
                if i == w[0]:
                    T_j_weights.append(w)

        #print("T_j", T_j_weights)
        T_j_root = T[1][j]
        #print("T_j_root", T_j_root)
        T0_index = None
        for l in range(len(T[0])):
            #print('iteration',l)
            if T[1][j] in T[0][l]:
                T0_index = l
        T_j_subtree = T[0][T0_index]
        #print("T_j_root 2", T_j_subtree)

        max_latency = max(max_latency, single_robot_schedule(T_j_weights, T_j_subtree,T_j_root))
    # Print the results
    print('***RESULTS***')
    print('Original weights:', original_weights)
    print('Dyadic weights:', weights)
    print('Subtrees represented by node ids:', T[0])
    print('Node ids and weights:', weights)
    print('Number of robots:', k)
    print('Minimized Maximum weighted latency:', max_latency)
    print('***END***')

    # Draw the graph
    attach_status_to_nodes(graph)

    graph.nodes[T[1][0]]['is_occupied'] = True
    graph.nodes[T[1][1]]['is_occupied'] = True
    plt.ion()
    for i in range(50):
        draw_graph(graph, pos, True, T[0], labels)
        plt.pause(0.75)
        if i > 20: #move the robots after 20 iterations
            for subtree in T[0]:
                move(graph, subtree)

        # plt.savefig("output/subtrees" +  ".png",
        #     bbox_inches='tight', dpi = 250)
        plt.clf()

    plt.ioff()

#original_weights = [(0, 9), (1, 1), (2, 3), (3, 5), (4, 5), (5, 6), (6, 7), (7, 7), (8, 5), (9, 9)]
#original_weights = [(3, 2), (4, 3), (5, 2),(6, 1), (0, 1), (1, 1), (2, 1), (7, 3),(8, 2)]
original_weights = [(3, 2), (4, 3), (5, 2), (0, 5), (1, 1),(6, 1), (2, 1), (7, 3),(8, 2)]
#original_weights = [(1, 3), (2, 2), (3, 1), (4, 2), (0, 3)]

# original_weights = [(1, 1), (2, 2), (4, 2), (0, 3),(3, 1)]
# original_weights = [(1, 3), (2, 2), (3, 1), (4, 2), (0, 1)]
# original_weights = []
# for i in range(10):
#     original_weights.append((i, random.randint(1,10)))
# print("original_weights", original_weights)
if __name__ == '__main__':
    main(original_weights)


from datetime import date, datetime, timedelta, timezone
from decimal import ROUND_HALF_UP, Decimal

import pandas as pd
import psycopg2
from dateutil.relativedelta import relativedelta

from ..config import Config
from ..errors import ServiceError
from ..models.patient import AsahikawaPatientFactory, HokkaidoPatientFactory
from ..services.database import ConnectionPool
from ..services.service import Service

class AsahikawaPatientService(Service):
    """旭川市の公表する新型コロナウイルス感染症患者データを扱うサービス"""

    def __init__(self, pool: ConnectionPool):
        """
        Args:
            table_name (str): テーブル名
            pool (:obj:`ConnectionPool`): SimpleConnectionPoolを要素に持つオブジェクト

        """
        Service.__init__(self, "asahikawa_patients", pool)

    def create(self, patients: AsahikawaPatientFactory) -> None:
        """データベースへ新型コロナウイルス感染症患者データを一括登録する

        Args:
            patients (:obj:`AsahikawaPatientFactory`): 患者データリスト
                患者データのオブジェクトのリストを要素に持つオブジェクト

        """
        items = (
            "patient_number",
            "city_code",
            "prefecture",
            "city_name",
            "publication_date",
            "onset_date",
            "residence",
            "age",
            "sex",
            "occupation",
            "status",
            "symptom",
            "overseas_travel_history",
            "be_discharged",
            "note",
            "hokkaido_patient_number",
            "surrounding_status",
            "close_contact",
            "updated_at",
        )
        # バルクインサートするデータのリストを作成
        data_lists = list()
        for patient in patients.items:
            data_lists.append(
                [
                    patient.patient_number,
                    patient.city_code,
                    patient.prefecture,
                    patient.city_name,
                    patient.publication_date,
                    patient.onset_date,
                    patient.residence,
                    patient.age,
                    patient.sex,
                    patient.occupation,
                    patient.status,
                    patient.symptom,
                    patient.overseas_travel_history,
                    patient.be_discharged,
                    patient.note,
                    patient.hokkaido_patient_number,
                    patient.surrounding_status,
                    patient.close_contact,
                    datetime.now(timezone(timedelta(hours=+9))),
                ]
            )

        # データベースへ登録処理
        self.upsert(
            items=items,
            primary_key="patient_number",
            data_lists=data_lists,
        )

    def delete(self, patient_number: int) -> bool:
        """指定した識別番号の陽性患者データを削除する

        Args:
            patient_number (int): 削除する陽性患者データの識別番号

        Returns:
            bool: データ削除に成功したら真を返す

        """
        state = "DELETE from asahikawa_patients WHERE patient_number = %s;"
        values = (patient_number,)
        result = False
        try:
            with self.get_connection() as cur:
                cur.execute(state, values)
                if cur.statusmessage == "DELETE 1":
                    result = True

            self.info_log("市内番号" + str(patient_number) + "を削除しました。")
        except (
            psycopg2.DataError,
            psycopg2.IntegrityError,
            psycopg2.InternalError,
        ) as e:
            self.error_log(e.args[0])
            raise ServiceError("陽性患者データを削除できませんでした。")

        return result

    def find_all(self) -> AsahikawaPatientFactory:
        """新型コロナウイルス感染症患者の全件を返す

        Returns:
            res (:obj:`AsahikawaPatientFactory`): 患者データリストデータ
                新型コロナウイルス感染症患者オブジェクトの全件リストを要素に持つ
                オブジェクト

        """
        state = (
            "SELECT"
            + " "
            + "a.patient_number,a.city_code,a.prefecture,a.city_name,"
            + "a.publication_date,"
            + "h.onset_date,a.residence,a.age,a.sex,h.occupation as h_occupation,"
            + "a.occupation as a_occupation,h.status,h.symptom,"
            + "h.overseas_travel_history,h.be_discharged,a.note,"
            + "a.hokkaido_patient_number,a.surrounding_status,a.close_contact"
            + " "
            + "FROM"
            + " "
            + self.table_name
            + " "
            + "AS a"
            + " "
            + "LEFT JOIN hokkaido_patients AS h"
            + " "
            + "ON a.hokkaido_patient_number = h.patient_number"
            + " "
            + "ORDER BY a.patient_number ASC;"
        )
        factory = AsahikawaPatientFactory()
        with self.get_connection() as cur:
            cur.execute(state)
            for dict_cursor in cur.fetchall():
                row = dict(dict_cursor)
                # 北海道データがない場合、職業は旭川データの値をセット
                if row["h_occupation"] is None:
                    row["occupation"] = row["a_occupation"]
                else:
                    row["occupation"] = row["h_occupation"]
                del row["h_occupation"], row["a_occupation"]
                factory.create(**row)

        return factory

    def find(self, page: int = 1, desc: bool = True) -> tuple[AsahikawaPatientFactory, int]:
        """新型コロナウイルス感染症患者データのリストをページネーション用に分割して返す

        Args:
            page (int): 検索結果を分割する場合、何番目の分割結果か数値で指定
            desc (bool): 降順にする場合Trueを指定

        Returns:
            res (tuple): ページネーションデータ
                AsahikawaPatientFactoryオブジェクトと
                ページネーションした場合の最大ページ数の数値を要素に持つタプル

        """
        if not isinstance(page, int):
            raise ServiceError("検索結果のページ指定に誤りがあります。")

        pagenation_option = ""
        max_page = 1

        count_state = "SELECT" + " " + "count(patient_number)" + " " + "FROM" + " " + self.table_name + ";"
        with self.get_connection() as cur:
            cur.execute(count_state)
            res = cur.fetchone()

        results_number = res["count"]
        # 検索結果の最大ページ数を取得
        max_view_number = 100
        if results_number < max_view_number:
            max_page = 1
        else:
            if divmod(results_number, max_view_number)[1] == 0:
                max_page = divmod(results_number, max_view_number)[0]
            else:
                max_page = divmod(results_number, max_view_number)[0] + 1

        # 指定されたページ数の検索結果を表示するためにスキップするレコード数を取得
        if max_page < page:
            raise ServiceError("指定したページ数が上限を超えています。")
        else:
            skip_record_number = (page - 1) * max_view_number

        # ページネーション用の追加SQL文字列を生成
        pagenation_option = " LIMIT " + str(max_view_number)
        if 1 < page:
            pagenation_option += " OFFSET " + str(skip_record_number)

        if desc:
            order = "DESC"
        else:
            order = "ASC"

        state = (
            "SELECT"
            + " "
            + "a.patient_number,a.city_code,a.prefecture,a.city_name,"
            + "a.publication_date,"
            + "h.onset_date,a.residence,a.age,a.sex,h.occupation,h.status,h.symptom,"
            + "h.overseas_travel_history,h.be_discharged,a.note,"
            + "a.hokkaido_patient_number,a.surrounding_status,a.close_contact"
            + " "
            + "FROM"
            + " "
            + self.table_name
            + " "
            + "AS a"
            + " "
            + "LEFT JOIN hokkaido_patients AS h"
            + " "
            + "ON a.hokkaido_patient_number = h.patient_number"
            + " "
            + "ORDER BY a.patient_number"
            + " "
            + order
        )
        state += pagenation_option + ";"
        factory = AsahikawaPatientFactory()
        with self.get_connection() as cur:
            cur.execute(state)
            for row in cur.fetchall():
                factory.create(**row)

        return (factory, max_page)

    def get_rows(self) -> list:
        """陽性患者属性データをリストを返す

        Returns:
            rows (list of list): 陽性患者属性データの二次元配列

        """
        patients = self.find_all()
        rows = list()
        for patient in patients.items:
            patient_number = str(patient.patient_number)

            if patient.publication_date is None:
                publication_date = ""
            else:
                publication_date = patient.publication_date.strftime("%Y-%m-%d")

            if patient.onset_date is None:
                onset_date = ""
            else:
                onset_date = patient.onset_date.strftime("%Y-%m-%d")

            if patient.overseas_travel_history is None:
                overseas_travel_history = ""
            else:
                overseas_travel_history = str(int(patient.overseas_travel_history))

            if patient.be_discharged is None:
                be_discharged = ""
            else:
                be_discharged = str(int(patient.be_discharged))

            rows.append(
                [
                    "" if v is None else v
                    for v in [
                        patient_number,
                        patient.city_code,
                        patient.prefecture,
                        patient.city_name,
                        publication_date,
                        onset_date,
                        patient.residence,
                        patient.age,
                        patient.sex,
                        patient.occupation,
                        patient.status,
                        patient.symptom,
                        overseas_travel_history,
                        be_discharged,
                        patient.note,
                    ]
                ]
            )
        return rows

    def get_aggregate_by_days_per_age(self, from_date: date, to_date: date) -> list:
        """指定した期間の1日ごとの年代別陽性患者数の集計結果を返す

        Args:
            from_date (obj:`date`): 集計の始期
            to_date (obj:`date`): 集計の終期

        Returns:
            aggregate_by_days_per_age (list of dict): 集計結果
                1日ごとの日付とその日の年代別新規陽性患者数を要素とする辞書のリスト

        """
        if not isinstance(from_date, date) or not isinstance(to_date, date):
            raise ServiceError("期間の範囲指定が日付になっていません。")

        state = (
            "SELECT date(from_day) AS publication_date, "
            + "COUNT(CASE WHEN age = '10歳未満' THEN TRUE ELSE NULL END) AS age_under_10, "
            + "COUNT(CASE WHEN age = '10代' THEN TRUE ELSE NULL END) AS age_10s, "
            + "COUNT(CASE WHEN age = '20代' THEN TRUE ELSE NULL END) AS age_20s, "
            + "COUNT(CASE WHEN age = '30代' THEN TRUE ELSE NULL END) AS age_30s, "
            + "COUNT(CASE WHEN age = '40代' THEN TRUE ELSE NULL END) AS age_40s, "
            + "COUNT(CASE WHEN age = '50代' THEN TRUE ELSE NULL END) AS age_50s, "
            + "COUNT(CASE WHEN age = '60代' THEN TRUE ELSE NULL END) AS age_60s, "
            + "COUNT(CASE WHEN age = '70代' THEN TRUE ELSE NULL END) AS age_70s, "
            + "COUNT(CASE WHEN age = '80代' THEN TRUE ELSE NULL END) AS age_80s, "
            + "COUNT(CASE WHEN age = '90歳以上' THEN TRUE ELSE NULL END) AS age_over_90, "
            + "COUNT(CASE WHEN age = '' THEN TRUE ELSE NULL END) AS investigating "
            + "FROM "
            + "(SELECT generate_series AS from_day, "
            + "generate_series + '1 day'::interval AS to_day FROM "
            + "generate_series(%s::DATE, %s::DATE, '1 day')) "
            + "AS day_ranges LEFT JOIN asahikawa_patients ON "
            + "from_day <= asahikawa_patients.publication_date AND "
            + "asahikawa_patients.publication_date < to_day GROUP BY from_day "
            + "ORDER BY from_day;"
        )
        aggregate_by_days_per_age = list()
        with self.get_connection() as cur:
            cur.execute(state, (from_date.strftime("%Y-%m-%d"), to_date.strftime("%Y-%m-%d")))
            for row in cur.fetchall():
                aggregate_by_days_per_age.append(dict(row))

        return aggregate_by_days_per_age

    def get_aggregate_by_days(self, from_date: date, to_date: date) -> list:
        """指定した期間の1日ごとの陽性患者数の集計結果を返す

        Args:
            from_date (obj:`date`): 集計の始期
            to_date (obj:`date`): 集計の終期

        Returns:
            aggregate_by_days (list of tuple): 集計結果
                1日ごとの日付とその週の新規陽性患者数を要素とするタプル

        """
        if not isinstance(from_date, date) or not isinstance(to_date, date):
            raise ServiceError("期間の範囲指定が日付になっていません。")

        state = (
            "SELECT date(from_day) AS days, "
            + "COUNT(DISTINCT patient_number) AS patients FROM "
            + "(SELECT generate_series AS from_day, "
            + "generate_series + '1 day'::interval AS to_day FROM "
            + "generate_series(%s::DATE, %s::DATE, '1 day')) "
            + "AS day_ranges LEFT JOIN asahikawa_patients ON "
            + "from_day <= asahikawa_patients.publication_date AND "
            + "asahikawa_patients.publication_date < to_day GROUP BY from_day;"
        )
        aggregate_by_days = list()
        with self.get_connection() as cur:
            cur.execute(state, (from_date.strftime("%Y-%m-%d"), to_date.strftime("%Y-%m-%d")))
            for row in cur.fetchall():
                aggregate_by_days.append((row[0], row[1]))

        return aggregate_by_days

    def get_aggregate_by_weeks(self, from_date: date, to_date: date) -> list:
        """指定した期間の1週間ごとの陽性患者数の集計結果を返す

        Args:
            from_date (obj:`date`): 集計の始期
            to_date (obj:`date`): 集計の終期

        Returns:
            aggregate_by_weeks (list of tuple): 集計結果
                1週間ごとの日付とその週の新規陽性患者数を要素とするタプルのリスト

        """
        if not isinstance(from_date, date) or not isinstance(to_date, date):
            raise ServiceError("期間の範囲指定が日付になっていません。")

        state = (
            "SELECT date(from_week) AS weeks, "
            + "COUNT(DISTINCT patient_number) AS patients FROM "
            + "(SELECT generate_series AS from_week, "
            + "generate_series + '7 days'::interval AS to_week FROM "
            + "generate_series(%s::DATE, %s::DATE, '7 days')) "
            + "AS week_ranges LEFT JOIN asahikawa_patients ON "
            + "from_week <= asahikawa_patients.publication_date AND "
            + "asahikawa_patients.publication_date < to_week GROUP BY from_week;"
        )
        aggregate_by_weeks = list()
        with self.get_connection() as cur:
            cur.execute(state, (from_date.strftime("%Y-%m-%d"), to_date.strftime("%Y-%m-%d")))
            for row in cur.fetchall():
                aggregate_by_weeks.append((row[0], row[1]))

        return aggregate_by_weeks

    def get_aggregate_by_weeks_per_age(self, from_date: date, to_date: date) -> pd.DataFrame:
        """指定した期間の1週間ごとの年代別の陽性患者数の集計結果を返す

        Args:
            from_date (obj:`date`): 集計の始期
            to_date (obj:`date`): 集計の終期

        Returns:
            aggregate_by_weeks (:obj:`pd.DataFrame`): 集計結果
                1週間ごとの日付とその週の年代別新規陽性患者数をpandasのDataFrameで返す

        """
        if not isinstance(from_date, date) or not isinstance(to_date, date):
            raise ServiceError("期間の範囲指定が日付になっていません。")

        state = (
            "SELECT date(from_week) AS weeks, age, "
            + "COUNT(DISTINCT patient_number) AS patients FROM "
            + "(SELECT generate_series AS from_week, "
            + "generate_series + '7 days'::interval AS to_week FROM "
            + "generate_series(%s::DATE, %s::DATE, '7 days')) "
            + "AS week_ranges LEFT JOIN asahikawa_patients ON "
            + "from_week <= asahikawa_patients.publication_date AND "
            + "asahikawa_patients.publication_date < to_week GROUP BY from_week, age "
            + "ORDER BY weeks, age;"
        )
        df = pd.DataFrame(
            columns=[
                "10歳未満",
                "10代",
                "20代",
                "30代",
                "40代",
                "50代",
                "60代",
                "70代",
                "80代",
                "90歳以上",
                "非公表",
            ]
        )
        with self.get_connection() as cur:
            cur.execute(state, (from_date.strftime("%Y-%m-%d"), to_date.strftime("%Y-%m-%d")))
            for row in cur.fetchall():
                if row["age"] is None:
                    df.loc[row["weeks"]] = 0
                elif row["age"] == "":
                    df.at[row["weeks"], "非公表"] = row["patients"]
                else:
                    df.at[row["weeks"], row["age"]] = row["patients"]

        return df.fillna(0)

    def get_seven_days_moving_average(self, from_date: date, to_date: date) -> list:
        """1日あたりの新規陽性患者数の7日間移動平均の計算結果を返す

        Args:
            from_date (obj:`date`): 集計の始期
            to_date (obj:`date`): 集計の終期

        Returns:
            seven_days_moving_average (list of tuple): 集計結果
                1週間ごとの日付とその週の1日あたり平均新規陽性患者数を要素とする
                タプルのリスト
        """
        aggregate_by_weeks = self.get_aggregate_by_weeks(from_date=from_date, to_date=to_date)
        seven_days_moving_average = list()
        for patients_number in aggregate_by_weeks:
            moving_average = float(
                Decimal(str(patients_number[1] / 7)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
            )
            seven_days_moving_average.append((patients_number[0], moving_average))
        return seven_days_moving_average

    def get_per_hundred_thousand_population_per_week(self, from_date: date, to_date: date) -> list:
        """1週間の人口10万人あたりの新規陽性患者数の計算結果を返す

        Args:
            from_date (obj:`date`): 集計の始期
            to_date (obj:`date`): 集計の終期

        Returns:
            per_hundred_thousand (list of tuple): 集計結果
                1週間ごとの日付とその週の人口10万人あたり新規陽性患者数を要素とする
                タプルのリスト
        """
        aggregate_by_weeks = self.get_aggregate_by_weeks(from_date=from_date, to_date=to_date)
        per_hundred_thousand_population_per_week = list()
        for patients_number in aggregate_by_weeks:
            per_hundred_thousand_population = float(
                Decimal(str(patients_number[1] / Config.POPULATION * 100000)).quantize(
                    Decimal("0.01"), rounding=ROUND_HALF_UP
                )
            )
            per_hundred_thousand_population_per_week.append((patients_number[0], per_hundred_thousand_population))
        return per_hundred_thousand_population_per_week

    def get_reproduction_number(self, to_date: date) -> float:
        """指定した日時点の実効再生産数の簡易推定値を算出

        国立感染症研究所の「COVID-19感染報告者数に基づく簡易実効再生産数推定方法」に基づき計算している。
        https://www.niid.go.jp/niid/ja/diseases/ka/corona-virus/2019-ncov/2502-idsc/iasr-in/10465-496d04.html

        Args:
            to_date (obj:`date`): 集計の終期

        Returns:
            reproduction_number (float): 実効再生産数

        """
        generation_time = 5
        from_date = to_date - relativedelta(days=6 + generation_time)
        aggregate_by_days = self.get_aggregate_by_days(from_date=from_date, to_date=to_date)
        latest_number = 0
        generation_time_before_number = 0
        i = 0
        for patients_number in aggregate_by_days:
            if i < 5:
                generation_time_before_number += patients_number[1]
            elif 5 <= i and i < 7:
                generation_time_before_number += patients_number[1]
                latest_number += patients_number[1]
            else:
                latest_number += patients_number[1]
            i += 1

        if generation_time_before_number == 0:
            return 0

        return float(
            Decimal(str(latest_number / generation_time_before_number)).quantize(
                Decimal("0.01"), rounding=ROUND_HALF_UP
            )
        )

    def get_total_by_months(self, from_date: date, to_date: date) -> list:
        """指定した期間の1か月ごとの陽性患者数の累計結果を返す

        Args:
            from_date (obj:`date`): 累計の始期
            to_date (obj:`date`): 累計の終期

        Returns:
            total_by_months (list of tuple): 集計結果
                1か月ごとの年月とその週までの累計陽性患者数を要素とするタプルのリスト

        """
        if not isinstance(from_date, date) or not isinstance(to_date, date):
            raise ServiceError("期間の範囲指定が日付になっていません。")

        state = (
            "SELECT date(aggregate_patients.from_month), "
            + "SUM(aggregate_patients.patients) OVER("
            + "ORDER BY aggregate_patients.from_month) AS total_patients FROM "
            + "("
            + "SELECT from_month, COUNT(DISTINCT patient_number) as patients FROM "
            + "("
            + "SELECT generate_series AS from_month, generate_series + "
            + "'1 months'::interval AS to_month FROM generate_series(%s::DATE, %s::DATE, '1 months')"
            + ") AS month_ranges "
            + "LEFT JOIN asahikawa_patients "
            + "ON from_month <= asahikawa_patients.publication_date AND "
            + "asahikawa_patients.publication_date < to_month GROUP BY from_month"
            + ") AS aggregate_patients;"
        )
        total_by_months = list()
        with self.get_connection() as cur:
            cur.execute(state, (from_date.strftime("%Y-%m-%d"), to_date.strftime("%Y-%m-%d")))
            for row in cur.fetchall():
                total_by_months.append((row[0], row[1]))

        return total_by_months

    def get_patients_number_by_age(self, from_date: date, to_date: date) -> list:
        """年代別の陽性患者数を返す

        Args:
            from_date (obj:`date`): 累計の始期
            to_date (obj:`date`): 累計の終期

        Returns:
            patients_number_by_age (list of tuple): 集計結果
                年代別の陽性患者数を要素とするタプルのリスト

        """
        if not isinstance(from_date, date) or not isinstance(to_date, date):
            raise ServiceError("期間の範囲指定が日付になっていません。")

        state = (
            "SELECT age,COUNT(age) FROM asahikawa_patients WHERE DATE(publication_date) "
            + "BETWEEN %s AND %s GROUP BY age ORDER BY age;"
        )
        patients_number_by_age = [
            ("10歳未満", 0),
            ("10代", 0),
            ("20代", 0),
            ("30代", 0),
            ("40代", 0),
            ("50代", 0),
            ("60代", 0),
            ("70代", 0),
            ("80代", 0),
            ("90歳以上", 0),
        ]
        with self.get_connection() as cur:
            cur.execute(state, (from_date.strftime("%Y-%m-%d"), to_date.strftime("%Y-%m-%d")))
            for row in cur.fetchall():
                if row[0] == "10歳未満":
                    patients_number_by_age[0] = (row[0], row[1])
                elif row[0] == "10代":
                    patients_number_by_age[1] = (row[0], row[1])
                elif row[0] == "20代":
                    patients_number_by_age[2] = (row[0], row[1])
                elif row[0] == "30代":
                    patients_number_by_age[3] = (row[0], row[1])
                elif row[0] == "40代":
                    patients_number_by_age[4] = (row[0], row[1])
                elif row[0] == "50代":
                    patients_number_by_age[5] = (row[0], row[1])
                elif row[0] == "60代":
                    patients_number_by_age[6] = (row[0], row[1])
                elif row[0] == "70代":
                    patients_number_by_age[7] = (row[0], row[1])
                elif row[0] == "80代":
                    patients_number_by_age[8] = (row[0], row[1])
                elif row[0] == "90歳以上":
                    patients_number_by_age[9] = (row[0], row[1])

        return patients_number_by_age

    def get_patients_number(self, target_date: date) -> int:
        """指定した日の陽性患者数を返す

        Args:
            target_date (obj:`date`): 対象年月日

        Returns:
            patients_number (int): 対象年月日の陽性患者数

        """
        state = "SELECT COUNT(patient_number) FROM" + " " + self.table_name + " " + "WHERE publication_date = %s;"
        with self.get_connection() as cur:
            cur.execute(state, (target_date,))
            res = cur.fetchone()

        patients_number = res[0]
        if isinstance(patients_number, int):
            return patients_number
        else:
            return 0

class HokkaidoPatientService(Service):
    """北海道の公表する新型コロナウイルス感染症患者データを扱うサービス"""

    def __init__(self, pool: ConnectionPool):
        """
        Args:
            table_name (str): テーブル名
            pool (:obj:`ConnectionPool`): SimpleConnectionPoolを要素に持つオブジェクト

        """
        Service.__init__(self, "hokkaido_patients", pool)

    def create(self, patients: HokkaidoPatientFactory) -> None:
        """データベースへ新型コロナウイルス感染症患者データを保存

        Args:
            patient (:obj:`HokkaidoPatientFactory`): 集計結果
                患者データのオブジェクトのリストを要素に持つオブジェクト

        """
        items = (
            "patient_number",
            "city_code",
            "prefecture",
            "city_name",
            "publication_date",
            "onset_date",
            "residence",
            "age",
            "sex",
            "occupation",
            "status",
            "symptom",
            "overseas_travel_history",
            "be_discharged",
            "note",
            "updated_at",
        )

        data_lists = list()
        for patient in patients.items:
            data_lists.append(
                [
                    patient.patient_number,
                    patient.city_code,
                    patient.prefecture,
                    patient.city_name,
                    patient.publication_date,
                    patient.onset_date,
                    patient.residence,
                    patient.age,
                    patient.sex,
                    patient.occupation,
                    patient.status,
                    patient.symptom,
                    patient.overseas_travel_history,
                    patient.be_discharged,
                    patient.note,
                    datetime.now(timezone(timedelta(hours=+9))),
                ]
            )

        # データベースへ登録処理
        self.upsert(
            items=items,
            primary_key="patient_number",
            data_lists=data_lists,
        )


from imageio import imread, imwrite
import matplotlib.pyplot as plt
import numpy as np
import scipy
import math
from skimage.transform import rescale
from pathlib import Path
import sys

def downscaleByHalf(img, antiAliasing=False):
    toReturn = rescale(img, (0.5, 0.5, 1), anti_aliasing=antiAliasing)
    return toReturn

def padEdge(img,amount):
    padded = np.pad(img,((amount,amount),(amount,amount),(0,0)),mode='edge')
    return padded

def getNeighborhoods(image, neighborhoodWidth):
    neighborhoods = []
    neighborhoodWidth = abs(neighborhoodWidth)
    if (neighborhoodWidth%2 == 0):
        neighborhoodWidth = neighborhoodWidth - 1
    offset = math.floor(neighborhoodWidth/2)
    paddedImage = padEdge(image,offset)
    #for each pixel
    for row in range(offset,paddedImage.shape[0]-offset):
        for column in range(offset, paddedImage.shape[1]-offset):
            pixelToAdd = []
            #neighborhood loops
            for i in range(-offset,offset+1):
                for j in range(-offset,offset+1):
                    for k in range(0,3): #color
                        pixelToAdd.append(paddedImage[row+i,column+j,k])
            neighborhoods.append(pixelToAdd)
    return neighborhoods

def breakupImage(img):
    im1 = img[0::2,0::2,:] #start 1st row, 1st column
    im2 = img[0::2,1::2,:] #start 1st row, 2nd column
    im3 = img[1::2,0::2,:] #start 2nd row, 1st column
    im4 = img[1::2,1::2,:] #start 2nd row, 2nd column
    return im1,im2,im3,im4

def calcRegression(images):
    neighborhoods = []

    images0r = []
    images0g = []
    images0b = []
    images1r = []
    images1g = []
    images1b = []
    images2r = []
    images2g = []
    images2b = []
    images3r = []
    images3g = []
    images3b = []

    for image in images:
        #convert image to 0-1 values as imread opens them as values 0-255
        image = image/255
        downscaled = downscaleByHalf(image)
        if not neighborhoods:
            neighborhoods = getNeighborhoods(downscaled,5)
        else:
            np.concatenate((neighborhoods,getNeighborhoods(downscaled,5)))
        im0,im1,im2,im3 = breakupImage(image)
        images0r.append(im0[:,:,0])
        images0g.append(im0[:,:,1])
        images0b.append(im0[:,:,2])
        images1r.append(im1[:,:,0])
        images1g.append(im1[:,:,1])
        images1b.append(im1[:,:,2])
        images2r.append(im2[:,:,0])
        images2g.append(im2[:,:,1])
        images2b.append(im2[:,:,2])
        images3r.append(im3[:,:,0])
        images3g.append(im3[:,:,1])
        images3b.append(im3[:,:,2])

    neighborhoods = np.insert(neighborhoods,0,1,axis =1)

    # b vectors (original size images) reshaped to be vectors
    r0 = np.vstack(np.reshape(images0r,-1))
    g0 = np.vstack(np.reshape(images0g,-1))
    b0 = np.vstack(np.reshape(images0b,-1))
    r1 = np.vstack(np.reshape(images1r,-1))
    g1 = np.vstack(np.reshape(images1g,-1))
    b1 = np.vstack(np.reshape(images1b,-1))
    r2 = np.vstack(np.reshape(images2r,-1))
    g2 = np.vstack(np.reshape(images2g,-1))
    b2 = np.vstack(np.reshape(images2b,-1))
    r3 = np.vstack(np.reshape(images3r,-1))
    g3 = np.vstack(np.reshape(images3g,-1))
    b3 = np.vstack(np.reshape(images3b,-1))

    #regressions
    result0r = np.linalg.lstsq(neighborhoods, r0, rcond=None)[0]
    print("Completed 1/12 regressions")
    result0g = np.linalg.lstsq(neighborhoods, g0, rcond=None)[0]
    result0b = np.linalg.lstsq(neighborhoods, b0, rcond=None)[0]
    print("Completed 3/12 regressions")
    result1r = np.linalg.lstsq(neighborhoods, r1, rcond=None)[0]
    result1g = np.linalg.lstsq(neighborhoods, g1, rcond=None)[0]
    result1b = np.linalg.lstsq(neighborhoods, b1, rcond=None)[0]
    print("Completed 6/12 regressions")
    result2r = np.linalg.lstsq(neighborhoods, r2, rcond=None)[0]
    result2g = np.linalg.lstsq(neighborhoods, g2, rcond=None)[0]
    result2b = np.linalg.lstsq(neighborhoods, b2, rcond=None)[0]
    result3r = np.linalg.lstsq(neighborhoods, r3, rcond=None)[0]
    result3g = np.linalg.lstsq(neighborhoods, g3, rcond=None)[0]
    result3b = np.linalg.lstsq(neighborhoods, b3, rcond=None)[0]
    print("Completed 12/12 regressions")

    results = [result0r, result0g, result0b, result1r, result1g, result1b, result2r, result2g, result2b, result3r, result3g, result3b]

    return results

def upscaleImg(img, regressions):
    neighborhoods = getNeighborhoods(img, 5)
#     neighborhoods = np.insert(neighborhoods,0,1,axis =1)

    #pixelColorValues
    PCV = []
    #get rid of the the extra dimension
    clippedRegressions = []
    for regression in regressions:
        regression = regression[1:]
        clippedRegressions.append(regression)
    for i in range (0,12):
        values = neighborhoods @ clippedRegressions[i]
        PCV.append(values)

    #create final image
    finalImageWidth = np.shape(img)[1] * 2
    finalImageHeight = np.shape(img)[0] * 2
    toReturn = np.ndarray(shape=(finalImageHeight,finalImageWidth,3))
    for curRow in range(0,finalImageHeight):

        # only add an offset for every other row and max offset will only be half the width of upscaled image
        rowOffset = curRow//2 * (finalImageWidth//2)
        for curCol in range(0,finalImageWidth):
            #placeToIndex
            pti = curCol//2 + rowOffset
            if curRow % 2 == 0:
                if curCol % 2 == 0:
                    pixels = [PCV[0][pti],PCV[1][pti],PCV[2][pti]]
                    toReturn[curRow][curCol] = pixels
                else:
                    pixels = [PCV[3][pti],PCV[4][pti],PCV[5][pti]]
                    toReturn[curRow][curCol] = pixels
            else:
                if curCol % 2 == 0:
                    pixels = [PCV[6][pti],PCV[7][pti],PCV[8][pti]]
                    toReturn[curRow][curCol] = pixels
                else:
                    pixels = [PCV[9][pti],PCV[10][pti],PCV[11][pti]]
                    toReturn[curRow][curCol] = pixels
    return toReturn

def openImages(imagesDirectory):
    images = []
    for file in Path(imagesDirectory).iterdir():
        try:
            im = imread(file)
            images.append(im)
        except:
            print("can't read a file, moving to next")
    return images

def main(pathToImages, imageToUpscale):

    # print(pathToImages, imageToUpscale)
    images = openImages(pathToImages)
    if len(images) <= 0:
        print("no images found in directory")
        return 0
    toUpscale = []
    try:
        toUpscale = imread(imageToUpscale)
        toUpscale = toUpscale/255
    except:
        print("Image to upscale cannot be opened")

    regressions = calcRegression(images)
    upscaled = upscaleImg(toUpscale,regressions)
    plt.imshow(upscaled)
    imwrite('upscaled.jpg', upscaled[:, :, :])

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: pathToImagesFolder, fileName for image to upscale")
    main(sys.argv[1],sys.argv[2])


import os
import sys
import time
import argparse
import numpy as np
from tqdm import tqdm
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt

os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"

# --- M I N D S P O R E -------------------------------------------------
import mindspore
from mindspore import nn
from mindspore.dataset import vision
from mindspore import context
context.set_context(
        mode=context.PYNATIVE_MODE,
        save_graphs=False, save_graphs_path='./graphs',
        device_id=0,device_target='GPU')  # 'Ascend', 'GPU', 'CPU'
# -----------------------------------------------------------------------

sys.path.append('..')
from core.common.utils import create_folder
from core.common.scoring import score, score_tqd, score_shrq
from core.ms import data as data
from core.ms import models

def get_args():
    parser = argparse.ArgumentParser(description='PyTorch IQA')
    parser.add_argument('--data-dir', metavar='DIR',
                        help='path to dataset')
    parser.add_argument('--dataset', type=str,
                        choices=['live', 'csiq', 'tid2013',
                                 'liu', 'ma', 'shrq', 'dibr', 'pipal',
                                 'qads', 'tqd', 'kadid', 'pieapp','custom'],
                        help='dataset name')
    parser.add_argument('--model-path',
                        help='path to checkpoint')
    parser.add_argument('-j', '--workers', default=0, type=int, metavar='N',
                        help='number of data loading workers (default: 4)')
    parser.add_argument('-b', '--batch-size', default=16, type=int, metavar='N',
                        help='mini-batch size (default: 16)')
    parser.add_argument('--backbone', default='vgg', type=str,
                        choices=['resnet', 'alex', 'vgg', 'squeeze'],help='backbone network')
    parser.add_argument('--lpips', dest='lpips', action='store_true',
                        help='use lpips model')
    parser.add_argument('--dists', dest='dists', action='store_true',
                        help='use dists model')
    parser.add_argument('--iqt', dest='iqt', action='store_true',
                        help='use iqt model')
    parser.add_argument('--l2pooling', action='store_true',
                        help='l2pooling in vgg (similar to DISTS)')
    parser.add_argument('-p', '--print-freq', default=10, type=int,
                        metavar='N', help='print frequency (default: 10)')
    parser.add_argument('--loader', default='pil', type=str,
                        choices=['cv2', 'pil'],
                        help='image loader')
    parser.add_argument('--resize', default=0, type=int,
                        help='image resize')
    parser.add_argument('--patch_sampler', default=None, type=str,
                        choices=['rand', 'entire'],
                        help='patch sampler strategy')
    parser.add_argument('--debug', dest='debug', action='store_true',
                        help='turn DEBUG on')
    args = parser.parse_args()
    return args

def main():
    args = get_args()

    main_worker(args)

def main_worker(args):

    # IQA model ---------------------------------------------------------
    # FR-IQA
    if args.lpips:
        net = models.LPIPSsinglewRef(net=args.backbone, lpips=True,
                         pretrained=True, pnet_tune=True, l2pooling=args.l2pooling)
    elif args.dists:
        if args.backbone != 'vgg':
            print("[WARNING] ignoring argument '--backbone {}', DISTS only supports vgg.".format(args.backbone))
        net = models.DISTSsinglewRef(pnet_tune=True)
    elif args.iqt:
        net = None
    # ----------------------------------------------------
    # B-IQA
    elif args.backbone == 'resnet':
        #model = models.ResNet50(1, args.pretrained)
        net = models.ResNet50(n_classes=1, pretrained=True)
    elif args.backbone == 'vgg':
        model = models.VGG16(1, args.pretrained)
    elif args.backbone == 'alex':
        model = models.AlexNet(1, args.pretrained)

    print("=> loading checkpoint '{}'".format(args.model_path))
    param_dict = mindspore.load_checkpoint(args.model_path)
    param_not_load = mindspore.load_param_into_net(net, param_dict,strict_load=True)
    print("done loading network weights.\n")

    # Data loading code
    # LPIPS
    if args.lpips:
        normalize = vision.Normalize((.5, .5, .5),(.5, .5, .5),is_hwc=False)
    # DISTS or IQT
    elif args.dists or args.iqt:
        normalize = vision.Normalize((0., 0., 0.),(1., 1., 1.),is_hwc=False)
    # else...
    else:
        normalize = vision.Normalize(mean=(0.485, 0.456, 0.406),
                                      std=(0.229, 0.224, 0.225),is_hwc=False)

    if args.loader == 'cv2':
        img_loader = data.cv2_loader
        val_transforms = data.ValTransforms(normalize=normalize, resize=args.resize)
    elif args.loader == 'pil':
        img_loader = data.pil_loader
        val_transforms = data.ValTransformsPIL(normalize=normalize, resize=args.resize)

    #-- PieAPP (test split) ------------------------------------------------
    if args.dataset == 'pieapp':
        df_path = '../data/' + args.dataset + '/test.csv'

        loader = torch.utils.data.DataLoader(
            data.IQAsinglewRef(args.data_dir, val_transforms,
                               df_path=df_path, loader=img_loader),
            batch_size=args.batch_size, shuffle=False,
            num_workers=args.workers, pin_memory=True)

        y_pred = extract(loader, model, args)

    #-- PIPAL (train split) ------------------------------------------------
    elif args.dataset == 'pipal':
        df_path = '../data/' + args.dataset + '/train.csv'

        loader = mindspore.dataset.GeneratorDataset(
            source=data.PIPALsinglewRef(args.data_dir, val_transforms,
                               df_path=df_path, split='all', loader=img_loader),
            shuffle=False,
            num_parallel_workers=args.workers)
        loader = loader.batch(batch_size=args.batch_size)

        y_pred = extract(loader, model, args)

    #-- LIVE / CSIQ / TID2013 / (...) --------------------------------------
    else:
        df_path = '../data/' + args.dataset + '/all.csv'

        loader = mindspore.dataset.GeneratorDataset(
            source=data.IQAsinglewRef(args.data_dir, val_transforms,
                               df_path=df_path, loader=img_loader),
            column_names=['ref_img','dist_img','mos'],
            shuffle=False,
            num_parallel_workers=args.workers)
        loader = loader.batch(batch_size=args.batch_size)

        y_pred = extract(loader, net, args)

def save_results(res, fpath):
    final = []
    for i in range(len(res)):
        final.append((res.index[i], res['pred'][i]))
    final = sorted(final, key=lambda x: x[0])

    txt = ''
    for i in range(len(res)):
        if i != 0:
            txt += '\n'
        txt += '%s,%f' % (final[i][0], final[i][1])

    fdir = os.path.dirname(fpath)
    create_folder(fdir)
    with open(fpath, 'w+') as f:
        f.write(txt)

def plot_scores(x, y, fpath):
    plt.figure(figsize=(6, 6))
    plt.scatter(x, y)
    plt.xlabel('Predicted scores')
    plt.ylabel('MOS')
    plt.savefig(fpath, dpi=100)
    plt.close()

def extract(val_loader, model, args):
    model.set_train(False)

    all_output = []
    all_target = []
    test_ensemble=args.patch_sampler

    print("\ninference strategy: '{}', resize={}".format(test_ensemble,args.resize))

    end = time.time()

    #if 'elo' in keys or 'mos' in keys:
    if True:
        i=0
        for batch in tqdm(val_loader.create_dict_iterator()):
            ref=batch['ref_img']
            x0=batch['dist_img']
            y0=batch['mos']
            if test_ensemble == 'rand':
                # ensemble eval w/ random patches ------------------------
                n_ensemble=20
                crop_size=256
                pred=0
                for j in range(n_ensemble):
                    _, c, h, w = ref.shape
                    new_h = crop_size
                    new_w = crop_size
                    top = np.random.randint(0, h - new_h)
                    left = np.random.randint(0, w - new_w)

                    r_img_crop = ref[:, :, top: top+new_h, left: left+new_w]
                    d_img_crop =  x0[:, :, top: top+new_h, left: left+new_w]

                    y0_patch = y0

                    # mindspore conversion
                    ref_imgs = r_img_crop
                    dist_imgs = d_img_crop

                    # compute output
                    if isinstance(model,models.ResNet):
                        # B-IQA: disregard 'ref' image
                        output = model(dist_imgs)
                    else:
                        # FR-IQA: 'ref' is part of model input
                        output, _ = model(ref_imgs, dist_imgs)
                    pred += float(mindspore.Tensor.squeeze(output))

                # ensemble average
                pred /= n_ensemble
                # record
                if len(ref) == 1:
                    all_output.append(pred)
                else:
                    all_output.extend(pred)
                all_target.extend(y0.asnumpy())

            elif test_ensemble == 'entire':
                # ensemble eval w/ entire image patchified ---------------
                crop_size=256
                # LIVE or CSIQ:256 , TID:128, QADS:120
                if args.dataset in ['tid2013']:
                    step = 128
                elif args.dataset == 'qads':
                    step=120
                else:
                    step = 256
                if args.debug:
                    print("  crop_sz={}, step={}".format(crop_size,step))
                pred=0
                from patchify import patchify
                ref_img = np.moveaxis(np.squeeze(ref.asnumpy()),0,-1)
                r_patches = patchify(ref_img , (crop_size,crop_size,3) , step)
                if args.debug:
                    print(" ",r_patches.shape[0]*r_patches.shape[1], \
                            "patches extracted from image:",ref.size())

                dis_img = np.moveaxis(np.squeeze(x0.asnumpy()),0,-1)
                d_patches = patchify(dis_img , (crop_size,crop_size,3) , step)
                for j in range(r_patches.shape[0]):
                    for k in range(r_patches.shape[1]):
                        r_patch = mindspore.Tensor(np.expand_dims(np.moveaxis(r_patches[j, k, 0],-1,0),0))
                        d_patch = mindspore.Tensor(np.expand_dims(np.moveaxis(d_patches[j, k, 0],-1,0),0))

                        # mindspore conversion
                        ref_imgs = r_patch
                        dist_imgs = d_patch

                        # compute output
                        if isinstance(model,models.ResNet):
                            # B-IQA: disregard 'ref' image
                            output = model(dist_imgs)
                        else:
                            # FR-IQA: 'ref' is part of model input
                            output, _ = model(ref_imgs, dist_imgs)
                        pred += float(mindspore.Tensor.squeeze(output))

                # ensemble average
                pred /= (r_patches.shape[0] * r_patches.shape[1])
                # record
                if len(ref) == 1:
                    all_output.append(pred)
                else:
                    all_output.extend(pred)
                    all_target.extend(y0.asnumpy())
                all_target.extend(y0.asnumpy())

            else:
                # single-patch eval --------------------------------------
                label = float(mindspore.Tensor.squeeze(y0))

                if args.debug:
                    print("model input:",x0.shape,y0.shape)
                    print("net:",type(model))
                    print(type(models.ResNet))
                    print(type(models.ResNet50))
                # compute output
                if isinstance(model,models.ResNet):
                    # B-IQA: disregard 'ref' image
                    output = model(x0) #dist_imgs)
                else:
                    # FR-IQA: 'ref' is part of model input
                    output, _ = model(ref, x0)
                if args.debug:
                    print("model output:",output.shape)
                pred = float(mindspore.Tensor.squeeze(output))

                # record
                if len(ref) == 1:
                    all_output.append(pred)
                else:
                    all_output.extend(pred)
                all_target.extend([label])
            #-------------------------------------------------------------
            i+=1
        #-----------------------------------------------------------------

        txt = score(all_output, all_target, prefix='\n(all) ')
        print(txt)

        all_output = np.asarray(all_output)
        all_target = np.asarray(all_target)
        if args.dataset == 'tqd':
            txt = score_tqd(all_output, all_target, val_loader.dataset.df)
            print(txt)
        elif args.dataset == 'shrq':
            txt = score_shrq(all_output, all_target)
            print(txt)

        fdir = os.path.join(os.path.dirname(args.model_path), args.dataset)
        create_folder(fdir)
        if args.resize == 0:
            fpath = os.path.join(fdir, 'plot.png')
        else:
            fpath = os.path.join(fdir, 'plot_%d.png' % args.resize)
        plot_scores(all_output, all_target, fpath=fpath)
    else:
        for i, (ref, x0) in tqdm(enumerate(val_loader)):
            ref = ref.cuda(non_blocking=True)
            x0 = x0.cuda(non_blocking=True)

            # compute output
            output, _ = model(ref, x0)

            # record
            all_output.extend(output.cpu().numpy().squeeze())
    return all_output

def accuracy(d0s, d1s, gts, dists):

    d0s = np.array(d0s)
    d1s = np.array(d1s)
    gts = np.array(gts)

    scores = (d0s<d1s)*(1.-gts) + (d1s<d0s)*gts + (d1s==d0s)*.5

    txt = 'Overall accuracy: %.3f' % (np.mean(scores))

    for dist in np.unique(dists):
        cond = dists == dist
        scores = (d0s[cond]<d1s[cond])*(1.-gts[cond]) + \
            (d1s[cond]<d0s[cond])*gts[cond] + (d1s[cond]==d0s[cond])*.5

        txt += '\n.. %s: %.3f' % (dist, np.mean(scores))
    return txt

def extract_pair(val_loader, model, args):
    # switch to evaluate mode
    model.eval()

    all_output0 = []
    all_output1 = []
    all_target = []
    all_shape = []
    with torch.no_grad():
        end = time.time()

        for i, (ref, (x0, x1, y)) in tqdm(enumerate(val_loader)):
            ref = ref.cuda(non_blocking=True)
            x0 = x0.cuda(non_blocking=True)
            x1 = x1.cuda(non_blocking=True)
            y = y.cuda(non_blocking=True)

            # compute output
            output0, _ = model(ref, x0)
            output1, _ = model(ref, x1)

            # record
            if len(ref) == 1:
                all_output0.append(output0.cpu().numpy().squeeze())
                all_output1.append(output1.cpu().numpy().squeeze())
            else:
                all_output0.extend(output0.cpu().numpy().squeeze())
                all_output1.extend(output1.cpu().numpy().squeeze())
            all_target.extend(y.cpu().numpy())

        txt = accuracy(all_output1, all_output0, all_target,
                       val_loader.dataset.df['dist'].values)

        print(txt)

if __name__ == '__main__':
    main()


import nltk
from nltk.tokenize import word_tokenize, sent_tokenize
from nltk.tag import pos_tag
from nltk.chunk import ne_chunk
from nltk.corpus import stopwords

# Función para leer un archivo y devolverlo como una cadena de texto
def get_text(path_and_file):
    with open(path_and_file, 'r') as file:
        text = file.read()
    return text

def process_text(text):

    # Tokenización de oraciones
    sentences = sent_tokenize(text)
    print("Oraciones:", sentences)

    # Tokenización de palabras
    tokens = word_tokenize(text)
    print("Tokens:", tokens)

    # Etiquetado gramatical
    tagged = pos_tag(tokens)
    print("Etiquetas gramaticales:", tagged)

    # Reconocimiento de entidades nombradas
    named_entities = ne_chunk(tagged)
    print("Entidades nombradas:", named_entities)

    # Eliminación de palabras vacías (stop words)
    stop_words = set(stopwords.words('english'))
    filtered_words = [token for token in tokens if token.lower() not in stop_words]
    print("Palabras filtradas:", filtered_words)

# Texto de ejemplo
archivo = 'texto.txt'
texto_ejemplo = get_text(archivo)

# Procesar el texto
process_text(texto_ejemplo)


import toml
from discord.ext import commands

from utils.bot_class import MyBot
from utils.checks import server_admin_or_permission

class Cog(commands.Cog):
    def __init__(self, bot: MyBot, *args, **kwargs):
        self.bot = bot
        super().__init__(*args, **kwargs)

    @classmethod
    def setup(cls, bot: MyBot):
        return bot.add_cog(cls(bot))

    def config(self):
        config = self.bot.config
        cog_config = config["cogs"].get(self.qualified_name, {})
        return cog_config

    async def cog_check(self, ctx):
        command = ctx.command
        cog = command.cog
        if len(command.checks) == 0:
            permission_name = f"{cog.qualified_name}.{command.name}"
            my_check = server_admin_or_permission(permission_name).predicate
            ret = super().cog_check(ctx)
            ret = ret and await my_check(ctx)
            return ret
        else:
            return super().cog_check(ctx)


import sys
import re
import subprocess

# Usage
if len(sys.argv) < 3:
	print("usage: python3 extractFasta.py <id list> <fasta db> <output>")
	sys.exit(1)

idFile = sys.argv[1]
fastaFile = sys.argv[2]
outFile = sys.argv[3]

fdb = {}
header = ''
seq = ''

idlist = []

# Read ID File
with open(idFile) as IDS:
	for line in IDS:
		line = line.strip()
		idlist.append(line)
# Read FASTA file
with open(fastaFile) as FASTA:
	for line in FASTA:
		if line.startswith(">"):
			if header != '' and seq != '':
				fdb[header] = seq
				seq = ''
				header = line
			else:
				header = line
		else:
			seq = seq + line
	fdb[header] = seq

# Write to Output File
with open(outFile,"w") as OUT:
	for id in idlist:
		for key in fdb.keys():
			if id in key:
				OUT.write(key+fdb[key])


import tensorflow as tf
import numpy as np
import optuna

import tensorflow.keras.backend as K

keras = tf.keras

class OptunaCallback(keras.callbacks.Callback):
    def __init__(self, trial):
        self.trial = trial

    def on_epoch_end(self, epoch, logs):
        current_val_error = 1.0 - logs["val_acc"]
        self.trial.report(current_val_error, step=epoch)
        # 打ち切り判定
        if self.trial.should_prune(epoch):
            raise optuna.structs.TrialPruned()

def create_dataset(batch_size):
    (x_train,y_train), (x_valid,y_valid)=keras.datasets.fashion_mnist.load_data()
    x_train = x_train / 255.0
    x_train = np.reshape(x_train,(60000,28,28,1))
    x_train = x_train.astype(np.float32)
    y_train = tf.keras.utils.to_categorical(y_train,num_classes=10)

    x_valid = x_valid / 255.0
    x_valid = np.reshape(x_valid, (10000,28,28,1))
    x_valid = x_valid.astype(np.float32)
    y_valid = tf.keras.utils.to_categorical(y_valid,num_classes=10)

    c = tf.Variable(0, dtype=tf.int32)

    def map_fn(x,y):
        # c.assign_add(1)
        return (x,y)

    train_set= tf.data.Dataset.from_tensor_slices((x_train,y_train)).map(map_func=map_fn).repeat().batch(batch_size)
    valid_set = tf.data.Dataset.from_tensor_slices((x_valid,y_valid)).repeat().batch(batch_size)
    return (train_set, 60000),(valid_set, 10000)

def create_model():
    model = tf.keras.Sequential()
    model.add(tf.keras.Input(shape=(28,28,1)))
    model.add(tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu'))
    model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
    model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
    model.add(tf.keras.layers.Dropout(0.25))
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(128, activation='relu'))
    model.add(tf.keras.layers.Dropout(0.5))
    model.add(tf.keras.layers.Dense(10, activation='softmax'))

    return model

def train(lr, max_epoch, trial):
    batch_size = 100
    (train_set, train_num), (valid_set, valid_num) = create_dataset(batch_size)

    print(train_set)

    model = create_model()
    optimizer = tf.keras.optimizers.SGD(lr=lr)
    model.compile(loss='categorical_crossentropy',
              optimizer=optimizer,
              metrics=['accuracy'])
    model.summary()
    optuna_callback = OptunaCallback(trial)
    model.fit(train_set,steps_per_epoch=train_num/batch_size,validation_data=valid_set,validation_steps=valid_num/batch_size,epochs=max_epoch)

def objective(trial):
    max_epoch = 20
    learning_rate = trial.suggest_loguniform("learning_rate", 1e-7, 1e0)
    K.clear_session()
    train(learning_rate, max_epoch, trial)
    hist = train(learning_rate, max_epoch, trial)
    return 1.0 - np.max(hist["val_acc"])

if __name__ == '__main__':
    study = optuna.create_study()
    study.optimize(objective, n_trials=2)


import asyncio

from structures import Controller

async def main():
    cont = Controller()
    cont.toggle(True)

    while True:
        await asyncio.sleep(1)
        print(f"PT1 {cont.PT1.buffer[-1]}")
        print(f"PT2 {cont.PT2.buffer[-1]}")

    await asyncio.sleep(1)
    await cont.toggle(False)

if __name__ == "__main__":
    eventLoop = asyncio.new_event_loop()
    eventLoop.create_task(main())
    eventLoop.run_forever()


from image import Image
from deformation_model import DeformationModel
from movie import Movie
import numpy as np
from scipy import optimize
import mrcfile as mrc

def deform_file(path=None, shape=None, time_points=None, coefficients=None,
                save=None, add_grid=True, save_movie=True, verbose=True):
    """
    Deforms provided file based on the deformation model.
    :param path: Path to an image file in gray-scale, which should be loaded.
        If None scipy.misc.face is used instead.
    :param shape: array like object with at least two elements describing
        (width, height) of the image
    :param time_points: determines number of deformed images generated and
        their time (None is equal to range(10))
    :param coefficients: coefficients used in deformation model, describing the
        doming
    :param save: None - images are only returned, other inputs are regarded as
        folder paths where the results are saved
    :param add_grid: True - black grid is drawn over the image to better show
        the resulting deformation
    :param save_movie: True - if save=True then also the movie of the deformed
        images is saved as a STAR file format (with the individual images saved
        as mrc files)
    :param verbose: True - printing additional information about the current
        process state
    :return: ([images], coefficients) - images are numpy array with resulting
                                        data ordered as time_points
                                      - coefficients are coefficients used in
                                        the deformation model
    """
    if time_points is None:
        time_points = range(10)

    if verbose:
        print("Loading file")

    if path is None:
        img = Image()
        img.load_dummy(0, add_grid)
    else:
        img = Image(path, 0)

    if shape is None:
        img.shrink_to_reasonable()
    else:
        img.resize(shape)

    if verbose:
        print("Applying model")

    model = DeformationModel()
    if coefficients is None:
        model.initialize_model_randomly(img.shape(), max(time_points))
    else:
        model.coeffs = coefficients

    results = []
    for t in time_points:
        results.append(model.apply_model(img, 0, t))
        if verbose:
            print("Generated deformation in time point:", t)

    if save:
        if verbose:
            print("Saving results")

        for i in results:
            i.save(save, name="DeformationTime" + str(i.time_stamp))

        if save_movie:
            movie = Movie()
            for i in results:
                movie.add(i, True)
            movie.save_movie_mrc("./")

    results = [i.image_data for i in results]

    if verbose:
        print("Deformations finished.")

    return results, model.coeffs

def motion_correct_files(paths=[], time_points=[], coefficients=None,
                         save_path=None, save_partial=False, verbose=True):
    """
    Corrects motion (proof of concept implementation)
    :param paths: paths to deformed gray-scale files
    :param time_points: time_points of the provided files
    :param coefficients: coefficients used to correct motion, if None the whole
        calculation including coefficient estimation is performed
    :param save_path: None - result is only returned, any other value is
        treated as path to folder where to save result
    :param save_partial: True - partial results are saved into folder defined
        in save_path (individual corrected images)
    :param verbose: True - printing additional information about the current
        process state
    :return: numpy array representing the corrected image
    """

    if verbose:
        print("Loading files")

    movie = Movie()
    if (len(paths) == 1 and paths[0].endswith("mrc")):
        # single compact mrc file
        movie.load_compact_mrc(paths[0], time_points)
        for img in movie.micrographs:
            img.save("./", "ld")
    else:
        for p, t in zip(paths, time_points):
            img = Image(p, t)
            movie.add(img)

    movie.save_sum("./", "_simple_total")

    if verbose:
        print("Correcting for global shift")
    movie.correct_global_shift()

    movie.save_sum("./", "_global_corrected_total")

    if coefficients is None:
        if verbose:
            print("Calculating local shifts")
        local_shifts = movie.calculate_local_shifts()

        if verbose:
            print("Estimating deformation model coefficients")
        model = DeformationModel()
        model.initialize_model(*local_shifts)
    else:
        model = DeformationModel()
        model.coeffs = coefficients

    if verbose:
        print("Applying model")

    for i in range(len(movie.micrographs)):
        m = movie.micrographs[i]
        movie.micrographs[i] = model.apply_model(m, m.time_stamp, 0)
        if save_path and save_partial:
            movie.micrographs[i].save(save_path, name=("partial" + str(i)))
        if verbose:
            print("Restored image " + str(i))

    if save_path:
        movie.save_sum(save_path)

    if verbose:
        print("Restoration finished")

    return movie.sum_images()

if __name__ == "__main__":
    time_span = 10
    time_step = 0.5
    time_points = [x * time_step for x in range(int(time_span / time_step))]
    results, coeffs = deform_file(save="./", time_points=time_points,
                                  verbose=True)

    # paths = ["DeformationTime"+str(x) + ".png" for x in time_points]
    paths = ["./movie.mrc"]
    motion_correct_files(paths=paths, time_points=time_points, save_path="./",
                         save_partial=False, verbose=True)


import requests
from twilio.rest import Client
import os
from dotenv import load_dotenv

load_dotenv()

appid = os.getenv("APPID")
lat = 48.135124
lon = -11.581981

account_sid = os.environ.get("ACCOUNT_SID")
auth_token = os.environ.get('AUTH_TOKEN')
print(account_sid)
print(auth_token)

parameters = {
    "lat": lat,
    'lon': lon,
    'appid': appid,
    'exclude': 'current,minutely,daily'

}

response = requests.get(
    url="https://api.openweathermap.org/data/2.5/onecall", params=parameters)
response.raise_for_status()
weather_data = response.json()

weather_slice = weather_data['hourly'][:20]
will_rain = False
for hour_data in weather_slice:
    condition = hour_data['weather'][0]['id']

    if int(condition) < 700:
        client = Client(account_sid, auth_token)
        message = client.messages \
            .create(body="print your umbrella.", from_='+19625499365', to='+13695829586')

        print(message.status)


f = open("test.txt",'r',encoding = 'utf-8')
f.read(4)    # read the first 4 data
# 'This'
f.read(4)    # read the next 4 data
# ' is '
f.read()     # read in the rest till end of file
# 'my first file\nThis file\ncontains three lines\n'
f.read()  # further reading returns empty sting
# ''

f.tell()    # get the current file position
# 56
f.seek(0)   # bring file cursor to initial position
# 0
print(f.read())  # read the entire file
# This is my first file
# This file
# contains three lines

# We can read a file line-by-line using a for loop. This is both efficient and fast.
for line in f:
    print(line, end='')
# This is my first file
# This file
# contains three lines

# we can use the readline() method to read individual lines of a file.
# This method reads a file till the newline, including the newline character.

f.readline()
# 'This is my first file\n'
f.readline()
# 'This file\n'
f.readline()
# 'contains three lines\n'
f.readline()
# ''

# readlines() method returns a list of remaining lines of the entire file.
f.readlines()
# ['This is my first file\n', 'This file\n', 'contains three lines\n']