#! -*- coding: utf-8 -*-
import logging
from transformers import (
    AutoConfig,
    AutoModelWithLMHead,
    AutoTokenizer,
    DataCollatorForLanguageModeling,
    TextDataset,
    Trainer,
    TrainingArguments,
    set_seed,
    AlbertForMaskedLM,
    BertTokenizer,
    AutoModel,
)
import math
import os
from msnlp.config import SUPPORT_MODELS, SUPPORT_MODEL_NAMES

logger = logging.getLogger(__name__)

class MSPretrainedModel:
    """MS pretrained model class."""

    def __init__(self, pretrain_name: str):
        super().__init__()
        self.config = AutoConfig.from_pretrained(pretrain_name)

        if pretrain_name not in SUPPORT_MODEL_NAMES:
            raise ValueError(
                '{} not supported right now. '
                'You could use `MSPretrainedModel.support_models()`'
                ' to see which supported models.'.format(pretrain_name))
        self._from_pretrained(pretrain_name)

    def _from_pretrained(self, pretrain_name: str):
        r"""
        根据模型名字，加载不同的模型.
    """
        if 'albert' in pretrain_name:
            model = AlbertForMaskedLM.from_pretrained(pretrain_name)
            tokenizer = BertTokenizer.from_pretrained(pretrain_name)
        elif 'bert' in pretrain_name:
            tokenizer = AutoTokenizer.from_pretrained(pretrain_name)
            model = AutoModelWithLMHead.from_pretrained(pretrain_name)

        self.model = model
        self.tokenizer = tokenizer

    @classmethod
    def support_models(cls):
        r"""
        获取能支持的预训练模型的信息.
    """
        return SUPPORT_MODELS

    def fine_tune(
            self,
            train_file,
            model_path='./',
            output_dir='./',
            block_size=128,
            eval_file=None,
            seed=None):
        r"""
        用非标注语料来微调预训练模型.

        Params:
            train_file: training dataset file.
    """
        if not seed:
            seed = random.randint(0, 2020)
        set_seed(seed)

        if self.config.model_type in ["bert", "roberta", "distilbert", "camembert"]:
            mlm = True
        else:
            mlm = False

        training_args = TrainingArguments(output_dir=output_dir)
        train_dataset = TextDataset(
            tokenizer=self.tokenizer, file_path=train_file, block_size=block_size)
        if eval_file:
            eval_dataset = TextDataset(
                tokenizer=self.tokenizer, file_path=eval_file, block_size=block_size)
        else:
            eval_dataset = None
        data_collator = DataCollatorForLanguageModeling(
            tokenizer=self.tokenizer, mlm=mlm)

        # Initialize our Trainer
        trainer = Trainer(
            model=self.model,
            args=training_args,
            data_collator=data_collator,
            train_dataset=train_dataset,
            eval_dataset=eval_dataset,
            prediction_loss_only=True,
        )
        trainer.train(model_path=model_path)
        trainer.save_model()
        self.tokenizer.save_pretrained(output_dir)

        # Evalutation
        if eval_file:
            logger.info("*** Evaluate ***")
            eval_output = trainer.evaluate()
            perplexity = math.exp(eval_output["eval_loss"])
            result = {"perplexity": perplexity}
            output_eval_file = os.path.join(
                training_args.output_dir, "eval_results_lm.txt")
            with open(output_eval_file, "w") as writer:
                logger.info("***** Eval results *****")
                for key in sorted(result.keys()):
                    logger.info("  %s = %s", key, str(result[key]))
                    writer.write("%s = %s\n" % (key, str(result[key])))

        return result

    # todo
    def sen_embeddings(self, text):
        r"""
        输出一个文本的句向量.
    """
        pass

    def _get_dataset(file_path, block_size, evaluate=False):
        return TextDataset(
            tokenizer=self.tokenizer, file_path=file_path, block_size=block_size)

def test():
    train_file = '/Users/ijinmao/Downloads/wikitext-2-raw/news.chinese.train.raw'
    valid_file = '/Users/ijinmao/Downloads/wikitext-2-raw/news.chinese.valid.raw'
    pretrained_model = MSPretrainedModel('bert-base-chinese')
    pretrained_model.fine_tune(
        train_file,
        eval_file=valid_file,
        output_dir='../../../tmp',
        model_path='../../../tmp')

if __name__ == '__main__':
    test()


"""Interacting with graphs
==========================

This module contains classes and functions for inspecting, manipulating, and traversing graphs
"""
import logging
from collections import OrderedDict

import attr
import networkx as nx
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord

from cortexpy.constants import EdgeTraversalOrientation, EdgeDFSTraversalDirection
from cortexpy.graph.cortex import CortexDiGraph, ConsistentCortexDiGraph
from cortexpy.graph.parser.kmer import revcomp_target_to_match_ref
from cortexpy.graph.serializer.unitig import UnitigCollapser
from cortexpy.links import UnitigLinkWalker, LinkedGraphTraverser
from cortexpy.utils import lexlo, revcomp

logger = logging.getLogger(__name__)

def make_multi_graph(graph):
    if isinstance(graph, nx.Graph):
        return nx.MultiGraph(graph)
    if isinstance(graph, nx.DiGraph):
        return nx.MultiDiGraph(graph)
    return graph

@attr.s(slots=True)
class Interactor(object):
    graph = attr.ib()

    @classmethod
    def from_graph(cls, graph):
        return cls(graph=graph)

    def compose_in_graph(self, graph_to_add):
        """Compose two graphs and store the result in the interactor graph"""
        for g in [graph_to_add, self.graph]:
            assert g.is_multigraph()
            assert g.is_directed()
        self.graph.add_nodes_from(graph_to_add.nodes(data=True))
        if isinstance(graph_to_add, nx.Graph):
            self.graph.add_edges_from(graph_to_add.edges(keys=True))

    def find_nodes_of_tips_less_than(self, n):
        nodes_to_prune = set()
        graph = make_multi_graph(self.graph)
        num_tips = 0
        num_tips_to_prune = 0
        for node, direction_of_end in list(edge_nodes_of(self.graph)):
            tip = find_tip_from(
                n=n,
                graph=self.graph,
                start=node,
                next_node_generator=node_generator_from_edges(
                    nx.edge_dfs(
                        graph,
                        source=node,
                        orientation=EdgeTraversalOrientation.other(direction_of_end).name
                    )
                )
            )
            num_tips += 1
            if tip:
                nodes_to_prune |= tip
                num_tips_to_prune += 1
        logger.info('Found %s of %s tips shorter than %s.', num_tips_to_prune, num_tips, n)
        return nodes_to_prune

    def prune_tips_less_than(self, n):
        logger.info(f'Removing tips shorter than {n} k-mers')
        nodes_to_prune = self.find_nodes_of_tips_less_than(n)
        logger.info('Pruning %s nodes', len(nodes_to_prune))
        self.graph.remove_nodes_from(nodes_to_prune)
        return self

    def make_graph_nodes_consistent(self, seed_kmer_strings=None):
        """
        Take a Cortex graph and make all nodes have kmer_strings that are consistent with each
        other. If a seed kmer string is provided, then start with that seed kmer.
        """
        if self.graph.is_consistent():
            return self
        if seed_kmer_strings is None:
            seed_kmer_strings = []
        graph = CortexDiGraph(self.graph)
        new_graph = ConsistentCortexDiGraph(graph=self.graph.graph)

        seeds = SeedKmerStringIterator.from_all_kmer_strings_and_seeds(self.graph.nodes(),
                                                                       seed_kmer_strings)

        for seed, lexlo_seed in seeds:
            new_graph.add_node(seed, kmer=self.graph.node[lexlo_seed])
            seeds.remove(lexlo_seed)
            for source, sink, key, direction in nx.edge_dfs(graph, lexlo_seed, 'ignore'):
                if direction == 'forward':
                    rc_after_ref_kmer = True
                    ref, target = source, sink
                elif direction == 'reverse':
                    ref, target = sink, source
                    rc_after_ref_kmer = False
                else:
                    raise Exception("unknown direction: {}".format(direction))
                if ref not in new_graph.node:
                    ref = revcomp(ref)
                    rc_after_ref_kmer = not rc_after_ref_kmer
                matched_target, _ = revcomp_target_to_match_ref(target, ref, rc_after_ref_kmer)
                new_graph.add_node(matched_target, kmer=graph.node[matched_target])
                seeds.remove(lexlo(matched_target))
        self.graph = new_graph
        return self

    def keep_color(self, color):
        self.graph = make_copy_of_color_for_kmer_graph(self.graph, color, include_self_refs=False)
        return self

    def all_simple_paths(self, extra_incoming_node=None, links=None):
        if not isinstance(self.graph, nx.Graph):
            assert self.graph.is_consistent()
        if extra_incoming_node:
            for neighbor in self.graph.pred[extra_incoming_node]:
                for color in self.graph.graph['colors']:
                    self.graph.remove_edge(neighbor, extra_incoming_node, color)
        unitig_graph = UnitigCollapser(self.graph) \
            .collapse_kmer_unitigs() \
            .unitig_graph
        unitig_graph = nx.DiGraph(unitig_graph)
        unitig_graph = nx.convert_node_labels_to_integers(unitig_graph)
        path_converter = UnitigGraphPathConverter.from_unitig_graph(unitig_graph)

        record_idx = 0
        in_nodes = sorted(list(in_nodes_of(unitig_graph)))
        logger.info(f"Found {len(in_nodes)} incoming tip nodes")
        out_nodes = set(sorted(list(out_nodes_of(unitig_graph))))
        logger.info(f"Found {len(out_nodes)} outgoing tip nodes")
        for sidx, source in enumerate(in_nodes):
            if source in out_nodes:
                logger.info('Incoming node %s; %s outgoing nodes; Path number %s',
                            sidx,
                            len(out_nodes),
                            record_idx)
                yield SeqRecord(Seq(unitig_graph.node[source]['unitig']), id=str(record_idx),
                                description='')
                record_idx += 1
                continue
            if links is not None:
                wrapped_graph = LinkedGraphTraverser.from_graph_and_link_walker(
                    unitig_graph,
                    UnitigLinkWalker.from_links_unitigs_kmer_size_unitig(
                        links,
                        unitig_graph,
                        unitig_graph.graph['kmer_size'],
                        source
                    )
                )
                paths = nx.all_simple_paths(wrapped_graph,
                                            source,
                                            out_nodes,
                                            cutoff=len(self.graph) - 1)
            else:
                paths = nx.all_simple_paths(unitig_graph,
                                            source,
                                            out_nodes,
                                            cutoff=len(self.graph) - 1)

            for pidx, path in enumerate(paths):
                if pidx % 100000 == 0:
                    logger.info('Incoming node %s; %s outgoing nodes; Path number %s', sidx,
                                len(out_nodes), record_idx)
                yield SeqRecord(
                    Seq(path_converter.to_contig(path)),
                    id=str(record_idx),
                    description='')
                record_idx += 1

@attr.s(slots=True)
class SeedKmerStringIterator:
    """Iterates seeds and their lexlo representations that exist in the supplied all_kmers:

    >>> list(SeedKmerStringIterator.from_all_kmer_strings_and_seeds(['AAC'], ['GTT']))
    [('GTT', 'AAC')]

    Kmers that are not in the seed list are return after that:

    >>> list(SeedKmerStringIterator.from_all_kmer_strings_and_seeds(['AAA', 'AAC'], ['GTT']))
    [('GTT', 'AAC'), ('AAA', 'AAA')]

    Seeds that do not exist in the all_kmers are not returned.

    >>> list(SeedKmerStringIterator.from_all_kmer_strings_and_seeds([], ['CCC']))
    []

    Returned kmers from all_kmers list are returned in order.

    >>> list(SeedKmerStringIterator.from_all_kmer_strings_and_seeds(['AAA', 'AAG', 'AAC'], []))
    [('AAA', 'AAA'), ('AAG', 'AAG'), ('AAC', 'AAC')]
    """
    seed_kmer_strings = attr.ib()
    _unseen_lexlo_kmer_strings = attr.ib()
    _seen_lexlo_kmer_strings = attr.ib(attr.Factory(set))

    @classmethod
    def from_all_kmer_strings_and_seeds(cls, all_kmers, seeds):
        return cls(list(seeds),
                   OrderedDict.fromkeys(lexlo(k_string) for k_string in all_kmers))

    def __iter__(self):
        return self

    def __next__(self):
        while self.seed_kmer_strings:
            seed = self.seed_kmer_strings.pop()
            lexlo_seed = lexlo(seed)
            if lexlo_seed not in self._unseen_lexlo_kmer_strings:
                continue
            self._seen_lexlo_kmer_strings.add(lexlo_seed)
            return seed, lexlo_seed
        while self._unseen_lexlo_kmer_strings:
            unseen, _ = self._unseen_lexlo_kmer_strings.popitem(last=False)
            if unseen in self._seen_lexlo_kmer_strings:
                continue
            self._seen_lexlo_kmer_strings.add(unseen)
            return unseen, unseen
        raise StopIteration

    def remove(self, lexlo_kmer_string):
        assert lexlo_kmer_string == lexlo(lexlo_kmer_string)
        self._seen_lexlo_kmer_strings.add(lexlo_kmer_string)

def node_generator_from_edges(edge_generator):
    for edge in edge_generator:
        if len(edge) == 2:
            yield edge[1]
        elif len(edge) == 3:
            if edge[2] == EdgeTraversalOrientation.reverse.name:
                yield edge[0]
            else:
                yield edge[1]
        elif len(edge) == 4:
            if edge[3] == EdgeDFSTraversalDirection.reverse.name:
                yield edge[0]
            elif edge[3] == EdgeDFSTraversalDirection.forward.name:
                yield edge[1]
            else:
                raise ValueError('Could not make sense of edge: %s', edge)
        else:
            raise ValueError('Unexpected edge tuple length: %s', len(edge))

def find_tip_from(*, n, start, graph, next_node_generator):
    tip = set()
    query = start
    for _ in range(n):
        if len(set(graph.in_edges(query))) > 1 or len(set(graph.out_edges(query))) > 1:
            return tip
        else:
            tip.add(query)
            try:
                query = next(next_node_generator)
            except StopIteration:
                return tip
    return None

def make_copy_of_color_for_kmer_graph(graph, color, include_self_refs=False):
    """Makes a copy of graph, but only copies over links with key=color.
    Only copies over nodes that are linked by a link with key=color.
    """
    out_graph = nx.MultiDiGraph(colors=[color])
    for u, v, key, data in graph.edges(keys=True, data=True):
        if key == color:
            if u == v and not include_self_refs:
                continue
            out_graph.add_edge(u, v, key=key, **data)
    for node in list(out_graph):
        out_graph.add_node(node, kmer=graph.node[node])
    return out_graph

@attr.s(slots=True)
class UnitigGraphPathConverter:
    reprs = attr.ib()

    @classmethod
    def from_unitig_graph(cls, graph):
        reprs = {u: rpr for u, rpr in graph.nodes.data('repr')}
        return cls(reprs)

    def to_contig(self, path):
        return ''.join([self.reprs[u] for u in path])

def in_nodes_of(graph):
    for source in graph.nodes():
        if graph.in_degree(source) == 0:
            yield source

def out_nodes_of(graph):
    for target in graph.nodes():
        if graph.out_degree(target) == 0:
            yield target

def edge_nodes_of(graph):
    """Find all edge nodes of a graph

    Second return value is direction of edge.
    """
    for node in graph.nodes():
        if graph.out_degree(node) == 0:
            yield (node, EdgeTraversalOrientation.original)
        if graph.in_degree(node) == 0:
            yield (node, EdgeTraversalOrientation.reverse)


from lava.magma.core.learning.learning_rule import Loihi3FLearningRule
from lava.magma.core.learning.utils import float_to_literal

class RewardModulatedSTDP(Loihi3FLearningRule):
    def __init__(
            self,
            learning_rate: float,
            A_plus: float,
            A_minus: float,
            pre_trace_decay_tau: float,
            post_trace_decay_tau: float,
            pre_trace_kernel_magnitude: float,
            post_trace_kernel_magnitude: float,
            eligibility_trace_decay_tau: float,
            *args,
            **kwargs
    ):
        """
        Reward-Modulated Spike-timing dependent plasticity (STDP)
        as defined in Frémaux, Nicolas, and Wulfram Gerstner.
        "Neuromodulated spike-timing-dependent plasticity, and
        theory of three-factor learning rules." Frontiers in
        neural circuits 9 (2016).

        Parameters
        ==========

        learning_rate: float
            Overall learning rate scaling the intensity of weight changes.
        A_plus:
            Scaling the weight change on pre-synaptic spike times.
        A_minus:
            Scaling the weight change on post-synaptic spike times.
        pre_trace_decay_tau:
            Decay time constant of the pre-synaptic activity trace.
        post_trace_decay_tau:
            Decay time constant of the post-synaptic activity trace.
        pre_trace_kernel_magnitude:
            The magnitude of increase to the pre-synaptic trace value
            at the instant of pre-synaptic spike.
        post_trace_kernel_magnitude:
            The magnitude of increase to the post-synaptic trace value
            at the instant of post-synaptic spike.
        eligibility_trace_decay_tau:
            Decay time constant of the eligibility trace.

        """
        self.learning_rate = float_to_literal(learning_rate)
        self.A_plus = float_to_literal(A_plus)
        self.A_minus = float_to_literal(A_minus)
        self.pre_trace_decay_tau = pre_trace_decay_tau
        self.post_trace_decay_tau = post_trace_decay_tau
        self.pre_trace_kernel_magnitude = pre_trace_kernel_magnitude
        self.post_trace_kernel_magnitude = post_trace_kernel_magnitude
        self.eligibility_trace_decay_tau = \
            float_to_literal(eligibility_trace_decay_tau)

        # Trace impulse values
        x1_impulse = pre_trace_kernel_magnitude

        # Trace decay constants
        x1_tau = self.pre_trace_decay_tau

        # Eligibility trace represented as dt
        dt = f"{self.learning_rate} * {self.A_minus} * x0 * y1 + " \
             f"{self.learning_rate} * {self.A_plus} * y0 * x1 - " \
             f"u0 * t * {self.eligibility_trace_decay_tau}"

        # Reward-modulated weight update
        dw = " u0 * t * y2 "

        super().__init__(
            dw=dw,
            dt=dt,
            x1_impulse=x1_impulse,
            x1_tau=x1_tau,
            *args,
            **kwargs
        )


from db.run_sql import run_sql

from models.workout import Workout
from models.member import Member

def save(workout):
    sql = """ INSERT into workouts
    (name, description, duration, date, time, capacity, status)
    VALUES (%s, %s, %s, %s, %s, %s, %s)
    RETURNING * """
    values = [workout.name, workout.description, workout.duration, workout.date, workout.time, workout.capacity, workout.status]
    results = run_sql(sql, values)
    workout.id = results[0]['id']
    return workout

def delete_all():
    sql = "DELETE from workouts"
    run_sql(sql)

def delete(id):
    sql = "DELETE from workouts where id = %s"
    values = [id]
    run_sql(sql, values)

def select_all():
    workouts = []
    sql = " SELECT * from workouts ORDER BY DATE, TIME "
    results = run_sql(sql)

    for row in results:
        workout = Workout(row['name'], row['description'], row['duration'], row['date'], row['time'], row['capacity'], row['status'], row['id'])
        workouts.append(workout)
    return workouts

def select(id):
    sql = "SELECT * FROM workouts WHERE id = %s"
    values = [id]
    results = run_sql(sql, values)

    if results:
        result = results[0]
        workout = Workout(result['name'], result['description'], result['duration'], result['date'], result['time'], result['capacity'], result['status'], result['id'])
    return workout

def members(workout):
    members = []

    sql = """SELECT members.* FROM members
    INNER JOIN bookings ON bookings.member_id = members.id
    WHERE workout_id = %s"""

    values = [workout.id]
    results = run_sql(sql, values)

    for row in results:
        member = Member(row['name'], row['email'], row['status'], row['type'], row['id'])
        members.append(member)
    return members

def update(workout):
    sql = "UPDATE workouts SET (name, description, duration, date, time, capacity, status) = (%s, %s, %s, %s, %s, %s, %s) WHERE id = %s"
    values = [workout.name, workout.description, workout.duration, workout.date, workout.time, workout.capacity, workout.status, workout.id]
    run_sql(sql, values)


import os

import tensorflow as tf

import data
import generative_model.model as ml
from generative_model.configs import DEFINES

DATA_OUT_PATH = 'data_out/'

def main(self):
    saved_answer = ''
    data_out_path = os.path.join(os.getcwd(), DATA_OUT_PATH)
    os.makedirs(data_out_path, exist_ok=True)
    char2idx, idx2char, vocabulary_length = data.load_vocabulary()
    train_input, train_label, eval_input, eval_label = data.load_data()

    train_input_enc, train_input_enc_length = data.enc_processing(train_input, char2idx)
    train_output_dec, train_output_dec_length = data.dec_output_processing(train_label, char2idx)
    train_target_dec = data.dec_target_processing(train_label, char2idx)

    eval_input_enc, eval_input_enc_length = data.enc_processing(eval_input, char2idx)
    eval_output_dec, eval_output_dec_length = data.dec_output_processing(eval_label, char2idx)
    eval_target_dec = data.dec_target_processing(eval_label, char2idx)
    check_point_path = os.path.join(os.getcwd(), DEFINES.check_point_path)
    os.makedirs(check_point_path, exist_ok=True)

    classifier = tf.estimator.Estimator(
        model_fn=ml.Model,  # 모델 등록한다.
        model_dir=DEFINES.check_point_path,  # 체크포인트 위치 등록한다.
        params={  # 모델 쪽으로 파라메터 전달한다.
            'hidden_size': DEFINES.hidden_size,  # 가중치 크기 설정한다.
            'learning_rate': DEFINES.learning_rate,  # 학습율 설정한다.
            'vocabulary_length': vocabulary_length,  # 딕셔너리 크기를 설정한다.
            'embedding_size': DEFINES.embedding_size,  # 임베딩 크기를 설정한다.
            'max_sequence_length': DEFINES.max_sequence_length,
        })

    classifier.train(input_fn=lambda:data.train_input_fn(
        train_input_enc, train_output_dec, train_target_dec,  DEFINES.batch_size), steps=DEFINES.train_steps)

    eval_result = classifier.evaluate(input_fn=lambda: data.eval_input_fn(
        eval_input_enc, eval_output_dec, eval_target_dec, DEFINES.batch_size))
    print('\nEVAL set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
    predic_input_enc, predic_input_enc_length = data.enc_processing(["안녕"], char2idx)
    predic_output_dec, predic_output_decLength = data.dec_output_processing([""], char2idx)
    predic_target_dec = data.dec_target_processing([""], char2idx)

    for i in range(DEFINES.max_sequence_length):
        if i > 0:
            predic_output_dec, predic_output_decLength = data.dec_output_processing([answer], char2idx)
            predic_target_dec = data.dec_target_processing([answer], char2idx)

        predictions = classifier.predict(
            input_fn=lambda: data.eval_input_fn(predic_input_enc, predic_output_dec, predic_target_dec, 1))

        answer = data.pred_next_string(predictions, idx2char)
        if len(answer) == len(saved_answer):
            break
        else:
            saved_answer = answer

    print("answer: ", answer)

if __name__ == '__main__':
    tf.logging.set_verbosity(tf.logging.INFO)
    tf.app.run(main)


from math import sqrt

print('Welcome to circle computation.')
firstname= input('What is your name please?: ')

r = ['radius','r']
d = ['diameter','d']
c = ['circumference','c']
a = ['area','a']

data = input('Do you want to enter the radius, diameter, circumference or area? ')

def radius(x):
    print('Dear', firstname, ', based on the date you privided, the radius of the circle is: ', x)
    diameter = x *2
    print('The diameter of the circle is', diameter)

    circumference = round(22/7 * diameter)
    print('The circumference of the circle is', circumference)

    area = round(22/7 * x**2)
    print('The area of the circle is', area)

if data in r:
    rad = int(input('Enter the radius:'))
    radius(rad)

def diameter(v):
    print('Dear', firstname, ', based on the date you privided, the diameter of the circle is: ', v)
    radius = v/2
    print('The radius of the circle is', radius)

    circumference = round(22/7 *v)
    print('The circumference of the circle is', circumference)

    area = round(22/7 * radius**2)
    print('Area of the circle is', area)

if data in d:
    diam = int(input('Enter the diameter: '))
    diameter(diam)

def circumference(p):
    print('Dear', firstname, ', based on the date you privided, the circumference of the circle is: ', p)
    radius = round(p/ (2*22/7 ))
    print('The radius of the circle is', radius)

    diameter = radius*2
    print('The diameter of the circle is', diameter)

    area = round(22/7 * radius ** 2)
    print('The area of the circle is', area)

if data in c:
    circ = int(input('Enter the circumference of the circle: '))
    circumference(circ)

def area(y):
    print('Dear', firstname, ', based on the date you privided, the area of the circle is: ', y)
    radius = round(sqrt(y/22/7))
    print('The radius of the circle is', radius)

    diameter = radius *2
    print('The diameter of the circle is', diameter)

    circumference = round(22/7 *diameter)
    print('The circumference of the circle is:', circumference)

if data in a:
    ar= int(input('Enter the area of the circle: '))
    area(ar)


def sort(array: list[int]) -> list[int]:
    """Sorts the array using the insertion sort method."""
    # Arrays of size 0/1 are already sorted.
    if len(array) < 2:
        return array

    array_length: int = len(array)

    for i in range(array_length):
        # Skip first
        if i == 0:
            continue

        # Main logic loop
        new_index = i
        while new_index > 0:
            if array[new_index - 1] < array[i]:
                break

            new_index -= 1

        # Insert value right after the first number less than it
        value_to_insert = array.pop(i)
        array.insert(new_index, value_to_insert)

    return array


a=input()
b=input()
if len(a)<len(b):
    a="0"*(len(b) -len(a) )+a
elif len(b)<len(a):
    b="0"*(len(a) - len(b))+b

ans=""
carry=0
print(a,b)
for (i,j) in zip(a[::-1],b[::-1]):
    if i!=j :
        if carry==0:
            ans+="1"
            carry=0
        else:
            ans+="0"
            carry=1
    elif i==j=="0":
        if carry==0:
            ans+="0"
        else:
            ans+="1"
            carry=0
    elif i==j=="1":
        if carry==0:
            ans+="0"
            carry=1
        else:
            ans+="1"
            carry=1
if carry==1:
    ans+="1"
print(ans[::-1])


from django.db import models
from .common import Common

class GradeEntry(Common):
    """
    Individual grade entries.

    Attributes:
        name: Entry name
        points: Points obtained for the graded item
        max_points: Maximum number of points possible for the graded item
        student: Student who the entry belongs to
        category: Category that the entry is in
    """

    class Meta:
        verbose_name_plural = 'grade entries'

    name = models.CharField(max_length=50, null=False, verbose_name='Name')
    points = models.FloatField(null=False, verbose_name='Points', help_text='Number of points obtained')
    max_points = models.FloatField(
        null=False,
        verbose_name='Max Points',
        help_text='Maximum number of points possible'
    )
    student = models.ForeignKey(
        to='grades.User',
        on_delete=models.CASCADE,
        related_name='grade_entries',
        null=False,
        verbose_name='Student',
        blank=True
    )
    category = models.ForeignKey(
        to='Category',
        on_delete=models.CASCADE,
        related_name='grade_entries',
        null=False,
        verbose_name='Category'
    )

    def __str__(self) -> str:
        return f'{self.name} - {self.points} / {self.max_points} ({self.student})'


# -*- coding: utf-8 -*-

from aplication.news_feed.models import NewsFeedModels

from datetime import datetime, timedelta

import logging
logger = logging.getLogger(__name__)

def run(*args):

    now = datetime.now()
    last_month = now - timedelta(days=30)

    logger.info(
        'Removendo Noticias ate %s' % (last_month.strftime('%d/%m/%Y'))
    )
    old_news = NewsFeedModels.objects.filter(created__lte=last_month)
    count_itens = old_news.count()
    for news in old_news:
        news.delete()

    logger.info('Foram Removidas %s itens' % (count_itens))


from __future__ import with_statement

import sys
assert sys.version_info[0:2] >= (2, 5), "Python 2.5 or higher is required"

from os.path import isfile
from setuptools import setup

install_requires = ["fabric", "gitpython"]
if sys.version_info[0:2] < (2, 7):
    install_requires.extend(["argparse"])

if sys.version_info[0:2] == (2, 5):
    install_requires.append("requests==0.10.0")
else:
    install_requires.append("requests")

if isfile("README.rst"):
    with open("README.rst", "r") as readme:
        long_description = readme.read()
else:
    long_description = ""

setup(
    name="pyfarm.operations",
    version="0.7.0-dev0",
    packages=["pyfarm",
              "pyfarm.operations"],
    namespace_packages=["pyfarm"],
    entry_points={
        "console_scripts":[
            "pyfarm-dev-release = pyfarm.operations.dev.release:main",
            "pyfarm-dev-tags = pyfarm.operations.dev.tag:tags_main"]},
    install_requires=install_requires,
    url="https://github.com/pyfarm/pyfarm",
    license="Apache v2.0",
    author="Oliver Palmer",
    author_email="development@pyfarm.net",
    description="The root repository of PyFarm containing operations and"
                "deployment code",
    long_description=long_description,
    classifiers=[
        "Development Status :: 2 - Pre-Alpha",
        "Environment :: Other Environment",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: Apache Software License",
        "Natural Language :: English",
        "Operating System :: OS Independent",
        "Programming Language :: Python :: 2 :: Only",  # (for now)
        "Programming Language :: Python :: 2.5",
        "Programming Language :: Python :: 2.6",
        "Programming Language :: Python :: 2.7",
        "Topic :: System :: Distributed Computing"])


'''
Condition
    - TL : 1s(약 2000만)
      ML : 128(32*100만)
    - 1<=N<=100

Question
    - 뽑힌 정수들의 개수를 출력하고, 뽑힌 정수들을 오름차순으로 출력

Access
    try_1)
        - 예상 분류 : dp
          문제 분류 : 그래프 이론, 그래프 탐색, DFS

        1. i = 1~n까지 탐색 시작
        2. bfs(i) 시작
            2-1. i를 firstSet에 넣음
            2-2. 두번째 라인에서 i번째 숫자를 secondSet에 넣음
            2-3. secondLine[i]에 방문한 적이 없다면 다시 bfs(secondLine[i])를 시작
            2-4. 방문했던 수라면 fstSet과 secSet을 비교하여 같은경우에만 answer에 대입함
'''

import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

#define function
def bfs(stt,fstSet:list,secSet:list):
    global answer, visited
    if stt >n:
        return

    # stt를 첫번째 집합에 대입하고 방문처리
    fstSet.append(stt)
    visited.add(stt)

    # 두번째 줄의 stt번째 숫자를, 두번째 집합에 대입
    secNum = secLine[stt]
    secSet.append(secNum)

    # 두번째 줄의 stt번째 숫자에 방문한적이 없다면 bfs 진행
    if secNum not in visited:
        bfs(secNum,fstSet,secSet)

    # 방문했다면 fstSet과 secSet을 비교해서 answer에추가
    else:
        fstSet.sort()
        secSet.sort()
        if fstSet==secSet:
            answer.update(fstSet)
        return

def solution():
    global visited
    for stt in fstLine:
        fstSet=[]
        secSet=[]
        visited = set()
        bfs(stt,fstSet,secSet)
    return

#main
n=int(input())
fstLine = [i for i in range(1,n+1)]
secLine = [0] + [int(input()) for _ in range(n)]
answer = set()
solution()
answer = list(answer)
answer.sort()
print(len(answer))
print(*answer,sep='\n')


print('это высокосный год?')
a=int(input())
d=a%4
c=a%100
if c!=0 and d==0:
    print('YES')
elif d!=0 and c==0:
    print('NO')
else:
    print('NO')

#вместо переменной "а" вводил "х" - почемуто выдает ошибку


#! /bin/env python
# https://cms-analysis.github.io/HiggsAnalysis-CombinedLimit/part2/bin-wise-stats/
import os, os.path, sys, stat, argparse, getpass, json
import subprocess
import json
import glob
import ROOT
ROOT.gROOT.SetBatch()
ROOT.PyConfig.IgnoreCommandLineOptions = True
import logging
logger = logging.getLogger(__name__)

from math import sqrt
from datetime import datetime

import numpy as np
import Harvester as H
import Constants as Constants
import CombineHarvester.CombineTools.ch as ch

import logging
LOG_LEVEL = logging.DEBUG
stream = logging.StreamHandler()
stream.setLevel(LOG_LEVEL)
logger = logging.getLogger(__name__)
logger.setLevel(LOG_LEVEL)
logger.addHandler(stream)
try:
    import colorlog
    from colorlog import ColoredFormatter
    formatter = ColoredFormatter(
                "%(log_color)s%(levelname)-8s%(reset)s %(log_color)s%(message)s",
                datefmt=None,
                reset=True,
                log_colors={
                        'DEBUG':    'cyan',
                        'INFO':     'green',
                        'WARNING':  'blue',
                        'ERROR':    'red',
                        'CRITICAL': 'red',
                        },
                secondary_log_colors={},
                style='%')
    stream.setFormatter(formatter)
except ImportError:
    print(' try https://pypi.org/project/colorlog/  for colorlog')
    pass

def get_Nm_for_runmode(mode):
    Nm_formode = {'ellipse':'rho_steps',
                  'dnn'    :'dnn_scores',
                  'mjj'    :'mjj_bins',
                  'mlljj'  :'mlljj_bins',
                  'mjj_vs_mlljj' : 'mjj_vs_mlljj_map',
                  'mjj_and_mlljj': 'mjj_and_mlljj_combined_bins', }
    return Nm_formode[mode]

def format_parameters(p):
    mH = "%.2f" % p[0]
    mA = "%.2f" % p[1]
    return ("MH_"+str(mH) + "_" + "MA_"+str(mA)).replace(".", "p")

def format_ellipse(p, ellipses):
    mH = "%.2f" % p[0]
    mA = "%.2f" % p[1]
    for ie, e in enumerate(ellipses['MuMu'], 0): #put here the enumerate index!!!
        # it does not matter which flavor we pick as we are checking only the ellipse index
        mA_file = "%.2f" % e[-2]
        mH_file = "%.2f" % e[-1]
        if mA == mA_file and mH == mH_file: # check sim masses
            return '{:d}'.format(ie)        # return ellipse index

def parameter_type(s):
    try:
        if s == 'all':
            return 'all'
        x, y = map(float, s.replace("m", "-").split(','))
        if x.is_integer():
            x = int(x)
        if y.is_integer():
            y = int(y)
        return x, y
    except:
        raise argparse.ArgumentTypeError("Parameter must be x,y")

def get_hist_regex(r):
    return '^%s(__.*(up|down))?$' % r

def get_signal_parameters(f):
    # HToZATo2L2B_MH-200_MA-50.root
    split_filename = f.replace('.root','').replace('HToZATo2L2B_','')
    split_filename = split_filename.split('_')
    MH = split_filename[0].split('-')[1]
    MA = split_filename[1].split('-')[1]
    return int(MH), int(MA)

signal_grid = [
        #part0 : 21 signal samples
        ( 200, 50), ( 200, 100), ( 300, 100),
        ( 250, 50), #( 250, 100),
        #( 300, 50),
        ( 300, 100), #( 300, 200),
        #( 500, 50), ( 500, 200), ( 500, 400),
        #( 650, 50),
        #( 800, 50), ( 800, 200), ( 800, 400), ( 800, 700),
        #(1000, 50), (1000, 200), (1000, 500),
        #(2000, 1000),
        #(3000, 2000)
        ]
extra_signals = [
        ]

def prepare_DataCards(grid_data= None, dataset=None, expectSignal=None, era= None, parameters= None, mode= None, input= None, ellipses_mumu_file= None, output= None, method= None, node= None, blind= False, signal_strength= False, stat_only= False, verbose= False, split_by_categories= False, scale= False):

    luminosity = Constants.getLuminosity(era)

    signal_grid = list(set(grid_data))
    parameters = []
    for f in glob.glob(os.path.join(options.input, '*.root')):
        split_filename = f.split('/')[-1]
        if not split_filename.startswith('HToZATo2L2B_'):
            continue
        mH, mA = get_signal_parameters(split_filename)
        if (mH, mA) in signal_grid:
            parameters.append( (mH, mA) )

    if signal_strength:
        parameters = [( 500, 300)]
    if len(parameters) == 1 and parameters[0] == 'all':
        parameters = parameters[:]
    for p in parameters:
        if not p in parameters:
            print("Invalid parameter '%s'. Valid values are %s" % (str(p), str(parameters)))
            return

    print("\tEra and the corresponding luminosity      : %s, %s" %(era, Constants.getLuminosity(era)))
    print("\tInput path                                : %s" %input )
    print("\tGenerating set of cards for parameter(s)  : %s" % (', '.join([str(x) for x in parameters])))
    print("\tChosen analysis mode                      : %s" % mode)

    ellipses = {}
    ellipses['MuMu'] = []
    ellipses['ElEl'] = []
    ellipses['MuEl'] = []
    with open(ellipses_mumu_file.replace('ElEl', 'MuMu')) as inf:
        content = json.load(inf)
        ellipses['MuMu'] = content
        ellipses['MuEl'] = content
    with open(ellipses_mumu_file.replace('MuMu', 'ElEl')) as inf:
        content = json.load(inf)
        ellipses['ElEl'] = content

    prepareShapes(input, dataset, expectSignal, era, method, parameters, ['ggH', 'bbH'], ['boosted', 'resolved'], ['MuMu', 'ElEl'], ellipses, mode, output, luminosity, split_by_categories, scale, blind, signal_strength, stat_only, verbose)

    # Create helper script to run limits
    output = os.path.join(output, mode)
    print( '\tThe generated script to run limits can be found in : %s/' %output)
    script = """#! /bin/bash
scripts=`find {output} -name "*_run_{method}.sh"`
for script in $scripts; do
    dir=$(dirname $script)
    script=$(basename $script)
    echo "\tComputing with ${{script}}"
    pushd $dir &> /dev/null
    . $script
    popd &> /dev/null
done
""".format(output=output, method=method)

    script_name = "run_combined_%s_%s.sh" % (mode, method)
    with open(script_name, 'w') as f:
        f.write(script)

    st = os.stat(script_name)
    os.chmod(script_name, st.st_mode | stat.S_IEXEC)

    if method=="hybridnew":
        logger.info("All done. You can run everything by executing %r" % ('./' + script_name[:-3]+"_onSlurm.sh"))
    else:
        logger.info("All done. You can run everything by executing %r" % ('./' + script_name))

def prepareShapes(input=None, dataset=None, expectSignal=None, era=None, method=None, parameters=None, productions=None, regions=None, flavors=None, ellipses=None, mode=None, output=None, luminosity=None, split_by_categories=False, scale=False, blind=False, signal_strength=False, stat_only=False, verbose=False):
    if mode == "mjj_and_mlljj":
        categories = [
                (1, 'mlljj'),
                (2, 'mjj')
                ]
    elif mode == "mjj_vs_mlljj":
        categories = [
                (1, 'mjj_vs_mlljj')
                ]
    elif mode == "mjj":
        categories = [
                (1, 'mjj')
                ]
    elif mode == "mlljj":
        categories = [
                (1, 'mlljj')
                ]
    elif mode == "ellipse":
        categories = [
                # % (flavour, ellipse_index)
                (1, 'ellipse_{}_{}')
                ]
    elif mode == "postfit":
        split_by_categories = True
        categories = [
                # % ( MH, MA)
                (1, 'dnn_ggH_resolved_MH_{}_MA_{}')
                # % (flavour, ellipse_index)
                #(2, 'ellipse_{}_{}'),
                #(3, 'mlljj'),
                #(4, 'mjj'),
                #(5, 'mjj_vs_mlljj')
                ]
    elif mode == "dnn":
        categories = [
                # % ( MH, MA)
                (1, 'dnn_ggH_resolved_MH_{}_MA_{}')
                ]

    histfactory_to_combine_categories = {}
    histfactory_to_combine_processes  = {
            # main Background
            'ttbar'    : ['^TT*', '^ttbar_*'],
            'SingleTop': ['^ST_*'],
            'DY'       : ['^DYJetsToLL_0J*', '^DYJetsToLL_1J*', '^DYJetsToLL_2J*', '^DYToLL_*'],
            # Others Backgrounds
            'WPlusJets': ['^WJetsToLNu*'],
            'ttV'      : ['^TT(WJets|Z)To*'],
            'VV'       : ['^(ZZ|WW|WZ)To*'],
            'VVV'      : ['^(ZZZ|WWW|WZZ|WWZ)*'],
            #'Wgamma'  : ['^WGToLNuG_TuneCUETP8M1'], TODO add this sample
            'SMHiggs'  : ['^ggZH_HToBB_ZToNuNu*', '^HZJ_HToWW*', '^ZH_HToBB_ZToLL*', '^ggZH_HToBB_ZToLL*', '^ttHJet*']
            }
    if options.mode == "postfit":
        for p in parameters:
            mH = p[0]
            mA = p[1]

            formatted_p = format_parameters(p)
            formatted_e = format_ellipse(p, ellipses)

            histfactory_to_combine_categories = {
                'dnn_ggH_resolved_MH_{}_MA_{}'.format(mH, mA) : get_hist_regex('DNNOutput_{flavor}channel_resolvedselection_ZAscan_MA_%s_MH_%s'%(mA, mH)),
                #'ellipse_{}_{}'.format(formatted_p, formatted_e):    get_hist_regex('rho_steps_histo_{flavor}_hZA_lljj_deepCSV_btagM_mll_and_met_cut_%s' % format_ellipse(p, ellipses)),
                #'mjj':      get_hist_regex('jj_M_{flavor}_hZA_lljj_deepCSV_btagM_'),
                #'mlljj': get_hist_regex('lljj_M_{flavor}_hZA_lljj_deepCSV_btagM_'),
            }
    # Shape depending on the signal hypothesis
    for p in parameters:
        mH = p[0]
        mA = p[1]

        formatted_p = format_parameters(p)
        formatted_e = format_ellipse(p, ellipses)

        suffix = formatted_p.replace('MH_', 'MH-').replace('MA_','MA-')
        # Signal process
        histfactory_to_combine_processes['HToZATo2L2B_MH-%s_MA-%s'%(mH,mA), p] = ['^HToZATo2L2B_MH-%s_MA-%s*'%(mH, mA)]

        if mode == "postfit":
            histfactory_to_combine_categories[('dnn_ggH_resolved_MH_{}_MA_{}'.format(mH, mA), p)] = get_hist_regex('DNNOutput_{flavor}channel_resolvedselection_ZAscan_MA_%s_MH_%s'%(mA, mH))
        elif mode == "mjj_and_mlljj":
            histfactory_to_combine_categories[('mjj', p)]   = get_hist_regex('jj_M_resolved_{flavor}_hZA_lljj_DeepCSVM_mll_and_met_cut')
            histfactory_to_combine_categories[('mlljj', p)] = get_hist_regex('lljj_M_resolved_{flavor}_hZA_lljj_DeepCSVM_mll_and_met_cut')
        elif mode == "mjj_vs_mlljj":
            histfactory_to_combine_categories[('mjj_vs_mlljj', p)] = get_hist_regex('Mjj_vs_Mlljj_resolved_{flavor}_hZA_lljj_DeepCSVM_mll_and_met_cut')
        elif mode == "mlljj":
            histfactory_to_combine_categories[('mlljj', p)] = get_hist_regex('{flavor}_resolved_METCut__mllbb_DeepCSVM')
        elif mode == "mjj":
            histfactory_to_combine_categories[('mjj', p)]   = get_hist_regex('jj_M_resolved_{flavor}_hZA_lljj_DeepCSVM_mll_and_met_cut')
        elif mode == "ellipse":
            histfactory_to_combine_categories[('ellipse_{}_{}'.format(formatted_p, formatted_e), p)] = get_hist_regex('rho_steps_resolved_histo_{flavor}_hZA_lljj_DeepCSV_btagM__METCut__%s'%formatted_p)
        elif mode == "dnn": # FIXME ugly histos name
            #histfactory_to_combine_categories[('dnn_ggH_resolved_MH_{}_MA_{}'.format(mH, mA), p)] = get_hist_regex('DNNOutput_{flavor}channel_resolvedselection_ZAscan_MA_%s_MH_%s'%(mA, mH))
            histfactory_to_combine_categories[('dnn_ggH_resolved_MH_{}_MA_{}'.format(mH, mA), p)] = get_hist_regex('DNNOutput_ZAnode_{flavor}_resolved_DeepCSVM_METCut_gg_fusion_MH_%s_MA_%s'%(mH, mA))

    print( '\thistfactory_to_combine_categories    : %s '%histfactory_to_combine_categories )

    if not blind:
        histfactory_to_combine_processes['data_obs'] = ['^DoubleMuon*', '^DoubleEG*', '^MuonEG*', '^SingleMuon*', '^EGamma*']

    H.splitJECBySources = False
    if signal_strength:
        H.scaleZAToSMCrossSection = True
    H.splitTTbarUncertBinByBin = False

    output_filename = os.path.join(output, 'shapes_HToZATo2L2B.root')
    file, systematics = H.prepareFile(processes_map=histfactory_to_combine_processes, categories_map=histfactory_to_combine_categories, input=input, output_filename=output_filename, signal_process='HToZATo2L2B', method=method, luminosity=luminosity, flavors=flavors, era=era, blind=blind)

    #print ( "\tsystematics : %s       :" %systematics )
    for i, p in enumerate(parameters):
        mH = p[0]
        mA = p[1]

        cb = ch.CombineHarvester()
        if verbose:
            cb.SetVerbosity(3)
        cb.SetFlag("zero-negative-bins-on-import", True)

        # Dummy mass value used for all combine input when a mass is needed
        mass = "125"
        formatted_p = format_parameters(p)
        formatted_e = format_ellipse(p, ellipses)

        analysis_name = 'HToZATo2L2B'
        categories_with_parameters = categories[:]
        for i, k in enumerate(categories_with_parameters):
            if mode in ['dnn', 'postfit']:
                categories_with_parameters[i] = (k[0], k[1].format(mH, mA))
            elif mode == 'ellipse':
                categories_with_parameters[i] = (k[0], k[1].format('MH-%s_MA-%s'%(mH, mA), formatted_e))
            else:
                print( 'FIXME' )
        print( '\tcategories_with_parameters      :  %s '%categories_with_parameters)
        #cb.AddObservations( mass, analysis, era, channel, bin)
        cb.AddObservations(['*'], [analysis_name], ['13TeV_%s'%era], flavors, categories_with_parameters)
        bkg_processes = [
                'ttbar',
                'SingleTop',
                'DY',
                #'WPlusJets',
                #'ttV',
                #'VV',
                #'VVV',
                #'Wgamma',
                #'SMHiggs'
                ]

        # FIXME I am not sure if this intended or a mistake
        for flavor in flavors:
            processes = []
            cb.AddProcesses(['*'], [analysis_name], ['13TeV_%s'%era], [flavor], bkg_processes, categories_with_parameters, False)
            processes += bkg_processes
        sig_process = 'HToZATo2L2B'
        cb.AddProcesses([mass], [analysis_name], ['13TeV_%s'%era], flavors, [sig_process], categories_with_parameters, True)
        processes += [sig_process]
        print ( "\tprocesses       : %s" %processes)

        if not stat_only:
            processes_without_weighted_data = cb.cp()
            processes_without_weighted_data.FilterProcs(lambda p: 'data' in p.process())
            processes_without_weighted_data.AddSyst(cb, 'lumi_$ERA', 'lnN', ch.SystMap('era')(['13TeV_%s'%era], Constants.getLuminosityUncertainty(era)))

            if not H.splitTTbarUncertBinByBin:
                cb.cp().AddSyst(cb, 'ttbar_xsec', 'lnN', ch.SystMap('process')
                        (['ttbar'], 1.001525372691124) )
            cb.cp().AddSyst(cb, 'SingleTop_xsec', 'lnN', ch.SystMap('process')
                    (['SingleTop'], 1.0029650414264797) )
            cb.cp().AddSyst(cb, 'DY_xsec', 'lnN', ch.SystMap('process')
                        (['DY'], 1.007841991384859) )
            if signal_strength:
                # https://twiki.cern.ch/twiki/bin/view/LHCPhysics/LHCHXSWGHH#Current_recommendations_for_di_H
                cb.cp().AddSyst(cb, '$PROCESS_xsec', 'lnN', ch.SystMap('process')
                    ([sig_process], 1.0729) )

            for _, category_with_parameters in categories_with_parameters:
                for flavor in flavors:
                    for process in processes:
                        process = str(process)
                        if sig_process in process:
                            process = sig_process
                        if not process in cb.cp().channel([flavor]).process_set():
                            print("[{}, {}] Process '{}' not found, skipping systematics".format(category_with_parameters, flavor, process))
                        for s in systematics[flavor][category_with_parameters][process]:
                            s = str(s)
                            if H.ignoreSystematic(flavor, process, s):
                                print("[{}, {}, {}] Ignoring systematic '{}'".format(category_with_parameters, flavor, process, s))
                                continue
                            #FIXME s = H.renameSystematic(flavor, process, s)
                            cb.cp().channel([flavor]).process([process]).AddSyst(cb, s, 'shape', ch.SystMap()(1.00))

        # Import shapes from ROOT file
        for flavor in flavors:
            cb.cp().channel([flavor]).backgrounds().ExtractShapes(file, '$BIN/$PROCESS_%s' % flavor, '$BIN/$PROCESS_%s__$SYSTEMATIC' % flavor)
            cb.cp().channel([flavor]).signals().ExtractShapes(file, '$BIN/$PROCESS_MH-%s_MA-%s_%s' % (p[0],p[1], flavor), '$BIN/$PROCESS_%s_%s__$SYSTEMATIC' % ('MH-%s_MA-%s'%(p[0],p[1]), flavor))

        if scale:
            cb.cp().process(['HToZATo2L2B']).ForEachProc(lambda x : x.set_rate(x.rate()*1000))
            cb.cp().process(['HToZATo2L2B']).PrintProcs()

        # Bin by bin uncertainties
        if not stat_only:
            bkgs = cb.cp().backgrounds()
            bkgs.FilterProcs(lambda p: 'data' in p.process())
            bbb = ch.BinByBinFactory()
            bbb.SetAddThreshold(0.05).SetMergeThreshold(0.5).SetFixNorm(False)
            bbb.MergeBinErrors(bkgs)
            bbb.AddBinByBin(bkgs, cb)

        output_prefix      = 'HToZATo2L2B'
        #output_prefix_run = 'HToZATo2L2B_%s' % (formatted_e)

        output_dir = os.path.join(output, mode, H.get_method_group(method), 'MH-%s_MA-%s'%(p[0],p[1]))
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        def createRunCombineScript(mass, output_dir, output_prefix):
            # Write small script to compute the limit
            datacard = os.path.join(output_dir, output_prefix + '.dat')
            workspace_file = os.path.basename(os.path.join(output_dir, output_prefix + '_combine_workspace.root'))

            if method == 'hybridnew':
                script = """#! /bin/bash
pushd {dir}
# If workspace does not exist, create it once
if [ ! -f {workspace_root} ]; then
    text2workspace.py {datacard} -m {mass} -o {workspace_root}
fi
# Run limit
combine {method} --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} -S {systematics} &> {name}.log
combine {method} --expectedFromGrid=0.5 --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} -S {systematics} &> {name}_exp.log
combine {method} --expectedFromGrid=0.84 --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} -S {systematics} &> {name}_P1sigma.log
combine {method} --expectedFromGrid=0.16 --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} -S {systematics} &> {name}_M1sigma.log
combine {method} --expectedFromGrid=0.975 --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} -S {systematics} &> {name}_P2sigma.log
combine {method} --expectedFromGrid=0.025 --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} -S {systematics} &> {name}_M2sigma.log
popd
""".format(workspace_root=workspace_file, datacard=os.path.basename(datacard), name=output_prefix, mass=mass, systematics=(0 if stat_only else 1), method=H.get_combine_method(method), dir=os.path.dirname(os.path.abspath(datacard)))
            else:
                script = """#! /bin/bash
pushd {dir}
# If workspace does not exist, create it once
if [ ! -f {workspace_root} ]; then
    text2workspace.py {datacard} -m {mass} -o {workspace_root}
fi
# Run combined
#combine {method} --X-rtd MINIMIZER_analytic -m {mass} -n {name} {workspace_root} {dataset} --expectSignal {expectSignal} {blind} &> {name}.log
combine {method} -m {mass} -n {name} {workspace_root} {dataset} --expectSignal {expectSignal} {blind} &> {name}.log
popd
""".format(workspace_root=workspace_file, datacard=os.path.basename(datacard), name=output_prefix, mass=mass, systematics=(0 if stat_only else 1), method=H.get_combine_method(method), dir=os.path.dirname(os.path.abspath(datacard)), dataset=('-t -1' if dataset=='asimov' else '-t 8 -s -1'), blind=('--run blind' if blind else ''), expectSignal=expectSignal)

            script_file = os.path.join(output_dir, output_prefix + ('_run_%s.sh' % method))
            print( method, script_file)
            with open(script_file, 'w') as f:
                f.write(script)

            st = os.stat(script_file)
            os.chmod(script_file, st.st_mode | stat.S_IEXEC)

        # Write card
        def writeCard(c, mass, output_dir, output_prefix, script=True):
            datacard = os.path.join(output_dir, output_prefix + '.dat')
            c.cp().mass([mass, "*"]).WriteDatacard(datacard, os.path.join(output_dir, output_prefix + '_shapes.root'))
            if script:
                createRunCombineScript(mass, output_dir, output_prefix)

        print ("Writing datacards!")
        print (categories_with_parameters )
        mergeable_flavors = ['MuMu', 'ElEl']
        if split_by_categories:
            for flavor in flavors:
                for i, cat in enumerate(categories_with_parameters):
                    cat_output_prefix = output_prefix + '_%s_%s' % (flavor, cat[1])
                    writeCard(cb.cp().bin([cat[1]]).channel([flavor]), mass, output_dir, cat_output_prefix, i + 1 == len(categories_with_parameters))

            for i, cat in enumerate(categories_with_parameters):
                if all(x in flavors for x in mergeable_flavors):
                    print("Merging flavors datacards into a single one for {}".format(cat[1]))
                    # Merge all flavors into a single datacards
                    datacards = ["{flavor}={prefix}_{flavor}_{category}.dat".format(prefix=output_prefix, flavor=x, category=cat[1]) for x in mergeable_flavors]
                    args = ['combineCards.py'] + datacards

                    merged_datacard_name = output_prefix + '_' + '_'.join(mergeable_flavors) + '_' + cat[1]
                    merged_datacard = os.path.join(output_dir, merged_datacard_name + '.dat')
                    with open(merged_datacard, 'w') as f:
                        subprocess.check_call(args, cwd=output_dir, stdout=f)

                    createRunCombineScript(mass, output_dir, merged_datacard_name)

            for flavor in flavors:
                if mode == "postfit":
                    name = get_Nm_for_runmode('dnn')
                    script = """#! /bin/bash
pushd {dir}
# Fit the {name} distribution
./{prefix}_{categories}_run_fit.sh

# Create post-fit shapes for all the categories
for CAT in {categories}; do
    text2workspace.py {prefix}_${{CAT}}.dat -m {mass} -o {prefix}_${{CAT}}_combine_workspace.root
    PostFitShapesFromWorkspace -w {prefix}_${{CAT}}_combine_workspace.root -d {prefix}_${{CAT}}.dat -o postfit_shapes_${{CAT}}.root -f fitDiagnostics{prefix}_${{CAT}}.root:fit_b -m {mass} --postfit --sampling --samples 1000 --print
    $CMSSW_BASE/src/ZAStatAnalysis/utils/convertPostfitShapesForPlotIt.py -i postfit_shapes_${{CAT}}.root -o plotIt_{flavor} --signal-process HToZATo2L2B -n {name}
done
popd
""".format(prefix=output_prefix + '_' + flavor, flavor=flavor, mass=125, parameter='MH-%s_MA-%s'%(mH,mA), categories=' '.join([x[1] for x in categories_with_parameters]), dir=os.path.abspath(output_dir), name=name)
                    script_file = os.path.join(output_dir, output_prefix + '_' + flavor + ('_do_postfit.sh'))
                    with open(script_file, 'w') as f:
                        f.write(script)

                    st = os.stat(script_file)
                    os.chmod(script_file, st.st_mode | stat.S_IEXEC)
        else:
            print ( flavor, flavors, cb.cp().channel([flavor]), mass, output_dir, output_prefix + "_" + flavor )

            for flavor in flavors:
                writeCard(cb.cp().channel([flavor]), mass, output_dir, output_prefix + "_" + flavor)
            if all(x in flavors for x in mergeable_flavors):
                print("Merging flavors datacards into a single one")
                # Merge all flavors into a single datacards
                datacards = ["{flavor}={prefix}_{flavor}.dat".format(prefix=output_prefix, flavor=x) for x in mergeable_flavors]
                args = ['combineCards.py'] + datacards

                merged_datacard = os.path.join(output_dir, output_prefix + '_' + '_'.join(mergeable_flavors) + '.dat')
                with open(merged_datacard, 'w') as f:
                    subprocess.check_call(args, cwd=output_dir, stdout=f)

                createRunCombineScript(mass, output_dir, output_prefix + '_' + '_'.join(mergeable_flavors))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Create shape datacards ready for combine')
    parser.add_argument('-i', '--input',        action='store', dest='input', type=str, required=True,
                                                help='HistFactory input path: those are the histograms for signal/data/backgrounds that pass through all the following \n'
                                                     'steps: 1/- final selection ( 2l+bjets pass btagging discr cut + met + corrections + etc... ) \n'
                                                     '       2/- do skim  \n'
                                                     '       3/- DNN trained using these skimmed trees \n'
                                                     '       4/- run bamboo to produce your dnn outputs(prefit plots) with all systematics variations using the model you get from training.\n')
    parser.add_argument('-o', '--output',       action='store', dest='output', required=True, default=None,
                                                help='Output directory')
    parser.add_argument('-e', '--era',          action='store', dest='era', required=True, default=None, choices=['2016', '2017', '2018'],
                                                help='You need to pass your era')
    parser.add_argument('-p', '--parameters',   nargs='+', metavar='MH,MA', dest='parameters', type=parameter_type, default=['all'],
                                                help='Parameters list. Use `all` as an alias for all parameters')
    parser.add_argument('-s', '--stat',         action='store_true', dest='stat_only', required=False, default=False,
                                                help='Do not consider systematic uncertainties')
    parser.add_argument('-v', '--verbose',      action='store_true', required=False, default=False,
                                                help='For debugging purposes , you may consider this argument !')
    parser.add_argument('--expectSignal',       action='store', required=True, type=int, choices=[0, 1],
                                                help=' Is this S+B fit B-Only  ? ')
    parser.add_argument('--mode',               action='store', dest='mode', default='dnn', choices=['mjj_vs_mlljj', 'mjj_and_mlljj', 'postfit', 'mjj', 'mlljj', 'ellipse', 'dnn'],
                                                help='Analysis mode')
    parser.add_argument('--node',               action='store', dest='node', default='ZA', choices=['DY', 'TT', 'ZA'],
                                                help='DNN nodes')
    parser.add_argument('--method',             action='store', dest='method', required=True, default=None, choices=['asymptotic', 'hybridnew', 'fit'],
                                                help='Analysis method')
    parser.add_argument('--blind',              action='store_true', dest='blind', required=False,
                                                help='Use fake data instead of real data')
    parser.add_argument('--signal-strength',    action='store_true', dest="signal_strength", required=False, default=False,
                                                help='Put limit on the signal strength instead of the cross-section')
    parser.add_argument('--ellipses-mumu-file', action='store', dest='ellipses_mumu_file', required=False,
                                default='/home/ucl/cp3/kjaffel/bamboodev/ZA_FullAnalysis/bamboo_/ZATools/scripts_ZA/ellipsesScripts/vers20.06.03Inputs/fullEllipseParamWindow_MuMu.json',
                                                help='file containing the ellipses parameters for MuMu (ElEl is assumed to be in the same directory)')
    parser.add_argument('--scale',              action='store_true', dest='scale', required=False, default=False,
                                                help='scale signal rate')
    parser.add_argument('--dataset',            action='store', dest='dataset', choices=['toys', 'asimov'], required=True, default=None,
                                                help='if asimov:\n'
                                                        '-t -1 will produce an Asimov dataset in which statistical fluctuations are suppressed. \n'
                                                     'if toys: \n'
                                                        '-t N with N > 0. Combine will generate N toy datasets from the model and re-run the method once per toy. \n'
                                                        'The seed for the toy generation can be modified with the option -s (use -s -1 for a random seed). \n'
                                                        'The output file will contain one entry in the tree for each of these toys.\n')
    options = parser.parse_args()
    options.mode = options.mode.lower()

    prepare_DataCards(grid_data= signal_grid + extra_signals, dataset= options.dataset, expectSignal=options.expectSignal, era=options.era, parameters=options.parameters, mode=options.mode, input=options.input, ellipses_mumu_file=options.ellipses_mumu_file, output=options.output, method=options.method, node=options.node, blind=options.blind, signal_strength=options.signal_strength, stat_only=options.stat_only, verbose=options.verbose, split_by_categories=True, scale=options.scale)


def main():
    text = input("Fraction: ")
    text2 = convert(text)
    print(gauge(text2))

def convert(fraction):
    x, y = fraction.split("/")

    if int(x)/int(y) > 1:
        raise ValueError
    elif int(y) == 0:
        raise ZeroDivisionError
    return round(int(x)/int(y) * 100)

def gauge(percentage):
    if 0 <= percentage <= 1:
        return ("E")
    elif 99 <= percentage <= 100:
        return ("F")
    elif 1 < percentage < 99:
        return str(percentage) + "%"

if __name__ == "__main__":
    main()


m=int(input())
p=[]
sum=[]
flag=0
for i in range(m):
    s = input()
    p.append(list(map(int, s.split(','))))

for i in range(0,len(p)):
    for k in range(0,len(p)):
        if(i==k):continue
        if(p[i][1]==p[k][0]):
            sum.append(k)
            flag=1
            break;
    if (flag==0):
        sum.append(-1)
    flag=0
print(sum)


'''
Representation of unit tests for answer boxes in edX-platform courses, together with a
representation of a full set of such tests for a course.
'''

import yaml
import os

class AnswerBoxUnitTest(object):
    '''
    Representation of a single unit test for an answer box.
    '''
    SPEC_FIELDS = ['url_name', 'responses', 'expected']
    def __init__(self, test_spec=None, test_name=None):
        '''
        test_spec = dict giving url_name, responses, and expected.
        test_name = name of this test (or, e.g. at least a sequential index number for the test)

        responses   = ordered list of strings, specifying user input for each input in the answer box element
        expected    = either list or single string instance of "correct" or "incorrect" or "error"
        box_indexes = list of (x,y) integer pairs specifying index number of the answer box
                      entry.  This is used to construct the input box ID, which is of the form
                      input_<url_name>_<x>_<y>, where <x> indexes which \abox the input is, and
                      <y> indexes which input element it is, within a given abox (for aboxes with
                      multiple input boxes).  This list should have the same length as the responses.
                      If box_indices is not provided, then it defaults to
                                  zip(range(len(responses)), [0]*len(responses))
                      Note that the edX platform seems to start x from 2 (and not 1, or 0), and
                      y from 1.  We stick to the convention that x and y both start at 0, and leave
                      the offsets for edxapi.
        '''
        self.url_name = None
        self.responses = []
        self.expected = []
        self.name = test_name
        self.box_indexes = []
        if test_spec:
            for field in self.SPEC_FIELDS:
                if not field in test_spec:
                    print("Missing %s from test %s" % (field, test_name))
                else:
                    setattr(self, field, test_spec[field])
            self.box_indexes = test_spec.get('box_indexes', self.box_indexes)
        if not isinstance(self.responses, list):
            raise Exception("[AnswerBoxUnitTes] illegel responses=%s -- must be list" % self.responses)
        if isinstance(self.expected, list) and not len(self.expected)==len(self.responses):
            raise Exception("[AnswerBoxUnitTes] mismatched lengths responses=%s ; expected=%s" % (self.responses, self.expected))
        if not self.box_indexes:
            self.box_indexes = list(zip(list(range(len(self.responses))), [0]*len(self.responses)))
        if not len(self.box_indexes)==len(self.responses):
            raise Exception("[AnswerBoxUnitTes] mismatched lengths responses=%s ; box_indexes=%s" % (self.responses, self.box_indexes))

    def __unicode__(self):
        return "[AnswerBoxUnitTest] url_name=%s, responses=%s, expected=%s indexes=%s (%s)" % (self.url_name,
                                                                                self.responses,
                                                                                self.expected,
                                                                                self.box_indexes,
                                                                                self.name)

    __str__ = __unicode__

    @property
    def expected_as_list(self):
        if not isinstance(self.expected, list):
            return [self.expected] * len(self.responses)
        return self.expected

    def box_indexes_plus(self, offset=1):
        '''
        Return box indexes, with the <x> coordinate incremented by offset
        '''
        return [(x+offset, y) for (x,y) in self.box_indexes]

    @property
    def box_indexes_as_list(self):
        '''
        Return box indexes, as list of lists (instead of as list of tuples).
        Needed so YAML outputs correctly.
        '''
        return [list(x) for x in self.box_indexes]

    @property
    def max_box_x_index(self):
        '''
        Return largest x index of box indexes
        '''
        return max([x[0] for x in self.box_indexes])

    def __add__(self, other):
        assert self.url_name==other.url_name
        both_responses = self.responses + other.responses
        both_expected = self.expected_as_list + other.expected_as_list
        both_name = "combination of %s and %s" % (str(self.name), str(other.name))
        both_indexes = self.box_indexes + other.box_indexes_plus(offset=self.max_box_x_index+1)
        return AnswerBoxUnitTest(dict(url_name=self.url_name,
                                      responses=both_responses,
                                      expected=both_expected,
                                      box_indexes=both_indexes,
                                      name=both_name))

    def as_dict(self):
        '''
        Return dict representation of this AnswerBoxUnitTest object
        '''
        data = dict(url_name=self.url_name, responses=self.responses, expected=self.expected,
                    box_indexes=self.box_indexes_as_list)
        if self.name:
            data['name'] = self.name
        return data

class CourseUnitTestSet(object):
    '''
    Set of tests (AnswerBoxUnitTest objecs), for an edX-platform course.
    '''
    def __init__(self, fn=None, verbose=True, yaml_string=None):
        '''
        fn = name of file to load course unit tests from (defaults to looking for YAML)
        '''
        self.config = {}
        self.tests = []
        self.verbose = verbose
        if fn or yaml_string:
            self.load_tests_from_file(fn=fn, yaml_string=yaml_string)

    def add_tests(self, tests):
        '''
        tests - list of AnswerBoxUnitTest objects
        '''
        for test in tests:
            self.add_test(test)

    def add_test(self, test):
        '''
        test - AnswerBoxUnitTest object
        '''
        if not isinstance(test, AnswerBoxUnitTest):
            raise Exception("[CourseUnitTestSet] add_test: test must be an instance of AnswerBoxUnitTest")
        self.tests.append(test)

    def output_to_file(self, ofn):
        '''
        Write test set to output file in YAML format.
        '''
        cut_spec = {'config': self.config, 'tests': [x.as_dict() for x in self.tests]}
        open(ofn, 'w').write(yaml.dump(cut_spec))

    def load_tests_from_file(self, fn=None, yaml_string=None):
        if fn:
            if not os.path.exists(fn):
                raise Exception("[CourseUnitTestSet] Expecting course unit test config file - but no such file %s" % fn)
            yaml_string = open(fn).read()
        if not yaml_string:
            raise Exception("[CourseUnitTestSet] empty YAML string %s" % yaml_string)
        cut_specs = yaml.load(yaml_string)
        if 'config' in cut_specs:
            self.config = cut_specs['config']
            # self.__dict__.update(cut_specs['config'])
        self.cut_specs = cut_specs
        cnt = 0
        for test in cut_specs.get('tests', []):
            cnt += 1
            abutest = AnswerBoxUnitTest(test, cnt)
            self.tests.append(abutest)
        self.ntests = len(self.tests)
        if self.verbose:
            print("[CourseUnitTestSet] Loaded %s answer box unit tests from %s" % (self.ntests, fn))

#-----------------------------------------------------------------------------
# unit tests

def test_abut1():
    abut1 = AnswerBoxUnitTest(dict(responses=["1"], expected="correct", url_name="x"))
    abut2 = AnswerBoxUnitTest(dict(responses=["2"], expected="incorrect", url_name="x"))
    abut3 = abut1 + abut2
    assert abut3.url_name=="x"
    assert abut3.expected==["correct", "incorrect"]
    assert abut3.responses==["1", "2"]

def test_cutset1():
    yaml = """config: {a: 2}
tests:
- expected: [correct]
  name: A problem/test_1
  responses: [red]
  url_name: a_problem
    """
    cutset = CourseUnitTestSet(yaml_string=yaml)
    assert len(cutset.tests)==1
    assert cutset.config['a']==2
    assert cutset.tests[0].expected==['correct']
    assert cutset.tests[0].responses==['red']
    assert cutset.tests[0].url_name=="a_problem"

    abut2 = AnswerBoxUnitTest(dict(responses=["2"], expected="incorrect", url_name="x"))
    cutset.add_tests([abut2])
    assert len(cutset.tests)==2

def test_cutset2():
    yaml = """config: {a: 2}
tests:
- expected: [correct]
  name: A problem/test_1
  responses: [red]
  url_name: a_problem
    """
    cutset = CourseUnitTestSet(yaml_string=yaml)

    cfn = "/tmp/tmp_cutset.yaml"
    cutset.output_to_file(cfn)

    cutset2 = CourseUnitTestSet(cfn)
    assert len(cutset2.tests)==1
    assert cutset2.config['a']==2
    assert cutset2.tests[0].expected==['correct']
    assert cutset2.tests[0].responses==['red']
    assert cutset2.tests[0].url_name=="a_problem"


from django.contrib import admin
from django.urls import path, include
from sistema.views import ProdutosViewSet, ProdutoresViewSet, PedidoViewSet, RelatorioViewSet, \
    ListaPedidosProdutorViewSet
from rest_framework import routers

router = routers.DefaultRouter()
router.register('produtor', ProdutoresViewSet, basename='Produtores')
router.register('produto', ProdutosViewSet, basename='Produtos')
router.register('pedido', PedidoViewSet, basename='Pedidos')
router.register('relatorio', RelatorioViewSet, basename='Relatorio')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
    path('produtor/<int:pk>/pedidos/', ListaPedidosProdutorViewSet.as_view())
]


import tifffile
from pathlib import Path
import matplotlib.pylab as plt
import numpy as np
import pandas as pd
from skimage.morphology import  remove_small_objects
from skimage.measure import label, regionprops

# https://pypi.org/project/hampel/
# https://dsp.stackexchange.com/questions/26552/what-is-a-hampel-filter-and-how-does-it-work
from hampel import hampel

import matplotlib as mpl
mpl.rcParams['figure.dpi'] = 300

# https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.RANSACRegressor.html#sklearn.linear_model.RANSACRegressor
from sklearn.linear_model import RANSACRegressor

#%%
########### helper functions

## calculate layer length 2nd method
# placenta image is vertical here, meaning edges are at the top and bottom
# layers increase left to right
def _find_bottom_layer_vertices(mask):
    list_layer_vertices = []
    n_rows, n_cols = mask.shape # subtracting cols length inverts graph
    for pos_row, row in enumerate(mask): # iterate through rows
        for pos_col, pixel_value in enumerate(row): #iterate through cols in row

            if pixel_value == True: # mask is at edge of mask
                list_layer_vertices.append((pos_row, n_cols-pos_col)) # save layer pixel
                break # go to next row

    return list_layer_vertices

## calculate layer length 2nd method
# placenta image is vertical here, meaning edges are at the top and bottom
# layers increase left to right
def _find_top_layer_vertices(mask):
    list_layer_vertices = []
    for pos_row, row in enumerate(mask): # iterate through rows
        for pos_col, pixel_value in enumerate(row): #iterate through cols in row

            if (pos_col+1) == len(row): # check if we've reached the end of the array
                break # goto next row

            if pixel_value == True: # mask edge found
                list_layer_vertices.append((pos_row, pos_col)) # save layer pixel
                break # go to next row
    return list_layer_vertices

def compute_layer_thickness(mask, method, debug=True):

    # validation
    if method not in [1,2]:
        print(f"Error invalid method id: {method}")
        return

    if debug:
        plt.title("input mask")
        plt.imshow(np.transpose(mask))
        plt.show()

    ############ remove small blobs (anything 10% or smaller)
    label_image, num_labels = label(mask, return_num=True)
    label_region_props = regionprops(label_image)
    for pos, region in enumerate(label_region_props):
        # print(f"pos: {pos} area: {region.area}")
        if pos == 0:   # initialize with first region
            largest_region = region  # initialize largest region
        elif region.area > largest_region.area:
            largest_region = region

    # remove
    layer_mask = label_image # this is done to supress warning about removing blobs on binary mask
    if num_labels > 2: # if num labels == 2 you only have bg and one connected component
        layer_mask = remove_small_objects(label_image, min_size=(largest_region.area*0.1))  # remove spots < 10% largest region found

    layer_mask[layer_mask > 0] = 1 # make mask binary of area will be off

    if debug:
        plt.title("after removing small blobs")
        plt.imshow(layer_mask)
        plt.show()

    ##### EDGE CALCULATION
    vertices_top = _find_top_layer_vertices(layer_mask)
    vertices_bottom = _find_bottom_layer_vertices(np.flip(layer_mask, axis=1))

    list_top_bottom_vertices = [vertices_top, vertices_bottom ]

    # show edges extracted
    # for vertices in list_top_bottom_vertices:
    #     list_vertex_rows = [rows for rows, _ in vertices] # extract height value
    #     list_vertex_heights = [cols for _, cols in vertices]

    #     # show vertices extracted
    #     plt.title("plot of vertices")
    #     plt.scatter(list_vertex_rows, list_vertex_heights, s=1)
    # plt.show()

    # Save equation coefficients, min and max
    list_coeffs = []

    for vertices in list_top_bottom_vertices:
        pass

        ##
        list_vertex_rows = [rows for rows, _ in vertices] # extract height value
        list_vertex_heights = [cols for _, cols in vertices]

        ###### apply hampel filter to remove outliers
        series_heights = pd.Series(list_vertex_heights)
        list_heights_cleaned = hampel(series_heights, window_size=11, n=1, imputation=True) # window size was 3

        # print(len(list_vertex_rows))
        # print(len(list_vertex_heights))
        # print(len(series_heights))
        # print(len(list_heights_cleaned))

        if debug:
            plt.title("red: original, black: after hampel filter")
            series_heights.plot(style="r-", alpha=1)
            series_heights_cleaned = pd.Series(list_heights_cleaned)
            series_heights_cleaned.plot(style="k-", alpha=1)
            plt.show()

        ####### Robtus Fitting RANSAC
        #https://stackoverflow.com/questions/55682156/iteratively-fitting-polynomial-curve/55787598

        from sklearn.metrics import mean_squared_error
        class PolynomialRegression(object):
            def __init__(self, degree=2, coeffs=None):
                self.degree = degree
                self.coeffs = coeffs

            def fit(self, X, y):
                self.coeffs = np.polyfit(X.ravel(), y, self.degree)

            def get_params(self, deep=False):
                return {'coeffs': self.coeffs}

            def set_params(self, coeffs=None, random_state=None):
                self.coeffs = coeffs

            def predict(self, X):
                poly_eqn = np.poly1d(self.coeffs)
                y_hat = poly_eqn(X.ravel())
                return y_hat

            def score(self, X, y):
                return mean_squared_error(y, self.predict(X))

        x_vals = np.asarray(list_vertex_rows)
        y_vals = np.asarray(list_heights_cleaned)

        if debug:
            plt.title("input to RANSACRegressor")
            plt.scatter(x_vals, y_vals, s=1)
            plt.show()

        poly_degree = 2
        stdevs = 3
        residual_threshold = stdevs * np.std(y_vals)
        ransac = RANSACRegressor(PolynomialRegression(degree=poly_degree),
                                  residual_threshold=residual_threshold,
                                  random_state=0)

        ransac.fit(np.expand_dims(x_vals, axis=1), y_vals)
        inlier_mask = ransac.inlier_mask_

        y_hat = ransac.predict(np.expand_dims(x_vals, axis=1))
        if debug:
            plt.plot(x_vals, y_vals, 'bx', label='input samples')
            plt.plot(x_vals[inlier_mask], y_vals[inlier_mask], 'go', markersize=2, label=f'inliers ({str(stdevs)}*STD)')
            plt.plot(x_vals, y_hat, 'r-', label='estimated curve')
            plt.legend()
            plt.show()

        list_vertex_rows

        coeffs = np.polyfit(x_vals, y_hat, poly_degree)
        list_coeffs.append([coeffs, (np.min(list_vertex_rows), np.max(list_vertex_rows))])

    mask = np.transpose(mask) # compute things on a horizontal mask
    n_rows, n_cols = mask.shape
    # plt.imshow(mask)
    # plt.show()

    # METHOD 1 - CALCULATE MIDDLE LINE
    if method == 1:
        #print("method 1 selected")
        poly_top_edge = np.poly1d(list_coeffs[0][0])
        poly_bottom_edge = np.poly1d(list_coeffs[1][0])

        x_vals = np.linspace(0, n_cols, num=(n_cols +1)) # +1 to produce whole numbers/pixels

        y_hat_top = poly_top_edge(x_vals) # top is lower number due to origin on top left
        y_hat_bottom = poly_bottom_edge(x_vals)

        y_hat_middle = y_hat_top + ((y_hat_bottom - y_hat_top)/2)

        # Fit new line and get y values
        coeffs_middle_poly = np.polyfit(x_vals, y_hat_middle, poly_degree)
        poly_middle = np.poly1d(coeffs_middle_poly)
        y_hat_middle = poly_middle(x_vals)

        # Only keep pixels in image
        bool_array_valid_points = y_hat_middle <= n_rows
        x_vals_within_image = x_vals[bool_array_valid_points]
        y_vals_within_image = y_hat_middle[bool_array_valid_points]

        length = 0
        for pos, (x,y) in enumerate(zip(x_vals_within_image, y_vals_within_image)):
            pass
            # reached last value
            index_next_point = idx_curr_value =  pos+1
            if index_next_point == len(x_vals_within_image):
                break

            x_dist = np.absolute(x-x_vals_within_image[index_next_point])
            y_dist = np.absolute(y-y_vals_within_image[index_next_point])
            length +=np.sqrt(x_dist**2 + y_dist**2) # pythagoras

        thickness = np.sum(mask)/length

        if debug:
            plt.title(f"method 1 center line\n layer length: {length:.4f} \n thickness: {thickness:.4f}")
            plt.imshow(mask)
            plt.plot(x_vals_within_image, y_vals_within_image, '-',  linewidth=1)
            plt.show()

        return thickness, [coeffs_middle_poly]

    if method == 2:
        #print("method 2 selected")
        # METHOD 2 - CALCULATE TOP AND BOTTOM EDGES AND AVERAGE DISTANCE

        list_layer_lengths = []

        if debug:
            plt.imshow(mask)

        # Average top and bottom lengths
        list_points_edges = []
        for equation_params in list_coeffs:
            pass
            coeffs, (min_value,max_value) = equation_params
            poly_eqn = np.poly1d(coeffs)

            # y values part of the image
            x_vals = np.linspace(0, n_cols, num=(n_cols +1)) # +1 to produce whole numbers/pixels
            y_hat = poly_eqn(x_vals)

            # Only keep pixels in image
            bool_array_valid_points = y_hat <= n_rows
            x_vals_within_image = x_vals[bool_array_valid_points]
            y_vals_within_image = y_hat[bool_array_valid_points]

            # store points in list_to_return
            list_points_edges.append((x_vals_within_image,y_vals_within_image))

            # Calculate top and bottom lengths
            length = 0
            for pos, (x, y) in enumerate(zip(*[x_vals_within_image, y_vals_within_image])) :
                pass
                index_next_point = idx_curr_value =  pos+1

                #last value outside of array, no next point
                if idx_curr_value == len(x_vals_within_image):
                    break
                # calculate distance
                x_dist = np.absolute(x-x_vals_within_image[index_next_point])
                y_dist = np.absolute(y-y_vals_within_image[index_next_point])
                length +=np.sqrt(x_dist**2 + y_dist**2) # pythagoras
            list_layer_lengths.append(length)

            #plot image
            if debug:
                plt.plot(x_vals_within_image, y_vals_within_image, '-', label='estimated curve', linewidth=1)

        #calculate mean and finally plot lines
        mean_length = np.mean(list_layer_lengths)
        area = np.sum(mask)
        thickness = area/mean_length

        if debug:
            plt.title(f"method 2 avg top and bottom \n top layer: {list_layer_lengths[0]:.4f} bottom layer: {list_layer_lengths[1]:.4f} mean: {mean_length:.4f} \n thickness: {thickness:.4f} ")
            plt.show()

        # return thickness and coeffs of polynomials
        return thickness, mean_length, area, [list_coeffs[0][0], list_coeffs[1][0]] , list_points_edges

#%%

if __name__ == "__main__":
    pass

# Algorithm --> Smooth curved surfaces
# for each mask -->
# to find the top and bottom
# 	for each column find top and bottom masks and take average

working_dir = Path("C:/Users/Nabiki/Desktop/split_masks_selected")
im_paths = list(working_dir.glob("*.tiff"))

#iterate through every mask
for im_path in im_paths: #[3:4]:
    pass
        # LOAD AND SHOW MASK
    mask = tifffile.imread(im_path)
    mask = mask.transpose() ################## image must be vertical and binary
    # plt.title("initial working image")
    # plt.imshow(mask)
    # plt.show()
    method = 2
    thickness = compute_layer_thickness(mask, method, show_images=False)


import math

class Body:
    gravitational_constant = 1

    def __init__(self,
                 mass: float,
                 x: float,
                 y: float,
                 x_velocity: float = 0,
                 y_velocity: float = 0) -> None:
        self.mass = mass
        self.x = x
        self.y = y
        self.x_velocity = x_velocity
        self.y_velocity = y_velocity
        self.x_acceleration = 0
        self.y_acceleration = 0
        self.x_force = 0
        self.y_force = 0

    def calculate_force_vector(
            self, other, max_combination_distance: float) -> tuple[float]:
        d = max(max_combination_distance,
                math.sqrt((other.x - self.x)**2 + (other.y - self.y)**2))
        force = ((self.gravitational_constant * self.mass * other.mass)
                /
                (d**2))
        angle = math.atan2(other.y - self.y, other.x - self.x)
        x_force = math.cos(angle) * force
        y_force = math.sin(angle) * force
        return (x_force, y_force)


from pathlib import Path

import appdirs
from PySide6.QtCore import Signal

from mouse.classifier.cnn_classifier import PRETRAINED_MODELS_CHECKPOINTS
from mouseapp.model.utils import SerializableModel

class FilteringModel(SerializableModel):

    frequency_filter_changed = Signal(bool)
    frequency_threshold_changed = Signal(float)

    neural_network_filter_changed = Signal(bool)
    model_name_changed = Signal(str)
    model_batch_size_changed = Signal(int)
    model_confidence_threshold_changed = Signal(float)

    def __init__(self):
        super().__init__()

        self._default_values = {
            "_frequency_filter":
                False,
            "_frequency_threshold":
                18000.0,
            "_neural_network_filter":
                False,
            "_model_name":
                next(iter(PRETRAINED_MODELS_CHECKPOINTS)),
            "_batch_size":
                1,
            "_confidence_threshold":
                0.2,
            "_cache_dir":
                Path(appdirs.user_data_dir(appname="MoUSE")) /
                "nn_pretrained_models_cache",
        }
        # Frequency filtering
        self._frequency_filter: bool = False
        self._frequency_threshold: float = 0.0

        # Neural network filtering
        self._neural_network_filter: bool = False
        self._model_name = "cnn-binary-v1-custom"
        self._batch_size = 1
        self._confidence_threshold = 0.2
        self._cache_dir = None

        self.set_default_values()
        self.emit_all_setting_signals()

    def set_default_values(self):
        for key, val in self._default_values.items():
            setattr(self, key, val)

    @property
    def frequency_filter(self) -> bool:
        return self._frequency_filter

    @frequency_filter.setter
    def frequency_filter(self, value: bool):
        self._frequency_filter = value

    @property
    def frequency_threshold(self) -> float:
        return self._frequency_threshold

    @frequency_threshold.setter
    def frequency_threshold(self, value: float):
        self._frequency_threshold = value

    @property
    def neural_network_filter(self) -> bool:
        return self._neural_network_filter

    @neural_network_filter.setter
    def neural_network_filter(self, value: bool):
        self._neural_network_filter = value

    @property
    def model_name(self):
        return self._model_name

    @model_name.setter
    def model_name(self, value: str):
        if value not in PRETRAINED_MODELS_CHECKPOINTS:
            raise ValueError(f"Model type should be one of "
                             f"{list(PRETRAINED_MODELS_CHECKPOINTS.keys())} "
                             f"but found {value}")
        self._model_name = value

    @property
    def batch_size(self):
        return int(self._batch_size)

    @batch_size.setter
    def batch_size(self, value: int):
        if value <= 0:
            raise ValueError("Batch size should be greater than zero")
        self._batch_size = int(value)

    @property
    def confidence_threshold(self):
        return self._confidence_threshold

    @confidence_threshold.setter
    def confidence_threshold(self, value: float):
        if value < 0:
            raise ValueError("Confidence threshold should be in range [0, 1]")
        self._confidence_threshold = value

    @property
    def cache_dir(self):
        return self._cache_dir

    @cache_dir.setter
    def cache_dir(self, value: str):
        self._cache_dir = value

    def emit_all_setting_signals(self):
        self.frequency_filter_changed.emit(self.frequency_filter)
        self.frequency_threshold_changed.emit(self.frequency_threshold)

        self.neural_network_filter_changed.emit(self.neural_network_filter)
        self.model_name_changed.emit(self.model_name)
        self.model_batch_size_changed.emit(self.batch_size)
        self.model_confidence_threshold_changed.emit(self.confidence_threshold)

    def get_kwargs(self):
        kwargs = dict()
        for key in self._default_values.keys():
            value = getattr(self, key)
            kwargs[key[1:]] = value

        return kwargs

    def _value_to_dict(self, name, value):
        return value

    def _value_from_dict(self, name, value):
        return value


import CO2_tree as co2t
import CO2Forest as co2f
import numpy
import pickle
from scipy import sparse
from sklearn.metrics import f1_score
from sklearn.metrics import accuracy_score

from sklearn.model_selection import KFold
kf = KFold(n_splits=5)

with open("titanicX.pkl","rb") as f:
    x = pickle.load(f)

with open("titanicY.pkl","rb") as f:
    y = pickle.load(f)

y = y + 1
tree_deth = [9]
sratios = [0.1]
sratios2 = [1.0]
fratios = [0.8]

C = [5000]
#C=[5000,10000]

best_v_acc = 0.

cdp = []

for d in tree_deth:
    for sratio in sratios:
        for sratio2 in sratios2:
            for fratio in fratios:
                for c in C:
                    for ns in [0.]:
                        for cov in [1 for _ in range(10000)]:
                            v_sc = []
                            v2_sc = []
                            t_scw = []
                            t_scf = []
                            wd = []

                            covs = []
                            print ("Test carbon forest with tree deth= ", d+1, " C= ", c, " s ratio ", sratio," s ration 2" ,sratio2," f ratio ",fratio," noise=",ns, "cov=",cov)
                            for train, test in kf.split(x):

                                trc = co2f.CO2Forest(C=c, dual=False,tol = 0.0000001,max_iter=1000000,kernel='linear',max_deth=d,n_jobs=10,sample_ratio=1.0, feature_ratio = fratio,n_estimators=10,gamma=1,dropout_low=sratio,dropout_high=sratio2,noise=ns,cov_dr=cov)

                                trc.fit(sparse.csr_matrix(x[train]), y[train])

                                #Y_v = trc.predict(sparse.csr_matrix(x[test]),True)
                                Y_v_f = trc.predict(sparse.csr_matrix(x[test]),False)

                                #proba_v = trc.predict_proba(sparse.csr_matrix(x[test]),use_weight=True)
                                #proba_f = trc.predict_proba(sparse.csr_matrix(x[test]),use_weight=False)

                                covs.append(numpy.abs(trc.covs).mean())
                                #for i in range(Y_v.shape[0]):
                                #    if Y_v[i] != Y_v_f[i]:
                                #        print ("diff: ")
                                #        print(proba_v[i])
                                #        print(proba_f[i])

                                #wd.append(accuracy_score(Y_v,Y_v_f))

                                #Y_t_w = trc.predict(sparse.csr_matrix(x[train]),True)
                                Y_t_f =  trc.predict(sparse.csr_matrix(x[train]),False)
                                #print(Y_v)

                                try:
                                    #v_sc.append(f1_score(y[test],Y_v))
                                    #t_scw.append(f1_score(y[train],Y_t_w))
                                    t_scf.append(f1_score(y[train],Y_t_f))
                                    v2_sc.append(f1_score(y[test],Y_v_f))

                                except Exception as e:
                                    print("Error:", e)

                            print (v_sc)
                            #v_sc = numpy.asarray(v_sc)
                            v2_sc = numpy.asarray(v2_sc)
                            #t_scw = numpy.asarray(t_scw)
                            t_scf = numpy.asarray(t_scf)

                            #if v_sc.mean() > best_v_acc:
                            #    best_v_acc = v_sc.mean()

                            #print ("Test f1:", v_sc.mean())
                            #print ("Delta_w: ",t_scw.mean() - v_sc.mean())
                            print ("Delta_f: ",t_scf.mean() - v2_sc.mean())
                            #print ("Sim: ", numpy.asarray(wd).mean())
                            print("COVS: ",numpy.asarray(covs).mean())

                            for ij in range(len(t_scf)):
                                if covs[ij] > 0.38:
                                    cdp.append((t_scf[ij] - v2_sc[ij],covs[ij]))

#print ("Best result is:", best_v_acc)
print ("cov vs delta:",cdp)


some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']

#Do Type Casting of the set on the list to remove the duplicate values
new_set = set(some_list)

#Duplicates are removed
print(f'The New set is:{new_set}')

#Make the newset to list using list type casting.
new_list = list(new_set)

#print the newlist.
print('The New list is:{}'.format(new_list))

#Sort the list
new_list.sort()

#print the newlist
print('The New list is:{}'.format(new_list))

#Make Duplicates into new list
some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']

#creates a new list
duplicates = list()

#loop thru each value in the list
for value in some_list:

    #check if count greater than 1 and value should not be present in the duplicates.
    # This is to avoid counting same duplicate value again
    if(some_list.count(value) > 1 and value not in duplicates):

        #adding item into list
        duplicates.append(value)

#Duplicates are removed
print(f'The Duplicate values are :{duplicates}')


class Solution:
    def shipWithinDays(self, weights: List[int], days: int) -> int:

        def can_fit_with(given_capacity):
            curr_day, curr_capacity = 0, 0

            for i in range(len(weights)):
                curr_capacity += weights[i]
                if curr_capacity > given_capacity:
                    if curr_day == days - 1:
                        return False
                    curr_capacity = weights[i]
                    curr_day += 1
            return True

        def binary_search(start, end):
            while start < end:
                mid = (start+end)//2
                if can_fit_with(mid):
                    end = mid
                else:
                    start = mid+1
            return end

        min_capacity, max_capacity = 0, 0
        for weight in weights:
            min_capacity = max(min_capacity, weight)
            max_capacity += weight

        return binary_search(min_capacity, max_capacity)


import flask
import psycopg2
from ..authenticated_blueprint_preparator import AuthenticatedBlueprintPreparator
from .decorators import rest_endpoint

name = 'religion'
app = AuthenticatedBlueprintPreparator(name, __name__, template_folder=None)

@app.route('/religions', role=['user', 'visitor'])
@rest_endpoint
def get_all_religions(c):
    '''
    Get a hierarchy of religions.

    @returns            application/json

    This utilizes the `parent_id` attribute in the table `religion` to build a
    list of trees. The return value is an array of JSON objects. Each root node
    is a main religion, and one of its attributes is `children`, holding an
    array of children, which may again hold children, and so on.

    Each node of each tree has the following, exemplary (2020-01-09) structure:

        {
            "abbreviation": "MARO",
            "children": [ ... ],
            "color": "hsl(10, 80%, 50%)",
            "id": 3,
            "name": "Maronite Church",
            "parent_id": 98
        }
    '''
    c.execute('select * from religion')
    data = list(map(lambda x: x._asdict(), c.fetchall()))

    def append_children(parent, lst):
        children = list(filter(lambda x: x['parent_id'] == parent['id'], lst))
        parent['children'] = children
        for child in children:
            append_children(child, lst)
        return parent

    toplevel = list(map(lambda x: append_children(x, data), filter(lambda x: x['parent_id'] is None, data)))

    return flask.jsonify(toplevel)

@app.route('/religion-list', role=['user', 'visitor'])
@rest_endpoint
def get_religion_list(c):
    '''
    Get a list of religion names and IDs.

    @returns            application/json

    Example return value excerpt:

        [
          {
            "id": 1,
            "name": "Christianity",
            "parent_id": null
          },
          {
            "id": 5,
            "name": "Church of the East",
            "parent_id": 1
          },
          ...
        ]
    '''
    c.execute('select id, name, parent_id from religion')
    return flask.jsonify(list(map(lambda x: x._asdict(), c.fetchall())))


import datetime

def pretty_print(date):

    day_suffix = ''

    ones_digit = date.day%10
    tens_digit = date.day//10
    if tens_digit == 1:
        day_suffix = 'th'
    else:
        if ones_digit == 1:
            day_suffix = 'st'
        elif ones_digit == 2:
            day_suffix = 'nd'
        elif ones_digit == 3:
            day_suffix = 'rd'
        else:
            day_suffix = 'th'

    day = int(date.strftime('%d'))
    return date.strftime(f'%A, %B {day}{day_suffix} %Y')

# date = datetime.datetime.now()
date = datetime.datetime(2019, 9, 1)
for i in range(40):
    print(pretty_print(date))
    dt = datetime.timedelta(days=1)
    date += dt