## Standard libraries
import os

## PyTorch
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import pytorch_lightning as pl

import numpy as np
import math
import matplotlib.pyplot as plt

from VAES.se2cnn.nn import R2ToSE2Conv, SE2ToSE2Conv, SE2ToR2Conv, SE2ToSE2ConvNext, Fourier, SE2LayerNorm, SpatialMaxPool, SE2ToR2Projection, SpatialUpsample

# from .types_ import *

class SE2VAE(pl.LightningModule):

    def __init__(self,
                 original_input_channels: int,
                 latent_dim: int,
                 N: int,
                 hidden_dim: int,
                 kernel_size: int,
                 depth: int,
                 variational: bool,
                 lr=0.0001,
                 **kwargs):

        super(SE2VAE, self).__init__()
        self.save_hyperparameters()

        self.variational = variational
        self.latent_dim = latent_dim
        self.fourier = Fourier(N)
        if variational:
            self.encoder_output_dim =latent_dim + 1 + 1# + 1 for log variance/sigma
        else:
            self.encoder_output_dim = latent_dim + 1 #plus 1 for theta
        self.spatial_size = 68
        self.lr = lr
        self.N = N

        # ------------------------------------------------------------
        # --------- ENCODER-------------------------------------------
        # ------------------------------------------------------------

        modules = []

        modules.append(R2ToSE2Conv(original_input_channels, hidden_dim, N, kernel_size=kernel_size, padding=0))
        modules.append(SE2LayerNorm(hidden_dim))
        modules.append(nn.LeakyReLU())
        modules.append(SpatialMaxPool(kernel_size=2, stride=2, padding=0, nbOrientations=N))

        for l in range(depth - 2):
            modules.append(SE2ToSE2ConvNext(hidden_dim, hidden_dim, N, kernel_size=kernel_size, padding=0))
            modules.append(SpatialMaxPool(kernel_size=2, stride=2, padding=0, nbOrientations=N))

        modules.append(SE2ToSE2Conv(hidden_dim, self.encoder_output_dim, N, kernel_size=kernel_size, padding=0))
        self.encoder = nn.Sequential(*modules)
        # print(self.encoder)
        # print(self.encoder_output_dim)

        # ------------------------------------------------------------
        # --------- DECODER-------------------------------------------
        # ------------------------------------------------------------

        modules = []

        modules.append(SE2ToSE2ConvNext(latent_dim, hidden_dim, N, kernel_size=kernel_size, padding=(kernel_size-1)))
        modules.append(SpatialUpsample(2, N))
        modules.append(nn.LeakyReLU())

        for _ in range(depth-2):
            modules.append(SE2ToSE2ConvNext(hidden_dim, hidden_dim, N, kernel_size=kernel_size, padding=(kernel_size-1)))
            modules.append(SpatialUpsample(2, N))

        modules.append(SE2ToR2Conv(hidden_dim, original_input_channels, N, kernel_size=5, padding=(kernel_size-1)))
        modules.append(nn.Identity())

        self.decoder = nn.Sequential(*modules)
        self.mask = torch.nn.Parameter(build_mask(self.spatial_size), requires_grad=False)

    def encode(self, input):
        """
        Encodes the input by passing through the encoder network
        and returns the latent codes.
        :param input: (Tensor) Input tensor to encoder [N x C x H x W]
        :return: (Tensor) List of latent codes
        """
        return self.encoder(input)

    def decode(self, z):
        """
        Maps the given latent codes
        onto the image space.
        :param z: (Tensor) [B x D]
        :return: (Tensor) [B x C x H x W]
        """
        return self.decoder(z)

    def reparameterize(self, mu, logvar):
        """
        Reparameterization trick to sample from N(mu, var) from
        N(0,1).
        :param mu: (Tensor) Mean of the latent Gaussian [B x D]
        :param logvar: (Tensor) Standard deviation of the latent Gaussian [B x D]
        :return: (Tensor) [B x D]
        """
        std = torch.exp(0.5 * logvar)
        eps = torch.randn_like(std)
        return eps * std + mu

    def forward(self, input, **kwargs):
        latent = self.encode(input)

        if self.variational:
            z_mu = latent[:, :self.latent_dim]  # [B, k, N, X, Y]
            z_theta = latent[:, self.latent_dim:self.latent_dim+1]  # [B, 1, N, X, Y]
            z_log_var = latent[:, self.latent_dim:self.latent_dim+1]  # [B, 1, N, X, Y]

            mu = self.fourier.band_limit_signal(z_mu)  # [B, k, N, ...]
            log_var = self.fourier.regular_to_irrep(z_log_var, 0)[:, :, 0]  # [B, 1, 2, X, Y] -> [B, 1, X, Y], note only the 1st coordinate is non-zero

            if self.N > 2:
                pose = self.fourier.regular_to_irrep(z_theta, 1)  # [B, 1, 2, X, Y]
                pose_theta = torch.atan2(pose[:,:,1],pose[:,:,0])  # [B, 1, X, Y]
            else:
                pose_theta = None
            if self.N > 2:
                mu_aligned = self.fourier.rotate_signal(mu, -pose_theta)
            else:
                mu_aligned = mu

            gauss_mu = mu_aligned.flatten(1, 2)[..., 0, 0]  # [B, k, 2 or N, X=1, Y=1] -> [B, k*2 or k*N]
            gauss_log_var = F.softplus(log_var)[..., 0, 0]  # [B, 1, X, Y] -> [B, 1]

            sampled_landmarks_aligned = self.reparameterize(gauss_mu, gauss_log_var)
            sampled_landmarks_aligned = sampled_landmarks_aligned.unflatten(1, [self.latent_dim, -1])[...,None,None]
            if self.N > 2:
                sampled_landmarks = self.fourier.rotate_signal(sampled_landmarks_aligned, pose_theta)
            else:
                sampled_landmarks = sampled_landmarks_aligned

            # Equivariant decoder
            z = sampled_landmarks # ([64, 10, 8, 1, 1])

        # autoencoder case
        else:

            z_mu = latent[:, :self.latent_dim]  # [B, k, N, X, Y]
            z_theta = latent[:, self.latent_dim:self.latent_dim+1]

            mu = self.fourier.band_limit_signal(z_mu)  # [B, k, N, ...]
            if self.N > 2:
                pose = self.fourier.regular_to_irrep(z_theta, 1)  # [B, 1, 2, X, Y]
                pose_theta = torch.atan2(pose[:,:,1],pose[:,:,0])  # [B, 1, X, Y]
            else:
                pose_theta = None
            if self.N > 2:
                mu_aligned = self.fourier.rotate_signal(mu, -pose_theta)
            else:
                mu_aligned = mu

            gauss_mu = mu_aligned.flatten(1, 2)[..., 0, 0]  # [B, k, 2 or N, X=1, Y=1] -> [B, k*2 or k*N]

            sampled_landmarks_aligned = gauss_mu.unflatten(1, [self.latent_dim, -1])[...,None,None]  # [B, k * 2 or k * N, 1, 1]

            z = sampled_landmarks_aligned
            gauss_log_var = None

        return  self.decode(z), gauss_mu, gauss_log_var

    def _get_reconstruction_loss(self, batch):
        """
        Computes the VAE loss function.
        KL(N(\mu, \sigma), N(0, 1)) = \log \frac{1}{\sigma} + \frac{\sigma^2 + \mu^2}{2} - \frac{1}{2}
        :param args:
        :param kwargs:
        :return:
        """
        x, y = batch  # We do not need the labels

        x_hat, mu, log_var = self.forward(x)
        # print('xhat: {}, mu: {}, var: {}'.format(x_hat.shape, mu.shape, log_var.shape))

        # recon_loss = self.mask * F.mse_loss(x_hat, x, reduction="none")
        recon_loss =  F.mse_loss(x_hat, x, reduction="none")

        recon_loss = recon_loss.sum(dim=[1, 2, 3]).mean(dim=[0])

        if self.variational:

            kld_loss = torch.mean(-0.5 * torch.sum(1 + log_var - mu ** 2 - log_var.exp(), dim = 1), dim = 0)
        else:
            kld_loss = None

        return recon_loss, kld_loss

    def random_sample(self,
               num_samples:int, **kwargs):
        """
        Samples from the latent space and return the corresponding
        image space map.
        :param num_samples: (Int) Number of samples
        :param current_device: (Int) Device to run the model
        :return: (Tensor)
        """
        z = torch.randn(num_samples, self.latent_dim*self.N)

        z = z[..., None, None].unflatten(1, [self.latent_dim, self.N]).to(self.device)
        samples = self.decode(z)
        return samples

    def reconstruct(self, x, **kwargs):
        """
        Given an input image x, returns the reconstructed image
        :param x: (Tensor) [B x C x H x W]
        :return: (Tensor) [B x C x H x W]
        """

        return self.forward(x)[0]

    def configure_optimizers(self):
        optimizer = optim.Adam(self.parameters(), lr=self.lr)
        scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, self.trainer.max_epochs)
        return {"optimizer": optimizer, "lr_scheduler": scheduler, "monitor": "val_loss"}

    def training_step(self, batch, batch_idx):
        loss, kld = self._get_reconstruction_loss(batch)
        self.log('train_loss (recon)', loss)
        if self.variational:
            self.log('train_loss (kld)', kld)
            self.log('train_loss (recon+kld)', loss + kld)
            return loss + kld
        else:
            return loss

    def validation_step(self, batch, batch_idx):
        loss, kld = self._get_reconstruction_loss(batch)
        self.log('val_loss (recon)', loss)
        if self.variational:
            self.log('val_loss (kld)', kld)
            self.log('val_loss (recon+kld)', loss + kld)
            return loss + kld
        else:
            return loss

    def test_step(self, batch, batch_idx):
        loss, kld = self._get_reconstruction_loss(batch)
        self.log('test_loss (recon)', loss)
        if self.variational:
            self.log('test_loss (kld)', kld)
            self.log('test_loss (recon+kld)', loss + kld)
            return loss + kld
        else:
            return loss

    def on_load_checkpoint(self, checkpoint):
        self.train()

def build_mask(s, margin=2, dtype=torch.float32):
    mask = torch.zeros(1, 1, s, s, dtype=dtype)

    c = (s-1) / 2
    t = (c - margin/100.*c)**2
    sig = 2.
    for x in range(s):
        for y in range(s):
            r = (x - c) ** 2 + (y - c) ** 2
            if r > t:
                mask[..., x, y] = math.exp((t - r)/sig**2)
            else:
                mask[..., x, y] = 1.

    return mask


'''
A very simple timmy bot for MTG drafting.

To Run: python3 timmy.py
'''
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import sys

## Import path hacking to make this run referencing the modules it needs.
PACKAGE_PARENT = '../..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(),
                             os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

from lib.pack_generator import PackGenerator
from lib.draft_data_reader import DraftDataReader

import argparse

import tensorflow as tf

FLAGS = None

## Prints the usage string to stdout.
def print_usage():
    print('Improper arguments!\n'
          'Run as python3 timmy.py <training_packs.txt> <validation_packs.txt> <training_iterations> <model_name> [set_file.json] [card_rankings.txt]\n'
          '|  training_packs.txt = the file containing serialized packs for training the NN\n'
          '|  validation_packs.txt = the file containing serialized packs for validating the NN\n'
          '|  training_iterations = the number of iterations to train the NN\n'
          '|  model_name = the filename to save the trained NN model to\n'
          '|  set_file.json = json filename containing the MTG cards\n'
          '|  card_rankings.txt = file containing rankings for each card\n')

def main(_):
    if (len(sys.argv) != 5 and len(sys.argv) != 7):
        print_usage()
        sys.exit()

    print('Top of main')

    training_packs_file = sys.argv[1]
    validation_packs_file = sys.argv[2]
    training_iterations = int(sys.argv[3])
    model_name = sys.argv[4]
    set_file = ''
    card_rankings_file = ''
    set_file = '../../data/kaladesh/kaladesh.json'
    card_rankings_file = '../../data/kaladesh/kaladesh_pick_order.txt'

    if (len(sys.argv) == 5):
        set_file = '../../data/kaladesh/kaladesh.json'
        card_rankings_file = '../../data/kaladesh/kaladesh_pick_order.txt'

    pack_gen = PackGenerator(set_file, card_rankings_file)

    ## Create the training data reader
    training_draft_data_reader = DraftDataReader(pack_gen)
    training_draft_data_reader.read_data(training_packs_file)

    ## Create the validation data reader
    validation_draft_data_reader = DraftDataReader(pack_gen)
    validation_draft_data_reader.read_data(validation_packs_file)

    nn_node_height = pack_gen.num_cards_in_set + 1

    ''' Create the model '''
    print('Creating the initial model')

    ## X is the input placeholder which takes in N number of packs of cards
    ## (represented as an array of nn_node_height decimal valeus). Note that the keyword
    ## None here allows us to provide any number of input arrays.
    x = tf.placeholder(tf.float32, [None, nn_node_height])

    ## W is the main mesh for the NN.
    W = tf.Variable(tf.zeros([nn_node_height, nn_node_height]))

    ## b is the bias which is applied to the output of multiplying x with W, and
    ## allows us to tweak the final values to account for things.
    b = tf.Variable(tf.zeros([nn_node_height]))

    ## This is the actual line of code which represents our initial NN
    ## computation. It takes in any number of images and converts them to guesses
    ## as to what the number actually was.
    y = tf.matmul(x, W) + b

    ''' Define loss and optimizer '''

    ## This is the set of expected values for each of the trial runs.
    y_ = tf.placeholder(tf.float32, [None, nn_node_height])

    '''
    The raw formulation of cross-entropy,

    tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.softmax(y)),
                                  reduction_indices=[1]))

    can be numerically unstable.

    So here we use tf.nn.softmax_cross_entropy_with_logits on the raw outputs of
    'y', and then average across the batch.
    '''

    print('Defining the loss function')

    ## Here we define what the loss function will be for our NN. This is
    ## important because we need some way to tell our NN how well it did with its
    ## guesses so that our back-propogation step (the optimizer) can help the NN
    ## to converge to a model which makes better guesses.
    cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_))

    print('Defining the optimization function')

    ## This is the step that ties everything together. It takes the output of the
    ## matrix multiplication (wrapped in the cross_entropy function to define
    ## loss), and applies the gradient descent optimization routine to tweak the
    ## biases within the model.
    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

    ## Initilize all variables and placeholders for this training session.
    sess = tf.InteractiveSession()

    print('Starting the session')
    saver = tf.train.Saver()

    ''' Train the model '''

    ## Launches the training session
    tf.initialize_all_variables().run()

    print('Begin training the model')

    ## Here we are running 1000 loops on 100 randomly chosen elements from the
    ## input set. Note that training in this way saves time because choosing
    ## randomly tends to be almost as effective as training over the entire
    ## dataset (and it saves time).
    count = 0
    for _ in range(training_iterations):
        if count % 100 == 0:
            print('Training iteration: ' + str(count))
        count += 1
        ## Grab random values from the training set
        batch_xs, batch_ys = training_draft_data_reader.next_batch(100)

        ## Run those values through the model
        sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

    ''' Test trained model '''

    print('Test the trained model')

    ## Compare the expected and actual values for each run
    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))

    ## Condense the above array down into a number
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    ## Print the % correct
    batch_xs, batch_ys = validation_draft_data_reader.next_batch(100)
    print(sess.run(accuracy, feed_dict={x: batch_xs, y_: batch_ys}))

    ''' Save Dat Model Yo! '''
    saver.save(sess, model_name)

    '''
    ## This is just an example of how to send a single pack through the NN
    batch_xs = validation_draft_data_reader.next_batch(1)
    print('batch_xs: ')
    print(batch_xs[0])
    softmax_y = tf.nn.softmax(y)
    fetches = [softmax_y]
    res = sess.run(fetches, feed_dict = {x: batch_xs[0]})
    print(res)
    '''

if __name__ == '__main__':
    '''
    parser = argparse.ArgumentParser()
    parser.add_argument('--data_dir', type=str, default='/tmp/data',
            help='Directory for storing data')
    FLAGS = parser.parse_args()
    '''
    print('Calling app.run()')
    tf.app.run()


import celery
from celery.signals import task_postrun, task_prerun, worker_process_init

class Celery(object):
    def __init__(self, app=None, sentry=None):
        self.app = app
        self.context = None
        self.celery = celery.Celery(__name__)
        if app:
            self.init_app(app, sentry)

    def init_app(self, app, sentry=None):
        self.app = app
        new_celery = celery.Celery(
            app.import_name,
            broker=app.config['CELERY_BROKER_URL'],
            backend=app.config['CELERY_RESULT_BACKEND'],
        )
        self.celery.__dict__.update(vars(new_celery))
        self.celery.conf.update(app.config)

        worker_process_init.connect(self._worker_process_init)

        task_postrun.connect(self._task_postrun)
        task_prerun.connect(self._task_prerun)

    def task(self, *args, **kwargs):
        return self.celery.task(*args, **kwargs)

    def get_celery_app(self):
        return self.celery

    def _worker_process_init(self, **kwargs):
        self.app.app_context().push()

    def _task_prerun(self, task, **kwargs):
        if self.app is None:
            return
        context = task._flask_context = [
            self.app.app_context(),
            self.app.test_request_context(),
        ]
        for ctx in context:
            ctx.push()

    def _task_postrun(self, task, **kwargs):
        try:
            context = task._flask_context
        except AttributeError:
            return
        for ctx in context:
            ctx.pop()


from builtins import object
from six import string_types

import datetime
import logging
import select
import socket
import sys

from desktop import conf
from desktop.lib.i18n import smart_str

from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE

if sys.version_info[0] > 2:
  from django.utils.translation import gettext as _
else:
  from django.utils.translation import ugettext as _

BOMS = (
    (BOM_UTF8, "UTF-8"),
    (BOM_UTF32_BE, "UTF-32-BE"),
    (BOM_UTF32_LE, "UTF-32-LE"),
    (BOM_UTF16_BE, "UTF-16-BE"),
    (BOM_UTF16_LE, "UTF-16-LE"),
)

__all__ = ['CaseInsensitiveDict', 'create_synchronous_io_multiplexer']

LOG = logging.getLogger()

class CaseInsensitiveDict(dict):
  def __setitem__(self, key, value):
    super(CaseInsensitiveDict, self).__setitem__(key.lower(), value)

  def __getitem__(self, key):
    return super(CaseInsensitiveDict, self).__getitem__(key.lower())

  def __contains__(self, key):
    return super(CaseInsensitiveDict, self).__contains__(key.lower())

  @classmethod
  def from_dict(cls, _dict):
    return CaseInsensitiveDict([(isinstance(key, string_types) and key.lower() or key, _dict[key]) for key in _dict])

class SynchronousIOMultiplexer(object):
  def read(self, rd):
    raise NotImplementedError(_('"read" method is not implemented'))

  def write(self, rd):
    raise NotImplementedError(_('"write" method is not implemented'))

  def error(self, rd):
    raise NotImplementedError(_('"error" method is not implemented'))

class SelectSynchronousIOMultiplexer(SynchronousIOMultiplexer):
  def __init__(self, timeout=0):
    self.timeout = 0

  def read(self, fds):
    rlist, wlist, xlist = select.select(fds, [], [], self.timeout)
    return rlist

class PollSynchronousIOMultiplexer(SynchronousIOMultiplexer):
  def __init__(self, timeout=0):
    self.timeout = 0

  def read(self, fds):
    poll_obj = select.poll()
    for fd in fds:
      poll_obj.register(fd, select.POLLIN)
    event_list = poll_obj.poll(self.timeout)
    return [fd_event_tuple[0] for fd_event_tuple in event_list]

def create_synchronous_io_multiplexer(timeout=0):
  if conf.POLL_ENABLED.get():
    try:
      from select import poll
      return PollSynchronousIOMultiplexer(timeout)
    except ImportError:
      pass
  return SelectSynchronousIOMultiplexer(timeout)

def find_unused_port():
  """
  Finds a port that's available.
  Unfortunately, this port may not be available by the time
  the subprocess uses it, but this generally works.
  """
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  try:
    sock.bind(('127.0.0.1', 0))
    sock.listen(socket.SOMAXCONN)
    _, port = sock.getsockname()
  finally:
    sock.close()

  return port

def force_list_to_strings(lst):
  if not lst:
    return lst

  new_list = []
  for item in lst:
    if isinstance(item, string_types):
      # Strings should not be unicode.
      new_list.append(smart_str(item))
    elif isinstance(item, dict):
      # Recursively force dicts to strings.
      new_list.append(force_dict_to_strings(item))
    elif isinstance(item, list):
      new_list.append(force_list_to_strings(item))
    else:
      # Normal objects, or other literals, should not be converted.
      new_list.append(item)

  return new_list

def force_dict_to_strings(dictionary):
  if not dictionary:
    return dictionary

  new_dict = {}
  for k in dictionary:
    new_key = smart_str(k)
    if isinstance(dictionary[k], string_types):
      # Strings should not be unicode.
      new_dict[new_key] = smart_str(dictionary[k])
    elif isinstance(dictionary[k], dict):
      # Recursively force dicts to strings.
      new_dict[new_key] = force_dict_to_strings(dictionary[k])
    elif isinstance(dictionary[k], list):
      new_dict[new_key] = force_list_to_strings(dictionary[k])
    else:
      # Normal objects, or other literals, should not be converted.
      new_dict[new_key] = dictionary[k]

  return new_dict

def from_string_to_bits(str_value):
  return ''.join(format(ord(byte), '08b') for byte in str_value)

def get_bytes_from_bits(bit_string):
  """
  This should be used in py3 or above
  """
  padded_bits = bit_string + '0' * (8 - len(bit_string) % 8)
  return list(int(padded_bits, 2).to_bytes(len(padded_bits) // 8, 'big'))

def isASCII(data):
  try:
    data.decode('ASCII')
  except UnicodeDecodeError:
    return False
  else:
    return True

def isUTF8(data):
  try:
    data.decode('UTF-8')
  except UnicodeDecodeError:
    return False
  else:
    return True

def isGB2312(data):
  try:
    data.decode('gb2312')
  except UnicodeDecodeError:
    return False
  else:
    return True

def is_big5(data):
  try:
    data.decode('big5')
  except UnicodeDecodeError:
    return False
  else:
    return True

def is_shift_jis(data):
  try:
    data.decode('shift-jis')
  except UnicodeDecodeError:
    return False
  else:
    return True

def isEUCKR(data):
  try:
    data.decode('EUC-KR')
  except UnicodeDecodeError:
    return False
  else:
    return True

def isISO8859_1(data):
  try:
    data.decode('iso-8859-1')
  except UnicodeDecodeError:
    return False
  else:
    return True

def isCP1252(data):
  try:
    data.decode('cp1252')
  except UnicodeDecodeError:
    return False
  else:
    return True

def isUTF8Strict(data):
  try:
    decoded = data.decode('UTF-8')
  except UnicodeDecodeError:
    return False
  else:
    for ch in decoded:
      if 0xD800 <= ord(ch) <= 0xDFFF:
        return False
    return True

def check_bom(data):
  return [encoding for bom, encoding in BOMS if data.startswith(bom)]

def check_encoding(data):
  """
  this is a simplified alternative to GPL chardet
  """
  LOG.debug("checking data encoding: %s" % data)
  if isASCII(data):
    return 'ASCII'
  elif sys.version_info[0] == 2 and isUTF8(data):
    return 'utf-8'
  elif sys.version_info[0] > 2 and isUTF8Strict(data):
    return 'utf-8'
  else:
    encoding = check_bom(data)
    if encoding:
      return encoding[0]
    elif isEUCKR(data):
      return 'EUC-KR'
    elif isGB2312(data):
      return 'gb2312'
    elif is_big5(data):
      return 'big5'
    elif is_shift_jis(data):
      return 'shift-jis'
    elif isISO8859_1(data):
      return 'iso-8859-1'
    else:
      return 'cp1252'

def current_ms_from_utc():
  return (datetime.datetime.utcnow() - datetime.datetime.utcfromtimestamp(0)).total_seconds() * 1000


#!/bin/env python
from subprocess import check_output
import locale
import re
import requests
import sys
from time import sleep
import os
from bottle import route, run, request, response
import json
import socket
import netifaces as ni
from datetime import timedelta

class GPUInfo(object):

	commands = {
		"odgc": ["aticonfig", "--adapter={0}", "--odgc"],
		"odgt": ["aticonfig", "--adapter={0}", "--odgt"],
		"fan":  ["aticonfig", "--pplib-cmd", "get fanspeed {0}"],
		"lsmod": ["lsmod"],
	}

	gpu_mem_posit = {
		"gpu": 1,
		"mem": 2,
	}

	def __init__(self):

		self.encoding = "utf-8"
		self.isCatalystLoaded()

	def isCatalystLoaded(self):

		info = self.getInformation("lsmod")
		if "fglrx" in info:
			return True
		sys.exit(1)

	def getInformation(self, source, adapter=0):

		command = [part.format(adapter) for part in self.commands[source]]

		try:
			info = check_output(command)
		except OSError:
			sys.exit(1)

		return info.decode(self.encoding)

	def getLoad(self, adapter=0):

		info = self.getInformation("odgc", adapter).split("\n")

		for line in info:
			try:
				load_match = re.search(r"GPU load\D+(\d+)%", line)
				if load_match:
					return load_match.group(1)
			except IndexError:
				sys.exit(1)

	def getFanspeed(self, adapter=0):

		info = self.getInformation("fan", adapter)
		try:
			fan_match = re.search("(\d{1,3})%", info)
			return fan_match.group(1)
		except IndexError:
			sys.exit(1)

	def getCurrentClock(self, gpu_or_mem, adapter=0):

		if gpu_or_mem not in self.gpu_mem_posit:
			sys.exit(1)
		info = self.getInformation("odgc").split("\n")
		current_clock_regex = re.compile(r'Current Clocks\D+(\d+)\s+(\d+)')

		for line in info:
			current_clock_match = current_clock_regex.search(line)
			if current_clock_match:
				return current_clock_match.group(self.gpu_mem_posit[gpu_or_mem])

	def getMaxClock(self, gpu_or_mem, adapter=0):

		if gpu_or_mem not in self.gpu_mem_posit:
			sys.exit(1)
		info = self.getInformation("odgc", adapter).split("\n")
		max_clock_regex = re.compile(r'Current Peak\D+(\d+)\s+(\d+)')

		for line in info:
			max_clock_match = max_clock_regex.search(line)
			if max_clock_match:
				return max_clock_match.group(self.gpu_mem_posit[gpu_or_mem])

	def getTemperature(self, adapter=0):

		info = self.getInformation("odgt", adapter)
		try:
			temp_match = re.search(r'(\d{2,3})\.\d{2} C', info)
			return temp_match.group(1)
		except IndexError:
			sys.exit(1)

	def get_adapter(self):

		s = check_output(["aticonfig", "--list-adapters"])

		for l in s.splitlines():
			n = l[:2].replace(" ", "").replace("*", "")

		return int(n)

def get_uptime():

	with open('/proc/uptime', 'r') as f:
		uptime_seconds = float(f.readline().split()[0])
		uptime_string = str(timedelta(seconds = uptime_seconds))

		return uptime_string

def get_name():
	return socket.gethostname()

def get_ip():
	ni.ifaddresses('eth0')
	ip = ni.ifaddresses('eth0')[2][0]['addr']

	return ip

def dico():

	grosTableau = {}
	data = {}
	gpu = []
	gpu0 = {}
	gpu1 = {}
	gpu2 = {}
	gpu3 = {}
	gpu4 = {}
	gpu5 = {}

	g = GPUInfo()
	ip = get_ip()

	data['Uptime'] = get_uptime()
	data['Name'] = get_name()
	data['Ip'] = get_ip()

	gpu0['Load'] = str(g.getLoad())
	gpu0['Heat'] = str(g.getTemperature(adapter = 0))
	gpu0['FanSpeed'] = str(g.getFanspeed(adapter = 0))
	gpu0['MaxClock'] = str(g.getMaxClock("gpu", adapter = 0))
	gpu0['CurrentClock'] = g.getCurrentClock("gpu", adapter = 0)
	gpu0['MaxMem'] = str(g.getMaxClock("mem", adapter = 0))
	gpu0['CurrentMem'] = g.getCurrentClock("mem", adapter = 0)
	#gpu0['Information'] = str(g.getInformation("odgc", adapter = 0))

	gpu1['Load'] = str(g.getLoad())
	gpu1['Heat'] = str(g.getTemperature(adapter = 1))
	gpu1['FanSpeed'] = str(g.getFanspeed(adapter = 1))
	gpu1['MaxClock'] = str(g.getMaxClock("gpu", adapter = 1))
	gpu1['CurrentClock'] = g.getCurrentClock("gpu", adapter = 1)
	gpu1['MaxMem'] = str(g.getMaxClock("mem", adapter = 1))
	gpu1['CurrentMem'] = g.getCurrentClock("mem", adapter = 1)
	#gpu1['Information'] = str(g.getInformation("odgc", adapter = 1))

	gpu2['Load'] = str(g.getLoad())
	gpu2['Heat'] = str(g.getTemperature(adapter = 2))
	gpu2['FanSpeed'] = str(g.getFanspeed(adapter = 2))
	gpu2['MaxClock'] = str(g.getMaxClock("gpu", adapter = 2))
	gpu2['CurrentClock'] = g.getCurrentClock("gpu", adapter = 2)
	gpu2['MaxMem'] = str(g.getMaxClock("mem", adapter = 2))
	gpu2['CurrentMem'] = g.getCurrentClock("mem", adapter = 2)
	#gpu2['Information'] = str(g.getInformation("odgc", adapter = 2))

	gpu3['Load'] = str(g.getLoad())
	gpu3['Heat'] = str(g.getTemperature(adapter = 3))
	gpu3['FanSpeed'] = str(g.getFanspeed(adapter = 3))
	gpu3['MaxClock'] = str(g.getMaxClock("gpu", adapter = 3))
	gpu3['CurrentClock'] = g.getCurrentClock("gpu", adapter = 3)
	gpu3['MaxMem'] = str(g.getMaxClock("mem", adapter = 3))
	gpu3['CurrentMem'] = g.getCurrentClock("mem", adapter = 3)
	#gpu3['Information'] = str(g.getInformation("odgc", adapter = 3))

	gpu4['Load'] = str(g.getLoad())
	gpu4['Heat'] = str(g.getTemperature(adapter = 4))
	gpu4['FanSpeed'] = str(g.getFanspeed(adapter = 4))
	gpu4['MaxClock'] = str(g.getMaxClock("gpu", adapter = 4))
	gpu4['CurrentClock'] = g.getCurrentClock("gpu", adapter = 4)
	gpu4['MaxMem'] = str(g.getMaxClock("mem", adapter = 4))
	gpu4['CurrentMem'] = g.getCurrentClock("mem", adapter = 4)
	#gpu4['Information'] = str(g.getInformation("odgc", adapter = 4))

	gpu5['Load'] = str(g.getLoad())
	gpu5['Heat'] = str(g.getTemperature(adapter = 5))
	gpu5['FanSpeed'] = str(g.getFanspeed(adapter = 5))
	gpu5['MaxClock'] = str(g.getMaxClock("gpu", adapter = 5))
	gpu5['CurrentClock'] = g.getCurrentClock("gpu", adapter = 5)
	gpu5['MaxMem'] = str(g.getMaxClock("mem", adapter = 5))
	gpu5['CurrentMem'] = g.getCurrentClock("mem", adapter = 5)
	#gpu5['Information'] = str(g.getInformation("odgc", adapter = 5))

	listeGPU = [gpu0, gpu1, gpu2, gpu3, gpu4, gpu5]
	i = 0
	result = g.get_adapter()

	while i <= n:
		gpu.append(listeGPU[i])
		i += 1

	"""
	gpu.append(gpu0)
	gpu.append(gpu1)
	gpu.append(gpu2)
	gpu.append(gpu3)
	gpu.append(gpu4)
	gpu.append(gpu5)
	"""
	data['gpu'] = gpu
	grosTableau['data'] = data

	return grosTableau

@route('/', method='get')
def api():
	response['Access-Control-Allow-Origin'] = '*'
	response['Access-Control-Allow-Methods'] = 'GET'
	response['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept'
	d = dico()

	return json.dumps(d)

if __name__ == '__main__':

	ip = get_ip()
	run(host=ip, port=6969)


from appium import webdriver
import time
import random

def slide_app(keywords):

    desired_caps = {
        'platformName': 'Android',
        'platformVersion': '5.1.1',
        'deviceName': 'OPPO R11 Plus',
        'appPackage': 'com.xingin.xhs',
        'appActivity': 'com.xingin.alioth.search.GlobalSearchActivity t29',
        'noReset': 'True',
        'unicodeKeyboard': 'True',
        'resetKeyboard': 'True'
    }

    # Appium Server
    server = 'http://localhost:4723/wd/hub'
    driver = webdriver.Remote(server, desired_caps)

    search = driver.find_element_by_id('com.xingin.xhs:id/bos')
    search.click()
    time.sleep(10)
    text = driver.find_element_by_id('com.xingin.xhs:id/bos')
    time.sleep(10)
    text.send_keys(keywords)
    button = driver.find_element_by_id('com.xingin.xhs:id/bow')
    button.click()
    time.sleep(10)
    latest_post = driver.find_element_by_id('com.xingin.xhs:id/cxk')
    latest_post.click()
    time.sleep(10)

    width = driver.get_window_size()['width']
    height = driver.get_window_size()['height']
    slide = 0

    while slide < 500:
        print('Keywords: {}, Slide: {}/500'.format(keywords,slide))
        postname = driver.find_elements_by_id('com.xingin.xhs:id/c4t')
        driver.swipe(width * 0.5, height * 0.75, width * 0.5, height * 0.25)
        slide = slide + 1
        time.sleep(random.uniform(2, 5))
        print(postname)

    driver.save_screenshot('endpos.png')

def run():
#insert the words you want to search in Xiaohongshu app
    keywords_list = ['成都民宿']
    for keywords in keywords_list:
        print('Start Spider...')
        print('Keywords: {}'.format(keywords))
        slide_app(keywords)
        time.sleep(60)

if __name__ == '__main__':
    run()


import os
import sys

import gi

gi.require_version("Gst", "1.0")
gi.require_version("GstApp", "1.0")
gi.require_version("GstVideo", "1.0")
from gi.repository import Gst, GLib, GObject, GstApp, GstVideo

Gst.init(sys.argv if hasattr(sys, "argv") else None)

def main(args):
    video_file_path = os.path.expanduser("~/Videos/27.mp4")

    # Standard GStreamer initialization
    # GObject.threads_init()
    Gst.init(None)

    print("Creating Pipeline \n ")
    pipeline = Gst.Pipeline()
    if not pipeline:
        sys.stderr.write(" Unable to create Pipeline \n")

    source = Gst.ElementFactory.make("filesrc", "file-source")
    source.set_property("location", video_file_path)

    stream_demux = Gst.ElementFactory.make("qtdemux", "mux")
    h264parser = Gst.ElementFactory.make("h264parse", "videoparsersbad")
    h264parser.set_property("config-interval", -1)

    mpeg_ts_mux = Gst.ElementFactory.make("mpegtsmux", "mpegtsmux")

    hls_sink = Gst.ElementFactory.make("hlssink", "hls")
    hls_sink.set_property("location", "%06d.ts")
    hls_sink.set_property("target-duration", 5)

    pipeline.add(source)
    pipeline.add(stream_demux)
    pipeline.add(h264parser)
    pipeline.add(mpeg_ts_mux)
    pipeline.add(hls_sink)

    source.link(stream_demux)
    stream_demux.link(h264parser)

    h264parser.link(mpeg_ts_mux)
    mpeg_ts_mux.link(hls_sink)

    loop = GLib.MainLoop()

    # start play back and listen to events
    print("Starting pipeline \n")
    pipeline.set_state(Gst.State.PLAYING)
    try:
        loop.run()
    except:
        pass
    # cleanup
    pipeline.set_state(Gst.State.NULL)

def demo():
    # pipeline_str = 'filesrc location=/home/leefr/Videos/27.mp4 ! qtdemux ! h264parse config-interval=-1 ! mpegtsmux ! hlssink location="%06d.ts" target-duration=5'
    # pipeline_str = 'appsrc emit-signals=True is-live=True caps=video/x-raw,format=RGB,width=640,height=480,framerate=30/1 ! queue ! videoconvert ! autovideosink'
    pipeline_str = 'filesrc location=/home/leefr/Videos/27.mp4 ! queue ! videoconvert ! autovideosink'

    pipeline = Gst.parse_launch(pipeline_str)
    loop = GLib.MainLoop()

    # start play back and listen to events
    print("Starting pipeline \n")
    pipeline.set_state(Gst.State.PLAYING)
    try:
        loop.run()
    except:
        pass
    # cleanup
    pipeline.set_state(Gst.State.NULL)

if __name__ == '__main__':
    # sys.exit(main(sys.argv))
    demo()


import cv2
import numpy as np

def thresholding(img):

    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower_white = np.array([80, 0, 0])
    upper_white = np.array([255,100,255])
    mask_white = cv2.inRange(img_hsv, lower_white, upper_white)
    return mask_white

def warp_img(img, points, w, h, inverse = False):
    pts1 = np.float32(points)
    pts2 = np.float32([[0, 0], [w, 0], [0, h], [w, h]])

    if inverse:
        matrix = cv2.getPerspectiveTransform(pts2, pts1)
    else:
        matrix = cv2.getPerspectiveTransform(pts1, pts2)
    img_warp = cv2.warpPerspective(img, matrix, (w, h))
    return img_warp

def nothing(a):
    pass

def initialize_trackbars(initial_trackbar_vals, w_t = 480, h_t = 240):
    cv2.namedWindow("Trackbars")
    cv2.resizeWindow("Trackbars", 360, 240)
    cv2.createTrackbar("Width Top", "Trackbars", initial_trackbar_vals[0], w_t//2, nothing)
    cv2.createTrackbar("Height Top", "Trackbars", initial_trackbar_vals[1], h_t, nothing)
    cv2.createTrackbar("Width Bottom", "Trackbars", initial_trackbar_vals[2], w_t // 2, nothing)
    cv2.createTrackbar("Height Bottom", "Trackbars", initial_trackbar_vals[3], h_t, nothing)

def val_trackbars(w_t = 480, h_t = 240):
    width_top = cv2.getTrackbarPos("Width Top", "Trackbars")
    height_top = cv2.getTrackbarPos("Height Top", "Trackbars")
    width_bottom = cv2.getTrackbarPos("Width Bottom", "Trackbars")
    height_bottom = cv2.getTrackbarPos("Height Bottom", "Trackbars")
    points = np.float32([(width_top, height_top), (w_t - width_top, height_top),
                         (width_bottom, height_bottom), (w_t - width_bottom, height_bottom)])
    return points

def draw_points(img, points):
    for x in range(4):
        cv2.circle(img, (int(points[x][0]), int(points[x][1])), 15, (0, 0, 255), cv2.FILLED)
    return img

def get_histogram(img, min_per = 0.1, display = False, region = 1):
    if region == 1:
        histogram_vals = np.sum(img, axis = 0)
    else:
        histogram_vals = np.sum(img[img.shape[0] // region:,:], axis = 0)
    #print(histogram_vals)
    max_value = np.max(histogram_vals)
    min_value = min_per * max_value

    index_array = np.where(histogram_vals >= min_value)
    base_point = int(np.average(index_array))

    if display:
        img_histogram = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)
        for x, intensity in enumerate(histogram_vals):
            cv2.line(img_histogram, (x, img.shape[0]), (x,img.shape[0] - intensity // 255 // region), (255, 0, 255), 1)
            cv2.circle(img_histogram, (base_point, img.shape[0]), 20, (0, 255, 255), cv2.FILLED)
        return base_point, img_histogram

    return base_point

def stack_images(scale, img_array):
    rows = len(img_array)
    cols = len(img_array[0])
    rows_available = isinstance(img_array[0], list)
    width = img_array[0][0].shape[1]
    height = img_array[0][0].shape[0]
    if rows_available:
        for x in range(0, rows):
            for y in range(0, cols):
                if img_array[x][y].shape[:2] == img_array[0][0].shape[:2]:
                    img_array[x][y] = cv2.resize(img_array[x][y], (0, 0), None, scale, scale)
                else:
                    img_array[x][y] = cv2.resize(img_array[x][y], (img_array[0][0].shape[1], img_array[0][0].shape[0]),
                                                None, scale, scale)
                if len(img_array[x][y].shape) == 2: img_array[x][y] = cv2.cvtColor(img_array[x][y], cv2.COLOR_GRAY2BGR)
        image_blank = np.zeros((height, width, 3), np.uint8)
        hor = [image_blank] * rows
        hor_con = [image_blank] * rows
        for x in range(0, rows):
            hor[x] = np.hstack(img_array[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if img_array[x].shape[:2] == img_array[0].shape[:2]:
                img_array[x] = cv2.resize(img_array[x], (0, 0), None, scale, scale)
            else:
                img_array[x] = cv2.resize(img_array[x], (img_array[0].shape[1], img_array[0].shape[0]), None, scale, scale)
            if len(img_array[x].shape) == 2: img_array[x] = cv2.cvtColor(img_array[x], cv2.COLOR_GRAY2BGR)
        hor = np.hstack(img_array)
        ver = hor
    return ver


"""https://adventofcode.com/2015/day/20"""

from helper import read

# READ INPUT
data = read("./2015/inputs/20.txt").strip()
# TEST INPUT
# data = read("./2015/inputs/20-test.txt")
# PARSE INPUT
def calculate_presents(house_number: int) -> int:
    return sum(
        house * 10 for house in range(1, house_number + 1) if house_number % house == 0
    )

present_count = int(data)

# Brute force
def visit_houses(present_count: int):
    house = 0
    presents = 0
    while presents <= present_count:
        house += 1
        presents = calculate_presents(house)
        # print(f"{house=},{presents=},{presents/house}")
    return house, presents

# PART 1
present_goal = int(data)
part_1_answer, presents = visit_houses(present_goal)
print(f"PART 1: {part_1_answer}")

# PART 2

part_2_answer = None
print(f"PART 2: {part_2_answer}")


from commands import command_dict
from bounds import in_bounds
import numpy as np
from collections import deque
import logging
import time

class CommandManager:
    def __init__(self, delay=1, qsize=10):
        self.delay = delay
        self.last_act = 0

        # remember the last qsize frames
        self.queue = deque(maxlen=qsize)
        self.qsize = qsize

        logging.basicConfig(level=logging.INFO)

    def recv_boxes(self, boxes):
        if len(boxes) == 1:
            mdpt = self.process_single_hand(boxes[0])
        else:
            mdpts = self.process_dual_hand(boxes)

    def process_single_hand(self, box):
        mdpt = self.midpoint(box)

        command = self.in_bounds(mdpt)
        if command:
            self.action(command)

    def action(self, command):
        if time.time() - self.last_act > self.delay:
            if command in command_dict:
                command_dict[command].f()
            self.last_act = time.time()

    def in_bounds(self, midpoint):
        return in_bounds(midpoint, command_dict)

    def process_dual_hand(self, boxes):
        # euclid distance
        mdpt1 = self.midpoint(boxes[0])
        mdpt2 = self.midpoint(boxes[1])
        dist = np.linalg.norm(mdpt1 - mdpt2)
        self.queue.append(dist)
        if self.isIncreasing():
            self.action("zoomOut")
        elif self.isDecreasing():
            self.action("zoomIn")
        print(dist)
        #print(self.in_bounds(mdpt1), self.in_bounds(mdpt2))

    def isIncreasing(self, min_len=10):
        increase = 0
        queue = list(self.queue)
        if len(queue) < min_len:
            return False
        for i in range(1, len(queue)):
            if queue[i-1] < queue[i]:
                increase += 1

        if increase > min_len // 2:
            # reset queue
            self.queue.clear()
            return True
        return False

    def isDecreasing(self, min_len=10):
        decrease = 0
        queue = list(self.queue)
        if len(queue) < min_len:
            return False
        for i in range(1, len(queue)):
            if queue[i-1] > queue[i]:
                decrease += 1

        if decrease > min_len // 2:
            # reset queue
            self.queue.clear()
            return True
        return False

    def midpoint(self, box):
        return np.mean([[box[0], box[2]], [box[1], box[3]]], axis=1)


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

import coordinate_chart
import normalization

import data.mouse_dataset.mouse_dataset as mouse_dataset

# Dataset parameters
n_train = 500        # Number of training samples to use
random_train = False # Optionally randomly select the training images from the whole dataset
camera_size = 2 * np.array([mouse_dataset.cx, mouse_dataset.cy])

# Manifold learning
target_dim = 2   # The target dimension for ISOMAP.
neighbors_k = 12 # The number of neighbors used for ISOMAP.

# Visualization
embedding_point_radius = 20
vis_point_radius = 20
vis_pc_radius = 20

###########
# Dataset #
###########

if random_train:
	mouse_dataset.load_train()
	train_inds = np.random.choice(mouse_dataset.n_train, n_train, replace=False)
else:
	mouse_dataset.load_train(n_train)
	train_inds = np.arange(n_train)

train_data = np.array([mouse_dataset.train_poses[i] for i in train_inds])[:,:,:2]
normalized_train_data, translations, rotations = normalization.normalize_pointcloud_2d(train_data)

train_clouds = [mouse_dataset.train_clouds[i][:,[1,0]] for i in train_inds]
normalized_train_clouds = [np.matmul(train_clouds[i] - translations[i], rotations[i]) for i in range(n_train)]

####################
# Coordinate Chart #
####################

cc = coordinate_chart.CoordinateChart(normalized_train_data.reshape(n_train,-1), target_dim, neighbors_k)

########################
# Visualization/Figure #
########################

def create_interactive_embedding_visulization(cc, point_cloud_dim):
	fig = plt.figure()
	ax0 = fig.add_subplot(1, 2, 1)
	ax1 = fig.add_subplot(1, 2, 2)
	axes = [ax0, ax1]

	points = axes[0].scatter(cc.embedding[:,0], cc.embedding[:,1], c="grey", s=20**2)
	xlim = axes[0].get_xlim()
	ylim = axes[0].get_ylim()

	every_possible_point = np.concatenate(normalized_train_clouds)
	mfd_xlims = (np.min(every_possible_point[:,0]), np.max(every_possible_point[:,0]))
	mfd_ylims = (np.min(every_possible_point[:,1]), np.max(every_possible_point[:,1]))

	def hover(event):
		xy = np.array([event.xdata, event.ydata])
		if xy[0] is None or xy[1] is None:
			return

		# Find the nearest embedding point
		nearest_idx = -1
		nearest_dist = np.inf
		for i in range(len(cc.embedding)):
			if np.linalg.norm(cc.embedding[i] - xy) < nearest_dist:
				nearest_dist = np.linalg.norm(cc.embedding[i] - xy)
				nearest_idx = i

		# Display the embedding and highlighted point
		axes[0].clear()
		axes[0].scatter(cc.embedding[:,0], cc.embedding[:,1], c="grey", s=embedding_point_radius**2) # Draw the embedding points
		axes[0].scatter([cc.embedding[nearest_idx,0]], [cc.embedding[nearest_idx,1]], c="blue", s=embedding_point_radius**2) # Draw the nearest point
		axes[0].set_xlim(xlim) # Fix axes limits
		axes[0].set_ylim(ylim)

		# Transform the selected point
		point_cloud = normalized_train_data[nearest_idx]
		mouse_cloud = normalized_train_clouds[nearest_idx]

		# Draw the original point cloud
		axes[1].clear()
		axes[1].scatter(mouse_cloud[:,0], mouse_cloud[:,1], s=vis_pc_radius**2, c="grey")
		axes[1].scatter(point_cloud[:,0], point_cloud[:,1], s=vis_point_radius**2, c="blue")
		axes[1].plot(point_cloud[:,0], point_cloud[:,1], c="blue")
		axes[1].set_xlim(mfd_xlims)
		axes[1].set_ylim(mfd_ylims)

		# Update the figure
		fig.canvas.draw_idle()

	fig.canvas.mpl_connect('motion_notify_event', hover)
	mng = plt.get_current_fig_manager()
	mng.resize(*mng.window.maxsize())
	plt.show()

create_interactive_embedding_visulization(cc, 2)


import streamlit as st
import numpy as np
from streamlit_option_menu import option_menu
import anomaly_detect
import data_visualization
import helpers
import inference

st.sidebar.image("https://s3.ap-southeast-1.amazonaws.com/files-scs-prod/public%2Fimages%2F1667201979950-image.png", use_column_width=True)
EXAMPLE_NO = 1
def streamlit_menu(example=1):
    if example == 1:
        # 1. as sidebar menu
        with st.sidebar:
            selected = option_menu(
                    menu_title="AnoBot",  # required
                    options=["Upload Data", "Train & Detect Anomalies","Visualization of Results","Model Inference","Information"],
                    icons=["cloud-upload", "bi bi-search","bi bi-graph-up-arrow",'bullseye', "bi bi-info-square"],  # optional
                    menu_icon="robot",  # optional
                    default_index=0,  # optional

                    styles = {"nav-link-selected": {"background-color": "#009999"},
                         }
            )

        return selected

selected = streamlit_menu(example=EXAMPLE_NO)

if selected == "Upload Data":
    helpers.data_uploader()
if selected == 'Train & Detect Anomalies':
    anomaly_detect.detect_anomalies()
if selected == "Model Inference":
    inference.main()
if selected == 'Visualization of Results':
    data_visualization.viz_anomaly_data()
if selected == 'Information':
    helpers.info()

def histogram_intersection(a, b):
    v = np.minimum(a, b).sum().round(decimals=1)
    return v


#!/usr/bin/env python2

from indices import WORD_INDEX

from apollocaffe.layers import *
from corpus import Scene, Bird # "Scene" and "Bird" refer to namedtuple data, e.g., `` Scene = namedtuple("Scene", ["image_id", "props", "description", "features"]) ´´
                               # Using "Scene" and "Bird" allows to distinguish data without the need for storing it in separate classes.
import numpy as np
from scipy.misc import logsumexp

N_PROP_TYPES = 8
N_PROP_OBJECTS = 35

class EuclideanScorer(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, l_query, ll_targets, labels):
        net = self.apollo_net

        batch_size, n_dims = net.blobs[l_query].shape
        n_targets = len(ll_targets)

        l_cat = "EuclideanScorer_%s_%s_cat" % (self.name, prefix)
        l_inv_query = "EuclideanScorer_%s_%s_inv_query" % (self.name, prefix)
        l_tile_query = "EuclideanScorer_%s_%s_tile_query" % (self.name, prefix)
        l_add_query = "EuclideanScorer_%s_%s_add_query" % (self.name, prefix)
        l_sq = "EuclideanScorer_%s_%s_sq" % (self.name, prefix)
        l_neg = "EuclideanScorer_%s_%s_neg" % (self.name, prefix)
        l_reduce = "EuclideanScorer_%s_%s_reduce" % (self.name, prefix)
        l_label = "EuclideanScorer_%s_%s_target" % (self.name, prefix)
        l_loss = "EuclideanScorer_%s_%s_loss" % (self.name, prefix)

        p_reduce = ["EuclideanScorer_reduce_weight",
                    "EuclideanScorer_reduce_bias"]

        for l_target in ll_targets:
            net.blobs[l_target].reshape((batch_size, n_dims, 1, 1))
        net.f(Concat(l_cat, axis=2, bottoms=ll_targets))
        net.f(Power(l_inv_query, scale=-1, bottoms=[l_query]))
        net.blobs[l_inv_query].reshape((batch_size, n_dims, 1, 1))
        net.f(Tile(l_tile_query, tiles=n_targets, axis=2, bottoms=[l_inv_query]))
        net.f(Eltwise(l_add_query, "SUM", bottoms=[l_tile_query, l_cat]))
        net.f(Power(l_sq, power=2, bottoms=[l_add_query]))
        net.f(Power(l_neg, scale=-1, bottoms=[l_sq]))
        net.f(Convolution(
            l_reduce, (1,1), 1, bottoms=[l_neg], param_names=p_reduce,
            param_lr_mults=[0,0], weight_filler=Filler("constant", 1),
            bias_filler=Filler("constant", 0)))
        net.blobs[l_reduce].reshape((batch_size, n_targets))
        net.f(NumpyData(l_label, labels))
        loss = net.f(SoftmaxWithLoss(l_loss, bottoms=[l_reduce, l_label]))
        denominators = logsumexp(net.blobs[l_reduce].data, axis=1)
        chosen_logprobs = net.blobs[l_reduce].data[range(batch_size), labels.astype(int)]
        chosen_logprobs -= denominators

        predictions = np.argmax(net.blobs[l_reduce].data, axis=1)
        acc = np.mean(predictions==labels)
        accs = predictions == labels

        return chosen_logprobs, accs

# Choice ranker R
#   The choice ranker takes a string encoding and a collection of referent encodings,
#   assigns a score to each (string, referent) pair, and then transforms these scores
#   into a distribution over referents.
class MlpScorer(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    #                         v--Corresponds to ``l_string_enc´´ in the caller.
    #                         v        v--Corresponds to ``ll_scenes´´ in the caller.
    #                         v        v           v--Array of zeros.
    def forward(self, prefix, l_query, ll_targets, labels):
        """
            l_query: Embedding of a description (i.e., caption) of shape torch.Size([100, 100])
            ll_targets: Embedding of Scenes (target and distractor). It is a list of tensors 2 tensors each of shape torch.Size([100, 100])
            prefix : Not used --> Passed to forward() only with an empty string.
        """
        net = self.apollo_net

        batch_size, n_dims = net.blobs[l_query].shape
        n_targets = len(ll_targets)

        l_cat = "MlpScorer_%s_%s_cat" % (self.name, prefix)
        l_tile_query = "MlpScorer_%s_%s_tile_query" % (self.name, prefix)
        l_sum = "MlpScorer_%s_%s_sum" % (self.name, prefix)
        l_relu = "MlpScorer_%s_%s_relu" % (self.name, prefix)
        l_ip = "MlpScorer_%s_%s_ip" % (self.name, prefix)
        l_label = "MlpScorer_%s_%s_label" % (self.name, prefix)
        l_loss = "MlpScorer_%s_%s_loss" % (self.name, prefix)

        p_ip = ["MlpScorer_%s_weight", "MlpScorer_%s_bias"]

        for l_target in ll_targets:
            net.blobs[l_target].reshape((batch_size, 1, n_dims))
        net.blobs[l_query].reshape((batch_size, 1, n_dims))
        net.f(Concat(l_cat, axis=1, bottoms=ll_targets)) # Put target and distractor scene ("referent") in same blob. Assumption: Horizontal concatenation.
        net.f(Tile(l_tile_query, tiles=n_targets, axis=1, bottoms=[l_query])) # Make the shape of the description embedding match the shape of the scenes embedding.
        net.f(Eltwise(l_sum, "SUM", bottoms=[l_tile_query, l_cat]))
        net.f(ReLU(l_relu, bottoms=[l_sum]))
        net.f(InnerProduct(l_ip, 1, bottoms=[l_relu], axis=2, param_names=p_ip)) # l_ip -> Inner Product.
        net.blobs[l_ip].reshape((batch_size, n_targets))
        net.f(NumpyData(l_label, labels))    #              v--Row vector with all values 0.
        loss = net.f(SoftmaxWithLoss(l_loss, bottoms=[l_ip, l_label]))

        denominators = logsumexp(net.blobs[l_ip].data, axis=1) # Denominator of equation (3).
        chosen_logprobs = net.blobs[l_ip].data[range(batch_size), labels.astype(int)]
        chosen_logprobs -= denominators

        predictions = np.argmax(net.blobs[l_ip].data, axis=1)
        accs = predictions == labels

        return chosen_logprobs, accs

# Referent encoder (section 3.2)
class LinearSceneEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        net = self.apollo_net

        # What type of data do we have? Is it abstract scenes...?
        if isinstance(scenes[0], Scene):
            feature_data = np.zeros((len(scenes), N_PROP_TYPES * N_PROP_OBJECTS)) # For the final evaluation, this was an array of size ``100 x 280´´ (c.f.: section 4.4).
            #                                                                       Because 100 samples were used.
            for i_scene, scene in enumerate(scenes):
                for prop in scene.props:
                    #            v--0..99 v-- 0..7 (sky object s ... toy object t) v--35            v--specifies the exact object (=png image) of the given type.
                    feature_data[i_scene, prop.type_index *                        N_PROP_OBJECTS + prop.object_index] = 1
                    # INTERPRETATION:
                    #   The number of ones ``1´´ corresponds to the number of features used. The position of the ones ``1´´ corresponds to which exact feature (i.e., png-feature image) was used.
                    #   Thus, EACH scene or referent is represented as 1x280 row vector.  This IS the feature representation f(r) --> c.f. section 3.1 in the paper.
        else:
            # ...or rather birds?
            assert isinstance(scenes[0], Bird)
            feature_data = np.zeros((len(scenes), len(scenes[0].features)))
            for i_scene, scene in enumerate(scenes):
                feature_data[i_scene, :] = scenes[i_scene].features # "features" == feature representation f(r) of one referent (i.e., of one image).
                                                                    # --> Set during load_scenes() in corpus.py

        l_data = "LinearSceneEncoder%s_%s_data" % (self.name, prefix)
        l_drop = "LinearSceneEncoder%s_%s_drop" % (self.name, prefix)
        l_ip1 = "LinearSceneEncoder%s_%s_ip1" % (self.name, prefix)
        l_relu1 = "LinearSceneEncoder%s_%s_relu1" % (self.name, prefix)
        l_ip2 = "LinearSceneEncoder%s_%s_ip2" % (self.name, prefix)

        p_ip1 = ["LinearSceneEncoder%s_ip1_weight" % self.name,
                 "LinearSceneEncoder%s_ip1_bias" % self.name]
        p_ip2 = ["LinearSceneEncoder%s_ip2_weight" % self.name,
                 "LinearSceneEncoder%s_ip2_bias" % self.name]

        #               v-- name (passes a string as label)
        #               v       v-- the actual data
        net.f(NumpyData(l_data, feature_data))
        # ``InnerProduct´´ is a fully connected layer. ``nn.Linear´´ is the PyTorch equivalent. The following command creates the referent encoding E_r --> c.f. equation (1) in section 3.2
        net.f(InnerProduct(
                l_ip1, self.config.hidden_size, bottoms=[l_data], # ``bottoms´´ is the input data to this layer.
                param_names=p_ip1))

        return l_ip1

# Description encoder (section 3.2)
class LinearStringEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        """
            scenes : Description, i.e., sentence, to be encoded.
        """
        net = self.apollo_net

        # For the final experiment, ``feature_data´´ takes the following format: 100 x 1063.
        #                        v--100     , v--1063
        feature_data = np.zeros((len(scenes), len(WORD_INDEX)))
        for i_scene, scene in enumerate(scenes):
            for word in scene.description:          # "description" attribute comes from the "Scenes" namedtuple from corpus.py
                feature_data[i_scene, word] += 1    # ``feature_data´´ contains integer numbers >= 0 (i.e., 0, 1, 2, ...)

        l_data = "LinearStringEncoder_%s_%s_data" % (self.name, prefix)
        l_ip = "LinearStringEncoder_%s_%s_ip" % (self.name, prefix)

        p_ip = ["LinearStringEncoder_%s_ip_weight" % self.name,
                "LinearStringEncoder_%s_ip_bias" % self.name]

        net.f(NumpyData(l_data, feature_data))
        net.f(InnerProduct(
                l_ip, self.config.hidden_size, bottoms=[l_data],
                param_names=p_ip))

        return l_ip

class BowSceneEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        net = self.apollo_net

        max_props = max(len(scene.props) for scene in scenes)
        type_data = np.zeros((len(scenes), max_props))
        object_data = np.zeros((len(scenes), max_props))
        feature_data = np.zeros((len(scenes), max_props, 4))
        for i_scene, scene in enumerate(scenes):
            offset = max_props - len(scene.props)
            for i_prop, prop in enumerate(scene.props):
                type_data[i_scene, offset+i_prop] = prop.type_index
                object_data[i_scene, offset+i_prop] = prop.object_index
                feature_data[i_scene, offset+i_prop, :] = \
                        [prop.x, prop.y, prop.z, prop.flip]

        l_type = "BowSceneEncoder_%s_%s_type_%d"
        l_object = "BowSceneEncoder_%s_%s_object_%d"
        l_feature = "BowSceneEncoder_%s_%s_feature_%d"
        l_type_vec = "BowSceneEncoder_%s_%s_type_vec_%d"
        l_object_vec = "BowSceneEncoder_%s_%s_object_vec_%d"
        l_prop = "BowSceneEncoder_%s_%s_prop_%d"
        l_all_props = "BowSceneEncoder_%s_%s_all_props" % (self.name, prefix)
        l_drop = "BowSceneEncoder_%s_%s_drop" % (self.name, prefix)
        l_ip1 = "BowSceneEncoder_%s_%s_ip1" % (self.name, prefix)
        l_relu1 = "BowSceneEncoder_%s_%s_relu1" % (self.name, prefix)
        l_ip2 = "BowSceneEncoder_%s_%s_ip2" % (self.name, prefix)

        p_type_vec = ["BowSceneEncoder_%s_type_vec" % self.name]
        p_object_vec = ["BowSceneEncoder_%s_object_vec" % self.name]
        p_ip1 = ["BowSceneEncoder_%s_ip1_weight" % self.name,
                 "BowSceneEncoder_%s_ip1_bias" % self.name]
        p_ip2 = ["BowSceneEncoder_%s_ip2_weight" % self.name,
                 "BowSceneEncoder_%s_ip2_bias" % self.name]

        for i_step in range(max_props):
            l_type_i = l_type % (self.name, prefix, i_step)
            l_object_i = l_object % (self.name, prefix, i_step)
            l_feature_i = l_feature % (self.name, prefix, i_step)
            l_type_vec_i = l_type_vec % (self.name, prefix, i_step)
            l_object_vec_i = l_object_vec % (self.name, prefix, i_step)
            l_prop_i = l_prop % (self.name, prefix, i_step)

            net.f(NumpyData(l_type_i, type_data[:, i_step]))
            net.f(NumpyData(l_object_i, object_data[:, i_step]))
            net.f(NumpyData(l_feature_i, feature_data[:, i_step]))
            net.f(Wordvec(
                    l_type_vec_i, self.config.prop_embedding_size, N_PROP_TYPES,
                    bottoms=[l_type_i], param_names=p_type_vec))
            net.f(Wordvec(
                    l_object_vec_i, self.config.prop_embedding_size, N_PROP_OBJECTS,
                    bottoms=[l_object_i], param_names=p_object_vec))
            net.f(Concat(
                    l_prop_i,
                    bottoms=[l_type_vec_i, l_object_vec_i, l_feature_i]))

        net.f(Eltwise(
                l_all_props, "SUM",
                bottoms=[l_prop % (self.name, prefix, i_step)
                         for i_step in range(max_props)]))
        if dropout:
            net.f(Dropout(l_drop, 0.5, bottoms=[l_all_props]))
            l_p = l_drop
        else:
            l_p = l_all_props

        net.f(InnerProduct(
                l_ip1, self.config.hidden_size, bottoms=[l_p],
                param_names=p_ip1))

        return l_ip1

class BowStringEncoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, scenes, dropout):
        net = self.apollo_net

        max_words = max(len(scene.description) for scene in scenes)
        word_data = np.zeros((len(scenes), max_words))
        for i_scene, scene in enumerate(scenes):
            offset = max_words - len(scene.description)
            for i_word, word in enumerate(scene.description):
                word_data[i_scene, offset+i_word] = word

        l_word = "BowStringEncoder_%s_%s_word_%d"
        l_word_vec = "BowStringEncoder_%s_%s_word_vec_%d"
        l_all_words = "BowStringEncoder_%s_%s_all_words" % (self.name, prefix)
        l_drop = "BowStringEncoder_%s_%s_drop" % (self.name, prefix)
        l_ip1 = "BowStringEncoder_%s_%s_ip1" % (self.name, prefix)
        l_relu1 = "BowStringEncoder_%s_%s_relu1" % (self.name, prefix)
        l_ip2 = "BowStringEncoder_%s_%s_ip2" % (self.name, prefix)

        p_word_vec = ["BowStringEncoder_%s_word_vec" % self.name]
        p_ip1 = ["BowStringEncoder_%s_ip1_weight" % self.name,
                 "BowStringEncoder_%s_ip1_param" % self.name]
        p_ip2 = ["BowStringEncoder_%s_ip2_weight" % self.name,
                 "BowStringEncoder_%s_ip2_param" % self.name]

        for i_step in range(max_words):
            l_word_i = l_word % (self.name, prefix, i_step)
            l_word_vec_i = l_word_vec % (self.name, prefix, i_step)

            net.f(NumpyData(l_word_i, word_data[:, i_step]))
            net.f(Wordvec(
                    l_word_vec_i, self.config.word_embedding_size,
                    len(WORD_INDEX), bottoms=[l_word_i], param_names=p_word_vec))

        net.f(Eltwise(
                l_all_words, "MAX",
                bottoms=[l_word_vec % (self.name, prefix, i_step)
                         for i_step in range(max_words)]))

        if dropout:
            net.f(Dropout(l_drop, 0.5, bottoms=[l_all_words]))
            l_r = l_drop
        else:
            l_r = l_all_words

        net.f(InnerProduct(
                l_ip1, self.config.hidden_size, bottoms=[l_r],
                param_names=p_ip1))
        net.f(ReLU(l_relu1, bottoms=[l_ip1]))
        net.f(InnerProduct(
                l_ip2, self.config.hidden_size, bottoms=[l_relu1],
                param_names=p_ip2))

        return l_ip2

# The referent describer D takes an image encoding and outputs a description using a (feedforward) conditional neural language model.
class MlpStringDecoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, encoding, scenes, dropout):
        """
        encoding: Is the linear embedding tensor of the targets ``scenes´´ (equation (1)).
        scenes  : Target scenes.
        """
        net = self.apollo_net

        max_words = max(len(scene.description) for scene in scenes)
        history_features = np.zeros((len(scenes), max_words, len(WORD_INDEX)))
        last_features = np.zeros((len(scenes), max_words, len(WORD_INDEX)))
        targets = np.zeros((len(scenes), max_words))
        for i_scene, scene in enumerate(scenes): # For each scene, parse its description and...
            #                             v--Example: description=[1, 2, 248, 11, 295, 14]
            for i_word, word in enumerate(scene.description): # ...for every single word within the description...
                if word == 0:
                    continue #       v--Starting position always changes (by one index ahead).
                for ii_word in range(i_word + 1, len(scene.description)): #...look at vocabulary index of the words starting from the second till last position.
                #                                                          That is, we look at progressively smaller parts of the description as the index ii_word...
                #                                                          keeps moving further and further towards the right boundary of the description.
                    history_features[i_scene, ii_word, word] += 1
                last_features[i_scene, i_word, word] += 1
                targets[i_scene, i_word] = word

        l_history_data = "MlpStringDecoder_%s_%s_history_data_%d"
        l_last_data = "MlpStringDecoder_%s_%s_last_data_%d"
        l_cat_features = "MlpStringDecoder_%s_%s_cat_features_%d"
        l_ip1 = "MlpStringDecoder_%s_%s_ip1_%d"
        l_cat = "MlpStringDecoder_%s_%s_cat_%d"
        l_relu1 = "MlpStringDecoder_%s_%s_relu1_%d"
        l_ip2 = "MlpStringDecoder_%s_%s_ip2_%d"
        l_target = "MlpStringDecoder_%s_%s_target_%d"
        l_loss = "MlpStringDecoder_%s_%s_loss_%d"

        p_ip1 = ["MlpStringDecoder_%s_ip1_weight" % self.name,
                 "MlpStringDecoder_%s_ip1_bias" % self.name]
        p_ip2 = ["MlpStringDecoder_%s_ip2_weight" % self.name,
                 "MlpStringDecoder_%s_ip2_bias" % self.name]

        loss = 0
        for i_step in range(1, max_words):
            l_history_data_i = l_history_data % (self.name, prefix, i_step)
            l_last_data_i = l_last_data % (self.name, prefix, i_step)
            l_cat_features_i = l_cat_features % (self.name, prefix, i_step)
            l_ip1_i = l_ip1 % (self.name, prefix, i_step)
            l_cat_i = l_cat % (self.name, prefix, i_step)
            l_relu1_i = l_relu1 % (self.name, prefix, i_step)
            l_ip2_i = l_ip2 % (self.name, prefix, i_step)
            l_target_i = l_target % (self.name, prefix, i_step)
            l_loss_i = l_loss % (self.name, prefix, i_step)

            net.f(NumpyData(l_history_data_i, history_features[:,i_step-1,:]))
            net.f(NumpyData(l_last_data_i, last_features[:,i_step-1,:]))
            net.f(Concat(l_cat_features_i, bottoms=[l_history_data_i, l_last_data_i]))
            net.f(InnerProduct(l_ip1_i, self.config.hidden_size, bottoms=[l_cat_features_i], param_names=p_ip1)) # (W7 @ [dn, d<n, ei])
            net.f(Concat(l_cat_i, bottoms=[l_ip1_i, encoding])) # Taking the referent embedding of the target scene into account.
            net.f(ReLU(l_relu1_i, bottoms=[l_cat_i]))
            net.f(InnerProduct(l_ip2_i, len(WORD_INDEX), bottoms=[l_relu1_i],param_names=p_ip2))                 # W6 @ ReLU(...)
            net.f(NumpyData(l_target_i, targets[:,i_step]))     # This is the target...
            loss += net.f(SoftmaxWithLoss(                      # ...here, the loss of the prediction vs. target is computed!
                l_loss_i, bottoms=[l_ip2_i, l_target_i],
                ignore_label=0, normalize=False))

        return -np.asarray(loss)

    """
    Draws a sequence of words, i.e., samples d_1, ..., d_n ~ p_S0(.|r_i)

    Remark: The paper does not specify, how the sampling actually works.
            This seems to be an "implementational detail".
    """
    def sample(self, prefix, encoding, viterbi):
        """
        encoding: Encoding of abstract scene image, i.e., referent encoding.
        viterbi : Decoding scheme:
                    ``False´´ corresponds to greedy sampling: Randomly sample index of one word from the vocabulary.
                    ``True´´ corresponds to pure sampling (non-deterministic; truly random).
                    Note: Set to False in the pragmatic speaker S1 (SamplingSpeaker1).
        """
        net = self.apollo_net

        max_words = 20
        batch_size = net.blobs[encoding].shape[0]

        out_logprobs = np.zeros((batch_size,))
        samples = np.zeros((batch_size, max_words))
        history_features = np.zeros((batch_size, len(WORD_INDEX)))
        last_features = np.zeros((batch_size, len(WORD_INDEX)))
        samples[:,0] = WORD_INDEX["<s>"]
        last_features[:,WORD_INDEX["<s>"]] += 1

        l_history_data = "MlpStringDecoder_%s_%s_history_data_%d"
        l_last_data = "MlpStringDecoder_%s_%s_last_data_%d"
        l_cat_features = "MlpStringDecoder_%s_%s_cat_features_%d"
        l_ip1 = "MlpStringDecoder_%s_%s_ip1_%d"
        l_cat = "MlpStringDecoder_%s_%s_cat_%d"
        l_relu1 = "MlpStringDecoder_%s_%s_relu1_%d"
        l_ip2 = "MlpStringDecoder_%s_%s_ip2_%d"
        l_softmax = "MlpStringDecoder_%s_%s_softmax_%d"

        p_ip1 = ["MlpStringDecoder_%s_ip1_weight" % self.name,
                 "MlpStringDecoder_%s_ip1_bias" % self.name]
        p_ip2 = ["MlpStringDecoder_%s_ip2_weight" % self.name,
                 "MlpStringDecoder_%s_ip2_bias" % self.name]

        # Compute sampling distribution p_S0:
        for i_step in range(1, max_words):
            l_history_data_i = l_history_data % (self.name, prefix, i_step)
            l_last_data_i = l_last_data % (self.name, prefix, i_step)
            l_cat_features_i = l_cat_features % (self.name, prefix, i_step)
            l_ip1_i = l_ip1 % (self.name, prefix, i_step)
            l_cat_i = l_cat % (self.name, prefix, i_step)
            l_relu1_i = l_relu1 % (self.name, prefix, i_step)
            l_ip2_i = l_ip2 % (self.name, prefix, i_step)
            l_softmax_i = l_softmax % (self.name, prefix, i_step)

            net.f(DummyData(l_history_data_i, (1,1,1,1))) # Initialise tensor with random values.
            net.blobs[l_history_data_i].reshape(history_features.shape)
            net.f(DummyData(l_last_data_i, (1,1,1,1)))    # Initialise tensor with random values.
            net.blobs[l_last_data_i].reshape(last_features.shape)
            net.blobs[l_history_data_i].data[...] = history_features
            net.blobs[l_last_data_i].data[...] = last_features
            net.f(Concat(l_cat_features_i, bottoms=[l_history_data_i, l_last_data_i]))
            net.f(InnerProduct(
                l_ip1_i, self.config.hidden_size, bottoms=[l_cat_features_i],
                param_names=p_ip1))
            net.f(Concat(l_cat_i, bottoms=[l_ip1_i, encoding]))
            net.f(ReLU(l_relu1_i, bottoms=[l_cat_i]))
            net.f(InnerProduct(
                l_ip2_i, len(WORD_INDEX), bottoms=[l_relu1_i],
                param_names=p_ip2))
            net.f(Softmax(l_softmax_i, bottoms=[l_ip2_i]))

            # Draw samples (i.e., words d_i) from probability distribution p_S0:
            probs = net.blobs[l_softmax_i].data
            history_features += last_features
            last_features[...] = 0
            for i_datum in range(batch_size):
                d_probs = probs[i_datum,:].astype(float)
                d_probs /= d_probs.sum()
                if viterbi:
                    choice = d_probs.argmax() # Find index of largest word-probability.
                else:
                    choice = np.random.multinomial(1, d_probs).argmax() # Randomly draw one sample, i.e., get the index of one single word from the vocabulary.
                samples[i_datum, i_step] = choice
                last_features[i_datum, choice] += 1
                out_logprobs[i_datum] += np.log(d_probs[choice])

        # This creates a candidate caption / sentence / description of the image e_r.
        out_samples = []
        for i in range(samples.shape[0]):
            this_sample = []
            for j in range(samples.shape[1]):
                word = WORD_INDEX.get(samples[i,j])
                #this_sample.append(word)
                this_sample.append(samples[i,j])
                if word == "</s>":
                    break
            if this_sample[-1] != WORD_INDEX["</s>"]:
                this_sample.append(WORD_INDEX["</s>"])
            out_samples.append(this_sample)
        return out_logprobs, out_samples

class LstmStringDecoder(object):
    def __init__(self, name, apollo_net, config):
        self.name = name
        self.apollo_net = apollo_net
        self.config = config

    def forward(self, prefix, encoding, scenes, dropout):
        net = self.apollo_net

        max_words = max(len(scene.description) for scene in scenes)
        word_data = np.zeros((len(scenes), max_words))
        for i_scene, scene in enumerate(scenes):
            offset = max_words - len(scene.description)
            for i_word, word in enumerate(scene.description):
                #word_data[i_scene, offset+i_word] = word
                word_data[i_scene, i_word] = word

        l_seed = "LstmStringDecoder_%s_%s_seed" % (self.name, prefix)
        l_prev_word = "LstmStringDecoder_%s_%s_word_%d"
        l_word_vec = "LstmStringDecoder_%s_%s_word_vec_%d"
        l_drop_in = "LstmStringDecoder_%s_%s_drop_in_%d"
        l_concat = "LstmStringDecoder_%s_%s_concat_%d"
        l_lstm = "LstmStringDecoder_%s_%s_lstm_%d"
        l_hidden = "LstmStringDecoder_%s_%s_hidden_%d"
        l_mem = "LstmStringDecoder_%s_%s_mem_%d"
        l_drop_out = "LstmStringDecoder_%s_%s_drop_out_%d"
        l_output = "LstmStringDecoder_%s_%s_output_%d"
        l_target = "LstmStringDecoder_%s_%s_target_%d"
        l_loss = "LstmStringDecoder_%s_%s_loss_%d"

        p_word_vec = ["LstmStringDecoder_%s_word_vec" % self.name]
        p_lstm = ["LstmStringDecoder_%s_lstm_iv" % self.name,
                  "LstmStringDecoder_%s_lstm_ig" % self.name,
                  "LstmStringDecoder_%s_lstm_fg" % self.name,
                  "LstmStringDecoder_%s_lstm_og" % self.name]
        p_output = ["LstmStringDecoder_%s_output_weight" % self.name,
                    "LstmStringDecoder_%s_output_bias" % self.name]

        loss = 0
        net.f(NumpyData(
                l_seed, np.zeros((len(scenes), self.config.hidden_size))))
        for i_step in range(1, max_words):
            l_prev_word_i = l_prev_word % (self.name, prefix, i_step)
            l_word_vec_i = l_word_vec % (self.name, prefix, i_step)
            l_drop_in_i = l_drop_in % (self.name, prefix, i_step)
            l_concat_i = l_concat % (self.name, prefix, i_step)
            l_lstm_i = l_lstm % (self.name, prefix, i_step)
            l_hidden_i = l_hidden % (self.name, prefix, i_step)
            l_mem_i = l_mem % (self.name, prefix, i_step)
            l_drop_out_i = l_drop_out % (self.name, prefix, i_step)
            l_output_i = l_output % (self.name, prefix, i_step)
            l_target_i = l_target % (self.name, prefix, i_step)
            l_loss_i = l_loss % (self.name, prefix, i_step)

            if i_step == 1:
                prev_hidden = l_seed
                prev_mem = l_seed
            else:
                prev_hidden = l_hidden % (self.name, prefix, i_step - 1)
                prev_mem = l_mem % (self.name, prefix, i_step - 1)

            net.f(NumpyData(l_prev_word_i, word_data[:, i_step-1]))
            net.f(Wordvec(
                    l_word_vec_i, self.config.word_embedding_size,
                    len(WORD_INDEX), bottoms=[l_prev_word_i],
                    param_names=p_word_vec))
            #if dropout:
            #    net.f(Dropout(l_drop_in_i, 0.5, bottoms=[l_word_vec_i]))
            #    l_wv = l_drop_in_i
            #else:
            #    l_wv = l_word_vec_i
            net.f(Concat(l_concat_i, bottoms=[prev_hidden, l_word_vec_i, encoding]))
            net.f(LstmUnit(
                    l_lstm_i, bottoms=[l_concat_i, prev_mem],
                    param_names=p_lstm, tops=[l_hidden_i, l_mem_i],
                    num_cells=self.config.hidden_size))
            net.f(NumpyData(l_target_i, word_data[:, i_step]))
            #if dropout:
            #    net.f(Dropout(l_drop_out_i, 0.5, bottoms=[l_hidden_i]))
            #    l_h = l_drop_out_i
            #else:
            #    l_h = l_hidden_i
            net.f(InnerProduct(
                    l_output_i, len(WORD_INDEX), bottoms=[l_hidden_i],
                    param_names=p_output))
            loss += net.f(SoftmaxWithLoss(
                    #l_loss_i, bottoms=[l_output_i, l_target_i]))
                    l_loss_i, ignore_label=0, bottoms=[l_output_i, l_target_i]))

        return np.asarray(loss)

    # TODO consolidate
    def sample(self, prefix, encoding, viterbi):
        net = self.apollo_net

        batch_size = net.blobs[encoding].shape[0]
        max_words = 20

        l_seed = "LstmStringDecoder_%s_%s_seed"
        l_prev_word = "LstmStringDecoder_%s_%s_word_%d"
        l_word_vec = "LstmStringDecoder_%s_%s_word_vec_%d"
        l_concat = "LstmStringDecoder_%s_%s_concat_%d"
        l_lstm = "LstmStringDecoder_%s_%s_lstm_%d"
        l_hidden = "LstmStringDecoder_%s_%s_hidden_%d"
        l_mem = "LstmStringDecoder_%s_%s_mem_%d"
        l_output = "LstmStringDecoder_%s_%s_output_%d"
        l_softmax = "LstmStringDecoder_%s_%s_softmax_%d"

        p_word_vec = ["LstmStringDecoder_%s_word_vec" % self.name]
        p_lstm = ["LstmStringDecoder_%s_lstm_iv" % self.name,
                  "LstmStringDecoder_%s_lstm_ig" % self.name,
                  "LstmStringDecoder_%s_lstm_fg" % self.name,
                  "LstmStringDecoder_%s_lstm_og" % self.name]
        p_output = ["LstmStringDecoder_%s_output_weight" % self.name,
                    "LstmStringDecoder_%s_output_bias" % self.name]

        samples = np.zeros((batch_size, max_words), dtype=int)
        samples[:,0] = WORD_INDEX["<s>"]

        net.f(NumpyData(
                l_seed, np.zeros((batch_size, self.config.hidden_size))))
        for i_step in range(1, max_words):
            l_prev_word_i = l_prev_word % (self.name, prefix, i_step)
            l_word_vec_i = l_word_vec % (self.name, prefix, i_step)
            l_concat_i = l_concat % (self.name, prefix, i_step)
            l_lstm_i = l_lstm % (self.name, prefix, i_step)
            l_hidden_i = l_hidden % (self.name, prefix, i_step)
            l_mem_i = l_mem % (self.name, prefix, i_step)
            l_output_i = l_output % (self.name, prefix, i_step)
            l_softmax_i = l_softmax % (self.name, prefix, i_step)

            if i_step == 1:
                prev_hidden = l_seed
                prev_mem = l_seed
            else:
                prev_hidden = l_hidden % (self.name, prefix, i_step - 1)
                prev_mem = l_mem % (self.name, prefix, i_step - 1)

            net.f(NumpyData(l_prev_word_i, samples[:, i_step-1]))
            net.f(Wordvec(
                    l_word_vec_i, self.config.word_embedding_size,
                    len(WORD_INDEX), bottoms=[l_prev_word_i],
                    param_names=p_word_vec))
            net.f(Concat(
                    l_concat_i, bottoms=[prev_hidden, l_word_vec_i, encoding]))
            net.f(LstmUnit(
                    l_lstm_i, bottoms=[l_concat_i, prev_mem],
                    param_names=p_lstm, tops=[l_hidden_i, l_mem_i],
                    num_cells=self.config.hidden_size))
            net.f(InnerProduct(
                    l_output_i, len(WORD_INDEX), bottoms=[l_hidden_i],
                    param_names=p_output))
            net.f(Softmax(l_softmax_i, bottoms=[l_output_i]))

            choices = []
            for i in range(batch_size):
                probs = net.blobs[l_softmax_i].data[i,:].astype(np.float64)
                probs /= probs.sum()
                if viterbi:
                    choices.append(np.argmax(probs))
                else:
                    choices.append(np.random.choice(len(WORD_INDEX), p=probs))
            samples[:, i_step] = choices

        out_samples = []
        for i in range(samples.shape[0]):
            this_sample = []
            for j in range(samples.shape[1]):
                word = WORD_INDEX.get(samples[i,j])
                this_sample.append(samples[i,j])
                if word == "</s>":
                    break
            out_samples.append(this_sample)
        return out_samples


# import imageio.v3 as iio
import imageio
import csv
import os

# 找要疊加的圖片
def findPictureName(id):
    # 要疊加的照片
    statckList = []
    order = 0
    print("GEI ID:",id)
    for data in cut_shot:
        # cut
        if data[1] == 1 and statckList != []:
            if order == id:
                break
            order += 1
            statckList.clear()
        # shot
        elif data[1] == 0:
            # data[0]: 彩色 PM2.5 圖片名字
            statckList.append(data[0])
    return statckList
def makeGif(cutType,id,speed,year):
    # 要疊成 gif 的圖片
    stackList = findPictureName(id)
    path = f"./image/{year}/{cutType}/{id}.gif"
    images = []
    for filename in stackList:
        filename = filename.replace("/","-")
        filename = filename.replace(" ","-")
        filename = filename.replace(":","-")
        filename += ".png"
        images.append(imageio.imread("../../sis/"+filename))
    imageio.mimsave(path,images,duration=speed)
    '''
    with imageio.get_writer(path, mode='I',fps=speed) as writer:
        for filename in stackList:
            filename = filename.replace("/","-")
            filename = filename.replace(" ","-")
            filename = filename.replace(":","-")
            filename += ".png"
            image = imageio.imread("../../sis/"+filename)
            writer.append_data(image)
    '''

def main(cutType,file,sourceCut,year):
    global cut_shot
    # cut and shot
    cut_shot = []
    with open("../../make_GEI/"+sourceCut, newline= '') as csvfile :
        rows = csv.reader(csvfile, delimiter = ',')
        for row in rows :
            try:
                cut_shot.append([row[0]]+list(map(int,row[1:])))
            except:
                pass
    # GEI 數量
    with open(f"../../make_GEI/data/GEI_data/{year}/{cutType}/{file}.csv", newline= '') as csvfile :
        rows = csv.reader(csvfile, delimiter = ',')
        GEINum = len(list(rows))-1 # -1: 去掉標題

    for id in range(GEINum):
        makeGif(cutType,id,2,year)
def createFile(path):
    if os.path.isdir(path) == False:
        os.system("mkdir "+ path)
if __name__ == "__main__":
    # gif 存放在哪一個資料夾
    file = "GEI_origin"
    sourceCut = input("(KMenas.csv、HCED1.csv、RasterScan4.csv)\ncut file = ")# "KMeans.csv"
    cutType = sourceCut[:sourceCut.find(".csv")]
    year = int(input("Please enter the year: "))
    createFile("./image")
    createFile(f"./image/{year}")
    createFile(f"./image/{year}/{cutType}")
    main(cutType,file,sourceCut,year)


import matplotlib.pyplot as plt
import pandas as pd
import pymongo

myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["mydatabase"]

def numb_articles_by_coll(date,col_name):

    # articles from collection
    articles_by_coll = []
    # collection
    col = mydb[col_name]
    cursor = col.find({})
    for document in cursor:
        count = 0
        # for each date check how many articles published
        for d in date:
            for i in range(len(document.get('articles'))):
                if (d in document.get('articles')[i]['publishedAt']):
                    count += 1
            print('Collection ' + col.name + ' has ' + str(count) + ' articles' + ' published at ' + d)
            articles_by_coll.append(count)

    print('\n')
    return articles_by_coll

date = ['2022-12-22', '2022-12-23', '2022-12-24', '2022-12-25', '2022-12-26']
# store number of articles from collections
articles = []
# store name of collections
collections = []

for col_name in mydb.list_collection_names():
    # search all collections except domain name and users
    if col_name != 'sources_domain_name' and col_name != 'users':
        # find and store the number of articles from collection for these dates
        articles.append(numb_articles_by_coll(date, col_name))
        # find and store the collections names that have articles with these dates
        collections.append(col_name)

# create dataframe
df = pd.DataFrame(data={'date': date, collections[0]: articles[0], collections[1]: articles[1], collections[2]: articles[2]
                        , collections[3]: articles[3], collections[4]: articles[4], collections[5]: articles[5]
                        , collections[6]: articles[6], collections[7]: articles[7], collections[8]: articles[8]})

print(df)

# plot
df.plot(x='date', kind='bar', stacked=True)
plt.ylabel("Number of articles")
plt.title('Articles published by category')
plt.show()


import numpy as np
from torchvision import transforms
import torchvision
from torch.utils.data import DataLoader,Dataset
from PIL import Image
import glob
import torch
import torch.nn as nn
import torch.nn.functional as F
import os
import tensorboardX

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
epoch_num = 200
lr = 0.01
#net = VGGNet().to(device)
net = InceptionNetSmall().to(device)
#loss
loss_fun = nn.CrossEntropyLoss()
#optim
optimizer = torch.optim.Adam(net.parameters(),lr = lr)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer,step_size = 5,gamma = 0.9)

if not os.path.exists('F:/DownloadFile/cifar-10-batches-py/log3'):
		os.mkdir('F:/DownloadFile/cifar-10-batches-py/log3')

writer = tensorboardX.SummaryWriter('F:/DownloadFile/cifar-10-batches-py/log3')

#train
step_n = 0
for epoch in range(epoch_num):
	print("epoch is ", epoch)

	for idx,data in enumerate(train_loader):
		net.train()
		inputs,labels = data
		inputs,labels = inputs.to(device),labels.to(device)
		outputs = net(inputs)
		batch_size = inputs.size(0)
		loss = loss_fun(outputs,labels)
		optimizer.zero_grad()
		loss.backward()
		optimizer.step()
		_,pred = torch.max(outputs,dim = 1)
		correct = pred.eq(labels.data).cpu().sum()
		print("train step",idx,"loss is ",loss.item(),"mini-batch correct is ",100.0 * correct / 200)
		writer.add_scalar('train loss',loss.item(),global_step = step_n)
		writer.add_scalar('train correct',100.0 * correct.item() / 200,global_step = step_n)
		step_n += 1
	if not os.path.exists('F:/DownloadFile/cifar-10-batches-py/models'):
		os.mkdir('F:/DownloadFile/cifar-10-batches-py/models')
	torch.save(net.state_dict(),'F:/DownloadFile/cifar-10-batches-py/models/{}.pth'.format(epoch + 1))
	scheduler.step()
	print("train lr is ",optimizer.state_dict()['param_groups'][0]['lr'])

	sum_loss = 0
	sum_correct = 0
	for idx,data in enumerate(test_loader):
		net.eval()
		inputs,labels = data
		inputs,labels = inputs.to(device),labels.to(device)
		outputs = net(inputs)
		batch_size = inputs.size(0)
		loss = loss_fun(outputs,labels)
		_,pred = torch.max(outputs,dim = 1)
		correct = pred.eq(labels.data).cpu().sum()
		sum_loss += loss.item()
		sum_correct += correct.item()

		#print("test step",idx,"loss is ",loss.item(),"mini-batch correct is ",100.0 * correct / 168)
	test_loss = sum_loss * 1.0 / len(test_loader)
	test_correct = sum_correct * 100.0 / len(test_loader) / 200
	writer.add_scalar('test loss',test_loss,global_step = epoch + 1)
	writer.add_scalar('test correct',test_correct,global_step = epoch + 1)
	print("epoch step",epoch + 1,"test loss is ",test_loss,"mini-batch correct is ",test_correct)
writer.close()


#!/usr/bin/env python3
""" Module for using redis in Python """

import redis
from functools import wraps
import requests
from typing import Callable

cache = redis.Redis()

def count_calls(method: Callable) -> Callable:
    """Decorator to count the number of times functions are called"""
    @wraps(method)
    def count_calls_wrapper(*args) -> str:
        """Counts the number of calls the wrapped function makes"""
        key = f"count:{args[0]}"
        cache.incr(key)
        cache.expire(key, 10)
        return method(*args)

    return count_calls_wrapper

@count_calls
def get_page(url: str) -> str:
    """GET HTML content from URL and return it"""
    r = requests.get(url)
    return r.text

# Test the function with a slow response URL
if __name__ == "__main__":
    slow_url = "http://slowwly.robertomurray.co.uk/delay/5000/url/http://www.example.com"
    html_content = get_page(slow_url)
    print(html_content)


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
from WindPy import *
from wind.tools import downloader

w.start()
def oi(startdate='2012-7-29',enddate='2013-7-29',varity='rb.shf',wind_code='all',member_name='all',order_by='long'):
    '''利用万得数据接口获取得品种机构龙虎榜数据，类似于万得F9持仓分析'''
    #构造参数
    startdate =startdate
    enddate = enddate
    varity = varity
    wind_code = wind_code
    member_name = member_name
    order_by = order_by
    para1="futureoi"
    para2="startdate=%s;enddate=%s;varity=%s;wind_code=%s;\
    member_name=%s;order_by=%s" %(startdate,enddate,varity,wind_code,member_name,order_by)
    #获取万得期货持仓数据
    data=w.wset(para1,para2)
    #将万得的数据结构转化为pandas数据结构并返回
    ErrorCode = data.ErrorCode
    Codes = data.Codes
    Fields = data.Fields
    Times = data.Times
    Data = data.Data
    # index=data[0]
    df = pd.DataFrame(Data).T
    df.columns = Fields
    print('期货机构持仓情况如下：')
    # print(df)
    print(df.shape)
    # df.to_csv(r"C:\Users\gsyuan\Desktop\Wind Data\oi.csv", header=False)
    return df

def gethistoi(n=12,member_name='永安期货'):
    '''利用万得数据接口获取某家期货公司的历史持仓'''
    # startdate =datetime.datetime.now()-timedelta(30*n)
    # enddate =datetime.datetime.now()
    data=[]
    while n>0:
        startdate = datetime.now() - timedelta(30 * n)
        enddate =datetime.now()-timedelta(30 * n-30)
        d1="%s" % startdate.date()
        d2="%s" % enddate.date()
        df=oi(startdate =d1,enddate = d2,member_name=member_name)
        n=n-1
        data.append(df)
        # with open(r"C:\Users\gsyuan\Desktop\Wind Data\oi.csv",mode='a') as f:
        #     df.to_csv(f,header=False)
        print(df.date)
    df = pd.concat(data).drop_duplicates(subset='date',keep=False)
    df.to_csv(r"C:\Users\gsyuan\Desktop\Wind Data\oi.csv", header=False)

#交易所数据源
def cffexoi(date='0811'):
    date = date
    url = 'http://www.cffex.com.cn/fzjy/ccpm/2016%s/%s/IF_1.csv' % (date[0:2], date[-2:])
    downloader(url)

def shfeoi():
    dates = ['20160104', '20160105']
    for date in dates:
        url = 'http://www.shfe.com.cn/data/dailydata/kx/pm%s.dat' % date
        downloader(url)

# oi(startdate='2015-4-5',enddate='2016-6-6',member_name='永安期货')

if __name__ == '__main__':
  oi()
  gethistoi(n=12)


import vtk
from kanvas.canvas import Renderer, RenderWindow, Box

class ArrowFactory:
    '''Make arrows
'''
    def __init__(self, shaftRadius=0.05, tipLength=0.2):
        '''Set arrow parameters
'''
        self._shaftRadius = shaftRadius
        self._tipLength = tipLength

    def makeArrow(self):
        '''Make arrow with current parameter settings
'''
        arrow = vtk.vtkArrowSource()
        arrow.SetShaftRadius(self._shaftRadius)

        arrow.SetTipLength(self._tipLength)
        return arrow

    @property
    def shaftRadius(self):
        return self._shaftRadius

    @shaftRadius.setter
    def shaftRadius(self, value):
        self._shaftRadius = value

    @property
    def tipLength(self):
        return self._tipLength

    @tipLength.setter
    def tipLength(self, value):
        self._tipLength = value

class ConeFactory:
    '''Cone
'''
    def __init__(self, height=3.0, radius=1.0, resolution=20):
        '''Initialize settings for making cones
'''
        self._height = height
        self._radius = radius
        self._resolution = resolution

    def makeCone(self):
        '''Make a cone with the current settings
'''
        cone = vtk.vtkConeSource()
        cone.SetHeight(self._height)
        cone.SetRadius(self._radius)
        cone.SetResolution( self._resolution)
        return cone

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self, value):
        self._height = value

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value

    @property
    def resolution(self):
        return self._resolution

    @resolution.setter
    def resolution(self, value):
        self.resolution = value

def parabola3D(x, y, k=-1.5, c=0.0):
    '''
'''
    return (k* (x**2 + y**2) ) + c

if __name__ == '__main__':

    coneFactory = ConeFactory()
    arrowFactory = ArrowFactory()

    renderWindow = RenderWindow(size=(800, 400), BoxClass=Box)
    #rwBox = renderWindow.box
    #print(rwBox)

    renderer1 = Renderer()
    # renderer1.renderer.ResetCamera()
    camera1 = renderer1.renderer.GetActiveCamera()
    # vtkCamera settings:
    # https://www.vtk.org/doc/nightly/html/classvtkCamera.html#ac1dcd796574d6b2abcade341587838c2
    camera1.Elevation(-30)
    camera1.Dolly(.2)

    # renderer1.renderer.Dolly(30)
    renderer1.addCallback(renderWindow.azimuthCallback)

    actorProperty1 = vtk.vtkProperty()
    actorProperty1.SetColor(.6, .2, .2)
    actorProperty1.SetDiffuse(.7)
    actorProperty1.SetSpecular(.4)
    actorProperty1.SetSpecularPower(20)

    renderer1.addActorSource(arrowFactory.makeArrow(), actorProperty=actorProperty1,
                             position=(0.25, -.1, 0) )

    property3 = vtk.vtkProperty()
    property3.SetColor(.4, 0, .4)
    renderer1.addActorSource(vtk.vtkCubeSource(), actorProperty=property3,
                             position=(0.1, 1, -1.5))

    renderer2 = Renderer(background=(.1, .2, .2))
    property2 = vtk.vtkProperty()
    property2.SetColor(.2, .2, .8)
    renderer2.addActorSource(coneFactory.makeCone(), actorProperty=property2, position=(0, 0, 0), box=None)
    renderer2.renderer.ResetCamera()
    camera2 = renderer2.renderer.GetActiveCamera()
    camera2.Azimuth(75)
    # camera2.Dolly(.75)
    camera2.Elevation(40)

    renderWindow.addRenderer(renderer1, (0.0, 0.0, 0.5, 1.0))
    renderWindow.addRenderer(renderer2, (0.5, 0.0, 1.0, 1.0))
    # renderWindow.addRenderer(renderer2, (0.0, 0.0, 1.0, 1.0))

    # rwBox.boxWidget.On()
    renderWindow.rotate()
    renderWindow.renderInteractive()