import os, sys
import argparse
import json
import socket
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from parameter.private_config import *
from datetime import datetime

class Parameter:
    def __init__(self, config_path=None, debug=False, information=None):
        self.base_path = self.get_base_path()
        self.debug = debug
        self.experiment_target = EXPERIMENT_TARGET
        self.DEFAULT_CONFIGS = global_configs()
        self.arg_names = []
        self.host_name = 'localhost'
        self.ip = '127.0.0.1'
        self.exec_time = datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
        self.commit_id = self.get_commit_id()
        self.log_func = None
        self.json_name = 'parameter.json'
        self.txt_name = 'parameter.txt'
        self.information = information
        if config_path:
            self.config_path = config_path
        else:
            self.info('use default config path')
            self.config_path = osp.join(get_base_path(), 'parameter')
        self.info(f'json path is {os.path.join(self.config_path, self.json_name)}, '
                  f'txt path is {os.path.join(self.config_path, self.txt_name)}')
        if config_path:
            self.load_config()
        else:
            self.args = self.parse()
            self.apply_vars(self.args)

    def set_log_func(self, log_func):
        self.log_func = log_func

    def info(self, info):
        if self.log_func is not None:
            self.log_func(info)
        else:
            print(info)

    @staticmethod
    def get_base_path():
        return get_base_path()

    def set_config_path(self, config_path):
        self.config_path = config_path

    @staticmethod
    def important_configs():
        res = ['env_name', 'use_true_parameter', 'use_rmdm',
               'use_uposi', 'share_ep', "rnn_fix_length",
               'uniform_sample', 'enhance_ep', 'bottle_neck', 'stop_pg_for_ep', "ep_dim", 'seed']
        return res

    def apply_vars(self, args):
        for name in self.arg_names:
            setattr(self, name, getattr(args, name))

    def make_dict(self):
        res = {}
        for name in self.arg_names:
            res[name] = getattr(self, name)
        res['description'] = self.experiment_target
        res['exec_time'] = self.exec_time
        res['commit_id'] = self.commit_id
        return res

    def parse(self):
        parser = argparse.ArgumentParser(description=EXPERIMENT_TARGET)

        self.env_name = "Hopper-v2"
        parser.add_argument('--env_name', default=self.env_name, metavar='G',
                            help='name of the environment to run')
        self.register_param('env_name')

        self.model_path = ""
        parser.add_argument('--model_path', metavar='G',
                            help='path of pre-trained model')
        self.register_param("model_path")

        self.render = False
        parser.add_argument('--render', action='store_true', default=self.render,
                            help='render the environment')
        self.register_param("render")

        self.log_std = -1.5
        parser.add_argument('--log_std', type=float, default=self.log_std, metavar='G',
                            help='log std for the policy (default: -0.0)')
        self.register_param('log_std')

        self.gamma = 0.99
        parser.add_argument('--gamma', type=float, default=self.gamma, metavar='G',
                            help='discount factor (default: 0.99)')
        self.register_param('gamma')

        self.learning_rate = 3e-4
        parser.add_argument('--learning_rate', type=float, default=self.learning_rate, metavar='G',
                            help='learning rate (default: 3e-4)')
        self.register_param('learning_rate')

        self.value_learning_rate = 1e-3
        parser.add_argument('--value_learning_rate', type=float, default=self.value_learning_rate, metavar='G',
                            help='learning rate (default: 1e-3)')
        self.register_param('value_learning_rate')

        self.num_threads = 4
        parser.add_argument('--num_threads', type=int, default=self.num_threads, metavar='N',
                            help='number of threads for agent (default: 1)')
        self.register_param('num_threads')

        self.seed = 1
        parser.add_argument('--seed', type=int, default=self.seed, metavar='N',
                            help='random seed (default: 1)')
        self.register_param('seed')

        self.random_num = 4000
        parser.add_argument('--random_num', type=int, default=self.random_num, metavar='N',
                            help='sample random_num fully random samples,')
        self.register_param('random_num')

        self.start_train_num = 20000
        parser.add_argument('--start_train_num', type=int, default=self.start_train_num, metavar='N',
                            help='after reach start_train_num, training start')
        self.register_param('start_train_num')

        self.test_sample_num = 4000
        parser.add_argument('--test_sample_num', type=int, default=self.test_sample_num, metavar='N',
                            help='sample num in test phase')
        self.register_param('test_sample_num')

        self.sac_update_time = 1000
        parser.add_argument('--sac_update_time', type=int, default=self.sac_update_time, metavar='N',
                            help='update time after sampling a batch data')
        self.register_param('sac_update_time')

        self.sac_replay_size = 1e6
        parser.add_argument('--sac_replay_size', type=int, default=self.sac_replay_size, metavar='N',
                            help='update time after sampling a batch data')
        self.register_param('sac_replay_size')

        self.min_batch_size = 1200
        parser.add_argument('--min_batch_size', type=int, default=self.min_batch_size, metavar='N',
                            help='minimal sample number per iteration')
        self.register_param('min_batch_size')

        if FC_MODE:
            self.sac_mini_batch_size = 256
            parser.add_argument('--sac_mini_batch_size', type=int, default=self.sac_mini_batch_size, metavar='N',
                                help='update time after sampling a batch data')
            self.register_param('sac_mini_batch_size')

            self.sac_inner_iter_num = 1
            parser.add_argument('--sac_inner_iter_num', type=int, default=self.sac_inner_iter_num, metavar='N',
                                help='after sample several trajectories from replay buffer, '
                                     'sac_inner_iter_num mini-batch will be sampled from the batch, '
                                     'and model will be optimized for sac_inner_iter_num times.')
            self.register_param('sac_inner_iter_num')
        else:
            self.sac_mini_batch_size = 256
            parser.add_argument('--sac_mini_batch_size', type=int, default=self.sac_mini_batch_size, metavar='N',
                                help='sac_mini_batch_size trajectories will be sampled from the replay buffer.')
            self.register_param('sac_mini_batch_size')

            self.sac_inner_iter_num = 1
            parser.add_argument('--sac_inner_iter_num', type=int, default=self.sac_inner_iter_num, metavar='N',
                                help='after sample several trajectories from replay buffer, '
                                     'sac_inner_iter_num mini-batch will be sampled from the batch, '
                                     'and model will be optimized for sac_inner_iter_num times.')
            self.register_param('sac_inner_iter_num')

        self.rnn_sample_max_batch_size = 3e5
        parser.add_argument('--rnn_sample_max_batch_size', type=int, default=self.rnn_sample_max_batch_size, metavar='N',
                            help='max point num sampled from replay buffer per time')
        self.register_param('rnn_sample_max_batch_size')

        self.rnn_slice_num = 16
        parser.add_argument('--rnn_slice_num', type=int, default=self.rnn_slice_num, metavar='N',
                            help='gradient clip steps')
        self.register_param('rnn_slice_num')

        self.sac_tau = 0.995
        parser.add_argument('--sac_tau', type=float, default=self.sac_tau, metavar='N',
                            help='ratio of coping value net to target value net')
        self.register_param('sac_tau')

        self.sac_alpha = 0.2
        parser.add_argument('--sac_alpha', type=float, default=self.sac_alpha, metavar='N',
                            help='sac temperature coefficient')
        self.register_param('sac_alpha')

        self.reward_scale = 1.0
        parser.add_argument('--reward_scale', type=float, default=self.reward_scale, metavar='N',
                            help='sac temperature coefficient')
        self.register_param('reward_scale')

        self.max_iter_num = 10000
        parser.add_argument('--max_iter_num', type=int, default=self.max_iter_num, metavar='N',
                            help='maximal number of main iterations (default: 500)')
        self.register_param('max_iter_num')

        self.save_model_interval = 5
        parser.add_argument('--save_model_interval', type=int, default=self.save_model_interval, metavar='N',
                            help="interval between saving model (default: 5, means don't save)")
        self.register_param('save_model_interval')

        self.std_learnable = 1
        parser.add_argument('--std_learnable', type=int, default=self.std_learnable, metavar='N',
                            help="standard dev can be learned")
        self.register_param('std_learnable')

        self.update_interval = 1
        parser.add_argument('--update_interval', type=int, default=self.update_interval, metavar='N',
                            help="standard dev can be learned")
        self.register_param('update_interval')

        self.ep_pretrain_path_suffix = 'None'   # '-use_rmdm-rnn_len_32-ep_dim_2-1-debug'
        parser.add_argument('--ep_pretrain_path_suffix', type=str, default=self.ep_pretrain_path_suffix, metavar='N',
                            help="environment probing pretrain model path")
        self.register_param('ep_pretrain_path_suffix')

        self.name_suffix = 'None'  # '-use_rmdm-rnn_len_32-ep_dim_2-1-debug'
        parser.add_argument('--name_suffix', type=str, default=self.name_suffix, metavar='N',
                            help="name suffix of the experiment")
        self.register_param('name_suffix')

        self.ep_apply_tau = 0.99
        parser.add_argument('--ep_apply_tau', type=float, default=self.ep_apply_tau, metavar='N',
                            help="tau used to apply ep")
        self.register_param('ep_apply_tau')

        self.target_entropy_ratio = 1.5
        parser.add_argument('--target_entropy_ratio', type=float, default=self.target_entropy_ratio, metavar='N',
                            help="target entropy")
        self.register_param('target_entropy_ratio')

        self.history_length = 0
        parser.add_argument('--history_length', type=int, default=self.history_length, metavar='N',
                            help="interval between saving model (default: 0, means don't save)")
        self.register_param('history_length')

        self.task_num = 0
        parser.add_argument('--task_num', type=int, default=self.task_num, metavar='N',
                            help="interval between saving model (default: 0, means don't save)")
        self.register_param('task_num')

        self.test_task_num = 0
        parser.add_argument('--test_task_num', type=int, default=self.test_task_num, metavar='N',
                            help="number of tasks for testing")
        self.register_param('test_task_num')

        self.use_true_parameter = False
        parser.add_argument('--use_true_parameter', action='store_true')
        self.register_param("use_true_parameter")

        self.bottle_neck = False
        parser.add_argument('--bottle_neck', action='store_true')
        self.register_param("bottle_neck")

        self.transition_learn_aux = False
        parser.add_argument('--transition_learn_aux', action='store_true')
        self.register_param("transition_learn_aux")

        self.bottle_sigma = 1e-2
        parser.add_argument('--bottle_sigma', type=float, default=self.bottle_sigma, metavar='N',
                            help="std of the noise injected to ep while inference (information bottleneck)")
        self.register_param('bottle_sigma')

        self.l2_norm_for_ep = 0.0
        parser.add_argument('--l2_norm_for_ep', type=float, default=self.l2_norm_for_ep, metavar='N',
                            help="L2 norm added to EP module")
        self.register_param('l2_norm_for_ep')

        self.policy_max_gradient = 10
        parser.add_argument('--policy_max_gradient', type=float, default=self.policy_max_gradient, metavar='N',
                            help="maximum gradient of policy")
        self.register_param('policy_max_gradient')

        self.use_rmdm = False
        parser.add_argument('--use_rmdm', action='store_true',
                            help="use Relational Matrix Determinant Maximization or not")
        self.register_param('use_rmdm')

        self.use_uposi = False
        parser.add_argument('--use_uposi', action='store_true')
        self.register_param('use_uposi')

        self.uniform_sample = False
        parser.add_argument('--uniform_sample', action='store_true')
        self.register_param('uniform_sample')

        self.share_ep = False
        parser.add_argument('--share_ep', action='store_true')
        self.register_param('share_ep')

        self.enhance_ep = False
        parser.add_argument('--enhance_ep', action='store_true')
        self.register_param('enhance_ep')

        self.stop_pg_for_ep = False
        parser.add_argument('--stop_pg_for_ep', action='store_true')
        self.register_param('stop_pg_for_ep')

        self.use_contrastive = False
        parser.add_argument('--use_contrastive', action='store_true')
        self.register_param('use_contrastive')

        self.rmdm_update_interval = -1
        parser.add_argument('--rmdm_update_interval', type=int, default=self.rmdm_update_interval, metavar='N',
                            help="update interval of rmdm")
        self.register_param('rmdm_update_interval')

        self.rnn_fix_length = 0
        parser.add_argument('--rnn_fix_length', type=int, default=self.rnn_fix_length, metavar='N',
                            help="fix the rnn memory length to rnn_fix_length")
        self.register_param('rnn_fix_length')

        self.minimal_repre_rp_size = 1e5
        parser.add_argument('--minimal_repre_rp_size', type=float, default=self.minimal_repre_rp_size, metavar='N',
                            help="after minimal_repre_rp_size, start training EP module")
        self.register_param('minimal_repre_rp_size')

        # self.ep_start_num = 150000
        self.ep_start_num = 0
        parser.add_argument('--ep_start_num', type=int, default=self.ep_start_num, metavar='N',
                            help="only when the size of the replay buffer is larger than ep_start_num"
                                 ", ep can be learned")
        self.register_param('ep_start_num')

        self.kernel_type = 'rbf_element_wise'
        parser.add_argument('--kernel_type', default=self.kernel_type, metavar='G',
                            help='kernel type for DPP loss computing (rbf/rbf_element_wise/inner)')
        self.register_param('kernel_type')

        self.rmdm_ratio = 1.0
        parser.add_argument('--rmdm_ratio', type=float, default=self.rmdm_ratio, metavar='N',
                            help="gradient ratio of rmdm")
        self.register_param('rmdm_ratio')

        self.test_variable = 1.0
        parser.add_argument('--test_variable', type=float, default=self.test_variable, metavar='N',
                            help="variable for testing variable")
        self.register_param('test_variable')

        self.rmdm_tau = 0.995
        parser.add_argument('--rmdm_tau', type=float, default=self.rmdm_tau, metavar='N',
                            help="smoothing ratio of the representation")
        self.register_param('rmdm_tau')

        self.repre_loss_factor = 1.0
        parser.add_argument('--repre_loss_factor', type=float, default=self.repre_loss_factor, metavar='N',
                            help="size of the representation loss")
        self.register_param('repre_loss_factor')

        self.ep_smooth_factor = 0.0
        parser.add_argument('--ep_smooth_factor', type=float, default=self.ep_smooth_factor, metavar='N',
                            help="smooth  factor for ep module, 0.0 for apply concurrently")
        self.register_param('ep_smooth_factor')

        self.rbf_radius = 80.0
        parser.add_argument('--rbf_radius', type=float, default=self.rbf_radius, metavar='N',
                            help="radius of the rbf kerel")
        self.register_param('rbf_radius')

        self.env_default_change_range = 3.0
        parser.add_argument('--env_default_change_range', type=float, default=self.env_default_change_range, metavar='N',
                            help="environment default change range")
        self.register_param('env_default_change_range')

        self.env_ood_change_range = 4.0
        parser.add_argument('--env_ood_change_range', type=float, default=self.env_ood_change_range,
                            metavar='N',
                            help="environment OOD change range")
        self.register_param('env_ood_change_range')

        self.consistency_loss_weight = 50.0
        parser.add_argument('--consistency_loss_weight', type=float, default=self.consistency_loss_weight, metavar='N',
                            help="loss ratio of the consistency loss")
        self.register_param('consistency_loss_weight')

        self.diversity_loss_weight = 0.025
        parser.add_argument('--diversity_loss_weight', type=float, default=self.diversity_loss_weight, metavar='N',
                            help="loss ratio of the DPP loss")
        self.register_param('diversity_loss_weight')

        self.varying_params = ['gravity', 'body_mass']
        parser.add_argument('--varying_params', nargs='+', type=str, default=self.varying_params)
        self.register_param('varying_params')

        self.up_hidden_size = [128, 64]
        parser.add_argument('--up_hidden_size', nargs='+', type=int, default=self.up_hidden_size,
                            help="architecture of the hidden layers of Universe Policy")
        self.register_param('up_hidden_size')

        self.up_activations = ['leaky_relu', 'leaky_relu', 'linear']
        parser.add_argument('--up_activations', nargs='+', type=str,
                            default=self.up_activations,
                            help="activation of each layer of Universe Policy")
        self.register_param('up_activations')

        self.up_layer_type = ['fc', 'fc', 'fc']
        parser.add_argument('--up_layer_type', nargs='+', type=str,
                            default=self.up_layer_type,
                            help="net type of Universe Policy")
        self.register_param('up_layer_type')

        # self.ep_hidden_size = [128, 64, 32] # [128, 64, 32]
        self.ep_hidden_size = [128, 64] # [256, 128]
        parser.add_argument('--ep_hidden_size', nargs='+', type=int, default=self.ep_hidden_size,
                            help="architecture of the hidden layers of Environment Probing Net")
        self.register_param('ep_hidden_size')

        if FC_MODE:
            self.ep_activations = ['leaky_relu', 'leaky_relu', 'leaky_relu', 'tanh']
            parser.add_argument('--ep_activations', nargs='+', type=str,
                                default=self.ep_activations,
                                help="activation of each layer of Environment Probing Net")
            self.register_param('ep_activations')

            self.ep_layer_type = ['fc', 'fc', 'fc', 'fc']
            parser.add_argument('--ep_layer_type', nargs='+', type=str,
                                default=self.ep_layer_type,
                                help="net type of Environment Probing Net")
            self.register_param('ep_layer_type')
        else:
            # original RNN architecture
            self.ep_activations = ['leaky_relu', 'linear', 'tanh']
            parser.add_argument('--ep_activations', nargs='+', type=str,
                                default=self.ep_activations,
                                help="activation of each layer of Environment Probing Net")
            self.register_param('ep_activations')
            self.ep_layer_type = ['fc', 'gru', 'fc']
            parser.add_argument('--ep_layer_type', nargs='+', type=str,
                                default=self.ep_layer_type,
                                help="net type of Environment Probing Net")
            self.register_param('ep_layer_type')
            # fc architecture
            # self.ep_activations = ['leaky_relu', 'tanh', 'tanh']
            # parser.add_argument('--ep_activations', nargs='+', type=str,
            #                     default=self.ep_activations,
            #                     help="activation of each layer of Environment Probing Net")
            # self.register_param('ep_activations')
            # self.ep_layer_type = ['fc', 'fc', 'fc']
            # parser.add_argument('--ep_layer_type', nargs='+', type=str,
            #                     default=self.ep_layer_type,
            #                     help="net type of Environment Probing Net")
            # self.register_param('ep_layer_type')

        self.ep_dim = 2
        parser.add_argument('--ep_dim', type=int, default=self.ep_dim, metavar='N',
                            help="dimension of environment features")
        self.register_param('ep_dim')

        self.value_hidden_size = [128, 64]
        parser.add_argument('--value_hidden_size', nargs='+', type=int, default=self.value_hidden_size,
                            help="architecture of the hidden layers of value")
        self.register_param('value_hidden_size')

        self.value_activations = ['leaky_relu', 'leaky_relu', 'linear']
        parser.add_argument('--value_activations', nargs='+', type=str,
                            default=self.value_activations,
                            help="activation of each layer of value")
        self.register_param('value_activations')

        self.value_layer_type = ['fc', 'fc', 'fc']
        parser.add_argument('--value_layer_type', nargs='+', type=str,
                            default=self.value_layer_type,
                            help="net type of value")
        self.register_param('value_layer_type')

        return parser.parse_args()

    def register_param(self, name):
        self.arg_names.append(name)

    def get_experiment_description(self):
        description = f"本机{self.host_name}, ip为{self.ip}\n"
        description += f"目前实验目的为{self.experiment_target}\n"
        description += f"实验简称: {self.short_name}\n"
        description += f"commit id: {self.commit_id}\n"
        vars = ''
        important_config = self.important_configs()
        for name in self.arg_names:
            if name in important_config:
                vars += f'**{name}**: {getattr(self, name)}\n'
            else:
                vars += f'{name}: {getattr(self, name)}\n'
        for name in self.DEFAULT_CONFIGS:
            vars += f'{name}: {self.DEFAULT_CONFIGS[name]}\n'
        return description + vars

    def __str__(self):
        return self.get_experiment_description()

    def clear_local_file(self):
        cmd = f'rm -f {os.path.join(self.config_path, self.json_name)} {os.path.join(self.config_path, self.txt_name)}'
        system(cmd)

    def save_config(self):
        self.info(f'save json config to {os.path.join(self.config_path, self.json_name)}')
        if not os.path.exists(self.config_path):
            os.makedirs(self.config_path)
        with open(os.path.join(self.config_path, self.json_name), 'w') as f:
            things = self.make_dict()
            ser = json.dumps(things)
            f.write(ser)
        self.info(f'save readable config to {os.path.join(self.config_path, self.txt_name)}')
        with open(os.path.join(self.config_path, self.txt_name), 'w') as f:
            print(self, file=f)

    def load_config(self):
        self.info(f'load json config from {os.path.join(self.config_path, self.json_name)}')
        with open(os.path.join(self.config_path, self.json_name), 'r') as f:
            ser = json.load(f)
        for k, v in ser.items():
            if not k == 'description':
                setattr(self, k, v)
                self.register_param(k)
        self.experiment_target = ser['description']

    @property
    def differences(self):
        if not os.path.exists(os.path.join(self.config_path, self.json_name)):
            return None
        with open(os.path.join(self.config_path, self.json_name), 'r') as f:
            ser = json.load(f)
        differences = []
        for k, v in ser.items():
            if not hasattr(self, k):
                differences.append(k)
            else:
                v2 = getattr(self, k)
                if not v2 == v:
                    differences.append(k)
        return differences

    def check_identity(self, need_decription=False, need_exec_time=False):
        if not os.path.exists(os.path.join(self.config_path, self.json_name)):
            self.info(f'{os.path.join(self.config_path, self.json_name)} not exists')
            return False
        with open(os.path.join(self.config_path, self.json_name), 'r') as f:
            ser = json.load(f)
        flag = True
        for k, v in ser.items():
            if not k == 'description' and not k == 'exec_time':
                if not hasattr(self, k):
                    flag = False
                    return flag
                v2 = getattr(self, k)
                if not v2 == v:
                    flag = False
                    return flag
        if need_decription:
            if not self.experiment_target == ser['description']:
                flag = False
                return flag
        if need_exec_time:
            if not self.exec_time == ser['exec_time']:
                flag = False
                return flag
        return flag

    @property
    def short_name(self):
        name = ''
        for item in self.important_configs():
            value = getattr(self, item)
            if value:
                if item == 'env_name':
                    name += value
                elif item == 'seed':
                    name += f'-{value}'
                elif item == 'rnn_fix_length':
                    name += f"-rnn_len_{value}"
                elif item == 'ep_dim':
                    name += f"-ep_dim_{value}"
                else:
                    name += f'-{item}'
        if self.debug:
            name += '-debug'
        if self.information is not None:
            name += '-{}'.format(self.information)
        if hasattr(self, 'name_suffix') and not self.name_suffix == 'None':
            name += f'_{self.name_suffix}'
        elif not len(SHORT_NAME_SUFFIX) == 0:
            name += f'_{SHORT_NAME_SUFFIX}'
        return name

    def get_commit_id(self):
        base_path = get_base_path()
        cmd = f'cd {base_path} && git log'
        commit_id = None
        try:
            with os.popen(cmd) as f:
                line = f.readline()
                words = line.split(' ')
                commit_id = words[-1][:-1]
        except Exception as e:
            self.info(f'Error occurs while fetching commit id!!! {e}')
        return commit_id

if __name__ == '__main__':
    parameter = Parameter()
    parameter.get_commit_id()
    print(parameter)


import os
import pathlib
import shutil
from tempfile import mkdtemp
import unittest
from fuse.data.utils.sample import get_sample_id
from fuse.utils.file_io.file_io import create_dir
from typing import Any

from fuseimg.datasets.kits21 import KITS21
from fuseimg.datasets.stoic21 import STOIC21
from tqdm import trange
from testbook import testbook
from fuse.eval.metrics.stat.metrics_stat_common import MetricUniqueValues
from fuse.utils.multiprocessing.run_multiprocessed import (
    get_from_global_storage,
    run_multiprocessed,
)
from fuse.eval.evaluator import EvaluatorDefault

from fuseimg.datasets.isic import ISIC
from fuse_examples.imaging.classification.isic.golden_members import (
    FULL_GOLDEN_MEMBERS,
    TEN_GOLDEN_MEMBERS,
)

notebook_path = os.path.join(
    pathlib.Path(__file__).parent.resolve(), "../kits21_example.ipynb"
)

def ds_getitem(index: int) -> Any:
    sample = get_from_global_storage("ds")[index].flatten()
    del sample["data.input.img"]
    return sample

class TestDatasets(unittest.TestCase):
    def setUp(self) -> None:
        super().setUp()
        self.kits21_cache_dir = mkdtemp(prefix="kits21_cache")
        self.kits21_data_dir = (
            os.environ["KITS21_DATA_PATH"]
            if "KITS21_DATA_PATH" in os.environ
            else mkdtemp(prefix="kits21_data")
        )

        self.stoic21_cache_dir = mkdtemp(prefix="stoic_cache")

        self.isic_cache_dir = mkdtemp(prefix="isic_cache")
        self.isic_data_dir = (
            os.environ["ISIC19_DATA_PATH"]
            if "ISIC19_DATA_PATH" in os.environ
            else mkdtemp(prefix="isic_data")
        )

    def test_kits21(self) -> None:
        KITS21.download(self.kits21_data_dir, cases=list(range(10)))

        create_dir(self.kits21_cache_dir)
        dataset = KITS21.dataset(
            data_path=self.kits21_data_dir,
            cache_dir=self.kits21_cache_dir,
            reset_cache=True,
            sample_ids=[f"case_{id:05d}" for id in range(10)],
        )
        self.assertEqual(len(dataset), 10)
        for sample_index in trange(10):
            sample = dataset[sample_index]
            self.assertEqual(get_sample_id(sample), f"case_{sample_index:05d}")

    @unittest.skipIf(
        "STOIC21_DATA_PATH" not in os.environ,
        "Expecting environment variable STOIC21_DATA_PATH to be defined",
    )
    def test_stoic21(self) -> None:
        data_path = os.environ["STOIC21_DATA_PATH"]
        sids = STOIC21.sample_ids(data_path)[:10]
        ds = STOIC21.dataset(
            sample_ids=sids,
            data_path=data_path,
            cache_dir=self.stoic21_cache_dir,
            reset_cache=True,
        )

        metrics = {
            "age": MetricUniqueValues(key="data.input.age"),
            "gender": MetricUniqueValues(key="data.input.gender"),
            "thickness": MetricUniqueValues(key="data.metadata.SliceThickness"),
            "covid": MetricUniqueValues(key="data.gt.probCOVID"),
            "severe": MetricUniqueValues(key="data.gt.probSevere"),
        }
        evaluator = EvaluatorDefault()

        data_iter = run_multiprocessed(
            worker_func=ds_getitem,
            args_list=range(len(ds)),
            copy_to_global_storage={"ds": ds},
            workers=10,
            verbose=1,
            as_iterator=True,
        )

        results = evaluator.eval(
            ids=None, data=data_iter, metrics=metrics, id_key="data.sample_id"
        )

        self.assertEqual(ds[0]["data.input.clinical"].shape[0], 8)
        self.assertTrue(5 in dict(results["metrics.age"]))

    def test_isic(self) -> None:

        create_dir(self.isic_cache_dir)
        dataset = ISIC.dataset(
            self.isic_data_dir,
            self.isic_cache_dir,
            train=True,
            reset_cache=True,
            samples_ids=TEN_GOLDEN_MEMBERS,
        )
        self.assertEqual(len(dataset), 10)
        for sample_index in range(10):
            sample = dataset[sample_index]
            self.assertEqual(get_sample_id(sample), TEN_GOLDEN_MEMBERS[sample_index])

    @testbook(notebook_path, execute=range(0, 4), timeout=120)
    def test_basic(tb, self) -> None:  # type: ignore
        tb.execute_cell([4, 5])

        tb.inject(
            """
            assert(np.max(my_dataset[0]['data.input.img'])>=0 and np.max(my_dataset[0]['data.input.img'])<=1)
            """
        )

    @testbook(notebook_path, execute=range(0, 4), timeout=240)
    def test_caching(tb, self) -> None:  # type: ignore
        tb.execute_cell([9])

        tb.execute_cell([16, 17])
        tb.inject(
            """
            assert(isinstance(my_dataset[0]["data.gt.seg"], torch.Tensor))
            """
        )

    @testbook(notebook_path, execute=range(0, 4), timeout=240)
    def test_custom(tb, self) -> None:  # type: ignore
        tb.execute_cell([25])

        tb.inject(
            """
            assert(my_dataset[0]["data.gt.seg"].shape[1:] == (4, 256, 256))
            """
        )

    def tearDown(self) -> None:
        shutil.rmtree(self.kits21_cache_dir)
        if "KITS21_DATA_PATH" not in os.environ:
            shutil.rmtree(self.kits21_data_dir)

        shutil.rmtree(self.stoic21_cache_dir)

        shutil.rmtree(self.isic_cache_dir)
        if "ISIC19_DATA_PATH" not in os.environ:
            shutil.rmtree(self.isic_data_dir)

        super().tearDown()

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


import argparse

def load_data(file_name):
    data = []
    with open(file_name, 'r') as f:
        for line in f:
            line_data = []
            for digit in line.strip():
                line_data.append(int(digit))
            data.append(line_data)

    return data

def step_increment(grid, flashes):
    flashed = True
    for i in range(len(grid)):
        for j in range(len(grid[i])):
            grid[i][j] = grid[i][j] + 1

    while flashed:
        flashed = False
        for i in range(len(grid)):
            for j in range(len(grid[i])):
                if grid[i][j] > 9:
                    flashed = True
                    flashes = flashes + 1
                    if i > 0 and j > 0 and grid[i - 1][j - 1] != 0:
                        grid[i - 1][j - 1] = grid[i - 1][j - 1] + 1
                    if i > 0 and grid[i - 1][j] != 0:
                        grid[i - 1][j] = grid[i - 1][j] + 1
                    if i > 0 and j < len(grid[i - 1]) - 1 and grid[i - 1][j + 1] != 0:
                        grid[i - 1][j + 1] = grid[i - 1][j + 1] + 1
                    if j > 0 and grid[i][j - 1] != 0:
                        grid[i][j - 1] = grid[i][j - 1] + 1
                    grid[i][j] = 0
                    if j < len(grid[i]) - 1 and grid[i][j + 1] != 0:
                        grid[i][j + 1] = grid[i][j + 1] + 1
                    if i < len(grid) - 1 and j > 0 and grid[i + 1][j - 1] != 0:
                        grid[i + 1][j - 1] = grid[i + 1][j - 1] + 1
                    if i < len(grid) - 1 and grid[i + 1][j] != 0:
                        grid[i + 1][j] = grid[i + 1][j] + 1
                    if i < len(grid) - 1 and j < len(grid[i + 1]) - 1 and grid[i + 1][j + 1] != 0:
                        grid[i + 1][j + 1] = grid[i + 1][j + 1] + 1

    return flashes

def count_flashes(grid, n):
    flashes = 0

    for num_steps in range(n):
        flashes = step_increment(grid, flashes)

    return flashes

def find_full_flash_step(grid):
    step = 0
    total = 0
    for i in range(len(grid)):
        total = total + sum(grid[i])
    while total:
        step_increment(grid, 0)
        step = step + 1
        total = 0
        for i in range(len(grid)):
            total = total + sum(grid[i])

    return step

def main():
    parser = argparse.ArgumentParser(description='AoC Day 11 Dumbo Octopus')
    parser.add_argument('-f', '--file',
                        help='Input file with each line containing energy level of octopus from 0-9.',
                        default='input.txt')
    parser.add_argument('-c', '--code',
                        help='Select 1: Count number of flashes after n steps or 2: Find step number of full flash',
                        type=int,
                        default=1)
    arguments = parser.parse_args()

    grid = load_data(arguments.file)
    # print(grid)
    if arguments.code == 1:
        print(count_flashes(grid, 100))
    elif arguments.code == 2:
        print(find_full_flash_step(grid))
    else:
        print("Selected code not valid")

if __name__ == "__main__":
    main()


from django.core.exceptions import ObjectDoesNotExist

from bookingsystem.models import Restaurants

class DatabaseUpdater():
    def update_model_instance(self, model_class, restaurant_id, instance_id, column_name, column_value):
        try:
            if model_class != Restaurants:
                instance = model_class.objects.get(restaurant_id=restaurant_id, id=instance_id)
            elif model_class == Restaurants:
                instance = model_class.objects.get(id=restaurant_id)
            if hasattr(instance, column_name):
                if column_name == 'price':
                    column_value = float(column_value.replace(',', '.'))
                setattr(instance, column_name, column_value)
                instance.save()
            else:
                print(f'Invalid column_name {column_name} for model {model_class.__name__}')
        except ObjectDoesNotExist:
            print(f'{model_class.__name__} with id {instance_id} does not exist')


from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep

ser = Service("C:\Program Files (x86)\chromedriver.exe")
op = webdriver.ChromeOptions()

text = input("Search Google or Type URL: ")

class GoogleBot:

	def __init__(self, text):
		self.s = webdriver.Chrome(service=ser, options=op)
		self.s.get("https://www.google.com/search?q=" + text + "&start")

GoogleBot(text)


import logging
import os

from pynput import keyboard

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s;%(levelname)s;%(message)s')

ROOT_DIR = os.path.dirname(os.path.abspath(__file__))

WIDTH = 300
HEIGHT = 200

START_BUTTON = keyboard.Key.left
STOP_BUTTON = keyboard.Key.right

SAVED = 1
ABORTED = 0


# This Python Bot will retweet and like specific hashtag and mention
# install tweepy using pip install tweepy
# import the required modules
import tweepy
import time

# Import Twitter application keys, tokens, and secrets from keys.py.
from keys import *

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth, wait_on_rate_limit=True)

# test authentication
api.verify_credentials()
print("Authentication Successful")

# hashtag and mention that you want to retweet
search = "kate028" and "kate028_"
nfTweets = 100

for tweet in tweepy.Cursor(api.search_tweets, search).items(nfTweets):
    try:
        tweet.favorite()
        print('Liked')
        tweet.retweet()
        print('Retweeted')
        tweet.sleep(10) # 10(in sec) is the time you want to have in-between retweets.
    except StopIteration:
        break

    # Some basic error handling. Will print out why retweet failed, into your terminal.
    # except tweepy.errors.TweepyException as error:
    #     print('\nError. Retweet not successful. Reason: ')
    #     print(error.reason)


# from __future__ import print_function
import os
import sys
import numpy as np
import cv2
import glob
# from matplotlib import pyplot as plt
# from common import splitfn

def lupa( image ):
    _, file_name = os.path.split( image )
    status = 0
    img_names_undistort = [img for img in glob.glob( image )]
    new_path = "/путь для сохранения обработанных изображений/"

    camera_matrix = np.array([[1.26125746e+03, 0.00000000e+00, 9.40592038e+02],
                            [0.00000000e+00, 1.21705719e+03, 5.96848905e+02],
                            [0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]);
    dist_coefs = np.array([-0.49181345,  0.25848255, -0.01067125, -0.00127517, -0.01900726]);

    i = 0

    #for img_found in img_names_undistort:
    while i < len(img_names_undistort):
        img = cv2.imread(img_names_undistort[i])
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        h,  w = img.shape[:2]
        newcameramtx, roi = cv2.getOptimalNewCameraMatrix(camera_matrix, dist_coefs, (w, h), 1, (w, h))

        dst = cv2.undistort(img, camera_matrix, dist_coefs, None, newcameramtx)

        dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)

        # crop and save the image
        x, y, w, h = roi
        dst = dst[y:y+h-50, x+70:x+w-20]

        i = i + 1
        status = 1
    cv2.imwrite( f"./processed_files/{file_name}", dst )
    return status


import numpy as np
import torch

class EarlyStop():
    def __init__(self, model, checkpoint, mode='min', label='score', tries=20):
        self.model = model
        self.checkpoint = checkpoint
        self.trial = 0
        self.label = label
        self.tries = tries

        if mode == 'min':
            self.monitor_op = np.less
            self.best_score = np.Inf
        elif mode == 'max':
            self.monitor_op = np.greater
            self.best_score = -np.Inf

    def on_epoch_end(self, score):
        if self.monitor_op(score, self.best_score):
            print(f"{self.label} improved, {self.best_score} -> {score}")
            print(f"{self.label} improved by {self.best_score - score}")
            print(f'Saving model: output/models/{self.checkpoint}.pt')
            torch.save(self.model.state_dict(), f'output/models/{self.checkpoint}.pt')

            self.best_score = score
            self.trial = 0

        else:
            self.trial += 1

            if self.trial > self.tries:
                print(f'Early stopping')

                return True

            print(f"{self.label} did not improved ({self.best_score}), {self.trial} / {self.tries}")

        return False


from cgitb import text
from urllib import request
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.core.cache import cache
from django.forms.models import model_to_dict
from estoque.filters import EstoqueFilter
from django.db import IntegrityError
from django.http.response import JsonResponse
from django.urls.base import reverse
from django.views.generic.edit import DeleteView, UpdateView
from django.views.generic.list import ListView
import pyqrcode
from abc import abstractmethod
from estoque.models import Estoque
from estoque.forms import *
from django.urls import reverse_lazy
from django.contrib import messages
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin
from braces.views import GroupRequiredMixin
from django.views.generic import TemplateView, CreateView
from datetime import date, datetime, timedelta
from django.contrib.auth.decorators import login_required
from usuarios.permissoes import group_required
from django.views.decorators.csrf import csrf_exempt

class InserirItemView(GroupRequiredMixin, LoginRequiredMixin, CreateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    selected_categoria ='0'

    model = Item
    template_name = 'estoque/inserir-item.html'
    success_url = reverse_lazy('inserir-item')
    form_class = InserirItemForm

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['ultimos_dez'] =  Item.objects.all().order_by('-id')
        context['inserir'] =  True
        context['selected_categoria'] =  self.selected_categoria
        return context

    def form_valid(self, form):
        f = super().form_valid(form)

        # GERANDO O QR CODE
        # qr_code = gerar_qrcode(f"#ID#{self.object.pk}")
        # self.object.qr_code = f'{qr_code}'

        self.object.save()
        messages.add_message(
            self.request,
            messages.SUCCESS,
            'ITEM  adicionado com SUCESSO!'
        )
        return f

    def post(self, request, *args, **kwargs):
        new_categoria = request.POST.get("new_categoria")
        if new_categoria:
            try:
                categoria = Categoria.objects.create(categoria=new_categoria)
                self.selected_categoria = categoria.pk
                messages.add_message(
                        self.request,
                        messages.SUCCESS,
                        'Categoria Adicionada!'
                    )
            except IntegrityError:
                if 'unique constraint':
                    messages.add_message(
                        self.request,
                        messages.WARNING,
                        f'CATEGORIA: {request.POST.get("new_categoria")} Já Adicionada!'
                    )

        return super().post(request, *args, **kwargs)

class DetalharItemView(GroupRequiredMixin, LoginRequiredMixin, TemplateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    template_name = "estoque/detalhar-item.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["item_atual"] = Item.objects.get(pk=self.kwargs.get('pk'))
        return context

class EditarItemView(GroupRequiredMixin, LoginRequiredMixin, UpdateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    template_name = 'estoque/inserir-item.html'
    model = Item
    form_class = InserirItemForm

    def get_success_url(self):
        return reverse('ver-estoque')
        # return reverse('detalhar-item', kwargs = {'pk': self.kwargs.get('pk')})

class ExcluirItemView(GroupRequiredMixin, LoginRequiredMixin,DeleteView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = Item
    success_url = reverse_lazy("inserir-item")

class InicioEstoque(GroupRequiredMixin, LoginRequiredMixin, TemplateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    template_name= 'estoque/ver-estoque.html'
    success_url = reverse_lazy('ver-estoque')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # objects = Estoque.objects.select_related('item')

        #Ao iniciar o estoque não carrega todos os itens de primeira, somente quando usar o Form de filtragem
        if self.request.GET.get('filterStatus'):
            objects = Estoque.objects.all()
            filter_list = EstoqueFilter(self.request.GET, queryset = objects )
        else:
            objects = Estoque.objects.none()
            filter_list = EstoqueFilter(self.request.GET, queryset = objects )

        context["filter"] = filter_list
        cache.set('filter_estoque_resultados', filter_list, 600)

        return context

class VerEstoqueVarios(GroupRequiredMixin, LoginRequiredMixin, TemplateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    template_name= 'estoque/ver-estoque-varios.html'
    success_url = reverse_lazy('ver-estoque-varios')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # objects = Estoque.objects.select_related('item')

        #Ao iniciar o estoque não carrega todos os itens de primeira, somente quando usar o Form de filtragem
        if self.request.GET.get('filterStatus'):
            objects = Estoque.objects.all()
            filter_list = EstoqueFilter(self.request.GET, queryset = objects )
        else:
            objects = Estoque.objects.none()
            filter_list = EstoqueFilter(self.request.GET, queryset = objects )

        context["filter"] = filter_list
        cache.set('filter_estoque_resultados', filter_list, 600)

        return context

class MovimentacaoEstoqueView(GroupRequiredMixin, LoginRequiredMixin, CreateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = MovimentacaoEstoque
    template_name= 'estoque/mov-estoque.html'
    success_url = reverse_lazy('mov-estoque')
    form_class = MovimentacaoModelForm

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['itensEstoque'] =  Estoque.objects.order_by('pk').all()
        context["log_list"] = LogMovimentacao.objects.all().order_by('-pk')[:20]
        return context

    def form_valid(self, form):
        response = super().form_valid(form)
        tipo = form.cleaned_data['tipo']

        #preenchendo Estoque
        estoque = Estoque()
        item_form = self.request.POST.get('item_selecionado')

        # Verificando se existe o COD: ou o item é valido!
        try:
            item_id = item_form.split('COD: ')[1] #fatia a string, deixando apenas a matricula
        except IndexError:
            messages.add_message(
                    self.request,
                    messages.WARNING,
                    'Vazio ou Não existe!!'
                )
        else:
            item_atual = Item.objects.get(pk=item_id)

            estoque.quantidade = form.cleaned_data['qtd']

            # Verificando se a quantidade é somente positiva e maior que zero
            if(estoque.quantidade <= 0):
                 messages.add_message(
                    self.request,
                    messages.WARNING,
                    'Valor Negativo ou Zerado - Favor inserir outro valor!'
                )
            else:
                estoque.item = item_atual
                #verificando se é Entrada ou Saída
                if tipo == '1': #Caso seja Entrada
                    if not Estoque.objects.filter(item= item_atual).exists():
                        estoque.save()
                        print('Nome Item no Estoque: '+ estoque.item.descricao)
                    else:
                        #somar quantidade
                        qnt_anterior = Estoque.objects.get(item= item_atual).quantidade
                        soma = quantidade=estoque.quantidade+qnt_anterior
                        Estoque.objects.filter(item= item_atual).update(quantidade=soma)

                        msg = str(estoque.quantidade)+' '+str(estoque.item.unid_medida)+' - '+str(estoque.item.descricao)+' foi ACRESCENTADO ao Estoque - Total no Estoque: '+str(soma)
                        log_item_updated(request = self.request, item = item_atual, qnt = estoque.quantidade, saldo = soma, adicionado= True)

                        messages.add_message(
                            self.request,
                            messages.SUCCESS,
                            msg
                        )
                else: #caso seja Saída
                    if not Estoque.objects.filter(item= item_atual).exists():
                        messages.add_message(
                            self.request,
                            messages.WARNING,
                            'Item: '+str(item_atual)+' NÃO ENCONTRADO!'
                        )
                    else:
                        #diminuir quantidade
                        qnt_anterior = Estoque.objects.get(item= item_atual).quantidade
                        sobra = qnt_anterior-estoque.quantidade
                        if sobra >= 0:
                            Estoque.objects.filter(item= item_atual).update(quantidade=sobra)

                            msg = str(estoque.quantidade)+' '+str(estoque.item.unid_medida)+' - '+str(estoque.item.descricao)+' foi RETIRADO ao Estoque - Total no Estoque: '+str(sobra)

                            log_item_updated(request = self.request, item = item_atual, qnt = estoque.quantidade, saldo = sobra, adicionado= False)
                            messages.add_message(
                                self.request,
                                messages.WARNING,
                                msg
                            )
                        else:
                            messages.add_message(
                                self.request,
                                messages.WARNING,
                                'NÃO HÁ ITENS SUFICIENTES NO ESTOQUE!'
                            )

        return response

class CategoriasEstoque(GroupRequiredMixin, LoginRequiredMixin, CreateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = Categoria
    template_name= 'estoque/categorias-estoque.html'
    success_url = reverse_lazy('categorias-estoque')
    form_class = CategoriaModelForm

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categorias'] =  Categoria.objects.all().order_by('pk')
        return context

class EditarCategoriaEstoque(GroupRequiredMixin, LoginRequiredMixin, UpdateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = Categoria
    template_name= 'estoque/categorias-estoque.html'
    success_url = reverse_lazy('categorias-estoque')
    form_class = CategoriaModelForm

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categorias'] =  Categoria.objects.all().order_by('pk')
        context['editar'] =  True
        return context

class ExcluirCategoriaEstoque(GroupRequiredMixin, LoginRequiredMixin, DeleteView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = Categoria
    success_url = reverse_lazy("categorias-estoque")

class BuscaEstoqueView(GroupRequiredMixin, LoginRequiredMixin, ListView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = Estoque
    template_name = 'estoque/buscar-estoque.html'

    def get_queryset(self):
        query = self.request.GET.get('q')
        object_list = ''
        if query != None:
            object_list = Estoque.objects.filter(Q(item__descricao__icontains=query))
        return  object_list

class ImprimirResultadosEstoqueView(GroupRequiredMixin, LoginRequiredMixin, TemplateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = Categoria
    template_name= 'estoque/resultados-impressao.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter_list'] = cache.get('filter_estoque_resultados')

        return context

class ImprimirListaItensView(GroupRequiredMixin, LoginRequiredMixin, TemplateView):
    login_url = reverse_lazy('login')
    group_required = [u'Administrador', u'Estoque', u'Tecnico',]

    model = ItensSelecionados
    template_name= 'estoque/lista-itens-impressao.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter_list'] = ItensSelecionados.objects.all()

        return context

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def autocompleteitens(request):
    query = request.GET.get('term')
    query_set = Item.objects.filter(descricao__icontains=query) | Item.objects.filter(pk__iexact=query)
    myList=[]
    myList += [x.descricao+' - '+x.unid_medida+' - COD: '+str(x.pk) for x in query_set]
    return JsonResponse(myList,safe=False)

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def gerar_qrcode(text):
    code = pyqrcode.create(text)
    code.png(f"simo/media/qrcodes/{text}.png", scale=6,)

    if code != 0:
        print(f"QRCode gerado com sucesso - {text}!")
        return f"qrcodes/{text}.png"
    else:
        print(f"ERRO ao gerar QRCode - {text}!")
        return False

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def estoque_filter(request):
    if request.method == 'POST':
        objects = Estoque.objects.all()

        filter_list = EstoqueFilter(request.POST, queryset = objects)
        lista_itens = list()

        for item in list(filter_list.qs.values()):
            lista_aux = list()
            obj = Item.objects.get(id=item['item_id'])
            lista_aux.append(item['id'])
            lista_aux.append(obj.id)
            lista_aux.append(obj.descricao)
            if obj.marca:
                lista_aux.append(obj.marca)
            else:
                lista_aux.append('-')
            if obj.categoria:
                lista_aux.append(obj.categoria.categoria)
            else:
                lista_aux.append('-')
            if obj.fornecedor:
                lista_aux.append(obj.fornecedor.nome)
            else:
                lista_aux.append('-')
            lista_aux.append(obj.unid_medida)
            lista_aux.append(item['quantidade'])

            lista_itens.append(lista_aux)

        return JsonResponse({'filter': lista_itens}, status=200)

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def add_filtro_varios(request):

    carregar_itens = ItensSelecionados.objects.all()

    template_name = 'estoque/lista-itens-selecionados.html'
    if request.method == 'POST':
        tasks = request.POST.getlist('array[]')
        print(tasks)

        for item in tasks:
            if not carregar_itens.filter(estoque__item__pk=int(item)):
                aux = ItensSelecionados(estoque = Estoque.objects.get(item__pk=int(item)))
                aux.save()

        context = {
            'itens_selecionados': carregar_itens.order_by('-pk')
        }

        return render(request, template_name, context)
    else:
        return HttpResponse('Item Não Adicionado') #TODO FAZER UMA RESPOSTA EM HTML COM TABELA VAZIA

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def remover_filtro_varios(request):

    template_name = 'estoque/lista-itens-selecionados.html'

    try:
        item_selecionado = ItensSelecionados.objects.get(estoque__item__pk=request.POST.get('id'))
        item_selecionado.delete()

        context = {
            'itens_selecionados': ItensSelecionados.objects.all().order_by('-pk')
        }
        return render(request, template_name, context )

    except:

      return HttpResponse('Item Não Encontrado ou Já excluído!') #TODO FAZER UMA RESPOSTA EM HTML COM TABELA VAZIA

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def remover_lista_selecionada(request):
    template_name = 'estoque/lista-itens-selecionados.html'

    try:
        ItensSelecionados.objects.all().delete()

        return render(request, template_name)

    except:

      return HttpResponse('Lista Não encontrada ou já excluída!') #TODO FAZER UMA RESPOSTA EM HTML COM TABELA VAZIA

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def log_item_updated(request, item, qnt, saldo, adicionado):

   current_time = datetime.now()
   #formated_data = current_time.strftime("%d/%m/%Y - %H:%M")

   usuario = None
   if request.user.is_authenticated:
        usuario = request.user

   novo_log = LogMovimentacao(usuario=usuario, item=item.descricao, quantidade=qnt, saldo=saldo, adicionado=adicionado, data_inclusao=current_time)
   novo_log.save()

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def estoque_busca_varios(request):
    if request.POST.get("descricao") == "":
        return render(request, template_name='estoque/fragmentos/itens_busca_varios.html', context={'error': 'Campos Vazios'})
    else:
        objects = Estoque.objects.all()
        filter_list = EstoqueFilter(request.POST, queryset = objects )

    return render(request, template_name='estoque/fragmentos/itens_busca_varios.html', context={'filter_list': filter_list})

@group_required('Administrador', 'Estoque','Tecnico')
@login_required(login_url='login/')
@csrf_exempt
def limpar_itens_lista(request):
    return render(request, template_name='estoque/fragmentos/itens_busca_varios.html', context={'filter_list': ''})


from brownie import DREToken
from scripts.helpers import get_account
from web3 import Web3

init_supply = Web3.toWei(9999, 'ether')

def deploy():
    account = get_account()

    dre_token = DREToken.deploy(init_supply, {'from': account})

    print(f'{dre_token.name} was deployed !')

def main():
    deploy()


from flask import g

from flask_testing import TestCase
from shapely.geometry import Point
from exeris.core import models, main

from tests import util

class EncoderTest(TestCase):
    create_app = util.set_up_app_with_database

    def setUp(self):
        rl = models.RootLocation(Point(1, 1), 111)
        pl = util.create_player('player1')
        self.character1 = util.create_character('char1', rl, pl)
        self.character2 = util.create_character('char2', rl, pl)
        str(self.character2)

    values = (0, 1, 2, 3, 10, 100, 1053218997898321983, 2 ** 63 - 4, 2 ** 64 - 3, 2 ** 64 - 1)

    def test_codec_match(self):
        g.character = self.character1
        for val in self.values:
            enc = main.encode(val)
            self.assertTrue(len(enc) > 0)
            self.assertTrue(enc.isdigit())
            self.assertEqual(main.decode(enc), val)

    def test_codec_no_match(self):
        g.character = self.character1
        encoded = [main.encode(i) for i in self.values]
        g.character = self.character2
        for val, enc in zip(self.values, encoded):
            self.assertRaises(ValueError, main.decode, enc)
            self.assertNotEqual(main.encode(val), enc)

    def test_codec_invalid(self):
        g.character = self.character1
        for val in self.values:
            enc = main.encode(val)
            self.assertRaises(ValueError, main.decode, str(int(enc) + 1))

    tearDown = util.tear_down_rollback


# Problem 7
# 10001st Prime

from tools.prime import is_prime

count = 2  # For the numbers 2 and 3
candidate = 3

while count < 10001:
    candidate += 2
    if is_prime(candidate):
        count += 1

print(candidate)


# -*- coding: utf-8 -*-
"""
Created on Thu Nov 28 09:19:50 2019

@author: Nikita
"""

#importing the required libraries

import matplotlib.pyplot as plt
import numpy as np
from math import pi
import scipy.fftpack as sf
import scipy.signal as sig
from scipy.io import wavfile
from scipy import signal
from scipy.io import loadmat
from numpy.fft import fft
from scipy.signal import firwin, lfilter
import simpleaudio as sa

plt.close("all")

# Plotting the fft of the original signal

[fs1,y1]=wavfile.read(r'C:\Users\Nikita\Downloads\SYB35.wav')
ts=1/fs1
p=len(y1)
t=[i*ts for i in range (p)]
k=[i*fs1/p for i in range (p)]
x1=fft(y1)

plt.plot(k,abs(fft(y1)))
plt.title(" FFT of Original signal")
plt.xlabel("frequency")
plt.ylabel("amplitude")
plt.show()

#plotting the fft of the noisy signal

[fs2,y2]=wavfile.read(r'C:\Users\Nikita\Downloads\noisy35.wav')
x2=fft(y2)

plt.plot(k,abs(fft(y2)))
plt.title("FFT of Noisy signal")
plt.xlabel("frequency")
plt.ylabel("amplitude")
plt.show()

#loading the .mat file
noisy = loadmat(r'C:\Users\Nikita\Downloads\noisy35.mat')
x3 = []
for i in noisy['x3']:
    x3.extend(i)

#filtering of the signal
nyq = fs2//2
norm_cutoff = 1000/nyq
fil=signal.firwin(1000,norm_cutoff)
filt = signal.lfilter(fil,1,x3)

plt.plot(t,filt)
plt.title("Filtered signal")
plt.xlabel("time")
plt.ylabel("amplitude")
plt.show()

plt.plot(k,abs(fft(filt)))
plt.title("FFT of filtered signal")
plt.xlabel("frequency")
plt.ylabel("amplitude")
plt.show()

#playing the original signal
wave_obj = sa.WaveObject.from_wave_file(r'C:\Users\Nikita\Downloads\SYB35.wav')
play_obj = wave_obj.play()
play_obj.wait_done() # wait for playback to finish before exiting

#playing the noisy signal
wave_obj = sa.WaveObject.from_wave_file(r'C:\Users\Nikita\Downloads\noisy35.wav')
play_obj = wave_obj.play()
play_obj.wait_done() # wait for playback to finish before exiting

filt *= 32767 / np.max(np.abs(filt))

# convert to 16-bit data
filt = filt.astype(np.int16)
# start playback
play_obj = sa.play_buffer(filt, 1, 2, fs2)
play_obj.wait_done()


from typing import List

from fastapi import APIRouter, Depends

from app.auth.service import get_current_user
from app.budget.serializer import Budget, BudgetHistory
from app.budget.service import BudgetService
from app.finances.serializer import Period

router = APIRouter(
    prefix='/budget',
    tags=['Бюджет']
)

@router.get('/', response_model=Budget)
def get_budget(
        user_id: int = Depends(get_current_user),
        service: BudgetService = Depends()
):
    return service.get_budget(user_id=user_id)

@router.get('/history', response_model=List[BudgetHistory])
def get_budget_history(
        period: Period = Depends(),
        user_id: int = Depends(get_current_user),
        service: BudgetService = Depends()
):
    return service.get_budget_history(
        user_id=user_id,
        period=period
    )


import nltk
from nltk import word_tokenize
from nltk.util import ngrams
from collections import Counter

import re
import urllib.request

def tokens(text):
    """
    Get all words from the corpus
    """
    return re.findall('[a-z]+', text.lower())

#Reading Text file
with open("inputTextfile",'r') as f:
    content = f.read()

WORDS = tokens(open('inputTextfile').read())
print(WORDS)
print(content)

#Tokenization
from nltk.stem import WordNetLemmatizer
print("\n")
print("LEMMATIZATION")
lemmatize_list = []
lemmatizer=WordNetLemmatizer()
for WORD in WORDS:
    print(lemmatizer.lemmatize(WORD))

#Bi-GRAM
from nltk import word_tokenize
from nltk.util import ngrams
print("\n\n")
print("BI-GRAM")
input_list = []
for WORD in WORDS:
    input_list=input_list+[WORD]

def find_trigrams(input_list):
  bigram_list = []
  for i in range(len(input_list)-2):
      bigram_list.append((input_list[i], input_list[i+1]))
  return bigram_list
print(find_trigrams(input_list))
print("\n")

#Bi-gram frequency
print("\n")
print("BIGRAM FREQUENCY")
frequencies = Counter([])
bigrams = ngrams(WORDS, 2)
frequencies += Counter(bigrams)
print(frequencies)

#Top five bi-gram word
print("\n")
print("TOP FIVE BI-GRAM WORDS")
topFiveBG=list()
for i in range (0,5) :
    topFiveBG.append(" ".join(re.findall("[a-zA-Z]+",str(frequencies).split(":")[i])))
print(topFiveBG)

#Finding all the sentences with those most repeated bi-grams
print("\n")
print("ALL SENTENCE WITH MOST BI-GRAM WORDS")
lines={}
for line in content.split("."):
    for word in topFiveBG:
        if word in line:
            if line in lines:
                pass
            else:
                lines[line]=""
result=list()
for line in lines:
    result.append(line+".")
print(result)


#!/usr/bin/python3
# pylint: disable=line-too-long
# pylint: disable=too-many-branches
# pylint: disable=too-many-nested-blocks
# pylint: disable=consider-using-dict-items

"""Ansible Dynamic Inventory
Author: Paul Wetering
Github: http://www.github.com/cusux
"""
import sys
from os import walk,path
from argparse import ArgumentParser
from re import sub
from yaml import safe_load, YAMLError

try:
    from json import loads, dumps
except ImportError:
    from simplejson import loads, dumps

### NON-NATIVE AWX IMPLEMENTATION ###
# Define wether or not AWX is being used by setting boolean
USE_AWX = 0

# Define AWX project name for the inventory, required if USE_AWX is true
PROJECT_NAME = "ansible"

if USE_AWX:
    if PROJECT_NAME == "":
        print("Please provide a valid project name in the inventory script. Exiting now...")
        sys.exit()
    else:
        PROJECT_DIR_ROOT = "/var/lib/awx/projects/" + PROJECT_NAME
        PATH_SPECIFICATION = "/inventory/"
        PATH_TO_DEFINITIONS = PROJECT_DIR_ROOT + PATH_SPECIFICATION
else:
    PROJECT_DIR_ROOT = path.dirname(path.dirname(path.realpath(__file__)))
    PATH_SPECIFICATION = "/" + PROJECT_NAME + "/inventory/"
    PATH_TO_DEFINITIONS = PROJECT_DIR_ROOT + PATH_SPECIFICATION
### END OF NON-NATIVE AWX IMPLEMENTATION ###

# Define mandatory global properties
mandatory_dicts = ['version','kind','metadata','spec']

# Define mandatory machineObjects (mo) properties
mandatory_mo_metadata = ['hostname']
mandatory_mo_spec = ['inventory_groups','inventory_vars']
mandatory_mo_inventory_vars = ['ansible_host']

# Define mandatory groupObjects (go) properties
mandatory_go_metadata = ['groupname']
mandatory_go_spec = ['parent_groups','group_vars']

sanity = {}
list_of_definitions = []
# The basic layout for the dict object as defined by Ansible Development documentation
inventory_object = { '_meta': { 'hostvars': {} }, 'all': { 'children': [ 'ungrouped' ] }}
# Prevent unnecessary host iteration on a list object by predefining at least the `_meta` object
inventory_list_object = inventory_object
inventory_host_object = {}

# r=root, d=directories, f = files
for r, d, f in walk(PATH_TO_DEFINITIONS):
    for yamlfile in f:
        list_of_definitions.append(path.join(r, yamlfile))

class DynamicInventory:
    """Main class to produce the dynamic inventory"""
    def __init__(self):
        self.inventory = {}
        self.read_cli_args()

        # Called with `--check`.
        if self.args.check:
            self.inventory = self.sanity_check()
        # Called with `--list`.
        elif self.args.list:
            self.inventory = self.list_inventory()
        # Called with `--host [hostname]`.
        elif self.args.host:
            self.inventory = self.host_details(self.args.host)
        else:
            self.inventory = self.dynamic_inventory()

        print(dumps(self.inventory))

    @classmethod
    def sanity_dict_check(cls, main_key, item_key):
        """Validate inventory object existence in sanity dict"""
        if not main_key in sanity:
            sanity[main_key] = {}
        if not item_key in sanity[main_key].keys():
            sanity[main_key][item_key] = []

        return sanity

    @classmethod
    def sanity_check(cls):
        """Validate the inventory objects"""
        for file in list_of_definitions:
            with open(file, 'r', encoding='UTF8') as stream:
                try:
                    file_object = safe_load(stream)
                    file_name = sub("[^A-Za-z0-9.]+", '', str(file.split('/')[-1:]))
                    if file_object['kind'] == 'machineObject':
                        for dict_item in mandatory_dicts:
                            if not dict_item in file_object.keys():
                                cls.sanity_dict_check('invalid_objects', file_name)
                                sanity['invalid_objects'][file_name].append(dict_item)
                            else:
                                if dict_item == "metadata":
                                    for meta_item in mandatory_mo_metadata:
                                        if meta_item not in file_object[dict_item].keys():
                                            cls.sanity_dict_check('invalid_objects', file_name)
                                            sanity['invalid_objects'][file_name].append({'metadata' : [meta_item]})
                                elif dict_item == "spec":
                                    for spec_item in mandatory_mo_spec:
                                        if (spec_item not in file_object[dict_item].keys()) or (file_object[dict_item][spec_item] is None):
                                            cls.sanity_dict_check('invalid_objects', file_name)
                                            sanity['invalid_objects'][file_name].append(spec_item)
                                        elif spec_item == "inventory_vars":
                                            for inventory_vars_item in mandatory_mo_inventory_vars:
                                                if inventory_vars_item not in file_object[dict_item][spec_item]:
                                                    cls.sanity_dict_check('invalid_objects', file_name)
                                                    sanity['invalid_objects'][file_name].append({spec_item : [inventory_vars_item]})
                    if file_object['kind'] == 'groupObject':
                        for dict_item in mandatory_dicts:
                            if not dict_item in file_object.keys():
                                cls.sanity_dict_check('invalid_objects', file_name)
                                sanity['invalid_objects'][file_name].append(dict_item)
                            else:
                                if dict_item == "metadata":
                                    for meta_item in mandatory_go_metadata:
                                        if meta_item not in file_object[dict_item].keys():
                                            cls.sanity_dict_check('invalid_objects', file_name)
                                            sanity['invalid_objects'][file_name].append({'metadata' : [meta_item]})
                                elif dict_item == "spec":
                                    for spec_item in mandatory_go_spec:
                                        if (spec_item not in file_object[dict_item].keys()) or (file_object[dict_item][spec_item] is None):
                                            cls.sanity_dict_check('invalid_objects', file_name)
                                            sanity['invalid_objects'][file_name].append(spec_item)
                except YAMLError as error:
                    return error
        if not any(sanity.values()):
            sanity['result'] = ['Sanity check PASSED.']
        else:
            sanity['result'] = ['Sanity check FAILED.']
        return sanity

    @classmethod
    def dynamic_inventory(cls):
        """Compile the dynamic inventory"""
        # Compile hosts and host vars
        for file in list_of_definitions:
            with open(file, 'r', encoding='UTF8') as stream:
                try:
                    file_object = safe_load(stream)
                    if file_object['kind'] == 'machineObject':
                        hostname = file_object['metadata']['hostname']
                        inventory_object['_meta']['hostvars'].update({ hostname : file_object['spec']['inventory_vars'] })
                        if not file_object['spec']['inventory_groups']:
                            if 'ungrouped' not in inventory_object:
                                inventory_object.update({ 'ungrouped' : { 'hosts': [] } })
                            inventory_object['ungrouped']['hosts'].append( hostname )
                        else:
                            for group in file_object['spec']['inventory_groups']:
                                if not group in inventory_object:
                                    inventory_object.update({ group : { 'hosts': [] } })
                                inventory_object[group]['hosts'].append( hostname )
                except YAMLError as error:
                    return error

        # Map groups to groups and hosts
        for file in list_of_definitions:
            with open(file, 'r', encoding='UTF8') as stream:
                try:
                    file_object = safe_load(stream)
                    if file_object['kind'] == 'groupObject':
                        groupname = file_object['metadata']['groupname']
                        if not groupname in inventory_object['all']['children']:
                            if not file_object['spec']['parent_groups']:
                                inventory_object['all']['children'].append(groupname)
                        for parent_group in file_object['spec']['parent_groups']:
                            if not parent_group in inventory_object:
                                inventory_object.update({ parent_group : { 'children': [groupname] } })
                            elif not 'children' in inventory_object[parent_group]:
                                inventory_object[parent_group].update({'children' : [groupname] })
                            else:
                                inventory_object[parent_group]['children'].append(groupname)
                except YAMLError as error:
                    return error

        # Map group_vars to hosts
        # Yes, below piece of shit coding is nasty, but for now we'll keep it this way.
        for file in list_of_definitions:
            with open(file, 'r', encoding='UTF8') as stream:
                try:
                    file_object = safe_load(stream)
                    if file_object['kind'] == 'groupObject':
                        for group in inventory_object:
                            if not group in ['_meta','all']:
                                for section in inventory_object[group]:
                                    if not section == 'children':
                                        for host in inventory_object[group][section]:
                                            if file_object['metadata']['groupname'] == group:
                                                for group_var in file_object['spec']['group_vars'].keys():
                                                    inventory_object['_meta']['hostvars'][host].update( { group_var : file_object['spec']['group_vars'][group_var] } )
                                    if section == 'children':
                                        for child_group in inventory_object[group][section]:
                                            if child_group in inventory_object:
                                                if 'hosts' in inventory_object[child_group].keys():
                                                    for host in inventory_object[child_group]['hosts']:
                                                        if file_object['metadata']['groupname'] in [group, child_group]:
                                                            for group_var in file_object['spec']['group_vars'].keys():
                                                                inventory_object['_meta']['hostvars'][host].update( { group_var : file_object['spec']['group_vars'][group_var] } )
                except YAMLError as error:
                    return error
        return loads(dumps(inventory_object, sort_keys=True))

    @classmethod
    def list_inventory(cls):
        """Compile host list with inventory objects"""
        lst_inventory_object = cls.dynamic_inventory()
        for file in list_of_definitions:
            with open(file, 'r', encoding='UTF8') as stream:
                try:
                    file_object = safe_load(stream)
                    if file_object['kind'] == 'machineObject':
                        for group in file_object['spec']['inventory_groups']:
                            if not group in inventory_list_object:
                                inventory_list_object.update({ group : {} })
                            if not 'hosts' in inventory_list_object[group].keys():
                                inventory_list_object[group].update({ 'hosts' : [] })
                            inventory_list_object[group]['hosts'].append(file_object['metadata']['hostname'])
                    if file_object['kind'] == 'groupObject':
                        groupname = file_object['metadata']['groupname']
                        for group_var in file_object['spec']['group_vars']:
                            if not group_var in inventory_list_object:
                                inventory_list_object.update({ groupname : { 'vars': file_object['spec']['group_vars'] } })
                            else:
                                inventory_list_object[groupname]['vars'].append(file_object['spec']['group_vars'][group_var])
                        if groupname in lst_inventory_object.keys():
                            if 'children' in lst_inventory_object[groupname].keys():
                                for child in lst_inventory_object[groupname]['children']:
                                    if not 'children' in inventory_list_object[groupname].keys():
                                        inventory_list_object[groupname].update({ 'children' : [] })
                                        inventory_list_object[groupname]['children'].append(child)
                                    else:
                                        inventory_list_object[groupname]['children'].append(child)
                except YAMLError as error:
                    return error
        return loads(dumps(inventory_list_object, sort_keys=True))

    def host_details(self,hostname):
        """Compile inventory details for given host"""
        hst_inventory_object = self.dynamic_inventory()
        for file in list_of_definitions:
            if hostname in file:
                hst_inventory_host_object = hst_inventory_object['_meta']['hostvars'][hostname]
        return loads(dumps(hst_inventory_host_object, sort_keys=True))

    def read_cli_args(self):
        """Read the command line args passed to the script"""
        parser = ArgumentParser()
        parser.add_argument('--check', action = 'store_true')
        parser.add_argument('--list', action = 'store_true')
        parser.add_argument('--host', action = 'store')
        self.args = parser.parse_args()

# Return the dynamic inventory
DynamicInventory()


#! python3
import SimpleITK
import SimpleITK as sitk
import matplotlib.pyplot as plt
import numpy as np
import csv
import os
from utils import swap_labels
#import winshell

############################### CONFIGURATION #####################################
DEBUG = 0 # In debug mode, all the intermediate iamges are written.
USE_COSINES_AND_ORIGIN = 1

############################## REGISTRATION PARAMETER FILES ######################
similarityMetricForReg = 'NMI'
parameterFilesPath = '../../Data/Elastix/'
paramFileRigid = 'Parameters_Rigid_' + similarityMetricForReg
paramFileAffine = 'Parameters_Affine_' + similarityMetricForReg
paramFileNonRigid = 'Parameters_BSpline_NCC_1000iters_2048samples'#Par0000bspline_500'

############################### IMAGES AVAILABLE ###################################

dataPath = '../../Data/LumbarSpine3D/RawData/' # Base data path.
outputPath = '../../Data/LumbarSpine3D/ResampledData/' # Base data path.
outputAugmentedLinearPath = '../../Data/LumbarSpine3D/TrainingSetAugmentedLinear/' # Base data path.
outputAugmentedNonLinearPath = '../../Data/LumbarSpine3D/TrainingSetAugmentedNonLinear/' # Base data path.
if not os.path.exists(outputPath):
    os.makedirs(outputPath)
if not os.path.exists(outputAugmentedLinearPath):
    os.makedirs(outputAugmentedLinearPath)
if not os.path.exists(outputAugmentedNonLinearPath):
    os.makedirs(outputAugmentedNonLinearPath)
# Get the atlases names and files:
# Look for the folders or shortcuts:
data = os.listdir(dataPath)
data = sorted(data)
# Image format extension:
extensionShortcuts = 'lnk'
strForShortcut = '-> '
extensionImages = 'mhd'
tagInPhase = '_I'
tagAutLabels = '_aut'
tagManLabels = '_labels'

#for folder in data:
#    auxPath = dataPath + folder + '\\'
#    files = os.listdir(auxPath)
def main(imagesPath, suffixIntensityImages, suffixLabelsImage, outputPath):
    atlasNames = []  # Names of the atlases
    atlasImageFilenames = list(2)  # Filenames of the intensity images
    atlasLabelsFilenames = []  # Filenames of the label images
    folderIndex = []
    # Create subdirectories for the intensity images and labels images.
    # The intensity images can be different image types which will be a different channel:
    #for i in range(0, len(suffixIntensityImages)):
    os.makedirs(outputPath + "ImagesTr" + os.sep)
    # Now the labels subdir:
    os.makedirs(outputPath + "LabelsTr" + os.sep)
    # Check the input
    for filename in data:
        name, extension = os.path.splitext(filename)
        # Substract the tagInPhase:
        atlasName = name.split('_')[0]
        if name.endswith(suffixLabelsImage) and extension.endswith(extensionImages):
            # Filename for the labels
            filenameLabels = filename
            # We have the labels filename, and now we need to identify the intensity images (more than one if there
            # are multiple channels):
            atlasNames.append(atlasName)
            # Check intensity images:
            for suffix in suffixIntensityImages:
                # Check if filename is the in phase header and the labels exists:
                filenameImages = imagesPath + atlasName + suffix + '.' + extensionImages
                if os.path.exists(filenameImages):
                    # Intensity image:
                    atlasImageFilenames.append(filenameImages)

            # Check if filename is the in phase header and the labels exists:
            filenameImages = dataPath + atlasName + suffixIntensityImages + '.' + extensionImages

            # Manual Labels image:
            atlasLabelsFilenames.append(filenameLabels)

    print("Number of atlases images: {0}".format(len(atlasNames)))
    print("List of atlases: {0}\n".format(atlasNames))

    ################################### REFERENCE IMAGE FOR THE REGISTRATION #######################
    indexReference = 1
    referenceImage = sitk.ReadImage(atlasImageFilenames[indexReference])
    print('Reference image: {0}. Voxel size: {1}'.format(atlasImageFilenames[indexReference], referenceImage.GetSize()))

    ################################### READ IMAGES, EXTRACT SLICES AND REGISTER IMAGES TO THE REFERENCE ########################################
    for i in range(0, len(atlasNames)):
        print('Altas:{0}\n'.format(atlasImageFilenames[i]))
        ############## 1) READ IMAGE WITH LABELS #############     #poner 3
        # Read target image:
        atlasImage = sitk.ReadImage(atlasImageFilenames[i])
        atlasManLabel = sitk.ReadImage(atlasLabelsFilenames[i])

        # Cast the image as float:
        atlasImage = sitk.Cast(atlasImage, sitk.sitkFloat32)   #lo convierte en float 32
        # Rigid registration to match voxel size and FOV.
        ############## 1) RIGID REGISTRATION #############
        # elastixImageFilter filter
        elastixImageFilter = sitk.ElastixImageFilter()
        # Parameter maps:
        parameterMapVector = sitk.VectorOfParameterMap()
        parameterMapVector.append(elastixImageFilter.ReadParameterFile(parameterFilesPath + paramFileRigid + '.txt'))
        # Registration:
        elastixImageFilter.SetFixedImage(referenceImage)
        elastixImageFilter.SetMovingImage(atlasImage)
        elastixImageFilter.SetParameterMap(parameterMapVector)
        elastixImageFilter.Execute()
        # Get result and apply transform to labels:
        # Get the images:
        atlasImage = elastixImageFilter.GetResultImage()
        # Apply transform:
        transformixImageFilter = sitk.TransformixImageFilter()
        transformixImageFilter.SetMovingImage(atlasManLabel)
        transformixImageFilter.SetTransformParameterMap(elastixImageFilter.GetTransformParameterMap())
        transformixImageFilter.SetTransformParameter("FinalBSplineInterpolationOrder", "0")
        transformixImageFilter.SetTransformParameter("ResultImagePixelType", "unsigned char")
        transformixImageFilter.Execute()
        transformixImageFilter.SetMovingImage(atlasManLabel)
        transformixImageFilter.Execute()
        atlasManLabel = sitk.Cast(transformixImageFilter.GetResultImage(), sitk.sitkUInt8)
        ## Crop The resulting image

        # atlasSliceImage = atlasSliceImage[100:700, 160:480, :]
        # atlasSliceManLabel = atlasSliceManLabel[100:700, 160:480, :]

        # Resample images:
        original_spacing = atlasImage.GetSpacing()
        original_size = atlasImage.GetSize()
        origin = atlasImage.GetOrigin()
        direction = atlasImage.GetDirection()

        new_spacing = [spc * 2 for spc in original_spacing]
        new_spacing[2] = original_spacing[2]
        new_size = [int(sz / 2) for sz in original_size]
        new_size[2] = original_size[2]

        #resampled_image.SetDirection(direction)
        resampler = sitk.ResampleImageFilter()
        resampler.SetSize(new_size)
        resampler.SetOutputSpacing(new_spacing)
        resampler.SetOutputOrigin(origin)
        resampled_image = resampler.Execute(atlasImage)
        resampler.SetInterpolator(sitk.sitkNearestNeighbor)
        resampled_label = resampler.Execute(atlasManLabel)
        # write the 3d images:
        sitk.WriteImage(resampled_image, outputPath + atlasNames[i] + '.' + extensionImages)
        sitk.WriteImage(resampled_label, outputPath + atlasNames[i] + tagManLabels + '.' + extensionImages)

if __name__ == '__main__':
    main()


import numpy as np
import unittest
from sklearn.metrics import accuracy_score, precision_score
from sklearn.tree import DecisionTreeClassifier

"""The Node class represents a node in the decision tree. It has several attributes,
including feature_index, threshold, value, left, and right. These attributes store
information about the feature used to split the data at this node, the threshold value
for the split, the predicted value if this node is a leaf node, and the left and right
child nodes."""
class Node:
    def __init__(
            self,
            feature_index=None,
            threshold=None,
            value=None,
            left=None,
            right=None,
    ):
        self.feature_index = feature_index
        self.threshold = threshold
        self.value = value
        self.left = left
        self.right = right

"""The _most_common_label function takes in a target vector y and returns the most common label in y.
If there is more than one label with the highest count, one of them is chosen randomly."""
def _most_common_label(y):
    unique, counts = np.unique(y, return_counts=True)
    max_indices = np.argwhere(counts == counts.max()).flatten()
    if len(max_indices) > 1:
        max_index = np.random.choice(max_indices)
    else:
        max_index = max_indices[0]
    return unique[max_index]

"""The _entropy function calculates the entropy of a target vector y. Entropy is a measure of impurity or disorder in a dataset.
The goal of a decision tree is to split the data in such a way that the resulting subsets have lower entropy (i.e., are more pure)
than the original dataset."""
def _entropy(y):
    unique, counts = np.unique(y, return_counts=True)
    probabilities = counts / counts.sum()
    entropy = sum(probabilities * -np.log2(probabilities))
    return entropy

"""The _gini_index function calculates the Gini index of a target vector y. The Gini index is another
measure of impurity or disorder in a dataset. Like entropy, it can be used to evaluate the quality of
a split in a decision tree."""
def _gini_index(y):
    unique, counts = np.unique(y, return_counts=True)
    probabilities = counts / counts.sum()
    gini_index = 1 - sum(probabilities ** 2)
    return gini_index

"""The _information_gain function calculates the information gain of a split. Information gain measures
the reduction in entropy (or Gini index) achieved by splitting the data on a particular feature and threshold.
The function takes in several arguments, including the target vector y, a column of the feature matrix X_column,
a threshold value for the split, and the criterion used to measure impurity ('entropy' or 'gini'). It returns
the information gain achieved by splitting X_column on the given threshold."""
def _information_gain(y, X_column, threshold, criterion):
    if criterion == 'entropy':
        parent = _entropy(y)
    elif criterion == 'gini':
        parent = _gini_index(y)

    left_indices, right_indices = _split(X_column, threshold)

    if len(left_indices) == 0 or len(right_indices) == 0:
        return 0

    n = len(y)
    len_left, len_right = len(left_indices), len(right_indices)

    if criterion == 'entropy':
        left, right = (
            _entropy(y[left_indices]),
            _entropy(y[right_indices]),
        )
    elif criterion == 'gini':
        left, right = (
            _gini_index(y[left_indices]),
            _gini_index(y[right_indices]),
        )

    child = (len_left / n) * left + (len_right / n) * right

    ig = parent - child
    return ig

"""The _gain_ratio function calculates the gain ratio of a split. Gain ratio is similar to information
gain but normalizes the information gain by dividing it by the entropy of the feature used for splitting.
This can help prevent bias towards features with many possible values."""
def _gain_ratio(y, X_column, threshold):
    info_gain = _information_gain(y, X_column, threshold, 'entropy')

    left_indices, right_indices = _split(X_column, threshold)

    if len(left_indices) == 0 or len(right_indices) == 0:
        return 0

    n = len(y)
    n_left, n_right = len(left_indices), len(right_indices)
    p_left, p_right = n_left / n, n_right / n
    attr_entropy = (
            -p_left * np.log2(p_left) - p_right * np.log2(p_right)
    )

    gain_ratio = info_gain / attr_entropy
    return gain_ratio

"""The _split function takes in a column of the feature matrix X_column and a threshold value and
returns two arrays containing the indices of rows that should go to the left and right child nodes
after splitting on this feature and threshold."""
def _split(X_column, threshold):
    left_indices = np.argwhere(X_column <= threshold).flatten()
    right_indices = np.argwhere(X_column > threshold).flatten()

    return left_indices, right_indices

"""The DecisionTree class implements a decision tree classifier. It has several attributes that control its behavior,
including criterion, which specifies the criterion used to measure impurity ('entropy', 'gini', or 'gain_ratio'),
max_depth, which specifies the maximum depth of the tree, min_samples_split, which specifies the minimum number of
samples required to split an internal node, and max_leaf_nodes, which specifies the maximum number of leaf nodes in the tree."""
class DecisionTree:

    def __init__(
            self,
            criterion='entropy',
            max_depth=None,
            min_samples_split=2,
            max_leaf_nodes=20,
    ):
        self.criterion = criterion
        self.max_depth = max_depth
        self.min_samples_split = min_samples_split
        self.max_leaf_nodes = max_leaf_nodes

    """The fit method takes in a feature matrix X and a target vector y and builds a decision tree using these data.
    It calls the _grow_tree method to recursively build the tree."""
    def fit(self, X, y):
        self.tree_ = self._grow_tree(X, y)

    """The predict method takes in a feature matrix X and returns an array containing predicted values for each row in X.
    It calls the _predict method to make predictions for individual rows."""
    def predict(self, X):
        return [self._predict(inputs) for inputs in X]

    """The _grow_tree method recursively builds a decision tree using depth-first search. It takes in several arguments,
    including a feature matrix X, a target vector y, and an optional depth argument that keeps track of how deep we are in"""
    def _grow_tree(self, X, y, depth=0):
        n_samples, n_features = X.shape
        n_labels = len(np.unique(y))

        if (
                depth >= self.max_depth
                or n_labels == 1
                or n_samples < self.min_samples_split
        ):
            leaf_value = _most_common_label(y)
            return Node(value=leaf_value)

        feature_indices = np.arange(n_features)
        best_feature, best_threshold = self._best_criteria(
            X, y, feature_indices
        )
        left_indices, right_indices = _split(
            X[:, best_feature], best_threshold
        )

        left = self._grow_tree(X[left_indices, :], y[left_indices], depth + 1)
        right = self._grow_tree(X[right_indices, :], y[right_indices], depth + 1)

        return Node(
            best_feature,
            best_threshold,
            _most_common_label(y),
            left,
            right,
        )

    """The _predict method takes in a single row of data inputs and traverses the decision tree to make a prediction.
    It starts at the root node and moves down the tree by comparing inputs to the threshold at each node and following
    the appropriate child node until it reaches a leaf node. The predicted value is then returned."""
    def _predict(self, inputs):
        node = self.tree_

        while node.left:
            if inputs[node.feature_index] < node.threshold:
                node = node.left
            else:
                node = node.right

        return node.value

    """The _best_criteria method finds the best feature and threshold to split the data on. It does this by iterating over all
    features and all possible thresholds for each feature and calculating the information gain (or gain ratio) achieved by
    splitting on that feature and threshold. The feature and threshold with the highest information gain (or gain ratio) are returned."""
    def _best_criteria(self, X, y, feature_indices):
        best_gain = -1
        split_index, split_threshold = None, None

        for feature_index in feature_indices:
            X_column = X[:, feature_index]
            thresholds = np.unique(X_column)

            for threshold in thresholds:
                if self.criterion in ['entropy', 'gini']:
                    gain = _information_gain(
                        y,
                        X_column,
                        threshold,
                        self.criterion,
                    )
                elif self.criterion == 'gain_ratio':
                    gain = _gain_ratio(y, X_column, threshold)
                else:
                    raise ValueError(
                        "Invalid criterion: {}".format(self.criterion)
                    )

                if gain > best_gain:
                    best_gain = gain
                    split_index = feature_index
                    split_threshold = threshold

        return split_index, split_threshold

#test class
class TestDecisionTree(unittest.TestCase):

    def generate_random_dataset(self, n_samples, n_features, n_classes):
        X = np.random.rand(n_samples, n_features)
        y = np.random.randint(0, n_classes, size=n_samples)
        return X, y

    def test_predict(self):
        X, y = self.generate_random_dataset(1000, 10, 2)
        Xp, yp = self.generate_random_dataset(300, 10, 2)
        dt = DecisionTree(max_depth=10)
        dt.fit(X, y)
        y_pred = dt.predict(Xp)
        self.assertEqual(len(y_pred), len(yp))

        print("Custom Decision Tree")
        print("Accuracy:", accuracy_score(yp, y_pred))
        print("Precision:", precision_score(yp, y_pred))

        # scikit-learn implementation
        dt_sklearn = DecisionTreeClassifier(max_depth=10)
        dt_sklearn.fit(X, y)
        y_pred_sklearn = dt_sklearn.predict(Xp)

        print("Scikit-learn Decision Tree")
        print("Accuracy:", accuracy_score(yp, y_pred_sklearn))
        print("Precision:", precision_score(yp, y_pred_sklearn))

def main():
    test_dt = TestDecisionTree()
    test_dt.test_predict()

if __name__ == "__main__":
    main()