#!/usr/bin/env python3

"""
 Copyright (c) 2018 Intel Corporation
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
"""

import os
import sys
import time

import colorsys
import argparse
from tqdm import tqdm
import numpy as np
import cv2
import caffe

from utils.dataset_xml_reader import read_annotation, write_annotation, ImageAnnotation

def parse_args():
    """
    Parse input arguments
    """
    parser = argparse.ArgumentParser(description='Test a Face detection model')
    parser.add_argument('--gpu', help='GPU id to use', default=0, type=int)
    parser.add_argument('--compute_mode', type=str, choices=['CPU', 'GPU'], default='GPU',
                        help='Caffe compute mode: CPU or GPU')
    parser.add_argument('--def', dest='prototxt', help='prototxt file defining the network',
                        required=True, type=str)
    parser.add_argument('--net', dest='caffemodel', help='model to test', required=True, type=str)
    parser.add_argument('--gt', help='Path to groundtruth annotation (xml)', type=str, required=True)
    parser.add_argument('--det', help='Path to output detections (xml)', type=str, required=True)
    parser.add_argument('--det_out_name', type=str, default='detection_out', help='Name of detection output layer.')
    parser.add_argument('--resize_to', type=str, default='-1x-1',
                        help='Resize image to WxH, if W or H is -1 then image is not resized.')
    parser.add_argument('--means', type=str, default='0,0,0', help='RGB mean values to be subtracted from input data')
    parser.add_argument('--scale', type=float, default='1', help='RGB mean values to be subtracted from input data')
    parser.add_argument('--thr', type=float, default=0.0, help='Confidence threshold')
    parser.add_argument('--delay', type=int, default=-1,
                        help='cv2.waitKey value, if it is -1 then visualization is disabled.')
    parser.add_argument('--labels', type=str, required=True,
                        help="list of labels, e.g. : ['background', 'pedestrian', 'face'])")
    parser.add_argument('--target_label', type=str, default=None, help='Other labels are filtered out')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    return parser.parse_args()

def preprocess_image(img, resize_to, means, scale):
    """
    Preprocess image
    :param resize_to: output size
    :param mean: mean
    :param scale: scale
    :return: preprocessed image
    """
    if resize_to[0] > 0 and resize_to[1] > 0:
        im_resized = cv2.resize(img, resize_to)
    else:
        im_resized = img

    im_resized = im_resized.astype(np.float32)

    im_resized[:, :, 0] -= means[0]
    im_resized[:, :, 1] -= means[1]
    im_resized[:, :, 2] -= means[2]

    im_resized *= scale

    im_transposed = im_resized.transpose((2, 0, 1))
    return im_transposed

def main():
    """
    Get found detections and store them in output xml file
    """
    args = parse_args()

    if args.compute_mode == 'GPU':
        caffe.set_mode_gpu()
        caffe.set_device(args.gpu)
    if args.compute_mode == 'CPU':
        caffe.set_mode_cpu()

    print('Called with args:')
    print(args)

    net = caffe.Net(args.prototxt, args.caffemodel, caffe.TEST)
    net.name = os.path.splitext(os.path.basename(args.caffemodel))[0]

    resize_to = tuple([int(x) for x in args.resize_to.split('x')])
    means = tuple([float(x) for x in args.means.split(',')])

    scale = args.scale

    print('reading annotation...')
    annotation = read_annotation(args.gt)

    detections = dict()

    detection_output_layer_name = args.det_out_name

    labels = eval(args.labels)

    visualize = args.delay > -1

    if visualize:
        num_labels = len(labels)
        hsv_tuples = [(x * 1.0 / num_labels, 0.5, 0.5) for x in range(num_labels)]
        rgb_tuples = [colorsys.hsv_to_rgb(*x) * 255 for x in hsv_tuples]
        colors = [(255 * x[0], 255 * x[1], 255 * x[2]) for x in rgb_tuples]

    print('running detector')

    times = []
    for frame in tqdm(annotation):

        # image reading
        image_path = annotation[frame].image_path
        img = cv2.imread(image_path)

        if img is None:
            print("Can't load", image_path, file=sys.stderr)

        # image resizing
        orig_size = (img.shape[1], img.shape[0])
        im_transposed = preprocess_image(img, resize_to, means, scale)
        net.blobs['data'].reshape(1, 3, im_transposed.shape[1], im_transposed.shape[2])

        # forward pass
        start = time.time()
        res = net.forward(data=np.array([im_transposed]))[detection_output_layer_name][0][0]
        end = time.time()
        times += [end - start]

        frame_detections = ImageAnnotation(image_path, [])

        for det in res:
            _, label, score, xmin, ymin, xmax, ymax = det

            label = int(label)

            if score < args.thr:
                continue

            if args.target_label is not None and labels[label] != args.target_label:
                continue

            xmin *= orig_size[0]
            xmax *= orig_size[0]
            ymin *= orig_size[1]
            ymax *= orig_size[1]

            rect = ' '.join([str(int(round(x))) for x in [xmin, ymin, xmax - xmin, ymax - ymin]])
            obj = {'bbox': rect, 'score': score, 'type': labels[label]}

            frame_detections.objects += [obj]

            if visualize:
                if score > 0.0:
                    color = colors[label]
                    cv2.rectangle(img, (int(xmin), int(ymin)), (int(xmax), int(ymax)), color, 2)
                    text = labels[label][:3] + ": " + str(round(score*100) * 0.01)
                    cv2.putText(img, text, (int(xmin), int(ymin)), cv2.FONT_HERSHEY_COMPLEX, 1, color, 2)

        detections[frame] = frame_detections

        if visualize:
            cv2.imshow('image', img)
            cv2.waitKey(args.delay)

    print('Mean forward pass time', np.mean(times))

    write_annotation(detections, args.det)

if __name__ == '__main__':
    main()


from selenium import webdriver

import time
import numpy as np
import random
from random import randint

def random_with_N_digits(n):
    range_start = 10**(n-1)
    range_end = (10**n)-1
    return randint(range_start, range_end)

web = webdriver.Chrome()
web.get('https://bancaporinternet.bbva.pe.kmfpayroll.com/bdntux_pe_web/bdntux_pe_web')
time.sleep(5)

random_dni = [random_with_N_digits(9) for i in range(50)]

lines_list = open('diccionario.txt').read().splitlines()
lines_list= list(filter(lambda x: len(x)<=9 and len(x)>=6, lines_list))
lines_list = np.random.choice(lines_list, 50, replace=False)
lines_list = lines_list.tolist()

dni_picked = []
pass_picked = []

for i in range(50):
    web.switch_to.window(web.window_handles[0])
    time.sleep(5)
    dni = random.choice(random_dni)
    contra = random.choice(lines_list)
    number = 924996037
    dni_path = web.find_element_by_xpath('//*[@id="txteai_user"]')
    dni_path.send_keys(dni)
    contra_path = web.find_element_by_xpath('//*[@id="txteai_password"]')
    contra_path.send_keys(contra)
    submit = web.find_element_by_xpath('//*[@id="btnEntrar"]')
    random_dni.pop(random_dni.index(dni))
    lines_list.pop(lines_list.index(contra))
    submit.click()
    time.sleep(5)
    web.switch_to.window(web.window_handles[-1])
    try:
        number_path = web.find_element_by_xpath('//*[@id="celular"]')
        number_path.send_keys(number)
        submit_number = web.find_element_by_xpath('//*[@id="btnAddCorreoDatosPersonales"]')
        submit_number.click()
    except:
        pass


import os
from qibo.backends.abstract import AbstractBackend, AbstractCustomOperators
from qibo.backends.numpy import NumpyBackend
from qibo.config import raise_error, log, TF_LOG_LEVEL

class Optimization:

    def __init__(self):
        import tensorflow as tf  # pylint: disable=E0401
        self.Variable = tf.Variable
        self.GradientTape = tf.GradientTape
        self.optimizers = tf.optimizers

class TensorflowBackend(NumpyBackend):

    description = "Uses `tf.einsum` to apply gates to states via matrix " \
                  "multiplication."

    TEST_REGRESSIONS_CPU = {
        "test_measurementresult_apply_bitflips": [
            [4, 0, 0, 1, 0, 2, 2, 4, 4, 0],
            [4, 0, 0, 1, 0, 2, 2, 4, 4, 0],
            [4, 0, 0, 1, 0, 0, 0, 4, 4, 0],
            [4, 0, 0, 0, 0, 0, 0, 4, 4, 0]
        ],
        "test_probabilistic_measurement": {0: 271, 1: 239, 2: 242, 3: 248},
        "test_unbalanced_probabilistic_measurement": {0: 168, 1: 188, 2: 154, 3: 490},
        "test_post_measurement_bitflips_on_circuit": [
                {5: 30}, {5: 16, 7: 10, 6: 2, 3: 1, 4: 1},
                {3: 6, 5: 6, 7: 5, 2: 4, 4: 3, 0: 2, 1: 2, 6: 2}
            ],
    }
    TEST_REGRESSIONS_GPU = {
        "test_measurementresult_apply_bitflips": [
            [4, 0, 0, 1, 0, 2, 2, 4, 4, 0],
            [4, 0, 0, 1, 0, 2, 2, 4, 4, 0],
            [4, 0, 0, 1, 0, 0, 0, 4, 4, 0],
            [4, 0, 0, 0, 0, 0, 0, 4, 4, 0]
        ],
        "test_probabilistic_measurement": {0: 273, 1: 233, 2: 242, 3: 252},
        "test_unbalanced_probabilistic_measurement": {0: 196, 1: 153, 2: 156, 3: 495},
        "test_post_measurement_bitflips_on_circuit": [
                {5: 30}, {5: 16, 7: 10, 6: 2, 3: 1, 4: 1},
                {3: 6, 5: 6, 7: 5, 2: 4, 4: 3, 0: 2, 1: 2, 6: 2}
            ],
    }

    def __init__(self):
        super().__init__()
        os.environ["TF_CPP_MIN_LOG_LEVEL"] = str(TF_LOG_LEVEL)
        import tensorflow as tf  # pylint: disable=E0401
        self.backend = tf
        self.name = "tensorflow"

        self.cpu_devices = tf.config.list_logical_devices("CPU")
        self.gpu_devices = tf.config.list_logical_devices("GPU")
        if self.gpu_devices: # pragma: no cover
            # CI does not use GPUs
            self.default_device = self.gpu_devices[0].name
        elif self.cpu_devices:
            self.default_device = self.cpu_devices[0].name
        else: # pragma: no cover
            # case not tested by GitHub workflows because it requires no device
            raise_error(RuntimeError, "Unable to find Tensorflow devices.")

        self.tensor_types = (self.np.ndarray, tf.Tensor, tf.Variable)
        self.native_types = (tf.Tensor, tf.Variable)
        self.Tensor = tf.Tensor
        self.random = tf.random
        self.newaxis = tf.newaxis
        self.sparse = tf.sparse
        from tensorflow.python.framework import errors_impl  # pylint: disable=E0611,E0401
        self.oom_error = errors_impl.ResourceExhaustedError
        self.optimization = Optimization()

        # seed to use in the measurement frequency custom op
        self._seed = None
        # seed can be modified using ``K.set_seed``
        self.supports_gradients = True

    def test_regressions(self, name):
        if "GPU" in self.default_device:  # pragma: no cover
            # Ci does not use GPUs
            return self.TEST_REGRESSIONS_GPU.get(name)
        else:
            return self.TEST_REGRESSIONS_CPU.get(name)

    def set_device(self, name):
        AbstractBackend.set_device(self, name)

    def set_threads(self, nthreads):
        log.warning("`set_threads` is not supported by the tensorflow "
                    "backend. Please use tensorflow's thread setters: "
                    "`tf.config.threading.set_inter_op_parallelism_threads` "
                    "or `tf.config.threading.set_intra_op_parallelism_threads` "
                    "to switch the number of threads.")
        AbstractBackend.set_threads(self, nthreads)

    def to_numpy(self, x):
        if isinstance(x, self.numeric_types):
            return x
        elif self.issparse(x):
            from scipy.sparse import coo_matrix
            idx = self.np.array(x.indices)
            values = self.np.array(x.values)
            shape = tuple(x.shape)
            return coo_matrix((values, (idx[:, 0], idx[:, 1])), shape=shape)
        return self.np.array(x, copy=False)

    def to_complex(self, re, img):
        return self.backend.complex(re, img)

    def cast(self, x, dtype='DTYPECPX'):
        if isinstance(dtype, str):
            dtype = self.dtypes(dtype)
        if isinstance(x, self.np.ndarray):
            dtypestr = dtype.__repr__().split(".")[1]
            x = x.astype(getattr(self.np, dtypestr))
        elif self.issparse(x):
            return x
        return self.backend.cast(x, dtype=dtype)

    def issparse(self, x):
        return isinstance(x, self.sparse.SparseTensor)

    def diag(self, x, dtype='DTYPECPX'):
        if isinstance(dtype, str):
            dtype = self.dtypes(dtype)
        return self.backend.cast(self.backend.linalg.diag(x), dtype=dtype)

    def concatenate(self, x, axis=None):
        return self.backend.concat(x, axis=axis)

    def copy(self, x):
        return x + self.backend.zeros_like(x)

    def range(self, start, finish, step, dtype=None):
        if isinstance(dtype, str):
            dtype = self.dtypes(dtype)
        return self.backend.range(start, finish, step, dtype=dtype)

    def real(self, x):
        return self.backend.math.real(x)

    def imag(self, x):
        return self.backend.math.imag(x)

    def conj(self, x):
        return self.backend.math.conj(x)

    def mod(self, x, y):
        return self.backend.math.mod(x, y)

    def right_shift(self, x, y):
        return self.backend.bitwise.right_shift(x, y)

    def pow(self, base, exponent):
        return self.backend.math.pow(base, exponent)

    def square(self, x):
        return self.backend.square(x)

    def sqrt(self, x):
        return self.backend.math.sqrt(x)

    def log(self, x):
        return self.backend.math.log(x)

    def trace(self, x):
        return self.backend.linalg.trace(x)

    def expm(self, x):
        return self.backend.linalg.expm(x)

    def sum(self, x, axis=None):
        return self.backend.reduce_sum(x, axis=axis)

    def dot(self, x, y):
        if self.issparse(x) or self.issparse(y):
            if self.issparse(x) and self.issparse(y):
                raise_error(NotImplementedError, "Tensorflow does not support "
                                                 "multiplication of two sparse "
                                                 "matrices.")
            return self.sparse.sparse_dense_matmul(x, y)
        return self.tensordot(x, y, axes=1)

    def outer(self, x, y):
        return self.tensordot(x, y, axes=0)

    def kron(self, x, y):
        dim = int(x.shape[0]) * int(y.shape[0])
        z = self.transpose(self.outer(x, y), axes=[0, 2, 1, 3])
        return self.reshape(z, (dim, dim))

    def inv(self, x):
        raise_error(NotImplementedError)

    def unique(self, x, return_counts=False):
        if return_counts:
            res, _, counts = self.backend.unique_with_counts(
                x, out_idx=self.dtypes('DTYPEINT'))
            return res, counts
        res, _  = self.backend.unique(x, out_idx=self.dtypes('DTYPEINT'))
        return res

    def gather(self, x, indices=None, condition=None, axis=0):
        if indices is not None:
            return self.backend.gather(x, indices, axis=axis)

        if condition is None:
            raise_error(ValueError, "Gather call is missing indices and "
                                    "condition.")
        indices = self.backend.where(condition)
        return self.backend.gather(x, indices, axis=axis)[:, 0]

    def gather_nd(self, x, indices):
        return self.backend.gather_nd(x, indices)

    def initial_state(self, nqubits, is_matrix=False): # pragma: no cover
        dim = 1 + is_matrix
        shape = dim * (2 ** nqubits,)
        idx = self.backend.constant([dim * [0]], dtype=self.dtypes('DTYPEINT'))
        state = self.backend.zeros(shape, dtype=self.dtypes('DTYPECPX'))
        update = self.backend.constant([1], dtype=self.dtypes('DTYPECPX'))
        state = self.backend.tensor_scatter_nd_update(state, idx, update)
        return state

    def random_uniform(self, shape, dtype='DTYPE'):
        return self.backend.random.uniform(shape, dtype=self.dtypes(dtype))

    def sample_shots(self, probs, nshots):
        from qibo.config import SHOT_BATCH_SIZE
        logits = self.log(probs)[self.newaxis]
        samples = [self.random.categorical(
            logits, SHOT_BATCH_SIZE, dtype=self.dtypes('DTYPEINT'))[0]
            for _ in range(nshots // SHOT_BATCH_SIZE)]
        samples.append(self.random.categorical(
                logits, nshots % SHOT_BATCH_SIZE,
                dtype=self.dtypes('DTYPEINT'))[0])
        return self.concatenate(samples, axis=0)

    def sample_frequencies(self, probs, nshots):
        logits = self.log(probs)[self.newaxis]
        samples = self.random.categorical(logits, nshots, dtype=self.dtypes('DTYPEINT'))[0]
        res, counts = self.unique(samples, return_counts=True)
        frequencies = self.zeros(int(probs.shape[0]), dtype=self.dtypes('DTYPEINT'))
        frequencies = self.backend.tensor_scatter_nd_add(frequencies, res[:, self.newaxis], counts)
        return frequencies

    def compile(self, func):
        return self.backend.function(func)

    def device(self, device_name):
        return self.backend.device(device_name)

    def on_cpu(self):
        return self.device(self.cpu_devices[0])

    def cpu_tensor(self, x, dtype=None):
        if dtype is None:
            dtype = x.dtype
        return self.backend.Variable(x, dtype=dtype)

    def cpu_cast(self, x, dtype='DTYPECPX'):
        dtype = self._dtypes.get(dtype)
        with self.on_cpu():
            return self.cast(x, dtype=dtype)

    def cpu_assign(self, state, i, piece):
        state.pieces[i].assign(piece)

    def executing_eagerly(self):
        return self.backend.executing_eagerly()

    def set_seed(self, seed):
        self._seed = seed
        self.backend.random.set_seed(seed)


import os
import types

import librosa
import numpy as np
import pytorch_lightning as pl
import torch
from torch.utils.data import DataLoader

import htsat_config
from cog import BasePredictor, Input, Path
from data_processor import MusdbDataset
from models.asp_model import AutoTaggingWarpper, SeparatorModel, ZeroShotASP
from models.htsat import HTSAT_Swin_Transformer
from sed_model import SEDWrapper
from utils import prepprocess_audio

def get_inference_configs():
    config = types.SimpleNamespace()
    config.ckpt_path = "pretrained/zeroshot_asp_full.ckpt"
    config.sed_ckpt_path = "pretrained/htsat_audioset_2048d.ckpt"
    config.wave_output_path = "predict_outputs"
    config.test_key = "query_name"
    config.test_type = "mix"
    config.loss_type = "mae"
    config.infer_type = "mean"
    config.sample_rate = 32000
    config.segment_frames = 200
    config.hop_samples = 320
    config.energy_thres = 0.1
    config.using_whiting = False
    config.latent_dim = 2048
    config.classes_num = 527
    config.overlap_rate = 0.5
    config.num_workers = 1

    return config

def load_models(config):
    sed_model = HTSAT_Swin_Transformer(
        spec_size=htsat_config.htsat_spec_size,
        patch_size=htsat_config.htsat_patch_size,
        in_chans=1,
        num_classes=htsat_config.classes_num,
        window_size=htsat_config.htsat_window_size,
        config=htsat_config,
        depths=htsat_config.htsat_depth,
        embed_dim=htsat_config.htsat_dim,
        patch_stride=htsat_config.htsat_stride,
        num_heads=htsat_config.htsat_num_head,
    )
    at_model = SEDWrapper(sed_model=sed_model, config=htsat_config, dataset=None)

    ckpt = torch.load(config.sed_ckpt_path, map_location="cpu")
    at_model.load_state_dict(ckpt["state_dict"])

    at_wrapper = AutoTaggingWarpper(
        at_model=at_model, config=config, target_keys=[config.test_key]
    )

    asp_model = ZeroShotASP(channels=1, config=config, at_model=at_model, dataset=None)
    ckpt = torch.load(config.ckpt_path, map_location="cpu")
    asp_model.load_state_dict(ckpt["state_dict"], strict=False)

    return at_wrapper, asp_model

def get_dataloader_from_sound_file(sound_file_path, config):
    signal, sampling_rate = librosa.load(str(sound_file_path), sr=None)
    signal = prepprocess_audio(
        signal[:, None], sampling_rate, config.sample_rate, config.test_type
    )
    signal = np.array([signal, signal]) # Duplicate signal for later use
    dataset = MusdbDataset(tracks=[signal])
    data_loader = DataLoader(dataset, num_workers=config.num_workers, batch_size=1, shuffle=False)
    return data_loader

class Predictor(BasePredictor):
    def setup(self):
        self.config = get_inference_configs()
        os.makedirs(self.config.wave_output_path, exist_ok=True)
        self.at_wrapper, self.asp_model = load_models(self.config)

    def predict(
        self,
        mix_file: Path = Input(description="Reference sound to extract source from"),
        query_file: Path = Input(description="Query sound to be searched and extracted from mix"),
    ) -> Path:
        ref_loader = get_dataloader_from_sound_file(str(mix_file), self.config)

        query_loader = get_dataloader_from_sound_file(str(query_file), self.config)

        trainer = pl.Trainer(gpus=1)
        trainer.test(self.at_wrapper, test_dataloaders=query_loader)
        avg_at = self.at_wrapper.avg_at

        exp_model = SeparatorModel(
            model=self.asp_model,
            config=self.config,
            target_keys=[self.config.test_key],
            avg_at=avg_at,
            using_wiener=False,
            calc_sdr=False,
            output_wav=True,
        )
        trainer.test(exp_model, test_dataloaders=ref_loader)

        prediction_path = os.path.join(
            self.config.wave_output_path, f"0_{self.config.test_key}_pred_(0.0).wav"
        )
        return prediction_path


# coding: utf-8
# Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department
# Distributed under the terms of "New BSD License", see the LICENSE file.

import unittest
import numpy as np
from pyiron_atomistics.atomistics.structure._visualize import _get_flattened_orientation

class TestAtoms(unittest.TestCase):
    @classmethod
    def tearDownClass(cls):
        pass

    @classmethod
    def setUpClass(cls):
        pass

    def test_get_flattened_orientation(self):
        R = np.random.random(9).reshape(-1, 3)
        R = np.array(_get_flattened_orientation(R, 1)).reshape(4, 4)
        self.assertAlmostEqual(np.linalg.det(R), 1)

if __name__ == "__main__":
    unittest.main()


#!/usr/bin/python
#coding: utf-8
import os
import math
import cv2
import numpy as np
import Func
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import platform
pltfm = platform.system()
if pltfm == 'Linux':
    from libsvm_linux import svmutil as svm
elif pltfm == 'Darwin':
    from libsvm_mac import svmutil as svm
else:
    raise "Unsupported Platform!"

class PornClassifier:
    def __init__(self):
        self.modelpath = "model.m"

    def classify(self, img):
        IHandler = Func.PornImageHandler()
        #img = cv2.imread(filename)
        num = 1
        VecList = []
        label = []
        #   将图片特征向量
        VecList.append(IHandler.GetFeature(img))
        label.append(1)
        num += 1
        if os.path.exists(self.modelpath):
            model = svm.svm_load_model(self.modelpath)
        else:
            self.train()
        p_labs, p_acc, p_vals = svm.svm_predict(label, VecList, model, '-b 1')
        print p_labs, p_acc, p_vals
        if p_labs[0] > 0.5:
            return True
        else:
            return False
    def __SubProc(self, Func, VecList, label, img, l, num, length):
        #   将图片特征向量
        VecList.append(Func.GetFeature(img, num))
        label.append(l)
        print "%.2f %% (%4d/%4d)"%(float(num) * 100 / length, num, length)

    def ExtractFeature(self, truepath, falsepath):
        num = 1
        VecList = []
        label = []
        self.truelist = self.__load_images(truepath)
        self.falselist = self.__load_images(falsepath)
        IHandler = Func.PornImageHandler()
        #   训练正样本
        for img in self.truelist:
            self.__SubProc(IHandler, VecList, label, img, 1, num, len(self.truelist)+len(self.falselist))
            num += 1
        #   训练负样本
        for img in self.falselist:
            self.__SubProc(IHandler, VecList, label, img, 0, num, len(self.truelist)+len(self.falselist))
            num += 1
        print "[*]  Created Process Pool!"
        print len(VecList) , " ", len(label)
        return label, VecList

    def __SaveAsMat(self, label, VecList, filename):
        with open(filename, 'w') as f:
            vstr = ''
            for i in range(len(VecList)):
                vstr += str(label[i])
                vstr += ' '
                for j in range(len(VecList[i])):
                    vstr += str(j+1) + ':' + str(VecList[i][j]) + ' '
                vstr += '\n'
            print vstr
            f.write(vstr)
        f.close()

    def train(self, label, VecList):
        #self.__SaveAsMat(label, VecList, "prob.mat")
        #model = svm.svm_train(label, VecList, '-s 0 -t 0 -c 15 -g 0.01 -b 1')
        model = svm.svm_train(label, VecList, '-s 1 -t 2 -c 2 -g 0.0001 -b 1 -h 0 ')
        svm.svm_save_model(self.modelpath, model)
        print "model trained..."

    def crossvalid(self, label, VecList):
        result = svm.svm_train(label, VecList, '-s 1 -t 2 -c 2 -g 0.0001 -b 1 -h 0 -v 5')
        print result

if __name__ == '__main__':
    '''
    Porn = PornClassifier("test/IsPorn", "test/NotPorn", "inter/")
    rootpath = "test/test"
    '''
    Porn = PornClassifier("data/IsPorn", "data/NotPorn", "inter/")
    #Porn.train()

    c = 0
    a = 0
    rootpath = "data/false"
    for f in os.listdir(rootpath):
        filepath = os.path.join(rootpath, f)
        if not os.path.isdir(filepath):
            print f
            if f != '.DS_Store':
                if Porn.classify(filepath):
                    c += 1
                a += 1
    print float(c) * 100 / a , "%"
    #Porn.classify("test.jpg")


import os
from copy import deepcopy

import numpy as np
import torch

from .nn_blocks import GaussianActor, DoubleQNet, make_feature_extractor_fn
from .noise import OUNoise

def soft_update_net(args, online_net, target_net):
    tau = args.tau
    with torch.no_grad():
        for online_x, target_x in zip(online_net.parameters(), target_net.parameters()):
            target_x.data.mul_(1 - tau)
            target_x.data.add_(tau * online_x.data)

class SACAgent(object):
    def __init__(self, args, env, device):
        self.device = device
        feature_extractor_fn = make_feature_extractor_fn(args, env)
        self.actor = GaussianActor(args, env.n_act, feature_extractor_fn).to(device)
        self.actor_optimizer = torch.optim.Adam(self.actor.parameters(), lr=args.lr)

        self.online_doubleQ = DoubleQNet(args, env.n_act, feature_extractor_fn).to(device)
        self.Q_optimizer = torch.optim.Adam(self.online_doubleQ.parameters(), lr=args.lr)

        self.target_doubleQ = deepcopy(self.online_doubleQ)
        for x in self.target_doubleQ.parameters():
            x.requires_grad = False

        if args.additional_OU_noise > 0:
            self.addional_noise = True
            self.online_noise_scale = args.additional_OU_noise
            self.noise_gen = OUNoise(env.n_act, np.random.randint(1e9))
        else:
            self.addional_noise = False

    @torch.no_grad()
    def act(self, obs, deterministic=False):
        obs = torch.tensor(obs, dtype=torch.float32, device=self.device).unsqueeze(0)
        action = self.actor(obs, deterministic).squeeze(0).cpu().numpy()
        if self.addional_noise:
            action += self.online_noise_scale * self.noise_gen()
            action = np.clip(action, -1, 1)
        return action

    def lr_decay(self, args, cur, total):
        for param_group in self.actor_optimizer.param_groups:
            param_group["lr"] = args.lr * (1 - cur / total)
        for param_group in self.Q_optimizer.param_groups:
            param_group["lr"] = args.lr * (1 - cur / total)

    def learn(self, args, buffer, T):
        stats = {}
        batch_size = args.batch_size

        idx = np.random.choice(len(buffer), batch_size, replace=True)
        data = buffer.get(idx, collect_next_obs=True)
        obs = torch.as_tensor(data["obs"]).to(self.device)
        action = torch.as_tensor(data["action"]).to(self.device)
        reward = torch.as_tensor(data["reward"]).to(self.device)
        done = torch.as_tensor(data["done"]).to(self.device)
        next_obs = torch.as_tensor(data["next_obs"]).to(self.device)

        Q1, Q2 = self.online_doubleQ(obs, action)
        with torch.no_grad():
            next_action, next_log_p = self.actor(next_obs, with_log_p=True)
            next_Q1, next_Q2 = self.target_doubleQ(next_obs, next_action)
            next_Q = torch.min(next_Q1, next_Q2)
            tar_Q = reward + args.gamma * (1 - done) * (next_Q - args.alpha * next_log_p)

        Q_loss = ((Q1 - tar_Q) ** 2).mean() + ((Q2 - tar_Q) ** 2).mean()
        self.Q_optimizer.zero_grad()
        Q_loss.backward()
        self.Q_optimizer.step()
        stats["Q1"] = Q1.mean().item()
        stats["Q2"] = Q2.mean().item()
        stats["Q_loss"] = Q_loss.item()

        for x in self.online_doubleQ.parameters():
            x.requires_grad = False

        r_action, log_p = self.actor(obs, with_log_p=True)
        r_Q1, r_Q2 = self.online_doubleQ(obs, r_action)
        actor_loss = (args.alpha * log_p - torch.min(r_Q1, r_Q2)).mean()
        self.actor_optimizer.zero_grad()
        actor_loss.backward()
        self.actor_optimizer.step()
        stats["actor_loss"] = actor_loss.item()

        for x in self.online_doubleQ.parameters():
            x.requires_grad = True
        soft_update_net(args, self.online_doubleQ, self.target_doubleQ)

        if args.wandb_show:
            from .logger import log
            log("train", T, stats)
        stats["T"] = T
        return stats

    def load(self, load_file):
        data = torch.load(load_file)
        self.actor.load_state_dict(data["actor"])
        self.online_doubleQ.load_state_dict(data["online_doubleQ"])
        self.target_doubleQ.load_state_dict(data["target_doubleQ"])
        self.actor_optimizer.load_state_dict(data["actor_optimizer"])
        self.Q_optimizer.load_state_dict(data["Q_optimizer"])

    def save(self, save_dir, file_name):
        data = {"actor": self.actor.state_dict(),
                "online_doubleQ": self.online_doubleQ.state_dict(),
                "target_doubleQ": self.target_doubleQ.state_dict(),
                "actor_optimizer": self.actor_optimizer.state_dict(),
                "Q_optimizer": self.Q_optimizer.state_dict()}
        torch.save(data, os.path.join(save_dir, file_name))


from pdb import set_trace as T
import abc

import numpy as np
from forge.blade.systems import experience, ai, combat

from forge.blade.lib.enums import Material

class Skills:
   def __init__(self, config):
      expCalc     = experience.ExperienceCalculator()
      self.skills = set()
      self.config = config

      #Combat skills
      self.constitution = Constitution(self.skills, expCalc, config)
      self.melee        = Melee(self.skills, expCalc, config)
      self.range        = Range(self.skills, expCalc, config)
      self.mage         = Mage(self.skills, expCalc, config)
      self.defense      = Defense(self.skills, expCalc, config)

      #Harvesting Skills
      self.fishing      = Fishing(self.skills, expCalc, config)
      self.hunting      = Hunting(self.skills, expCalc, config)
      self.mining       = Mining(self.skills, expCalc, config)

      #Processing Skills
      self.cooking      = Cooking(self.skills, expCalc, config)
      self.smithing     = Smithing(self.skills, expCalc, config)

   def packet(self):
      data = {}

      data['constitution'] = self.constitution.packet()
      data['melee']        = self.melee.packet()
      data['range']        = self.range.packet()
      data['mage']         = self.mage.packet()
      data['defense']      = self.defense.packet()
      data['fishing']      = self.fishing.packet()
      data['hunting']      = self.hunting.packet()
      data['cooking']      = self.cooking.packet()
      data['smithing']     = self.smithing.packet()
      data['level']        = combat.level(self)

      return data

   def update(self, ent, world, actions):
      for skill in self.skills:
         skill.update(ent, world)

   def applyDamage(self, dmg, style):
      scale = self.config.XPSCALE
      self.constitution.exp += scale * dmg * 2

      skill = self.__dict__[style]
      skill.exp += scale * dmg * 4

   def receiveDamage(self, dmg):
      scale = self.config.XPSCALE
      self.constitution.exp += scale * dmg * 2
      self.defense.exp      += scale * dmg * 4

class Skill:
   skillItems = abc.ABCMeta
   def __init__(self, skills, expCalc, config):
      self.expCalc = expCalc
      self.exp     = 0

      self.config  = config
      skills.add(self)

   def packet(self):
      data = {}

      data['exp']   = self.exp
      data['level'] = self.level

      return data

   def update(self, ent, world):
      pass

   @property
   def level(self):
      lvl = self.expCalc.levelAtExp(self.exp)
      assert lvl == int(lvl)
      return int(lvl)

class CombatSkill(Skill): pass

class Constitution(CombatSkill):
   def __init__(self, skills, expCalc, config):
      super().__init__(skills, expCalc, config)
      self.exp = self.expCalc.expAtLevel(config.HEALTH)

   def update(self, ent, world):
      health = ent.resources.health
      food   = ent.resources.food
      water  = ent.resources.water

      health.max = self.level

      #Heal if above half resources
      if food.val > food.max // 2 and water.val > water.max // 2:
         restore = np.floor(self.level * self.config.HEALTHRESTORE)
         restore = min(health.missing, restore)
         health.increment(restore)

      if food.val <= 0:
         health.decrement()
      if water.val <= 0:
         health.decrement()

class Melee(CombatSkill): pass
class Range(CombatSkill): pass
class Mage(CombatSkill): pass
class Defense(CombatSkill): pass

class NonCombatSkill(Skill):
   def success(self, levelReq):
      level = self.level
      if level < levelReq:
         return False
      chance = 0.5 + 0.05*(level - levelReq)
      if chance >= 1.0:
         return True
      return np.random.rand() < chance

   def attempt(self, inv, item):
      if (item.createSkill != self.__class__ or
            self.level < item.createLevel):
         return

      if item.recipe is not None:
         #Check that everything is available
         if not inv.satisfies(item.recipe): return
         inv.removeRecipe(item.recipe)

      if item.alwaysSucceeds or self.success(item.createLevel):
         inv.add(item, item.amtMade)
         self.exp += item.exp
         return True

class HarvestingSkill(NonCombatSkill):
   #Attempt each item from highest to lowest tier until success
   def harvest(self, inv):
      for e in self.skillItems:
         if self.attempt(inv, e):
            return

class Fishing(HarvestingSkill):
   def __init__(self, skills, expCalc, config):
      super().__init__(skills, expCalc, config)
      self.exp = self.expCalc.expAtLevel(config.RESOURCE)

   def update(self, ent, world):
      water     = ent.resources.water
      water.max = self.level
      water.decrement()

      if Material.WATER.value not in ai.adjacentMats(world.env, ent.base.pos):
         return

      restore = np.floor(self.level * self.config.RESOURCERESTORE)
      restore = min(water.missing, restore)
      water.increment(restore)

      scale = self.config.XPSCALE
      self.exp += scale * restore;

class Hunting(HarvestingSkill):
   def __init__(self, skills, expCalc, config):
      super().__init__(skills, expCalc, config)
      self.exp = self.expCalc.expAtLevel(config.RESOURCE)

   def update(self, ent, world):
      food     = ent.resources.food
      food.max = self.level
      food.decrement()

      r, c = ent.base.pos
      if (type(world.env.tiles[r, c].mat) not in [Material.FOREST.value] or
            not world.env.harvest(r, c)):
         return

      restore = np.floor(self.level * self.config.RESOURCERESTORE)
      restore = min(food.missing, restore)
      food.increment(restore)

      scale = self.config.XPSCALE
      self.exp += scale * restore;

class Mining(HarvestingSkill): pass

class ProcessingSkill(NonCombatSkill):
   def process(self, inv, item):
      self.attempt(inv, item)

class Cooking(ProcessingSkill): pass
class Smithing(ProcessingSkill): pass


# -*- coding: utf-8 -*-
"""
Created on Sat Feb  2 22:35:41 2019

@author: abhis
"""

import math

#model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['accuracy'])
#model.load_weights("bigger_model_chcekpoint_weights.h5")

#modification
import os
os.environ['KERAS_BACKEND'] = 'theano'
import time
import h5py
import json
import requests
import numpy as np
from keras.models import model_from_json
import PIL
from PIL import Image
from keras import backend as K
from keras.models import load_model

class Pred_tumor(object):

    def __init__(self):
        self.model=None
        self.url = 'http://127.0.0.1:8000/image/api'
        self.dirPath = '/Users/aakashvarma/Documents/Coding/Med-I/backend/uploads'

    def load_train_model(self):
        os.chdir('/Users/aakashvarma/Documents/Coding/Med-I/python_files')

        self.model=load_model('mri_model_weights.h5')
        print("Loaded model from disk")

    def getData(self, link):
        response = requests.get(link)
        self.data = response.json()
        return self.data

    def extractImage(self,path):
        imgData = self.getData(self.url)
        imgFilename = imgData["imagedata"]["filename"]

        os.chdir(path)
        try:
            #img = Image.open(imgFilename)

            #img=cv2.imread('028.png')
            #imfile=img
            imfile=Image.open(imgFilename)
            return imfile
        except:
            print("Unable to load image")

    def prediction(self):
        imfile = self.extractImage(self.dirPath)
        data = np.asarray(imfile.resize((128, 128), PIL.Image.ANTIALIAS))
        ynew = data.reshape(1,128,128,3)
        # Pred = model.predict(ynew)

        self.load_train_model()
        self.predc = self.model.predict_classes(ynew)

        if self.predc[0][0]==1:
            return "Tumor detected"
        else:
            return "Normal"


"""
ndt.py
File containing class definitions of NDT approximation for Consensus NDT SLAM
Also contains helper NDT functions
Author: Ashwin Kanhere
Date created: 15th April 2019
Last modified: 13th November 2019
"""
import numpy as np
import pptk
import utils
import transforms3d
from scipy.optimize import check_grad
from scipy.optimize import minimize
import odometry
import diagnostics
import integrity
import numpy_indexed
import itertools
import time
from scipy.interpolate import RegularGridInterpolator as RGI

"""
Importing base libraries
"""

class NDTCloudBase:
    """
    A class to store the sparse grid center points, means and covariances for grid points that are full.
    This class will be the de facto default for working with NDT point clouds.
    After refactoring for multiscale NDT with different methods, has become parent class for all NDT approximation methods
    """
    def __init__(self, xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size, cloud_type):
        """
        A method to initialize a member of the NDTCloud class. When initializing a member of the class, grid limits are
        given along with the grid sizes. Using these values a sparse grid is created and corresponding zero mean and
        covariance lists are also created.
        Since the first grid is highly dependent on the user it is for, there is no default initialization
        :param xlim: Limit of the grid along the x-axis
        :param ylim: Limit of the grid along the y-axis
        :param zlim: Limit of the grid along the z-axis
        :param input_horiz_grid_size: User entered
        :param input_vert_grid_size:
        """
        # Don't really need to store the limits of the space spanned by the NDT cloud. They will be needed to find if
        # the origin is a grid center though
        # When initializing the cloud, the origin is either going to be a grid center or not.
        self.horiz_grid_size = np.float(input_horiz_grid_size)
        self.vert_grid_size = np.float(input_vert_grid_size)
        # Create NDT map for reference grid
        # Initialize empty lists to store means and covariance matrices
        self.stats = {}  # Create an empty dictionary for mu and sigma corresponding to each voxel
        """
        Dictionary structure is {<key = center point>, {<key = 'mu'>, [mu value], <key='sigma'>, [sigma_value]
        , <key='no_points'>, int, <key='integrity'>, float}, ...}
        NOTE: key must be a tuple not a ndarray
        """
        self.local_to_global = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
        self.max_no_points = 0
        self.first_center = np.empty([1, 3])
        self.max_no_voxels = -1
        self.cloud_type = cloud_type

    def update_displacement(self, odometry_vector):
        """
        A function to update the displacement of the current local frame of reference from the global reference
        :param odometry_vector: A vector of [x, y, z, phi, theta, psi] measuring the  affine transformation of the
        current local frame of reference (LiDAR origin) to the global frame of reference (map origin)
        :return: None
        """
        # TODO:
        # Update translation vector
        self.local_to_global[:3] += odometry_vector[:3]
        # Update euler angle vector
        phi_local = np.deg2rad(self.local_to_global[3])
        theta_local = np.deg2rad(self.local_to_global[4])
        psi_local = np.deg2rad(self.local_to_global[5])
        R_local = transforms3d.euler.euler2mat(phi_local, theta_local, psi_local)
        phi_delta = np.deg2rad(odometry_vector[3])
        theta_delta = np.deg2rad(odometry_vector[4])
        psi_delta = np.deg2rad(odometry_vector[5])
        R_delta = transforms3d.euler.euler2mat(phi_delta, theta_delta, psi_delta, 'rxyz')
        R_new = np.matmul(R_delta, R_local)
        phi_rad, theta_rad, psi_rad = transforms3d.euler.mat2euler(R_new, 'rxyz')
        angle_new = np.rad2deg(np.array([phi_rad, theta_rad, psi_rad]))
        self.local_to_global[3:] = angle_new
        return None

    def find_voxel_center(self, ref_pointcloud, tol=1.0e-7):
        """
        A function to return grid indices for a given set of 3D points. The input may be a set of (x, y, z) Nx3 or
        (x, y, z, int) Nx4. This function is written to be agnostic to either form of the array
        This function also checks if points on a edge of the grid upto a tolerance level. If they are, it assigns them
        a value to ensure that no calculations involve that point
        :param ref_pointcloud: Nx3 or Nx4 numpy array for which binning is required
        :param tol: Tolerance for picking center. Default values used for overlapping
        :return: grid_centers: Matrix containing center coordinates corresponding to the given points Nx3
        """
        # Used an array over a tuple as there is a small possibility that the coordinates might change
        ref_points = np.array(ref_pointcloud[:, :3])  # to remove intensity if it has been passed accidentally
        grid_size = np.array([self.horiz_grid_size, self.horiz_grid_size, self.vert_grid_size])
        number_row = np.shape(self.first_center)[0]
        points_repeated = np.tile(ref_points, (number_row, 1))
        N = ref_points.shape[0]
        voxel_centers = np.zeros_like(points_repeated)
        for i in range(number_row):
            pre_voxel_number = (ref_points + self.first_center[i, :]) / grid_size
            pre_voxel_center = np.round(pre_voxel_number).astype(int) * grid_size
            first_grid_edge = self.first_center[i, :] - 0.5*np.array([self.horiz_grid_size, self.horiz_grid_size,
                                                                      self.vert_grid_size])
            line_check = np.abs(np.mod(ref_points, grid_size) + first_grid_edge)
            pre_voxel_center[line_check < tol] = np.nan
            pre_voxel_center[np.abs(line_check - 1) < tol] = np.nan
            voxel_centers[i*N:(i+1)*N, :] = np.multiply(np.sign(ref_points), np.abs(pre_voxel_center) -
                                                        np.sign(ref_points)*np.broadcast_to(self.first_center[i, :],
                                                                                (N, 3)))
        return points_repeated, voxel_centers

    def bin_in_voxels(self, points_to_bin):
        """
        Function to bin given points into voxels in a dictionary approach
        :param points_to_bin: The points that are to be binned into the voxel clusters indexed by the voxel center tuple
        :return: points_in_voxel: A dictionary indexed by the tuple of the center of the bin
        """
        points_repeated, voxel_centers = self.find_voxel_center(points_to_bin)
        dummy = numpy_indexed.group_by(voxel_centers, points_repeated)
        points_in_voxels = {}
        for i in range(np.shape(dummy[0])[0]):
            voxel_key = tuple(dummy[0][i])
            points_in_voxels[voxel_key] = dummy[1][i]
        return points_in_voxels

    def find_likelihood(self, transformed_pc):
        """
        Function to return likelihood for a given transformed point cloud w.r.t NDT point cloud
        Slightly different from reference papers in that 1/2det(sigma) is also included while calculating the likelihood
        The likelihood is increased if a corresponding Gaussian is found. If not, 0 is added
        :param transformed_pc: Point cloud that has been passed through a candidate affine transformation
        :return: likelihood: Scalar value representing the likelihood of the given
        """
        transformed_xyz = transformed_pc[:, :3]
        likelihood = 0
        points_in_voxels = self.bin_in_voxels(transformed_xyz)
        for key, val in points_in_voxels.items():
            if key in self.stats:
                sigma = self.stats[key]['sigma']
                sigma_inv = np.linalg.inv(sigma)
                diff = np.atleast_2d(val - self.stats[key]['mu'])
                likelihood += np.sum(np.exp(-0.5 * np.diag(np.matmul(np.matmul(diff, sigma_inv), diff.T))))
        return likelihood

    def display(self, plot_density=1.0):
        """
        Function to display the single NDT approximation
        :param fig: The figure object on which the probability function has to be plotted
        :param plot_density: The density of the plot (as a int scalar) the higher the density, the more points per grid
        :return: plot_points: The points sampled from the distribution that are to be plotted like any other PC
        """
        base_num_pts = 48  # 3 points per vertical and 4 per horizontal
        plot_points = np.empty([3, 0])
        plot_integrity = np.empty(0)
        for key, value in self.stats.items():
            sigma = self.stats[key]['sigma']
            mu = self.stats[key]['mu']
            measure_num = self.stats[key]['no_points']
            num_pts = np.int(3 * measure_num / self.max_no_points * plot_density * base_num_pts )
            if num_pts < 2:
                num_pts = 2
            if 'integrity' in self.stats[key]:
                voxel_score = self.stats[key]['integrity'] * np.ones(num_pts)
            else:
                voxel_score = np.ones(num_pts)
            center_pt = np.array(key)
            grid_lim = np.zeros([2, 3])
            grid_lim[0, 0] = center_pt[0] - self.horiz_grid_size
            grid_lim[1, 0] = center_pt[0] + self.horiz_grid_size
            grid_lim[0, 1] = center_pt[1] - self.horiz_grid_size
            grid_lim[1, 1] = center_pt[1] + self.horiz_grid_size
            grid_lim[0, 2] = center_pt[2] - self.vert_grid_size
            grid_lim[1, 2] = center_pt[2] + self.vert_grid_size
            grid_plot_points = np.random.multivariate_normal(mu, sigma, num_pts)
            # Ensure that all selected points are inside the grid
            for i in range(3):
                grid_plot_points[grid_plot_points[:, i] < grid_lim[0, i], i] = grid_lim[0, i]
                grid_plot_points[grid_plot_points[:, i] > grid_lim[1, i], i] = grid_lim[1, i]
            plot_points = np.hstack((plot_points, grid_plot_points.T))
            plot_integrity = np.append(plot_integrity, voxel_score)
        print('The maximum number of points per voxel is ', self.max_no_points)
        return plot_points.T, plot_integrity

    def update_stats(self, points_in_voxels):
        """
        Function to update the statistics of the NDT cloud given points and the center of the grid that they belong to
        :param points_in_voxels: A dictionary indexed by the center of the grid and containing corresponding values
        :return: None
        """
        for k, v in points_in_voxels.items():
            no_in_voxel = v.size/3  # to prevent a single row vector from being counted as 3
            if k in self.stats:
                # Use update methodology from 3D NDT Scan Matching Paper Eq 4 and 5
                m_old = self.stats[k]['no_points']*self.stats[k]['mu']  # row vector
                s_old = self.stats[k]['no_points']*self.stats[k]['sigma'] + \
                        np.matmul(np.reshape(self.stats[k]['mu'], [3, 1]), np.reshape(m_old, [1, 3]))
                m_new = m_old + np.sum(v, axis=0)
                s_new = s_old + np.matmul(v.T, v)
                self.stats[k]['no_points'] += no_in_voxel
                self.stats[k]['mu'] = m_new/self.stats[k]['no_points']
                self.stats[k]['sigma'] = (s_new - np.matmul(np.reshape(self.stats[k]['mu'], [3, 1]),
                                                            np.reshape(m_new, [1, 3])))/self.stats[k]['no_points']
                if self.stats[k]['no_points'] > self.max_no_points:
                    self.max_no_points = self.stats[k]['no_points']
            else:
                if no_in_voxel >= 5 and np.sum(np.isnan(np.array(k))) == 0:
                    self.stats[k] = {}  # Initialize empty dictionary before populating with values
                    self.stats[k]['mu'] = np.mean(v, axis=0)
                    self.stats[k]['sigma'] = np.cov(v, rowvar=False)
                    self.stats[k]['no_points'] = no_in_voxel
                    self.stats[k]['idx'] = self.pairing_cent2int(np.atleast_2d(np.array(k)))
                    self.max_no_voxels += 1
                    if self.stats[k]['no_points'] > self.max_no_points:
                        self.max_no_points = self.stats[k]['no_points']
        return None

    def eig_check(self):
        """
        Function to perform an eigenvalue based consistency check on the covariance matrix and adjust values accordingly
        Algorithm based on 3d NDT Scan Matching and Biber's NDT paper
        Using an SVD approach here. For covariance matrices, SVD and eigen decomposition should be the same. SVD
        implementations are often more stable
        :return: None
        """
        scale_param = 0.0001
        for key, val in self.stats.items():
            u, s_diag, v = np.linalg.svd(val['sigma'])  # np.svd naturally returns a diagonal
            s_diag[s_diag < scale_param*s_diag.max()] = scale_param*s_diag.max()
            val['sigma'] = np.matmul(np.matmul(u, np.diag(s_diag)), v)
        return None

    def update_cloud(self, pc_points):
        """
        Function to add points to current NDT approximation. This function adds both, new centers and points to
        existing grid points.
        :param pc_points: The points that are to be added to the NDT approximation. Might be Nx3 or Nx4.
        Function agnostic to that
        :return: None
        """
        # This function should be used to update an empty NDT cloud as well using the given points
        # Find grid centers corresponding to given points
        update_points = pc_points[:, :3]
        # Dictionary approach here as well
        points_in_voxels = self.bin_in_voxels(update_points)
        # Update the NDT approximation with these binned points
        self.update_stats(points_in_voxels)
        self.eig_check()
        return None

    def find_integrity(self, points):
        """
        Given a set of points and the underlying NDT Cloud, find the integrity of each voxel and the combined navigation
        solution
        :param points: Transformed points for which the integrity is required
        :return: Im: The integrity of the navigation solution obtained using the transformed points given
        :return: iscore: Voxel integrity score corresponding to the voxel center
        """
        test_xyz = points[:, :3]
        binned_points = self.bin_in_voxels(test_xyz)
        N = len(self.stats)
        iscore_array = np.zeros(N)
        loop_index = 0
        mu_points = np.zeros([N, 3])
        for key, val in self.stats.items():
            if key in binned_points:
                mu_points[loop_index, :] = val['mu']
                iscore_array[loop_index] = integrity.voxel_integrity(val, binned_points[key])
                self.stats[key]['integrity'] = iscore_array[loop_index]
                if np.isnan(iscore_array[loop_index]):
                    print('NaN detected!')
                loop_index += 1
            else:
                self.stats[key]['integrity'] = 0
        iscore_array[iscore_array == 0] = 1e-9
        Im, iscore_sum = integrity.solution_score(mu_points[:loop_index, :], iscore_array[:loop_index], points)
        # The loop index is added to ensure that only points that have a corresponding voxel are used for IDOP
        return Im, iscore_sum

    def optimization_integrity(self, points):
        """
        Given a set of points and the underlying NDT Cloud, find the integrity of each voxel and the combined navigation
        solution
        :param points: Transformed points for which the integrity is required
        :return: Im: The integrity of the navigation solution obtained using the transformed points given
        :return: iscore: Voxel integrity score corresponding to the voxel center
        """
        test_xyz = points[:, :3]
        binned_points = self.bin_in_voxels(test_xyz)
        N = len(self.stats)
        iscore_dict = {}
        rbar_dict = {}
        k_dict = {}
        loop_index = 0
        mu_points = np.zeros([N, 3])
        for key, val in self.stats.items():
            if key in binned_points:
                mu_points[loop_index, :] = val['mu']
                iscore_dict[key], rbar_dict[key], k_dict[key] = integrity.voxel_int_opt(val, binned_points[key])
                if np.isnan(iscore_dict[key]):
                    print('NaN detected!')
                loop_index += 1
        iscore_dict[iscore_dict == 0] = 1e-9
        # The loop index is added to ensure that only points that have a corresponding voxel are used for IDOP
        return iscore_dict, rbar_dict, k_dict

    def filter_voxels_integrity(self, integrity_limit=0.7):
        """
        Function to trim an ndt_cloud based on the integrity values of its voxels
        :param self: The NDT approximation to be trimmed
        :param integrity_limit: The minimum valid voxel integrity value
        :return: ndt_cloud: The same NDT approximation, but now with all voxels below an integrity limit removed
        """
        delete_index = []
        for key in self.stats.keys():
            if self.stats[key]['integrity'] < integrity_limit:
                delete_index.append(key)
        for del_key in delete_index:
            del self.stats[del_key]
        return None

    def pairing_cent2int(self, point_centers):
        """

        :param point_centers: Nx3 numpy array containing coordinates under consideration
        :return:
        """
        """
        1. Using voxel size, convert each center to a coordinate with only integer values
        2. Implement a standard pairing function to bind said coordinate to an index
        """
        assert(point_centers.shape[1] == 3)  # Checking that the matrix is all row vectors
        # Assign unique positive value to each integer
        pt_centers_temp = np.copy(point_centers)
        pt_centers_temp = (pt_centers_temp + self.first_center[0, :])/np.array([self.horiz_grid_size, self.horiz_grid_size, self.vert_grid_size])
        pt_centers_temp[pt_centers_temp > 0] = 2*pt_centers_temp[pt_centers_temp > 0]
        pt_centers_temp[pt_centers_temp < 0] = -2*pt_centers_temp[pt_centers_temp < 0] - 1
        x = np.atleast_2d(pt_centers_temp[:, 0])
        y = np.atleast_2d(pt_centers_temp[:, 1])
        z = np.atleast_2d(pt_centers_temp[:, 2])
        assert(np.min(x) > -1)
        assert(np.min(y) > -1)
        assert(np.min(z) > -1)
        pair_1 = np.atleast_2d(0.5*(x + y)*(x + y + 1) + y)
        int_pairing = np.atleast_2d(0.5*(pair_1 + z)*(pair_1 + z + 1) + z)
        int_pairing = np.reshape(int_pairing, [-1, 1])
        assert(int_pairing.shape == (point_centers.shape[0], 1))
        return int_pairing

    def pair_check(self):
        """
        Checking that the number of voxels and the number of unique index assignments is the same
        :return: None
        """
        voxels = []
        number = 0
        for key in self.stats:
            voxels.append(self.stats[key]['idx'][0][0])
            number += 1
        voxels = np.array(voxels)
        unique_voxels, unique_counts, case_counts = np.unique(voxels, return_index=True, return_counts=True)
        unique_no = np.size(unique_voxels)
        print('The number of voxels is ', number)
        print('The number of maximum voxels is ', self.max_no_voxels)
        print('The number of unique voxels is ', unique_no)
        assert(np.size(unique_voxels) == self.max_no_voxels)
        return None

    def prune_pc(self, pc):
        """
        Remove all points that don't overlap with NDT Cloud
        :param pc: Point cloud
        :return pruned_pc: Unique points that overlap with NDT Cloud
        """
        pruned_pc = np.zeros([0, 3])
        center_dict = self.bin_in_voxels(pc)
        keys = np.zeros([0, 3])
        binned_keys = np.zeros([0, 3])
        original_keys = np.zeros([0, 3])
        for key in self.stats:
            original_keys = np.vstack((original_keys, key))
        for key in center_dict:
            binned_keys = np.vstack((binned_keys, key))
            if key in self.stats:
                keys = np.vstack((keys, key))
                pruned_pc = np.vstack((pruned_pc, center_dict[key]))
        return np.unique(pruned_pc, axis=0)

class NDTCloudNoOverLap(NDTCloudBase):
    """
    Class inherited from NDTCloudBase parent for NDT approximation with no overlapping voxels
    """
    def __init__(self, xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size, cloud_type):
        super(NDTCloudNoOverLap, self).__init__(xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size
                                                , cloud_type)
        self.first_center = np.zeros([1, 3])
        first_center_x = np.mod(2 * xlim / self.horiz_grid_size + 1, 2) * self.horiz_grid_size / 2.0
        first_center_y = np.mod(2 * ylim / self.horiz_grid_size + 1, 2) * self.horiz_grid_size / 2.0
        first_center_z = np.mod(2 * zlim / self.vert_grid_size + 1, 2) * self.vert_grid_size / 2.0
        self.first_center[0, :] = np.array([first_center_x, first_center_y, first_center_z])

class NDTCloudOverLap(NDTCloudBase):
    """
    Class inherited from NDTCloudBase parent for NDT approximation with overlapping voxels. Overlap ensure smoother likelihood computation
    """
    def __init__(self, xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size, cloud_type):
        super(NDTCloudOverLap, self).__init__(xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size
                                              , cloud_type)
        self.first_center = np.empty([8, 3])
        for i in range(8):
            offset = np.array([np.mod(i, 2), np.mod(np.int(i / 2), 2), np.int(i / 4)])
            first_center_x = np.mod(2 * xlim / self.horiz_grid_size + offset[0] + 1, 2) * self.horiz_grid_size / 2.0
            first_center_y = np.mod(2 * ylim / self.horiz_grid_size + offset[1] + 1, 2) * self.horiz_grid_size / 2.0
            first_center_z = np.mod(2 * zlim / self.vert_grid_size + offset[2] + 1, 2) * self.vert_grid_size / 2.0
            self.first_center[i, :] = np.array([first_center_x, first_center_y, first_center_z])

class NDTCloudInterpolated(NDTCloudBase):
    """
    Class inherited from NDTCloudBase parent for NDT approximation with non-overlapping voxels with interpolated likelihood calculation.
    Method of objective, Jacobian and Hessian computations is different from base class.
    """
    def __init__(self, xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size, cloud_type):
        super(NDTCloudInterpolated, self).__init__(xlim, ylim, zlim, input_horiz_grid_size, input_vert_grid_size
                                                   , cloud_type)
        self.first_center = np.zeros([1, 3])
        first_center_x = np.mod(2 * xlim / self.horiz_grid_size + 1, 2) * self.horiz_grid_size / 2.0
        first_center_y = np.mod(2 * ylim / self.horiz_grid_size + 1, 2) * self.horiz_grid_size / 2.0
        first_center_z = np.mod(2 * zlim / self.vert_grid_size + 1, 2) * self.vert_grid_size / 2.0
        self.first_center[0, :] = np.array([first_center_x, first_center_y, first_center_z])

    def find_octant(self, transformed_xyz):
        """
        Find which octant of divided voxel point lies in. Used to find centers of neighbouring voxels
        :param transformed_xyz: PC after transformation
        :return octant: Octants for each point in the PC
        """
        _, point_centers = self.find_voxel_center(transformed_xyz)
        diff_sign = np.sign(transformed_xyz - point_centers)
        diff_sign[np.isnan(diff_sign)] = -1.0
        octant_index = np.zeros([2, 2, 2])
        octant_index[1, 1, 1] = 1
        octant_index[0, 1, 1] = 2
        octant_index[0, 0, 1] = 3
        octant_index[1, 0, 1] = 4
        octant_index[1, 1, 0] = 5
        octant_index[0, 1, 0] = 6
        octant_index[0, 0, 0] = 7
        octant_index[1, 0, 0] = 8
        diff_sign[diff_sign == -1] = 0
        diff_sign = diff_sign.astype(np.int, copy=False)
        octant = octant_index[diff_sign[:, 0], diff_sign[:, 1], diff_sign[:, 2]]
        return octant

    def find_neighbours(self, transformed_xyz, no_neighbours=8):
        """
        Return centers of voxels neighbouring points in given point cloud
        :param transformed_xyz: PC after transformation
        :param no_neighbours: Number of neighbours to find, 8 by default
        :return nearby: neighbours of each point in transformed_xyz
        """
        if no_neighbours == 8:
            octants = self.find_octant(transformed_xyz)
        else:
            octants = 0
            ValueError("Input number of neighbours not supported")
        diff_index = self.octant2diff()
        oct_index = octants.astype(np.int) - 1
        grid_disp = np.array([self.horiz_grid_size, self.horiz_grid_size, self.vert_grid_size])
        _, point_centers = self.find_voxel_center(transformed_xyz, tol=0.0)
        nearby = np.tile(point_centers, 8) + np.tile(grid_disp, no_neighbours)*diff_index[oct_index, :]
        assert(not np.any(np.isnan(nearby)))
        return nearby

    @staticmethod
    def octant2diff():
        """
        Map octant to coordinate changes in center of voxel
        return diff_index: Octant to difference mapping
        """
        # Defining a reverse octant index
        oct_rev = np.zeros([8, 2, 3])
        oct_rev[0, 1, :] = [1, 1, 1]
        oct_rev[1, 1, :] = [-1, 1, 1]
        oct_rev[2, 1, :] = [-1, -1, 1]
        oct_rev[3, 1, :] = [1, -1, 1]
        oct_rev[4, 1, :] = [1, 1, -1]
        oct_rev[5, 1, :] = [-1, 1, -1]
        oct_rev[6, 1, :] = [-1, -1, -1]
        oct_rev[7, 1, :] = [1, -1, -1]
        # Creating a displacement vector pertaining to each octant
        diff_index = np.zeros([8, 24])
        for vidx in range(8):
            counter = 0
            for xidx in range(2):
                for yidx in range(2):
                    for zidx in range(2):
                        diff_index[vidx, 3*counter:3*counter+3] = [oct_rev[vidx, xidx, 0], oct_rev[vidx, yidx, 1],
                                                                   oct_rev[vidx, zidx, 2]]
                        counter += 1
        return diff_index

    def find_interp_weights(self, pts, neighbours):
        """
        Function debugged by checking sum of all values and that the max and min do not leave the unit interval
        :param pts: Points for which interpolated weights are required
        :param neighbours: Neighbours of points for pts and NDT cloud
        :return weights: Weight of each neighbour for corresponding point
        """
        norm_neighbours = (neighbours - np.tile(neighbours[:, :3], 8)) / \
                          np.tile(np.array([self.horiz_grid_size, self.horiz_grid_size, self.vert_grid_size]), 8)
        norm_neighbours[norm_neighbours == -1] = 1
        diff_pts_mask = np.abs(np.tile(pts - neighbours[:, :3], 8))
        diff_pts_minus_mask = np.ones_like(diff_pts_mask) - diff_pts_mask
        weight_fact = diff_pts_mask*norm_neighbours + diff_pts_minus_mask*(1 - norm_neighbours)
        testing = np.hsplit(weight_fact, 8)
        weights = np.prod(testing, axis=2)
        return weights

    def find_likelihood(self, transformed_pc):
        """
        Likelihood calculated on a per point basis. First, calculate the 8 closest grid centers/ or means to a point
        Use expectation of point for each Gaussian as the value at the mean of that Gaussian.
        Vectorized implementation
        Finally, calculate an interpolation for the actual value of the mean with the associated weights
        :param transformed_pc: PC for which likelihood calculation is required
        :return likelihhod: Calculated interpolated likelihood
        """
        transformed_xyz = transformed_pc[:, :3]
        neighbours = self.find_neighbours(transformed_xyz)
        N = transformed_xyz.shape[0]
        vect_nearby_init = np.array(np.hsplit(neighbours, 8))
        vert_stack = np.reshape(vect_nearby_init, [N*8, 3])
        vert_idx = self.pairing_cent2int(vert_stack)
        vect_nearby_idx = np.reshape(vert_idx.T, [8, N]).T
        vect_mus = np.empty([8, N, 3, 1])
        vect_inv_sigmas = 10000*np.ones([8, N, 3, 3])
        for key in self.stats:
            indices = vect_nearby_idx == self.stats[key]['idx']
            mean = self.stats[key]['mu']
            inv_sigma = np.linalg.inv(self.stats[key]['sigma'])
            vect_mus[indices.T, :, 0] = mean
            vect_inv_sigmas[indices.T, :, :] = inv_sigma
        diff = np.empty_like(vect_mus)
        diff[:, :, :, 0] = -vect_mus[:, :, :, 0] + transformed_xyz[:N, :]
        diff_transpose = np.transpose(diff, [0, 1, 3, 2])
        lkds = np.exp(-0.5*np.matmul(np.matmul(diff_transpose, vect_inv_sigmas), diff))[:, :, 0, 0]
        weights = self.find_interp_weights(transformed_xyz, neighbours)[:, :N]
        wgt_lkd = weights*lkds
        likelihood = np.sum(wgt_lkd)
        return likelihood

def ndt_approx(ref_pointcloud, horiz_grid_size=0.5, vert_grid_size=0.5, type='overlapping'):
    """
    Function to create single NDT approximation for given offset and point cloud
    :param ref_pointcloud: [x, y, z, int] Nx4 or Nx3 numpy array of the reference point cloud
    :param horiz_grid_size: Float describing required horizontal grid size (in m)
    :param vert_grid_size: Float describing required vertical grid size. LiDAR span will be significantly shorter ...
    ... vertically with different concentrations, hence the different sizes. Same as horiz_grid_size by default
    :param type: Input to control overlap, and type of objective function used for calculation
    :return: ndt_cloud: NDT approximated cloud for the given point cloud and grid size
    """
    if ref_pointcloud.shape[1] == 4:
        ref_pointcloud = ref_pointcloud[:, :3]
    # Extract the size of the grid
    xlim = np.ceil(np.max(np.absolute(ref_pointcloud[:, 0]))) + 2*horiz_grid_size
    ylim = np.ceil(np.max(np.absolute(ref_pointcloud[:, 1]))) + 2*horiz_grid_size
    zlim = np.ceil(np.max(np.absolute(ref_pointcloud[:, 2]))) + 2*vert_grid_size
    # Create NDT map for reference grid
    if type == 'overlapping':
        ndt_cloud = NDTCloudOverLap(xlim, ylim, zlim, input_horiz_grid_size=horiz_grid_size,
                                    input_vert_grid_size=vert_grid_size, cloud_type=type)
    elif type == 'nooverlap':
        ndt_cloud = NDTCloudNoOverLap(xlim, ylim, zlim, input_horiz_grid_size=horiz_grid_size,
                                      input_vert_grid_size=vert_grid_size, cloud_type=type)
    elif type == 'interpolate':
        ndt_cloud = NDTCloudInterpolated(xlim, ylim, zlim, input_horiz_grid_size=horiz_grid_size,
                                         input_vert_grid_size=vert_grid_size, cloud_type=type)
    else:
        print('Wrong type of NDT Cloud specified in input. Defaulting to overlapping cloud')
        ndt_cloud = NDTCloudOverLap(xlim, ylim, zlim, input_horiz_grid_size=horiz_grid_size,
                                    input_vert_grid_size=vert_grid_size, cloud_type='overlapping')
    ndt_cloud.update_cloud(ref_pointcloud)
    return ndt_cloud

def display_ndt_cloud(ndt_cloud, point_density=0.1):
    """
    Function to display NDT approximation from a collection of NDT clouds
    :param ndt_cloud: NDT point cloud approximation
    :return: None
    """
    points_to_plot, pt_integrity = ndt_cloud.display(plot_density=point_density)
    pt_integrity = (np.max(pt_integrity) - pt_integrity)/(np.max(pt_integrity) - np.min(pt_integrity))
    ndt_viewer = pptk.viewer(points_to_plot, pt_integrity)
    ndt_viewer.color_map('hot')
    ndt_viewer.set(lookat=[0.0, 0.0, 0.0])
    return None

def find_pc_limits(pointcloud):
    """
    Function to find cartesian coordinate limits of given point cloud
    :param pointcloud: Given point cloud as an np.array of shape Nx3
    :return: xlim, ylim, zlim: Corresponding maximum absolute coordinate values
    """
    xlim = np.max(np.abs(pointcloud[:, 0]))
    ylim = np.max(np.abs(pointcloud[:, 1]))
    zlim = np.max(np.abs(pointcloud[:, 2]))
    return xlim, ylim, zlim

def multi_scale_ndt_odom(ref_pc, test_pc, scale_vect, filter_cv, test_mode, iters1, iters2):
    """
    find odometry mapping test PC to reference PC using multiscale NDT approximation
    :param ref_pc: Reference PC
    :param test_pc: Test PC
    :param scale_vect: Vector with NDT voxel lengths
    :param filter_cv: Voxel consensus metric below which voxels are removed
    :param test_mode: Type of NDT approximation, overlapping, nooverlap, interpolate
    :param iters1: Maximum number of iterations before removing low consensus voxels
    :param iters2: Maximum number of iterations after removing low consensus voxels
    """
    use_ref_pc = np.copy(ref_pc)
    use_test_pc = np.copy(test_pc)
    odom = np.zeros([np.size(scale_vect), 6])
    tic = time.time()
    for scale_idx, scale in enumerate(scale_vect):
        #print('DEBUG: Optimizing for voxel size ', scale)
        ref_ndt = ndt_approx(use_ref_pc, horiz_grid_size=scale, vert_grid_size=scale, type=test_mode)
        odom[scale_idx, :] = odometry.odometry(ref_ndt, use_test_pc, max_iter_pre=iters1, max_iter_post=iters2,
                                               integrity_filter=filter_cv)
        if len(ref_ndt.stats)!= 0:
            use_ref_pc = ref_ndt.prune_pc(ref_pc)
            #print('DEBUG: Size of ref_ndt is ', len(ref_ndt.stats))
            #print('DEBUG: Size of the pruned point cloud is ', np.shape(use_ref_pc)[0])
            use_test_pc = utils.transform_pc(odom[scale_idx, :], test_pc)
        else:
            break
    # Transform the test point cloud by the obtained odometry
    toc = time.time()
    return odom[scale_idx, :], toc - tic, odom


import numpy as np
import cv2
from PIL import Image
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from pandastable import Table, TableModel
from tensorflow.keras.preprocessing import image
import datetime
from threading import Thread
# from Spotipy import *
import time
import pandas as pd
face_cascade=cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
ds_factor=0.6

emotion_model = Sequential()
emotion_model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
emotion_model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))
emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))
emotion_model.add(Flatten())
emotion_model.add(Dense(1024, activation='relu'))
emotion_model.add(Dropout(0.5))
emotion_model.add(Dense(7, activation='softmax'))
emotion_model.load_weights('model.h5')

cv2.ocl.setUseOpenCL(False)

emotion_dict = {0:"Angry",1:"Disgusted",2:"Fearful",3:"Happy",4:"Neutral",5:"Sad",6:"Surprised"}
music_dist={0:"songs/angry.csv",1:"songs/disgusted.csv ",2:"songs/fearful.csv",3:"songs/happy.csv",4:"songs/neutral.csv",5:"songs/sad.csv",6:"songs/surprised.csv"}
global last_frame1
last_frame1 = np.zeros((480, 640, 3), dtype=np.uint8)
global cap1
show_text=[0]

''' Class for calculating FPS while streaming. Used this to check performance of using another thread for video streaming '''
class FPS:
	def __init__(self):
		# store the start time, end time, and total number of frames
		# that were examined between the start and end intervals
		self._start = None
		self._end = None
		self._numFrames = 0
	def start(self):
		# start the timer
		self._start = datetime.datetime.now()
		return self
	def stop(self):
		# stop the timer
		self._end = datetime.datetime.now()
	def update(self):
		# increment the total number of frames examined during the
		# start and end intervals
		self._numFrames += 1
	def elapsed(self):
		# return the total number of seconds between the start and
		# end interval
		return (self._end - self._start).total_seconds()
	def fps(self):
		# compute the (approximate) frames per second
		return self._numFrames / self.elapsed()

''' Class for using another thread for video streaming to boost performance '''
class WebcamVideoStream:

		def __init__(self, src=0):
			self.stream = cv2.VideoCapture(src,cv2.CAP_DSHOW)
			(self.grabbed, self.frame) = self.stream.read()
			self.stopped = False

		def start(self):
				# start the thread to read frames from the video stream
			Thread(target=self.update, args=()).start()
			return self

		def update(self):
			# keep looping infinitely until the thread is stopped
			while True:
				# if the thread indicator variable is set, stop the thread
				if self.stopped:
					return
				# otherwise, read the next frame from the stream
				(self.grabbed, self.frame) = self.stream.read()

		def read(self):
			# return the frame most recently read
			return self.frame
		def stop(self):
			# indicate that the thread should be stopped
			self.stopped = True

''' Class for reading video stream, generating prediction and recommendations '''
class VideoCamera(object):

	def get_frame(self):
		global cap1
		global df1
		cap1 = WebcamVideoStream(src=0).start()
		image = cap1.read()
		image=cv2.resize(image,(600,500))
		gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
		face_rects=face_cascade.detectMultiScale(gray,1.3,5)
		df1 = pd.read_csv(music_dist[show_text[0]])
		df1 = df1[['Name','Album','Artist']]
		df1 = df1.head(15)
		for (x,y,w,h) in face_rects:
			cv2.rectangle(image,(x,y-50),(x+w,y+h+10),(0,255,0),2)
			roi_gray_frame = gray[y:y + h, x:x + w]
			cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray_frame, (48, 48)), -1), 0)
			prediction = emotion_model.predict(cropped_img)

			maxindex = int(np.argmax(prediction))
			show_text[0] = maxindex
			#print("===========================================",music_dist[show_text[0]],"===========================================")
			#print(df1)
			cv2.putText(image, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
			df1 = music_rec()

		global last_frame1
		last_frame1 = image.copy()
		pic = cv2.cvtColor(last_frame1, cv2.COLOR_BGR2RGB)
		img = Image.fromarray(last_frame1)
		img = np.array(img)
		ret, jpeg = cv2.imencode('.jpg', img)
		return jpeg.tobytes(), df1

def music_rec():
	# print('---------------- Value ------------', music_dist[show_text[0]])
	df = pd.read_csv(music_dist[show_text[0]])
	df = df[['Name','Album','Artist']]
	df = df.head(15)
	return df


#!/usr/bin/env python
'''
mcu: Modeling and Crystallographic Utilities
Copyright (C) 2019 Hung Q. Pham. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Email: Hung Q. Pham <pqh3.14@gmail.com>
'''

import numpy as np
import re, argparse
from ..utils.misc import check_exist
from ..vasp import const
from ..cell import utils as cell_utils

lattice_MATCH = re.compile(r'''
[\w\W]*
 Lattice [ ]* vectors [ ]* \:
(?P<content>
  [\s\S]*?(?=\n.*?[ ] $|\n[ ]\n)  # match everything until next blank line or EOL
)
''', re.VERBOSE)

species_MATCH = re.compile(r'''
[ ]*
 Species [ ]* \:
(?P<content>
  [\s\S]*?(?=\n.*?[ ] $|\n[ ]\n)  # match everything until next blank line or EOL
)
''', re.VERBOSE)

kmesh_MATCH = re.compile(r'''
[\w\W]* k-point [ ]* grid [ ]* \: [ ]* (?P<kx>\S+) [ ]* (?P<ky>\S+) [ ]* (?P<kz>\S+)
''', re.VERBOSE)

koffset_MATCH = re.compile(r'''
[\w\W]* k-point [ ]* offset [ ]* \: [ ]* (?P<kx>\S+) [ ]* (?P<ky>\S+) [ ]* (?P<kz>\S+)
''', re.VERBOSE)

total_charge_MATCH = re.compile(r'''
[\w\W]*
Total [ ]* nuclear [ ]* charge    [ ]* \: [ ]* (?P<nuclear>\S+) [ ]* \n
Total [ ]* core [ ]* charge       [ ]* \: [ ]* (?P<core>\S+) [ ]* \n
Total [ ]* valence [ ]* charge    [ ]* \: [ ]* (?P<valence>\S+) [ ]* \n
Total [ ]* excess [ ]* charge     [ ]* \: [ ]* (?P<excess>\S+) [ ]* \n
Total [ ]* electronic [ ]* charge [ ]* \: [ ]* (?P<electronic>\S+)
''', re.VERBOSE)

states_charge_MATCH = re.compile(r'''
[\w\W]*
Number [ ]* of [ ]* empty [ ]* states  [ ]* \: [ ]* (?P<empty>\S+) [ ]* \n
Total [ ]* number [ ]* of [ ]* valence [ ]* states [ ]* \: [ ]* (?P<valence>\S+) [ ]* \n
Total [ ]* number [ ]* of [ ]* core [ ]* states [ ]* \: [ ]* (?P<core>\S+)
''', re.VERBOSE)

############ For SCF loops ##################
energies_MATCH = re.compile(r'''
[ ]*
 Energies [ ]* \:
(?P<content>
  [\s\S]*?(?=\n.*?[ ] $|\n[ ]\n)  # match everything until next blank line or EOL
)
''', re.VERBOSE)

charges_MATCH = re.compile(r'''
[ ]*
 Charges [ ]* \:
(?P<content>
  [\s\S]*?(?=\n.*?[ ] $|\n[ ]\n)  # match everything until next blank line or EOL
)
''', re.VERBOSE)

def read_info(filename):
    '''Read the INFO.OUT file'''
    assert check_exist(filename), 'Cannot find : ' + filename
    with open(filename, "r") as data_file:
        data = data_file.read()

        # spin
        spin = int('spin-polarised' in data)
        soc = 'spin-orbit coupling' in data
        if soc: spin = False

        # Cell information
        # row-vectors instead of column-vectors as in elk output
        tmp = lattice_MATCH.match(data)['content']
        lattice = np.float64(tmp.split()).reshape(3,3, order='F')

        # Get atom info
        species_blocks = []
        atom = []
        magnetic = []
        frac_coords = []
        for atoms in species_MATCH.finditer(data):
            atoms_data = atoms.groupdict()['content']
            tmp = atoms_data.split('\n')
            species = {}
            species['atom type'] = re.findall(r"\((?P<val>\S+)\)", tmp[0])[0]
            species['parameters'] = tmp[1].split(':')[1].strip()
            species['name'] = tmp[2].split(':')[1].strip()
            species['nuclear charge'] = float(tmp[3].split(':')[1])
            species['electronic charge'] = float(tmp[4].split(':')[1])
            species['atomic mass'] = float(tmp[5].split(':')[1])
            species['muffin-tin radius'] = float(tmp[6].split(':')[1])
            species['muffin-tin radial'] = int(tmp[7].split(':')[1])
            species['muffin-tin inner'] = int(tmp[8].split(':')[1])
            for atm in tmp[10:]:
                atom.append(species['atom type'])
                atm_split = atm.split()
                frac_coords.append(np.float64(atm_split[2:5]))
                magnetic.append(np.float64(atm_split[5:]))

            species_blocks.append(species)

        # Make the cell tuple
        atom_number = cell_utils.convert_atomtype(atom)
        cell = (lattice * const.AUTOA, frac_coords, atom_number)

        # kmesh
        tmp = kmesh_MATCH.match(data)
        kmesh = np.int64([tmp['kx'], tmp['ky'], tmp['kz']])
        tmp = koffset_MATCH.match(data)
        kmesh_shift = np.float64([tmp['kx'], tmp['ky'], tmp['kz']])

        # total charge
        charge_data = total_charge_MATCH.match(data)
        charge = {}
        charge['nuclear'] = float(charge_data['nuclear'])
        charge['core'] = float(charge_data['core'])
        charge['valence'] = float(charge_data['valence'])
        charge['excess'] = float(charge_data['excess'])
        charge['electronic'] = float(charge_data['electronic'])

        # Total states:
        states_data = states_charge_MATCH.match(data)
        states = {}
        states['empty'] = states_data['empty']
        states['core'] = states_data['core']
        states['valence'] = states_data['valence']

        # Collect the SCF cycles
        energies_blocks = []
        for cycle in energies_MATCH.finditer(data):
            energies_data = cycle.groupdict()['content']
            tmp = energies_data.split('\n')
            energies = {}
            energies['Fermi'] = float(tmp[1].split(':')[1])
            energies['sum of eigenvalues'] = float(tmp[2].split(':')[1])
            energies['electron kinetic'] = float(tmp[3].split(':')[1])
            energies['core electron kinetic'] = float(tmp[4].split(':')[1])
            energies['Coulomb'] = float(tmp[5].split(':')[1])
            energies['Coulomb potential'] = float(tmp[6].split(':')[1])
            energies['nuclear-nuclear'] = float(tmp[7].split(':')[1])
            energies['electron-nuclear'] = float(tmp[8].split(':')[1])
            energies['Hartree'] = float(tmp[9].split(':')[1])
            energies['Madelung'] = float(tmp[10].split(':')[1])
            energies['xc potential'] = float(tmp[11].split(':')[1])
            energies['exchange'] = float(tmp[12].split(':')[1])
            energies['correlation'] = float(tmp[13].split(':')[1])
            energies['electron entropic'] = float(tmp[14].split(':')[1])
            energies['total energy'] = float(tmp[15].split(':')[1])
            energies_blocks.append(energies)

        out = {}
        out['Species'] = species_blocks
        out['Energies'] = energies_blocks
        out['charge'] = charge
        out['states'] = states
        out['atom'] = atom
        out['cell'] = cell
        out['soc'] = soc
        out['spin'] = spin

        return out

def read_kpoints(filename):
    '''Read the KPOINTS.OUT file'''
    assert check_exist(filename), 'Cannot find : ' + filename
    with open(filename, "r") as data_file:
        data = data_file.read()
        tmp = np.float64(" ".join(data.split('\n')[1:-1]).split()).reshape(-1, 6)
        return tmp[:,1:4], tmp[:,4]           # kpts and kpts weight

eigval_MATCH = re.compile(r'''
[ ]*
 \([ ]* state, [ ]* eigenvalue [ ]* and [ ]* occupancy [ ]* below\)
(?P<content>
  [\s\S]*?(?=\n.*?[ ] $|\n[ ]\n)  # match everything until next blank line or EOL
)
''', re.VERBOSE)

def read_eigval(filename):
    '''Read the KPOINTS.OUT file
       Return:
        eigvals[spin, kpt, band, eigenvalues]
        occ[spin, kpt, band, occupancy]
    '''
    assert check_exist(filename), 'Cannot find : ' + filename
    with open(filename, "r") as data_file:
        data = data_file.read()

        eigvals = []
        occ = []
        for eigval in eigval_MATCH.finditer(data):
            eigval_data = eigval['content']
            tmp = np.float64(eigval_data.split()).reshape(-1, 3)
            eigvals.append(tmp[:,1])
            occ.append(tmp[:,2])

        eigvals = np.asarray(eigvals)
        nkpts = eigvals.shape[0]
        nband = eigvals.shape[1]
        occ = np.asarray(occ)

        # Check if this is a spin-polarized calculation
        if (occ[0] <= 1.0).any() and abs((-occ[0]).argsort() - np.arange(occ[0].shape[0])).sum() > 1e-3:
            assert np.mod(nband,2) == 0, "This is not a spin-polarised calculation"
            nband = nband//2

        eigvals = eigvals.reshape(nkpts, nband, -1).transpose(2, 0, 1)
        occ = occ.reshape(nkpts, nband, -1).transpose(2, 0, 1)
        return eigvals, occ

############ Read BAND***.OUT - begin ##################
def read_bandlines(filename):
    '''Read the BANDLINES.OUT file
    '''
    assert check_exist(filename), 'Cannot find : ' + filename
    with open(filename, "r") as data_file:
        data = np.float64(data_file.read().split()).reshape(-1,2)
        nkpoint = data.shape[0] // 2
        return data[2*np.arange(nkpoint), 0] / const.AUTOA

def read_band(filename, spin_polarized=False):
    '''Read BAND.OUT or BAND_Sss_Aaaaa.OUT

       Depends on the tasks, BAND.OUT or BAND_Sss_Aaaaa.OUT contains different projection
       For tasks 20:    kpt  |  e (a.u.)
       For tasks 21:    kpt  |  e (a.u.)  |  Total  |   s   |   p   |   d   |   f   |
       For tasks 22:    kpt  |  e (a.u.)  |   s     |  p(-1,0,+1)  |  d(-2,-1,0,+1,+2)  |  f(-3,-2,-1,0,+1,+2,+3)
       For tasks 23:    kpt  |  e (a.u.)  |   up    |  down |

       Return:
                bands[spin, kpt, band-th, projected contribution]
    '''
    assert check_exist(filename), 'Cannot find : ' + filename
    with open(filename, 'r') as data_file:
        data = data_file.read()
        tmp = data.split('\n \n')[:-1]

        # Figure out how many kpt and how many column
        nband = len(tmp)
        tmp2 = tmp[0].split('\n')
        nkpts = len(tmp2)
        ncol = len(tmp2[0].split())
        bands = []
        for i, band in enumerate(tmp):
            formatted_band = np.float64(band.split()).reshape(-1, ncol)
            if i == 0: proj_kpath = formatted_band[:,0] / const.AUTOA           # in Angstrom-1
            bands.append(formatted_band[:,1:])

        if spin_polarized:
            assert np.mod(nband,2) == 0, "This is not a spin-polarised calculation"
            nband = nband//2

        bands = np.asarray(bands).reshape(-1, nband, nkpts, ncol - 1).transpose(0, 2, 1, 3) * const.AUTOEV
        return proj_kpath, bands

def read_plot1d(filename):
    '''Read the plot1d of elk.in'''

    with open(filename, 'r') as data_file:
        data = data_file.read()
        assert 'plot1d' in data, "plot1d block cannot be found in the elk.in"
        tmp_with_comments = data.split('\n')
        tmp = [item for item in tmp_with_comments if not '!' in item]   # remove comments
        for i, item in enumerate(tmp):
            if 'plot1d' in item:
                where_plot1d = i
                break

        nkpoint, npts = np.int64(tmp[where_plot1d + 1].split()[:2])
        sym_kvecs = np.float64([tmp[i].split()[:3] for i in range(where_plot1d + 2, where_plot1d + nkpoint + 2)])

        return sym_kvecs, npts

############ Read DOS - begin ##################
def read_dos(filename, spin_polarized=False):
    '''Read TDOS.OUT, IDOS.OUT, PDOS_Sss_Aaaaa.OUT

       For PDOS_Sss_Aaaaa.OUT:
       e (a.u.)  |   s     |  p(-1,0,+1)  |  d(-2,-1,0,+1,+2)  |  f(-3,-2,-1,0,+1,+2,+3)
       Return:
                dos[spin, e, dos]
    '''
    assert check_exist(filename), 'Cannot find : ' + filename
    with open(filename, 'r') as data_file:
        data = data_file.read()
        tmp = data.split('\n \n')[:-1]

        # Figure out how many kpt and how many column
        ndos = len(tmp)
        nepsilon = len(tmp[0].split('\n'))
        dos = []
        for i, block in enumerate(tmp):
            formatted_dos = np.float64(block.split()).reshape(nepsilon, 2)
            if i == 0: epsilon = formatted_dos[:,0] * const.AUTOEV          # in eV
            dos.append(formatted_dos[:,1])

        if spin_polarized:
            assert np.mod(ndos,2) == 0, "This is not a spin-polarised calculation"
            ndos = ndos//2

        dos = np.asarray(dos).reshape(-1, ndos, nepsilon).transpose(0, 2, 1)
        return epsilon, dos


import mlprocessors as mlpr
import os
import time
import numpy as np
from os.path import join
from subprocess import Popen, PIPE
import shlex
import random
import string
import shutil
from spikeforest import mdaio
import spikeextractors as se
from spikeforest import SFMdaRecordingExtractor, SFMdaSortingExtractor
import sys
import shlex
import traceback
from .install_kilosort import install_kilosort

class KiloSort(mlpr.Processor):
    """
    Kilosort wrapper for SpikeForest framework
      written by J. James Jun, May 21, 2019

    [Prerequisite]
    1. MATLAB (Tested on R2018b)
    2. CUDA Toolkit v9.1 (module load cuda/9.1.85)
    3. GCC 6.4.0 (module load gcc/6.4.0)

    [Optional: Installation instruction in SpikeForest environment]
    1. Run `git clone https://github.com/cortex-lab/KiloSort.git`
    3. In Matlab, run `CUDA/mexGPUall` to compile all CUDA codes
    4. Add `KILOSORT_PATH_DEV=...` in your .bashrc file.
    """

    NAME = 'KiloSort'
    VERSION = '0.2.2'  # wrapper VERSION
    ADDITIONAL_FILES = ['*.m']
    ENVIRONMENT_VARIABLES = [
        'NUM_WORKERS', 'MKL_NUM_THREADS', 'NUMEXPR_NUM_THREADS', 'OMP_NUM_THREADS']
    CONTAINER = None
    LOCAL_MODULES = ['../../spikeforest']

    recording_dir = mlpr.Input('Directory of recording', directory=True)
    channels = mlpr.IntegerListParameter(
        description='List of channels to use.', optional=True, default=[])
    firings_out = mlpr.Output('Output firings file')

    detect_sign = mlpr.IntegerParameter(optional=True, default=-1,
                                        description='Use -1 or 1, depending on the sign of the spikes in the recording')
    adjacency_radius = mlpr.FloatParameter(optional=True, default=-1,
                                           description='Currently unused')
    detect_threshold = mlpr.FloatParameter(
        optional=True, default=3, description='')
    # prm_template_name=mlpr.StringParameter(optional=False,description='TODO')
    freq_min = mlpr.FloatParameter(
        optional=True, default=300, description='Use 0 for no bandpass filtering')
    freq_max = mlpr.FloatParameter(
        optional=True, default=6000, description='Use 0 for no bandpass filtering')
    merge_thresh = mlpr.FloatParameter(
        optional=True, default=0.98, description='TODO')
    pc_per_chan = mlpr.IntegerParameter(
        optional=True, default=3, description='TODO')

    @staticmethod
    def install():
        print('Auto-installing kilosort.')
        return install_kilosort(
            repo='https://github.com/cortex-lab/KiloSort.git',
            commit='3f33771f8fdf8c3846a7f8a75cc8c318b44ed48c'
        )

    def run(self):
        keep_temp_files = False
        code = ''.join(random.choice(string.ascii_uppercase)
                       for x in range(10))
        tmpdir = os.environ.get('TEMPDIR', '/tmp') + '/kilosort-tmp-' + code

        try:
            recording = SFMdaRecordingExtractor(self.recording_dir)
            if len(self.channels) > 0:
                recording = se.SubRecordingExtractor(
                    parent_recording=recording, channel_ids=self.channels)
            if not os.path.exists(tmpdir):
                os.mkdir(tmpdir)
            sorting = kilosort_helper(
                recording=recording,
                tmpdir=tmpdir,
                detect_sign=self.detect_sign,
                adjacency_radius=self.adjacency_radius,
                detect_threshold=self.detect_threshold,
                merge_thresh=self.merge_thresh,
                freq_min=self.freq_min,
                freq_max=self.freq_max,
                pc_per_chan=self.pc_per_chan
            )
            SFMdaSortingExtractor.write_sorting(
                sorting=sorting, save_path=self.firings_out)
        except:
            if os.path.exists(tmpdir):
                if not keep_temp_files:
                    shutil.rmtree(tmpdir)
            raise
        if not getattr(self, '_keep_temp_files', False):
            shutil.rmtree(tmpdir)

def kilosort_helper(*,
                    recording,  # Recording object
                    tmpdir,  # Temporary working directory
                    detect_sign=-1,  # Polarity of the spikes, -1, 0, or 1
                    adjacency_radius=-1,  # Channel neighborhood adjacency radius corresponding to geom file
                    detect_threshold=5,  # Threshold for detection
                    merge_thresh=.98,  # Cluster merging threhold 0..1
                    freq_min=300,  # Lower frequency limit for band-pass filter
                    freq_max=6000,  # Upper frequency limit for band-pass filter
                    pc_per_chan=3,  # Number of pc per channel
                    ):
    kilosort_path = os.environ.get('KILOSORT_PATH_DEV', None)
    if kilosort_path:
        print('Using kilosort from KILOSORT_PATH_DEV directory: {}'.format(kilosort_path))
    else:
        try:
            kilosort_path = KiloSort.install()
        except:
            traceback.print_exc()
            raise Exception('Problem installing kilosort. You can set the KILOSORT_PATH_DEV to force to use a particular path.')
    print('Using kilosort from: {}'.format(kilosort_path))

    source_dir = os.path.dirname(os.path.realpath(__file__))

    dataset_dir = tmpdir + '/kilosort_dataset'
    # Generate three files in the dataset directory: raw.mda, geom.csv, params.json
    SFMdaRecordingExtractor.write_recording(
        recording=recording, save_path=dataset_dir)

    samplerate = recording.get_sampling_frequency()

    print('Reading timeseries header...')
    HH = mdaio.readmda_header(dataset_dir + '/raw.mda')
    num_channels = HH.dims[0]
    num_timepoints = HH.dims[1]
    duration_minutes = num_timepoints / samplerate / 60
    print('Num. channels = {}, Num. timepoints = {}, duration = {} minutes'.format(
        num_channels, num_timepoints, duration_minutes))

    print('Creating argfile.txt file...')
    txt = ''
    txt += 'samplerate={}\n'.format(samplerate)
    txt += 'detect_sign={}\n'.format(detect_sign)
    txt += 'adjacency_radius={}\n'.format(adjacency_radius)
    txt += 'detect_threshold={}\n'.format(detect_threshold)
    txt += 'merge_thresh={}\n'.format(merge_thresh)
    txt += 'freq_min={}\n'.format(freq_min)
    txt += 'freq_max={}\n'.format(freq_max)
    txt += 'pc_per_chan={}\n'.format(pc_per_chan)
    _write_text_file(dataset_dir + '/argfile.txt', txt)

    print('Running kilosort in {tmpdir}...'.format(tmpdir=tmpdir))
    cmd = '''
        addpath('{source_dir}');
        addpath('{source_dir}/mdaio')
        try
            p_kilosort('{ksort}', '{tmpdir}', '{raw}', '{geom}', '{firings}', '{arg}');
        catch
            quit(1);
        end
        quit(0);
        '''
    cmd = cmd.format(source_dir=source_dir, ksort=kilosort_path,
                     tmpdir=tmpdir, raw=dataset_dir + '/raw.mda', geom=dataset_dir + '/geom.csv',
                     firings=tmpdir + '/firings.mda', arg=dataset_dir + '/argfile.txt')
    matlab_cmd = mlpr.ShellScript(cmd, script_path=tmpdir + '/run_kilosort.m', keep_temp_files=True)
    matlab_cmd.write()
    shell_cmd = '''
        #!/bin/bash
        cd {tmpdir}
        echo '=====================' `date` '====================='
        matlab -nosplash -nodisplay -r run_kilosort
    '''.format(tmpdir=tmpdir)
    shell_cmd = mlpr.ShellScript(shell_cmd, script_path=tmpdir + '/run_kilosort.sh', keep_temp_files=True)
    shell_cmd.write(tmpdir + '/run_kilosort.sh')
    shell_cmd.start()
    retcode = shell_cmd.wait()

    if retcode != 0:
        raise Exception('kilosort returned a non-zero exit code')

    # parse output
    result_fname = tmpdir + '/firings.mda'
    if not os.path.exists(result_fname):
        raise Exception('Result file does not exist: ' + result_fname)

    firings = mdaio.readmda(result_fname)
    sorting = se.NumpySortingExtractor()
    sorting.set_times_labels(firings[1, :], firings[2, :])
    return sorting

def _read_text_file(fname):
    with open(fname) as f:
        return f.read()

def _write_text_file(fname, str):
    with open(fname, 'w') as f:
        f.write(str)