import requests
from urllib.parse import urlencode
import re
from requests import codes
import os
from hashlib import md5

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'Host': 'p3-tt.bytecdn.cn',
    'Upgrade-Insecure-Requests': 1,
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
}

def get_page(offset):
    params = {
        'aid': '24',
        'offset': offset,
        'format': 'json',
        # 'keyword': '街拍',
        'autoload': 'true',
        'count': '20',
        'cur_tab': '1',
        'from': 'search_tab',
        'pd': 'synthesis'
    }
    base_url = 'https://www.toutiao.com/api/search/content/?keyword=%E8%A5%BF%E5%AE%89'
    url = base_url + urlencode(params)
    try:
        resp = requests.get(url)
        print(url)
        if 200 == resp.status_code:
            print(resp.json())
            return resp.json()
    except requests.ConnectionError:
        return None

items = []

def get_images(json):
    if json.get('data'):
        data = json.get('data')
        for item in data:
            title = item.get('title')
            images = item.get('image_list')

            if title is None or images is None:
                continue

            for image in images:
                origin_image = re.sub("list/300x196/", "origin/", image.get('url'))

                print(image.get('url'))
                print(origin_image)
                print("---")

                # 返回一个生成器
                map = {
                    # 'image': origin_image,
                    'image': origin_image,
                    'title': title
                }

                items.append(map)

def save_image(item):
    # 获取文件系统分隔符
    img_path = '/Users/zzzz/Desktop/image' + os.path.sep + item.get('title')
    if not os.path.exists(img_path):
        os.makedirs(img_path)
    try:
        resp = requests.get(item.get('image'), headers)
        if codes.ok == resp.status_code:
            file_path = img_path + os.path.sep + '{file_name}.{file_suffix}'.format(
                file_name=md5(resp.content).hexdigest(),
                file_suffix='jpg')
            if not os.path.exists(file_path):

                with open(file_path, 'wb') as f:
                    f.write(resp.content)
                print('Downloaded image path is %s' % file_path)
            else:
                print('Already Downloaded', file_path)
    except requests.ConnectionError:
        print('Failed to Save Image，item %s' % item)

def main(offset):

    for offset in range(0,100,20):
        json = get_page(offset)
        get_images(json)
        for item in items:
            save_image(item)

main(0)


import numpy as np
from scipy import stats
# from expon_cusum import Lv,F1
# import matplotlib.pyplot as plt

### This script is used to compare the thresholds for CuSum & WL-Cusum

## From first commit
class F1(object):
    def __init__(self,c,mu_1=1,sig_1=1):
        self.c = c
        self.mu_1 = mu_1
        self.dist = stats.norm(0,sig_1)
    def pdf(self,y,nu,t):
        # Require: t > nu
        assert(not isinstance(y,np.ndarray))
        return self.dist.pdf(y-self.mu_1*np.exp(self.c*(t-nu)))
    def logpdf(self,y,nu,t):
        # Require: t > nu
        assert(not isinstance(y,np.ndarray))
        return self.dist.logpdf(y-self.mu_1*np.exp(self.c*(t-nu)))
    def rvs(self,size,nu,t):
        # Require: t > nu
        return self.dist.rvs(size=size) + self.mu_1*np.exp(self.c*(np.arange(t,t+size)-nu))
    def logpdf_arr(self,y):
        assert(isinstance(y,np.ndarray))
        ind = np.arange(float(len(y)))
        return np.sum(self.dist.logpdf(y-self.mu_1*np.exp(self.c*ind)))
def gfun(y,fc,f0):
    llr = np.zeros(len(y))
    for k in range(len(y)):
        llr[k] = fc.logpdf_arr(y[k:]) - np.sum(f0.logpdf(y[k:]))
    # print(llr)
    return (np.argmax(llr),np.amax(llr))
def Lv(y, f0, c, t):
    max_k, max_llr = gfun(y,F1(c,mu_1=f0.mean(),sig_1=np.sqrt(f0.var())),f0)
    # print(t,max_k)
    return max_llr

c = 0.4
f0 = stats.norm(0.1,100)
# f1 = F1(c,mu_1=f0.mean(),sig_1=np.sqrt(f0.var()))

b_1 = np.exp(np.linspace(np.log(.75),np.log(1.05),5))
b_2 = np.exp(np.linspace(np.log(.22),np.log(.32),5))
b_3 = np.exp(np.linspace(np.log(2),np.log(4.8),5))

N = 10000

mtfa_1 = np.zeros(len(b_1))
mtfa_2 = np.zeros(len(b_2))
mtfa_3 = np.zeros(len(b_3))
# add_1 = np.zeros(len(b_1))
# add_2 = np.zeros(len(b_2))
# add_3 = np.zeros(len(b_3))
W_1 = 25
W_2 = 50

for j in range(N):
    for i in range(len(b_1)):
        t = W_1
        y = f0.rvs(size=2000)
        while True:
            try:
                y[t]
            except IndexError:
                y = np.append(y,f0.rvs(size=2000))
            v_1 = Lv(y[max(1,t-W_1+1):t+1], f0, c, t)
            if (v_1 > b_1[i]):
                mtfa_1[i] = mtfa_1[i] + t - W_1 + 1
                break
            t = t + 1
        # print(mtfa_1[i])

    for i in range(len(b_2)):
        t = W_2
        y = f0.rvs(size=2000)
        while True:
            try:
                y[t]
            except IndexError:
                y = np.append(y,f0.rvs(size=2000))
            v_2 = Lv(y[max(1,t-W_2+1):t+1], f0, c, t)
            if (v_2 > b_2[i]):
                mtfa_2[i] = mtfa_2[i] + t - W_2 + 1
                break
            t = t + 1
        # print(mtfa_2[i])

    # No WL
    for i in range(len(b_3)):
        t = 0
        y = f0.rvs(size=2000)
        while True:
            try:
                y[t]
            except IndexError:
                y = np.append(y,f0.rvs(size=2000))
            v_3 = Lv(y[:t+1], f0, c, t)
            if (v_3 > b_3[i]):
                mtfa_3[i] = mtfa_3[i] + t + 1
                break
            t = t + 1

    # for i in range(len(b_1)):
    #     t = W_1
    #     y = f0.rvs(size=W_1)
    #     while True:
    #         try:
    #             y[t]
    #         except IndexError:
    #             y = np.append(y,f1.rvs(size=W_1,nu=W_1-1,t=t))
    #         v_1 = Lv(y[max(1,t-W_1+1):t+1], f0, c, t)
    #         if (v_1 > b_1[i]):
    #             add_1[i] = add_1[i] + t - W_1 + 1
    #             break
    #         t = t + 1
    #
    # for i in range(len(b_2)):
    #     t = W_2
    #     y = f0.rvs(size=W_2)
    #     while True:
    #         try:
    #             y[t]
    #         except IndexError:
    #             y = np.append(y,f1.rvs(size=W_2,nu=W_2-1,t=t))
    #         v_2 = Lv(y[max(1,t-W_2+1):t+1], f0, c, t)
    #         if (v_2 > b_2[i]):
    #             add_2[i] = add_2[i] + t - W_2 + 1
    #             break
    #         t = t + 1
    #
    # for i in range(len(b_3)):
    #     t = W_3
    #     y = f0.rvs(size=W_3)
    #     while True:
    #         try:
    #             y[t]
    #         except IndexError:
    #             y = np.append(y,f1.rvs(size=W_3,nu=W_3-1,t=t))
    #         v_3 = Lv(y[max(1,t-W_3+1):t+1], f0, c, t)
    #         if (v_3 > b_3[i]):
    #             add_3[i] = add_3[i] + t - W_3 + 1
    #             break
    #         t = t + 1

    if j % 10 == 9:
        print("Num of Iterations:", (j+1))
        print("mtfa_1:", mtfa_1 / (j+1))
        print("mtfa_2:", mtfa_2 / (j+1))
        print("mtfa_3:", mtfa_3 / (j+1))
        print("add_1:", add_1 / (j+1))
        print("add_2:", add_2 / (j+1))
        print("add_3:", add_3 / (j+1))
        # with open('./icp_cusum_t1.npy', 'wb') as f:
        #     np.save(f, mtfa_1 / (j+1))
        #     np.save(f, mtfa_2 / (j+1))
        #     np.save(f, mtfa_3 / (j+1))
        #     np.save(f, add_1 / (j+1))
        #     np.save(f, add_2 / (j+1))
        #     np.save(f, add_3 / (j+1))

###


import torch
import torch.nn as nn
import torch.nn.functional as F
from mmcv.runner import force_fp32, BaseModule, auto_fp16
from mmcv.ops.roi_align import roi_align

from mmdet.core import (bbox_cxcywh_to_xyxy, bbox_xyxy_to_cxcywh,
                        build_assigner, build_sampler, multi_apply,
                        reduce_mean)
from mmdet.models.builder import HEADS

import torch.distributed as dist
import random
from timm.models.vision_transformer import trunc_normal_

from model import build_model

import numpy as np
import os
from math import sqrt

BYTES_PER_FLOAT = 4
# TODO: This memory limit may be too much or too little. It would be better to
# determine it based on available resources.
GPU_MEM_LIMIT = 1024**3  # 1 GB memory limit

@HEADS.register_module()
class InsSegHead(BaseModule):
    _version = 2

    def __init__(self,
                 task_id,
                 num_classes,
                 loss_weight=1.0,
                 num_query=100,
                 num_bins=2000,
                 coord_norm='abs',
                 norm_val=1333,
                 transformer=None,
                 sync_cls_avg_factor=False,
                 with_mask=True,
                 init_cfg=None,
                 vae_cfg=dict(
                     token_length=16,
                     mask_size=64,
                     embedding_dim=64,
                     num_embeddings=256,
                     pretrained='vqvae_patch16_256_64.pth',
                     freeze=True
                 ),
                 seq_aug=None,
                 box_std=0.2,
                 cls_drop=0.,
                 mask_before_label=False,
                 sup_neg_mask=False,
                 no_sup_mask=False,
                 cls_weight=1.0,
                 box_weight=1.0,
                 mask_weight=1.0,
                 class_label_corruption='rand_n_fake_cls',
                 decoder_loss_weight=0.,
                 dice_loss_weight=1.0,
                 max_obj_decoderloss=100,
                 **kwargs):
        super().__init__(init_cfg)
        self.cnt = 0
        self.decoder_loss_weight = decoder_loss_weight
        self.max_obj_decoderloss = max_obj_decoderloss
        self.dice_loss_weight = dice_loss_weight
        self.task_id = task_id
        self.loss_weight = loss_weight
        self.class_label_corruption = class_label_corruption
        self.cls_weight = cls_weight
        self.box_weight = box_weight
        self.mask_weight = mask_weight
        self.mask_before_label = mask_before_label
        self.sup_neg_mask = sup_neg_mask
        self.no_sup_mask = no_sup_mask
        self.bg_cls_weight = 0
        self.sync_cls_avg_factor = sync_cls_avg_factor

        self.num_query = num_query
        self.num_bins = num_bins
        self.coord_norm = coord_norm
        self.norm_val = norm_val
        self.num_classes = num_classes
        self.fp16_enabled = False

        self.with_mask = with_mask
        self.box_std = box_std
        self.cls_drop = cls_drop
        self.transformer = transformer
        self.mask_token_length = vae_cfg['token_length']
        self.transformer.mask_token_length = self.mask_token_length
        self.vqvae = build_model(vae_cfg)
        self.mask_size = (vae_cfg['mask_size'], vae_cfg['mask_size'])
        self.vae_cfg = vae_cfg
        self.seq_aug = seq_aug
        self.num_vocal = self.transformer.num_vocal
        self.class_offset = num_bins + 1
        self.special_offset = self.class_offset + num_classes
        self.noise_label = self.special_offset + 1
        self.mask_offset = self.special_offset + 2

        class_weight = torch.ones(self.num_vocal)
        class_weight[:self.num_bins+1] = box_weight
        class_weight[self.class_offset: self.class_offset +
                     num_classes] = cls_weight
        class_weight[self.noise_label] = cls_weight
        class_weight[self.mask_offset: self.mask_offset +
                     self.vae_cfg.num_embeddings] = mask_weight

        self.loss_seq = nn.CrossEntropyLoss(
            weight=class_weight, reduction='sum')

    def build_input_seq(self, targets, max_objects=100):
        device = targets[0][0].device

        def shift_bbox(bbox, scale_factor):
            n = bbox.shape[0]
            box_xy = torch.rand((n, 2), device=device) * scale_factor[:2]
            box_wh = (bbox[:, 2:] - bbox[:, :2]) / 2.
            box = torch.cat([box_xy - box_wh, box_xy + box_wh], dim=-1)
            return box

        def random_bbox(n, scale_factor):
            box_xy = torch.rand((n, 2), device=device)
            # trunc normal generate [-2,2]
            box_wh = torch.abs(trunc_normal_(
                torch.empty((n, 2), device=device)) / 4)
            box = torch.cat([box_xy - box_wh, box_xy + box_wh],
                            dim=-1) * scale_factor
            return box

        def jitter_bbox(bbox, max_range=0.1):
            n = bbox.shape[0]
            if n == 0:
                return bbox
            w = bbox[:, 2] - bbox[:, 0]
            h = bbox[:, 3] - bbox[:, 1]

            noise = torch.stack([w, h, w, h], dim=-1)
            noise_rate = trunc_normal_(torch.empty(
                (n, 4), device=device)) / 2 * max_range
            bbox = bbox + noise * noise_rate

            return bbox

        assert self.coord_norm == 'abs'
        input_seq_list = []
        bad_bbox_flag_list = []
        max_len = max([t[0].size(0) for t in targets])
        for b_i, target in enumerate(targets):
            box, mask_token, gt_masks, mask_idx, label, img_size = target
            mask_token_sft = mask_token + self.mask_offset
            h, w = img_size[0], img_size[1]
            scale_factor = torch.tensor([w, h, w, h], device=device)

            label_token = label.unsqueeze(1) + self.class_offset
            if self.coord_norm == 'abs':
                norm_box = box / self.norm_val
            else:
                norm_box = box / scale_factor
            box_tokens = (
                norm_box * self.num_bins).round().long().clamp(min=0, max=self.num_bins)
            if self.mask_before_label:
                input_tokens = torch.cat(
                    [box_tokens, mask_token_sft, label_token], dim=1)
            else:
                input_tokens = torch.cat(
                    [box_tokens, label_token, mask_token_sft], dim=1)
            if self.seq_aug is None:
                input_tokens = input_tokens.flatten()
                nan = torch.full((max_len * (5 + self.vae_cfg.token_length) -
                                 len(input_tokens),), 0, dtype=torch.int64, device=device)
                input_seq = torch.cat([input_tokens, nan], dim=0)
                input_seq_list.append(input_seq)
                continue

            num_objects = input_tokens.shape[0]
            num_noise = max_objects - num_objects

            # Create bad bbox.
            dup_bbox_size = random.randint(0, num_noise)
            dup_bbox_size = 0 if num_objects == 0 else dup_bbox_size
            bad_bbox_size = num_noise - dup_bbox_size

            random_class = self.noise_label  # noise label
            multiplier = 1 if num_objects == 0 else num_noise // num_objects + 1
            box_tiled = box.repeat((multiplier, 1))
            box_tiled_idx = torch.arange(
                len(box), device=device).repeat(multiplier)
            bad_bbox_shift = box_tiled[torch.randperm(len(box_tiled))[
                :bad_bbox_size]]
            bad_bbox_shift = shift_bbox(bad_bbox_shift, scale_factor)
            bad_bbox_random = torch.cat(
                (random_bbox(bad_bbox_size, scale_factor), bad_bbox_shift), dim=0)
            bad_bbox = bad_bbox_random[torch.randperm(
                len(bad_bbox_random))[:bad_bbox_size]]
            bad_bbox_label = torch.full(
                (bad_bbox_size, ), random_class, device=device)
            bad_mask = self.vqvae.encode(torch.zeros(
                (1,)+self.mask_size, device=device))
            bad_mask_token = bad_mask.expand(bad_bbox_size, -1)

            # Create dup bbox.
            permidx = torch.randperm(len(box_tiled), device=device)[
                :dup_bbox_size]
            dup_bbox = box_tiled[permidx]
            dup_bbox = jitter_bbox(dup_bbox, max_range=0.1)
            dup_bbox = dup_bbox.max(box.new([0., 0., 0., 0.])).min(
                scale_factor)  # add for pre crop/roi
            dup_bbox_label = torch.full(
                (dup_bbox_size, ), random_class, device=device)

            dup_mask = crop_and_resize_gpu(
                gt_masks, dup_bbox, self.mask_size, mask_idx[box_tiled_idx[permidx]], device=device)
            dup_mask_token = self.vqvae.encode(dup_mask)

            shuffle_idx = torch.randperm(num_noise)
            bad_bbox_flag = torch.cat((torch.ones(bad_bbox_size, device=device), torch.zeros(
                dup_bbox_size, device=device))).to(torch.bool)
            bad_bbox_flag_list.append(
                bad_bbox_flag[shuffle_idx].nonzero(as_tuple=True)[0])
            noise_box = torch.cat((bad_bbox, dup_bbox), dim=0)[shuffle_idx].max(
                box.new([0., 0., 0., 0.])).min(scale_factor)
            noise_box_label = torch.cat(
                (bad_bbox_label, dup_bbox_label), dim=0)[shuffle_idx]
            noise_mask_token = torch.cat(
                (bad_mask_token, dup_mask_token), dim=0)[shuffle_idx]

            if self.coord_norm == 'abs':
                random_norm_box = noise_box / self.norm_val
            else:
                random_norm_box = noise_box / scale_factor
            noise_box_tokens = (
                random_norm_box * self.num_bins).round().long().clamp(min=0, max=self.num_bins)
            if self.mask_before_label:
                fake_tokens = torch.cat(
                    [noise_box_tokens, noise_mask_token + self.mask_offset, noise_box_label.unsqueeze(1)], dim=1)
            else:
                fake_tokens = torch.cat([noise_box_tokens, noise_box_label.unsqueeze(
                    1), noise_mask_token + self.mask_offset], dim=1)

            input_seq = torch.cat([input_tokens, fake_tokens], dim=0).flatten()
            input_seq_list.append(input_seq)
        return torch.stack(input_seq_list, dim=0), bad_bbox_flag_list

    def get_targets(self, input_seq, num_objects_list, bad_bbox_flag_list):
        N, L = input_seq.shape[0], input_seq.shape[1]//(
            5 + self.vae_cfg.token_length)
        for seq, num_objects, bad_bbox_flag in zip(input_seq, num_objects_list, bad_bbox_flag_list):
            seq.view(L, 5 + self.vae_cfg.token_length)[num_objects:, :4] = -100
            if self.no_sup_mask:
                if self.mask_before_label:
                    seq.view(
                        L, 5 + self.vae_cfg.token_length)[:, 4:4+self.vae_cfg.token_length] = -100
                else:
                    seq.view(L, 5 + self.vae_cfg.token_length)[:, 5:] = -100
            elif self.sup_neg_mask:
                if self.mask_before_label:
                    seq.view(L, 5 + self.vae_cfg.token_length)[
                        num_objects+bad_bbox_flag, 4:4+self.vae_cfg.token_length] = -100
                else:
                    seq.view(
                        L, 5 + self.vae_cfg.token_length)[num_objects+bad_bbox_flag, 5:] = -100
            else:
                if self.mask_before_label:
                    seq.view(
                        L, 5 + self.vae_cfg.token_length)[num_objects:, 4:4+self.vae_cfg.token_length] = -100
                else:
                    seq.view(
                        L, 5 + self.vae_cfg.token_length)[num_objects:, 5:] = -100

        return input_seq

    def forward(self, feats, img_metas, input_seq=None):
        num_levels = len(feats)
        img_metas_list = [img_metas for _ in range(num_levels)]
        input_seq_list = [input_seq for _ in range(num_levels)]
        return multi_apply(self.forward_single, feats, img_metas_list, input_seq_list)

    def forward_single(self, x, img_metas, input_seq):
        batch_size = x.size(0)
        input_img_h, input_img_w = img_metas[0]['batch_input_shape']
        if self.with_mask:
            masks = x.new_ones((batch_size, input_img_h, input_img_w))
            for img_id in range(batch_size):
                img_h, img_w, _ = img_metas[img_id]['img_shape']
                masks[img_id, :img_h, :img_w] = 0
        else:
            masks = x.new_zeros((batch_size, input_img_h, input_img_w))

        # interpolate masks to have the same spatial shape with x
        masks = F.interpolate(
            masks.unsqueeze(1), size=x.shape[-2:]).to(torch.bool).squeeze(1)
        # outs_dec: [bs, num_query, embed_dim]
        outs_dec = self.transformer(
            x, input_seq, masks, self.task_id, pred_len=self.num_query*(5+self.mask_token_length))

        return (outs_dec,)

    @force_fp32(apply_to=('out_seq'))
    def loss2(self,
              out_seq,
              target_seq
              ):
        # NOTE defaultly only the outputs from the last feature scale is used.
        # only for log purpose
        B, L, C = out_seq.shape
        out_seq_objs = out_seq.view(B, -1, 5+self.mask_token_length, C)
        target_seq_objs = target_seq.view(B, -1, 5+self.mask_token_length)

        out_seq_box = out_seq_objs[:, :, :4, :].reshape(-1, self.num_vocal)
        target_seq_box = target_seq_objs[:, :, :4].flatten()
        num_pos_box = (target_seq_box > -1).sum()
        bbox_ce = self.loss_seq(
            out_seq_box, target_seq_box) / num_pos_box.clamp(min=1)

        if self.mask_before_label:
            out_seq_cls = out_seq_objs[:, :, -1, :].reshape(-1, self.num_vocal)
            target_seq_cls = target_seq_objs[:, :, -1].flatten()
            num_pos_cls = (target_seq_cls > -1).sum()
            cls_ce = self.loss_seq(
                out_seq_cls, target_seq_cls) / num_pos_cls.clamp(min=1)

            out_seq_mask = out_seq_objs[:, :, 4:4 +
                                        self.vae_cfg.token_length, :].reshape(-1, self.num_vocal)
            target_seq_mask = target_seq_objs[:, :,
                                              4:4+self.vae_cfg.token_length].flatten()
            num_pos_mask = (target_seq_mask > -1).sum()
            mask_ce = self.loss_seq(
                out_seq_mask, target_seq_mask) / num_pos_mask.clamp(min=1)
        else:
            out_seq_cls = out_seq_objs[:, :, 4, :].reshape(-1, self.num_vocal)
            target_seq_cls = target_seq_objs[:, :, 4].flatten()
            num_pos_cls = (target_seq_cls > -1).sum()
            cls_ce = self.loss_seq(
                out_seq_cls, target_seq_cls) / num_pos_cls.clamp(min=1)

            out_seq_mask = out_seq_objs[:, :, 5:,
                                        :].reshape(-1, self.num_vocal)
            target_seq_mask = target_seq_objs[:, :, 5:].flatten()
            num_pos_mask = (target_seq_mask > -1).sum()
            mask_ce = self.loss_seq(
                out_seq_mask, target_seq_mask) / num_pos_mask.clamp(min=1)
            num_obj = num_pos_mask // self.vae_cfg.token_length
            num_obj = num_obj.clamp(max=self.max_obj_decoderloss)
            if self.decoder_loss_weight > 0. and num_obj > 0.:
                assert B == 1
                vae_reso = int(sqrt(self.vae_cfg.token_length))
                vae_mask = out_seq_mask[:, self.mask_offset: self.mask_offset+self.vae_cfg.num_embeddings].view(
                    -1, vae_reso, vae_reso, self.vae_cfg.num_embeddings).permute(0, 3, 1, 2)
                soft_mask = self.vqvae.decode_soft(vae_mask[:num_obj])
                decoder_aux_ce = self.dice_loss_weight * \
                    dice_loss(
                        soft_mask, self.mask[:num_obj]) + F.mse_loss(soft_mask, self.mask[:num_obj])
            else:
                decoder_aux_ce = torch.tensor(
                    0., device=f'cuda:{torch.cuda.current_device()}')

            out_seq = out_seq.reshape(-1, self.num_vocal)
            target_seq = target_seq.flatten()

            loss_seq = self.loss_seq(out_seq, target_seq)

            loss_dict = {'loss': (loss_seq + decoder_aux_ce * self.decoder_loss_weight *
                                  num_pos_mask * self.mask_weight) * self.loss_weight}

            loss_dict.update({'cls_ce': cls_ce, 'bbox_ce': bbox_ce,
                             'mask_ce': mask_ce, 'decoder_aux_ce': decoder_aux_ce})
            return loss_dict

    def corrupt_label(self, input_seq):
        if self.class_label_corruption == 'none':
            return input_seq
        N, L = input_seq.shape[0], input_seq.shape[1]//(
            5+self.mask_token_length)
        device = input_seq.device
        randlabel = torch.randint(
            self.num_classes, (N, L), device=device) + self.class_offset
        noiselabel = torch.full((N, L), self.noise_label,
                                device=device)  # noise label
        if self.class_label_corruption == 'rand_n_fake_cls':
            corruptlabel = torch.where(torch.rand(
                (N, L), device=device) < 0.5, randlabel, noiselabel)
        elif self.class_label_corruption == 'rand_cls':
            corruptlabel = randlabel
        else:
            raise NotImplementedError
        if self.mask_before_label:
            input_seq.view(
                N, L, 5+self.mask_token_length)[:, :, -1] = corruptlabel
        else:
            input_seq.view(
                N, L, 5+self.mask_token_length)[:, :, 4] = corruptlabel
        return input_seq

    def get_seq(self,
                img_metas,
                gt_bboxes,
                gt_labels=None,
                gt_masks=None,
                gt_bboxes_ignore=None,
                proposal_cfg=None,
                ):
        assert proposal_cfg is None, '"proposal_cfg" must be None'
        # random permute box
        device = gt_labels[0].device
        gt_masktoken_list = []
        rand_idx_list = []
        for idx in range(len(gt_labels)):
            rand_idx = torch.randperm(len(gt_labels[idx]), device=device)
            gt_labels[idx] = gt_labels[idx][rand_idx]
            gt_bboxes[idx] = gt_bboxes[idx][rand_idx]
            # crop mask
            mask = crop_and_resize_gpu(
                gt_masks[idx], gt_bboxes[idx], self.mask_size, rand_idx, device=device)
            self.mask = mask
            mask_token = self.vqvae.encode(mask)

            gt_masktoken_list.append(mask_token)
            rand_idx_list.append(rand_idx)
        input_seq, bad_bbox_flag_list = self.build_input_seq(list(zip(gt_bboxes, gt_masktoken_list, gt_masks, rand_idx_list, gt_labels, [
                                                             img_meta['img_shape'][:2] for img_meta in img_metas])), max_objects=self.num_query)
        input_seq_corruptlabel = self.corrupt_label(input_seq.clone())[:, :-1]
        target_seq = self.get_targets(input_seq, [len(
            gt_label) for gt_label in gt_labels], bad_bbox_flag_list)  # set -100 ignore

        return input_seq_corruptlabel, target_seq

    @force_fp32(apply_to=('all_cls_scores_list', 'all_bbox_preds_list'))
    def get_bboxes(self,
                   all_cls_scores_list,
                   img_metas,
                   rescale=False):
        # NOTE defaultly only using outputs from the last feature level,
        # and only the outputs from the last decoder layer is used.
        cls_scores = all_cls_scores_list[-1]

        result_list = []
        for img_id in range(len(img_metas)):
            cls_score = cls_scores[img_id]
            img_shape = img_metas[img_id]['img_shape']
            ori_shape = img_metas[img_id]['ori_shape']
            scale_factor = img_metas[img_id]['scale_factor']
            proposals = self._get_bboxes_single(cls_score,
                                                img_shape, ori_shape, scale_factor,
                                                rescale)
            result_list.append(proposals)

        return result_list

    def _get_bboxes_single(self,
                           cls_score,
                           img_shape,
                           ori_shape,
                           scale_factor,
                           rescale=False):
        if len(cls_score) == 2:
            pred_token, pred_score = cls_score
            pred_mask_logits = None
        else:
            pred_token, pred_score, pred_mask_logits = cls_score
        # pred_token = pred_token.long()
        seq_len = pred_token.shape[0]
        obj_len = 5 + self.mask_token_length
        if seq_len < obj_len:
            device, dtype = pred_score.device, pred_score.dtype
            return torch.tensor([], device=device, dtype=dtype), torch.tensor([], device=device, dtype=torch.long), torch.empty((0, ori_shape[0], ori_shape[1]), device=device, dtype=torch.bool)
        num_objects = seq_len // obj_len
        pred_token = pred_token[:int(
            num_objects * obj_len)].reshape(num_objects, obj_len)
        if self.mask_before_label:
            pred_bbox_token = pred_token[:, :4]
            pred_class_token = pred_token[:, -1].long()
            pred_mask_token = pred_token[:, 4:4 +
                                         self.vae_cfg.token_length].long()
        else:
            pred_bbox_token = pred_token[:, :4]
            pred_class_token = pred_token[:, 4].long()
            pred_mask_token = pred_token[:, 5:].long()
        if self.coord_norm == 'abs':
            boxes_per_image = pred_bbox_token * self.norm_val / self.num_bins
        else:
            boxes_per_image = pred_bbox_token / self.num_bins
            boxes_per_image[:, 0::2] = boxes_per_image[:, 0::2] * img_shape[1]
            boxes_per_image[:, 1::2] = boxes_per_image[:, 1::2] * img_shape[0]
        if rescale:
            boxes_per_image /= boxes_per_image.new_tensor(scale_factor)

        if pred_mask_logits is None:  # hard inf
            seg_masks = self.decode_mask(
                pred_mask_token, boxes_per_image, ori_shape, soft_inf=False)
        else:  # soft inf
            seg_masks = self.decode_mask(
                pred_mask_logits, boxes_per_image, ori_shape, soft_inf=True)

        return torch.cat((boxes_per_image, pred_score[:num_objects].unsqueeze(-1)), dim=-1), pred_class_token, seg_masks

    def decode_mask(self, mask_token, bboxes, ori_shape, soft_inf=False):
        img_h, img_w = ori_shape[:2]
        device = mask_token.device

        # N, 1, H, W
        if soft_inf:
            _N, _L, _C = mask_token.shape
            mask_token = mask_token.transpose(1, 2).reshape(
                _N, _C, int(sqrt(_L)), int(sqrt(_L)))
            mask_pred = self.vqvae.decode_soft(
                mask_token).unsqueeze(1)  # mask_token is mask_logits
        else:
            mask_pred = self.vqvae.decode(mask_token).unsqueeze(1)

        N = len(mask_pred)
        # The actual implementation split the input into chunks,
        # and paste them chunk by chunk.
        if device.type == 'cpu':
            # CPU is most efficient when they are pasted one by one with
            # skip_empty=True, so that it performs minimal number of
            # operations.
            num_chunks = N
        else:
            # GPU benefits from parallelism for larger chunks,
            # but may have memory issue
            # the types of img_w and img_h are np.int32,
            # when the image resolution is large,
            # the calculation of num_chunks will overflow.
            # so we need to change the types of img_w and img_h to int.
            # See https://github.com/open-mmlab/mmdetection/pull/5191
            num_chunks = int(
                np.ceil(N * int(img_h) * int(img_w) * BYTES_PER_FLOAT /
                        GPU_MEM_LIMIT))
            assert (num_chunks <=
                    N), 'Default GPU_MEM_LIMIT is too small; try increasing it'
        chunks = torch.chunk(torch.arange(N, device=device), num_chunks)

        im_mask = torch.zeros(
            N,
            img_h,
            img_w,
            device=device,
            dtype=torch.bool)

        for inds in chunks:
            masks_chunk, spatial_inds = _do_paste_mask(
                mask_pred[inds],
                bboxes[inds],
                img_h,
                img_w,
                skip_empty=device.type == 'cpu')

            # must use >0 because of grid_sample padding 0.
            # version change to >= 0.5 and add denorm before
            masks_chunk = (masks_chunk >= 0.5).to(dtype=torch.bool)

            im_mask[(inds, ) + spatial_inds] = masks_chunk

        return im_mask

    def simple_test(self, feats, img_metas, rescale=False):
        # forward of this head requires img_metas
        outs = self.forward(feats, img_metas)
        results_list = self.get_bboxes(*outs, img_metas, rescale=rescale)
        return results_list

def dice_loss(inputs, targets):
    """
    Compute the DICE loss, similar to generalized IOU for masks
    Args:
        inputs: A float tensor of arbitrary shape.
                The predictions for each example.
        targets: A float tensor with the same shape as inputs. Stores the binary
                 classification label for each element in inputs
                (0 for the negative class and 1 for the positive class).
    """
    # inputs = inputs.sigmoid()
    # assert inputs.max() <= 1 and inputs.min() >= 0
    inputs = inputs.clip(min=0., max=1.)
    inputs = inputs.flatten(1)
    targets = targets.flatten(1)
    numerator = 2 * (inputs * targets).sum(-1)
    denominator = inputs.sum(-1) + targets.sum(-1)
    loss = 1 - (numerator + 1) / (denominator + 1)
    return loss.mean()

def sigmoid_focal_loss(inputs, targets, alpha: float = 0.25, gamma: float = 2):
    """
    Loss used in RetinaNet for dense detection: https://arxiv.org/abs/1708.02002.
    Args:
        inputs: A float tensor of arbitrary shape.
                The predictions for each example.
        targets: A float tensor with the same shape as inputs. Stores the binary
                 classification label for each element in inputs
                (0 for the negative class and 1 for the positive class).
        alpha: (optional) Weighting factor in range (0,1) to balance
                positive vs negative examples. Default = -1 (no weighting).
        gamma: Exponent of the modulating factor (1 - p_t) to
               balance easy vs hard examples.
    Returns:
        Loss tensor
    """
    prob = inputs.sigmoid()
    ce_loss = F.binary_cross_entropy_with_logits(
        inputs, targets, reduction="none")
    p_t = prob * targets + (1 - prob) * (1 - targets)
    loss = ce_loss * ((1 - p_t) ** gamma)

    if alpha >= 0:
        alpha_t = alpha * targets + (1 - alpha) * (1 - targets)
        loss = alpha_t * loss

    return loss.mean()

def crop_and_resize_gpu(bitmapmasks,
                        bboxes,
                        out_shape,
                        inds,
                        device='cpu',
                        interpolation='bilinear',
                        binarize=True):
    """See :func:`BaseInstanceMasks.crop_and_resize`."""
    if len(bitmapmasks.masks) == 0:
        return torch.empty((0, *out_shape), dtype=bboxes.dtype, device=device)

    # convert bboxes to tensor
    if isinstance(bboxes, np.ndarray):
        bboxes = torch.from_numpy(bboxes).to(device=device)
    if isinstance(inds, np.ndarray):
        inds = torch.from_numpy(inds).to(device=device)

    num_bbox = bboxes.shape[0]
    fake_inds = torch.arange(
        num_bbox, device=device).to(dtype=bboxes.dtype)[:, None]
    rois = torch.cat([fake_inds, bboxes], dim=1)  # Nx5
    rois = rois.to(device=device)
    if num_bbox > 0:
        gt_masks_th = torch.from_numpy(bitmapmasks.masks).to(device).index_select(
            0, inds).to(dtype=rois.dtype)
        targets = roi_align(gt_masks_th[:, None, :, :], rois, out_shape,
                            1.0, 0, 'avg', True).squeeze(1)
        if binarize:
            resized_masks = (targets >= 0.5)
        else:
            resized_masks = targets
    else:
        resized_masks = torch.empty(
            (0, *out_shape), dtype=bboxes.dtype, device=device)
    return resized_masks.to(dtype=bboxes.dtype)

def _do_paste_mask(masks, boxes, img_h, img_w, skip_empty=True):
    """Paste instance masks according to boxes.

    This implementation is modified from
    https://github.com/facebookresearch/detectron2/

    Args:
        masks (Tensor): N, 1, H, W
        boxes (Tensor): N, 4
        img_h (int): Height of the image to be pasted.
        img_w (int): Width of the image to be pasted.
        skip_empty (bool): Only paste masks within the region that
            tightly bound all boxes, and returns the results this region only.
            An important optimization for CPU.

    Returns:
        tuple: (Tensor, tuple). The first item is mask tensor, the second one
            is the slice object.
        If skip_empty == False, the whole image will be pasted. It will
            return a mask of shape (N, img_h, img_w) and an empty tuple.
        If skip_empty == True, only area around the mask will be pasted.
            A mask of shape (N, h', w') and its start and end coordinates
            in the original image will be returned.
    """
    # On GPU, paste all masks together (up to chunk size)
    # by using the entire image to sample the masks
    # Compared to pasting them one by one,
    # this has more operations but is faster on COCO-scale dataset.
    device = masks.device
    if skip_empty:
        x0_int, y0_int = torch.clamp(
            boxes.min(dim=0).values.floor()[:2] - 1,
            min=0).to(dtype=torch.int32)
        x1_int = torch.clamp(
            boxes[:, 2].max().ceil() + 1, max=img_w).to(dtype=torch.int32)
        y1_int = torch.clamp(
            boxes[:, 3].max().ceil() + 1, max=img_h).to(dtype=torch.int32)
    else:
        x0_int, y0_int = 0, 0
        x1_int, y1_int = img_w, img_h
    x0, y0, x1, y1 = torch.split(boxes, 1, dim=1)  # each is Nx1

    N = masks.shape[0]

    img_y = torch.arange(y0_int, y1_int, device=device).to(torch.float32) + 0.5
    img_x = torch.arange(x0_int, x1_int, device=device).to(torch.float32) + 0.5
    img_y = (img_y - y0) / (y1 - y0) * 2 - 1
    img_x = (img_x - x0) / (x1 - x0) * 2 - 1
    # img_x, img_y have shapes (N, w), (N, h)
    # IsInf op is not supported with ONNX<=1.7.0
    if not torch.onnx.is_in_onnx_export():
        if torch.isinf(img_x).any():
            inds = torch.where(torch.isinf(img_x))
            img_x[inds] = 0
        if torch.isinf(img_y).any():
            inds = torch.where(torch.isinf(img_y))
            img_y[inds] = 0

    gx = img_x[:, None, :].expand(N, img_y.size(1), img_x.size(1))
    gy = img_y[:, :, None].expand(N, img_y.size(1), img_x.size(1))
    grid = torch.stack([gx, gy], dim=3)

    img_masks = F.grid_sample(
        masks.to(dtype=torch.float32), grid, align_corners=False)

    if skip_empty:
        return img_masks[:, 0], (slice(y0_int, y1_int), slice(x0_int, x1_int))
    else:
        return img_masks[:, 0], ()


import numpy as np
import pandas as pd
import statsmodels.api as sm
from pandas.tseries.offsets import MonthEnd
from prettytable import PrettyTable, MARKDOWN
from sklearn.kernel_ridge import KernelRidge
from sklearn.linear_model import LassoCV, RidgeCV
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

from regression.regression_models import *
from utils.utils import Dataset, get_dataset

def get_regressors():
    return [
        'Lineare',
        'Lineare robusto (Huber)',
        'Lineare avanzato (Cook)',
        'Ridge',
        'Lasso',
        'Polinomiale (grado 2)',
        'Polinomiale (grado 3)',
        'Random Forest',
        'Gradient Boosting',
        'SVR (Kernel lineare)',
        'SVR (Kernel polinomiale)',
        'SVR (Kernel RBF)',
        'KernelRidge'
    ]

def get_regressors_smaller():
    return [
        'Lineare',
        'Lineare robusto (Huber)',
        'Lineare avanzato (Cook)',
        'Ridge',
        'Lasso',
        'Polinomiale (grado 2)',
        'Polinomiale (grado 3)',
        'Random Forest',
        'Gradient Boosting',
        'SVR (lineare)',
        'SVR (polinomiale)',
        'SVR (RBF)',
        'KernelRidge'
    ]

def avg(scores):
    return '%0.2f' % (sum(scores) / len(scores))

def make_avg(predictor, X, y, n=500):
    r2_scores, rmse_scores = [], []
    for _ in range(n):
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True)
        predictor.fit(X_train, y_train)
        r2_scores.append(predictor.score(X_test, y_test))
        rmse_scores.append(mean_squared_error(y_test, predictor.predict(X_test), squared=False))
    return avg(r2_scores), avg(rmse_scores)

def apply_linear_regression(X, y):
    return make_avg(get_linear_model(), X, y)

def apply_cook_regression(X, y):
    m = sm.OLS(y, sm.add_constant(X)).fit()
    infl = m.get_influence()
    soglia = 4 / len(X)
    (a, p) = infl.cooks_distance
    mask = a < soglia
    return make_avg(get_linear_model(), X[mask], y[mask])

def apply_huber_regression(X, y):
    return make_avg(get_huber_model(), X, y)

def apply_lasso_regression(X, y):
    lassoregcv = LassoCV(n_alphas=100, random_state=1)
    model = make_pipeline(StandardScaler(with_mean=False), lassoregcv)
    return make_avg(model, X, y)

def apply_ridge_regression(X, y):
    alpha_range = 10. ** np.arange(-2, 5)
    ridgereg = RidgeCV(alphas=alpha_range, scoring='neg_mean_squared_error')
    model = make_pipeline(StandardScaler(with_mean=False), ridgereg)
    return make_avg(model, X, y)

def apply_poly_regression(X, y):
    return make_avg(get_polynomial_model(), X, y)

def apply_poly_3_regression(X, y):
    m = make_pipeline(PolynomialFeatures(degree=3, include_bias=False), linear_model.LinearRegression(n_jobs=-1))
    return make_avg(m, X, y)

def apply_kridge_regression(X, y):
    kr = make_pipeline(StandardScaler(with_mean=False),
                       KernelRidge(alpha=1, kernel='poly', degree=2, gamma=1, coef0=1))
    return make_avg(kr, X, y)

def apply_random_forest_regression(X, y):
    return make_avg(get_random_forest_model(), X, y)

def apply_gradient_boosting_regression(X, y):
    return make_avg(get_gradient_boosting_model(), X, y)

def apply_svr_linear_regression(X, y):
    return make_avg(get_svr_linear_model(), X, y)

def apply_svr_polynomial_regression(X, y):
    return make_avg(get_svr_polynomial_model(), X, y)

def apply_rbf_polynomial_regression(X, y):
    return make_avg(get_svr_rbf_model(), X, y)

def evaluate(X, y):
    lr_score, lr_rmse = apply_linear_regression(X, y)
    huber_score, huber_rmse = apply_huber_regression(X, y)
    cook_score, cook_rmse = apply_cook_regression(X, y)

    ridge_score, ridge_rmse = apply_ridge_regression(X, y)
    lasso_score, lasso_rmse = apply_lasso_regression(X, y)
    kridge_score, kridge_rmse = apply_kridge_regression(X, y)

    poly_score, poly_rmse = apply_poly_regression(X, y)
    poly3_score, poly3_rmse = apply_poly_3_regression(X, y)
    rf_score, rf_rmse = apply_random_forest_regression(X, y)
    gb_score, gb_rmse = apply_gradient_boosting_regression(X, y)
    svr_lin_score, svr_lin_rmse = apply_svr_linear_regression(X, y)
    svr_poly_score, svr_poly_rmse = apply_svr_polynomial_regression(X, y)
    svr_rbf_score, svr_rbf_rmse = apply_rbf_polynomial_regression(X, y)

    r2_scores = [lr_score, huber_score, cook_score, ridge_score, lasso_score, poly_score, poly3_score, rf_score,
                 gb_score, svr_lin_score, svr_poly_score,
                 svr_rbf_score, kridge_score]
    rmse_scores = [lr_rmse, huber_rmse, cook_rmse, ridge_rmse, lasso_rmse, poly_rmse, poly3_rmse, rf_rmse, gb_rmse,
                   svr_lin_rmse, svr_poly_rmse,
                   svr_rbf_rmse, kridge_rmse]

    return r2_scores, rmse_scores

def print_annual_results(results, title):
    table = PrettyTable()
    # table.title = title
    table.add_column('Modello di regressione', get_regressors())
    table.add_column('R²', results[0])
    table.add_column('RMSE (µg/m³)', results[1])
    table.align = 'l'
    table.set_style(MARKDOWN)
    print(table)

def print_monthly_results(month_results, title):
    def construct_table(i):
        t = PrettyTable()
        # t.title = '{} | '.format('R²' if i == 0 else 'RMSE (µg/m³)') + title
        t.add_column('Modello', get_regressors_smaller())
        for res in month_results:
            if any(res['results'][i]):
                t.add_column(res['period'], res['results'][i])
        t.align = 'l'
        return t

    # R²
    table = construct_table(0)
    table.set_style(MARKDOWN)
    print(table)

    # RMSE
    table = construct_table(1)
    table.set_style(MARKDOWN)
    print(table)

def annual_summary(dataset, station, chemical):
    X = dataset['airqino_{}'.format(chemical)].values.reshape((-1, 1))
    y = dataset['arpat_{}'.format(chemical)].values
    results = evaluate(X, y)
    print_annual_results(results,
                         title='All year | {n} | {c} (n={l})'.format(c=chemical.upper(), n=station,
                                                                     l=str(len(dataset))))

def monthly_summary(dataset, station, chemical, is_24h=False):
    if chemical == 'no2':
        date_range = pd.date_range('2020-01-01', '2020-12-31', freq='MS')
    else:
        date_range = pd.date_range('2020-09-01', '2021-08-31', freq='MS')
    month_results = []
    for month in date_range:
        month_str = month.strftime('%b')
        month_start = month.strftime('%Y-%m-%d')
        month_end = (month + MonthEnd(1)).strftime('%Y-%m-%d')

        month_dataset = dataset.loc[month_start: month_end]
        threshold = 5 if is_24h else 70
        if month_dataset.empty or len(month_dataset.index) < threshold:
            month_results.append({
                'results': [[0 for _ in get_regressors()], [0 for _ in get_regressors()]],
                'period': month_str,
                'values_count': str(len(month_dataset.index))
            })
            continue

        X = month_dataset['airqino_{}'.format(chemical)].values.reshape((-1, 1))
        y = month_dataset['arpat_{}'.format(chemical)].values

        results = evaluate(X, y)
        month_results.append({'results': results, 'period': month_str, 'values_count': str(len(y))})

    print_monthly_results(month_results, title='Monthly results | {d} | {c}'.format(c=chemical.upper(), d=station))

if __name__ == '__main__':
    # SMART16 - NO2
    # dataset = get_dataset(Dataset.SMART16_NO2).loc['2020-01-18': '2020-12-31']
    # annual_summary(dataset=dataset, station='SMART16-CAPANNORI', chemical='no2')
    # monthly_summary(dataset=dataset, station='SMART16-CAPANNORI', chemical='no2')

    # SMART16_new - PM2.5
    # annual_summary(dataset=get_dataset(Dataset.SMART16_NEW_PM), station='SMART16_new-CAPANNORI', chemical='pm2.5')
    # monthly_summary(dataset=get_dataset(Dataset.SMART16_NEW_PM), station='SMART16_new-CAPANNORI', chemical='pm2.5')

    # SMART16_new - PM10
    # annual_summary(dataset=get_dataset(Dataset.SMART16_NEW_PM), station='SMART16_new-CAPANNORI', chemical='pm10')
    # monthly_summary(dataset=get_dataset(Dataset.SMART16_NEW_PM), station='SMART16_new-CAPANNORI', chemical='pm10')

    # SMART16_new - PM2.5 - 8H
    # annual_summary(get_dataset(Dataset.SMART16_NEW_PM_12H), 'SMART16_new-CAPANNORI-8h', 'pm2.5')
    # monthly_summary(get_dataset(Dataset.SMART16_NEW_PM_12H), 'SMART16_new-CAPANNORI-12h', 'pm2.5', is_24h=True)

    # SMART16_new - PM10 - 8H
    # annual_summary(get_dataset(Dataset.SMART16_NEW_PM_12H), 'SMART16_new-CAPANNORI-8h', 'pm10')
    monthly_summary(get_dataset(Dataset.SMART16_NEW_PM_12H), 'SMART16_new-CAPANNORI-8h', 'pm10', is_24h=True)


from data_objects.random_cycler import RandomCycler
from data_objects.utterance import Utterance
from pathlib import Path

"""Minimally altered code from https://github.com/Trebolium/Real-Time-Voice-Cloning/tree/master/encoder/data_objects"""

# Contains the set of utterances of a single speaker
class Speaker:
    def __init__(self, root: Path):
        self.root = root
        self.name = root.name
        self.utterances = None
        self.utterance_cycler = None

    def _load_utterances(self, num_feats):
        """ Utterance stores mel and wav paths, but does not make them npy objects until random_partial() is called"""
        spkr_uttrs_list = [f.name[:-4] for f in self.root.glob('*.npy')]
        self.utterances = [Utterance(self.root.joinpath(f+'.npy'), f+'.wav') for f in spkr_uttrs_list]
        self.utterance_cycler = RandomCycler(self.utterances)

    def random_partial(self, count, n_frames, num_feats):
        """
        Samples a batch of <count> unique partial utterances from the disk in a way that all
        utterances come up at least once every two cycles and in a random order every time.

        :param count: The number of partial utterances to sample from the set of utterances from
        that speaker. Utterances are guaranteed not to be repeated if <count> is not larger than
        the number of utterances available.
        :param n_frames: The number of frames in the partial utterance.
        :return: A list of tuples (utterance, frames, range) where utterance is an Utterance,
        frames are the frames of the partial utterances and range is the range of the partial
        utterance with regard to the complete utterance.
        """
        if self.utterances is None:
            self._load_utterances(num_feats)

        utterances = self.utterance_cycler.sample(count)
        """Utterance random__partial returns: (splice of numpy, (start/end values))"""
        a = [(u,) + u.random_partial(n_frames, num_feats) for u in utterances]

        """ a is a list of tuples (uttr objects, spliced uttr_features, start/end coords), size of count"""
        return a


"""
Author:    alberto.suarez@uam.es

Coauthors: joseantonio.alvarezo@estudiante.uam.es
           franciscojavier.saez@estudiante.uam.es

"""

import warnings
from abc import ABC, abstractmethod
from typing import Callable, Optional, Union, Type
from sklearn.gaussian_process.kernels import RBF

import matplotlib.pyplot as plt
import numpy as np
import scipy as sp

# needed for default implementation of set_params
from sklearn.base import BaseEstimator, TransformerMixin

class RandomFeaturesSampler(ABC, BaseEstimator, TransformerMixin):
    """Base class for random feature samplers."""

    def __init__(self, n_random_features: int) -> None:
        self.n_random_features = n_random_features
        self.w = None

    def _initialize_w(self, n_features: int) -> np.ndarray:
        pass

    @abstractmethod
    def fit(self, X: np.ndarray) -> np.ndarray:
        """Initialize w's for the random features.
        This should be implemented for each kernel."""
        pass

    def fit_transform(
        self, X: np.ndarray, X_prime: Optional[np.ndarray] = None
    ) -> np.ndarray:
        """Initialize  w's (fit) & compute random features (transform)."""
        n_features = np.shape(X)[1]
        self.fit(n_features)
        return self.transform(X)

    def transform(self, X: np.ndarray) -> np.ndarray:
        """Compute the random features.
        Assumes that the vector of w's has been initialized

        Parameters
        ----------
        X:
            Data matrix of shape (n_instances, n_features).

        Returns
        -------
        random_features:
            Array of shape (n_instances, n_random_features).
        """
        if self.w is None:
            raise ValueError("Use fit_transform to initialize w.")

        n_instances, n_features = np.shape(X)

        if np.shape(self.w)[1] != n_features:
            raise ValueError("Different # of features for X and w.")

        random_features = np.empty((n_instances, self.n_random_features))
        random_features[:, ::2] = np.cos(X @ self.w.T)
        random_features[:, 1::2] = np.sin(X @ self.w.T)

        norm_factor = np.sqrt(self.n_random_features // 2)
        random_features = random_features / norm_factor

        return random_features

class RandomFeaturesSamplerRBF(RandomFeaturesSampler):
    """Random Fourier Features for the RBF kernel."""

    def __init__(self, sigma: float = 1.0, n_random_features: int = 100) -> None:

        self.sigma = sigma
        # Initialize number of random features in parent class
        super().__init__(n_random_features)

    def fit(self, n_features: int = 100) -> np.ndarray:
        """Initialize the w's for the random features."""
        w_mean = np.zeros(n_features)
        w_cov_matrix = self.sigma**2 * np.identity(n_features)

        rng = np.random.default_rng()
        self.w = rng.multivariate_normal(
            w_mean,
            w_cov_matrix,
            self.n_random_features // 2,
        )

class RandomFeaturesSamplerMatern(RandomFeaturesSampler):
    """Random Fourier Features for the Matern kernel."""

    def __init__(
        self, scale: float = 1.0, nu: float = 1.0, n_random_features: int = 100
    ) -> None:
        """The Fourier transform of the Matérn kernel is a
        Student's t distribution with twice the degrees of freedom.
        Ref. Chapter 4 of
        Carl Edward Rasmussen and Christopher K. I. Williams. 2005.
        Gaussian Processes for Machine Learning
        (Adaptive Computation and Machine Learning). The MIT Press.
        There is probably a mistake with the scale factor.
        """

        # Changed variables since they CANNNOT be modified due to sklearn GridSearch
        # self.nu = 2.0 * nu
        self.nu = nu
        # Changed name from original's author name due to incompatibility with sklearn
        self.scale = scale

        super().__init__(n_random_features)
        self.w = None

    def fit(self, n_features: int) -> np.ndarray:
        """Compute w's for random Matérn features."""
        # Scale of the Fourier tranform of the kernel
        w_mean = np.zeros(n_features)
        w_cov_matrix = self.scale**2 * np.identity(n_features)

        self.w = random_multivariate_student_t(
            w_mean,
            w_cov_matrix,
            self.nu,
            self.n_random_features // 2,
        )

def random_multivariate_student_t(
    mean: np.ndarray,
    cov_matrix: np.ndarray,
    degrees_of_freedom: float,
    n_samples: int,
) -> np.ndarray:
    """Generate samples from a multivariate Student's t.
    https://en.wikipedia.org/wiki/Multivariate_t-distribution#Definition
    """

    # Dimensions of multivariate Student's t distribution.
    D = len(mean)

    rng = np.random.default_rng()
    x = rng.chisquare(degrees_of_freedom, n_samples) / degrees_of_freedom

    Z = rng.multivariate_normal(
        np.zeros(D),
        cov_matrix,
        n_samples,
    )

    X = mean + Z / np.sqrt(x)[:, np.newaxis]
    return X

class NystroemFeaturesSampler(BaseEstimator, TransformerMixin):
    """Sample Nystroem features."""

    def __init__(
        self,
        kernel: Callable[[np.ndarray, np.ndarray], np.ndarray] = RBF(),
        n_random_features: int = 100,
    ) -> None:
        # _kernel -> kernel due to SKlearn compatibility
        self.kernel = kernel
        self.component_indices_ = None
        # J
        self._X_reduced = None
        # W
        self._reduced_kernel_matrix = None
        # (W+)^1/2
        self._sqrtm_pinv_reduced_kernel_matrix = None
        # Needed for compatibility
        self.n_random_features = n_random_features

    def fit(
        self, X: np.ndarray, y: Optional[np.ndarray] = None  # Compatibility
    ) -> np.ndarray:
        """Precompute auxiliary quantities for Nystroem features."""
        n_instances = len(X)
        # Check dimensions to avoid selecting more features than
        # possible
        n_random_features = self.n_random_features
        if self.n_random_features > n_instances:
            n_random_features = n_instances

        # Sample subset of training instances.
        rng = np.random.default_rng()
        self.component_indices_ = rng.choice(
            range(n_instances),
            size=n_random_features,
            replace=False,
        )

        self._X_reduced = X[self.component_indices_, :]

        # Compute reduced kernel matrix.
        self._reduced_kernel_matrix = self.kernel(self._X_reduced, self._X_reduced)
        self._reduced_kernel_matrix = (
            self._reduced_kernel_matrix + self._reduced_kernel_matrix.T
        ) / 2.0  # enforce symmetry of kernel matrix

        # Compute auxiliary quantities.
        self._sqrtm_pinv_reduced_kernel_matrix = sp.linalg.sqrtm(
            np.linalg.pinv(self._reduced_kernel_matrix, rcond=1.0e-6, hermitian=True)
        )

        # Check that complex part is negligible and eliminate it
        if np.iscomplexobj(self._sqrtm_pinv_reduced_kernel_matrix):
            threshold_imaginary_part = 1.0e-6
            max_imaginary_part = np.max(
                np.abs(np.imag(self._sqrtm_pinv_reduced_kernel_matrix))
            )
            # if max_imaginary_part > threshold_imaginary_part:
            # warnings.warn("Maximum imaginary part is {}".format(max_imaginary_part))

            self._sqrtm_pinv_reduced_kernel_matrix = np.real(
                self._sqrtm_pinv_reduced_kernel_matrix
            )

    def approximate_kernel_matrix(
        self,
        X: np.ndarray,
        # Needed for sklearn compatibility
        X_prime: Optional[np.ndarray] = None,
    ) -> np.ndarray:
        """Approximate the kernel matrix using Nystroem features."""

        X_features = self.fit_transform(X)
        return X_features @ X_features.T

    def fit_transform(
        self,
        X: np.ndarray,
        X_prime: Optional[np.ndarray] = None,
    ) -> np.ndarray:
        """Compute Nyström features."""
        self.fit(X)
        return self.transform(X)

    def transform(self, X_prime: np.ndarray) -> np.ndarray:
        """Compute Nystroem features with precomputed quantities."""
        J = self.kernel(X_prime, self._X_reduced)
        return J @ self._sqrtm_pinv_reduced_kernel_matrix

def demo_kernel_approximation_features(
    X: np.ndarray,
    kernel: Callable[[np.ndarray, np.ndarray], np.ndarray],
    features_sampler_class: Union[
        Type[RandomFeaturesSampler], Type[NystroemFeaturesSampler]
    ],
    features_sampler_kwargs: np.ndarray,
    n_features: np.array,
) -> None:
    """Kernel approximation using random sampled features.
    Either RFF or Nyström features."""
    n_plots = len(n_features) + 1
    fig, axes = plt.subplots(1, n_plots)
    fig.set_size_inches(15, 4)
    font = {"fontname": "arial", "fontsize": 18}

    kernel_matrix = kernel(X, X)
    axes[0].imshow(kernel_matrix, cmap=plt.cm.Blues)
    axes[0].set_title("Exact kernel", **font)
    axes[0].set_xticks([])
    axes[0].set_yticks([])

    for n_f, ax in zip(n_features, axes[1:]):
        print("# of features = ", n_f)

        features_sampler = features_sampler_class(
            **features_sampler_kwargs, n_random_features=n_f
        )

        X_features = features_sampler.fit_transform(X)
        kernel_matrix_approx = X_features @ X_features.T

        ax.imshow(kernel_matrix_approx, cmap=plt.cm.Blues)

        err_approx = kernel_matrix - kernel_matrix_approx
        err_mean = np.mean(np.abs(err_approx))
        err_max = np.max(np.abs(err_approx))

        ax.set_xlabel(
            "err (mean) = {:.4f} \n err (max) = {:.4f}".format(err_mean, err_max),
            **font
        )

        ax.set_title("{} features".format(n_f), **font)

        ax.set_xticks([])
        ax.set_yticks([])
        plt.tight_layout()
    plt.show()

def plot_kernel_error(
    X: np.ndarray,
    kernel: Callable[[np.ndarray, np.ndarray], np.ndarray],
    features_sampler_class: Union[
        Type[RandomFeaturesSampler], Type[NystroemFeaturesSampler]
    ],
    features_sampler_kwargs: np.ndarray,
    n_features: np.ndarray,
    kernel_name: str,
) -> None:
    # Initialize variables
    kernel_matrix = kernel(X, X)
    errors = np.array([], dtype=float)

    for n_f in n_features:
        # Create sampler
        features_sampler = features_sampler_class(
            **features_sampler_kwargs, n_random_features=n_f
        )

        # Compute approximation
        X_features = features_sampler.fit_transform(X)
        kernel_matrix_approx = X_features @ X_features.T

        # Compute error
        mean_error = np.mean(np.abs(kernel_matrix - kernel_matrix_approx))
        errors = np.append(errors, mean_error)

    # Plotting
    _, ax = plt.subplots(1, 1, figsize=(10, 6))
    font = {"fontname": "arial", "fontsize": 18}
    ax.plot(n_features, errors, color="deepskyblue", label=r"kernel error")
    ax.set_title("{} kernel error study".format(kernel_name), **font)

if __name__ == "__main__":

    """
    import matplotlib.pyplot as plt
    import numpy as np
    from sklearn import datasets, svm
    from sklearn.kernel_approximation import RBFSampler
    from sklearn.metrics.pairwise import rbf_kernel

    import kernel_approximation as ka

    # A not so simple 2 D problem
    X, Y = datasets.make_moons(n_samples=100, noise=0.3, random_state=0)

    # Compute grid of points for plotting the decision regions
    grid_x, grid_y = np.meshgrid(
        np.linspace(-3, 3, 50),
        np.linspace(-3, 3, 50),
    )

    grid_X = np.c_[grid_x.ravel(), grid_y.ravel()]

    gamma = 0.5
    # Kernel matrix
    def kernel(X, Y):
        return rbf_kernel(X, Y, gamma=gamma)

    n_nystroem_features = 20

    nystroem_sampler = NystroemFeaturesSampler(kernel)
    nystroem_features = nystroem_sampler.fit_transform(X)
    nystroem_features_grid = nystroem_sampler.transform(grid_X)

    clf = svm.SVC(kernel='linear')
    # clf = svm.NuSVC(gamma='auto')
    clf.fit(nystroem_features, Y)

    """
    import matplotlib.pyplot as plt
    import numpy as np
    from sklearn import datasets
    from sklearn.gaussian_process.kernels import Matern
    from sklearn.kernel_approximation import RBFSampler
    from sklearn.metrics.pairwise import rbf_kernel

    # 3-D data
    n_instances = 1000
    X, t = datasets.make_s_curve(n_instances, noise=0.1)
    X = X[np.argsort(t)]

    # 2-D data
    # X, y = datasets.make_moons(n_samples=400, noise=.05)
    # X = X[np.argsort(y)]

    # Reshape if necessary
    if X.ndim == 1:
        X = X[:, np.newaxis]

    # Kernel parameters
    sigma = 1.0
    gamma = 1.0 / (2.0 * sigma**2)

    n_nystroem_features = [10, 100, 1000]

    # Kernel function
    def kernel(X, Y):
        return rbf_kernel(X, Y, gamma=gamma)

    nystroem_features = NystroemFeaturesSampler(kernel)

    demo_kernel_approximation_features(
        X,
        kernel,
        nystroem_features,
        n_nystroem_features,
    )


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import string
import random
import time
path = "D:\chromedriver.exe"
driver = webdriver.Chrome(path)
print("Opening up the browser")
driver.get("https://prnt.sc/")
print("Preparing cookies...")
driver.find_element_by_css_selector('.css-47sehv').click()
time.sleep(2)
while True:
    rastgele = ''.join(random.choices(string.ascii_lowercase + string.digits, k = 6))
    site = str(f'http://prnt.sc/{rastgele}')
    time.sleep(1)
    print("Accessing this site: "+ site)
    driver.get(site)
    time.sleep(0.5)
    print("Locating image...")
    time.sleep(2)
    filename = 'result'+rastgele+'.png'
    try:
        x = driver.find_element_by_xpath('//*[@id="screenshot-image"]')
        print("Downloading image...")
        print(x)
        with open(filename, 'wb') as file:
            file.write(driver.find_element_by_xpath('//*[@id="screenshot-image"]').screenshot_as_png)
            print("File successfully downloaded! File name : " + filename)
    except:
        print("Image not found, going to the next link")


from sklearn.svm import LinearSVC
import metodos as m

def ObtenerHiperParametros(x_train, y_train, x_test, y_test):
    parametros = [
        { 'penalty': ['l1'], 'C': [1, 10, 100], 'dual': [False], 'class_weight': [{1:4}, {1:5}] }
    ]
    medida = 'recall'

    return m.GridSearch(LinearSVC(), parametros, medida, x_train, y_train, x_test, y_test)

def Entrenar(x_train, y_train, parametros):
    # Después de aplicar Grid Search de determinaron los siguiente parámetros
    # {'C': 1, 'class_weight': {1: 5}, 'dual': False, 'penalty': 'l1'}

    modelo = LinearSVC(C=1, penalty='l1', dual=False, class_weight={1:5})
    modelo.fit(x_train, y_train)
    return modelo


from graphviz import Digraph as DotGraph

MAX_EDGES = 2000

def gshow(g, attr=None, file_name=None, view=False):
    if g is None: return

    """ shows a networx DiGraph g
        using graphviz
        it could become slow on large graphs (above MAX_EDGES)
    """
    ecount = g.number_of_edges()
    if ecount > MAX_EDGES:
        print('GRAPH TOO BIG TO SHOW, EDGES=', ecount)
        return
    dot = DotGraph()
    for e in gen_dot_edges(g, attr=attr):
        f, t, w = e
        dot.edge(f, t, label=w)
    print('generated:', file_name, 'edges:', ecount)
    dot.render(file_name, view=view)

def gen_dot_edges(g, attr=None):
    for e in g.edges():
        f, t = e
        if not attr:
            w = ''
        else:
            w = g[f][t].get(attr)
            if not w: w = ''
        if not isinstance(f, str): f = "#" + str(f)
        if not isinstance(t, str): t = "#" + str(t)
        f = f.replace(':', '.')
        t = t.replace(':', '.')
        w = str(w)
        yield (f, t, w)

def xshow(gs, attr=None, file_name=None, view=False):
    """ shows a sequence of (possibly originating from the same,
       via a transformation) displayed together, left to right
    """
    dot = DotGraph()
    ecount = 0
    for i, g in enumerate(gs):
        k = g.number_of_edges()
        ecount += k
        if ecount > MAX_EDGES:
            print('GRAPH CHAIN TOO BIG TO SHOW, EDGES=', ecount)
            return
        for f, t, w in gen_dot_edges(g, attr=attr):
            mark = "@" + str(i)
            dot.edge(f + mark, t + mark, label=w)
    print('generated:', file_name, 'edges:', ecount)
    dot.render(file_name, view=view)


import os
from PIL import Image
import torchvision
import torch, cv2, math, random
import numpy as np

device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
device_id = [0]
IMG_EXTENSIONS = ['jpg', 'jpeg', 'png', 'ppm', 'bmp', 'pgm']

def mkdir(path):
    if not os.path.exists(path):
        os.makedirs(path)

def pil_loader(path, mode='RGB'):
    """
    open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835)
    :param path: image path
    :return: PIL.Image
    """
    assert _is_image_file(path), "%s is not an image" % path
    with open(path, 'rb') as f:
        with Image.open(f) as img:
            return img.convert(mode)

def calculate_RF(model):
    layers = getLayers(model)
    r = 1
    for layer in layers[::-1]:
        if isinstance(layer, torch.nn.Conv2d):
            kernel = layer.kernel_size[0]
            padding = layer.padding[0]
            stride = layer.stride[0]
            r = stride * r + (kernel - stride)
    return r

def getLayers(model):
    """
    get each layer's name and its module
    :param model:
    :return: each layer's name and its module
    """
    layers = []

    def unfoldLayer(model):
        """
        unfold each layer
        :param model: the given model or a single layer
        :param root: root name
        :return:
        """

        # get all layers of the model
        layer_list = list(model.named_children())
        for item in layer_list:
            module = item[1]
            sublayer = list(module.named_children())
            sublayer_num = len(sublayer)

            # if current layer contains sublayers, add current layer name on its sublayers
            if sublayer_num == 0:
                layers.append(module)
            # if current layer contains sublayers, unfold them
            elif isinstance(module, torch.nn.Module):
                unfoldLayer(module)

    unfoldLayer(model)
    return layers

def load_as_tensor(path, mode='RGB'):
    """
    Load image to tensor
    :param path: image path
    :param mode: 'Y' returns 1 channel tensor, 'RGB' returns 3 channels, 'RGBA' returns 4 channels, 'YCbCr' returns 3 channels
    :return: 3D tensor
    """
    if mode != 'Y':
        return PIL2Tensor(pil_loader(path, mode=mode))
    else:
        return PIL2Tensor(pil_loader(path, mode='YCbCr'))[:1]

def PIL2Tensor(pil_image):
    return torchvision.transforms.functional.to_tensor(pil_image)

def Tensor2PIL(tensor_image, mode='RGB'):
    if len(tensor_image.size()) == 4 and tensor_image.size()[0] == 1:
        tensor_image = tensor_image.view(tensor_image.size()[1:])
    return torchvision.transforms.functional.to_pil_image(tensor_image.detach().cpu(), mode=mode)

def _is_image_file(filename):
    """
    judge if the file is an image file
    :param filename: path
    :return: bool of judgement
    """
    filename_lower = filename.lower()
    return any(filename_lower.endswith(ext) for ext in IMG_EXTENSIONS)

def image_files(path):
    """
    return list of images in the path
    :param path: path to Data Folder, absolute path
    :return: 1D list of image files absolute path
    """
    abs_path = os.path.abspath(path)
    image_files = os.listdir(abs_path)
    for i in range(len(image_files)):
        if (not os.path.isdir(image_files[i])) and (_is_image_file(image_files[i])):
            image_files[i] = os.path.join(abs_path, image_files[i])
    return image_files

def split_to_batches(l, n):
    for i in range(0, len(l), n):
        yield l[i:i + n]

def _sigmoid_to_tanh(x):
    """
    range [0, 1] to range [-1, 1]
    :param x: tensor type
    :return: tensor
    """
    return (x - 0.5) * 2.

def _tanh_to_sigmoid(x):
    """
    range [-1, 1] to range [0, 1]
    :param x:
    :return:
    """
    return x * 0.5 + 0.5

def _add_batch_one(tensor):
    """
    Return a tensor with size (1, ) + tensor.size
    :param tensor: 2D or 3D tensor
    :return: 3D or 4D tensor
    """
    return tensor.view((1, ) + tensor.size())

def _remove_batch(tensor):
    """
    Return a tensor with size tensor.size()[1:]
    :param tensor: 3D or 4D tensor
    :return: 2D or 3D tensor
    """
    return tensor.view(tensor.size()[1:])

def mod_crop(tensor, scale=4):
    B, C, H, W = tensor.shape
    return tensor[:, :, :H-H % scale, :W-W % scale]

def isotropic_gaussian_kernel(l, sigma, epsilon=1e-5):
    ax = np.arange(-l // 2 + 1., l // 2 + 1.)
    xx, yy = np.meshgrid(ax, ax)
    kernel = np.exp(-(xx ** 2 + yy ** 2) / (2. * (sigma + epsilon) ** 2))
    return kernel / np.sum(kernel)

def prepare_images(hr_path, scale=4):
    hr_pil = Image.open(hr_path)
    sizex, sizey = hr_pil.size
    hr_pil = hr_pil.crop((0, 0, sizex - sizex % scale, sizey - sizey % scale))
    sizex, sizey = hr_pil.size
    lr_pil = hr_pil.resize((sizex // scale, sizey // scale), Image.BICUBIC)
    return lr_pil, hr_pil

def same_seeds(seed = 2022):
    random.seed(seed)
    np.random.seed(seed)  # 保证后续使用random函数时，产生固定的随机数
    torch.manual_seed(seed)  # 固定随机种子（CPU）
    # if torch.cuda.is_available():  # 固定随机种子（GPU)
    torch.cuda.manual_seed(seed)  # 为当前GPU设置
    torch.cuda.manual_seed_all(seed)  # 为所有GPU设置

    torch.use_deterministic_algorithms(True)
    torch.backends.cudnn.enabled = False
    torch.backends.cudnn.benchmark = False  # GPU、网络结构固定，可设置为True
    torch.backends.cudnn.deterministic = True  # 固定网络结构
    os.environ['PYTHONHASHSEED'] = str(seed)
    os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8'

def post_process(input):
    out = torch.clamp(input, min=0., max=1.)
    out = np.moveaxis(torch.squeeze(out,0).detach().cpu().numpy(), 0, 2)
    out = out * 255
    out = out.astype(np.uint8)
    return out

def calculate_psnr(img1, img2):
    # img1 and img2 have range [0, 255]
    img1 = img1.astype(np.float64)
    img2 = img2.astype(np.float64)
    mse = np.mean((img1 - img2) ** 2)
    if mse == 0:
        return float("inf")
    return 20 * math.log10(255.0 / math.sqrt(mse))

def ssim(img1, img2):
    C1 = (0.01 * 255) ** 2
    C2 = (0.03 * 255) ** 2

    img1 = img1.astype(np.float64)
    img2 = img2.astype(np.float64)
    kernel = cv2.getGaussianKernel(11, 1.5)
    window = np.outer(kernel, kernel.transpose())

    mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5]  # valid
    mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
    mu1_sq = mu1 ** 2
    mu2_sq = mu2 ** 2
    mu1_mu2 = mu1 * mu2
    sigma1_sq = cv2.filter2D(img1 ** 2, -1, window)[5:-5, 5:-5] - mu1_sq
    sigma2_sq = cv2.filter2D(img2 ** 2, -1, window)[5:-5, 5:-5] - mu2_sq
    sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2

    ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / (
        (mu1_sq + mu2_sq + C1) * (sigma1_sq + sigma2_sq + C2)
    )
    return ssim_map.mean()

def calculate_ssim(img1, img2):
    """calculate SSIM
    the same outputs as MATLAB's
    img1, img2: [0, 255]
    """
    if not img1.shape == img2.shape:
        raise ValueError("Input images must have the same dimensions.")
    if img1.ndim == 2:
        return ssim(img1, img2)
    elif img1.ndim == 3:
        if img1.shape[2] == 3:
            ssims = []
            for i in range(3):
                ssims.append(ssim(img1, img2))
            return np.array(ssims).mean()
        elif img1.shape[2] == 1:
            return ssim(np.squeeze(img1), np.squeeze(img2))
    else:
        raise ValueError("Wrong input image dimensions.")

# def calculate_psnr(img1, img2, border=0):
#     # img1 and img2 have range [0, 255]
#     #img1 = img1.squeeze()
#     #img2 = img2.squeeze()
#     if not img1.shape == img2.shape:
#         raise ValueError('Input images must have the same dimensions.')
#     h, w = img1.shape[:2]
#     img1 = img1[border:h-border, border:w-border]
#     img2 = img2[border:h-border, border:w-border]
#
#     img1 = img1.astype(np.float64)
#     img2 = img2.astype(np.float64)
#     mse = np.mean((img1 - img2)**2)
#     if mse == 0:
#         return float('inf')
#     return 20 * math.log10(255.0 / math.sqrt(mse))
#
#
# # --------------------------------------------
# # SSIM
# # --------------------------------------------
# def calculate_ssim(img1, img2, border=0):
#     '''calculate SSIM
#     the same outputs as MATLAB's
#     img1, img2: [0, 255]
#     '''
#     #img1 = img1.squeeze()
#     #img2 = img2.squeeze()
#     if not img1.shape == img2.shape:
#         raise ValueError('Input images must have the same dimensions.')
#     h, w = img1.shape[:2]
#     img1 = img1[border:h-border, border:w-border]
#     img2 = img2[border:h-border, border:w-border]
#
#     if img1.ndim == 2:
#         return ssim(img1, img2)
#     elif img1.ndim == 3:
#         if img1.shape[2] == 3:
#             ssims = []
#             for i in range(3):
#                 ssims.append(ssim(img1[:,:,i], img2[:,:,i]))
#             return np.array(ssims).mean()
#         elif img1.shape[2] == 1:
#             return ssim(np.squeeze(img1), np.squeeze(img2))
#     else:
#         raise ValueError('Wrong input image dimensions.')
#
#
# def ssim(img1, img2):
#     C1 = (0.01 * 255)**2
#     C2 = (0.03 * 255)**2
#
#     img1 = img1.astype(np.float64)
#     img2 = img2.astype(np.float64)
#     kernel = cv2.getGaussianKernel(11, 1.5)
#     window = np.outer(kernel, kernel.transpose())
#
#     mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5]  # valid
#     mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
#     mu1_sq = mu1**2
#     mu2_sq = mu2**2
#     mu1_mu2 = mu1 * mu2
#     sigma1_sq = cv2.filter2D(img1**2, -1, window)[5:-5, 5:-5] - mu1_sq
#     sigma2_sq = cv2.filter2D(img2**2, -1, window)[5:-5, 5:-5] - mu2_sq
#     sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
#
#     ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
#                                                             (sigma1_sq + sigma2_sq + C2))
#     return ssim_map.mean()

def cv2_to_pil(img):
    image = Image.fromarray(cv2.cvtColor(img.astype(np.uint8), cv2.COLOR_BGR2RGB))
    return image

def pil_to_cv2(img):
    image = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
    return image


from random import randint, choice
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%d/%m/%Y")
file_name = "math_game_log.txt"

# Functions

def append_wrong_answer(answer,operation,file_name=file_name):
    with open(file_name, 'a') as f:
        f.write(f'\tExpression: {operation}, User Input: {answer}, '\
            f'Expected: {eval(operation)}\n')

def check_if_int(answer):
    '''Checks if the input is an integer. '''
    try:
        int(answer)
    except ValueError:
        print('Your answer cannot contain anything other than numbers. Please try again: ')
        return False

    else:
        return True

def addition(a, b):
    operation = f"{a} + {b}"
    answer = input(operation + ' = ')

    while check_if_int(answer) == False:
        answer = input ('\n'+operation + ' = ')

    if eval(operation) == int(answer):
        return('Excellent!')

    else:
        append_wrong_answer(answer, operation)
        return(f'Incorrect. The correct answer is {eval(operation)}.')

def subtraction(a, b):
    if difficulty == 'easy':
        while b>a:
            x1,x2 = difficulty_lvls['easy'][0][0], difficulty_lvls['easy'][0][-1]
            a, b= randint(x1, x2), randint(x1, x2)

    operation = f"{a} - {b}"
    answer = input (operation + ' = ')

    while check_if_int(answer) == False:
        answer = input ('\n'+operation + ' = ')

    if eval(operation) == int(answer):
        return(f'Correct! Well done, {name}.')
    else:
        append_wrong_answer(answer, operation)
        return(f'Incorrect. The correct answer is {eval(operation)}.')

def multiplication(a, b):
    operation = f"{a} * {b}"
    answer = input(operation + ' = ')

    while check_if_int(answer) == False:
        answer = input ('\n'+operation + ' = ')
    if eval(operation) == int(answer):
        return(f'Good job, {name}!')
    else:
        append_wrong_answer(answer, operation)
        return(f'Incorrect. The correct answer is {eval(operation)}.')

#                           *Actual game:*

"""For the dictionary below:
The first element of each list is the smallest possible number to be used
the second is the largest possible number. The first list is for the addition and
subtraction questionss, the second is for the multiplication questions."""

difficulty_lvls = {
    'easy': [[5, 30], [2, 11]],
    'intermediate': [[10, 50], [3, 12]],
    'difficult':[[12,100],[4, 17]],
    'expert': [[30, 2000], [6, 30]],
    }

name = input('Please enter your name: ').title()
difficulty = input("Difficulty level (easy, intermediate, difficult, expert): ")
while difficulty not in difficulty_lvls:
    difficulty = input("\nYou chose a non-existent level."\
        "Please try again(easy, intermediate, difficult, expert): ")

#     while False
# while difficulty in difficulty_lvls == False:
    # difficulty = input("\nYou chose a non-existent level."\
    #     "Please try again(easy, intermediate, difficult, expert): ")

with open(file_name) as f:
    contents = f.read()

with open(file_name, 'a') as f:
    if current_time not in contents:
        f.write(current_time + ': \n')
    f.write('\n'+name+':')
    f.write('\n\t'+difficulty.title()+'\n')

lst = ['addition', 'subtraction', 'multiplication']

greeting = (f"\nHello, {name}. You'll be given a chance to exit this program "\
" and level up after every 5 attempts. Let's begin! \n")
print(greeting)

i = 0
while True:

    if i%5==0:
        d=difficulty
        x1,x2=difficulty_lvls[d][0][0], difficulty_lvls[d][0][-1]
        y1,y2=difficulty_lvls[d][-1][0], difficulty_lvls[d][-1][-1]
# The issue here is that randint does not accept ranges
    a1,a2 = randint(x1, x2), randint(x1, x2)
    m1,m2 = randint(y1, y2), randint(y1, y2)

    '''Randomizer'''
    chosen = choice(lst)

    if chosen == lst[0]:
        print(addition(a1, a2))
    elif chosen == lst[1]:
        print(subtraction(a1, a2))
    else:
        print(multiplication(m1, m2))

    i+=1

    if i %5 == 0:
        print('\n')
        answer = input(f'Would you like to continue, {name}? (yes/no) ')
        if answer == 'no':
            break
# Here we ask if the user wants to go on to the next level. We must first
# check if the user is not currently at the last level as there is no lvl to lvl up to.
        if difficulty in list(difficulty_lvls.keys())[:-1]:
            lvl_up = input("Would you like to advance to the next level? (yes/no) ")
            if lvl_up == 'yes':
                next_index = list(difficulty_lvls.keys()).index(difficulty)+1
                difficulty = list(difficulty_lvls.keys())[next_index]
                print(f"\nNew difficulty level: {difficulty.title()}\n")
                with open(file_name, 'a') as f:
                    f.write('\n\t'+difficulty.title()+'\n')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import re
import sys
import argparse
import numpy as np
from collections import defaultdict,Counter
__author__ = 'menghao'
__mail__ = 'haomeng@genome.cn'

bindir = os.path.abspath(os.path.dirname(__file__))
pat1 = re.compile('^\s*$')

def parser_fasta(fasta):
    seq = []
    Dict = defaultdict(list)
    with open(fasta) as IN:
        for line in IN:
            if line.startswith('>'):
                name = line.rstrip()[1:]
                continue
            Dict[name] += line.rstrip()
    for i in Dict:
        seq.append([j for j in Dict[i]])
    return np.array(seq)

def main():
    parser = argparse.ArgumentParser(usage='Consensus_and_Profile',
                                     description=__doc__,
                                     formatter_class=argparse.RawDescriptionHelpFormatter,
                                     epilog='author:\t{0}\nmail:\t{1}'.format(__author__, __mail__))
    parser.add_argument('-i', '--input', help='input', dest='input', required=True)
    args = parser.parse_args()

    seq = parser_fasta(args.input)

    Dict = defaultdict(list)
    consensus = ''

    for i in range(seq.shape[1]):
        total = Counter(seq[:,i])
        consensus += total.most_common(1)[0][0]
        for c in ('A', 'C', 'T', 'G'):
            Dict[c].append(str(total[c]))

    print(consensus)

    for c in ('A', 'C', 'T', 'G'):
        print('{0}: {1}'.format(c,' '.join(Dict[c])))

if __name__ == "__main__":
    main()


from flask import Flask, request, jsonify
from models.db import db
from models.User_model import User
from backend.controller.extensions import bcrypt, jwt_manager, session
from datetime import datetime, timezone, timedelta
from flask_jwt_extended import get_jwt, create_access_token, get_jwt_identity
from flask_cors import CORS
import json

def create_app():
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SECRET_KEY'] = "215fb79f1848d253c541f30f2e83a86965d178fed3594e7adf4df128a90fb2633af7bbded04ff63f4214cb1d896cd2e119a9f6da64c26a74d283911c32fb5a4f"
    app.config['SESSION_TYPE'] = 'filesystem'
    app.config['JWT_SECRET_KEY'] = "06973e058893087d8aa8d73513c35254e097b25fe75131ad53dacf6e06296227e58955fad64d4d00862ac73a6d089ce7d422c017bab866eb8893be4540884d41"

    cors = CORS(app)

    with app.app_context():
        db.init_app(app)
        bcrypt.init_app(app)
        jwt_manager.init_app(app)
        session.init_app(app)

        @app.after_request
        def refresh_expiring_jwts(response):
            try:
                exp_timestamp = get_jwt()["exp"]
                now = datetime.now(timezone.utc)
                target_timestamp = datetime.timestamp(now + timedelta(minutes=30))
                if target_timestamp > exp_timestamp:
                    print(get_jwt_identity())
                    access_token = create_access_token(identity=get_jwt_identity())
                    data = response.get_json()
                    if type(data) is dict:
                        data["access_token"] = access_token
                        response.data = json.dumps(data)
                return response
            except (RuntimeError, KeyError):
                # Case where there is not a valid JWT. Just return the original respone
                return response

        @jwt_manager.user_lookup_loader
        def user_lookup_callback(_jwt_header, jwt_data):
            identity = jwt_data["sub"]
            return User.query.filter_by(email=identity).one_or_none()

        from routes.Container_routes import container_bp
        from routes.Auth_routes import auth_bp
        app.register_blueprint(container_bp, url_prefix='/api/v1/weblab')
        app.register_blueprint(auth_bp, url_prefix='/api/v1/auth')

        db.create_all()
    return app


import sys
from time import sleep

import pygame

from settings import Settings
import game_functions as gf
# from tetrominos import IShape
from tetrominos import IShape

def run_game():
    pygame.init()
    # Load game settings.
    settings = Settings()
    screen = pygame.display.set_mode(
        (settings.screen_width, settings.screen_height))
    pygame.display.set_caption(settings.title)

    # ishape = IShape(settings, 'I')
    ishape = IShape(settings)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    sys.exit()

        screen.fill(settings.color['white'])
        # Draw the grid lines.
        gf.show_grid(settings, screen)

        ishape.draw(screen)

        # ishape.draw(screen)
        # ishape.drop()
        # # ishape.move()
        ishape.rotate()
        sleep(1)
        pygame.display.flip()

if __name__ == '__main__':
    run_game()


import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import sys
import matplotlib.dates as mdates

fin = sys.argv[1]
fin_raw = sys.argv[2]
font = {'size': 14}
matplotlib.rc('font', **font)
data = pd.read_csv(fin, parse_dates=True, index_col=0)
data_raw = pd.read_csv(fin_raw, parse_dates=True, index_col=0)
fig, ax = plt.subplots(figsize=(14, 8))
ax.plot(data.index, data['load_kg'], 'k')
ax.plot(data_raw.index, data_raw['load_kg'], 'g')
plt.fill_between(data.index, ax.get_ylim()[0], data['load_kg'], color=(1, 0.2, 0.2, 0.2))
plt.minorticks_on()
fig.autofmt_xdate()
# Use a more precise date string for the x axis locations in the toolbar.
ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')
ax.grid(which='major', axis='both', linewidth=1.5, color='gray')
ax.xaxis.grid(True, 'minor', color='gray', alpha=0.3, ls='-', lw=1)
ax.yaxis.grid(True, 'minor', color='gray', alpha=0.3, ls='-', lw=1)
ax.set_xlabel('datetime')
ax.set_ylabel('load kg')
plt.grid('minor')
plt.tight_layout()
fout = fin.replace('.csv', '_withRaw.pdf')
plt.savefig(fout)
plt.show()


#!/usr/bin/python
import argparse
import json
import os
from os import listdir, path
import copy
from pathlib import Path
import re
import pandas as pd
import numpy as np
from bidict import bidict
from scipy import sparse
from sklearn.model_selection import cross_validate, StratifiedKFold
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import MultiLabelBinarizer

from echr.utils.folders import make_build_folder
from echr.utils.logger import getlogger
from echr.utils.cli import TAB
from rich.markdown import Markdown
from rich.console import Console
from rich.table import Table
from rich.progress import (
    Progress,
    BarColumn,
    TimeRemainingColumn,
)
from rich.panel import Panel
from rich.tree import Tree
from echr_experiments.config import ROUND_DIGITS, \
                                    SEED, \
                                    MULTICLASS_DESC_OUTPUT_FILE, \
                                    MULTICLASS_OUTPUT_FILE, \
                                    MULTICLASS_ARTICLES, \
                                    MULTICLASS_FLAVORS, \
                                    K_FOLD, \
                                    AS_TIME_SERIES, \
                                    MULTICLASS_CLASSIFIERS, \
                                    DEFAULT_FEATURE_THRESHOLD
from echr_experiments.format import format_filter_output, format_method_output
from echr_experiments.data import load_ECHR_instance, generate_datasets_descriptors
from echr_experiments.scorers import make_scorers, process_score, calculate_average_cm
from echr_experiments.utils import update_classifier_result, \
                                   update_dataset_filter_result, \
                                   update_dataset_metadata, \
                                   update_dataset_result, \
                                   update_article_desc

seed = SEED
result_file = MULTICLASS_OUTPUT_FILE
articles = MULTICLASS_ARTICLES
flavors = MULTICLASS_FLAVORS
k_fold = K_FOLD
as_time_series = AS_TIME_SERIES
feature_threshold = DEFAULT_FEATURE_THRESHOLD
classifiers = MULTICLASS_CLASSIFIERS

import warnings
from pandas.core.common import SettingWithCopyWarning

warnings.simplefilter(action="ignore", category=SettingWithCopyWarning)

log = getlogger()

def generate_outcomes_data(y_file, outcome_to_id, filter_threshold=100):
    # Generate hot-one outcome matrix
    with open(y_file) as file:
        f = lambda x: {x.split(':')[0]:x.split(':')[1]}
        outcomes = file.readlines()
        outcomes = pd.DataFrame(outcomes)
        outcomes[0] = outcomes[0].apply(lambda x: x.strip().split())
        outcomes['caseid'] = outcomes[0].apply(lambda x: x[0])
        outcomes[0] = outcomes[0].apply(lambda x: x[1])

    return outcomes

def map_outcome(art, x):
            if x[f'{art}:1'] == 1:
                return 1
            elif x[f'{art}:0'] == 1:
                return 0
            else:
                return -1

def load_dataset(X_file, min_threshold=0):
    with open(X_file) as file:
        f = lambda x: {x.split(':')[0]:x.split(':')[1]}
        X = file.readlines()
        X = pd.DataFrame(X)
        X[0] = X[0].apply(lambda x: sorted(x.strip().split()))
        #X['caseid'] = X[0].apply(lambda x: x[0])
        #X[0] = X[0].apply(lambda x: x[1:])

        # Generate hot-one outcome matrix
        mlb = MultiLabelBinarizer(sparse_output=True)
        X = X.join(
                    pd.DataFrame.sparse.from_spmatrix(
                        mlb.fit_transform(X.pop(0)),
                        index=X.index,
                        columns=mlb.classes_))
        return X

def run(console, build, force):
    __console = console
    global print
    print = __console.print

    outcomes_path = 'data/input/datasets/'
    raw_outcome_file = Path(outcomes_path) / 'outcomes.txt'
    outcome_matrix_file = Path(outcomes_path) / 'outcomes_matrix.csv'

    print(Markdown("- **Prepare outcome matrix**"))
    OUTCOME_TO_ID =  'data/input/datasets/outcomes_variables.json'
    with open(OUTCOME_TO_ID, 'r') as f:
        outcome_to_id = json.load(f)

    if True: #not os.path.isfile(outcome_matrix_file) or force:
        print(TAB + '> Generate the outcome matrix [green][DONE]')
        outcomes_matrix = generate_outcomes_data(raw_outcome_file, outcome_to_id, filter_threshold=100)
        outcomes_matrix.to_csv(outcome_matrix_file)
    else:
        print(TAB + '> Load the outcome matrix [green][DONE]')
    outcome_matrix = pd.read_csv(outcome_matrix_file)

    # Class encoding
    le = LabelEncoder()
    le.fit(outcomes_matrix[0])
    mapping_class = dict(zip(le.classes_, le.transform(le.classes_)))
    outcomes_matrix['decision'] = le.transform(outcomes_matrix[0])
    outcomes_matrix['article'] = outcomes_matrix[0].apply(lambda x: x.split(':')[0])
    CM = []  # Confusion matrices

    count = outcomes_matrix['article'].value_counts()
    count = json.loads(count.to_json())

    count = {k:v for k,v in count.items() if v > 100}
    articles_to_keep = list(count.keys())

    outcomes_matrix = outcomes_matrix[outcomes_matrix['article'].isin(articles_to_keep)]
    le = LabelEncoder()
    le.fit(outcomes_matrix[0])
    mapping_class = dict(zip(le.classes_, le.transform(le.classes_)))

    c_outcomes = bidict(outcome_to_id)
    metadata = json.loads(outcomes_matrix['article'].value_counts().to_json())
    metadata = {k:{'Size': v, 'Article': c_outcomes.inverse[int(k)] } for k,v in metadata.items()} # c_outcomes.inverse[int(k)]
    for art, mdata in metadata.items():
        mdata['Violation'] = outcomes_matrix[outcomes_matrix[0] == f'{art}:1'].shape[0]
        mdata['No-Violation'] = outcomes_matrix[outcomes_matrix[0] == f'{art}:0'].shape[0]
        mdata['Prevalence'] = mdata['Violation'] / (mdata['Violation'] + mdata['No-Violation'])

    update_article_desc('Multiclass', metadata, MULTICLASS_DESC_OUTPUT_FILE)
    print(TAB + '> Update dataset description [green][DONE]')

    print(Markdown("- **Experiment summary**"))
    FLAVORS = {'Descriptive only': 'descriptive.txt', 'Bag-of-Words only': 'BoW.txt', 'Descriptive and Bag-of-Words': 'descriptive+BoW.txt'}
    print(f"  | Flavors: {len(FLAVORS)}")
    print(f"  | Methods: {len(classifiers)}")
    print(f"  = {len(FLAVORS) * len(classifiers)} cross-validation procedures")
    print(f"  = Take some :coffee: or :tea: and  relax")

    try:
        f = open (result_file, "r")
        exp_results = json.loads(f.read())
        print(TAB + '> Load existing results [green][DONE]')
    except Exception as e:
        exp_results = {}
        print(TAB + '> No previous results [green][DONE]')

    table = Table(title="Cross-Validation Summary")

    table.add_column("Flavor", style="cyan", no_wrap=True)
    table.add_column("Method", justify="right", style="blue")
    table.add_column("Status", justify="right", style="green")

    for i, flavor in enumerate(FLAVORS.keys()):
            for k, method in enumerate(classifiers.keys()):
                dataset_name = f'Multiclass - {flavor}'
                status = exp_results.get(dataset_name, {}).get('methods', {}).get(method, None)
                status = '[green]DONE' if status else None
                table.add_row(flavor if k == 0 else None, method, status)

    print(table)

    for flavor, features_file in FLAVORS.items():
        print(Panel(f'[bold yellow] Cross-Validation Flavor {flavor.upper()}'), justify="center")

        print(Markdown("- **Prepare dataset**"))
        dataset_path = Path(outcomes_path) / features_file
        X = load_dataset(dataset_path)
        X = pd.DataFrame(X)
        X = X[X.index.isin(outcomes_matrix.index)]
        print(TAB + '> Load the dataset [green][DONE]')

        if flavor != 'Bag-of-Words':
            # Remove '0:'
            to_drop = [e for e in X.columns if e.startswith('0:')]
            X.drop(columns=to_drop, inplace=True)
            print(TAB + '> Drop unecessary columns [green][DONE]')

        print(Markdown(f"- **Cross-Validate**"))
        y = outcomes_matrix['decision']

        o = {'name': f'Multiclass - {flavor}'}
        dataset_name = o['name']

        if dataset_name not in exp_results:
            exp_results[dataset_name] = {}

        #format_filter_output(dataset_name, o)
        update_dataset_result(dataset_name, o, result_file)
        update_dataset_filter_result(dataset_name, o, result_file)

        metadata = exp_results.get(dataset_name, {}).get('filter', {})
        metadata['size'] = metadata.get('size', int(y.shape[0]))
        #metadata['violation'] = metadata.get('violation', int(y_art.sum()))
        #metadata['non_violation'] = metadata['size'] - metadata['violation']
        #metadata['prevalence'] = float(metadata['violation']) / metadata['size']

        update_dataset_metadata(dataset_name, metadata, result_file)
        print(TAB + '> Generate dataset metadata [green][DONE]')

        #if flavor == 'Descriptive only':
        #    update_article_desc(art, metadata, MULTICLASS_DESC_OUTPUT_FILE)
        #    print(TAB + '> Update dataset description [green][DONE]')

        CM = []
        for classifier_name, classifier in classifiers.items():
                    print(TAB + f'> [bold]{classifier_name}')
                    if exp_results.get(dataset_name, {}).get('methods', {}).get(classifier_name, None):
                        print(TAB + ' тоб Cross-Validation results already exist. [green][SKIP]')
                    else:
                        try:
                            scoring = make_scorers(multiclass=True, CM=CM)
                            cv = TimeSeriesSplit(n_splits=k_fold) if as_time_series \
                                else StratifiedKFold(n_splits=k_fold) #, random_state=seed)
                            #scores = cross_validate(classifier, X_art.to_numpy(), y_art.to_numpy(),
                            scores = cross_validate(classifier, X, y,
                                cv=cv,
                                scoring=scoring,
                                return_train_score=True,
                                verbose=10,
                                n_jobs=None, error_score='raise')
                            classifier_output = process_score(scores, scoring, seed, multilabel=True)
                            cm = calculate_average_cm(CM, train_score=True)
                            classifier_output['confusion_matrix'] = cm
                            classifier_output['confusion_matrix']['class_labels'] = list(le.classes_) #list(outcomes_matrix[0].value_counts().index) #list(le.classes_)
                            #format_method_output(classifier_name, classifier_output)
                            update_classifier_result(
                                dataset_name,
                                classifier_name,
                                classifier_output,
                                result_file
                            )
                            pass
                        except Exception as e:
                            print(e)

def main(args):
    console = Console(record=True)
    run(console, args.build, args.force)

def parse_args(parser):
    args = parser.parse_args()
    return args

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Multiclass experiments')
    parser.add_argument('--build', type=str, default="./build/echr_database/")
    parser.add_argument('-f', '--force', action='store_true')
    args = parse_args(parser)

    main(args)