import tensorflow.compat.v1 as tf
import os
import re
import time
import argparse
import datetime
import random
from socket import gethostname
from collections import deque, OrderedDict, namedtuple
from contextlib import ExitStack
from functools import partial
import numpy as np
import sys
import importlib
import validation
import log as logging
from tensorflow.python import ipu
from ipu_utils import get_config
from tensorflow.compiler.plugin.poplar.ops import gen_ipu_ops
from tensorflow.python.ipu.autoshard import automatic_sharding
from tensorflow.python.ipu import loops, ipu_infeed_queue, ipu_outfeed_queue, ipu_compiler
from tensorflow.python.ipu.utils import reset_ipu_seed
from tensorflow.python.ipu.ops import pipelining_ops
from ipu_optimizer import IPUOptimizer
from tensorflow.python.ipu.scopes import ipu_scope
import Datasets.data as dataset
from Datasets import imagenet_dataset
from weight_avg import average_ckpts, save_ckpt
DATASET_CONSTANTS = dataset.DATASET_CONSTANTS

GraphOps = namedtuple(
    'graphOps', ['graph',
                 'session',
                 'init',
                 'ops',
                 'placeholders',
                 'iterator',
                 'outfeed',
                 'saver',
                 'profile'])

pipeline_schedule_options = [str(p).split(".")[-1] for p in list(pipelining_ops.PipelineSchedule)]

def calculate_loss(logits, label, opts):
    predictions = tf.argmax(logits, 1, output_type=tf.int32)
    accuracy = tf.reduce_mean(tf.cast(tf.equal(predictions, label), tf.float16))

    # Loss
    if opts["label_smoothing"] > 0:
        num_classes = logits.get_shape().as_list()[1]
        smooth_negatives = opts["label_smoothing"] / (num_classes - 1)
        smooth_positives = (1.0 - opts["label_smoothing"])
        smoothed_labels = tf.one_hot(label, num_classes, on_value=smooth_positives, off_value=smooth_negatives)
        cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=smoothed_labels))
    else:
        cross_entropy = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=label))

    tf.add_to_collection('losses', cross_entropy)
    loss = tf.add_n(tf.get_collection('losses'), name='total_loss')

    return loss, cross_entropy, accuracy

def get_optimizer(opts):
    if opts['optimiser'] == 'SGD':
        opt_fun = tf.train.GradientDescentOptimizer
    elif opts['optimiser'] == 'momentum':
        opt_fun = partial(tf.train.MomentumOptimizer, momentum=opts['momentum'])
    elif opts['optimiser'] == 'RMSprop':
        opt_fun = partial(tf.train.RMSPropOptimizer, momentum=opts['momentum'],
                          decay=opts['rmsprop_decay'], epsilon=opts['rmsprop_epsilon'])
    else:
        raise ValueError("Optimizer {} not recognised".format(opts['optimiser']))

    wd_exclude = opts["wd_exclude"] if "wd_exclude" in opts.keys() else []

    # get variables to include in training
    if opts["variable_filter"]:
        var_list = [v for v in tf.trainable_variables() if any(s in v.name for s in opts["variable_filter"])]
    else:
        var_list = tf.trainable_variables()

    def filter_fn(name):
        return not any(s in name for s in wd_exclude)

    return lambda lr: IPUOptimizer(opt_fun(lr),
                                   sharded=opts["shards"] > 1 and opts['pipeline_depth'] == 1,
                                   replicas=opts["replicas"],
                                   gradients_to_accumulate=opts["gradients_to_accumulate"] * opts['pipeline_depth'],
                                   pipelining = opts['pipeline_depth'] > 1,
                                   grad_scale=opts["grad_scale"],
                                   weight_decay=opts["weight_decay"] * opts['loss_scaling'],
                                   weight_decay_filter_fn=filter_fn,
                                   var_list=var_list)

def calculate_and_apply_gradients(loss, opts=None, learning_rate=None):
    optimizer = get_optimizer(opts)(learning_rate / opts['lr_scale'])
    grads_and_vars = optimizer.compute_gradients(loss * opts['loss_scaling'])
    with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
        return learning_rate, optimizer.apply_gradients(grads_and_vars)

def basic_training_step(image, label, model, opts, learning_rate):
    """
    A basic training step that will work on all hardware
    """
    if opts['no_hostside_norm']:
        image = imagenet_dataset.accelerator_side_preprocessing(image, opts=opts)

    logits = model(opts, training=True, image=image)
    loss, cross_entropy, accuracy = calculate_loss(logits, label, opts)

    learning_rate, train_op = calculate_and_apply_gradients(loss, opts, learning_rate=learning_rate)
    if opts['shards'] > 1:
        def filter(edge):
            return (any(f in e for e in edge for f in opts["sharding_exclude_filter"]) or
                    not any(f in e for e in edge for f in opts["sharding_include_filter"]))
        automatic_sharding(opts['shards'], image, cross_entropy, edge_filter=filter)

    return loss, cross_entropy, accuracy, learning_rate, train_op

def basic_pipelined_training_step(model, opts, learning_rate, infeed, outfeed, iterations_per_step=1):

    def first_stage(learning_rate, image, label,  pipeline_stage=None, idx=None):
        if opts['no_hostside_norm'] and idx == 0:
            image = imagenet_dataset.accelerator_side_preprocessing(image, opts=opts)

        return learning_rate, pipeline_stage(image), label,

    def final_stage(learning_rate, x, label,  pipeline_stage=None):
        x = pipeline_stage(x)
        loss, cross_entropy, accuracy = calculate_loss(x, label, opts)
        return loss, cross_entropy, accuracy, learning_rate / opts["lr_scale"]

    model_stages = model(opts)
    computational_stages = [partial(first_stage, pipeline_stage=model_stages[idx], idx=idx) for idx in range(len(model_stages) - 1)]
    computational_stages.append(partial(final_stage, pipeline_stage=model_stages[-1]))

    def optimizer_function(loss, _, __, lr):
        optimizer = get_optimizer(opts)(lr)
        return pipelining_ops.OptimizerFunctionOutput(optimizer, loss * opts["loss_scaling"])

    options = None
    amps = opts['available_memory_proportion']
    if amps and len(amps) > 1:
        # Map values to the different pipeline stages
        options = []
        for i in range(len(amps) // 2):
            options.append(pipelining_ops.PipelineStageOptions({"availableMemoryProportion": amps[2*i]},
                                                               {"availableMemoryProportion": amps[2*i + 1]}))

    return pipelining_ops.pipeline(computational_stages=computational_stages,
                                   pipeline_depth=int(opts['pipeline_depth']),
                                   repeat_count=iterations_per_step,
                                   inputs=[learning_rate],
                                   infeed_queue=infeed,
                                   outfeed_queue=outfeed,
                                   optimizer_function=optimizer_function,
                                   forward_propagation_stages_poplar_options=options,
                                   backward_propagation_stages_poplar_options=options,
                                   pipeline_schedule=next(p for p in list(pipelining_ops.PipelineSchedule)
                                                          if opts["pipeline_schedule"] == str(p).split(".")[-1]),
                                   offload_weight_update_variables=False if opts['disable_variable_offloading'] else True,
                                   name="Pipeline")

def distributed_per_replica(function):
    """Run the function with the distribution strategy (if any) in a per-replica context."""
    def wrapper(*arguments):
        if tf.distribute.has_strategy():
            strategy = tf.distribute.get_strategy()
            return strategy.experimental_run_v2(function, args=arguments)
        else:
            return function(*arguments)

    return wrapper

@distributed_per_replica
def training_step_with_infeeds_and_outfeeds(train_iterator, outfeed, model, opts, learning_rate, iterations_per_step=1):
    """
    Training step that uses an infeed loop with outfeeds. This runs 'iterations_per_step' steps per session call. This leads to
    significant speed ups on IPU. Not compatible with running on CPU or GPU.
    """

    if int(opts['pipeline_depth']) > 1:
        training_step = partial(basic_pipelined_training_step,
                                model=model.staged_model,
                                opts=opts,
                                learning_rate=learning_rate,
                                infeed=train_iterator,
                                outfeed=outfeed,
                                iterations_per_step=iterations_per_step)

        return ipu_compiler.compile(training_step, [])
    else:
        training_step = partial(basic_training_step,
                                model=model.Model,
                                opts=opts,
                                learning_rate=learning_rate)

        def training_step_loop(image=None, label=None, outfeed=None):
            loss, cross_ent, accuracy, lr_out, apply_grads = training_step(image, label)
            outfeed = outfeed.enqueue((loss, cross_ent, accuracy, lr_out))
            return outfeed, apply_grads

        def compiled_fn():
            return loops.repeat(iterations_per_step,
                                partial(training_step_loop, outfeed=outfeed),
                                [],
                                train_iterator)

        return ipu_compiler.compile(compiled_fn, [])

def configure_distribution(opts, sess_config):
    """
    Creates the distribution strategy, updates the given session configuration
    accordingly, and starts a distributed server that allows the workers to connect.
    Returns the strategy, the session target address and the updated session configuration.
    """

    cluster = tf.distribute.cluster_resolver.SimpleClusterResolver(
        cluster_spec=tf.train.ClusterSpec(opts['distributed_cluster']),
        task_id=opts['distributed_worker_index'],
        task_type="worker")

    strategy = ipu.ipu_multi_worker_strategy.IPUMultiWorkerStrategy(cluster)
    sess_config = strategy.update_config_proto(sess_config)
    server = tf.distribute.Server(cluster.cluster_spec(),
                                  job_name=cluster.task_type,
                                  task_index=cluster.task_id,
                                  protocol=cluster.rpc_layer,
                                  config=sess_config)

    return strategy, server.target, sess_config

def training_graph(model, opts, iterations_per_step=1):
    train_graph = tf.Graph()
    sess_config = tf.ConfigProto()
    sess_target = None
    strategy = None

    if opts['distributed_cluster']:
        strategy, sess_target, sess_config = configure_distribution(opts, sess_config)

    with train_graph.as_default(), ExitStack() as stack:
        if strategy:
            stack.enter_context(strategy.scope())

        placeholders = dict()
        datatype = tf.float16 if opts["precision"].split('.') == '16' else tf.float32
        placeholders['learning_rate'] = tf.placeholder(datatype, shape=[])
        learning_rate = placeholders['learning_rate']

        # datasets must be defined outside the ipu device scope
        train_iterator = ipu_infeed_queue.IPUInfeedQueue(dataset.data(opts, is_training=True),
                                                         feed_name='training_feed',
                                                         replication_factor=opts['replicas'])
        outfeed_queue = ipu_outfeed_queue.IPUOutfeedQueue(feed_name="outfeed",
                                                          replication_factor=opts['replicas'])

        with ipu_scope('/device:IPU:0'):
            train = training_step_with_infeeds_and_outfeeds(train_iterator, outfeed_queue, model,
                                                            opts, learning_rate, iterations_per_step)

        outfeed = outfeed_queue.dequeue()
        if strategy:
            # Take the mean of all the outputs across the distributed workers
            outfeed = [strategy.reduce(tf.distribute.ReduceOp.MEAN, v) for v in outfeed]

        logging.print_trainable_variables(opts)

        train_saver = tf.train.Saver(max_to_keep=999999)
        with tf.device('cpu'):
            profile_report = gen_ipu_ops.ipu_event_trace()
        ipu.utils.move_variable_initialization_to_cpu(graph=None)
        train_init = tf.global_variables_initializer()

    globalAMP = None
    if opts["available_memory_proportion"] and len(opts["available_memory_proportion"]) == 1:
        globalAMP = opts["available_memory_proportion"][0]

    ipu_options = get_config(ipu_id=opts["select_ipu"],
                             prng=not opts["no_stochastic_rounding"],
                             shards=opts["shards"],
                             number_of_replicas=opts['replicas'],
                             max_cross_replica_buffer_size=opts["max_cross_replica_buffer_size"],
                             fp_exceptions=opts["fp_exceptions"],
                             half_partials=opts["enable_half_partials"],
                             conv_dithering=opts["enable_conv_dithering"],
                             xla_recompute=opts["xla_recompute"],
                             seed=opts["seed"],
                             profile=opts['profile'],
                             availableMemoryProportion=globalAMP,
                             stable_norm=opts["stable_norm"],
                             internalExchangeOptimisationTarget=opts[
                                 "internal_exchange_optimisation_target"
                             ])

    ipu.utils.configure_ipu_system(ipu_options)
    train_sess = tf.Session(graph=train_graph, config=sess_config, target=sess_target)

    return GraphOps(train_graph, train_sess, train_init, [train], placeholders, train_iterator, outfeed, train_saver, profile_report)

def training_step(train, e, learning_rate):
    # Run Training
    start = time.time()
    _ = train.session.run(train.ops, feed_dict={train.placeholders['learning_rate']: learning_rate})
    batch_time = (time.time() - start)
    if not os.environ.get('TF_POPLAR_FLAGS') or '--use_synthetic_data' not in os.environ.get('TF_POPLAR_FLAGS'):
        loss, cross_ent, accuracy, lr_out = train.session.run(train.outfeed)
        loss = np.mean(loss)
        accuracy = 100.0 * np.mean(accuracy)
        lr = lr_out.flatten()[-1]
    else:
        loss, accuracy, lr = 0, 0, 0
    return loss, accuracy, batch_time, lr

def train_process(model, LR_Class, opts):

    # --------------- OPTIONS --------------------
    epochs = opts["epochs"]
    iterations_per_epoch = DATASET_CONSTANTS[opts['dataset']]['NUM_IMAGES'] // opts["total_batch_size"]
    if not opts['iterations']:
        iterations = epochs * iterations_per_epoch
        log_freq = iterations_per_epoch // opts['logs_per_epoch']
    else:
        iterations = opts['iterations']
        log_freq = opts['log_freq']

    if log_freq < opts['batches_per_step']:
        iterations_per_step = log_freq
    else:
        iterations_per_step = log_freq // int(round(log_freq / opts['batches_per_step']))

    iterations_per_valid = iterations_per_epoch
    iterations_per_ckpt = iterations_per_epoch // opts['ckpts_per_epoch'] if opts['ckpts_per_epoch'] else np.inf

    LR = LR_Class(opts, iterations)

    batch_accs = deque(maxlen=iterations_per_epoch // iterations_per_step)
    batch_losses = deque(maxlen=iterations_per_epoch // iterations_per_step)
    batch_times = deque(maxlen=iterations_per_epoch // iterations_per_step)
    start_all = None

    # -------------- BUILD TRAINING GRAPH ----------------

    train = training_graph(model, opts, iterations_per_step*opts["gradients_to_accumulate"])
    train.session.run(train.init)
    train.session.run(train.iterator.initializer)

    # -------------- SAVE AND RESTORE --------------
    if opts.get('init_path'):
        train.saver.restore(train.session, opts['init_path'])

    if opts['ckpts_per_epoch']:
        filepath = train.saver.save(train.session, opts["checkpoint_path"], global_step=0)
        print("Saved checkpoint to {}".format(filepath))

    if opts.get('restoring'):
        filename_pattern = re.compile(".*ckpt-[0-9]+$")
        ckpt_pattern = re.compile(".*ckpt-([0-9]+)$")
        filenames = sorted([os.path.join(opts['logs_path'], f[:-len(".index")])
                            for f in os.listdir(opts['logs_path']) if filename_pattern.match(f[:-len(".index")]) and f[-len(".index"):] == ".index"], key=lambda x: int(ckpt_pattern.match(x).groups()[0]))
        latest_checkpoint = filenames[-1]
        logging.print_to_file_and_screen("Restoring training from latest checkpoint: {}".format(latest_checkpoint), opts)
        ckpt_pattern = re.compile(".*ckpt-([0-9]+)$")
        i = int(ckpt_pattern.match(latest_checkpoint).groups()[0])
        train.saver.restore(train.session, latest_checkpoint)
        epoch = float(opts["total_batch_size"] * (i + iterations_per_step)) / DATASET_CONSTANTS[opts['dataset']][
            'NUM_IMAGES']
    else:
        i = 0

    # ------------- TRAINING LOOP ----------------

    print_format = ("step: {step:6d}, iteration: {iteration:6d}, epoch: {epoch:6.2f}, lr: {lr:6.4g}, loss: {loss_avg:6.3f}, top-1 accuracy: {train_acc_avg:6.3f}%"
                    ", img/sec: {img_per_sec:6.2f}, time: {it_time:8.6f}, total_time: {total_time:8.1f}")

    step = 0
    start_all = time.time()
    while i < iterations:
        step += opts["gradients_to_accumulate"]
        log_this_step = ((i // log_freq) < ((i + iterations_per_step) // log_freq) or
                         (i == 0) or
                         ((i + (2 * iterations_per_step)) >= iterations))
        ckpt_this_step = (opts["ckpts_per_epoch"] and
                          ((i // iterations_per_ckpt) < ((i + iterations_per_step) // iterations_per_ckpt) or
                          (i == 0) or
                          ((i + (2 * iterations_per_step)) >= iterations)))
        valid_this_step = (opts['validation'] and
                           ((i // iterations_per_valid) < ((i + iterations_per_step) // iterations_per_valid) or
                           (i == 0) or
                           ((i + (2 * iterations_per_step)) >= iterations)))

        # Run Training
        try:
            batch_loss, batch_acc, batch_time, current_lr = training_step(train, i + 1, LR.feed_dict_lr(i))
            if opts['pipeline_depth'] > 1:
                current_lr *= opts["lr_scale"]
        except tf.errors.OpError as e:
            raise tf.errors.ResourceExhaustedError(e.node_def, e.op, e.message)

        batch_time /= iterations_per_step

        # Calculate Stats
        batch_accs.append([batch_acc])
        batch_losses.append([batch_loss])

        if i != 0:
            batch_times.append([batch_time])

        # Print loss
        if log_this_step:
            train_acc = np.mean(batch_accs)
            train_loss = np.mean(batch_losses)

            if len(batch_times) != 0:
                avg_batch_time = np.mean(batch_times)
            else:
                avg_batch_time = batch_time

            # flush times every time it is reported
            batch_times.clear()

            total_time = time.time() - start_all
            epoch = float(opts["total_batch_size"] * (i + iterations_per_step)) / DATASET_CONSTANTS[opts['dataset']]['NUM_IMAGES']

            stats = OrderedDict([
                ('step', step),
                ('iteration', i+iterations_per_step),
                ('epoch', epoch),
                ('lr', current_lr),
                ('loss_batch', batch_loss),
                ('loss_avg', train_loss),
                ('train_acc_batch', batch_acc),
                ('train_acc_avg', train_acc),
                ('it_time', avg_batch_time),
                ('img_per_sec', opts['total_batch_size']/avg_batch_time),
                ('total_time', total_time),
            ])

            logging.print_to_file_and_screen(print_format.format(**stats), opts)
            logging.write_to_csv(stats, i == 0, True, opts)

        if ckpt_this_step:
            filepath = train.saver.save(train.session, opts["checkpoint_path"], global_step=i+iterations_per_step)
            print("Saved checkpoint to {}".format(filepath))
            if 'ckpts' not in locals():
                ckpts = []
            ckpts.append((i + iterations_per_step, epoch, i == 0, filepath))

        # Eval
        if valid_this_step and opts['validation']:
            if 'validation_points' not in locals():
                validation_points = []
            validation_points.append((i + iterations_per_step, epoch, i == 0, filepath))

        # ------------ COLLECT PROFILE -----------
        if opts["profile"] and i == 0:
            from gcprofile import save_tf_report
            save_tf_report(train.session.run(train.profile))

        i += iterations_per_step

    if opts['weight_avg_N'] or opts['weight_avg_exp']:
        _ckpts = ckpts[:-1]  # discard final checkpoint as the final 2 are practically identical
        final_iteration, final_epoch = _ckpts[-1][:2]
        if opts['weight_avg_N']:
            for N in opts['weight_avg_N']:
                V = average_ckpts(
                    [c[3] for c in _ckpts if round(c[1], 1) >= round(final_epoch, 1) - N],
                    mode='mean')
                filename = os.path.join(opts["checkpoint_path"], "weight_avg_N_{}".format(N))
                save_ckpt(V, ckpts[-1][3], filename)
                validation_points.append((final_iteration, final_epoch, False, filename))

        if opts['weight_avg_exp']:
            for d in opts['weight_avg_exp']:
                V = average_ckpts(list(zip(*ckpts))[3], mode='exponential', decay=d)
                filename = os.path.join(opts["checkpoint_path"], "weight_avg_exp_{}".format(d))
                save_ckpt(V, ckpts[-1][3], filename)
                validation_points.append((final_iteration, final_epoch, False, filename))

    # ------------ VALIDATION ------------
    if 'validation_points' in locals() and opts['validation']:
        # -------------- BUILD VALIDATION GRAPH ----------------
        valid = validation.initialise_validation(model, opts)

        # ------------ RUN VALIDATION ------------
        for iteration, epoch, first_run, filepath in validation_points:
            validation.validation_run(valid, filepath, iteration, epoch, first_run, opts)

    # --------------- CLEANUP ----------------
    train.session.close()

def add_main_arguments(parser, required=True):
    group = parser.add_argument_group('Main')
    group.add_argument('--model', type=str.lower, default='resnet', help="Choose model")
    group.add_argument('--lr-schedule', default='stepped',
                       help="Learning rate schedule function. Default: stepped")
    group.add_argument('--help', action='store_true', help='Show help information')

    return parser

def set_main_defaults(opts):
    opts['summary_str'] = "\n"

def add_training_arguments(parser):
    tr_group = parser.add_argument_group('Training')
    tr_group.add_argument('--batch-size', type=int,
                          help="Set batch-size for training graph")
    tr_group.add_argument('--gradients-to-accumulate', type=int, default=1,
                          help="Number of gradients to accumulate before doing a weight update")
    tr_group.add_argument('--base-learning-rate', type=float,
                          help="Base learning rate exponent (2**N). blr = lr /  bs")
    tr_group.add_argument('--epochs', type=float,
                          help="Number of training epochs")
    tr_group.add_argument('--iterations', type=int, default=None,
                          help="Force a fixed number of training iterations to be run rather than epochs.")
    tr_group.add_argument('--weight-decay', type=float,
                          help="Value for weight decay bias, setting to 0 removes weight decay.")
    tr_group.add_argument('--loss-scaling', type=float, default=128,
                          help="Loss scaling factor")
    tr_group.add_argument('--label-smoothing', type=float, default=0,
                          help="Label smoothing factor (Default=0 => no smoothing)")

    tr_group.add_argument('--ckpts-per-epoch', type=int, default=1,
                          help="Checkpoints per epoch")
    tr_group.add_argument('--no-validation', action="store_false", dest='validation',
                          help="Dont do any validation runs.")
    tr_group.set_defaults(validation=True)
    tr_group.add_argument('--shards', type=int, default=1,
                          help="Number of IPU shards for training graph")
    tr_group.add_argument('--replicas', type=int, default=1,
                          help="Replicate graph N times to increase batch to batch-size*N")
    tr_group.add_argument('--max-cross-replica-buffer-size', type=int, default=10*1024*1024,
                          help="""The maximum number of bytes that can be waiting before a cross
                                replica sum op is scheduled. [Default=10*1024*1024]""")

    tr_group.add_argument('--pipeline-depth', type=int, default=1,
                          help="Depth of pipeline to use. Must also set --shards > 1.")
    tr_group.add_argument('--pipeline-splits', nargs='+', type=str, default=None,
                          help="Strings for splitting pipelines. E.g. b2/0/relu b3/0/relu")
    tr_group.add_argument('--pipeline-schedule', type=str, default="Interleaved",
                          choices=pipeline_schedule_options, help="Pipelining scheduler. Choose between 'Interleaved' and 'Grouped'")
    tr_group.add_argument('--optimiser', type=str, default="SGD", choices=['SGD', 'RMSprop', 'momentum'],
                          help="Optimiser")
    tr_group.add_argument('--momentum', type=float, default=0.9,
                          help="Momentum coefficient")
    tr_group.add_argument('--rmsprop-decay', type=float, default=0.9,
                          help="RMSprop decay coefficient")
    tr_group.add_argument('--rmsprop-epsilon', type=float, default=0.001,
                          help="RMSprop epsilon coefficient")
    tr_group.add_argument('--variable-filter', nargs='+', type=str, default=[],
                          help="Filter which variables to include in training")
    tr_group.add_argument('--init-path', type=str,
                          help="Path to checkpoint to initialise from")

    tr_group.add_argument('--distributed', action="store_true",
                          help="Use distributed multi-worker training")

    tr_group.add_argument('--stable-norm', action="store_true",
                          help="Use stable implementation of normalization functions")

    tr_group.add_argument('--weight-avg-N', nargs='+', type=int, default=None,
                          help="Number of checkpoints to average over")
    tr_group.add_argument('--weight-avg-exp', nargs='+', type=float, default=None,
                          help="Decay factor for averaging weights")
    return parser

def set_training_defaults(opts):
    if int(opts['pipeline_depth']) > 1:
        opts['gradients_to_accumulate'] = 1

    opts['total_batch_size'] = opts['batch_size']*opts['gradients_to_accumulate']*opts['pipeline_depth']*opts['replicas']*opts['distributed_worker_count']
    opts['summary_str'] += "Training\n"
    opts['summary_str'] += " Batch Size: {total_batch_size}\n"
    if opts['pipeline_depth'] > 1:
        opts['summary_str'] += "  Pipelined over {shards} stages with depth {pipeline_depth} \n"
    elif opts['gradients_to_accumulate'] > 1:
        opts['summary_str'] += "  Accumulated over {gradients_to_accumulate} fwds/bwds passes \n"
    if opts['replicas'] > 1:
        opts['summary_str'] += "  Training on {replicas} replicas \n"
    opts['summary_str'] += (" Base Learning Rate: 2**{base_learning_rate}\n"
                            " Weight Decay: {weight_decay}\n"
                            " Loss Scaling: {loss_scaling}\n")
    if opts["iterations"]:
        opts['summary_str'] += " Iterations: {iterations}\n"
    else:
        opts['summary_str'] += " Epochs: {epochs}\n"

    if opts['shards'] > 1:
        opts['summary_str'] += " Training Shards: {shards}\n"

    # lr_scale is used to scale down the LR to account for loss scaling
    # lr_scale==loss_scaling iff the update is not divided by a linear function
    # of the gradients otherwise lr_scale = 1
    opts['lr_scale'] = opts['loss_scaling']
    opts['grad_scale'] = 1.0
    if opts['optimiser'] == 'SGD':
        opts['summary_str'] += "SGD\n"
    elif opts['optimiser'] == 'momentum':
        opts['summary_str'] += ("SGD with Momentum\n"
                                " Momentum: {momentum}\n")
    elif opts['optimiser'] == 'RMSprop':
        opts['summary_str'] += ("RMSprop\n"
                                " Momentum: {momentum}\n"
                                " Decay: {rmsprop_decay}\n"
                                " Epsilon: {rmsprop_epsilon}\n")
        opts['lr_scale'] = 1.0
        opts['grad_scale'] = opts['loss_scaling']

def add_ipu_arguments(parser):
    group = parser.add_argument_group('IPU')
    group.add_argument('--precision', type=str, default="16.16", choices=["16.16", "16.32", "32.32"],
                       help="Precision of Ops(weights/activations/gradients) and Master data types: 16.16, 16.32, 32.32")
    group.add_argument('--enable-half-partials', action="store_true", default=False,
                       help="Use half (fp16) partials for both convolutions and matmuls")
    group.add_argument('--no-stochastic-rounding', action="store_true",
                       help="Disable Stochastic Rounding")
    group.add_argument('--batches-per-step', type=int, default=1000,
                       help="Maximum number of batches to perform on the device before returning to the host.")
    group.add_argument('--select-ipu', type=str, default="AUTO",
                       help="Select IPU either: AUTO or IPU ID")
    group.add_argument('--sharding-exclude-filter', nargs='+', type=str, default=['0/p'],
                       help="Excluded strings for splitting edges (only a substring must match)")
    group.add_argument('--sharding-include-filter', nargs='+', type=str, default=[''],
                       help="Included strings for splitting edges (only a substring must match)")
    group.add_argument('--fp-exceptions', action="store_true",
                       help="Turn on floating point exceptions")
    group.add_argument('--xla-recompute', action="store_true",
                       help="Allow recomputation of activations to reduce memory usage")
    group.add_argument('--seed', default=None, help="Seed for randomizing training")
    group.add_argument('--gc-profile', type=str, dest='profile', nargs='?', action='store', default=None,
                       const="IPU_PROFILE", choices=["DEVICE_PROFILE", "IPU_PROFILE", "TILE_PROFILE", "NO_PROFILE"],
                       help="Generate profile reprts")
    group.add_argument('--available-memory-proportion', default=None, nargs='+',
                       help="Proportion of memory which is available for convolutions. Use a value of less than 0.6 "
                            "to reduce memory usage.")
    group.add_argument('--disable-variable-offloading', action="store_true",
                       help="Disable offloading of variables to remote memory. This may increase live memory usage")
    group.add_argument('--enable-conv-dithering', action="store_true", default=False,
                       help="Enable dithering of the convolution start tile to improve tile memory balance")
    group.add_argument('--internal-exchange-optimisation-target', type=str, default=None,
                       choices=["balanced", "cycles", "memory"],
                       help="""The optimisation approach for internal exchanges.""")
    return parser

def set_distribution_defaults(opts):
    if opts['distributed']:
        if opts['batches_per_step'] > 1:
            raise ValueError("--batches-per-step must be 1 with distribution")

        # Read the cluster config from the `TF_CONFIG` environment variable
        cluster = tf.distribute.cluster_resolver.TFConfigClusterResolver()

        # Allow `mpirun` to override the task index
        cluster.task_id = os.getenv("OMPI_COMM_WORLD_RANK")
        cluster.task_type = "worker"

        opts['distributed_worker_count'] = cluster.cluster_spec().num_tasks("worker")
        opts['distributed_worker_index'] = cluster.task_id
        opts['distributed_cluster'] = cluster.cluster_spec().as_dict()

        opts['summary_str'] += 'Distribution\n'
        opts['summary_str'] += ' Worker count: {distributed_worker_count}\n'
        opts['summary_str'] += ' Worker index: {distributed_worker_index}\n'
        opts['summary_str'] += ' Cluster: {distributed_cluster}\n'
    else:
        opts['distributed_worker_count'] = 1
        opts['distributed_worker_index'] = 0
        opts['distributed_cluster'] = None

def set_ipu_defaults(opts):
    opts['summary_str'] += "Using Infeeds\n Max Batches Per Step: {batches_per_step}\n"
    opts['summary_str'] += 'Device\n'
    opts['summary_str'] += ' Precision: {}{}\n'.format(opts['precision'], '_noSR' if opts['no_stochastic_rounding'] else '')
    opts['summary_str'] += ' IPU\n'
    opts['poplar_version'] = os.popen('popc --version').read()
    opts['summary_str'] += ' {poplar_version}'
    opts['select_ipu'] = -1 if opts['select_ipu'].lower() == 'auto' else int(opts['select_ipu'])

    opts['hostname'] = gethostname()
    opts['datetime'] = str(datetime.datetime.now())

    if opts['seed']:
        # Seed the various random sources
        seed = int(opts['seed'])
        opts['seed_specified'] = True
        set_seeds(seed)
        opts['seed'] = seed
    else:
        opts['seed_specified'] = False

    opts['summary_str'] += (' {hostname}\n'
                            ' {datetime}\n')

def set_seeds(seed):
    random.seed(seed)
    # Set other seeds to different values for extra safety
    tf.set_random_seed(random.randint(0, 2**32 - 1))
    np.random.seed(random.randint(0, 2**32 - 1))
    reset_ipu_seed(random.randint(-2**16, 2**16 - 1))

def create_parser(model, lr_schedule, parser):
    parser = model.add_arguments(parser)
    parser = dataset.add_arguments(parser)
    parser = add_training_arguments(parser)
    parser = lr_schedule.add_arguments(parser)
    parser = add_ipu_arguments(parser)
    parser = logging.add_arguments(parser)
    return parser

def set_defaults(model, LR, opts):
    set_main_defaults(opts)
    dataset.set_defaults(opts)
    model.set_defaults(opts)
    set_distribution_defaults(opts)
    set_training_defaults(opts)
    LR.set_defaults(opts)
    validation.set_validation_defaults(opts)
    set_ipu_defaults(opts)
    logging.set_defaults(opts)

def set_profiling_opts(opts):
    if(opts["profile"]):
        opts["summary_str"] += 'A profiling session is run, the report will be retrieved for the first iteration'

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='CNN Training in TensorFlow', add_help=False)
    parser = add_main_arguments(parser)
    args, unknown = parser.parse_known_args()
    args = vars(args)

    try:
        model = importlib.import_module("Models." + args['model'])
    except ImportError:
        raise ValueError('Models/{}.py not found'.format(args['model']))

    try:
        lr_schedule = importlib.import_module("LR_Schedules." + args['lr_schedule'])
    except ImportError:
        raise ValueError("LR_Schedules/{}.py not found".format(args['lr_schedule']))

    # Large number of deprecation warnings that cannot be resolved yet.
    tf.logging.set_verbosity(tf.logging.ERROR)

    parser = create_parser(model, lr_schedule, parser)
    opts = vars(parser.parse_args())
    if opts['help']:
        parser.print_help()
    else:
        if opts['gradients_to_accumulate'] > 1 and opts['pipeline_depth'] > 1:
            raise ValueError("gradients-to-accumulate can't be specified when using --pipeline-depth > 1")
        if opts['pipeline_depth'] > 1 and opts['shards'] == 1:
            raise ValueError("--pipeline-depth can only be used if --shards > 1")
        amps = opts['available_memory_proportion']
        if amps and len(amps) > 1:
            if not opts['pipeline_depth'] > 1:
                raise ValueError('--available-memory-proportion should only have one value unless using pipelining')
            if len(amps) != int(opts['shards']) * 2:
                raise ValueError('--available-memory-proportion should have either one value or 2*shards values specified')

        opts["command"] = ' '.join(sys.argv)
        set_defaults(model, lr_schedule, opts)

        if opts['dataset'] == 'imagenet':
            if opts['image_size'] is None:
                opts['image_size'] = 224
            if opts['image_size'] != 224:
                opts['name'] += '_{}x{}'.format(opts['image_size'], opts['image_size'])
            opts['summary_str'] += "Image Size: {}x{}\n".format(opts['image_size'], opts['image_size'])
        elif 'cifar' in opts['dataset']:
            if opts['image_size'] is not None and opts['image_size'] != 32:
                raise ValueError('--image-size not supported for CIFAR sized datasets')
            opts['image_size'] = 32
        set_profiling_opts(opts)
        logging.print_to_file_and_screen("Command line: " + opts["command"], opts)
        logging.print_to_file_and_screen(opts["summary_str"].format(**opts), opts)
        opts["summary_str"] = ""
        logging.print_to_file_and_screen(opts, opts)
        train_process(model, lr_schedule.LearningRate, opts)


import sys
from collections import deque, Counter
sys.setrecursionlimit(5 * 10 ** 5)
# from pypyjit import set_param
# set_param('max_unroll_recursion=-1')
input = lambda: sys.stdin.readline().rstrip()
ii = lambda: int(input())
mi = lambda: map(int, input().split())
li = lambda: list(mi())
inf = 2 ** 63 - 1

def solve(X: str):
    buf = []
    for i in X:
        if buf and buf[-1] == "S" and i=="T":
            buf.pop()
            continue
        buf.append(i)
    print(len(buf))

def main():
    X = input()  # type: str
    solve(X)
    return

main()


import tkinter as tk

def imprimir_titulo(frame_implementacion):
    # Limpia el frame
    for item in frame_implementacion.winfo_children():
        item.destroy()

    # Imprime el titulo
    titulo = tk.Label(frame_implementacion, text="Ver pacientes del hospital", bg="white", font=("Helvetica", 16, "bold"))
    titulo.pack(pady=20)

def ver_pacientes(hospital,frame_implementacion):
    imprimir_titulo(frame_implementacion)

    titulo_ver_pacientes = tk.Label(frame_implementacion, text="Estos son todos los pacientes presentes en el hospital (Recuerda, si es necesario, desplazarse hacia abajo)",
    bg="white",font=("Helvetica", 10, "bold"))
    titulo_ver_pacientes.pack(pady=10)

    pacientes_text = tk.Text(frame_implementacion, bg="white", font=("Helvetica", 14))
    pacientes_text.pack(fill=tk.BOTH,expand=True)

    # Mostrar todas las vacunas presentes en el hospital
    for paciente in hospital.lista_pacientes:
        nombre = paciente.nombre
        cedula = paciente.cedula
        tipo_eps=paciente.tipo_eps

        texto_paciente = f"Nombre: {nombre}\nCedula: {cedula}\nTipo eps: {tipo_eps}\n\n"

        # Insertar el texto de la vacuna en el widget Text
        pacientes_text.insert(tk.END, texto_paciente)

    pacientes_text.config(padx=30)
    pacientes_text.config(highlightthickness=5, highlightbackground="#4D5BE4")
    pacientes_text.config(state="disabled")

    from src.ui_main.ventana_principal import implementacion_default

    boton_regresar = tk.Button(frame_implementacion, text="Regresar",
                               command=lambda: implementacion_default(frame_implementacion),
                               font=("Helvetica", 10, "bold"))
    boton_regresar.pack(pady=20)


from __future__ import print_function
import argparse
import os, sys
import random
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.backends.cudnn as cudnn
import torch.optim as optim
import torch.utils.data
from torch.autograd import Variable
import torch.nn.functional as F
import skimage
import skimage.io
import skimage.transform
import numpy as np
import time
import math
from utils.preprocess import scale_disp, default_transform

from networks.FADNet import FADNet
from networks.stackhourglass import PSMNet

# 2012 data /media/jiaren/ImageNet/data_scene_flow_2012/testing/

parser = argparse.ArgumentParser(description='FADNet')
parser.add_argument('--KITTI', default='2015',
                    help='KITTI version')
parser.add_argument('--datapath', default='/media/jiaren/ImageNet/data_scene_flow_2015/testing/',
                    help='select model')
parser.add_argument('--loadmodel', default=None,
                    help='loading model')
parser.add_argument('--savepath', default='results/',
                    help='path to save the results.')
parser.add_argument('--model', default='fadnet',
                    help='select model')
parser.add_argument('--maxdisp', type=int, default=192,
                    help='maxium disparity')
parser.add_argument('--no-cuda', action='store_true', default=False,
                    help='enables CUDA training')
parser.add_argument('--devices', type=str, help='indicates CUDA devices, e.g. 0,1,2', default='0')
parser.add_argument('--seed', type=int, default=1, metavar='S',
                    help='random seed (default: 1)')
args = parser.parse_args()
args.cuda = not args.no_cuda and torch.cuda.is_available()

if not os.path.exists(args.savepath):
    os.makedirs(args.savepath)

torch.manual_seed(args.seed)
if args.cuda:
    torch.cuda.manual_seed(args.seed)

if args.KITTI == '2015':
   from dataloader import KITTI_submission_loader as DA
else:
   from dataloader import KITTI_submission_loader2012 as DA

test_left_img, test_right_img = DA.dataloader(args.datapath)

devices = [int(item) for item in args.devices.split(',')]
ngpus = len(devices)

if args.model == 'psmnet':
    model = PSMNet(args.maxdisp)
elif args.model == 'fadnet':
    model = FADNet(False, True)
else:
    print('no model')
    sys.exit(-1)

model = nn.DataParallel(model, device_ids=devices)
model.cuda()

if args.loadmodel is not None:
    state_dict = torch.load(args.loadmodel)
    model.load_state_dict(state_dict['state_dict'])

print('Number of model parameters: {}'.format(sum([p.data.nelement() for p in model.parameters()])))

def test(imgL,imgR):
        model.eval()

        if args.cuda:
           imgL = torch.FloatTensor(imgL).cuda()
           imgR = torch.FloatTensor(imgR).cuda()

        imgL, imgR= Variable(imgL), Variable(imgR)

        #print(imgL.size(), imgR.size())
        with torch.no_grad():
            if args.model == "fadnet":
                output_net1, output_net2 = model(torch.cat((imgL, imgR), 1))
                output = torch.squeeze(output_net2)
            elif args.model == "psmnet":
                output = model(torch.cat((imgL, imgR), 1))
                output = torch.squeeze(output)

        pred_disp = output.data.cpu().numpy()

        print(pred_disp.shape)
        #print('larger than 192: %s' % pred_disp[pred_disp>0.75].shape)
        print('min: %f, max: %f, mean: %f' % (np.min(pred_disp), np.max(pred_disp), np.mean(pred_disp)))

        return pred_disp

def main():

   for inx in range(len(test_left_img)):
       print('image: %s'%test_left_img[inx])

       imgL_o = (skimage.io.imread(test_left_img[inx]).astype('float32'))
       imgR_o = (skimage.io.imread(test_right_img[inx]).astype('float32'))

       rgb_transform = default_transform()
       imgL = rgb_transform(imgL_o).numpy()
       imgR = rgb_transform(imgR_o).numpy()

       # resize
       imgsize = imgL_o.shape[:2]

       # scale to resize
       ##target_size = (512, 1792)
       #target_size = (384, 1344)
       #scale_h = imgsize[0]*1.0/target_size[0]
       #scale_w = imgsize[1]*1.0/target_size[1]

       ##imgL_o = skimage.transform.resize(imgL_o, target_size, preserve_range=True)
       ##imgR_o = skimage.transform.resize(imgR_o, target_size, preserve_range=True)

       #imgL = processed(imgL_o).numpy()
       #imgR = processed(imgR_o).numpy()

       imgL = np.reshape(imgL,[1,3,imgL.shape[1],imgL.shape[2]])
       imgR = np.reshape(imgR,[1,3,imgR.shape[1],imgR.shape[2]])

       # pad to resize (384, 1280)
       top_pad = 384-imgL.shape[2]
       left_pad = 1280-imgL.shape[3]
       imgL = np.lib.pad(imgL,((0,0),(0,0),(top_pad,0),(0,left_pad)),mode='constant',constant_values=0)
       imgR = np.lib.pad(imgR,((0,0),(0,0),(top_pad,0),(0,left_pad)),mode='constant',constant_values=0)

       start_time = time.time()
       pred_disp = test(imgL,imgR)
       print('time = %.2f' %(time.time() - start_time))

       top_pad   = 384-imgL_o.shape[0]
       left_pad  = 1280-imgL_o.shape[1]
       img = pred_disp[top_pad:,:-left_pad]

       # scale back
       #img = pred_disp
       #img = scale_disp(img, (imgsize[0], imgsize[1]))
       #round_img = skimage.transform.resize(round_img, imgsize, preserve_range=True)
       #print('out shape: ', img.shape)

       round_img = np.round(img*256)

       skimage.io.imsave(os.path.join(args.savepath, test_left_img[inx].split('/')[-1]),round_img.astype('uint16'))

if __name__ == '__main__':
   main()


from .Source import Source
from .EmotivPacket import EmotivPacket
from subprocess import check_output
from Crypto.Cipher import AES
from Crypto import Random
import threading
import select
import os
import code

class Emotiv(Source):
    def __init__(self, headsetId=0, research_headset=True):
        self.battery = 0
        self.headsetId = headsetId
        self.research_headset = research_headset
        self.sensors = {
            'F3': {'value': 0, 'quality': 0},
            'FC6': {'value': 0, 'quality': 0},
            'P7': {'value': 0, 'quality': 0},
            'T8': {'value': 0, 'quality': 0},
            'F7': {'value': 0, 'quality': 0},
            'F8': {'value': 0, 'quality': 0},
            'T7': {'value': 0, 'quality': 0},
            'P8': {'value': 0, 'quality': 0},
            'AF4': {'value': 0, 'quality': 0},
            'F4': {'value': 0, 'quality': 0},
            'AF3': {'value': 0, 'quality': 0},
            'O2': {'value': 0, 'quality': 0},
            'O1': {'value': 0, 'quality': 0},
            'FC5': {'value': 0, 'quality': 0},
            'X': {'value': 0, 'quality': 0},
            'Y': {'value': 0, 'quality': 0},
            'Unknown': {'value': 0, 'quality': 0}
        }
        self.range = float(1 << 13)
        self.timeout = 1000

        super(Emotiv, self).__init__()

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.hidraw.close()

    def setup(self):
        self.setupPosix()

    @staticmethod
    def getAvailableSignals():
        return ['AF3', 'AF4',
                'F3', 'F4', 'F7', 'F8',
                'FC5', 'FC6',
                'T7', 'T8',
                'O1', 'O2',
                'P7', 'P8']

    def setupCrypto(self, sn):
        type = 0 # feature[5]
        type &= 0xF
        type = 0
        # I believe type == True is for the Dev headset, I'm not using that. That's the point of this library in the first place I thought.
        k = ['\0'] * 16
        k[0] = sn[-1]
        k[1] = '\0'
        k[2] = sn[-2]
        if type:
            k[3] = 'H'
            k[4] = sn[-1]
            k[5] = '\0'
            k[6] = sn[-2]
            k[7] = 'T'
            k[8] = sn[-3]
            k[9] = '\x10'
            k[10] = sn[-4]
            k[11] = 'B'
        else:
            k[3] = 'T'
            k[4] = sn[-3]
            k[5] = '\x10'
            k[6] = sn[-4]
            k[7] = 'B'
            k[8] = sn[-1]
            k[9] = '\0'
            k[10] = sn[-2]
            k[11] = 'H'
        k[12] = sn[-3]
        k[13] = '\0'
        k[14] = sn[-4]
        k[15] = 'P'
        key = ''.join(k)
        iv = Random.new().read(AES.block_size)
        self.cipher = AES.new(key, AES.MODE_ECB, iv)

    def decryptPacket(self, task):
        data = self.cipher.decrypt(task[:16]) + self.cipher.decrypt(task[16:])
        packet = EmotivPacket(data, self.sensors)
        return packet

    def setupPosix(self):
        _os_decryption = False
        if os.path.exists('/dev/eeg/raw'):
            # The decrpytion is handled by the Linux epoc daemon. We don't need to handle it there.
            _os_decryption = True
            self.hidraw = open("/dev/eeg/raw")
        else:
            setup = self.getLinuxSetup()
            self.serialNum = setup[0]
            if os.path.exists("/dev/" + setup[1]):
                self.hidraw = open("/dev/" + setup[1], 'rb')
            else:
                self.hidraw = open("/dev/hidraw4", 'rb')
            self.setupCrypto(self.serialNum)
            thread = threading.Thread(target=self.read, daemon=True)
            thread.start()
        return True

    def normalize(self, value):
        return value / self.range

    def read(self):
        while True:
            (read, write, x) = select.select([self.hidraw],[],[],self.timeout)
            for file in read:
                data = self.hidraw.read(32)
                if data != "":
                    packet = self.decryptPacket(data)
                    output = {}
                    for (key, data) in packet.sensors.items():
                        output.update({key : self.normalize(data['value'])})
                    self.sendPackage(output)

    def getLinuxSetup(self):
        rawinputs = []
        for filename in os.listdir("/sys/class/hidraw"):
            realInputPath = check_output(["realpath", "/sys/class/hidraw/" + filename])
            realInputPath = realInputPath.decode()
            sPaths = realInputPath.split('/')
            s = len(sPaths)
            s = s - 4
            i = 0
            path = ""
            while s > i:
                path = path + sPaths[i] + "/"
                i += 1
            rawinputs.append([path, filename])
        hiddevices = []
        # TODO: Add support for multiple USB sticks? make a bit more elegant
        for input in rawinputs:
            try:
                with open(input[0] + "/manufacturer", 'r') as f:
                    manufacturer = f.readline()
                    f.close()
                if ("Emotiv Systems Inc." in manufacturer) or ("Emotiv Systems Pty Ltd" in manufacturer) :
                    with open(input[0] + "/serial", 'r') as f:
                        serial = f.readline().strip()
                        f.close()
                    #print("Serial: " + serial + " Device: " + input[1])
                    # Great we found it. But we need to use the second one...
                    hidraw = input[1]
                    id_hidraw = int(hidraw[-1])
                    # The dev headset might use the first device, or maybe if more than one are connected they might.
                    id_hidraw += 1
                    hidraw = "hidraw" + id_hidraw.__str__()
                    #print("Serial: " + serial + " Device: " + hidraw + " (Active)")
                    return [serial, hidraw, ]
            except IOError as e:
                print("Couldn't open file: %s" % e)


#!/usr/bin/env python
# encoding: utf-8

# @author: huhao
# @Software : PyCharm
# @file: CountMillionCharacters_Variations.py
# @time: 2019/6/27 18:48
# @Ducument：https://www.python.org/doc/
# @desc: 统计一个文件中各个英文字符的数量
# 识别txt文件，不能识别docx文件

try:
    input = input
except NameError:
    pass

def count_chas(filename):
    count = {}

    with open(filename,encoding='UTF-8') as info:    # inputFile Replaced with filename
        readfile = info.read()
        for character in readfile.upper():  # 为什么要大写？？  把大写去掉之后也可以，能区分大小写字符
            count[character] = count.get(character, 0) + 1

        return count

def main():
    is_exist = True
    # Try to open file if exist else raise exception and try again

    while(is_exist):
        try:
            inputFile = input("File Name / (0)exit : ").strip()     # Return a copy of the string S with leading and trailing whitespace removed.
            if inputFile == 0:
                break
            print(count_chas(inputFile))
        except FileNotFoundError:
            print('File not found...Try again!')

if __name__ == '__main__':
    main()


import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
def blink(pin):
        GPIO.output(pin,GPIO.HIGH)
        print("led on")
        time.sleep(0.15)
        GPIO.output(pin,GPIO.LOW)
        print("led off")
        time.sleep(0.15)
        return
GPIO.setmode(GPIO.BOARD)
GPIO.setup(15, GPIO.OUT)
for i in range(0,10):
        blink(15)
GPIO.cleanup()


#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
from datetime import datetime
from uuid import uuid4

import bcrypt
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
import base64

import allure

from data_etl import etl_process
from data_etl.etl_ccl_tag import get_random_process_tag_id, get_random_process_tag_info
from data_etl.etl_organization import get_random_organization_id, get_random_organization_info
from data_etl.etl_organization_robot import get_robot_organization_id
from data_etl.etl_process import *
from data_etl.etl_process_info import get_process_info_id
from data_etl.etl_requirement import get_requirement_id
from data_etl.etl_requirement_form import get_random_use_system
from data_etl.etl_robot import get_robot_id_list, get_robot_id, get_random_free_robot_id, get_robot_id_list_by_robot_id, \
    get_random_not_free_robot_id
from data_etl.etl_user import get_user_id
from project_path import TEST_DATA_PATH
from utils.common_tools import CommonTool
from conftest import *

# from utils.data_compare import assert_diff
# from utils.validate_json_schema import validate_json_schema

class TestRequirementLine:
    path = TEST_DATA_PATH + r"/create_requirement.yml"
    info = CommonTool().get_yaml_data_info(path)
    method = info['method']
    url = info['url']
    # headers = info['headers']
    param = CommonTool().get_yaml_data_for_req(path)['data']

    def setup_class(self):
        # logout_url = "http://172.19.192.44:30000/gateway/cs/api/private/v1/logout"
        self.env = os.environ['env']

        # admin, yewu, yewu_leader, pm, expert, tech_leader, kaifa_leader, kaifa
        # 登录业务账号，获取业务账号的token
        self.yw_info = CommonTool().get_token("yewu")
        self.yw_token = self.yw_info['token']
        self.process_owner = self.yw_info['username']
        self.yw_headers = {"Authorization": "Bearer " + self.yw_token}

        # 登录业务leader账号，获取业务leader账号的token
        self.yewu_leader_info = CommonTool().get_token("yewu_leader")
        self.yewu_leader_token = self.yewu_leader_info['token']
        self.yewu_leader_user = self.yewu_leader_info['username']
        self.yewu_leader_headers = {"Authorization": "Bearer " + self.yewu_leader_token}

        # 登录管理员账号，获取管理员账号的token
        self.admin_info = CommonTool().get_token("admin")
        self.admin_token = self.admin_info['token']
        self.admin_user = self.admin_info['username']
        self.admin_headers = {"Authorization": "Bearer " + self.admin_token}

        # 登录pm账号，获取pm账号的token
        self.pm_info = CommonTool().get_token("pm")
        self.pm_token = self.pm_info['token']
        self.pm_user = self.pm_info['username']
        self.pm_headers = {"Authorization": "Bearer " + self.pm_token}

        # 登录tech_leach账号，获取tech_leach账号的token
        self.tech_leader_info = CommonTool().get_token("tech_leader")
        self.tech_leader_token = self.tech_leader_info['token']
        self.tech_leader_user = self.tech_leader_info['username']
        self.tech_leader_headers = {"Authorization": "Bearer " + self.tech_leader_token}

        # 登录tech_ceo账号，获取tech_ceo账号的token
        self.tech_ceo_info = CommonTool().get_token("tech_ceo")
        self.tech_ceo_token = self.tech_leader_info['token']
        self.tech_ceo_user = self.tech_leader_info['username']
        self.tech_ceo_headers = {"Authorization": "Bearer " + self.tech_ceo_token}

        # 登录开发账号，获取开发账号的token
        self.kf_info = CommonTool().get_token("kaifa")
        self.kf_token = self.kf_info['token']
        self.kf_user = self.kf_info['username']
        self.kf_headers = {"Authorization": "Bearer " + self.kf_token}

        # 登录开发leader账号，获取开发账号的token
        self.kf_leader_info = CommonTool().get_token("kaifa_leader")
        self.kf_leader_token = self.kf_leader_info['token']
        self.kf_leader_user = self.kf_leader_info['username']
        self.kf_leader_headers = {"Authorization": "Bearer " + self.kf_leader_token}

        # 登录expert账号，获取expert账号的token
        self.expert_info = CommonTool().get_token("tech_leader")
        self.expert_token = self.expert_info['token']
        self.expert_user = self.expert_info['username']
        self.expert_headers = {"Authorization": "Bearer " + self.expert_token}

    @allure.feature('创建需求-流程-任务数据')
    @pytest.mark.requirement
    @pytest.mark.all
    @pytest.mark.parametrize('create_data, submit_data, yw_verify, pm_verify, expert_estimate, tech_estimate, dev_admin_estimate, confirm_develop_data, process_for_requriement_release, release_acceptance, process_estimate,process_enable, release_to_app_store, select_robots_for_run_process, run_process, detail, resp', param)
    @allure.title("{detail}")
    def test_requirement(self, set_base_url, create_data, submit_data, yw_verify, pm_verify, expert_estimate, tech_estimate, dev_admin_estimate,  confirm_develop_data,
                         process_for_requriement_release, release_acceptance, process_estimate, process_enable, release_to_app_store,
                         select_robots_for_run_process, run_process,detail, resp, get_env):
        # logout_url = "http://172.19.192.44:30000/gateway/cs/api/private/v1/logout"
        print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
        #获取随机的tag_info
        tag_info = get_random_process_tag_info(get_env)
        tag_id = tag_info['id']
        tag_name = tag_info['tag_name']

        #获取随机的organization_info
        # org_id = '1158609790175745'
        org_info = get_random_organization_info(self.env)
        org_id = org_info['id']
        org_name = org_info['name']

        #获取随机的use_system(涉及系统）
        # use_system = get_random_use_system(self.env)  #！！！！！！！！1.4环境原来写的库里没存use_system,待确认
        print("\n")
        print("================================"+ detail +"========================================")
        #创建一个待提交状态的需求
        create_data['name'] = CommonTool().get_requirement_name()
        create_data['process_owner'] = self.process_owner  #获取需求创建者
        create_data['businessLabel'] = tag_name  #获取标签名
        create_data['labels'] = []
        create_data['labels'].append({'labelId': create_data['businessLabel']})
        # create_data['useSystem'] = use_system #获取涉及系统   #！！！！！！！！1.4环境原来写的库里没存use_system,待确认
        # create_data['organizationId'] = org_id  #获取组织id
        # create_data['organizationName'] = org_name  #获取组织名称
        # create_data['organization'] = org_id + "-" + org_name  #获取组织名称
        create_data['organization'] = "1191662310166528-阳朔电网"  #获取组织名称    #！！！！！！！！之前1.3环境建需求时没有限制用户的组织权限，1.4好像加了，使用的组织必须是
        # create_data['organization'] = "1191662102368256-桂林电网"  #获取组织名称    #！！！！！！！！之前1.3环境建需求时没有限制用户的组织权限，1.4好像加了，使用的组织必须是

        print("业务人员创建一个待提交的需求：")
        request_url = set_base_url + self.url
        res = requests.request(self.method, request_url, headers=self.yw_headers, json=create_data, stream=True)
        assert res.json().get("success") == True

        # 获取process_instance_id
        process_instance_id = res.json().get("result").get("id")
        time.sleep(3)
        # 通过process_instance_id从数据库中获取requirement_id
        requirement_id = get_requirement_id(self.env, process_instance_id)
        print("requirement_id 是: " + requirement_id)
        print("res 是: " + res.text)

        if len(submit_data) == 0:
            return
        print("业务人员提交需求：")
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.yw_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)

        submit_data['current_operator'] = self.process_owner

        # params_for_submit = {
        #     "current_operator": process_owner,
        #     "status": 2
        # }

        # 提交需求
        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.yw_headers, json=submit_data, stream=True)
        assert res.status_code == 204
        if len(yw_verify) == 0:
            return

        # 业务leaader审批需求
        print("业务leader审批需求：")
        time.sleep(3)
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.yw_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)

        yw_verify['current_operator'] = self.yewu_leader_user
        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.yw_headers, json=yw_verify, stream=True)
        assert res.status_code == 204
        if len(pm_verify) == 0:
            return

        # pm审批需求
        print("pm审批需求：")
        time.sleep(3)
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.pm_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)

        pm_verify['current_operator'] = self.pm_user
        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.pm_headers, json=pm_verify, stream=True)
        assert res.status_code == 204
        if len(expert_estimate) == 0:
            return

        print("专家评估需求：")
        #专家评估需求
        time.sleep(3)
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.expert_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)

        expert_estimate['current_operator'] = self.expert_user
        time.sleep(3)

        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.expert_headers, json=expert_estimate, stream=True)
        assert res.status_code == 204
        if len(tech_estimate) == 0:
            return

        print("技术评估需求：")
        #专家评估需求
        time.sleep(3)
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.tech_leader_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)

        tech_estimate['current_operator'] = self.expert_user
        time.sleep(3)

        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.tech_leader_headers, json=tech_estimate, stream=True)
        assert res.status_code == 204
        # if len(tech_ceo_estimate) == 0:
        #     return

        print("技术总监评估需求：")
        #专家评估需求
        time.sleep(3)
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.tech_leader_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)
        tech_ceo_estimate = {}
        tech_ceo_estimate['current_operator'] = self.expert_user
        tech_ceo_estimate['status'] = 25
        time.sleep(3)

        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.tech_ceo_headers, json=tech_ceo_estimate, stream=True)
        assert res.status_code == 204
        if len(dev_admin_estimate) == 0:
            return

        print("开发领导评估需求：")
        #开发领导评估需求
        time.sleep(3)
        # 获取task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.kf_leader_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("task_id 是: " + task_id)

        dev_admin_estimate['current_operator'] = self.kf_leader_user
        dev_admin_estimate['developer'] = self.kf_user

        time.sleep(3)

        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.kf_leader_headers, json=dev_admin_estimate, stream=True)
        assert res.status_code == 204
        if len(confirm_develop_data) == 0:
            return

        #
        # print("管理员审批需求：")
        # # 获取该需求在待审核状态的task_id
        # url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        # time.sleep(3)
        # res = requests.request("GET", url, headers=self.admin_headers, stream=True)
        # task_id = res.json().get("data").get("taskId")
        # print("task_id 是: " + task_id)
        #
        # # 管理员审核需求并分配开发人员
        # # params_for_verify = {
        # #     "current_operator" : "dwxbxntest3",
        # #     "design" : 1123512485363969,
        # #     "developer" : "dwxbtest006",
        # #     "pass": True,
        # #     "priority": 1,
        # #     "status": 4
        # # }
        # verify_data['current_operator'] = self.admin_user
        # verify_data['developer'] = self.kf_user
        # url = set_base_url + "/be/hyperpm/form/task/" + task_id
        # res = requests.request("POST", url, headers=self.admin_headers, json=verify_data, stream=True)
        # assert res.status_code == 204

        print("开发人员确认开发需求：")
        #开发人员操作
        time.sleep(3)

        # 获取该需求在待开发状态的task_id
        url = set_base_url + "/be/api/v1/requirement/" + requirement_id
        time.sleep(3)
        res = requests.request("GET", url, headers=self.kf_headers, stream=True)
        task_id = res.json().get("data").get("taskId")
        print("获取该需求在待开发状态的task_id：")
        print("task_id 是: " + task_id)

        # 开发人员确认开发需求
        # params_for_confirm_develop = {
        #     "current_operator": "dwxbtest006",
        #     "developer": "dwxbtest006",
        #     "status": 5
        # }
        confirm_develop_data['current_operator'] = self.kf_user
        confirm_develop_data['developer'] = self.kf_user

        url = set_base_url + "/be/hyperpm/form/task/" + task_id
        res = requests.request("POST", url, headers=self.kf_headers, json=confirm_develop_data, stream=True)
        assert res.status_code == 204
        if len(process_for_requriement_release) == 0:
            return

        time.sleep(3)

        mrpax_file_name = CommonTool().get_mrpax_file()

        # 从设计器发布流程到流程列表
        print("从设计器发布流程到流程列表：")
        # process_name = process_for_requriement_release['projectName']
        process_name = mrpax_file_name
        process_for_requriement_release['projectName'] = process_name
        file_name = process_name+".mrpax"
        file_path = TEST_DATA_PATH + "mrpax/"+ file_name
        fo = open(file_path, 'rb')
        files = [
            ('mrpFile', (file_name, fo))
        ]
        print("mrpFile is " + file_path)

        # data = {
        #     "id" : requiremnt_id,
        # #     "projectDesc" : "projectDesc",
        # #     "projectName" :  "C",
        # #     "projectVersion" : "1.0.0",
        # #     "releaseIntroduce" : "releaseIntroduce",
        # #     # "useFile" : "",
        # #     "useIntroduce" : "useIntroduce"
        # # }

        process_for_requriement_release['id'] = requirement_id

        url = set_base_url + "/gateway/ac/api/private/v1/requirement/release"
        res = requests.request("PUT", url, headers=self.kf_headers, data=process_for_requriement_release, files=files)
        fo.close()
        print("res 是: " + res.text)
        if len(release_acceptance) == 0:
            return

        #避免文件使用重复，mrpax文件使用完毕后，删除使用过的mrpax
        CommonTool().remove_mrpax_file(file_path)

        time.sleep(5)
        # 业务人员操作验收通过
        print("业务人员操作验收通过：")
        url = set_base_url + "/be/api/v1/requirement/releaseAcceptance/" + str(requirement_id)
        # url = set_base_url + "/be/api/v1/requirement/releaseAcceptance/1506919216430051329"
        res = requests.request("PUT", url, headers=self.yw_headers, json=release_acceptance, stream=True)
        print("res 是: " + res.text)
        if len(process_estimate) == 0:
            return

        time.sleep(4)
        # 管理员操作流程-审核通过
        print("管理员操作流程-审核通过:")
        robot_process_id = str(etl_process.get_robot_process_id(self.env, process_name))
        url = set_base_url + "/gateway/orc-serv/api/private/v1/process/approve/" + robot_process_id
        res = requests.request("POST", url, headers=self.admin_headers, params=process_estimate)
        print("res 是: " + res.text)
        if len(process_enable) == 0:
            return

        time.sleep(3)

        if process_enable['currentVersionStatus'] == 1:
            #管理员启用流程
            print("管理员启用流程:")
            name_of_process_in_db = str(etl_process.get_process_name(self.env, process_name))
            process_enable['name'] = name_of_process_in_db
            url = set_base_url + "/gateway/orc-serv/api/private/v1/process/version/approval"
            res = requests.request("POST", url, headers=self.admin_headers, json=process_enable)
            print("res 是: " + res.text)
        elif process_enable['currentVersionStatus'] == 0:
            #管理员启用流程
            print("管理员启用流程:")
            process_enable['currentVersionStatus'] = 1
            name_of_process_in_db = str(etl_process.get_process_name(self.env, process_name))
            process_enable['name'] = name_of_process_in_db
            url = set_base_url + "/gateway/orc-serv/api/private/v1/process/version/approval"
            res = requests.request("POST", url, headers=self.admin_headers, json=process_enable)
            print("res 是: " + res.text)
            time.sleep(3)
            #管理员禁用流程：
            print("管理员禁用流程:")
            process_enable['currentVersionStatus'] = 0
            res = requests.request("POST", url, headers=self.admin_headers, json=process_enable)
            print(res.text)
        if len(release_to_app_store) == 0:
            return

        org_id_list = []
        org_id_list.append(org_id)

        tag_id_list = []
        # tag_id = get_random_process_tag_id(env)
        tag_id_list.append((tag_id))

        time.sleep(3)
        #管理员发布流程到应用市场：
        release_to_app_store['authorId'] = get_user_id(self.env,self.admin_user)
        release_to_app_store['authorName'] = self.admin_user
        release_to_app_store['fileUrl'] = get_process_file_path(self.env,name_of_process_in_db)  #流程在服务器的存储地址
        release_to_app_store['id'] = robot_process_id
        release_to_app_store['pluginId'] = str(get_process_info_id(self.env, process_name))  # plugin_id即流程id,即process_info表中的id
        release_to_app_store['pluginName'] = process_name
        release_to_app_store['resourceSn'] = get_process_resource_sn(self.env, process_name)
        release_to_app_store['organizationIds'] = org_id_list  # 随机生成组织id
        release_to_app_store['tagIds'] = tag_id_list             #!!!!!!待改

        url =  set_base_url + "/gateway/ac/api/private/v1/plugin/version/cs"
        res = requests.request("POST", url, headers=self.admin_headers, json=release_to_app_store,  stream=True)
        print("发布到流程市场:")
        print("res 是: " + res.text)
        if len(run_process) == 0:
            return

        time.sleep(3)

        robot_org_id = ""
        #为执行流程选择机器人：
        if select_robots_for_run_process['robotName'] == "free":
            robot_org_id = get_random_free_robot_id(self.env)
            robot_org_id = get_robot_organization_id(self.env, robot_org_id)  # 获取robotNme对应org_id
            select_robots_for_run_process['robotIds'] = get_robot_id_list_by_robot_id(robot_org_id)  # 通过随机生成的机器人id获取空闲机器人id列表
        elif select_robots_for_run_process['robotName'] == "not free":
            robot_org_id = get_random_not_free_robot_id(self.env)
            robot_org_id = get_robot_organization_id(self.env, robot_org_id)  # 获取robotNme对应org_id
            select_robots_for_run_process['robotIds'] = get_robot_id_list_by_robot_id(robot_org_id)  # 通过随机生成的机器人id获取非机器人id列表
        else:
            robot_org_id = get_robot_organization_id(self.env, get_robot_id(self.env, select_robots_for_run_process['robotName']))  # 获取robotNme对应org_id
            select_robots_for_run_process['robotIds'] = get_robot_id_list(self.env, select_robots_for_run_process['robotName'])  # 通过用例参数中指定的机器人名获取机器人id列表

        url = set_base_url + "/gateway/orc-serv/api/private/v1/jobs/select-robots"
        del select_robots_for_run_process['robotName']
        select_robots_for_run_process['labelName'] = CommonTool().get_robot_temp_label_name() #获取随机的uuid4labelname
        res = requests.request("POST", url, headers=self.admin_headers, json=select_robots_for_run_process,  stream=True)
        print("为执行流程选择机器人:")
        print(res.text)

        time.sleep(3)

        #管理员运行流程：
        print("管理员运行流程:")
        url = set_base_url + "/gateway/orc-serv/api/private/v1/processes/" + robot_process_id + "/get-instance"
        # url = set_base_url + "/gateway/orc-serv/api/private/v1/processes/1157549708525824/get-instance"
        run_process['conditions'] = select_robots_for_run_process['labelName']
        run_process['name'] = process_name + "_1.0.0"
        run_process['resourceSn'] = release_to_app_store['resourceSn']
        run_process['organizationId'] = robot_org_id

        res = requests.request("POST", url, headers=self.admin_headers, json=run_process,  stream=True)
        print("res 是: " + res.text)
        if len(run_process) == 0:
            return
        time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))

if __name__ == '__main__':
    pytest.main(["-s","test_requirements_line.py"])
    # pytest.main(["-s","test_requirement.py", "--env ali_master","-sq", "--alluredir", "./outputs/reports/raw"])
    # # os.system("allure generate ../reports/ -o ./outputs/reports/html --clean ")
    # pass
    # pytest.main(["-s","--env ali_master", "-v", "-q", 'test_requirement.py'])


"""Auteur: Simon LEYRAL
   Date : Octobre 2017

Enoncé

Cet exercice propose une variante de l’exercice précédent sur le carré de X.

Écrire un programme qui lit sur input une valeur naturelle n et qui affiche à l’écran un triangle supérieur
droit formé de X (voir exemples plus bas).

"""
n = int(input())

for i in range(n):
    if i == 0:
        print("X" * (n-i))
    else:
        print(" "*(i-1), "X"*(n-i))


import base64
import tkinter as tk

def on_button_click():
    # Get the hex string from the text entry
    hex_string = entry.get()

    # Decode the hex string to a bytes object
    bytes_obj = bytes.fromhex(hex_string)

    # Encode the bytes object to a base64 string
    base64_string = base64.b64encode(bytes_obj).decode()

    # Update the label with the result
    result_label.config(text=base64_string)

# Create the main window
root = tk.Tk()
root.title("Hex to Base64 Converter")

# Create a label and a text entry for the hex string
label = tk.Label(root, text="Enter a hex string:")
entry = tk.Entry(root)

# Create a button to trigger the conversion
button = tk.Button(root, text="Convert", command=on_button_click)

# Create a label to display the result
result_label = tk.Label(root, text="")

# Add the widgets to the window
label.pack()
entry.pack()
button.pack()
result_label.pack()

# Run the main loop
root.mainloop()


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

import cv2
import numpy as np
import os.path
import copy
from  tqdm import tqdm

# 椒盐噪声
def SaltAndPepper(src, percetage):
    SP_NoiseImg = src.copy()
    SP_NoiseNum = int(percetage * src.shape[0] * src.shape[1])
    for i in range(SP_NoiseNum):
        randR = np.random.randint(0, src.shape[0] - 1)
        randG = np.random.randint(0, src.shape[1] - 1)
        randB = np.random.randint(0, 3)
        if np.random.randint(0, 1) == 0:
            SP_NoiseImg[randR, randG, randB] = 0
        else:
            SP_NoiseImg[randR, randG, randB] = 255
    return SP_NoiseImg

# 高斯噪声
def addGaussianNoise(image, percetage):
    G_Noiseimg = image.copy()
    w = image.shape[1]
    h = image.shape[0]
    G_NoiseNum = int(percetage * image.shape[0] * image.shape[1])
    for i in range(G_NoiseNum):
        temp_x = np.random.randint(0, h)
        temp_y = np.random.randint(0, w)
        G_Noiseimg[temp_x][temp_y][np.random.randint(3)] = np.random.randn(1)[0]
    return G_Noiseimg

def gaussian_noise(img, mean, sigma):
    '''
    此函数用将产生的高斯噪声加到图片上
    传入:
        img   :  原图
        mean  :  均值
        sigma :  标准差
    返回:
        gaussian_out : 噪声处理后的图片
        noise        : 对应的噪声
    '''
    # 将图片灰度标准化
    img = img / 255
    # 产生高斯 noise
    noise = np.random.normal(mean, sigma, img.shape)
    # 将噪声和图片叠加
    gaussian_out = img + noise
    # 将超过 1 的置 1，低于 0 的置 0
    gaussian_out = np.clip(gaussian_out, 0, 1)
    # 将图片灰度范围的恢复为 0-255
    gaussian_out = np.uint8(gaussian_out*255)
    # 将噪声范围搞为 0-255
    # noise = np.uint8(noise*255)
    return gaussian_out, noise # 这里也会返回噪声，注意返回值

# 昏暗
def darker(image, percetage=0.9):
    image_copy = image.copy()
    w = image.shape[1]
    h = image.shape[0]
    # get darker
    for xi in range(0, w):
        for xj in range(0, h):
            image_copy[xj, xi, 0] = int(image[xj, xi, 0] * percetage)
            image_copy[xj, xi, 1] = int(image[xj, xi, 1] * percetage)
            image_copy[xj, xi, 2] = int(image[xj, xi, 2] * percetage)
    return image_copy

# 亮度
def brighter(image, percetage=1.5):
    image_copy = image.copy()
    w = image.shape[1]
    h = image.shape[0]
    # get brighter
    for xi in range(0, w):
        for xj in range(0, h):
            image_copy[xj, xi, 0] = np.clip(int(image[xj, xi, 0] * percetage), a_max=255, a_min=0)
            image_copy[xj, xi, 1] = np.clip(int(image[xj, xi, 1] * percetage), a_max=255, a_min=0)
            image_copy[xj, xi, 2] = np.clip(int(image[xj, xi, 2] * percetage), a_max=255, a_min=0)
    return image_copy

# 旋转
def rotate(image, angle, center=None, scale=1.0):
    (h, w) = image.shape[:2]
    # If no rotation center is specified, the center of the image is set as the rotation center
    if center is None:
        center = (w / 2, h / 2)
    m = cv2.getRotationMatrix2D(center, angle, scale)
    rotated = cv2.warpAffine(image, m, (w, h))
    return rotated

# 翻转
def flip(image):
    flipped_image = np.fliplr(image)
    return flipped_image
# 随机裁剪
def cutout(img, length=50,overimg=''):
    h=img.shape[0]
    w = img.shape[1]
    mask = np.ones((h, w))
    b, g, r = cv2.split(img)
    y = np.random.randint(h)
    x = np.random.randint(w)
    y1 = np.clip(y - length // 2, 0, h)
    y2 = np.clip(y + length // 2, 0, h)
    x1 = np.clip(x - length // 2, 0, w)
    x2 = np.clip(x + length // 2, 0, w)
    mask[y1: y2, x1: x2] = 0
    rm = r * mask
    gm = g * mask
    bm = b * mask
    merged = cv2.merge([bm, gm, rm])
    ###img for overlap
    if overimg != '':
        over = cv2.imread(overimg)
        overresize = cv2.resize(over, (w, h), interpolation=cv2.INTER_CUBIC)
        mask2 = np.zeros((h, w))
        bo, go, ro = cv2.split(overresize)
        mask2[y1: y2, x1: x2] = 1
        b = bo * mask2
        g = go * mask2
        r = ro * mask2
        merged2 = cv2.merge([b, g, r])
        return merged + merged2
    return merged
def saltpepper():
    for rate in np.linspace(0.01, 0.1, 10):
        for dir in tqdm(os.listdir(file_dir)):
            category = os.path.basename(dir)
            for img_name in os.listdir(file_dir + dir):
                file_out = os.path.join(f'{file_dir[0:-1]}-SaltAndPepper',"{:.3f}".format(rate), category) + '/'
                if not os.path.exists(file_out):
                    os.makedirs(file_out)
                img_path = os.path.join(file_dir, category, img_name)
                img = cv2.imread(img_path)
                # cv2.imwrite(file_out + img_name,img)
                # 镜像
                # flipped_img = flip(img)
                # cv2.imwrite(file_dir + img_name[0:-4] + '_fli.jpg', flipped_img)

                # 增加噪声
                img_salt = SaltAndPepper(img, rate)
                cv2.imwrite(file_out + img_name[0:-4] + '_p.jpg', img_salt)
def blur():
    for rate in np.linspace(1,10,10):
        for dir in tqdm(os.listdir(file_dir)):
            category = os.path.basename(dir)
            for img_name in os.listdir(file_dir + dir):
                file_out = os.path.join(f'{file_dir[0:-1]}-blur', f'{rate}', category) + '/'
                if not os.path.exists(file_out):
                    os.makedirs(file_out)
                img_path = os.path.join(file_dir, category, img_name)
                img = cv2.imread(img_path)
                # 增加噪声
                blur = cv2.blur(img, (int(rate), int(rate)))
                # #      cv2.GaussianBlur(图像，卷积核，标准差）
                cv2.imwrite(file_out + img_name[0:-4] + '_blur.jpg', blur)
def GaussianBlur():
    for rate in np.arange(1, 15, 2):
        for dir in tqdm(os.listdir(file_dir)):
            category = os.path.basename(dir)
            for img_name in os.listdir(file_dir + dir):
                file_out = os.path.join(f'{file_dir[0:-1]}-GaussianBlur', f'{rate}', category) + '/'
                if not os.path.exists(file_out):
                    os.makedirs(file_out)
                img_path = os.path.join(file_dir, category, img_name)
                img = cv2.imread(img_path)
                # 增加噪声
                blur = cv2.GaussianBlur(img, (int(rate), int(rate)),0)
                # #      cv2.GaussianBlur(图像，卷积核，标准差）
                cv2.imwrite(file_out + img_name[0:-4] + '_gb.jpg', blur)
def occlusion():
    for rate in np.arange(60, 100, 5):
        for dir in tqdm(os.listdir(file_dir)):
            category = os.path.basename(dir)
            for img_name in os.listdir(file_dir + dir):
                file_out = os.path.join(f'{file_dir[0:-1]}-occlusion61', f'{rate}', category) + '/'
                if not os.path.exists(file_out):
                    os.makedirs(file_out)
                img_path = os.path.join(file_dir, category, img_name)
                img = cv2.imread(img_path)
                cut = cutout(img, rate)
                # #      cv2.GaussianBlur(图像，卷积核，标准差）
                cv2.imwrite(file_out + img_name[0:-4] + '_gblur.jpg', cut)
# 图片文件夹路径
file_dir = './test-tomato-img/'
blur()
# for img_name in os.listdir(file_dir):
#     img_path = file_dir + img_name
#     img = cv2.imread(img_path)
#     # cv2.imshow("1",img)
#     # cv2.waitKey(5000)
#     # 旋转
#     rotated_90 = rotate(img, 90)
#     cv2.imwrite(file_dir + img_name[0:-4] + '_r90.jpg', rotated_90)
#     rotated_180 = rotate(img, 180)
#     cv2.imwrite(file_dir + img_name[0:-4] + '_r180.jpg', rotated_180)
            # img_gauss = addGaussianNoise(img, 0.3)
            # cv2.imwrite(file_out + img_name[0:-4] + '_noise.jpg', img_gauss)

            # 变亮、变暗
            # img_darker = darker(img)
            # cv2.imwrite(file_out + img_name[0:-4] + '_darker.jpg', img_darker)
            # img_brighter = brighter(img)
            # cv2.imwrite(file_out + img_name[0:-4] + '_brighter.jpg', img_brighter)
            #
            # blur = cv2.GaussianBlur(img, (7, 7), 1.5)
            # # #      cv2.GaussianBlur(图像，卷积核，标准差）
            # cv2.imwrite(file_out + img_name[0:-4] + '_blur.jpg', blur)

            # blur = cv2.blur(img, (7, 7))
            # # #      cv2.GaussianBlur(图像，卷积核，标准差）
            # cv2.imwrite(file_out + img_name[0:-4] + '_blur.jpg', blur)


#Importing required modules
import pandas as pd
import pandas_profiling as pp
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import preprocessing
from sklearn.linear_model import LinearRegression

#reading the train data and test data
train = pd.read_csv(r"heart_rate_prediction_train.csv")
test = pd.read_csv(r"heart_rate_prediction_test.csv")
train
test

x = train[['sampen']].values
y = train[['higuci']].values

m = test[['sampen']].values
n = test[['higuci']].values

x_train, x_test, y_train, y_test = x ,m, y, n

#build the regression model
linreg = LinearRegression()
linreg.fit(x_train, y_train)

#Prediction of Test set Result
test_pred = linreg.predict(x_test)
train_pred = linreg.predict(x_train)

#Creating Stress Graph
train['condition'].unique()
conditions = dict(train['condition'].value_counts())
labels = list(conditions.keys())
counts = list(conditions.values())
plt.bar(labels,counts, color ='green',width = 0.4)
plt.show()

#Projecting analysed data to output.html
le = preprocessing.LabelEncoder()
le.fit(train['condition'])
train['condition'] = le.transform(train['condition'])
test['condition'] = le.transform(test['condition'])
profile = pp.ProfileReport(train)
profile.to_file("output.html")

#Creating Heat Map
plt.figure(figsize=(12,10))
corr = train.corr()
sns.heatmap(corr, annot=False, cmap=plt.cm.Reds)
plt.show()

#Visualizing the training set results
plt.scatter(x_train, y_train, color = "green", cmap='viridis')
plt.colorbar()
plt.plot(x_train, train_pred, color = "red")
plt.title("Sampen vs Higuci (Training set)")
plt.xlabel("Sampen")
plt.ylabel("Higuci")
plt.show()

#Visualizing the test set results
plt.scatter(x_test, y_test, color = "blue", cmap='blues')
plt.colorbar()
plt.plot(x_train, train_pred, color = "red")
plt.title("Sampen vs Higuci (Test set)")
plt.xlabel("Sampen")
plt.ylabel("Higuci")
plt.show()

#Printing Training and Test Data sets
print("Training set top 5 rows:")
print(train.head(5))
print("Training set last 5 rows:")
print(train.tail(5))
print("Test set top 5 rows:")
print(test.head(5))
print("Test set last 5 rows:")
print(test.tail(5))


"""Various filters for Jinja."""

from datetime import datetime as _datetime
from calendar import month_name as _month_name

__all__ = [
    "rating",
    "article_date",
    "breaking_spaces",
    "datetime",
    "month_name",
    "suffix",
    "tagsort_count",
    "tagsort_name",
    "custom_strftime",
    "archive_date_format",
    "sidebar_date_format",
    "typogrify_amp",
    "index_template",
]

def rating(rate, outof):
    out = ''
    rate = int(rate)
    outof = int(outof)

    for i in range(1, outof + 1):
        if i <= rate:
            out += '<svg><use href="#star-full"></use></svg>'
        else:
            out += '<svg><use href="#star-empty"></use></svg>'

    out += ""
    out += f" {rate}/{outof}"

    return out

def month_name(month_number):
    return _month_name[month_number]

def suffix(d, wrap=True):
    tmp = "th" if 11 <= d <= 13 else {1: "st", 2: "nd", 3: "rd"}.get(d % 10, "th")
    if wrap:
        return '' + tmp + ""
    else:
        return tmp

def tagsort_count(tags, reverse=True):
    return sorted(tags, key=lambda x: len(x[1]), reverse=reverse)

def tagsort_name(tags, reverse=False):
    return sorted(tags, key=lambda x: x[0], reverse=reverse)

def custom_strftime(format, t):
    return t.strftime(format).replace("{S}", str(t.day) + suffix(t.day))

def archive_date_format(date):
    return custom_strftime("{S} %B, %Y", date)

def sidebar_date_format(date):
    return custom_strftime("%a {S} %B, %Y", date)

def typogrify_amp(value):
    from typogrify.filters import amp

    return amp(str(value))

def index_template(article, templates_for_tags):
    for tag in article.tags:
        if tag in templates_for_tags:
            return "index_item_" + templates_for_tags[tag] + ".html.j2"

    return "index_item_default.html.j2"

def tag_in_list(article_tags, tag_list):
    for tag in article_tags:
        if tag in tag_list:
            return True
        else:
            return False

def datetime(value, format_str="%Y/%m/%d %H:%M"):
    """
    Convert a datetime to a different format.

    The default format looks like --> 2016/11/25 12:34

    Args
    ----
        value (datetime.datetime): input date and time
        format_str (str): The datetime format string to apply to value

    Returns
    -------
        str: value, after the format_str has been applied

    """
    return value.strftime(format_str)

def article_date(value):
    """
    Convert a date to the format we want it displayed on the article template.

    Format looks like --> Friday, November 4, 2020

    Args
    ----
        value (datetime.datetime): input date

    Returns
    -------
        str: value, formatted nicely for displaying the date.

    """
    return "{dt:%A}, {dt:%B} {dt.day}, {dt.year}".format(dt=value)

def datetime_from_period(value):
    """
    Converts "period" into a datetime object.

    On yearly/monthly/daily archive pages, a "period" object is supplied so you
    know what timeperiod the particular archive page is for. This converts it
    to a datetime.datetime object, so it can be further processed.

    If a month is not provided (i.e. the period is for a yearly archive),
    January is assumed. If a day is not provided (i.e. the period is for a
    yearly or monthly archive), the 1st is assumed.

    You can also generate a tuple of (up to three) integers to get a datetime
    out, using the integer representation for the month (1=January, etc).

    If passes a single integer, it is assumed to represent a year.

    Args
    ----
        value (tuple or int): input period

    Returns
    -------
        datetime.datetime: value converted

    """
    if isinstance(value, int):
        value = (value,)

    if len(value) >= 2 and isinstance(value[1], int):
        placeholder_month = _datetime(2021, value[1], 1).strftime("%B")
    elif len(value) == 1:
        placeholder_month = _datetime(2021, 1, 1).strftime("%B")
    else:
        placeholder_month = value[1]

    new_value = " ".join(
        (
            str(value[0]),
            placeholder_month,
            str(value[2]) if len(value) >= 3 else "1",
        )
    )
    new_datetime = _datetime.strptime(new_value, "%Y %B %d")
    return new_datetime

def merge_date_url(value, url):
    """
    Given a Pelican setting URL that contains a placeholder for a date, and a
    date, it will combine the two to return the resulting URL.

    Args
    ----
        value (datetime.datetime): a date
        url (string): a Pelican URL setting

    Returns
    -------
        string: combined URL

    """
    return url.format(date=value)

def breaking_spaces(value):
    """
    Convert non-breaking spaces to regular spaces.

    Args
    ----
        value (str): input value

    Returns
    -------
        str: the input string, now with regular spaces

    """
    return value.replace("\u00A0", " ")

def titlecase(value):
    """
    Returns the titlecased version of the supplied text.

    Args
    ----
        value (str): input value

    Returns
    -------
        str: value, titlecase formatted

    """
    return _titlecase(value)


from flask import Flask, render_template, request
from interference import MaskModel
from werkzeug import secure_filename

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploaded'
img_path= 'C:\\Users\\Admin\\Desktop\\mask_rcnn-v2\\images\\12283150_12d37e6389_z.jpg'

# @app.route("/prediction", methods=['GET'])
def mask():
    model = MaskModel()
    img = model.segment_instance(img_path)
    return(img)

@app.route("/save", methods=['GET'])
def save(img):
    return img

@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
   if request.method == 'POST':
      f = request.files['file']
      f.save(secure_filename(f.filename))
      return 'file uploaded successfully'

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=False)


def print_arrays(arrays, labels=None, colwidth=12):
  """Pretty-prints a list of [1, T, D] arrays."""
  if labels is not None:
    print(" |".join(labels))
    widths = [len(l) for l in labels]
  else:
    widths = [colwidth] * len(arrays[0].shape[-1])
  for layer in arrays:
    print("=" * (colwidth + 1) * layer.shape[1])
    for row in layer[0]:
      print(" |".join([f"{x:<{width}.2f}" for x, width in zip(row, widths)]))


import tkinter as tk
from tkinter import *
from tkinter import ttk
from Library_Mods import *
from tkinter import messagebox

class MenuMain(tk.Tk):#Marshall wrote this code block
    def __init__(self):
        super().__init__()
        width = 380
        height = 205
        screen_wid = self.winfo_screenwidth()
        screen_hei = self.winfo_screenheight()
        x = (screen_wid/2) - (width/2)
        y = (screen_hei/2) - (height/2)
        self.geometry("%dx%d+%d+%d" % (width, height, x, y))
        self.style = ttk.Style()
        self.style2 = ttk.Style()
        self.style.configure('nbutton.TButton', background = '#e1d8b9', width = 18, height = 34)
        self.style2.configure('n2button.TButton', background = '#e1d8b9')
        self.configure(bg = '#e1d8b9')
        self.title("Public Library")
        self.set_up()

    def set_up(self):

        self.frame_start = tk.Frame(bg = '#e1d8b9')#Frame for start welcome and instructions
        self.frame_start.pack(padx = (0,10))
        tk.Label(self.frame_start, text = "Thank You for Visiting Your",
                  bg = '#e1d8b9', font = ('Baskerville Old Face', '12', 'bold')).grid(row = 0, column = 0, columnspan = 2)
        tk.Label(self.frame_start, text = "Anderson Public Library",
                  bg = '#e1d8b9', font = ('Baskerville Old Face', '24', 'bold')).grid(row = 1, column = 0, columnspan = 2)
        tk.Label(self.frame_start, text = "What Would You Like To Access",
                  bg = '#e1d8b9', font = ('Baskerville Old Face', '12', 'bold')).grid(row = 2, column = 0, columnspan = 2)

        self.but_horde = ttk.Button(self.frame_start, style = 'nbutton.TButton', text = "Reports", command = self.report)
        self.but_horde.grid(row = 3, column = 0, sticky = 'e', padx=1)

        self.but_char = ttk.Button(self.frame_start, style = 'nbutton.TButton',text = "Catalog", command = self.catalog)
        self.but_char.grid(row = 3, column = 1, sticky = 'w', padx=1)

        self.but_member = ttk.Button(self.frame_start, style='nbutton.TButton', text="Members", command=self.members_window)
        self.but_member.grid(row=4, column=0, columnspan = 2, pady=2)

        ttk.Button(self.frame_start, text = 'Exit', style = 'n2button.TButton',command = lambda : exit()).grid(row = 5, column = 0, columnspan = 2)

    def report(self):#opens report window
        self.show_reports()

    def show_reports(self):
        main_geometry = self.geometry()
        # Create an instance of Reports when the button is clicked
        new_win1 = Reports(self)
        new_win1.grab_set()
        self.report_instance = new_win1

    def catalog(self):#opens Catalog Window
        new_win2 = Book_Catalog(self)
        new_win2.grab_set()

    def members_window(self):#opens members Window
        new_win3 = Members(self)
        new_win3.grab_set()

    #Creates parent class instructions for other windows
    def clear_frame(frame):#Destroys child window on exit
        for widgets in frame.winfo_children():
            widgets.destroy()

class Reports(tk.Toplevel):#Marshall wrote this code block

    def __init__(self, parent):
        super().__init__(parent)
        self.width = 380
        self.height = 205
        self.screen_wid = self.winfo_screenwidth()
        self.screen_hei = self.winfo_screenheight()
        self.geometry(f"{self.screen_wid-25}x{self.screen_hei-60}")

        self.configure(bg = '#e1d8b9')
        self.style = ttk.Style()
        self.style.configure('nbutton.TButton', background = '#e1d8b9', width = 18, height = 34)
        self.title("Reports")
        self.report_window()
        self.grid_rowconfigure(2, weight=1)
        self.grid_columnconfigure(0, weight=1)

    def report_window(self):

        self.frame_head3 = tk.Frame(self, bg = '#e1d8b9')#Frame for image
        self.frame_head3.grid(row = 0, sticky='nsew')

        self.frame_buttons = tk.Frame(self, bg = '#e1d8b9', height=50)#Frame for image
        self.frame_buttons.grid(row = 1, sticky='nsew')
        self.frame_buttons.grid_columnconfigure(0, weight=1)
        self.frame_buttons.grid_columnconfigure(1, weight=1)
        tk.Label(self.frame_head3, text = "Which Report Would",
                  bg = '#e1d8b9', font = ('Baskerville Old Face', '18', 'bold')).pack(fill='x')
        tk.Label(self.frame_head3, text = "You Like to View",
                  bg = '#e1d8b9', font = ('Baskerville Old Face', '12')).pack(fill='x')

        ttk.Button(self.frame_buttons, text='Books Out', style='nbutton.TButton',
                   command=self.books_out).grid(row=0, column=0, padx=1, sticky='e')
        ttk.Button(self.frame_buttons, text='Books Late', style='nbutton.TButton',
                   command=self.books_late).grid(row=0, column=1, padx=1, sticky= 'w')

        ttk.Button(self.frame_buttons, text='Return to Main Menu', style='n2button.TButton',
                   command=self.destroy).grid(row=1, column=0, columnspan=2, pady=2)
        self.results2 = tk.Frame(self, bg = '#e1d8b9')#setting up results panel
        self.results2.grid(row=2, padx=10, pady=10,sticky='nsew')

    def books_out(self): #changes the reports window to reflect the actions of books out button
        MenuMain.clear_frame(self.results2)
        my_results = Report().bks_out_emails()
        my_scrollbar = tk.Scrollbar(self.results2)
        my_scrollbar.pack(side=RIGHT, fill=Y)
        text_box = Text(
            self.results2,yscrollcommand=my_scrollbar.set)
        text_box.pack(expand=True, fill='both')
        text_box.insert('end', my_results)
        text_box.config(state='disabled', padx=25)
        my_scrollbar.config(command=text_box.yview)

    def books_late(self):
        MenuMain.clear_frame(self.results2)
        my_results = Report().bks_late()
        my_scrollbar = tk.Scrollbar(self.results2)
        my_scrollbar.pack(side=RIGHT, fill=Y)
        text_box = Text(
            self.results2,yscrollcommand=my_scrollbar.set)
        text_box.pack(expand=True, fill='both')
        text_box.insert('end', my_results)
        text_box.config(state='disabled', padx=25)
        my_scrollbar.config(command=text_box.yview)

class Book_Catalog(tk.Toplevel):
    pass

class Members(tk.Toplevel):
    pass

def main():#starts program and begins run
    app = MenuMain()
    app.mainloop()

if __name__ == "__main__": main()