import time
import os
import numpy as np
import torch
from torch.autograd import Variable
from torch.optim.lr_scheduler import MultiStepLR

from src.data import *
from src.evaluate import evaluate
from src.model import SSD300, Loss
from src.utils import Encoder, SSDTransformer, dboxes300_coco

# Apex imports
try:
    from apex.parallel import DistributedDataParallel as DDP
    from apex.fp16_utils import *
except ImportError:
    raise ImportError(
        "Please install APEX from https://github.com/nvidia/apex")

def set_seeds(args):
    torch.cuda.set_device(args.local_rank)
    device = torch.device('cuda')

    if args.distributed:
        args.seed = broadcast_seeds(args.seed, device)
        local_seed = (args.seed + torch.distributed.get_rank()) % 2**32
        local_rank = torch.distributed.get_rank()
    else:
        local_seed = args.seed % 2**32
        local_rank = 0

    print("Rank", local_rank, "using seed = {}".format(local_seed))

    torch.manual_seed(local_seed)
    np.random.seed(seed=local_seed)

    return local_seed

def broadcast_seeds(seed, device):
    if torch.distributed.is_initialized():
        seeds_tensor = torch.LongTensor([seed]).to(device)
        torch.distributed.broadcast(seeds_tensor, 0)
        seed = seeds_tensor.item()
    return seed

def warmup(optim, warmup_iters, iteration, base_lr):
    if iteration < warmup_iters:
        new_lr = 1. * base_lr / warmup_iters * iteration
        for param_group in optim.param_groups:
            param_group['lr'] = new_lr

def tencent_trick(model):
    """
    Divide parameters into 2 groups.
    First group is BNs and all biases.
    Second group is the remaining model's parameters.
    Weight decay will be disabled in first group (aka tencent trick).
    """
    decay, no_decay = [], []
    for name, param in model.named_parameters():
        if not param.requires_grad:
            continue  # frozen weights
        if len(param.shape) == 1 or name.endswith(".bias"):
            no_decay.append(param)
        else:
            decay.append(param)
    return [{'params': no_decay, 'weight_decay': 0.0},
            {'params': decay}]

class AverageMeter(object):
    """Computes and stores the average and current value"""

    def __init__(self):
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

def train(args):
    args.distributed = False
    if 'WORLD_SIZE' in os.environ:
        args.distributed = int(os.environ['WORLD_SIZE']) > 1

    if args.distributed:
        torch.cuda.set_device(args.local_rank)
        torch.distributed.init_process_group(
            backend='nccl', init_method='env://')
        args.N_gpu = torch.distributed.get_world_size()
    else:
        args.N_gpu = 1

    dboxes = dboxes300_coco()
    encoder = Encoder(dboxes)
    cocoGt = get_coco_ground_truth(args)

    val_dataset = get_val_dataset(args)
    val_dataloader = get_val_dataloader(val_dataset, args)

    ssd300 = SSD300(len(cocoGt.cats) + 1)
    args.learning_rate = args.learning_rate * \
        args.N_gpu * (args.batch_size / 32)
    iteration = 0
    loss_func = Loss(dboxes)

    ssd300.cuda()
    loss_func.cuda()

    if args.fp16:
        ssd300 = network_to_half(ssd300)

    if args.distributed:
        ssd300 = DDP(ssd300)

    optimizer = torch.optim.SGD(
        tencent_trick(ssd300),
        lr=args.learning_rate,
        momentum=args.momentum,
        weight_decay=args.weight_decay)

    scheduler = MultiStepLR(
        optimizer=optimizer,
        milestones=args.multistep,
        gamma=0.1)

    if args.fp16:
        optimizer = FP16_Optimizer(optimizer, static_loss_scale=128.)

    inv_map = {v: k for k, v in val_dataset.label_map.items()}

    avg_loss = 0.0
    acc = 0
    batch_perf = AverageMeter()
    end = time.time()
    train_start = end

    args.train_annotate = os.path.join(
        args.data, "annotations/instances_train2017.json")
    args.train_coco_root = os.path.join(args.data, "train2017")
    local_seed = set_seeds(args)

    if args.data_pipeline == 'no_dali':
        train_trans = SSDTransformer(dboxes, args, (300, 300), val=False)
        train_dataset = get_train_dataset(args, train_trans)
        train_loader = get_train_loader(train_dataset, args, args.num_workers)
    elif args.data_pipeline == 'dali':
        train_loader = get_train_dali_loader(args, dboxes, local_seed)

    for epoch in range(args.epochs):
        start_epoch_time = time.time()
        scheduler.step()

        epoch_loop(train_loader, args, ssd300, time.time(),
                   loss_func, optimizer, iteration, avg_loss, batch_perf, epoch)
        torch.cuda.synchronize()

        if epoch in args.evaluation:
            acc = evaluate(ssd300, val_dataloader,
                           cocoGt, encoder, inv_map, args)

        try:
            train_loader.reset()
        except AttributeError:
            pass

    if args.local_rank == 0:
        print("Training end: Average speed: {:3f} img/sec, Total time: {:3f} sec, Final accuracy: {:3f} mAP"
          .format(
              args.N_gpu * args.batch_size / batch_perf.avg,
              time.time() - train_start,
              acc))

def epoch_loop(train_loader, args, ssd300, end, loss_func, optimizer, iteration, avg_loss, batch_perf, epoch):
    for nbatch, data in enumerate(train_loader):
        if args.data_pipeline == 'no_dali':
            (img, _, img_size, bbox, label) = data
            img = img.cuda()
            bbox = bbox.cuda()
            label = label.cuda()
        else:
            img = data[0]["images"]
            bbox = data[0]["boxes"]
            label = data[0]["labels"]
            label = label.type(torch.cuda.LongTensor)

        boxes_in_batch = len(label.nonzero())

        if boxes_in_batch != 0:
            ploc, plabel = ssd300(img)
            ploc, plabel = ploc.float(), plabel.float()

            trans_bbox = bbox.transpose(1, 2).contiguous().cuda()

            label = label.cuda()
            gloc = Variable(trans_bbox, requires_grad=False)
            glabel = Variable(label, requires_grad=False)

            loss = loss_func(ploc, plabel, gloc, glabel)

            if args.fp16:
                optimizer.backward(loss)
            else:
                loss.backward()

        if args.warmup is not None:
            warmup(optimizer, args.warmup, iteration, args.learning_rate)

        if not np.isinf(loss.item()):
            avg_loss = 0.999*avg_loss + 0.001*loss.item()

        optimizer.step()
        optimizer.zero_grad()

        batch_perf.update(time.time() - end)
        if args.local_rank == 0:
            log_perf(epoch, args, iteration, loss, avg_loss, batch_perf)

        iteration += 1
        end = time.time()

def log_perf(epoch, args, iteration, loss, avg_loss, batch_perf):
    print("Epoch {:2d}, Iteration: {:3d}, Loss function: {:5.3f}, Average Loss: {:.3f}, Speed: {:4f} img/sec, Avg speed: {:4f} img/sec"
          .format(epoch, iteration, loss.item(), avg_loss, args.batch_size / batch_perf.val, args.batch_size / batch_perf.avg))


import numpy as np
from numpy.core.einsumfunc import _parse_einsum_input

import mygrad as mg
from mygrad import Tensor

from .ops import *

__all__ = ["multi_matmul", "matmul", "einsum"]

def matmul(a, b, constant=False):
    r"""
    Matrix product of two tensors:

    ``matmul(x, y)`` is equivalent to ``x @ y``.

    This documentation was adapted from ``numpy.matmul``

    The behavior depends on the arguments in the following way.

    - If both arguments are 2-D they are multiplied like conventional
      matrices.
    - If either argument is N-D, N > 2, it is treated as a stack of
      matrices residing in the last two indexes and broadcast accordingly.
    - If the first argument is 1-D, it is promoted to a matrix by
      prepending a 1 to its dimensions. After matrix multiplication
      the prepended 1 is removed.
    - If the second argument is 1-D, it is promoted to a matrix by
      appending a 1 to its dimensions. After matrix multiplication
      the appended 1 is removed.

    Multiplication by a scalar is not allowed, use ``*`` instead. Note that
    multiplying a stack of matrices with a vector will result in a stack of
    vectors, but matmul will not recognize it as such.

    ``matmul`` differs from ``numpy.dot`` in two important ways.

    - Multiplication by scalars is not allowed.
    - Stacks of matrices are broadcast together as if the matrices
      were elements.

    Parameters
    ----------
    a : array_like

    b : array_like

    constant : bool, optional(default=False)
        If ``True``, the returned tensor is a constant (it
        does not back-propagate a gradient)

    Returns
    -------
    output : mygrad.Tensor
        Returns the matrix product of `a` and `b`.  If `a` and `b` are both
        1-D arrays then a scalar is returned; otherwise an array is
        returned.

    Raises
    ------
    ValueError
        If the last dimension of `a` is not the same size as
        the second-to-last dimension of `b`.

        If scalar value is passed.

    Notes
    -----
    The matmul function implements the semantics of the `@` operator introduced
    in Python 3.5 following PEP465.

    Examples
    --------
    For two 2D tensors, ``matmul(a, b)`` is the matrix product :math:`\sum_{j}{A_{ij} B_{jk}} = F_{ik}`:

    >>> import mygrad as mg
    >>> a = [[1, 0], [0, 1]]
    >>> b = [[4, 1], [2, 2]]
    >>> mg.matmul(a, b)
    Tensor([[4, 1],
            [2, 2]])

    For 2-D mixed with 1-D, the result is the matrix-vector product, :math:`\sum_{j}{A_{ij} B_{j}} = F_{i}`:

    >>> a = [[1, 0], [0, 1]]
    >>> b = [1, 2]
    >>> mg.matmul(a, b)
    Tensor([1, 2])

    Broadcasting is conventional for stacks of arrays. Here ``a`` is treated
    like a stack of three 5x6 matrices, and the 6x4 matrix ``b`` is broadcast
    matrix-multiplied against each one. This produces a shape-(3, 5, 4) tensor
    as a result.

    >>> a = mg.arange(3*5*6).reshape((3,5,6))
    >>> b = mg.arange(6*4).reshape((6,4))
    >>> mg.matmul(a,b).shape
    (3, 5, 4)

    Scalar multiplication raises an error.

    >>> mg.matmul(a, 3)
    Traceback (most recent call last):
    ...
    ValueError: Scalar operands are not allowed, use '*' instead"""
    return Tensor._op(MatMul, a, b, constant=constant)

def einsum(*operands, optimize=False, constant=False):
    r"""
    einsum(subscripts, *operands)

    Evaluates the Einstein summation convention on the operands. This implementation
    exactly mirrors that of ``numpy.einsum`` and supports back-propagation through
    all variety of tensor-products, sums, traces, and views that it can perform.

    The following docstring was adapted from the documentation for ``numpy.einsum``

    Using the Einstein summation convention, many common multi-dimensional
    array operations can be represented in a simple fashion.  This function
    provides a way to compute such summations. The best way to understand this
    function is to try the examples below, which show how many common NumPy/MyGrad
    functions can be implemented as calls to ``einsum``.

    Back-propagation via ``einsum`` is optimized such that any tensor that occurs
    redundantly within the summation will only have its gradient computed once.
    This optimization accommodates all number and combination of redundancies that can
    be encountered.

    E.g. back-propping through ``einsum('...,...->', x, x)`` will only incur a single
    computation/accumulation for ``x.grad`` rather than two. This permits users to
    leverage the efficiency of sum-reduction, where ``(x ** 2).sum()`` is sub-optimal,
    without being penalized during back-propagation.

    Parameters
    ----------
    subscripts : str
        Specifies the subscripts for summation.

    operands : array_like
        The tensors used in the summation.

    optimize : {False, True, 'greedy', 'optimal'}, optional (default=False)
        Controls if intermediate optimization should occur; also enables
        the use of BLAS where possible. This can produce significant speedups
        for computations like matrix multiplication.

        No optimization will occur if False and True will default to the 'greedy'
        algorithm. Also accepts an explicit contraction list from the
        ``np.einsum_path`` function. See ``np.einsum_path`` for more details.

    constant : bool, optional (default=False)
        If True, the resulting Tensor is a constant.

    Returns
    -------
    output : mygrad.Tensor
        The calculation based on the Einstein summation convention.

    Notes
    -----
    The subscripts string is a comma-separated list of subscript labels,
    where each label refers to a dimension of the corresponding operand.
    Repeated subscripts labels in one operand take the diagonal.  For example,
    ``einsum('ii', a)`` is equivalent to ``np.trace(a)`` (however, the former
    supports back-propagation).

    Whenever a label is repeated, it is summed, so ``einsum('i, i', a, b)``
    is equivalent to ``np.inner(a, b)``.  If a label appears only once,
    it is not summed, so ``einsum('i', a)`` produces a view of ``a``
    with no changes.

    The order of labels in the output is by default alphabetical.  This
    means that ``np.einsum('ij', a)`` doesn't affect a 2D tensor, while
    ``einsum('ji', a)`` takes its transpose.

    The output can be controlled by specifying output subscript labels
    as well.  This specifies the label order, and allows summing to
    be disallowed or forced when desired.  The call ``einsum('i->', a)``
    is like ``np.sum(a, axis=-1)``, and ``einsum('ii->i', a)``
    is like ``np.diag(a)``.  The difference is that `einsum` does not
    allow broadcasting by default.

    To enable and control broadcasting, use an ellipsis.  Default
    NumPy-style broadcasting is done by adding an ellipsis
    to the left of each term, like ``einsum('...ii->...i', a)``.
    To take the trace along the first and last axes,
    you can do ``einsum('i...i', a)``, or to do a matrix-matrix
    product with the left-most indices instead of rightmost, you can do
    ``einsum('ij...,jk...->ik...', a, b)``.

    When there is only one operand, no axes are summed, and no output
    parameter is provided, a view into the operand is returned instead
    of a new tensor.  Thus, taking the diagonal as ``einsum('ii->i', a)``
    produces a view.

    An alternative way to provide the subscripts and operands is as
    ``einsum(op0, sublist0, op1, sublist1, ..., [sublistout])``. The examples
    below have corresponding `einsum` calls with the two parameter methods.

    Examples
    --------
    >>> import mygrad as mg
    >>> import numpy as np
    >>> a = mg.arange(25).reshape(5,5)
    >>> b = mg.arange(5)
    >>> c = mg.arange(6).reshape(2,3)

    Compute the trace of ``a``, :math:`\sum_{i}{A_{ii}} = f`:

    >>> einsum('ii', a)
    Tensor(60)
    >>> einsum(a, [0, 0])
    Tensor(60)
    >>> np.trace(a.data)
    array(60)

    Return a view along the diagonal of ``a``, :math:`A_{ii} = F_{i}`:

    >>> einsum('ii->i', a)
    Tensor([ 0,  6, 12, 18, 24])
    >>> einsum(a, [0,0], [0])
    Tensor([ 0,  6, 12, 18, 24])
    >>> np.diag(a.data)
    array([ 0,  6, 12, 18, 24])

    Compute the matrix-vector product of ``a`` with ``b``, :math:`\sum_{j}{A_{ij} B_{j}} = F_{i}`:

    >>> einsum('ij,j', a, b)
    Tensor([ 30,  80, 130, 180, 230])
    >>> einsum(a, [0,1], b, [1])
    Tensor([ 30,  80, 130, 180, 230])
    >>> mg.matmul(a, b)
    Tensor([ 30,  80, 130, 180, 230])
    >>> einsum('...j,j', a, b)
    Tensor([ 30,  80, 130, 180, 230])

    Take the transpose of ``c``, :math:`C_{ji} = F_{ij}`:

    >>> einsum('ji', c)
    Tensor([[0, 3],
            [1, 4],
            [2, 5]])
    >>> einsum(c, [1, 0])
    Tensor([[0, 3],
            [1, 4],
            [2, 5]])
    >>> c.T
    Tensor([[0, 3],
            [1, 4],
            [2, 5]])

    Compute ``3 * c``:

    >>> einsum('..., ...', 3, c)
    Tensor([[ 0,  3,  6],
            [ 9, 12, 15]])
    >>> einsum(',ij', 3, c)
    Tensor([[ 0,  3,  6],
            [ 9, 12, 15]])
    >>> einsum(3, [Ellipsis], c, [Ellipsis])
    Tensor([[ 0,  3,  6],
            [ 9, 12, 15]])
    >>> 3 * c
    Tensor([[ 0,  3,  6],
            [ 9, 12, 15]])

    Compute the inner product of ``b`` with itself, :math:`\sum_{i}{B_{i} B_{i}} = f`:

    >>> einsum('i,i', b, b)
    Tensor(30)
    >>> einsum(b, [0], b, [0])
    Tensor(30)
    >>> np.inner(b.data, b.data)
    30

    Compute the outer product of ``array([1, 2])`` with ``b``, :math:`A_{i}B_{j} = F_{ij}`:

    >>> einsum('i,j', np.arange(2)+1, b)
    Tensor([[0, 1, 2, 3, 4],
           [0, 2, 4, 6, 8]])
    >>> einsum(np.arange(2)+1, [0], b, [1])
    Tensor([[0, 1, 2, 3, 4],
           [0, 2, 4, 6, 8]])
    >>> np.outer(np.arange(2)+1, b)
    array([[0, 1, 2, 3, 4],
           [0, 2, 4, 6, 8]])
    >>> einsum('i...->...', a)
    Tensor([50, 55, 60, 65, 70])
    >>> einsum(a, [0,Ellipsis], [Ellipsis])
    Tensor([50, 55, 60, 65, 70])
    >>> np.sum(a, axis=0)
    array([50, 55, 60, 65, 70])

    Compute the tensor product :math:`\sum_{ij}{A_{ijk} B_{jil}} = F_{kl}`

    >>> a = mg.arange(60.).reshape(3,4,5)
    >>> b = mg.arange(24.).reshape(4,3,2)
    >>> einsum('ijk,jil->kl', a, b)
    Tensor([[ 4400.,  4730.],
            [ 4532.,  4874.],
            [ 4664.,  5018.],
            [ 4796.,  5162.],
            [ 4928.,  5306.]])
    >>> einsum(a, [0,1,2], b, [1,0,3], [2,3])
    Tensor([[ 4400.,  4730.],
            [ 4532.,  4874.],
            [ 4664.,  5018.],
            [ 4796.,  5162.],
            [ 4928.,  5306.]])
    >>> np.tensordot(a,b, axes=([1,0],[0,1]))
    array([[ 4400.,  4730.],
            [ 4532.,  4874.],
            [ 4664.,  5018.],
            [ 4796.,  5162.],
            [ 4928.,  5306.]])

    Matrix multiply ``a.T`` with ``b.T``, :math:`\sum_{k}{A_{ki} B_{jk}} = F_{ij}`

    >>> a = mg.arange(6).reshape((3,2))
    >>> b = mg.arange(12).reshape((4,3))
    >>> einsum('ki,jk->ij', a, b)
    Tensor([[10, 28, 46, 64],
            [13, 40, 67, 94]])
    >>> einsum('ki,...k->i...', a, b)
    Tensor([[10, 28, 46, 64],
            [13, 40, 67, 94]])
    >>> einsum('k...,jk', a, b)
    Tensor([[10, 28, 46, 64],
            [13, 40, 67, 94]])

    Make an assignment to a view along the diagonal of ``a``:

    >>> a = mg.zeros((3, 3))
    >>> einsum('ii->i', a).data[:] = 1
    >>> a
    Tensor([[ 1.,  0.,  0.],
            [ 0.,  1.,  0.],
            [ 0.,  0.,  1.]])
    """

    # TODO: normalize error handling for invalid inputs
    operands = list(operands)
    if isinstance(operands[0], str):
        # operands form: "ijk, ijk", x, y
        variables = operands[1:]
        if any(isinstance(i, Tensor) for i in operands):
            operands[1:] = (
                var.data if isinstance(var, Tensor) else var for var in operands[1:]
            )
    else:
        # operands form: op0, sublist0, op1, sublist1, ..., [sublistout]
        end = -1 if len(operands) % 2 else None  # -1 if sublistout is included
        variables = operands[:end:2]
        if any(isinstance(i, Tensor) for i in operands):
            operands[:end:2] = (
                var.data if isinstance(var, Tensor) else var for var in operands[:end:2]
            )

    in_lbls, out_lbls, _ = _parse_einsum_input(operands)
    return Tensor._op(
        EinSum,
        *variables,
        op_kwargs=dict(in_lbls=in_lbls, out_lbls=out_lbls, optimize=optimize),
        constant=constant
    )

def multi_matmul(tensors, constant=False):
    """
    Matrix product of two or more tensors calculated in the optimal ordering

    Parameters
    ----------
    tensors: Sequence[array_like]
        The sequence of tensors to be matrix-multiplied.

    constant : bool, optional(default=False)
        If ``True``, the returned tensor is a constant (it
        does not back-propagate a gradient).

    Returns
    -------
    mygrad.Tensor
        Returns the matrix product of the tensors provided

    Extended Summary
    ----------------
    This documentation was adapted from ``numpy.linalg.multi_dot``

    Compute the matrix multiplication of two or more arrays in a single function
    call, while automatically selecting the fastest evaluation order.
    ``multi_matmul`` chains ``matmul`` and uses optimal parenthesization  [1]_ [2]_.
    Depending on the shapes of the matrices, this can speed up the multiplication a lot.

    If the first argument is 1-D it is treated as a row vector.

    If the last argument is 1-D it is treated as a column vector.

    The other arguments must be 2-D or greater.

    Think of `multi_dot` as an optimized version of::

        def multi_dot(tensors): return functools.reduce(mg.matmul, tensors)

    Raises
    ------
    ValueError
        If ``tensors`` contains less than two array_like items.

    ValueError
        If ``tensor`` other than the first or last is less than two dimensional

    See Also
    --------
    matmul : matrix multiplication with two arguments.

    References
    ----------

    .. [1] Cormen, "Introduction to Algorithms", Chapter 15.2, p. 370-378
    .. [2] http://en.wikipedia.org/wiki/Matrix_chain_multiplication

    Notes
    -----
    The cost for a matrix multiplication can be calculated with the
    following function::

        def cost(A, B):
            return A.shape[0] * A.shape[1] * B.shape[1]

    Let's assume we have three matrices :math:`A_{10x100}, B_{100x5}, C_{5x50}`.

    The costs for the two different parenthesizations are as follows::

        cost((AB)C) = 10*100*5 + 10*5*50   = 5000 + 2500   = 7500
        cost(A(BC)) = 10*100*50 + 100*5*50 = 50000 + 25000 = 75000

    Examples
    --------
    ``multi_matmul`` allows you to write:

    >>> from mygrad import multi_matmul, matmul, Tensor
    >>> import numpy as np
    >>> # Prepare some random tensors
    >>> A = Tensor(np.random.random((10000, 100)))
    >>> B = Tensor(np.random.random((100, 1000)))
    >>> C = Tensor(np.random.random((1000, 5)))
    >>> D = Tensor(np.random.random((5, 333)))
    >>> # the actual matrix multiplication
    >>> multi_matmul([A, B, C, D]) # computes (A @ (B @ C)) @ D

    instead of:

    >>> matmul(matmul(matmul(A, B), C), D)
    >>> # or
    >>> A @ B @ C @ D
    """

    for a in tensors:
        if not (1 <= a.ndim <= 2):
            raise ValueError(
                "%d-dimensional tensor given. Tensor must be one or two-dimensional"
                % (a.ndim,)
            )

    n = len(tensors)
    if n < 2:
        raise ValueError("Expecting at least two arrays.")
    elif n == 2:
        return matmul(tensors[0], tensors[1], constant)

    tensors = [a if isinstance(a, Tensor) else np.asarray(a) for a in tensors]

    # save original ndim to reshape the result array into the proper form later
    ndim_first, ndim_last = tensors[0].ndim, tensors[-1].ndim

    # Explicitly convert vectors to 2D arrays to keep the logic of this function simpler
    if tensors[0].ndim == 1:
        tensors[0] = mg.expand_dims(
            tensors[0],
            axis=0,
            constant=tensors[0].constant if isinstance(tensors[0], Tensor) else True,
        )
    if tensors[-1].ndim == 1:
        tensors[-1] = mg.expand_dims(
            tensors[-1],
            axis=1,
            constant=tensors[-1].constant if isinstance(tensors[-1], Tensor) else True,
        )

    if n == 3:
        result = _multi_matmul_three(tensors[0], tensors[1], tensors[2], constant)
    else:
        order = _multi_matmul_chain_order(tensors)
        result = _multi_matmul(tensors, order, 0, n - 1, constant)

    # return proper shape since we possibly added dimensions to the first
    # and last arrays
    if ndim_first == 1 and ndim_last == 1:
        return result[0, 0]
    elif ndim_first == 1 or ndim_last == 1:
        return result.reshape(-1)
    else:
        return result

def _multi_matmul_three(A, B, C, constant=False) -> Tensor:
    """
    Find the best order for three arrays and do the multiplication.

    """
    a0, a1b0 = A.shape[-2:]
    b1c0, c1 = C.shape[-2:]
    cost1 = a0 * b1c0 * (a1b0 + c1)
    cost2 = a1b0 * c1 * (a0 + b1c0)

    if cost1 < cost2:
        return matmul(matmul(A, B, constant), C, constant)
    else:
        return matmul(A, matmul(B, C, constant), constant)

def _multi_matmul_chain_order(arrays):
    """
    Return a np.array that encodes the optimal order of multiplications.
    The optimal order array is then used by `_multi_matmul()` to do the
    multiplication.

    The implementation CLOSELY follows Cormen, "Introduction to Algorithms",
    Chapter 15.2, p. 370-378.  Note that Cormen uses 1-based indices.

        cost[i, j] = min([
            cost[prefix] + cost[suffix] + cost_mult(prefix, suffix)
            for k in range(i, j)])
    """
    n = len(arrays)
    # p stores the dimensions of the matrices
    # Example for p: A_{10x100}, B_{100x5}, C_{5x50} --> p = [10, 100, 5, 50]
    # Using -2 to generalize for shapes that are more than 2 dimmensions
    p = [a.shape[-2] for a in arrays] + [arrays[-1].shape[-1]]
    # m is a matrix of costs of the subproblems
    # m[i,j]: min number of scalar multiplications needed to compute A_{i..j}
    m = np.zeros((n, n), dtype=np.double)
    # s is the actual ordering
    # s[i, j] is the value of k at which we split the product A_i..A_j
    s = np.empty((n, n), dtype=np.intp)

    for l in range(1, n):
        for i in range(n - l):
            j = i + l
            m[i, j] = np.inf
            for k in range(i, j):
                q = m[i, k] + m[k + 1, j] + p[i] * p[k + 1] * p[j + 1]
                if q < m[i, j]:
                    m[i, j] = q
                    s[i, j] = k  # Note that Cormen uses 1-based index
    return s

def _multi_matmul(arrays, order, i, j, constant=False) -> Tensor:
    """Actually do the multiplication with the given order."""
    if i == j:
        return arrays[i]
    else:
        return matmul(
            _multi_matmul(arrays, order, i, order[i, j], constant),
            _multi_matmul(arrays, order, order[i, j] + 1, j, constant),
            constant,
        )


# -*- coding: utf-8 -*-
"""
Created on Thu Sep 30 08:06:45 2021

@author: Diana Sofía Carrillo
"""
from sympy import*
from pylab import*
import numpy as np

def lagrange(x, t, u = None):
    n = len(x)
    t = Symbol('t')
    p = 0
    for i in range(n):
        L = 1
        for j in range(n):
            if j != i:
                L = L*(t - x[j])/(x[i]-x[j])
        p = p + y[i]*L
        p = expand(p)
    if u == None:
        return p
    else:
        return p.subs(t, u)

x = [40, 50, 60, 70, 80]
y = [35, 83, 153, 193, 215]
p = lagrange(x, y)
print("Polinomio de interpolación: ",p)
valor = 55
r = lagrange(x, y, valor)
print("Polinomio evaluado en", valor, ":",r)

def f(t): return t**4/3750 - 101*t**3/1500 + 371*t**2/60 - 7181*t/30 + 3343
t = arange(30, 80)
plot(t, f(t))
plot(x, y, 'o')
grid(true)
show()


class Solution:
    def searchRange(self, nums: 'List[int]', target: 'int') -> 'List[int]':
        # binary search
        left = 0
        right = len(nums) - 1
        middle = -1
        while left <= right:
            middle = (left + right) // 2
            if nums[middle] < target:
                left = middle + 1
            elif nums[middle] > target:
                right = middle - 1
            else:
                left = middle
                right = middle
                while left > 0 and nums[left - 1] == target:
                    left -= 1
                while right < len(nums) - 1 and nums[right + 1] == target:
                    right += 1
                return [left, right]
        return [-1, -1]


import os
import GitHub_ff14.fishinfo as fishinfo

# testid="440.html"
#
# fishinfo.fishinfo(testid)
# exit()
file_names = os.listdir("F:/htmls/fish/")
sqls=[]
for file in  file_names:
    sql = fishinfo.fishinfo(file)
    sqls.append(sql)
# fishinfo.connecttomysql(sqls)

#######测试########
# select ="SELECT a.fish_id,a.fish_name,a.weather,a.time,c.fish_area_name,b.baitname,b.probability,b.is_small_to_big FROM ff_fish a LEFT JOIN ff_fish_area c ON a.`where`=c.fish_area_id  LEFT JOIN ff_bait_fish b ON a.fish_id=b.fishid "
# js=fishinfo.testMysql2(select)
# fishinfo.write_to_file("F:/htmls/json1.txt", str(js))


import redis
from kazoo.client import KazooClient
import logging
from functools import reduce

class codis:

    def __init__(self, zk_addr, product, codis_version='v3'):
        logging.basicConfig()
        self.zk_addr = zk_addr
        self.product = product
        if codis_version == 'v2':
            self.base_url = '/zk/codis/db_{0}'.format(product)
        elif codis_version == 'v3':
            self.base_url = '/codis3/{0}'.format(product)

    def get_proxies(self):
        zk = KazooClient(hosts=self.zk_addr)
        try:
            zk.start()
            if not zk.exists(self.base_url):
                logging.error('{0} not exist'.format(self.base_url))
            else:
                children = zk.get_children('{0}/proxy'.format(self.base_url))
                if children is None:
                    logging.error('No proxy found in {0}'.format(self.base_url))
                else:
                    return list(map(lambda x: eval(zk.get(
                        '{0}/proxy/{1}'.format(self.base_url, x))[0])['proxy_addr'], children))

        except Exception as e:
            logging.error(
                "Failed to connect to {0}: {1}".format(self.zk_addr, e))
        finally:
            if zk is not None:
                zk.stop()

    def get_masters(self):
        zk = KazooClient(hosts=self.zk_addr)
        try:
            zk.start()
            if not zk.exists(self.base_url):
                logging.error('{0} not exist'.format(self.base_url))
            else:
                groups = zk.get_children('{0}/group'.format(self.base_url))
                if groups is None:
                    logging.error('No group found in {0}'.format(self.base_url))
                else:
                    return list(map(
                        lambda x: eval(zk.get(
                            '{0}/group/{1}'.format(self.base_url, x))[0])['servers'][0]['server'],
                        groups)
                    )

        except Exception as e:
            logging.error(
                "Failed to connect to {0}: {1}".format(self.zk_addr, e))
        finally:
            if zk is not None:
                zk.stop()

    def keys(self, pattern='*'):
        masters = self.get_masters()
        return reduce(
            lambda x, y: x + y,
            map(
                lambda x:
                redis.StrictRedis(
                    host=x.split(':')[0], port=x.split(':')[1]).keys(pattern=pattern),
                masters)
        )

def main():
    cds = codis('10.5.79.12:2181', "business")
    # print(cds.get_proxies())
    # print(cds.get_masters())
    print(cds.keys('*|jboss*'))
if __name__ == '__main__':
    main()


# !pip install GetOldTweets3

query_list = ['corona', 'COVID', 'COVID-19',]

location_list = [
    ['Andhra Pradesh',140],
    ['Arunachal Pradesh',101],
    ['Assam',98],
    ['Bihar',111],
    ['Chhattisgarh',129],
    ['Goa',21],
    ['Gujarat',155],
    ['Haryana',74],
    ['Himachal Pradesh',83],
    ['Jammu & Kashmir',165],
    ['Jharkhand',99],
    ['Karnataka',154],
    ['Kerala',69],
    ['Madhya Pradesh',195],
    ['Maharashtra',195],
    ['Manipur',52],
    ['Meghalaya',53],
    ['Mizoram',51],
    ['Nagaland',43],
    ['Odisha',138],
    ['Punjab',79],
    ['Rajasthan',205],
    ['Sikkim',30],
    ['Tamil Nadu',127],
    ['Telangana',117],
    ['Tripura',36],
    ['Uttarakhand',81],
    ['Uttar Pradesh',173],
    ['West Bengal',104]
]

location_list = [(location + ', India', within) for location, within in location_list]

date_list = [
    ("2019-11-01", "2019-11-30"), # Nov, 2019
    ("2019-12-01", "2019-12-31"), # Dec, 2019
    ("2020-01-01", "2020-01-31"), # Jan, 2020
    ("2020-02-01", "2020-02-29"), # Feb, 2020
    ("2020-03-01", "2020-03-31"), # Mar, 2020
    ("2020-04-01", "2020-04-30"), # Apr, 2020
    ("2020-05-01", "2020-05-30"), # May, 2020
]

import time
import GetOldTweets3 as got
import pandas as pd

for location, within in location_list:
  for since_date, until_date in date_list:
    text_tweets = []

    i = 0
    while i < len(query_list):
      query_text = query_list[i]

      tweetCriteria = got.manager.TweetCriteria().setQuerySearch(query_text).setNear(location).setSince(since_date).setUntil(until_date).setLang("en").setWithin(f"{within}mi")

      try:
        tweets = got.manager.TweetManager.getTweets(tweetCriteria)
      except:
        print("Error at", i)
        time.sleep(10)
        continue

      text_tweets.extend( [tweet.text for tweet in tweets] )
      i += 1

    df = pd.DataFrame({"Tweets": text_tweets}, columns=['Tweets',])
    df = df.drop_duplicates().reset_index(drop=True)

    df.to_csv(f"{location[:-7]}_{since_date[5:7]}_tweets.csv", index=False)

  print(location, "done")


# The Hazard Library
# Copyright (C) 2012-2016 GEM Foundation
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
import unittest

import numpy

import openquake.hazardlib
from openquake.hazardlib import const, imt
from openquake.hazardlib.site import Site, SiteCollection
from openquake.hazardlib.geo import Point
from openquake.hazardlib.tom import PoissonTOM
from openquake.hazardlib.calc.hazard_curve import calc_hazard_curves
from openquake.hazardlib.gsim.base import ContextMaker

class FakeSiteContext(object):
    def __init__(self, sites):
        self.sites = sites
        self.mesh = sites.mesh

class HazardCurvesTestCase(unittest.TestCase):
    class FakeRupture(object):
        def __init__(self, probability, tectonic_region_type):
            self.probability = probability
            self.tectonic_region_type = tectonic_region_type

        def get_probability_no_exceedance(self, poes):
            return (1 - self.probability) ** numpy.array(poes)

    class FakeSource(object):
        def __init__(self, source_id, ruptures, time_span, trt):
            self.source_id = source_id
            self.time_span = time_span
            self.ruptures = ruptures
            self.tectonic_region_type = trt
            self.src_group_id = 0

        def iter_ruptures(self):
            return iter(self.ruptures)

    class FailSource(FakeSource):
        def iter_ruptures(self):
            raise ValueError('Something bad happened')

    class FakeGSIM(object):
        REQUIRES_DISTANCES = set()
        REQUIRES_RUPTURE_PARAMETERS = set()
        REQUIRES_SITES_PARAMETERS = set()

        def __init__(self, truncation_level, imts, poes):
            self.truncation_level = truncation_level
            self.imts = imts
            self.poes = poes

        def get_poes(self, sctx, rctx, dctx, imt, imls, truncation_level):
            assert truncation_level is self.truncation_level
            return numpy.array([self.poes[(epicenter.latitude, rctx, imt)]
                                for epicenter in sctx.mesh])

        def __str__(self):
            return self.__class__.__name__

    def setUp(self):
        self.orig_make_contexts = ContextMaker.make_contexts
        ContextMaker.make_contexts = lambda self, sites, rupture: (
            FakeSiteContext(sites), rupture, None)
        self.truncation_level = 3.4
        self.imts = {'PGA': [1, 2, 3], 'PGD': [2, 4]}
        self.time_span = 49.2

        rup11 = self.FakeRupture(0.23, const.TRT.ACTIVE_SHALLOW_CRUST)
        rup12 = self.FakeRupture(0.15, const.TRT.ACTIVE_SHALLOW_CRUST)
        rup21 = self.FakeRupture(0.04, const.TRT.VOLCANIC)
        self.source1 = self.FakeSource(
            1, [rup11, rup12], self.time_span, const.TRT.ACTIVE_SHALLOW_CRUST)
        self.source2 = self.FakeSource(
            2, [rup21], self.time_span, const.TRT.VOLCANIC)
        self.sources = [self.source1, self.source2]
        site1 = Site(Point(10, 20), 1, True, 2, 3)
        site2 = Site(Point(20, 30), 2, False, 4, 5)
        self.sites = SiteCollection([site1, site2])

        gsim1 = self.FakeGSIM(self.truncation_level, self.imts, poes={
            (site1.location.latitude, rup11, imt.PGA()): [0.1, 0.05, 0.03],
            (site2.location.latitude, rup11, imt.PGA()): [0.11, 0.051, 0.034],
            (site1.location.latitude, rup12, imt.PGA()): [0.12, 0.052, 0.035],
            (site2.location.latitude, rup12, imt.PGA()): [0.13, 0.053, 0.036],

            (site1.location.latitude, rup11, imt.PGD()): [0.4, 0.33],
            (site2.location.latitude, rup11, imt.PGD()): [0.39, 0.331],
            (site1.location.latitude, rup12, imt.PGD()): [0.38, 0.332],
            (site2.location.latitude, rup12, imt.PGD()): [0.37, 0.333],
        })
        gsim2 = self.FakeGSIM(self.truncation_level, self.imts, poes={
            (site1.location.latitude, rup21, imt.PGA()): [0.5, 0.3, 0.2],
            (site2.location.latitude, rup21, imt.PGA()): [0.4, 0.2, 0.1],

            (site1.location.latitude, rup21, imt.PGD()): [0.24, 0.08],
            (site2.location.latitude, rup21, imt.PGD()): [0.14, 0.09],
        })
        self.gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: gsim1,
                      const.TRT.VOLCANIC: gsim2}

    def tearDown(self):
        ContextMaker.make_contexts = self.orig_make_contexts

    def test1(self):
        site1_pga_poe_expected = [0.0639157, 0.03320212, 0.02145989]
        site2_pga_poe_expected = [0.06406232, 0.02965879, 0.01864331]
        site1_pgd_poe_expected = [0.16146619, 0.1336553]
        site2_pgd_poe_expected = [0.15445961, 0.13437589]

        curves = calc_hazard_curves(
            self.sources, self.sites, self.imts,
            self.gsims, self.truncation_level)
        self.assertEqual(set(curves.dtype.fields), set(['PGA', 'PGD']))

        pga_curves = curves['PGA']
        self.assertIsInstance(pga_curves, numpy.ndarray)
        self.assertEqual(pga_curves.shape, (2, 3))  # two sites, three IMLs
        site1_pga_poe, site2_pga_poe = pga_curves
        numpy.testing.assert_allclose(
            site1_pga_poe, site1_pga_poe_expected, 1E-6)
        numpy.testing.assert_allclose(
            site2_pga_poe, site2_pga_poe_expected, 1E-6)

        pgd_curves = curves['PGD']
        self.assertIsInstance(pgd_curves, numpy.ndarray)
        self.assertEqual(pgd_curves.shape, (2, 2))  # two sites, two IMLs
        site1_pgd_poe, site2_pgd_poe = pgd_curves
        numpy.testing.assert_allclose(site1_pgd_poe, site1_pgd_poe_expected)
        numpy.testing.assert_allclose(site2_pgd_poe, site2_pgd_poe_expected)

    def test_source_errors(self):
        # exercise `hazard_curves_poissonian` in the case of an exception,
        # whereby we expect the source_id to be reported in the error message

        fail_source = self.FailSource(self.source2.source_id,
                                      self.source2.ruptures,
                                      self.source2.time_span,
                                      const.TRT.VOLCANIC)
        sources = iter([self.source1, fail_source])

        with self.assertRaises(ValueError) as ae:
            calc_hazard_curves(sources, self.sites, self.imts, self.gsims,
                               self.truncation_level)
        expected_error = (
            'An error occurred with source id=2. Error: Something bad happened'
        )
        self.assertEqual(expected_error, str(ae.exception))

class HazardCurvesFiltersTestCase(unittest.TestCase):
    class SitesCounterSourceSitesFilter(object):
        def __init__(self, chained_generator):
            self.counts = []
            self.chained_generator = chained_generator

        def __call__(self, sources, sites):
            for source, sites in self.chained_generator(sources, sites):
                self.counts.append(
                    (source.source_id, list(map(int, sites.vs30))))
                yield source, sites

    class SitesCounterRuptureFilter(object):
        def __init__(self, chained_generator):
            self.counts = []
            self.chained_generator = chained_generator

        def __call__(self, ruptures, sites):
            for rupture, sites in self.chained_generator(ruptures, sites):
                self.counts.append((rupture.mag, list(map(int, sites.vs30))))
                yield rupture, sites

    def test_point_sources(self):
        sources = [
            openquake.hazardlib.source.PointSource(
                source_id='point1', name='point1',
                tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST,
                mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD(
                    min_mag=4, bin_width=1, occurrence_rates=[5]
                ),
                nodal_plane_distribution=openquake.hazardlib.pmf.PMF([
                    (1, openquake.hazardlib.geo.NodalPlane(strike=0.0,
                                                           dip=90.0,
                                                           rake=0.0))
                ]),
                hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]),
                upper_seismogenic_depth=0.0,
                lower_seismogenic_depth=10.0,
                magnitude_scaling_relationship=
                openquake.hazardlib.scalerel.PeerMSR(),
                rupture_aspect_ratio=2,
                temporal_occurrence_model=PoissonTOM(1.),
                rupture_mesh_spacing=1.0,
                location=Point(10, 10)
            ),
            openquake.hazardlib.source.PointSource(
                source_id='point2', name='point2',
                tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST,
                mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD(
                    min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7]
                ),
                nodal_plane_distribution=openquake.hazardlib.pmf.PMF([
                    (1, openquake.hazardlib.geo.NodalPlane(strike=0,
                                                           dip=90,
                                                           rake=0.0)),
                ]),
                hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]),
                upper_seismogenic_depth=0.0,
                lower_seismogenic_depth=10.0,
                magnitude_scaling_relationship=
                openquake.hazardlib.scalerel.PeerMSR(),
                rupture_aspect_ratio=2,
                temporal_occurrence_model=PoissonTOM(1.),
                rupture_mesh_spacing=1.0,
                location=Point(10, 11)
            ),
        ]
        sites = [openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3),
                 openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3),
                 openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3),
                 openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3)]
        sitecol = openquake.hazardlib.site.SiteCollection(sites)

        from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997
        gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()}
        truncation_level = 1
        imts = {'PGA': [0.1, 0.5, 1.3]}

        from openquake.hazardlib.calc import filters
        source_site_filter = self.SitesCounterSourceSitesFilter(
            filters.SourceSitesFilter(30))
        calc_hazard_curves(
            sources, sitecol, imts, gsims, truncation_level,
            source_site_filter=source_site_filter)
        # there are two sources and four sites. The first source contains only
        # one rupture, the second source contains three ruptures.
        #
        # the first source has 'maximum projection radius' of 0.707 km
        # the second source has 'maximum projection radius' of 500.0 km
        #
        # the epicentral distances for source 1 are: [ 109.50558394,
        # 667.16955987,   66.71695599,   77.83644865]
        # the epicentral distances for source 2 are: [ 155.9412148 ,
        # 555.97463322,   44.47797066,   33.35847799]
        #
        # Considering that the source site filtering distance is set to 30 km,
        # for source 1, all sites have epicentral distance larger than
        # 0.707 + 30 km. This means that source 1 ('point 1') is not considered
        # in the calculation because too far.
        # for source 2, the 1st, 3rd and 4th sites have epicentral distances
        # smaller than 500.0 + 30 km. This means that source 2 ('point 2') is
        # considered in the calculation for site 1, 3, and 4.
        #
        # JB distances for rupture 1 in source 2 are: [ 155.43860273,
        #  555.26752644,   43.77086388,   32.65137121]
        # JB distances for rupture 2 in source 2 are: [ 150.98882575,
        #  548.90356541,   37.40690285,   26.28741018]
        # JB distances for rupture 3 in source 2 are: [ 109.50545819,
        # 55.97463322,    0.        ,    0.        ]
        #
        # Considering that the rupture site filtering distance is set to 30 km,
        # rupture 1 (magnitude 4) is not considered because too far, rupture 2
        # (magnitude 6) affect only the 4th site, rupture 3 (magnitude 8)
        # affect the 3rd and 4th sites.
        self.assertEqual(source_site_filter.counts,
                         [('point2', [1, 3, 4])])


'''Application loading'''

from pkgutil import iter_modules
from importlib import import_module
from pyviews.core.ioc import Scope, register_single, inject, wrap_with_scope
from tkviews.app import register_dependencies, register_binding_factory
from pykomcore import get_plugin_path
from pykomcore.command import Command
from pykom.logic.plugin import add_plugin
from pykom.logic.command import add_commands
from pykom.logic.api import add_api_commands, call_api
from pykom.logic.store import load_state
from pykom.view.binding import ScopedBindingFactory
from pykom import commands as core_commands
from pykom import api as core_api

def load_commands():
    add_commands('plugin', [
        Command(core_commands.show),
        Command(core_commands.hide)
    ])

def load_api():
    add_api_commands('plugin', [
        Command(core_api.show),
        Command(core_api.hide)
    ])

    add_api_commands('core', [
        Command(core_api.choice)
    ])

@inject('styles', 'commands', 'api_commands')
def load_plugins(styles=None, commands=None, api_commands=None):
    import plugins
    call_api_wrapped = wrap_with_scope(call_api)
    state = load_state()
    for module in iter_modules(plugins.__path__):
        plugin = import_module('plugins.{0}'.format(module.name))
        try:
            definition = plugin.get_definition()
        except AttributeError:
            print('plugin {0} does not implement get_definition'.format(module.name))
        else:
            with Scope(definition.name):
                register_dependencies()
                register_core_dependencies(definition, styles, call_api_wrapped)
                register_scoped_factory(definition.name)
                definition.register_dependencies()
                load_plugin_commands(definition, commands)
                load_plugin_api(definition, api_commands)
                definition.init(state=state.get(definition.name))
            add_plugin(definition)

def register_core_dependencies(definition, styles, call_api_wrapped):
    register_single('views_folder', get_plugin_path(definition.name))
    register_single('styles', styles)
    register_single('plugin_name', definition.name)
    register_single('call_api', call_api_wrapped)

def register_scoped_factory(scope_name):
    factory = ScopedBindingFactory(scope_name)
    register_binding_factory(factory)

def load_plugin_commands(definition, commands):
    plugin_commands = definition.get_commands()
    if plugin_commands:
        add_commands(definition.name, plugin_commands, commands=commands)

def load_plugin_api(definition, api_commands):
    plugin_api = definition.get_api_commands()
    if plugin_api:
        add_api_commands(definition.name, plugin_api, api_commands=api_commands)


"""
My script
"""
import os
os.environ["DJANGO_SETTINGS_MODULE"] = "django_ajax_demo.settings"

import django
django.setup()

from color_liker.models import Color

Color.objects.all()

colors = ["aqua", "black", "blue", "fuchsia",
	"gray", "green", "lime", "maroon", "navy", "olive", "orange",
	"purple", "red", "silver", "teal", "white", "yellow"]

Color.objects.bulk_create(Color(name=name) for name in colors)

Color.objects.all()


#-----------------------------------------------------------------------------------------------------
# In[2]:
#This is an alternative script to process diffusion data
#The key concept here from Diffusion_20_Octuber_Nipype is to register B0 to anatomical image
#Then use the transformation from resting state preprocessing to transfer the images to anatomical images
#The registration with FA_template was horrible
#This script was done after restripping the skull to remove extra parts of the skull
#The overlap with the VBM template is quite good, yet not so satifactory
#So, here I am trying with the WAX FA template downsized to 2mm
from nipype import config
cfg = dict(execution={'remove_unnecessary_outputs': False})
config.update_config(cfg)

import nipype.interfaces.fsl as fsl
import nipype.interfaces.afni as afni
import nipype.interfaces.ants as ants
# import nipype.interfaces.spm as spm
import nipype.interfaces.utility as utility
from nipype.interfaces.utility import IdentityInterface, Function
from os.path import join as opj
from nipype.interfaces.io import SelectFiles, DataSink
from nipype.pipeline.engine import Workflow, Node, MapNode

import numpy as np
import matplotlib.pyplot as plt

#-----------------------------------------------------------------------------------------------------
# In[2]:

experiment_dir = '/home/in/aeed/TBSS'

map_list=  [    'CHARMED_AD' ,'CHARMED_FA'  ,'CHARMED_FR' , 'CHARMED_IAD', 'CHARMED_MD',  'CHARMED_RD',

                'Diffusion_20_AD' , 'Diffusion_20_FA',  'Diffusion_20_MD' , 'Diffusion_20_RD',

                'Kurtosis_AD' , 'Kurtosis_AWF' , 'Kurtosis_MD' , 'Kurtosis_RD' , 'Kurtosis_TORT',
                'Kurtosis_AK' , 'Kurtosis_FA' ,  'Kurtosis_MK' , 'Kurtosis_RK',

                'NODDI_FICVF' , 'NODDI_ODI'
]

# map_list = ['229', '230', '365', '274']

output_dir  = 'DTI_TBSS_Wax'
working_dir = 'DTI_TBSS_workingdir_Wax_Template'

DTI_TBSS_Wax = Workflow (name = 'DTI_TBSS_Wax')
DTI_TBSS_Wax.base_dir = opj(experiment_dir, working_dir)

#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
# In[3]:

# Infosource - a function free node to iterate over the list of subject names
infosource = Node(IdentityInterface(fields=['map_id']),
                  name="infosource")
infosource.iterables = [('map_id', map_list)]

#-----------------------------------------------------------------------------------------------------
# In[4]:

templates = {

             'all_skeleton'             : 'Waxholm_Template/*/{map_id}/All_*_skeletonised.nii.gz',
             'skeleton_mask'            : 'Waxholm_Template/*/{map_id}/mean_FA_skeleton_mask.nii.gz',

             'all_image'                : 'Waxholm_Template/*/{map_id}/All_{map_id}_WAX.nii.gz',
             'mean_FA'               : 'Waxholm_Template/*/{map_id}/mean_FA.nii.gz',

 }

selectfiles = Node(SelectFiles(templates,
                               base_directory=experiment_dir),
                   name="selectfiles")
#-----------------------------------------------------------------------------------------------------
# In[5]:

datasink = Node(DataSink(), name = 'datasink')
datasink.inputs.container = output_dir
datasink.inputs.base_directory = experiment_dir

substitutions = [('_map_id_', ' ')]

datasink.inputs.substitutions = substitutions

#-----------------------------------------------------------------------------------------------------
#Design with two contrasts only

design = '/home/in/aeed/TBSS/Design_TBSS.mat'
contrast = '/home/in/aeed/TBSS/Design_TBSS.con'

#-----------------------------------------------------------------------------------------------------
#randomise on the skeletonised data
randomise_tbss = Node(fsl.Randomise(), name = 'randomise_tbss')
randomise_tbss.inputs.design_mat = design
randomise_tbss.inputs.tcon = contrast
randomise_tbss.inputs.num_perm = 10000
randomise_tbss.inputs.tfce2D = True
randomise_tbss.inputs.vox_p_values = True
randomise_tbss.inputs.base_name = 'TBSS_'

#-----------------------------------------------------------------------------------------------------
#smoothing the images
def nilearn_smoothing(image):
    import nilearn
    from nilearn.image import smooth_img

    import numpy as np
    import os

    kernel = [4.3,4.3,16]

    smoothed_img = smooth_img(image, kernel)
    smoothed_img.to_filename('smoothed_all.nii.gz')

    smoothed_output = os.path.abspath('smoothed_all.nii.gz')
    return  smoothed_output

nilearn_smoothing = Node(name = 'nilearn_smoothing',
                  interface = Function(input_names = ['image'],
                               output_names = ['smoothed_output'],
                  function = nilearn_smoothing))

#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#mask only FA values > 0.2 to gurantee it is WM
thresh_FA = Node(fsl.Threshold(), name = 'thresh_FA')
thresh_FA.inputs.thresh = 0.2

#-----------------------------------------------------------------------------------------------------
#binarize this mask
binarize_FA = Node(fsl.UnaryMaths(), name = 'binarize_FA')
binarize_FA.inputs.operation = 'bin'
binarize_FA.inputs.output_datatype = 'char'

#-----------------------------------------------------------------------------------------------------
#randomise on the smoothed all images
randomise_VBA = Node(fsl.Randomise(), name = 'randomise_vba')
randomise_VBA.inputs.design_mat = design
randomise_VBA.inputs.tcon = contrast
randomise_VBA.inputs.num_perm = 10000
randomise_VBA.inputs.tfce = True
randomise_VBA.inputs.vox_p_values = True
randomise_VBA.inputs.base_name = 'VBA_'

#-----------------------------------------------------------------------------------------------------
DTI_TBSS_Wax.connect ([

      (infosource, selectfiles,[('map_id','map_id')]),

      (selectfiles, randomise_tbss, [('all_skeleton','in_file')]),
      (selectfiles, randomise_tbss, [('skeleton_mask','mask')]),

      (selectfiles, nilearn_smoothing, [('all_image','image')]),

      (nilearn_smoothing, randomise_VBA, [('smoothed_output','in_file')]),

     (selectfiles, thresh_FA, [('mean_FA','in_file')]),
     (thresh_FA, binarize_FA, [('out_file','in_file')]),
     (binarize_FA, randomise_VBA, [('out_file','mask')])

  ])

DTI_TBSS_Wax.write_graph(graph2use='flat')
DTI_TBSS_Wax.run(plugin='SLURM')
# DTI_workflow.run(plugin='SLURM')


# -*- coding: utf-8 -*-
from __future__ import unicode_literals, division, print_function, absolute_import
from . import TestCase as BaseTestCase, skipIf, SkipTest
import os
import codecs
import hashlib
import json

import testdata

from endpoints.client import HTTPClient
from endpoints.interface.wsgi.client import WSGIServer

# def setUpModule():
#     if requests is None:
#         raise SkipTest("Skipping (u)wsgi server tests because no requests module")

###############################################################################
# Custom clients
###############################################################################
class WSGIClient(object):

    client_class = HTTPClient
    server_class = WSGIServer
    server_script_name = "endpoints_testserver_script.py"

    def __init__(self, controller_prefix, module_body, config_module_body='', host=''):
        self.cwd = testdata.create_dir()
        self.client = self.client_class(host)

        # create the controller module
        self.module_path = testdata.create_module(
            controller_prefix,
            module_body,
            self.cwd
        )

        # now create the server script
        self.script_path = testdata.create_file(
            self.server_script_name,
            os.linesep.join([
                "import os",
                "import sys",
                "import logging",
                "logging.basicConfig(",
                "    format=\"[%(levelname).1s] %(message)s\",",
                "    level=logging.DEBUG,",
                "    stream=sys.stdout",
                ")",
                #"sys.path.append('{}')".format(os.path.dirname(os.path.realpath(inspect.getsourcefile(endpoints)))),
                "sys.path.append('{}')".format(os.path.realpath(os.curdir)),
                "",
                #"from endpoints.interface.wsgi import *",
                "from endpoints.interface.wsgi import Application, Server",
                ""
                "os.environ['ENDPOINTS_PREFIX'] = '{}'".format(controller_prefix),
                "",
                "##############################################################",
                os.linesep.join(config_module_body),
                "##############################################################",
                #os.linesep.join(self.get_script_body()),
                "#from wsgiref.validate import validator",
                "#application = validator(Application())",
                "application = Application()",
                ""
            ]),
            self.cwd
        )

        # server
        self.server = self.server_class(
            controller_prefix=controller_prefix,
            host=host,
            wsgifile=self.script_path
        )
        self.server.cwd = self.cwd
        self.server.start()

    @classmethod
    def kill(cls):
        cls.server_class(controller_prefix="", wsgifile=cls.server_script_name).kill()

    def __getattr__(self, key):
        try:
            m = getattr(self.client, key)
        except AttributeError:
            m = getattr(self.server, key)

        return m

###############################################################################
# Actual tests
###############################################################################
class TestCase(BaseTestCase):

    client_class = None

    def setUp(self):
        self.client_class.kill()

    def tearDown(self):
        self.client_class.kill()

    def create_client(self, *args, **kwargs):
        kwargs.setdefault("host", self.get_host())
        return self.client_class(*args, **kwargs)

class WSGITest(TestCase):
    client_class = WSGIClient

    def test_request_url(self):
        """make sure request url gets controller_path correctly"""
        controller_prefix = "requesturl.controller"
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "class Requrl(Controller):",
            "    def GET(self):",
            "        return self.request.url.controller()",
            "",
        ])

        r = c.get('/requrl')
        self.assertTrue("/requrl" in r._body)

    def test_list_param_decorator(self):
        controller_prefix = "lpdcontroller"
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller, decorators",
            "class Listparamdec(Controller):",
            "    @decorators.param('user_ids', 'user_ids[]', type=int, action='append_list')",
            "    def GET(self, **kwargs):",
            "        return int(''.join(map(str, kwargs['user_ids'])))",
            ""
        ])

        r = c.get('/listparamdec?user_ids[]=12&user_ids[]=34')
        self.assertEqual("1234", r.body)

    def test_post_file(self):
        filepath = testdata.create_file("filename.txt", "this is a text file to upload")
        controller_prefix = 'wsgi.post_file'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "class Default(Controller):",
            "    def POST(self, *args, **kwargs):",
            "        return kwargs['file'].filename",
            "",
        ])

        r = c.post_file('/', {"foo": "bar", "baz": "che"}, {"file": filepath})
        self.assertEqual(200, r.code)
        self.assertTrue("filename.txt" in r.body)

    def test_post_file_with_param(self):
        """make sure specifying a param for the file upload works as expected"""
        filepath = testdata.create_file("post_file_with_param.txt", "post_file_with_param")
        controller_prefix = 'wsgi.post_file_with_param'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller, decorators",
            "class Default(Controller):",
            "    @decorators.param('file')",
            "    def POST(self, *args, **kwargs):",
            "        return kwargs['file'].filename",
            "",
        ])

        r = c.post_file('/', {"foo": "bar", "baz": "che"}, {"file": filepath})
        self.assertEqual(200, r.code)
        self.assertTrue("post_file_with_param.txt" in r.body)

    def test_post_basic(self):
        controller_prefix = 'wsgi.post'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "from endpoints.decorators import version",
            "class Default(Controller):",
            "    def GET(*args, **kwargs): pass",
            "    @version('', 'v1')",
            "    def POST_v1(*args, **kwargs): pass",
            "    @version('v2')",
            "    def POST_v2(*args, **kwargs): return kwargs['foo']",
            "",
        ])

        r = c.post(
            '/',
            {"foo": "bar"},
            headers={
                "content-type": "application/json",
                "Accept": "application/json;version=v2"
            }
        )
        self.assertEqual(200, r.code)
        self.assertEqual('"bar"', r.body)

        r = c.post('/', {})
        self.assertEqual(204, r.code)

        r = c.post('/', None, headers={"content-type": "application/json"})
        self.assertEqual(204, r.code)

        r = c.post('/', None)
        self.assertEqual(204, r.code)

        r = c.post('/', {}, headers={"content-type": "application/json"})
        self.assertEqual(204, r.code)

        r = c.post('/', {"foo": "bar"}, headers={"Accept": "application/json;version=v2"})
        self.assertEqual(200, r.code)
        self.assertEqual('"bar"', r.body)

    def test_post_ioerror(self):
        """turns out this is pretty common, a client will make a request and disappear,
        but now that we lazy load the body these errors are showing up in our logs where
        before they were silent because they failed, causing the process to be restarted,
        before they ever made it really into our logging system"""

        controller_prefix = 'wsgi.post_ioerror'
        c = self.create_client(
            controller_prefix,
            [
                "from endpoints import Controller",
                "",
                "class Default(Controller):",
                "    def POST(*args, **kwargs):",
                "        pass",
                "",
            ],
            config_module_body=[
                "from endpoints import Request as EReq",
                "",
                "class Request(EReq):",
                "    @property",
                "    def body_kwargs(self):",
                "        raise IOError('timeout during read(0) on wsgi.input')",
                "",
                "Application.request_class = Request",
                "",
            ],
        )

        r = c.post(
            '/',
            {"foo": "bar"},
            headers={
                "content-type": "application/json",
            }
        )
        self.assertEqual(408, r.code)

    def test_405_request(self):
        controller_prefix = 'request_405'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "class Foo(Controller):",
            "    def GET(self): pass",
            "",
        ])

        r = c.get('/foo/bar/baz?che=1&boo=2')
        self.assertEqual(405, r.code)

    def test_response_headers(self):
        controller_prefix = 'resp_headers.resp'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "class Default(Controller):",
            "    def GET(self):",
            "        self.response.set_header('FOO_BAR', 'check')",
            "",
        ])

        r = c.get('/')
        self.assertEqual(204, r.code)
        self.assertTrue("foo-bar" in r.headers)

    def test_file_stream(self):
        content = "this is a text file to stream"
        filepath = testdata.create_file("filename.txt", content)
        controller_prefix = 'wsgi.post_file'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "class Default(Controller):",
            "    def GET(self, *args, **kwargs):",
            "        f = open('{}')".format(filepath),
            "        self.response.set_header('content-type', 'text/plain')",
            "        return f",
            "",
        ])

        r = c.get('/')
        self.assertEqual(200, r.code)
        self.assertEqual(content, r.body)
        #self.assertTrue(r.body)

    def test_generators(self):
        controller_prefix = 'wsgi_generator'
        c = self.create_client(controller_prefix, [
            "from endpoints import Controller",
            "class Default(Controller):",
            "    def GET(self):",
            "        for x in range(100):",
            "            yield x",
        ])

        r = c.get('/')
        content = list(range(100))
        self.assertEqual(200, r.code)
        self.assertEqual(content, r._body)

###############################################################################
# Client tests
###############################################################################
class ClientTestCase(TestCase):
    server = None
    server_class = WSGIServer
    client_class = HTTPClient

    def setUp(self):
        if self.server:
            self.server.stop()

    def tearDown(self):
        if self.server:
            self.server.stop()

    def create_server(self, controller_prefix, contents, **kwargs):
        tdm = testdata.create_module(controller_prefix, contents)
        server = self.server_class(controller_prefix, host=self.get_host(), **kwargs)
        server.cwd = tdm.basedir
        server.stop()
        self.server = server
        self.server.start()
        return server

    def create_client(self, **kwargs):
        client = self.client_class(self.get_host(), **kwargs)
        return client

class HTTPClientTest(ClientTestCase):
    def test_get_fetch_url(self):
        c = self.create_client()

        uri = "http://foo.com"
        url = c.get_fetch_url(uri)
        self.assertEqual(uri, url)

        uri = "/foo/bar"
        url = c.get_fetch_url(uri)
        self.assertEqual("{}{}".format(c.get_fetch_host(), uri), url)

        url = c.get_fetch_url(["foo", "bar"])
        self.assertEqual("{}{}".format(c.get_fetch_host(), "/foo/bar"), url)

    def test_post_file(self):
        filepath = testdata.create_file("json_post_file.txt", "json post file")
        controller_prefix = 'jsonclient.controller'
        server = self.create_server(controller_prefix, [
            "from endpoints import Controller, decorators",
            "class Default(Controller):",
            "    @decorators.param('file')",
            "    def POST(self, *args, **kwargs):",
            "        return dict(body=kwargs['file'].filename)",
            "",
        ])
        c = self.create_client()
        r = c.post_file('/', {"foo": "bar", "baz": "che"}, {"file": filepath})
        self.assertEqual(200, r.code)
        self.assertEqual("json_post_file.txt", r._body["body"])

    def test_basic_auth(self):
        c = self.create_client()
        c.basic_auth("foo", "bar")
        self.assertRegexpMatches(c.headers["authorization"], "Basic\s+[a-zA-Z0-9=]+")

class WSGIServerTest(ClientTestCase):
    def test_start(self):
        controller_prefix = 'wsgiserverstart.controller'
        server = self.create_server(controller_prefix, [
            "from endpoints import Controller",
            "class Default(Controller):",
            "    def GET(self): pass",
            "",
        ])

    def test_wsgifile(self):
        wsgifile = testdata.create_file("wsgiserverapp.py", [
            "import os",
            "from endpoints.interface.wsgi import Application",
            "os.environ['WSGI_TESTING'] = 'foo bar'",
            "application = Application()",
            "",
        ])
        controller_prefix = 'wsgiservercon.controller'
        server = self.create_server(controller_prefix, [
            "import os",
            "from endpoints import Controller, decorators",
            "class Default(Controller):",
            "    def GET(self):",
            "        return os.environ['WSGI_TESTING']",
            "",
        ], wsgifile=wsgifile)
        c = self.create_client()

        r = c.get("/")
        self.assertEqual(200, r.code)
        self.assertEqual("foo bar", r._body)


"""Device handler for centralite 3460L."""
# pylint disable=C0103
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import (
    Basic,
    Identify,
    OnOff,
    OnOffConfiguration,
    Ota,
    PollControl,
)
from zigpy.zcl.clusters.homeautomation import Diagnostic
from zigpy.zcl.clusters.measurement import TemperatureMeasurement

from zhaquirks import PowerConfigurationCluster
from zhaquirks.centralite import CENTRALITE
from zhaquirks.const import (
    BUTTON_1,
    COMMAND,
    COMMAND_OFF,
    COMMAND_ON,
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
    SHORT_PRESS,
    SHORT_RELEASE,
)

class CustomPowerConfigurationCluster(PowerConfigurationCluster):
    """Custom PowerConfigurationCluster."""

    cluster_id = PowerConfigurationCluster.cluster_id
    MIN_VOLTS = 2.1
    MAX_VOLTS = 3.0

class CentraLite3460L(CustomDevice):
    """Custom device representing centralite 3460L."""

    signature = {
        #  <SimpleDescriptor endpoint=1 profile=260 device_type=6
        #  device_version=0
        #  input_clusters=[0, 1, 3, 7, 32, 1026, 2821]
        #  output_clusters=[3, 6, 25]>
        MODELS_INFO: [(CENTRALITE, "3460-L")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.REMOTE_CONTROL,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    CustomPowerConfigurationCluster.cluster_id,
                    Identify.cluster_id,
                    OnOffConfiguration.cluster_id,
                    PollControl.cluster_id,
                    TemperatureMeasurement.cluster_id,
                    Diagnostic.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    OnOff.cluster_id,
                    Ota.cluster_id,
                ],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    CustomPowerConfigurationCluster,
                    Identify.cluster_id,
                    OnOffConfiguration.cluster_id,
                    PollControl.cluster_id,
                    TemperatureMeasurement.cluster_id,
                    Diagnostic.cluster_id,
                ],
                OUTPUT_CLUSTERS: [
                    Identify.cluster_id,
                    OnOff.cluster_id,
                    Ota.cluster_id,
                ],
            }
        }
    }

    device_automation_triggers = {
        (SHORT_PRESS, BUTTON_1): {COMMAND: COMMAND_ON},
        (SHORT_RELEASE, BUTTON_1): {COMMAND: COMMAND_OFF},
    }


import asyncio
from wdom.document import get_document
from wdom.server import start_server, stop_server

if __name__ == '__main__':
    document = get_document()
    h1 = document.createElement('h1')
    h1.textContent = 'Hello, WDOM'
    document.body.appendChild(h1)

    start_server()
    try:
        asyncio.get_event_loop().run_forever()
    except KeyboardInterrupt:
        stop_server()


#!/usr/bin/env python

'''

This python file runs a ROS-node of name drone_control which holds the position of e-Drone on the given dummy.
This node publishes and subsribes the following topics:

		PUBLICATIONS			SUBSCRIPTIONS
		/drone_command			/whycon/poses
		/alt_error				/pid_tuning_altitude
		/pitch_error			/pid_tuning_pitch
		/roll_error				/pid_tuning_roll
		/yaw_error				/pid_tuning_yaw
								/drone_yaw

Rather than using different variables, use list. eg : self.setpoint = [1,2,3,4], where index corresponds to x,y,z and yaw_value...rather than defining self.x_setpoint = 1, self.y_setpoint = 2
CODE MODULARITY AND TECHNIQUES MENTIONED LIKE THIS WILL HELP YOU GAINING MORE MARKS WHILE CODE EVALUATION.
'''

# Importing the required libraries

from plutodrone.srv import *
from plutodrone.msg import *
from geometry_msgs.msg import PoseArray
from std_msgs.msg import Int16
from std_msgs.msg import Int32
from std_msgs.msg import Int64
from std_msgs.msg import Bool
from std_msgs.msg import Float64
from pid_tune.msg import PidTune
import rospy
import time

class Plutodrone():
    """docstring for Plutodrone"""

    def __init__(self):

        # initializing ros node with name drone_control
        rospy.init_node('drone_control')

        # [x,y,z,yaw_value]
        self.drone_position = [0.0, 0.0, 0.0, 0.0]

        self.initial_waypoint = [-4.85, -1.36, 25.0, 280]

        # initially setpoint and destination are both initial_waypoint
        self.destination = [-4.85, -1.36, 25.0, 280]
        self.setpoint = [-4.85, -1.36, 25.0, 280]

        # counter to loop thrrough the points in the path
        self.count = 0

        # Declaring a cmd of message type PlutoMsg and initializing values
        self.cmd = PlutoMsg()
        self.cmd.rcRoll = 1500
        self.cmd.rcPitch = 1500
        self.cmd.rcYaw = 1500
        self.cmd.rcThrottle = 1000
        self.cmd.rcAUX1 = 1500
        self.cmd.rcAUX2 = 1500
        self.cmd.rcAUX3 = 1500
        self.cmd.rcAUX4 = 1000
        # self.cmd.plutoIndex = 0

        self.Kp = [10, 10, 50, 10]
        self.Ki = [1, 1, 4, 0]
        self.Kd = [20, 20, 10, 5]

        # -----------------------Add other required variables for pid here ----------------------------------------------

        self.dis = [0, 0, 0, 0]  # distance between drone and destination
        self.dis_set = [0, 0, 0, 0]  # distance between drone and set point

        # PID variables
        self.error = [0, 0, 0, 0]
        self.d_error = [0, 0, 0, 0]
        self.last_time = time.time()

        self.output = [0, 0, 0, 0]
        self.error_sum = [0, 0, 0, 0]
        self.last_error = [0, 0, 0, 0]
        self.max_values = [175, 175, 300, 90]
        self.min_values = [-175, -175, -300, -90]
        self.path = PoseArray()

        self.path_retrieved = False  # bool value to check if new path has been received
        # to keep a track of the goals reached to disarm thre drone when waypoint is reached
        self.goals_reached = 0

        self.sample_time = 0.05  # in seconds

        # Publishing /drone_command, /alt_error, /pitch_error, /roll_error, /yaw_error
        self.command_pub = rospy.Publisher(
            '/drone_command', PlutoMsg, queue_size=1)
        # ------------------------Add other ROS Publishers here-----------------------------------------------------
        self.alt_error_pub = rospy.Publisher(
            '/alt_error', Float64, queue_size=1)
        self.pitch_error_pub = rospy.Publisher(
            '/pitch_error', Float64, queue_size=1)
        self.roll_error_pub = rospy.Publisher(
            '/roll_error', Float64, queue_size=1)
        self.yaw_error_pub = rospy.Publisher(
            '/yaw_error', Float64, queue_size=1)
        self.zero_line_pub = rospy.Publisher(
            '/zero_line', Float64, queue_size=1)
        self.path_req_pub = rospy.Publisher(
            '/path_plan', Bool, queue_size=10)

        # -----------------------------------------------------------------------------------------------------------

        # Subscribing to /whycon/poses, /drone_yaw, /pid_tuning_altitude, /pid_tuning_pitch, pid_tuning_roll
        rospy.Subscriber('whycon/poses', PoseArray, self.whycon_callback)
        rospy.Subscriber('/drone_yaw', Int32, self.drone_yaw_callback)

        rospy.Subscriber('/vrep/waypoints', PoseArray, self.update)
        # ------------------------------------------------------------------------------------------------------------

        self.arm()

    # Disarming condition of the drone

    def disarm(self):
        self.cmd.rcThrottle = 1300
        self.cmd.rcAUX4 = 1200
        self.command_pub.publish(self.cmd)
        rospy.sleep(1)

    # Arming condition of the drone

    def arm(self):
        self.disarm()
        self.cmd.rcRoll = 1500
        self.cmd.rcYaw = 1500
        self.cmd.rcPitch = 1500
        self.cmd.rcThrottle = 1000
        self.cmd.rcAUX4 = 1500
        self.command_pub.publish(self.cmd)
        rospy.sleep(1)

    def decrease_height(self):
        self.cmd.rcRoll = 1500
        self.cmd.rcYaw = 1500
        self.cmd.rcPitch = 1500
        self.cmd.rcThrottle = 1400
        self.command_pub.publish(self.cmd)

    # Whycon callback function
    # The function gets executed each time when /whycon node publishes /whycon/poses

    def whycon_callback(self, msg):
        self.drone_position[0] = msg.poses[0].position.x

        # --------------------Set the remaining co-ordinates of the drone from msg----------------------------------------------
        self.drone_position[1] = msg.poses[0].position.y
        self.drone_position[2] = msg.poses[0].position.z
        # ---------------------------------------------------------------------------------------------------------------

    # Callback function for /pid_tuning_altitude
    # This function gets executed each time when /tune_pid publishes /pid_tuning_altitude

    # ----------------------------Define callback function like altitide_set_pid to tune pitch, roll and yaw as well--------------
    def drone_yaw_callback(self, msg):
        self.drone_position[3] = msg.data

    def update(self, msg):
        # setting counter to 0 to traverse the points
        self.count = 0

        # setting destination to the last point of the path
        self.destination = [msg.poses[39].position.x,
                            msg.poses[39].position.y, msg.poses[39].position.z, 0]

        # setting set point to the first point of the path
        self.setpoint = [msg.poses[self.count].position.x,
                         msg.poses[self.count].position.y, msg.poses[self.count].position.z, 0]

        # storing the pose array to loop the points of the path
        self.path = msg

        # bool value confirm that path has been received
        self.path_retrieved = True

    # ----------------------------------------------------------------------------------------------------------------------

    def pid(self):

        self.now = time.time()
        self.time_change = self.now - self.last_time
        if(self.time_change >= self.sample_time):
            for i in range(4):
                self.error[i] = self.setpoint[i] - self.drone_position[i]

                # if self.error[3] > 180:
                #     self.error[3] = self.error[3] - 360

                self.error_sum[i] += self.error[i]*self.time_change
                if (self.error_sum[i] > self.max_values[i]):
                    self.error_sum[i] = self.max_values[i]
                elif (self.error_sum[i] < self.min_values[i]):
                    self.error_sum[i] = self.min_values[i]

                self.d_error[i] = (
                    self.error[i]-self.last_error[i])/self.time_change

                self.output[i] = self.Kp[i]*self.error[i] +\
                    self.Ki[i] * self.error_sum[i] + \
                    self.Kd[i] * self.d_error[i]

                if (self.output[i] > self.max_values[i]):
                    self.output[i] = self.max_values[i]
                elif (self.output[i] < self.min_values[i]):
                    self.output[i] = self.min_values[i]
                self.last_error[i] = self.error[i]

                # determining the error between drone and destination
                self.dis[i] = self.destination[i] - self.drone_position[i]

                # determining the error between drone and set_point
                self.dis_set[i] = self.setpoint[i] - self.drone_position[i]

            self.last_time = self.now

            self.cmd.rcPitch = 1500 - self.output[0]
            self.cmd.rcRoll = 1500 - self.output[1]
            self.cmd.rcThrottle = 1500 - self.output[2]
            self.cmd.rcYaw = 1500 + self.output[3]

            if (all(-0.75 < i < 0.75 for i in self.dis[:3])):  # if goal is reached
                self.goals_reached += 1
                if (self.goals_reached == 4): #landing the drone
                    self.decrease_height()  # back to initial_waypoint
                    rospy.sleep(1.5)
                    self.disarm()
                    # resetting destination until the new path is received and destination is updated
                self.destination = [0, 0, 0, 0]
                self.path_req_pub.publish(True)  # requesting new path
                # setting to false so that program waits at the same setpoint until new path is received
                self.path_retrieved = False
            else:
                self.path_req_pub.publish(False)

            if (all(-0.75 < i < 0.75 for i in self.dis_set[:3]) and self.path_retrieved == True):
                if(self.count < 39):  # to prevent counter from going out of index while waiting for a new path
                    self.count += 1
                    print(self.count)
                # looping through the points in the path
                self.setpoint = [self.path.poses[self.count].position.x,
                                 self.path.poses[self.count].position.y, self.path.poses[self.count].position.z, 0]
                rospy.sleep(0.005)

            # publishing zero line, errors and the drone command
            self.zero_line_pub.publish(0.0)
            self.pitch_error_pub.publish(self.error[0])
            self.roll_error_pub.publish(self.error[1])
            self.alt_error_pub.publish(self.error[2])
            self.yaw_error_pub.publish(self.error[3])
            self.command_pub.publish(self.cmd)

if __name__ == '__main__':

    drone = Plutodrone()

    while not rospy.is_shutdown():
        drone.pid()


"""
Same Number of Unique Elements
Write a function that returns True if two lists have the same number of unique elements, and False otherwise.

To illustrate:

lst1 = [1, 3, 4, 4, 4]
lst2 = [2, 5, 7]
In lst1, the number 4 appears three times, which means it contains three unique elements: [1, 3, 4]. Since lst1 and lst2 both contain the same number of unique elements, this example would return True.

Examples
same([1, 3, 4, 4, 4], [2, 5, 7]) ➞ True

same([9, 8, 7, 6], [4, 4, 3, 1]) ➞ False

same([2], [3, 3, 3, 3, 3]) ➞ True

"""

"""
Solution 1
"""

def same(a1, a2):
  return len(set(a1)) == len(set(a2))

"""
Solution 2
"""

def same(a1, a2):
	a1 = set(a1)
	a2 = set(a2)
	return len(a1) == len(a2)

"""
Solution 3
"""

def same(a1, a2):
	uniqueA1 = []
	uniqueA2 = []

	for item in a1:
		if item not in uniqueA1:
			uniqueA1.append(item)
	for item in a2:
		if item not in uniqueA2:
			uniqueA2.append(item)
	return len(uniqueA1) == len(uniqueA2)

+1500 Python Challenges/V Easy/Same Number of Unique Elements.py


import sys
sys.path.append("..")
import numpy as np
from load_data import *
from activation_code_methods import *
from sklearn.cluster import KMeans, SpectralClustering
from sklearn.neighbors import KNeighborsClassifier
from sklearn.multiclass import OneVsOneClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.mixture import GaussianMixture as GMM
from keras.models import load_model
from adult import Adult
import numpy as np
from keras.utils import to_categorical
from sklearn.metrics.cluster import contingency_matrix
from scipy.optimize import linear_sum_assignment

def compute_clustering_accuracy(cluster_result, label, n_cluster=2):
    partition_matrix = contingency_matrix(label, cluster_result)
    _, label_mapping = linear_sum_assignment(-partition_matrix)
    for i in range(n_cluster):
        cluster_result[cluster_result == label_mapping[i]] = n_cluster + i
    cluster_result = cluster_result - n_cluster
    smstr = np.nonzero(label - cluster_result)
    clustering_accuracy = 1 - np.shape(smstr[0])[0] / label.shape[0]
    match_index = np.array([1 if label[i]==cluster_result[i] else 0 for i in range(label.shape[0])])
    return clustering_accuracy

repeat = 5
begin_repeat = 1
save_path = '/public/data1/users/leishiye/neural_code/results/sample_size/result_list_sample_size_'
load_path = '/public/data1/users/leishiye/neural_code/models/sample_size/model_sample_size_'
depth = 1

dataset = 'adult'

num_classes = 2

n_clusters = num_classes

width_list = [60, 80, 100]
sample_size_list = [100, 200, 500, 1000, 2000, 5000, 10000, 15000, 20000]
# Load data
##########################################
trainset = Adult(root='/public/data1/users/leishiye/neural_code/datasets', train=True)
x_train = trainset.x / trainset.x.max(axis=0)
y_train = to_categorical(trainset.y)

num_train = int(x_train.shape[0] * 0.7)
num_test = x_train.shape[0] - num_train
mask = list(range(num_train, num_train+num_test))
x_test = x_train[mask]
y_test = y_train[mask]

mask = list(range(num_train))
x_train = x_train[mask]
y_train = y_train[mask]

test_label_scalar = np.argmax(y_test, axis=1).squeeze()

input_shape = x_train.shape[1:]

print('dataset: ' + dataset)
print('depth: ' + str(depth))

for iter in np.linspace(begin_repeat-1, begin_repeat + repeat-2, repeat).astype('int'):
    print('repeat: ' + str(iter + 1))
    for num_neuron in width_list:
        print('layer width: ' + str(num_neuron))
        result_list = []
        for sample_size in sample_size_list:
            print('sample size: ' + str(sample_size))

            # training set
            x_sub_train = x_train[:sample_size]
            y_sub_train = y_train[:sample_size]
            train_label_scalar = np.argmax(y_sub_train, axis=1).squeeze()

            mlp = load_model(load_path + str(sample_size) + '_width_' + str(num_neuron) + '_' +
                             dataset + '_depth_' + str(depth) + '_iter' + str(iter + 1) + '.h5')

            # evaluation
            train_score = mlp.evaluate(x_sub_train, y_sub_train, verbose=0)
            print("train loss: ", train_score[0])
            print("train accuracy: ", train_score[1])
            test_score = mlp.evaluate(x_test, y_test, verbose=0)
            print("test loss: ", test_score[0])
            print("test accuracy: ", test_score[1])

            # compute activation code
            train_activation_codes, test_activation_codes = compute_activation_code_for_mlp(x_sub_train, x_test, model=mlp)

            # compute redundancy ratio
            test_redundancy_ratio = (test_activation_codes.shape[0] - np.unique(test_activation_codes, axis=0).shape[
                0]) / x_test.shape[0]
            train_redundancy_ratio = (train_activation_codes.shape[0] - np.unique(train_activation_codes, axis=0).shape[
                0]) / x_sub_train.shape[0]

            print("train redundancy ratio: " + str(train_redundancy_ratio))
            print("test redundancy ratio: " + str(test_redundancy_ratio))

            # compute clustering accuracy with kmeans
            train_cluster_result = KMeans(n_clusters=n_clusters, random_state=9).fit_predict(train_activation_codes)
            train_clustering_accuracy_kmeans = compute_clustering_accuracy(train_cluster_result, train_label_scalar)

            test_cluster_result = KMeans(n_clusters=n_clusters, random_state=9).fit_predict(test_activation_codes)
            test_clustering_accuracy_kmeans = compute_clustering_accuracy(test_cluster_result, test_label_scalar)

            print("train_clustering_accuracy_kmeans: " + str(train_clustering_accuracy_kmeans))
            print("test_clustering_accuracy_kmeans: " + str(test_clustering_accuracy_kmeans))

            # compute clusterisng accuracy with KNN
            neigh = KNeighborsClassifier(n_neighbors=9, metric='hamming').fit(train_activation_codes,
                                                                              train_label_scalar)
            knn_pred_result = neigh.predict(test_activation_codes)
            smstr = np.nonzero(test_label_scalar - knn_pred_result)
            knn_accuracy = 1 - np.shape(smstr[0])[0] / test_label_scalar.shape[0]

            print("knn_accuracy: " + str(knn_accuracy))

            # compute multiclass logisticRegression
            logistic_classifier = OneVsOneClassifier(LogisticRegression(solver='liblinear', random_state=9)).fit(train_activation_codes,
                                                                                train_label_scalar)
            logistic_pred_result = logistic_classifier.predict(test_activation_codes)
            smstr = np.nonzero(test_label_scalar - logistic_pred_result)
            logistic_accuracy = 1 - np.shape(smstr[0])[0] / test_label_scalar.shape[0]

            print("logistic_accuracy: " + str(logistic_accuracy))

            result_list.extend([train_score[0], train_score[1], test_score[0], test_score[1], train_redundancy_ratio,
                                test_redundancy_ratio,
                                train_clustering_accuracy_kmeans, test_clustering_accuracy_kmeans, knn_accuracy,
                                logistic_accuracy])
        # save
        save_list(result_list, save_path + dataset + '_depth_' + str(depth) + '_width_' + str(num_neuron) + '_iter' + str(iter + 1))


from copy import copy

class Plateau:
    def __init__(self, nb_cases, largeur_muret):
        self.nb_cases = nb_cases
        self.largeur_muret = largeur_muret
        self.cote = (nb_cases - 1) * 2  # 16 pour 9 cases de large
        self.coords_murets = []  # de type (1, 1) , coordonnées impaires de 1 à 15
        self.joueurs = []  # append lors de l'initialisation d'un joueur

    def __contains__(self, value):
        return value in self.coords_murets

    def __copy__(self):
        copie = Plateau(self.nb_cases, self.largeur_muret)
        copie.coords_murets = self.coords_murets[:]
        copie.joueurs = self.joueurs
        return copie

    def __add__(self, coord):
        """return another Plateau + coord"""
        plateau_test = copy(self)
        plateau_test += coord
        return plateau_test

    def __iadd__(self, coords):
        """  += """
        self.coords_murets.append(coords)
        return self

    def ajouter_muret(self, coord):
        # coords = (x, y, position)

        if coord not in self:
            x, y = coord
            plateau_test = copy(self)
            for supp in range(self.largeur_muret * 2 - 1):
                if x % 2:  # muret vertical
                    coord_test = (x, y + supp)
                    if y + supp > self.cote:
                        print(f"pose impossible du muret {coord}. il finit en dehors du terrain")
                        return False
                else:
                    coord_test = (x + supp, y)
                    if x + supp > self.cote:
                        print(f"pose impossible du muret {coord}. il finit en dehors du terrain")
                        return False
                if coord_test in self:
                    print(f"pose impossible du muret {coord}. case {coord_test} déjà posée")
                    return False
                else:
                    plateau_test += coord_test
            for joueur in self.joueurs:
                if not joueur.teste_plateau(plateau_test):
                    print(f"bloquant pour {joueur}")
                    break
            else:
                self.coords_murets = plateau_test.coords_murets[:]
                return True
        return False

    def coord_voisins(self, coord):
        x, y = coord
        voisins = set()
        if x > 0 and (x - 1, y) not in self:
            # Vers l' Ouest
            voisins.add((x - 2, y))
        if x < self.cote and (x + 1, y) not in self:
            # Vers l' Est
            voisins.add((x + 2, y))
        if y > 0 and (x, y - 1) not in self:
            # Vers le Nord
            voisins.add((x, y - 2))
        if y < self.cote and (x, y + 1) not in self:
            # Vers le Sud
            voisins.add((x, y + 2))
        return list(voisins)

    def coord_voisins_immediats(self, coord):
        x, y = coord
        coords_joueurs = [joueur.coords for joueur in self.joueurs]
        voisins = set()
        if x > 0 and (x - 1, y) not in self:
            # Vers l' Ouest
            if (x - 2, y) not in coords_joueurs:
                voisins.add((x - 2, y))
            else:
                if x == 2 or (x - 3, y) in self:
                    if (x - 2, y - 1) not in self:
                        voisins.add((x - 2, y - 2))
                    if (x - 2, y + 1) not in self:
                        voisins.add((x - 2, y + 2))
                else:
                    voisins.add((x - 4, y))
        if x < self.cote and (x + 1, y) not in self:
            # Vers l' Est
            if (x + 2, y) not in coords_joueurs:
                voisins.add((x + 2, y))
            else:
                if x == 14 or (x + 3, y) in self:
                    if (x + 2, y - 1) not in self:
                        voisins.add((x + 2, y - 2))
                    if (x + 2, y + 1) not in self:
                        voisins.add((x + 2, y + 2))
                else:
                    voisins.add((x + 4, y))

        if y > 0 and (x, y - 1) not in self:
            # Vers le Nord
            if (x, y - 2) not in coords_joueurs:
                voisins.add((x, y - 2))
            else:
                if y == 2 or (x, y - 3) in self:
                    if (x - 1, y - 2) not in self:
                        voisins.add((x - 2, y - 2))
                    if (x + 1, y - 2) not in self:
                        voisins.add((x + 2, y - 2))
                else:
                    voisins.add((x, y - 4))

        if y < self.cote and (x, y + 1) not in self:
            # Vers le Sud

            if (x, y + 2) not in coords_joueurs:
                voisins.add((x, y + 2))
            else:
                if y == 14 or (x, y + 3) in self:
                    if (x - 1, y + 2) not in self:
                        voisins.add((x - 2, y + 2))
                    if (x + 1, y + 2) not in self:
                        voisins.add((x + 2, y + 2))
                else:
                    voisins.add((x, y + 4))
        voisins.difference_update(coords_joueurs)
        return list(voisins)

    def __str__(self):
        if self.coords_murets:
            return f"le plateau avec les murets suivants: {self.coords_murets}"
        else:
            return f"le plateau encore vierge de murets"

    def __repr__(self):
        return str(self)


import sys
counter = 1
ans = 0
record = 0
for line in sys.stdin:
    score = sum(list(map(int,line.split())))
    if(score > record):
        record = score
        ans = counter
    counter += 1

print(ans,record)


from django.contrib import admin
from articles.models import Articles

# class ContactAdmin(admin.ModelAdmin):
# 	fields = ('name','age')

class ArticlesAdmin(admin.ModelAdmin):
	list_display  = ('title','author','content')
	search_fields = ('title',)
	fieldsets = (
	['Main',{
		'fields':('title','author'),
	}],
	['Advance',{
		'classes':('collapse',),
		'fields':('content',),
	}]
	)

# Register your models here.
admin.site.register(Articles,ArticlesAdmin)


#calss header
class _ACCEPTANCE():
	def __init__(self,):
		self.name = "ACCEPTANCE"
		self.definitions = [u'general agreement that something is satisfactory or right, or that someone should be included in a group: ', u'the act of agreeing to an offer, plan, or invitation: ', u'the fact of accepting a difficult or unpleasant situation: ']

		self.parents = []
		self.childen = []
		self.properties = []
		self.jsondata = {}

		self.specie = 'nouns'

	def run(self, obj1 = [], obj2 = []):
		return self.jsondata


from bitarray import bitarray
import numpy

class Chromosome:

    def __init__(self, chromosome_length):
        self.alleles = bitarray(chromosome_length)
        self.alleles.setall(False)
        self.chromosome_length = chromosome_length

        # Initialize vector randomly
        for ii in range(0, chromosome_length):
            if (numpy.random.random() > 0.5):
                self.alleles[ii] = 1
            else:
                self.alleles[ii] = 0

    def print(self):
        print("Bit array:", self.alleles)
        # print("Number of ones:", self.alleles.count(True))
        return