# -*- coding: utf-8 -*-
"""
Simple neuron simulator for Python.
Also simulates voltage clamp and current clamp with access resistance.

Luke Campagnola 2015
github.com/campagnola/neurodemo
"""

from collections import OrderedDict
import numpy as np
import scipy.integrate
from ..units import us

class Sim(object):
    """Simulator for a collection of objects that derive from SimObject
    """
    def __init__(self, objects=None, temp=37.0, dt=10*us):
        self._objects = []
        self._all_objs = None
        self._time = 0.0
        self.temp = temp
        self.dt = dt
        self.odeint_args = {
            'h0': 1*us,
            'hmax': 100*us,
            'rtol': 1e-6,
            'atol': 1e-6,
            'full_output': 1,
        }
        if objects is not None:
            for obj in objects:
                self.add(obj)

    def add(self, obj):
        assert obj._sim is None
        obj._sim = self
        self._objects.append(obj)
        return obj

    def all_objects(self):
        """Ordered dictionary of all objects to be simulated, keyed by their names.
        """
        if self._all_objs is None:
            objs = OrderedDict()
            for o in self._objects:
                if not o.enabled:
                    continue
                for k,v in o.all_objects().items():
                    if k in objs:
                        raise NameError('Multiple objects with same name "%s": %s, %s' % (k, objs[k], v))
                    objs[k] = v
            self._all_objs = objs
        return self._all_objs

    @property
    def time(self):
        return self._time

    def run(self, samples=1000, **kwds):
        """Run the simulation until a number of *samples* have been acquired.

        Extra keyword arguments are passed to `scipy.integrate.odeint()`.
        """
        opts = self.odeint_args.copy()
        opts.update(kwds)

        # reset all_objs cache in case some part of the sim has changed
        self._all_objs = None
        all_objs = self.all_objects().values()

        # check that there is something to simulate
        if len(all_objs) == 0:
            raise RuntimeError("No objects added to simulation.")

        # Collect / prepare state variables for integration
        init_state = []
        difeq_vars = []
        dep_vars = {}
        for o in all_objs:
            pfx = o.name + '.'
            for k,v in o.difeq_state().items():
                difeq_vars.append(pfx + k)
                init_state.append(v)
            for k,v in o.dep_state_vars.items():
                dep_vars[pfx + k] = v
        self._simstate = SimState(difeq_vars, dep_vars)
        t = np.arange(0, samples) * self.dt + self._time

        # Run the simulation
        result, info = scipy.integrate.odeint(self.derivatives, init_state, t, **opts)

        # Update current state variables
        p = 0
        for o in all_objs:
            nvar = len(o.difeq_state())
            o.update_state(result[-1, p:p+nvar])
            p += nvar

        self._last_run_time = t
        return SimState(difeq_vars, dep_vars, result.T, t=t)

    def derivatives(self, state, t):
        objs = self.all_objects().values()
        self._simstate.state = state
        self._simstate.extra['t'] = t

        # Record the time of the last simulated sample. Note that this is NOT
        # the same as the last _requested_ sample; the integrator may go farther
        # depending on its time step
        self._time = t

        d = []
        for o in objs:
            d.extend(o.derivatives(self._simstate))

        return d

    @property
    def last_state(self):
        """Return the last values of all state variables in a SimState object.
        """
        return self._simstate

class SimState(object):
    """Contains the state of all diff. eq. variables in the simulation.

    During simulation runs, this is used to carry information about all
    variables at the current timepoint. After the simulation finishes, this is
    used to carry all state variable data collected during the simulation.

    Parameters
    ==========
        difeq_vars: list
            Names of all diff. eq. state variables
        dep_vars: dict
            Name:function pairs for all dependent variables that may be computed
        difeq_state: list
            Initial values for all dif. eq. state variables
        extra:
            Extra name:value pairs that may be accessed from this object
    """
    def __init__(self, difeq_vars, dep_vars=None, difeq_state=None, **extra):
        self.difeq_vars = difeq_vars
        # record indexes of difeq vars for fast retrieval
        self.indexes = dict([(k, i) for i,k in enumerate(difeq_vars)])

        self.dep_vars = dep_vars
        self.state = difeq_state
        self.extra = extra

    def set_state(self, difeq_state):
        self.state = difeq_state

    def __getitem__(self, key):
        # allow lookup by (object, var)
        if isinstance(key, tuple):
            key = key[0].name + '.' + key[1]
        try:
            # try this first for speed
            return self.state[self.indexes[key]]
        except KeyError:
            if key in self.dep_vars:
                return self.dep_vars[key](self)
            else:
                return self.extra[key]

    def keys(self):
        return self.difeq_vars + list(self.extra.keys())

    def __repr__(self):
        rep = 'SimState:\n'
        for i,k in enumerate(self.difeq_vars):
            rep += '  %s = %s\n' % (k, self.state[i])
        return rep

    def get_final_state(self):
        """Return a dictionary of all diff. eq. state variables and dependent
        variables for all objects in the simulation.
        """
        state = {}
        s = self.copy()
        clip = not np.isscalar(self['t'])
        if clip:
            # only get results for the last timepoint
            s.set_state(self.state[:, -1])

        for k in self.difeq_vars:
            state[k] = s[k]
        for k in self.dep_vars:
            state[k] = s[k]
        for k,v in self.extra.items():
            if clip:
                state[k] = v[-1]
            else:
                state[k] = v

        return state

    def copy(self):
        return SimState(self.difeq_vars, self.dep_vars, self.state, **self.extra)

class SimObject(object):
    """
    Base class for objects that participate in integration by providing a set
    of state variables and their derivatives.
    """
    instance_count = 0

    def __init__(self, init_state, name=None):
        self._sim = None
        if name is None:
            i = self.instance_count
            type(self).instance_count = i + 1
            if i == 0:
                name = self.type
            else:
                name = self.type + '%d' % i
        self._name = name
        self.enabled = True
        self._init_state = init_state.copy()  # in case we want to reset
        self._current_state = init_state.copy()
        self._sub_objs = []
        self.records = []
        self._rec_dtype = [(sv, float) for sv in init_state.keys()]

        # maps name:function for computing state vars that can be computed from
        # a SimState instance.
        self.dep_state_vars = {}

    @property
    def name(self):
        return self._name

    def all_objects(self):
        """SimObjects are organized in a hierarchy. This method returns an ordered
        dictionary of all enabled SimObjects in this branch of the hierarchy, beginning
        with self.
        """
        objs = OrderedDict()
        objs[self.name] = self
        for o in self._sub_objs:
            if not o.enabled:
                continue
            objs.update(o.all_objects())
        return objs

    def difeq_state(self):
        """An ordered dictionary of all variables required to solve the
        diff. eq. for this object.
        """
        return self._current_state

    def update_state(self, result):
        """Update diffeq state variables with their last simulated values.
        These will be used to initialize the solver when the next simulation
        begins.
        """
        for i,k in enumerate(self._current_state.keys()):
            self._current_state[k] = result[i]

    def derivatives(self, state):
        """Return derivatives of all state variables.

        Must be reimplemented in subclasses. This is used by the ODE solver
        to integrate during the simulation; should be as fast as possible.
        """
        raise NotImplementedError()

    @property
    def sim(self):
        """The Sim instance in which this object is being used.
        """
        return self._sim


"""Implementation of target attack.
  Three models (base_incep, adv_incep, res_incep) are used.
  The models are ensembled using mean norm gradient methrod.
  The inferstructure code is based on
  https://github.com/tensorflow/cleverhans/cleverhans/tree/master/
  examples/nips17_adversarial_competition/sample_targeted_attacks/iter_target_class
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import time

import numpy as np
import tensorflow as tf
from tensorflow.contrib import slim

from lib_adv import utils, attack

tf.flags.DEFINE_string(
    'output_dir',
    '../../intermediate_results/targeted_attacks_output/target_mng',
    'Output directory with images.')

tf.flags.DEFINE_string(
    'input_dir', '../../dataset/images_4/', 'Input directory with images.')

tf.flags.DEFINE_string(
    'checkpoint_path', 'mul_inception_v1.ckpt',
    'Path to checkpoint for inception network.')

tf.flags.DEFINE_string(
    'model_names',
    'base_inception,base_incpt_resnet,adv_inception,adv_incpt_resnet',
    'names of the multiple models, no space!')

tf.flags.DEFINE_string(
    'master', '', 'The address of the TensorFlow master to use.')

tf.flags.DEFINE_integer('image_width', 299, 'Width of each input images.')
tf.flags.DEFINE_integer('image_height', 299, 'Height of each input images.')
tf.flags.DEFINE_integer('image_depth', 3, 'Depth of each input images.')
tf.flags.DEFINE_integer('num_classes', 1001, 'Number of classes.')
tf.flags.DEFINE_integer('num_iter', 20, 'Number of iterations.')

tf.flags.DEFINE_integer('batch_size', 4, '#images process at one time.')
tf.flags.DEFINE_float('max_epsilon', 16.0, 'Max size of perturbation.')
tf.flags.DEFINE_integer('norm_ord', 1, 'order of norm to use')
tf.flags.DEFINE_string('labels_file', 'target_class.csv', 'target classes')

class ModelAttacker():
  """A target attacker model, multi-model ensembled."""
  def __init__(self, num_classes, image_pixels, model_names, max_epsilon,
               norm_ord, batch_shape):
    """Constructs a `ModelAttacker`.
        Set the parameters and build the base and adversarial graph"""
    prev = time.time()

    # image_factor is model dependent
    # Images for inception classifier are normalized to be in [-1, 1] interval
    # scale from [0, 255], range 255 to [-1, 1), range 2
    image_factor = 2.0 / 255.0

    list_mnames = model_names.split(',')
    eps, alpha = attack.parameters(max_epsilon, image_factor,
                                   image_pixels, norm_ord)

    utils.logger.debug('norm_ord = %d, alpha = %.3f, models: %s' % (
        norm_ord, alpha, list_mnames))

    # Prepare graph
    self._batch_shape = batch_shape
    self._x_input = tf.placeholder(tf.float32, shape=batch_shape)
    self._x_ref = tf.placeholder(tf.float32, shape=batch_shape)
    self._target_labels = tf.placeholder(tf.int32, shape=[batch_shape[0]])

    _, pred_labels, logits_w = attack.graph_base(self._x_input,
                                                 num_classes,
                                                 list_mnames)
    self._x_adv, _ = attack.graph_adv(self._x_input, num_classes,
                                      self._x_ref, self._target_labels,
                                      pred_labels, logits_w,
                                      alpha, eps, norm_ord)

    utils.logger.debug('graph init: %.3f seconds' % (time.time() - prev))

  def run(self, checkpoint_path, master, input_dir, labels_file, output_dir,
          num_iter):
    """Run the computation and generate adversarial images"""
    saver = tf.train.Saver(slim.get_model_variables())
    session_creator = tf.train.ChiefSessionCreator(
        scaffold=tf.train.Scaffold(saver=saver),
        checkpoint_filename_with_path=checkpoint_path,
        master=master)

    with tf.train.MonitoredSession(session_creator=session_creator) as sess:
      for filenames, images, labels in utils.load_images(input_dir,
                                                         self._batch_shape,
                                                         labels_file):
        adv_images = np.copy(images)
        for _ in range(num_iter):
          adv_images = sess.run(
              self._x_adv,
              feed_dict={
                  self._x_input: adv_images,
                  self._x_ref: images,
                  self._target_labels: labels})
        utils.save_images(adv_images, filenames, output_dir)

def main(_):
  tf.logging.set_verbosity(tf.logging.INFO)
  prev = time.time()

  FLG = tf.flags.FLAGS
  batch_shape = [FLG.batch_size, FLG.image_height, FLG.image_width,
                 FLG.image_depth]
  image_pixels = FLG.image_height * FLG.image_width * FLG.image_depth

  with tf.Graph().as_default():
    attacker = ModelAttacker(FLG.num_classes, image_pixels, FLG.model_names,
                             FLG.max_epsilon, FLG.norm_ord, batch_shape)
    attacker.run(FLG.checkpoint_path, FLG.master, FLG.input_dir,
                 FLG.labels_file, FLG.output_dir, FLG.num_iter)

  utils.logger.debug('%.3f seconds' % (time.time() - prev))

if __name__ == '__main__':
  tf.app.run()


from __future__ import annotations

from typing import Tuple, Dict

import numpy
import amulet_nbt

from amulet.api.block import Block
from amulet.api.chunk.blocks import Blocks
from amulet.world_interface.chunk.interfaces.anvil.base_anvil_interface import (
    BaseAnvilInterface,
)
from amulet.utils.world_utils import (
    decode_long_array,
    encode_long_array,
)

def properties_to_string(props: dict) -> str:
    """
    Converts a dictionary of blockstate properties to a string

    :param props: The dictionary of blockstate properties
    :return: The string version of the supplied blockstate properties
    """
    result = []
    for key, value in props.items():
        result.append("{}={}".format(key, value))
    return ",".join(result)

class Anvil1444Interface(BaseAnvilInterface):
    def __init__(self):
        BaseAnvilInterface.__init__(self)
        self.features["data_version"] = "int"
        self.features["last_update"] = "long"

        self.features["status"] = "j13"
        self.features["inhabited_time"] = "long"
        self.features["biomes"] = "256BA"
        self.features["height_map"] = "C5|36LA"

        self.features["blocks"] = "Sections|(BlockStates,Palette)"
        self.features["block_light"] = "Sections|2048BA"
        self.features["sky_light"] = "Sections|2048BA"

        self.features["block_entities"] = "list"
        self.features["block_entity_format"] = "namespace-str-id"
        self.features["block_entity_coord_format"] = "xyz-int"

        self.features["entities"] = "list"
        self.features["entity_format"] = "namespace-str-id"
        self.features["entity_coord_format"] = "Pos-list-double"

        self.features["tile_ticks"] = "list"

        self.features["liquid_ticks"] = "list"
        self.features["liquids_to_be_ticked"] = "16list|list"
        self.features["to_be_ticked"] = "16list|list"
        self.features["post_processing"] = "16list|list"
        self.features["structures"] = "compound"

    @staticmethod
    def minor_is_valid(key: int):
        return 1444 <= key < 1466

    def _decode_blocks(self, chunk_sections: amulet_nbt.TAG_List) -> Tuple[Dict[int, numpy.ndarray], numpy.ndarray]:
        if chunk_sections is None:
            raise NotImplementedError(
                "We don't support reading chunks that never been edited in Minecraft before"
            )

        blocks: Dict[int, numpy.ndarray] = {}
        palette = [Block(namespace="minecraft", base_name="air")]

        for section in chunk_sections:
            if "Palette" not in section:  # 1.14 makes palette/blocks optional.
                continue
            cy = section["Y"].value
            blocks[cy] = numpy.transpose(
                decode_long_array(
                    section["BlockStates"].value, 4096
                ).reshape((16, 16, 16)) + len(palette),
                (2, 0, 1)
            )

            palette += self._decode_palette(section["Palette"])

        np_palette, inverse = numpy.unique(palette, return_inverse=True)
        np_palette: numpy.ndarray
        inverse: numpy.ndarray
        for cy in blocks:
            blocks[cy] = inverse[blocks[cy]].astype(numpy.uint32)  # TODO: find a way to make the new blocks format change dtype
        return blocks, np_palette

    def _encode_blocks(
        self, blocks: Blocks, palette: numpy.ndarray
    ) -> amulet_nbt.TAG_List:
        sections = amulet_nbt.TAG_List()
        for cy in range(16):
            if cy in blocks:
                block_sub_array = numpy.transpose(blocks.get_sub_chunk(cy), (1, 2, 0)).ravel()

                sub_palette_, block_sub_array = numpy.unique(
                    block_sub_array, return_inverse=True
                )
                sub_palette = self._encode_palette(palette[sub_palette_])
                if (
                    len(sub_palette) == 1
                    and sub_palette[0]["Name"].value == "minecraft:air"
                ):
                    continue

                section = amulet_nbt.TAG_Compound()
                section["Y"] = amulet_nbt.TAG_Byte(cy)
                section["BlockStates"] = amulet_nbt.TAG_Long_Array(
                    encode_long_array(block_sub_array)
                )
                section["Palette"] = sub_palette
                sections.append(section)

        return sections

    @staticmethod
    def _decode_palette(palette: amulet_nbt.TAG_List) -> list:
        blockstates = []
        for entry in palette:
            namespace, base_name = entry["Name"].value.split(":", 1)
            properties = entry.get("Properties", amulet_nbt.TAG_Compound({})).value
            block = Block(
                namespace=namespace, base_name=base_name, properties=properties
            )
            blockstates.append(block)
        return blockstates

    @staticmethod
    def _encode_palette(blockstates: list) -> amulet_nbt.TAG_List:
        palette = amulet_nbt.TAG_List()
        for block in blockstates:
            entry = amulet_nbt.TAG_Compound()
            entry["Name"] = amulet_nbt.TAG_String(
                f"{block.namespace}:{block.base_name}"
            )
            entry["Properties"] = amulet_nbt.TAG_Compound(block.properties)
            palette.append(entry)
        return palette

INTERFACE_CLASS = Anvil1444Interface


import numpy as np

# The worker class is a member of the trainer class, the trainer can have multiple workers
class Worker():
    def __init__(self, settings, sess, number, trainerNumber, network, queues, coord):
        self.localAC = network
        self.name = 'worker{}'.format(number)
        self.number = number
        self.settings = settings
        self.trainerQueue = queues["trainer"]
        self.trainerNumber = trainerNumber
        self.coord = coord
        self.sess = sess
        self.playerActionQueue = queues["playerAction"]
        self.game = None
        self.playerActionQueue.put({"WindowSettings": True if self.name == "worker0" else False,
                                    "worker": number})

        self.episodeInProgress = True
        self.values = []

    def work(self, gameData):
        gameData # Get data from the game
        if gameData[0] == "CurrentFrame": # Process the next action based on frame
            frame = gameData[1]
            feedDict = {self.localAC.frame: [frame]}
            actionDist, value = self.sess.run([self.localAC.logits,
                                               self.localAC.value],
                                               feed_dict=feedDict)
            action = np.random.choice(actionDist[0], p=actionDist[0])
            action = np.argmax(actionDist==action)

            self.playerActionQueue.put(action)
            self.values.append(value[0,0])

        elif gameData[0] == "Bootstrap": # Bootstrap from bootstrap data
            print("{} is bootstrapping!".format(self.name))
            episodeData = gameData[1]
            bootstrapValues = self.values[0:len(episodeData)]
            self.values = self.values[len(episodeData)::]
            workerData = {"episodeData": episodeData,
                          "values": bootstrapValues,
                          "bootStrapValue": self.values[0],
                          "score": 0,
                          "worker": self.number,
                          "trainer": self.trainerNumber}
            self.trainerQueue.put(workerData)

        elif gameData[0] == "EpisodeData": # Episode is finished, perform training and logging
            episodeData = gameData[1]
            score = gameData[2]
            workerData = {"episodeData": episodeData,
                          "values": self.values,
                          "bootStrapValue": 0,
                          "score": score,
                          "worker": self.number,
                          "trainer": self.trainerNumber}
            self.trainerQueue.put(workerData)
            self.values = []

        elif gameData[0] == "Game closed!": # Game has been closed
            print("{}s game closed, saving and quitting program!".format(self.name))
            self.coord.request_stop()

        else:
            print("Invalid game data! got: {}".format(gameData[0]))


import numpy as np

import assistive_gym.envs.agents.human as h
from assistive_gym.envs.env import AssistiveEnv

def setup_human(env: AssistiveEnv):
    human = env.create_human(
        controllable=False,
        controllable_joint_indices=h.right_arm_joints,
        fixed_base=False,
        human_impairment="none",
        gender="random",
        mass=None,
        radius_scale=1.0,
        height_scale=1.0,
    )

    # Define the initial pose for the human
    joints_positions = [
        (human.j_right_elbow, -90),
        (human.j_left_elbow, -90),
        (human.j_right_hip_x, -80),
        (human.j_right_knee, 80),
        (human.j_left_hip_x, -80),
        (human.j_left_knee, 80),
    ]
    human.setup_joints(
        joints_positions,
        use_static_joints=False,
        reactive_force=None,
        reactive_gain=0.05,
    )

    # Set human on chair and increase body friction
    chair = env.furniture
    chair_pos, chair_orient = chair.get_base_pos_orient()
    human.set_base_pos_orient(
        chair_pos
        + np.array([0.01, 0, -0.5 + (0.89 if human.gender == "male" else 0.86)]),
        env.get_quaternion(env.get_euler(chair_orient) + np.array([-0.1, 0, 0])),
    )
    human.set_whole_body_frictions(
        lateral_friction=10, spinning_friction=10, rolling_friction=10
    )
    # Stiffen the joints so they do not fall limp so easily
    human.set_all_joints_stiffness(0.01)


import torch
import numpy as np
from copy import deepcopy
import torch.nn.functional as F

from tianshou.data import Batch
from tianshou.policy import BasePolicy

# from tianshou.exploration import OUNoise

class DDPGPolicy(BasePolicy):
    """docstring for DDPGPolicy"""

    def __init__(self, actor, actor_optim, critic, critic_optim,
                 tau=0.005, gamma=0.99, exploration_noise=0.1,
                 action_range=None, reward_normalization=False,
                 ignore_done=False):
        super().__init__()
        if actor is not None:
            self.actor, self.actor_old = actor, deepcopy(actor)
            self.actor_old.eval()
            self.actor_optim = actor_optim
        if critic is not None:
            self.critic, self.critic_old = critic, deepcopy(critic)
            self.critic_old.eval()
            self.critic_optim = critic_optim
        assert 0 < tau <= 1, 'tau should in (0, 1]'
        self._tau = tau
        assert 0 < gamma <= 1, 'gamma should in (0, 1]'
        self._gamma = gamma
        assert 0 <= exploration_noise, 'noise should not be negative'
        self._eps = exploration_noise
        assert action_range is not None
        self._range = action_range
        self._action_bias = (action_range[0] + action_range[1]) / 2
        self._action_scale = (action_range[1] - action_range[0]) / 2
        # it is only a little difference to use rand_normal
        # self.noise = OUNoise()
        self._rm_done = ignore_done
        self._rew_norm = reward_normalization
        self.__eps = np.finfo(np.float32).eps.item()

    def set_eps(self, eps):
        self._eps = eps

    def train(self):
        self.training = True
        self.actor.train()
        self.critic.train()

    def eval(self):
        self.training = False
        self.actor.eval()
        self.critic.eval()

    def sync_weight(self):
        for o, n in zip(self.actor_old.parameters(), self.actor.parameters()):
            o.data.copy_(o.data * (1 - self._tau) + n.data * self._tau)
        for o, n in zip(
                self.critic_old.parameters(), self.critic.parameters()):
            o.data.copy_(o.data * (1 - self._tau) + n.data * self._tau)

    def process_fn(self, batch, buffer, indice):
        if self._rew_norm:
            bfr = buffer.rew[:len(buffer)]
            mean, std = bfr.mean(), bfr.std()
            if std > self.__eps:
                batch.rew = (batch.rew - mean) / std
        if self._rm_done:
            batch.done = batch.done * 0.
        return batch

    def __call__(self, batch, state=None,
                 model='actor', input='obs', eps=None):
        model = getattr(self, model)
        obs = getattr(batch, input)
        logits, h = model(obs, state=state, info=batch.info)
        logits += self._action_bias
        if eps is None:
            eps = self._eps
        if eps > 0:
            # noise = np.random.normal(0, eps, size=logits.shape)
            # logits += torch.tensor(noise, device=logits.device)
            # noise = self.noise(logits.shape, eps)
            logits += torch.randn(
                size=logits.shape, device=logits.device) * eps
        logits = logits.clamp(self._range[0], self._range[1])
        return Batch(act=logits, state=h)

    def learn(self, batch, batch_size=None, repeat=1):
        target_q = self.critic_old(batch.obs_next, self(
            batch, model='actor_old', input='obs_next', eps=0).act)
        dev = target_q.device
        rew = torch.tensor(batch.rew, dtype=torch.float, device=dev)[:, None]
        done = torch.tensor(batch.done, dtype=torch.float, device=dev)[:, None]
        target_q = (rew + (1. - done) * self._gamma * target_q).detach()
        current_q = self.critic(batch.obs, batch.act)
        critic_loss = F.mse_loss(current_q, target_q)
        self.critic_optim.zero_grad()
        critic_loss.backward()
        self.critic_optim.step()
        actor_loss = -self.critic(batch.obs, self(batch, eps=0).act).mean()
        self.actor_optim.zero_grad()
        actor_loss.backward()
        self.actor_optim.step()
        self.sync_weight()
        return {
            'loss/actor': actor_loss.detach().cpu().numpy(),
            'loss/critic': critic_loss.detach().cpu().numpy(),
        }


from flask import Flask, render_template,request
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import sklearn as sk
import cv2
import os
import glob
import re
import base64
import time
from sklearn import svm
import io
from sklearn import metrics
from trial import test_model
from tensorflow.keras.models import load_model
import joblib

classifier_name = 2
facenet = load_model('models/facenet_keras.h5')
clf = joblib.load('models/FaceNet-SVM-model-full.joblib')
clf1 = load_model('models/FaceNet-NN-model.h5')
facenet._make_predict_function()
clf1._make_predict_function()
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
app = Flask(__name__)

@app.route('/')
def index(name=None):
    return render_template('index2.html',name=name)

@app.route('/clf',methods=["POST"])
def classvalue():
    global classifier_name
    classifier_name = request.form['classifierName']
    return classifier_name

@app.route('/photo',methods=["POST"])
def disp_pic():
    global classifier_name, clf, clf1, facenet, face_cascade

    img_data = request.form['imgData']
    try:
        classifier_name = classvalue()
    except:
        pass
    encoded_data = img_data.split(',')[1]
    nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    faces = face_cascade.detectMultiScale(img, 1.3, 5)
    count = 0
    if len(faces) > 0:
        for (x, y, w, h) in faces:
            crop_img = img[y - 50:y + w + 50, x - 50:x + h + 50]
            if classifier_name == 1:
                result, color = test_model(crop_img, facenet, clf,classifier_name)
            else:
                result, color = test_model(crop_img, facenet, clf1,classifier_name)
            if result == "Access Granted":
                count = count + 1
        if count > 0:
            cv2.putText(img, "Access Granted", (int(img.shape[0] / 4) - 25, int(img.shape[1] / 2) - 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2, cv2.LINE_AA)
        else:
            cv2.putText(img, result, (int(img.shape[0] / 4) - 25, int(img.shape[1] / 2) - 90), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2, cv2.LINE_AA)
    else:
        cv2.putText(img, "RETRY!!!", (int(img.shape[0] / 4) - 25, int(img.shape[1] / 2) - 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)
    cv2.imshow('image', img)
    cv2.waitKey(3000)
    cv2.destroyWindow('image')
    return img_data

def main():
    app.run()
    app.debug = True

if __name__ == '__main__':
    main()


import os
import os.path as osp
import numpy as np
import math
from utils.pose_utils import get_bbox
from pycocotools.coco import COCO
from config import cfg

class MuCo:
    def __init__(self, data_split):
        self.data_split = data_split
        self.img_dir = osp.join('..', 'data', 'MuCo', 'data')
        self.train_annot_path = osp.join('..', 'data', 'MuCo', 'data', 'MuCo-3DHP.json')
        self.joint_num = 21
        self.joints_name = ('Head_top', 'Thorax', 'R_Shoulder', 'R_Elbow', 'R_Wrist', 'L_Shoulder', 'L_Elbow', 'L_Wrist', 'R_Hip', 'R_Knee', 'R_Ankle', 'L_Hip', 'L_Knee', 'L_Ankle', 'Pelvis', 'Spine', 'Head', 'R_Hand', 'L_Hand', 'R_Toe', 'L_Toe')
        self.flip_pairs = ( (2, 5), (3, 6), (4, 7), (8, 11), (9, 12), (10, 13), (17, 18), (19, 20) )
        self.skeleton = ( (0, 16), (16, 1), (1, 15), (15, 14), (14, 8), (14, 11), (8, 9), (9, 10), (10, 19), (11, 12), (12, 13), (13, 20), (1, 2), (2, 3), (3, 4), (4, 17), (1, 5), (5, 6), (6, 7), (7, 18) )
        self.joints_have_depth = True
        self.root_idx = self.joints_name.index('Pelvis')
        self.data = self.load_data()

    def load_data(self):

        if self.data_split == 'train':
            db = COCO(self.train_annot_path)
        else:
            print('Unknown data subset')
            assert 0

        data = []
        for iid in db.imgs.keys():
            img = db.imgs[iid]
            img_id = img["id"]
            img_width, img_height = img['width'], img['height']
            imgname = img['file_name']
            img_path = osp.join(self.img_dir, imgname)
            f = img["f"]
            c = img["c"]

            # crop the closest person to the camera
            ann_ids = db.getAnnIds(img_id)
            anns = db.loadAnns(ann_ids)

            root_depths = [ann['keypoints_cam'][self.root_idx][2] for ann in anns]
            closest_pid = root_depths.index(min(root_depths))
            pid_list = [closest_pid]
            for i in range(len(anns)):
                if i == closest_pid:
                    continue
                picked = True
                for j in range(len(anns)):
                    if i == j:
                        continue
                    dist = (np.array(anns[i]['keypoints_cam'][self.root_idx]) - np.array(anns[j]['keypoints_cam'][self.root_idx])) ** 2
                    dist_2d = math.sqrt(np.sum(dist[:2]))
                    dist_3d = math.sqrt(np.sum(dist))
                    if dist_2d < 500 or dist_3d < 500:
                        picked = False
                if picked:
                    pid_list.append(i)

            for pid in pid_list:
                joint_cam = np.array(anns[pid]['keypoints_cam'])
                root_cam = joint_cam[self.root_idx]

                joint_img = np.array(anns[pid]['keypoints_img'])
                joint_img = np.concatenate([joint_img, joint_cam[:,2:]],1)
                joint_img[:,2] = joint_img[:,2] - root_cam[2]
                joint_vis = np.ones((self.joint_num,1))

                bbox = np.array(anns[pid]['bbox'])

                # sanitize bboxes
                x, y, w, h = bbox
                x1 = np.max((0, x))
                y1 = np.max((0, y))
                x2 = np.min((img_width - 1, x1 + np.max((0, w - 1))))
                y2 = np.min((img_height - 1, y1 + np.max((0, h - 1))))
                if w*h > 0 and x2 >= x1 and y2 >= y1:
                    bbox = np.array([x1, y1, x2-x1, y2-y1])
                else:
                    continue

                # aspect ratio preserving bbox
                w = bbox[2]
                h = bbox[3]
                c_x = bbox[0] + w/2.
                c_y = bbox[1] + h/2.
                aspect_ratio = cfg.input_shape[1]/cfg.input_shape[0]
                if w > aspect_ratio * h:
                    h = w / aspect_ratio
                elif w < aspect_ratio * h:
                    w = h * aspect_ratio
                bbox[2] = w*1.25
                bbox[3] = h*1.25
                bbox[0] = c_x - bbox[2]/2.
                bbox[1] = c_y - bbox[3]/2.

                data.append({
                    'img_path': img_path,
                    'bbox': bbox,
                    'joint_img': joint_img, # [org_img_x, org_img_y, depth - root_depth]
                    'joint_cam': joint_cam, # [X, Y, Z] in camera coordinate
                    'joint_vis': joint_vis,
                    'root_cam': root_cam, # [X, Y, Z] in camera coordinate
                    'f': f,
                    'c': c
                })

        return data


# filter.py
# Ben Cook (bcook@cfa.harvard.edu)

__all__ = ['Filter', 'ACS_WFC_F435W', 'ACS_WFC_F475W', 'ACS_WFC_F555W',
           'ACS_WFC_F606W',
           'ACS_WFC_F814W', 'ACS_WFC_F850LP',
           'm31_filter_sets', 'm49_filter_sets', 'm51_filter_sets',
           'default_m31_filters', 'default_m49_filters', 'default_m51_filters',
           'default_m87_filters', 'default_ngc4993_filters',
           'default_ngc3377_filters', 'default_df2_filters',
           # 'lowexp_m87_filters',
           'm87_filters_v2',
           'AVAILABLE_FILTERS',
           'm31_summer_filters', 'm31_winter_filters']

"""Define classes for Filters and other similar objects"""

import numpy as np
from astropy.io import fits
from .psf import PSF_Model
from ..simulation.gpu_utils import gpu_log10 as log10
from pkg_resources import resource_filename
from warnings import warn

class Filter:
    """Models observations in a single band

    A Filter specifies the conversions between magnitudes and counts, and PSF convolution

    Attributes:
       name -- descriptive name of the filter (string, eg: F475W)
       tex_name -- LaTeX formatted name of the filter, eg for use in plotting (string, eg: r"g$_{475}$")
       MIST_column -- column name in MIST tables (string, eg: vmag, fuv, or f275)
       props -- dictionary of other properties
    Methods:
       mag_to_counts -- convert absolute magnitudes to photon counts
       counts_to_mag -- convert photon counts to absolute magnitudes
       psf_convolve -- convolve (2D) array with the instrumental PSF
    Constructors:
       __init__ -- default, manual entry of all parameters
    """

    def __init__(self,
                 exposure=1.0, zpt_vega=0., zpt_ab=0., zpt_st=0., red_per_ebv=0.,
                 psf=None, name="", tex_name="", MIST_column="", MIST_column_alt="",
                 **kwargs):
        """Create a new Filter, given input properties of observation

        Arguments:
           exposure -- exposure time of the observation, in seconds (int or float)
           zero_point -- apparent (VEGA) magnitude corresponding to 1 count / second (int or float)
                   this value is affected by telescope aperture, sensitivity, etc.
           red_per_ebv -- the Reddening value [A_x / E(B-V)], such as from Schlafly & Finkbeiner 2011, Table 6 (float)
           psf -- the PSF kernel, should be normalized to one (2D square array of floats)
        Keyword Argments:
           name -- descriptive name of the filter (string)
           tex_name -- LaTeX formatted name of the filter, eg for use in plotting (string, eg: r"g$_{475}$")
           MIST_column -- column name in MIST tables (string)
           **kwargs -- all other keyword arguments will be saved as a dictionary
        """

        #validate and initialize internal attributes
        try:
            self._exposure = float(exposure)
            self._zpts = {}
            self._zpts['vega'] = float(zpt_vega)
            self._zpts['ab'] = float(zpt_ab)
            self._zpts['st'] = float(zpt_st)
            self.red_per_ebv = float(red_per_ebv)
        except TypeError:
            print('First six arguments must each be either a float or integer')
            raise

        # initialize public attributes
        if isinstance(psf, PSF_Model):
            self.psf_model = psf
        else:
            if psf is None:
                psf = np.ones((3, 3), dtype=float)
            self.psf_model = PSF_Model(psf,
                                       dither_by_default=kwargs.get('dither_by_default',
                                                                    False))
        self.psf_convolve = self.psf_model.convolve

        self.name = name
        self.tex_name = tex_name
        self.MIST_column = MIST_column
        self.MIST_column_alt = MIST_column_alt
        self.props = kwargs

    #########################
    # Filter methods

    def mag_to_counts(self, mags, mag_system='vega'):
        """Convert apparent magnitudes to photon counts (no reddening assumed)

        Arguments:
           mags -- apparent magnitudes (int or float or array or ndarray)
        Output:
           counts -- photon counts (same type as input)
        """
        if mag_system in self._zpts:
            zpt = self._zpts[mag_system]
        else:
            warn(('mag_system {0:s} not in list of magnitude '
                  'conversions. Reverting to Vega'.format(mag_system)))
            zpt = self._zpts['vega']

        return 10.**(-0.4 * (mags - zpt)) * self._exposure

    def counts_to_mag(self, counts, mag_system='vega', **kwargs):
        """Convert photon counts to apparent magnitudes

        Arguments:
           counts -- photon counts (int or float or array or ndarray)
        Output:
           mags -- apparent magnitudes (same type as input)
        """
        if mag_system in self._zpts:
            zpt = self._zpts[mag_system]
        else:
            warn(('mag_system {0:s} not in list of magnitude '
                  'conversions. Reverting to Vega'.format(mag_system)))
            zpt = self._zpts['vega']

        return -2.5*log10(counts / self._exposure, **kwargs) + zpt

##############################
# Pre-defined Filters

class ACS_WFC_F435W(Filter):
    """Return a Filter with HST F435W default params
    Arguments:
    Output: Filter with default F435W attributes
    """
    def __init__(self, **kwargs):
        args = {}
        # set defaults
        args['exposure'] = 2720.
        args['zpt_vega'] = 25.7885  # see filter_setup.ipynb
        args['zpt_ab'] = 25.6903
        args['zpt_st'] = 25.1801
        args['red_per_ebv'] = 3.610
        args['psf'] = PSF_Model.from_fits('ACS_WFC_F435W')
        args['name'] = "F435W"
        args['tex_name'] = r"B$_{435}$"
        args['MIST_column'] = "ACS_WFC_F435W"
        args['MIST_column_alt'] = "Bmag"
        # update with manual entries
        args.update(kwargs)
        super().__init__(**args)

class ACS_WFC_F475W(Filter):
    """Return a Filter with HST F475W default params
    Arguments:
    Output: Filter with default F475W attributes
    """
    def __init__(self, **kwargs):
        args = {}
        # set defaults
        args['exposure'] = 3620.
        args['zpt_vega'] = 26.1511  # see filter_setup.ipynb
        args['zpt_ab'] = 26.0586
        args['zpt_st'] = 25.7483
        args['red_per_ebv'] = 3.248
        args['psf'] = PSF_Model.from_fits('ACS_WFC_F475W')
        args['name'] = "F475W"
        args['tex_name'] = r"g$_{475}$"
        args['MIST_column'] = "ACS_WFC_F475W"
        args['MIST_column_alt'] = "bmag"
        # update with manual entries
        args.update(kwargs)
        super().__init__(**args)

class ACS_WFC_F555W(Filter):
    """Return a Filter with HST F555W default params
    Arguments:
    Output: Filter with default F555W attributes
    """
    def __init__(self, **kwargs):
        args = {}
        # set defaults
        args['exposure'] = 1360.
        args['zpt_vega'] = 25.7318  # see filter_setup.ipynb
        args['zpt_ab'] = 25.7319
        args['zpt_st'] = 25.6857
        args['red_per_ebv'] = 2.792
        args['psf'] = PSF_Model.from_fits('ACS_WFC_F555W')
        args['name'] = "F555W"
        args['tex_name'] = r"V$_{555}$"
        args['MIST_column'] = "ACS_WFC_F555W"
        args['MIST_column_alt'] = "vmag"
        # update with manual entries
        args.update(kwargs)
        super().__init__(**args)

class ACS_WFC_F606W(Filter):
    """Return a Filter with HST F606W default params
    Arguments:
    Output: Filter with default F606W attributes
    """
    def __init__(self, **kwargs):
        args = {}
        # set defaults
        args['exposure'] = 3500.
        args['zpt_vega'] = 26.4187  # see filter_setup.ipynb
        args['zpt_ab'] = 26.5116
        args['zpt_st'] = 26.6808
        args['red_per_ebv'] = 2.471
        args['psf'] = PSF_Model.from_fits('ACS_WFC_F606W')
        args['name'] = "F606W"
        args['tex_name'] = r"V$_{606}$"
        args['MIST_column'] = "ACS_WFC_F606W"
        args['MIST_column_alt'] = "Vmag"
        # update with manual entries
        args.update(kwargs)
        super().__init__(**args)

class ACS_WFC_F814W(Filter):
    """Return a Filter with HST F814W default params
    Arguments:
    Output: Filter with default F814W attributes
    """
    def __init__(self, **kwargs):
        args = {}
        # set defaults
        args['exposure'] = 1360.
        args['zpt_vega'] = 25.5283  # see filter_setup.ipynb
        args['zpt_ab'] = 25.9565
        args['zpt_st'] = 26.7927
        args['red_per_ebv'] = 1.536
        args['psf'] = PSF_Model.from_fits('ACS_WFC_F814W')
        args['name'] = "F814W"
        args['tex_name'] = r"I$_{814}$"
        args['MIST_column'] = "ACS_WFC_F814W"
        args['MIST_column_alt'] = "imag"
        # update with manual entries
        args.update(kwargs)
        super().__init__(**args)

class ACS_WFC_F850LP(Filter):
    """Return a Filter with HST F850LP default params
    Arguments:
    Output: Filter with default F850LP attributes
    """

    def __init__(self, **kwargs):
        args = {}
        # set defaults
        args['exposure'] = 560.0
        args['zpt_vega'] = 24.3530
        args['zpt_ab'] = 24.8788
        args['zpt_st'] = 25.9668
        args['red_per_ebv'] = 1.243
        args['psf'] = PSF_Model.from_fits('ACS_WFC_F850LP')
        args['name'] = 'F850LP'
        args['tex_name'] = r'z$_{850}$'
        args['MIST_column'] = 'ACS_WFC_F850LP'
        args['MIST_column_alt'] = 'zmag'
        # update with manual entries
        args.update(kwargs)
        super().__init__(**args)

AVAILABLE_FILTERS = {
    'F435W': ACS_WFC_F435W,
    'F475W': ACS_WFC_F475W,
    'F555W': ACS_WFC_F555W,
    'F606W': ACS_WFC_F606W,
    'F814W': ACS_WFC_F814W,
    'F850LP': ACS_WFC_F850LP,
}

m31_filter_sets = [ACS_WFC_F814W, ACS_WFC_F475W]
m51_filter_sets = [ACS_WFC_F814W, ACS_WFC_F555W, ACS_WFC_F435W]
m49_filter_sets = [ACS_WFC_F850LP, ACS_WFC_F475W]

def default_m31_filters(exp_F814W=3235.0,
                        exp_F475W=3620.0):
    filts = [ACS_WFC_F814W(exposure=exp_F814W),
             ACS_WFC_F475W(exposure=exp_F475W)]
    return filts

def m31_summer_filters(exp_F814W=3040.0,
                       exp_F475W=3440.0):
    filts = [ACS_WFC_F814W(exposure=exp_F814W),
             ACS_WFC_F475W(exposure=exp_F475W)]
    return filts

def m31_winter_filters(exp_F814W=3430.0,
                       exp_F475W=3800.0):
    filts = [ACS_WFC_F814W(exposure=exp_F814W),
             ACS_WFC_F475W(exposure=exp_F475W)]
    return filts

def default_m51_filters(exp_ratio=1.0,
                        alpha_F814W=1.0, alpha_F435W=1.0):
    psf_f814w = PSF_Model.from_fits('ACS_WFC_F814W',
                                    narrow_alpha=alpha_F814W)
    psf_f435w = PSF_Model.from_fits('ACS_WFC_F435W',
                                    narrow_alpha=alpha_F435W)
    red = ACS_WFC_F814W(
        exposure=1360.*exp_ratio,
        zpt_vega=25.5286,
        zpt_ab=25.9568,
        zpt_st=26.7930,
        psf=psf_f814w)
    blue = ACS_WFC_F435W(
        exposure=2720.*exp_ratio,
        zpt_vega=25.7889,
        zpt_ab=25.6907,
        zpt_st=25.1805,
        psf=psf_f435w)
    return [red, blue]

def default_m49_filters(exp_ratio=1.0,
                        alpha_F850LP=1.0, alpha_F475W=1.0):
    psf_f850lp = PSF_Model.from_fits('ACS_WFC_F850LP',
                                     narrow_alpha=alpha_F850LP)
    psf_f475w = PSF_Model.from_fits('ACS_WFC_F475W',
                                    narrow_alpha=alpha_F475W)
    red = ACS_WFC_F850LP(
        exposure=1120.*exp_ratio,
        zpt_vega=24.3530,
        zpt_ab=24.8788,
        zpt_st=25.9668,
        psf=psf_f850lp)
    blue = ACS_WFC_F475W(
        exposure=750.*exp_ratio,
        zpt_vega=26.1746,
        zpt_ab=26.0820,
        zpt_st=25.7713,
        psf=psf_f475w)
    return [red, blue]

def default_m87_filters(exp_ratio=1.0,
        alpha_F814W=1.0, alpha_F606W=1.0):
    psf_f814w = PSF_Model.from_fits('ACS_WFC_F814W',
                                    narrow_alpha=alpha_F814W)
    psf_f606w = PSF_Model.from_fits('ACS_WFC_F606W',
                                    narrow_alpha=alpha_F606W)
    red = ACS_WFC_F814W(
        exposure=2880.*exp_ratio,
        zpt_vega=25.5274,
        zpt_ab=25.9556,
        zpt_st=26.7919,
        psf=psf_f814w)
    blue = ACS_WFC_F606W(
        exposure=3000.*exp_ratio,
        zpt_vega=26.4187,
        zpt_ab=26.5116,
        zpt_st=26.6808,
        psf=psf_f606w)
    return [red, blue]

def m87_filters_v2(exp_ratio=1.0,
                   alpha_F814W=1.0, alpha_F475W=1.0):
    psf_f814w = PSF_Model.from_fits('ACS_WFC_F814W',
                                    narrow_alpha=alpha_F814W)
    psf_f475w = PSF_Model.from_fits('ACS_WFC_F475W',
                                    narrow_alpha=alpha_F475W)
    red = ACS_WFC_F814W(
        exposure=2880.*exp_ratio,
        zpt_vega=25.5274,
        zpt_ab=25.9556,
        zpt_st=26.7919,
        psf=psf_f814w)
    blue = ACS_WFC_F475W(
        exposure=750.*exp_ratio,
        zpt_vega=26.1753,
        zpt_ab=26.0828,
        zpt_st=25.7720,
        psf=psf_f475w)
    return [red, blue]

# def lowexp_m87_filters():
#     red = ACS_WFC_F814W(
#         exposure=2880.*0.95,
#         zpt_vega=25.5274,
#         zpt_ab=25.9556,
#         zpt_st=26.7919)
#     blue = ACS_WFC_F606W(
#         exposure=3000.*0.95,
#         zpt_vega=26.4187,
#         zpt_ab=26.5116,
#         zpt_st=26.6808)
#     return [red, blue]

def default_ngc3377_filters(exp_ratio=1.0,
                            alpha_F850LP=1.0, alpha_F475W=1.0):
    psf_f850lp = PSF_Model.from_fits('ACS_WFC_F850LP',
                                     narrow_alpha=alpha_F850LP)
    psf_f475w = PSF_Model.from_fits('ACS_WFC_F475W',
                                    narrow_alpha=alpha_F475W)
    red = ACS_WFC_F850LP(
        exposure=3005.0*exp_ratio,
        zpt_vega=24.3512,
        zpt_ab=24.8770,
        zpt_st=25.9650,
        psf=psf_f850lp)
    blue = ACS_WFC_F475W(
        exposure=1380.0*exp_ratio,
        zpt_vega=26.1702,
        zpt_ab=26.0776,
        zpt_st=25.7668,
        psf=psf_f475w)
    return [red, blue]

def default_ngc4993_filters(exp_ratio=1.0):
    red = ACS_WFC_F850LP(
        exposure=680.*exp_ratio,
        zpt_vega=24.3316,
        zpt_ab=24.8573,
        zpt_st=25.9444)
    blue = ACS_WFC_F475W(
        exposure=1395.*exp_ratio,
        zpt_vega=26.1477,
        zpt_ab=26.0552,
        zpt_st=25.7448)
    return [red, blue]

def default_df2_filters(exp_ratio=1.0):
    red = ACS_WFC_F814W(
        exposure=2320.*exp_ratio,
        zpt_vega=25.5163,
        zpt_ab=25.9442,
        zpt_st=26.7998)
    blue = ACS_WFC_F606W(
        exposure=2180.*exp_ratio,
        zpt_vega=26.4044,
        zpt_ab=26.4977,
        zpt_st=26.6679)
    return [red, blue]

def m31_narrow_psf(alpha_F814W=1.147, alpha_F475W=1.109):
    filts = []
    psf_f814w = PSF_Model.from_fits('ACS_WFC_F814W',
                                    narrow_alpha=alpha_F814W)
    psf_f475w = PSF_Model.from_fits('ACS_WFC_F475W',
                                    narrow_alpha=alpha_F475W)
    filts.append(ACS_WFC_F814W(exposure=3235., psf=psf_f814w))
    filts.append(ACS_WFC_F475W(exposure=3620., psf=psf_f475w))
    return filts


#!/usr/bin/env python

from __future__ import print_function

import argparse
import numpy as np
import time
from PIL import Image
import chainer
import chainer.functions as F
import chainer.links as L

def main():
    parser = argparse.ArgumentParser(description='vgg16')
    parser.add_argument('--input', '-i', type=str, default='./images/cat.jpg',
                        help='predict imagefile')
    parser.add_argument('--gpu', '-g', type=int, default=-1,
                        help='GPU ID (negative value indicates CPU)')
    args = parser.parse_args()

    print('GPU: {}'.format(args.gpu))
    print('Input: {}'.format(args.input))
    print('')

    # import VGG model
    print('load network')
    vgg16 = L.VGG16Layers()
    print('load network, done.')

    # prediction test
    img = Image.open(args.input)
    x = L.model.vision.vgg.prepare(img)
    x = x[np.newaxis] # batch size
    print('predict')
    starttime = time.time()
    result = vgg16(x)
    predict = F.argmax(F.softmax(result['prob'], axis=1), axis=1)
    endtime = time.time()
    print(predict, (endtime - starttime), 'sec')  # variable([281]) 47.0666120052 sec

if __name__ == '__main__':
    main()


# AUTOGENERATED! DO NOT EDIT! File to edit: 01_petastorm.ipynb (unless otherwise specified).

__all__ = ['ParquetIterableDataset']

# Cell
from petastorm import make_batch_reader, TransformSpec
from petastorm.pytorch import DataLoader as PetaDataLoader
from torch.utils.data import TensorDataset, DataLoader as TorchDataLoader, IterableDataset
from torch import tensor
from pyarrow.parquet import ParquetFile, ParquetReader
import os
import re
import torch
import math
import pandas as pd
import numpy as np

def _init_filenames(log, filename_param, rex=None):
    # note to self: I think that comes from petastorm/parquet but I don't really remember now :/
    FILE_PREFIX = 'file:'

    if rex is None:
        return filename_param

    filename = filename_param[len(FILE_PREFIX):]
    if not os.path.isdir(filename):
        raise ValueError(f"Filteri ng only possible for dirs, {filename} is not a one")

    paths = [os.path.join(dp, f) for dp, dn, fn in os.walk(filename) for f in fn]
    res = list(map(
        lambda f: FILE_PREFIX + f,
        filter(lambda f: re.match(rex, f) is not None, paths)
    ))
    if (len(res) == 0):
        raise ValueError(f"0 files remained out ot {len(paths)} - seems regex is too restrictive")

    if (len(res) == len(paths)):
        raise ValueError(f"{len(paths)} files remained out ot {len(paths)} - seems regex is a no op")

    log.debug(f"{filename_param} -> {len(res)} files out of {len(paths)} remained after applying filter ({rex})")
    return res;

# Cell
class ParquetIterableDataset(IterableDataset):
    def __init__(self, filename, log, rex=None):
        super().__init__()
        self._filename_param = filename
        self.rex_param = rex
        self.log = log
        # self.patch = PetastormLeakyDescriptorsPatch()
        # self.patch.patch_leaking_fd(log)
        self.filename_param = filename
        self.filename = _init_filenames(log, filename, rex)

    def _init_petaloader(self):
        def _transform_row(df_batch):
            return df_batch

        transform = TransformSpec(_transform_row, removed_fields=['cat_id', 'store_id', 'state_id'])
        reader = make_batch_reader(self.filename,
                 schema_fields=['id', 'item_id', 'dept_id', 'cat_id', 'day_id',
               'sales', 'day_date_str', 'month_id', 'date', 'wm_yr_wk',
               'snap_flag', 'sell_price', 'sales_dollars', 'store_id', 'state_id'],
                workers_count=1
                #,transform_spec = transform
        )
        return PetaDataLoader(reader=reader, batch_size=128, shuffling_queue_capacity=100000)

    def __len__(self):
        return 1913*30490 # can be arbitrary large value to prevent WARN logs, seem to be ignored anyway

    def __iter__(self):
        self.log.debug(f"Iterator created on {self._filename_param}")
        worker_info = torch.utils.data.get_worker_info()
        if worker_info is None:
            count_cells = 0
            count_batches = 0
            with self._init_petaloader() as loader:
                # self.patch.patch_loader(loader)
                for batch in loader:
                    count_batches += 1
                    # TODO: propagate petaloader's batches without breaking them into individual items
                    for idx in range(len(batch['sell_price'])):
                        price         = batch['sell_price'][idx]
                        sales_dollars = batch['sales_dollars'][idx] if ('sales_dollars' in batch) else -1.
                        price_is_nan = math.isnan(price)
                        # TODO: this starts to look like feature extraction, doesn't belong here
                        price_or_zero = 0. if price_is_nan else price
                        count_cells += 1
                        # float32 needed for pytorch downstream
                        yield {'features': tensor([price_or_zero, price_is_nan], dtype=torch.float32),
                               'targets': tensor([sales_dollars])}

            self.log.debug(f'Done iterating: {count_batches} batches / ({count_cells} cells) ')
        else:
            raise ValueError("Not implemented for multithreading")


#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Copyright (c) 2014-2021 Megvii Inc. All rights reserved.

import cv2
import numpy as np
import torch
import torchvision

from DOTA_devkit_YOLO import polyiou

__all__ = [
    "filter_box",
    "postprocess",
    "bboxes_iou",
    "matrix_iou",
    "adjust_box_anns",
    "xyxy2xywh",
    "xyxy2cxcywh",
    'bboxes_iou_obb',  # add
    'py_cpu_nms_poly',  # add
    'postprocessobb',
    'postprocessobb_kld'
]

def filter_box(output, scale_range):
    """
    output: (N, 5+class) shape
    """
    min_scale, max_scale = scale_range
    w = output[:, 2] - output[:, 0]
    h = output[:, 3] - output[:, 1]
    keep = (w * h > min_scale * min_scale) & (w * h < max_scale * max_scale)
    return output[keep]

def postprocess(prediction, num_classes, conf_thre=0.7, nms_thre=0.45):  # [batch, n_anchors_all, 4 + 1 +  80]
    box_corner = prediction.new(prediction.shape)
    box_corner[:, :, 0] = prediction[:, :, 0] - prediction[:, :, 2] / 2
    box_corner[:, :, 1] = prediction[:, :, 1] - prediction[:, :, 3] / 2
    box_corner[:, :, 2] = prediction[:, :, 0] + prediction[:, :, 2] / 2
    box_corner[:, :, 3] = prediction[:, :, 1] + prediction[:, :, 3] / 2
    prediction[:, :, :4] = box_corner[:, :, :4]

    output = [None for _ in range(len(prediction))]
    for i, image_pred in enumerate(prediction):

        # If none are remaining => process next image
        if not image_pred.size(0):
            continue
        # Get score and class with highest confidence
        class_conf, class_pred = torch.max(image_pred[:, 5: 5 + num_classes], 1, keepdim=True)  # [n_anchors_all, 1]

        conf_mask = (image_pred[:, 4] * class_conf.squeeze() >= conf_thre).squeeze()
        # Detections ordered as (x1, y1, x2, y2, obj_conf, class_conf, class_pred)
        detections = torch.cat((image_pred[:, :5], class_conf, class_pred.float()), 1)
        detections = detections[conf_mask]
        if not detections.size(0):
            continue

        nms_out_index = torchvision.ops.batched_nms(
            detections[:, :4],
            detections[:, 4] * detections[:, 5],
            detections[:, 6],
            nms_thre,
        )
        detections = detections[nms_out_index]
        if output[i] is None:
            output[i] = detections
        else:
            output[i] = torch.cat((output[i], detections))

    return output

def postprocessobb(prediction, num_classes, conf_thre=0.7, nms_thre=0.45):  # [batch, n_anchors_all, 4 + 1 + 180 + 80]
    # box_corner = prediction.new(prediction.shape)
    # box_corner[:, :, 0] = prediction[:, :, 0] - prediction[:, :, 2] / 2
    # box_corner[:, :, 1] = prediction[:, :, 1] - prediction[:, :, 3] / 2
    # box_corner[:, :, 2] = prediction[:, :, 0] + prediction[:, :, 2] / 2
    # box_corner[:, :, 3] = prediction[:, :, 1] + prediction[:, :, 3] / 2
    # prediction[:, :, :4] = box_corner[:, :, :4] # xywh to xyxy

    output = [None for _ in range(len(prediction))]
    for i, image_pred in enumerate(prediction):

        # If none are remaining => process next image
        if not image_pred.size(0):
            continue
        # Get score and class with highest confidence
        class_conf, class_pred = torch.max(image_pred[:, 185: 185 + num_classes], 1, keepdim=True)  # [n_anchors_all, 1]
        _, angle_pred = torch.max(image_pred[:, 5: 185], 1, keepdim=True)
        angle_pred = angle_pred - 90  # (-90, 89)
        # print(angle_pred)

        conf_mask = (image_pred[:, 4] * class_conf.squeeze() >= conf_thre).squeeze()
        # Detections ordered as (x, y, w, h, angle_pred, class_conf, class_pred, obj_conf)
        detections = torch.cat(
            (image_pred[:, :4], angle_pred.float(), class_conf, class_pred.float(), image_pred[:, 4].unsqueeze(1)), 1)
        detections = detections[conf_mask]
        if not detections.size(0):
            continue

        detections = detections.numpy()
        boxes = np.zeros((0, 10))
        boxes_class = np.zeros((0, 9))

        # print(detections[0:5, :])

        for j in range(detections.shape[0]):
            if -90 < detections[j][4] <= 0:
                detections[j][2], detections[j][3] = detections[j][3], detections[j][2]
                detections[j][4] = detections[j][4] + 90.0
            if detections[j][4] == -90.0:
                detections[j][4] = 90.0
            rect = ((detections[j][0], detections[j][1]), (detections[j][3], detections[j][2]), detections[j][4])

            # rect = ((detections[j][0], detections[j][1]), (detections[j][2], detections[j][3]), detections[j][4])
            box = cv2.boxPoints(rect)  # (x1,y1,x2,y2,x3,y3,x4,y4)
            box = np.int0(box)
            box = box.reshape(-1)
            box = np.append(box, detections[j][5] * detections[j][7])
            box = np.append(box, detections[j][6])
            # (x1,y1,x2,y2,x3,y3,x4,y4, class_conf*obj_conf, class_pred)
            box_class = np.copy(box[0:9])
            box_class[0:8] = box_class[0:8] + 4000 * detections[j][6]
            # (x1,y1,x2,y2,x3,y3,x4,y4, class_conf*obj_conf)
            box_class = box_class.reshape(1, 9)
            box = box.reshape(1, 10)
            boxes_class = np.append(box_class, boxes_class, axis=0)
            boxes = np.append(box, boxes, axis=0)

        nms_out_index = py_cpu_nms_poly(boxes_class, nms_thre)
        boxes = boxes[nms_out_index]
        boxes = torch.from_numpy(boxes)  # (x1,y1,x2,y2,x3,y3,x4,y4, class_conf*obj_conf, class_pred)

        if output[i] is None:
            output[i] = boxes
        else:
            output[i] = torch.cat((output[i], boxes))
    return output

def postprocessobb_kld(prediction, num_classes, conf_thre=0.7, nms_thre=0.45):  # [batch, n_anchors_all, 5 + 1 + 80]
    # box_corner = prediction.new(prediction.shape)
    # box_corner[:, :, 0] = prediction[:, :, 0] - prediction[:, :, 2] / 2
    # box_corner[:, :, 1] = prediction[:, :, 1] - prediction[:, :, 3] / 2
    # box_corner[:, :, 2] = prediction[:, :, 0] + prediction[:, :, 2] / 2
    # box_corner[:, :, 3] = prediction[:, :, 1] + prediction[:, :, 3] / 2
    # prediction[:, :, :4] = box_corner[:, :, :4] # xywh to xyxy

    output = [None for _ in range(len(prediction))]
    for i, image_pred in enumerate(prediction):
        # (x,y,w,h,angle,obj_conf,n_class)
        # If none are remaining => process next image
        if not image_pred.size(0):
            continue
        # Get score and class with highest confidence
        class_conf, class_pred = torch.max(image_pred[:, 6: 6 + num_classes], 1, keepdim=True)  # [n_anchors_all, 1]
        conf_mask = (image_pred[:, 5] * class_conf.squeeze() >= conf_thre).squeeze()
        detections = torch.cat((image_pred[:, :5], class_conf, class_pred.float(), image_pred[:, 5].unsqueeze(1)),
                               dim=1)
        detections = detections[conf_mask]
        if not detections.size(0):
            continue

        detections = detections.numpy()
        boxes = np.zeros((0, 10))
        boxes_class = np.zeros((0, 9))

        # print(detections[0:5, :])

        for j in range(detections.shape[0]):
            if -90 < detections[j][4] <= 0:
                detections[j][2], detections[j][3] = detections[j][3], detections[j][2]
                detections[j][4] = detections[j][4] + 90.0
            if detections[j][4] == -90.0:
                detections[j][4] = 90.0
            rect = ((detections[j][0], detections[j][1]), (detections[j][2], detections[j][3]), detections[j][4])

            # rect = ((detections[j][0], detections[j][1]), (detections[j][2], detections[j][3]), detections[j][4])
            box = cv2.boxPoints(rect)  # (x1,y1,x2,y2,x3,y3,x4,y4)
            box = np.int0(box)
            box = box.reshape(-1)
            box = np.append(box, detections[j][5] * detections[j][7])
            box = np.append(box, detections[j][6])
            # (x1,y1,x2,y2,x3,y3,x4,y4, class_conf*obj_conf, class_pred)
            box_class = np.copy(box[0:9])
            box_class[0:8] = box_class[0:8] + 4000 * detections[j][6]
            # (x1,y1,x2,y2,x3,y3,x4,y4, class_conf*obj_conf)
            box_class = box_class.reshape(1, 9)
            box = box.reshape(1, 10)
            boxes_class = np.append(box_class, boxes_class, axis=0)
            boxes = np.append(box, boxes, axis=0)

        nms_out_index = py_cpu_nms_poly(boxes_class, nms_thre)
        boxes = boxes[nms_out_index]
        boxes = torch.from_numpy(boxes)  # (x1,y1,x2,y2,x3,y3,x4,y4, score, class_pred)

        if output[i] is None:
            output[i] = boxes
        else:
            output[i] = torch.cat((output[i], boxes))
    return output

def py_cpu_nms_poly(dets, thresh):
    """
    任意四点poly nms.取出nms后的边框的索引
    @param dets: shape(detection_num, [poly, confidence1]) 原始图像中的检测出的目标数量
    @param thresh:
    @return:
            keep: 经nms后的目标边框的索引
    """
    scores = dets[:, 8]
    polys = []
    areas = []
    for i in range(len(dets)):
        tm_polygon = polyiou.VectorDouble([dets[i][0], dets[i][1],
                                           dets[i][2], dets[i][3],
                                           dets[i][4], dets[i][5],
                                           dets[i][6], dets[i][7]])
        polys.append(tm_polygon)

    # argsort将元素小到大排列 返回索引值 [::-1]即从后向前取元素
    order = scores.argsort()[::-1]  # 取出元素的索引值 顺序为从大到小
    keep = []
    while order.size > 0:
        ovr = []
        i = order[0]  # 取出当前剩余置信度最大的目标边框的索引
        keep.append(i)
        for j in range(order.size - 1):  # 求出置信度最大poly与其他所有poly的IoU
            iou = polyiou.iou_poly(polys[i], polys[order[j + 1]])
            ovr.append(iou)
        ovr = np.array(ovr)
        inds = np.where(ovr <= thresh)[0]  # 找出iou小于阈值的索引
        order = order[inds + 1]
    return keep

def bboxes_iou(bboxes_a, bboxes_b, xyxy=True):
    if bboxes_a.shape[1] != 4 or bboxes_b.shape[1] != 4:
        raise IndexError

    if xyxy:
        tl = torch.max(bboxes_a[:, None, :2], bboxes_b[:, :2])
        br = torch.min(bboxes_a[:, None, 2:], bboxes_b[:, 2:])
        area_a = torch.prod(bboxes_a[:, 2:] - bboxes_a[:, :2], 1)
        area_b = torch.prod(bboxes_b[:, 2:] - bboxes_b[:, :2], 1)
    else:
        tl = torch.max(
            (bboxes_a[:, None, :2] - bboxes_a[:, None, 2:] / 2),
            (bboxes_b[:, :2] - bboxes_b[:, 2:] / 2),
        )
        br = torch.min(
            (bboxes_a[:, None, :2] + bboxes_a[:, None, 2:] / 2),
            (bboxes_b[:, :2] + bboxes_b[:, 2:] / 2),
        )

        area_a = torch.prod(bboxes_a[:, 2:], 1)
        area_b = torch.prod(bboxes_b[:, 2:], 1)
    en = (tl < br).type(tl.type()).prod(dim=2)
    area_i = torch.prod(br - tl, 2) * en  # * ((tl < br).all())
    return area_i / (area_a[:, None] + area_b - area_i)

def matrix_iou(a, b):
    """
    return iou of a and b, numpy version for data augenmentation
    """
    lt = np.maximum(a[:, np.newaxis, :2], b[:, :2])
    rb = np.minimum(a[:, np.newaxis, 2:], b[:, 2:])

    area_i = np.prod(rb - lt, axis=2) * (lt < rb).all(axis=2)
    area_a = np.prod(a[:, 2:] - a[:, :2], axis=1)
    area_b = np.prod(b[:, 2:] - b[:, :2], axis=1)
    return area_i / (area_a[:, np.newaxis] + area_b - area_i + 1e-12)

def adjust_box_anns(bbox, scale_ratio, padw, padh, w_max, h_max):
    bbox[:, 0::2] = np.clip(bbox[:, 0::2] * scale_ratio + padw, 0, w_max)
    bbox[:, 1::2] = np.clip(bbox[:, 1::2] * scale_ratio + padh, 0, h_max)
    return bbox

def xyxy2xywh(bboxes):
    bboxes[:, 2] = bboxes[:, 2] - bboxes[:, 0]
    bboxes[:, 3] = bboxes[:, 3] - bboxes[:, 1]
    return bboxes

def xyxy2cxcywh(bboxes):
    bboxes[:, 2] = bboxes[:, 2] - bboxes[:, 0]
    bboxes[:, 3] = bboxes[:, 3] - bboxes[:, 1]
    bboxes[:, 0] = bboxes[:, 0] + bboxes[:, 2] * 0.5
    bboxes[:, 1] = bboxes[:, 1] + bboxes[:, 3] * 0.5
    return bboxes

def iou_rotate_calculate(boxes1, boxes2):
    area1 = boxes1[2] * boxes1[3]
    area2 = boxes2[2] * boxes2[3]
    r1 = ((boxes1[0], boxes1[1]), (boxes1[2], boxes1[3]), boxes1[4])
    r2 = ((boxes2[0], boxes2[1]), (boxes2[2], boxes2[3]), boxes2[4])

    int_pts = cv2.rotatedRectangleIntersection(r1, r2)[1]
    if int_pts is not None:
        order_pts = cv2.convexHull(int_pts, returnPoints=True)

        int_area = cv2.contourArea(order_pts)

        inter = int_area * 1.0 / (area1 + area2 - int_area)
        return inter
    else:
        return 0.0

def bboxes_iou_obb(gt_bboxes_per_image, bboxes_preds_per_image):
    ious = np.zeros((gt_bboxes_per_image.shape[0], bboxes_preds_per_image.shape[0]), dtype=np.float32)
    for i in range(gt_bboxes_per_image.shape[0]):
        for j in range(bboxes_preds_per_image.shape[0]):
            ious[i][j] = iou_rotate_calculate(gt_bboxes_per_image[i], bboxes_preds_per_image[j])
    return ious

def bboxes_iou_obb_cuda(gt_bboxes_per_image, bboxes_preds_per_image):
    ious = np.zeros((gt_bboxes_per_image.shape[0], bboxes_preds_per_image.shape[0]), dtype=np.float32)
    for i in range(gt_bboxes_per_image.shape[0]):
        for j in range(bboxes_preds_per_image.shape[0]):
            ious[i][j] = iou_rotate_calculate(gt_bboxes_per_image[i], bboxes_preds_per_image[j])
    return ious


"""Parsing functionality of a DeGiro 'Account.csv' file."""
import csv
import datetime
from pathlib import Path
from typing import Dict, Sequence, Tuple, List

import numpy as np

from . import market

# Header of the Account.csv file from DeGiro export
CSV_HEADER = "Datum,Tijd,Valutadatum,Product,ISIN,Omschrijving,FX,Mutatie,,Saldo,,Order Id"

# If any of these words (case agnostic) are found in a shares name, it is considered to be an ETF
SUBSTRINGS_IN_ETF = ["Amundi", "X-TR", "ETFS", "ISHARES", "LYXOR", "Vanguard", "WISDOMTR"]
# ... ano others, not complete of course

def read_account(account_csv: Path) -> Tuple[List[List[str]], datetime.date]:
    """Opens a DeGiro 'Account.csv' file and returns the contents as well as the first date"""
    csv_data = list(csv.reader(account_csv.open()))
    if csv_data[0] != CSV_HEADER.split(","):
        raise RuntimeError(f"Error while parsing '{account_csv}' file, unexpected header"
                           f"\nFound: {csv_data[0]}\nExpected: {CSV_HEADER.split(',')}")
    first_date = datetime.datetime.strptime(csv_data[-1][0], "%d-%m-%Y").date()
    return csv_data, first_date

def parse_single_row(row: List[str], dates: Sequence[datetime.date], date_index: int,
                     invested: np.ndarray, cash: np.ndarray, shares_value: np.ndarray, bank_cash: np.ndarray) -> None:
    """Parses a single row of the CSV data, updating all the NumPy arrays (they are both input and output)."""
    # pylint: disable=too-many-locals,too-many-arguments,too-many-statements,too-many-branches

    date, _, _, name, isin, description, _, currency, mutation_string, _, _, _ = row
    mutation = float(mutation_string.replace(",", ".")) if mutation_string != '' else 0.0
    currency_modifier = market.to_euro_modifier(currency, dates)[date_index] if currency not in ("", "EUR") else 1

    # ----- Cash in and out -----

    if description in ("iDEAL storting", "Storting"):
        if bank_cash[date_index] > mutation:
            bank_cash[date_index:] -= mutation
        else:
            invested[date_index:] += (mutation - bank_cash[date_index])
            cash[date_index:] += (mutation - bank_cash[date_index])
            bank_cash[date_index:] = 0

    elif description in ("Terugstorting",):
        bank_cash[date_index:] -= mutation

    # ----- Buying and selling -----

    elif description.split(" ")[0] in ("Koop", "Verkoop"):
        buy_or_sell = "sell" if description.split(" ")[0] == "Verkoop" else "buy"
        multiplier = -1 if buy_or_sell == "sell" else 1
        num_shares = int(description.split(" ")[1].replace(".", ""))
        is_etf = any([etf_subname.lower() in name.lower() for etf_subname in SUBSTRINGS_IN_ETF])
        this_share_value, _ = market.get_data_by_isin(isin, dates, is_etf=is_etf)
        if this_share_value is None:  # no historical prices available for this stock/etf
            this_share_value = np.zeros(shape=len(dates)) + (-mutation / num_shares)

        print(f"[DGPC] {date}: {buy_or_sell:4s} {num_shares:4d} @ {this_share_value[date_index]:8.2f} EUR of {name}")

        shares_value[date_index:] += multiplier * num_shares * this_share_value[date_index:]
        cash[date_index:] += mutation * currency_modifier

    elif description == "Contante Verrekening Aandelen":
        cash[date_index:] += mutation
        print(f"[DGPC] {date}: special sell for {mutation} EUR")

    # ----- DeGiro usage costs -----

    elif description == "DEGIRO transactiekosten":
        cash[date_index:] += mutation

    elif "DEGIRO Aansluitingskosten" in description:
        cash[date_index:] += mutation

    elif "Externe Kosten" in description:
        cash[date_index:] += mutation * currency_modifier

    elif "Stamp Duty" in description:
        cash[date_index:] += mutation * currency_modifier

    # ----- Dividend -----

    elif description == "Dividend":
        cash[date_index:] += mutation * currency_modifier

    elif "dividendbelasting" in description.lower():
        cash[date_index:] += mutation * currency_modifier

    # ----- Implications of cash on the DeGiro account -----

    elif "Koersverandering geldmarktfonds" in description:
        cash[date_index:] += mutation * currency_modifier

    elif description == "DEGIRO Geldmarktfondsen Compensatie":
        cash[date_index:] += mutation * currency_modifier

    elif description == "Fondsuitkering":
        cash[date_index:] += mutation * currency_modifier

    elif description == "Rente":
        cash[date_index:] += mutation * currency_modifier

    elif "Conversie geldmarktfonds" in description:
        pass  # Nothing to do?

    # ----- Others -----

    elif description in ("Valuta Creditering", "Valuta Debitering"):
        pass  # Nothing to do - already taken into account?

    else:
        print(f"[DGPC] {date}: Unsupported type of entry '{description}', contents:")
        print(row)

def parse_account(csv_data: List[List[str]], dates: List[datetime.date]) -> Tuple[Dict[str, np.ndarray],
                                                                                Dict[str, np.ndarray]]:
    """Parses the csv-data and constructs NumPy arrays for the given date range with cash value, total account value,
    and total invested."""

    # Initial values
    num_days = len(dates)
    invested = np.zeros(shape=num_days)
    cash = np.zeros(shape=num_days)
    shares_value = np.zeros(shape=num_days)

    # We make the assumption that any money going out of the DeGiro account is still on a bank and thus counted here
    # as cash. This value holds the amount of money on the bank at a given time while parsing, with future cash
    # deposits reducing this value.
    bank_cash = np.zeros(shape=num_days)

    # Parse the CSV data
    date_index = 0
    stop_parsing = False
    for row in csv_data[1:][::-1]:

        # Retrieves the data of this CSV row
        if row[0] == "":
            continue
        date = datetime.datetime.strptime(row[0], "%d-%m-%Y").date()

        # Advance the date till we reach the date of the CSV entry
        while date != dates[date_index]:
            date_index += 1
            if date_index == num_days:
                print(f"[DGPC] Warning, CSV date {date} larger than dates range (up to {dates[-1]}), skipping data")
                stop_parsing = True
                break

        if stop_parsing:
            break

        parse_single_row(row, tuple(dates), date_index,
                         invested, cash, shares_value, bank_cash)

    # Set the absolute value metrics
    total_account = shares_value + cash
    absolutes = {"nominal account (without profit/loss)": invested,
                 "cash in DeGiro account": cash,
                 "total account value": total_account}

    # Set the relative metrics
    performance = np.divide(total_account, invested, out=np.zeros_like(invested), where=invested != 0)

    relatives = {"account performance":  performance}
    return absolutes, relatives


import os
from itertools import chain

import matplotlib

matplotlib.use("Agg")

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib.gridspec import GridSpec
from more_itertools import flatten
from sklearn.cluster import KMeans

from larval_gonad.config import read_config

def main():
    lit_genes = list(flatten(read_config(snakemake.input.lit_genes).values()))
    biomarkers = get_biomarkers()
    zscore = pd.pivot_table(
        pd.read_feather(snakemake.input.zscore),
        values="zscore",
        index="FBgn",
        columns=["cluster", "rep"],
        aggfunc="first",
    ).reindex(biomarkers.index)

    zscore_ordered, groups = kmeans_cluster(zscore)
    biomarkers_w_groups = add_groups_to_biomarkers(zscore_ordered.index, groups, biomarkers)

    fig = plt.figure()
    gs = GridSpec(2, 1, height_ratios=[1, 0.01], hspace=0.01)
    ax = fig.add_subplot(gs[0, 0])
    cax = fig.add_subplot(gs[1, 0])
    sns.heatmap(
        zscore_ordered,
        xticklabels=True,
        yticklabels=False,
        vmin=-3,
        vmax=3,
        rasterized=True,
        cmap=snakemake.params.color,
        ax=ax,
        cbar_ax=cax,
        cbar_kws=dict(label="Z-Score (TPM)", ticks=[-3, 0, 3], orientation="horizontal"),
    )
    cleanup_xaxis(ax)
    cleanup_yaxis(ax, biomarkers_w_groups)
    add_annotations(ax, biomarkers_w_groups, lit_genes, zscore.shape[1])

    plt.savefig(snakemake.output[0])

def get_biomarkers():
    biomarkers = (
        pd.read_feather(snakemake.input.biomarkers)
        .sort_values("FBgn")
        .assign(
            cluster=lambda df: pd.Categorical(
                df.cluster.map(dict(snakemake.params.cluster_annot)),
                categories=snakemake.params.cluster_order,
                ordered=True,
            )
        )
    )
    return (
        biomarkers
        .set_index("FBgn")
        .gene_symbol.drop_duplicates()
    )

def kmeans_cluster(zscore):
    km = KMeans().fit(zscore)
    return zscore.iloc[np.argsort(km.labels_)], np.unique(km.labels_, return_counts=True)

def add_groups_to_biomarkers(index, groups, biomarkers):
    bwg = biomarkers.reindex(index)
    g2fbgn = pd.Series(
        flatten([[g] * s for g, s in zip(*groups)]),
        index=index,
        name="group"
    )
    return pd.concat([bwg, g2fbgn], axis=1, sort=True)

def cleanup_xaxis(ax):
    ax.set_xlabel("")
    ax.xaxis.set_ticks_position("top")
    ax.set_xticklabels(
        list(chain.from_iterable([("", x, "") for x in snakemake.params.cluster_order])),
        ha="center",
        va="bottom",
    )

    # Add lines separating cell types
    for i in range(1, len(snakemake.params.cluster_order)):
        ax.axvline(i * 3, color="w", ls="--", lw=0.5)

    return ax

def cleanup_yaxis(ax, biomarkers):
    ax.set_ylabel("")
    # Add lines separating groups
    loc = 0
    for _, dd in biomarkers.groupby("group"):
        loc += dd.shape[0]
        ax.axhline(loc, color="w", ls="--", lw=0.5)

    return ax

def add_annotations(ax, biomarkers, lit_genes, cols=30):
    """Adds annotation on the left and right sides.

    Annotation includes the number of genes and the gene
    names of literature genes found in that set.

    """

    loc = 0
    xloc_odd, xloc_even = (-5, cols + cols * 0.01)
    for i, (clus, dd) in enumerate(biomarkers.groupby("group")):
        loc, mid = take_step(loc, dd.shape[0])
        txt = f"{dd.shape[0]:,} genes"
        txt += check_for_lit_genes(dd, lit_genes)

        if i % 2 == 0:
            xloc = xloc_even
        else:
            xloc = xloc_odd

        ax.text(xloc, mid, txt, ha="left", va="center", fontsize=8)

def take_step(loc, step_size):
    prev = loc
    loc += step_size
    mid = loc - ((loc - prev) / 2)
    return loc, mid

def check_for_lit_genes(df, lit_genes):
    res = []
    for fbgn, dd in df.sort_values("gene_symbol").iterrows():
        if fbgn in lit_genes:
            res.append(dd.gene_symbol)
    return "\n" + "\n".join(res)

if __name__ == "__main__":
    if os.getenv("SNAKE_DEBUG", False):
        from larval_gonad.debug import snakemake_debug
        from larval_gonad.config import read_config

        config = read_config("config/common.yaml")

        snakemake = snakemake_debug(
            workdir="seurat3-cluster-wf",
            input=dict(
                biomarkers="../output/seurat3-cluster-wf/combined_n3_biomarkers.feather",
                clusters="../output/seurat3-cluster-wf/combined_n3_clusters.feather",
                zscore="../output/seurat3-cluster-wf/zscore_by_cluster_rep.feather",
                lit_genes="../config/literature_genes.yaml",
            ),
            params=dict(
                color="viridis",
                cluster_annot=config["cluster_annot"],
                cluster_order=config["cluster_order"],
            ),
        )

    plt.style.use("../config/figure_styles.mplstyle")
    plt.rcParams.update({
        'figure.figsize': (2.5, 4),
        'font.size': 8.0,
        'axes.titlesize': 8.0,
        'axes.labelsize': 8.0,
        'xtick.labelsize': 8.0,
    })

    main()


import numpy as np
from komodo.atari import AtariEnvironment
from komodo.dqn import DQN, ReplayMemory
from komodo.utils import create_directories, log_scalar

def train(id, batch_size, base_dir='./examples'):
    """
        - `id`: id of the environment (e.g., "Pong-v4")
        - `batch_size`: transitions per batch
    """

    _, log_dir, _ = create_directories('Pong-v4', "a2c", base_dir)
    env = AtariEnvironment(gym.make(id))
    agent = DQN()
    memory = ReplayMemory(env)
    global_returns = []
    global_steps = 0
    global_start = time.time()
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        agent.clone(sess)
        writer = tf.summary.FileWriter(log_dir, sess.graph)
        while True:
            # begin episode
            state = env.reset()
            episode_return = 0.0
            episode_steps = 0
            start = time.time()
            while True:
                action = agent.select_action(state)
                next_state, reward, done, info = env.step(action)
                transition = [state, action, reward, next_state, done]
                current_memories = memory.append(transition)
                state = next_state.copy()
                episode_return += reward
                episode_steps += 1
                global_steps += 1
                epsilon = agent.anneal_epsilon(global_steps)
                if episode_steps % agent.update_freq == 0:
                    batch = memory.sample(batch_size)
                    states, actions, rewards, next_states, done_flags = batch
                    summary = agent.update(
                        states,
                        actions,
                        rewards,
                        next_states,
                        done_flags,
                        sess
                    )
                if global_steps % agent.clone_steps == 0:
                    agent.clone(sess)
                if done:
                    break
            episode_fps = episode_steps / (time.time() - start)
            # end episode
            global_episodes += 1
            global_returns += [episode_return]
            global_time = time.time() - global_start
            avg_return = np.mean(global_returns[-100:])
            log_scalar(writer, 'avg_return', avg_return, global_steps)
            log_scalar(writer, 'return', episode_return, global_steps)
            log_scalar(writer, 'steps', episode_steps, global_steps)
            log_scalar(writer, 'fps', episode_fps, global_steps)
            log_scalar(writer, 'epsilon', epsilon, global_steps)
            writer.add_summary(summary, global_steps)
            print(f"step={global_steps}, episode={global_episodes}, avg_return={avg_return:.2f}, elapsed={global_time:.2f}, fps={episode_fps:.2f}, epsilon={epsilon:.2f}")
            if avg_return > pass_condition:
                print(f"Pass condition reached! (avg_return={avg_return:.2f})")
                break


#!/usr/bin/env python

# Light each LED in sequence, and repeat.

import numpy as np
import sys
sys.path.append("../ar/")
import fastopc, time
import functionLib as lib
import micStream

nStrips = 16
lStrip  = 64

client = fastopc.FastOPC('localhost:7890')

pixels = lib.Pixels(nStrips, lStrip, 20)
zeroStrip = np.zeros_like(pixels.getArrayForDisplay())

chance = 0.05
waitBetweenChances = 0.05
waitTimeMultiplier = 0.01

while True:
    if np.random.rand()<chance:
        waitTimeThisStar = np.random.rand() * waitTimeMultiplier
        dir       = np.random.choice([-1,1])
        strip     = np.random.randint(0,high=nStrips)
        pos       = np.random.randint(1, high=lStrip-1)
        color     = np.random.randint(0, 255, size=3)
        theoStrip = zeroStrip
        theoStrip[strip*lStrip+pos] = color
        for i in range(0, 64):
            modNum = np.mod(pos, 128)
            if modNum == 0 or modNum == 63 or modNum == 64 or modNum == 127:
                pixels.update(zeroStrip, 1.0, 1.0)
                client.putPixels(0, pixels.getArrayForDisplay())
                break
            else:
                pos+=dir
                theoStrip = np.roll(theoStrip, dir, axis=0)
                pixels.update(theoStrip, 1.0, 0.1)
                if np.sum(pixels.getArrayForDisplay()) > (1024*3*200):
                    client.putPixels(0, np.zeros_like(pixels.getArrayForDisplay()))
                    break
                else:
                    client.putPixels(0, pixels.getArrayForDisplay())
                time.sleep(waitTimeThisStar)
    time.sleep(waitBetweenChances)


# USAGE
# python full_pipeline.py --livemodel output_liveness/liveness.model --le-liveness output_liveness/le.pickle --detector face_detector  --recognizer output_recognizer/recognizer.pickle  --le-recognizer output_recognizer/le.pickle

# import the necessary packages
from imutils.video import VideoStream
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
from tensorflow.config import list_physical_devices, experimental
import face_recognition
import numpy as np
import argparse
import imutils
import pickle
import time
import cv2
import os
import copy
import dlib

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--livemodel", type=str, required=True, help="path to trained livness model")
ap.add_argument("-l", "--le-liveness", type=str, required=True, help="path to label encoder of liveness model")
ap.add_argument("-d", "--detector", type=str, required=True, help="path to OpenCV's deep learning face detector")
ap.add_argument("-c", "--confidence", type=float, default=0.5,  help="minimum probability to filter weak detections")
ap.add_argument("-r", "--recognizer", required=True, help="path to model trained to recognize faces")
ap.add_argument("-b", "--le-recognizer", required=True, help="path to label encoder of recognizer model")
args = vars(ap.parse_args())

#only grow tensorflow memory usage as is needed the process(good for low memory GPUs)
physical_devices = list_physical_devices('GPU')
try:
    experimental.set_memory_growth(physical_devices[0], True)
    dlib.DLIB_USE_CUDA = True
except:
    # Invalid device or cannot modify virtual devices once initialized.
    pass

# load our serialized face detector from disk
print("[INFO] loading face detector...")
protoPath = os.path.sep.join([args["detector"], "deploy.prototxt"])
modelPath = os.path.sep.join([args["detector"],
    "res10_300x300_ssd_iter_140000.caffemodel"])
net = cv2.dnn.readNetFromCaffe(protoPath, modelPath)

# load the liveness detector model and label encoder from disk
print("[INFO] loading liveness detector...")
livemodel = load_model(args["livemodel"])
le_liveness = pickle.loads(open(args["le_liveness"], "rb").read())

# load the actual face recognition model along with the label encoder
print("[INFO] loading face recognizer...")
recognizer = pickle.loads(open(args["recognizer"], "rb").read())
le_recognizer = pickle.loads(open(args["le_recognizer"], "rb").read())

# initialize the video stream and allow the camera sensor to warmup
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(2.0)

# loop over the frames from the video stream
while True:
    # grab the frame from the threaded video stream and resize it
    # to have a maximum width of 600 pixels
    frame = vs.read()
    frame = imutils.resize(frame, width=600)
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # grab the frame dimensions and convert it to a blob
    (h, w) = frame.shape[:2]
    blob = cv2.dnn.blobFromImage(
        cv2.resize(frame, (300, 300)), 1.0, (300, 300),
        (104.0, 177.0, 123.0), swapRB=False, crop=False)

    # pass the blob through the network and obtain the detections and
    # predictions.
    net.setInput(blob)
    detections = net.forward()

    #Initialize boxes for face recognition
    boxes = []

    # loop over the detections
    for i in range(0, detections.shape[2]):
        # extract the confidence (i.e., probability) associated with the
        # prediction
        confidence = detections[0, 0, i, 2]

        # filter out weak detections
        if confidence > args["confidence"]:
            # compute the (x, y)-coordinates of the bounding box for
            # the face and extract the face ROI
            box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
            (startX, startY, endX, endY) = box.astype("int")

            # ensure the detected bounding box does fall outside the
            # dimensions of the frame
            startX = max(0, startX)
            startY = max(0, startY)
            endX = min(w, endX)
            endY = min(h, endY)

            # extract the face ROI and make a copy for passing it to
            # face recognizer if needed
            face = frame[startY:endY, startX:endX]
            face2 = copy.deepcopy(face)

            # Preproces the face ROI in the exact same manner as our
            # training livenss data
            try:
                face = cv2.resize(face, (32, 32))
                face = face.astype("float") / 255.0
                face = img_to_array(face)
                face = np.expand_dims(face, axis=0)
            except:
                raise Exception("Your face is too close to the camera. Please move your face slightly away from it and try again")

            # pass the face ROI through the trained liveness detector
            # model to determine if the face is "real" or "fake"
            preds = livemodel.predict(face)[0]
            j = np.argmax(preds)
            label = le_liveness.classes_[j]

            # draw the label and bounding box on the frame if fake, else save
            # the bounding  box for face recognition. Threshold for real is 0.75
            if label == "fake" or preds[1]<0.75:
                label = "{}: {:.4f}".format("fake", preds[0])
                cv2.putText(frame, label, (startX, startY - 10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
                cv2.rectangle(frame, (startX, startY), (endX, endY),
                    (0, 0, 255), 2)
            else:
                #save the bounding  box for face recognition.
                boxes.append((startY, endX, endY, startX))

    # compute the facial embedding for the faces
    encodings = face_recognition.face_encodings(rgb, boxes)

    # initialize the list of names and their probabilities
    names = []
    probs = []

    # loop over the facial embeddings
    for encoding in encodings:
        # perform classification to recognize the face
        preds = recognizer.predict_proba(encoding.reshape(1,-1))[0]
        j = np.argmax(preds)
        proba = preds[j]
        name = le_recognizer.classes_[j]
        names.append(name)
        probs.append(proba)

    # loop over the recognized faces
    for ((top, right, bottom, left), name, proba) in zip(boxes, names, probs):
        # draw the predicted face name on the image
        cv2.rectangle(frame, (left, top), (right, bottom),
            (0, 255, 0), 2)
        y = top - 15 if top - 15 > 15 else top + 15
        cv2.putText(frame, "{}: {:.2f}%".format(name, proba*100), (left, y), cv2.FONT_HERSHEY_SIMPLEX,
            0.75, (0, 255, 0), 2)

    # show the output frame and wait for a key press
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    # if the `q` key was pressed, break from the loop
    if key == ord("q"):
        break

# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()