import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread
from skimage.transform import resize, rotate
from glob import glob
from tqdm import tqdm
from sklearn.model_selection import train_test_split
from sklearn.cluster import KMeans

# function to load training data from file path
def load_train(train_path, size=None, return_mask_report=True):
    images      = []
    masks       = []               # stores masks by adding them
    masks_obj   = []               # stores masks as is, donot add
    no_of_masks = []
    for path in tqdm(glob(train_path+"/*"),desc="loading training images"):
        # loading images
        path_i = glob(path + '/images/*.png')
        assert len(path_i) == 1
        img = imread(path_i[0])[:,:,:3]/255
        if size is not None:
            img = resize(img,size,order=3,mode="constant",preserve_range=True,anti_aliasing=False)
        images.append(img)
        # loading masks
        path_m = glob(path + '/masks/*.png')
        mask = []
        for p in path_m:
            img = imread(p)/255
            if size is not None:
                img = resize(img,size,order=0,mode="constant",preserve_range=True,anti_aliasing=False)
            mask.append(img)
        no_of_masks.append(len(mask))
        masks_obj.append(np.array(mask))
        mask = np.sum(mask, axis=0)
        mask = np.expand_dims(mask, axis=-1)
        masks.append(mask)
    # removing outliers identified in data exploration notebook
    del_idx = [332, 36] # Also 36 because no such image is present in Test Set.
    for idx in del_idx:
        del images[idx]
        del masks[idx]
        del masks_obj[idx]
    # converting to numpy array if all images have same sizes
    if size is not None:
        masks  = np.array(masks)
        images = np.array(images)

    if return_mask_report:
        return images, masks,masks_obj, np.array(no_of_masks)
    else:
        return images, masks,masks_obj

# a function to load test data
def load_test(test_path, return_testid=True):
    Test_Images = []
    Test_Id = []
    for path in tqdm(glob(test_path)):
        image_path = glob(path + '/images/*.png')
        test_id = glob(path + '/images/*.png')[0].split('/')[-1][:-4]
        assert len(image_path) == 1
        Test_Images.append(imread(image_path[0])[:,:,:3])
        Test_Id.append(test_id)
    if return_testid:
        return Test_Images, Test_Id
    else:
        return Test_Images

# function to generate augmented images given a batch of images and masks
def augmenter(images, masks, fliplr, flipud, rot, rot_mode, rot90):
    '''
    rot   :  does small angular rotations but keeps the dimensions same.
    rot90 :  rotates image by multiples of 90 degree and changes the dimensions
    '''
    aug_images = []
    aug_masks  =   []
    for image, mask in zip(images, masks):
        aug_img = image
        aug_mask = mask
        if fliplr: # randomly fliplr
            if np.random.uniform(low=0, high=1) > 0.5:
                aug_img = np.fliplr(aug_img)
                aug_mask = np.fliplr(aug_mask)
        if flipud: # randomly flipud
            if np.random.uniform(low=0, high=1) > 0.5:
                aug_img = np.flipud(aug_img)
                aug_mask = np.flipud(aug_mask)
        if rot90: # randomly rotate 90 degrees
            if np.random.uniform(low=0, high=1) > 0.5:
                k = np.random.randint(low=0, high=4)
                aug_img = np.rot90(aug_img, k = k, axes=(0,1))
                aug_mask = np.rot90(aug_mask, k = k, axes=(0,1))
        if rot != None: # randomly rotate if True
            if np.random.uniform(low=0, high=1) > 0.5:
                angle = np.random.uniform(low=0, high = rot)
                aug_img = rotate(aug_img, angle, mode = rot_mode, preserve_range=True)
                aug_mask = rotate(aug_mask, angle, mode = rot_mode, preserve_range=True)
        aug_images.append(aug_img)
        aug_masks.append(aug_mask)
    return np.array(aug_images), np.array(aug_masks)

# perform k-means segmentation on images
def kmeans_segmentor(images, n_clusters, return_np = True, n_jobs = -1, reduce_size = None, ):
    if reduce_size is not None:
        s = images.shape[1] # orig size
        images = np.array([resize(img,(reduce_size[0],reduce_size[1],3),mode="constant",preserve_range=True,anti_aliasing=True) for img in images])
    Cluster = []
    for image in tqdm(images, desc="generating cluster maps"):
        cluster = []
        for n in n_clusters:
            red, green, blue = image[:,:,0], image[:,:,1],image[:,:,2]
            original_shape = red.shape # so we can reshape the labels later
            samples = np.column_stack([red.flatten(), green.flatten(), blue.flatten()])
            clf = KMeans(n_clusters=n, n_jobs = n_jobs)
            labels = clf.fit_predict(samples).reshape(original_shape)
            values, counts = np.unique(labels, return_counts =True)

            argsort = counts.argsort()
            argsort = np.flip(argsort, axis=0)
            values_sorted = values[argsort]
            final_labels = np.zeros(labels.shape)
            i = 0
            for value in values_sorted:
                final_labels[labels==value] = i
                i = i+1
            final_labels = final_labels / final_labels.max() # new line added
            cluster.append(final_labels)
        cluster = np.array(cluster).transpose([1,2,0])
#        cluster = np.expand_dims(cluster, axis=-1)
        Cluster.append(cluster)

    if reduce_size is not None:
        Cluster = [resize(c, (s,s), mode="constant",order=0,anti_aliasing=False,preserve_range=True) for c in Cluster]
    if return_np:
        return np.array(Cluster)
    else:
        return Cluster

class DataLoader():
    '''
    A class to load images and masks for train and test folders. Capable of
    generating (augmented) batches for training.
    '''
    def __init__(self, train_folder, test_folder, size=None):
        self.train_folder  = train_folder
        self.test_folder   = test_folder
        self.size          = size
        self.batch_index   = 0
        self.kmeans        = False

    def load_training(self, val_size=0.3):
        '''
        A function to load training data and split into train and test set.
        To limit memory overhead during train/val splitting, data is loaded
        once, and kept as is; train/val indices are generated.
        '''
        # loading entire train set
        self.images, self.masks, self.masks_obj, self.n_masks = load_train(self.train_folder,size=self.size,return_mask_report=True)
        assert len(self.images) == len(self.masks) == len(self.masks_obj)

        # splitting training data into training and validation
        indices = np.arange(0, len(self.images))
        self.idx_train, self.idx_val = train_test_split(indices,test_size=val_size,random_state=42)
        self.n_train = len(self.idx_train)
        self.n_val   = len(self.idx_val)

    def kmeans_cluster(self, n_clusters=[2,3,5,7], data="train",reduce_size=None):
        '''
        a function to generate cluster maps using k-means.
        '''
        self.kmeans = True
        if data=="train":
            self.cluster_maps = kmeans_segmentor(self.images, n_clusters, reduce_size=reduce_size)
        if data=="test":
            self.cluster_maps_test = kmeans_segmentor(self.test_images, n_clusters, reduce_size=reduce_size)

    def load_testing(self):
        '''
        a function to load test data
        '''
        self.test_images, self.test_ids = load_test(self.test_folder, return_testid=True)
        assert len(self.test_images) == len(self.test_ids)
        self.n_test = len(self.test_images)

    def set_augmentor(self,fliplr=True,flipud=True,rot = 3,rot_mode='edge',rot90=True):
        '''
        set augmentor parameters
        '''
        self.fliplr   = fliplr
        self.flipud   = flipud
        self.rot      = rot
        self.rot_mode = rot_mode
        self.rot90    = rot90

    def reset_batch_iterator(self):
        '''
        set internal batch iterator to zero
        '''
        self.batch_index = 0

    def get_batch_train(self, batch_size, augment=True):
        '''
        a function to get batches from training data. Batches will be
        augmented if set to True.
        '''
        start=self.batch_index; end=start+batch_size
        self.batch_index = end
        if end > self.n_train:
            end = self.n_train
            self.batch_index = 0
        if start == end:
            start = 0; end = start + batch_size
            self.batch_index = end
        batch_images       = self.images[self.idx_train][start:end]
        batch_masks        = self.masks[self.idx_train][start:end]
        if self.kmeans:
            batch_cluster_maps = self.cluster_maps[self.idx_train][start:end]
            batch_images       = np.concatenate([batch_images, batch_cluster_maps],axis=-1)
        if augment:
            batch_images, batch_masks = augmenter(batch_images, batch_masks,
                                                  self.fliplr,self.flipud,
                                                  self.rot,self.rot_mode,
                                                  self.rot90)
        batch_masks = np.where(batch_masks > 0.5,1,0)
        return batch_images, batch_masks

    def get_val(self):
        '''
        a function to return validation data
        '''
        if self.kmeans:
            return np.concatenate([self.images[self.idx_val],self.cluster_maps[self.idx_val]],axis=-1), self.masks[self.idx_val]
        else:
            return self.images[self.idx_val], self.masks[self.idx_val]

if __name__ == "__main__":
    train_folder = './DataSet/stage1_train'
    test_folder  = './DataSet/stage1_test'
    dataloader   = DataLoader(train_folder,test_folder, (32,32) )

    dataloader.load_training()
    dataloader.set_augmentor()
    dataloader.kmeans_cluster()
    x,y = dataloader.get_batch_train(batch_size=10,augment=True)
    plt.subplot(1,3,1)
    plt.imshow(x[0,:,:,:3])
    plt.subplot(1,3,2)
    plt.imshow(x[0,:,:,:3]/x[0,:,:,:3].max())
    plt.subplot(1,3,3)
    plt.imshow(y[0,:,:,0])
#    dataloader.reset_batch_iterator()
    print(np.unique(y))


from datetime import datetime, timedelta, timezone
from opentelemetry import trace
from lib.db import db

# Connection pooling for our DB
# from lib.db import pool, query_wrap_array

tracer = trace.get_tracer("home.activities")

class HomeActivities:
  def run(cognito_user_id=None):
  # CloudWatch Logs
  # def run(logger):
    # logger.info("HomeActivities")

    # create a span
    with tracer.start_as_current_span("home-activities-mock-data"):
      span = trace.get_current_span()
      # add an attribute
      now = datetime.now(timezone.utc).astimezone()
      span.set_attribute("app.now", now.isoformat())

      sql = db.template('activities','home')
      results = db.query_array_json(sql)
      return results


from matplotlib.pyplot import figure, subplots
from matplotlib.colors import LogNorm
from matplotlib.ticker import MultipleLocator

def plotA(Q, ttxt, vlim):
    E = Q.energy.values
    z = Q.altkm.values
    # species = Q.species.values
    Q = Q[0]  # FIXME first time only
    # %%

    def _doax(fg, ax, ttxt):
        ax.yaxis.set_major_locator(MultipleLocator(100))
        ax.yaxis.set_minor_locator(MultipleLocator(20))
        ax.set_xscale("log")
        ax.set_title(ttxt)
        ax.set_xlabel("beam energy [eV]")
        ax.autoscale(True, tight=True)  # fill axes

    # fg,axs = subplots(1,Q.species.size,sharey=True)
    # fg.suptitle(ttxt)
    fg = figure()

    # for ax,Qs,l in zip(axs,Q.values,species):
    Qs = Q.values
    ax = fg.gca()
    hi = ax.pcolormesh(E, z, Qs, vmin=vlim[0], vmax=vlim[1], norm=LogNorm())
    _doax(fg, ax, "")  # str(l))

    c = fg.colorbar(hi, ax=ax)
    c.set_label("Production Rate [cm$^{-3}$ s${^-1}$]")

    ax.set_ylabel("altitude [km]")

def fig7(W, z, Eplot):
    """
    Eqn. 6 uses each species individually, while Eqn A1 (actually used in the program)
    considers overall mass density of all three species at once.
    """
    # W: Nenergy x Nalt
    ax = figure().gca()
    for i, e in enumerate(Eplot):
        ax.plot(W[i, :], z, label="{:.0f}".format(e))
    ax.set_title("Eqn A1")
    ax.set_xscale("log")
    ax.set_ylim(80, 275)
    ax.set_xlim(1e7, 1e9)
    ax.set_xlabel("Energy Deposition [eV g$^{-1}$ cm$^2$]")
    ax.set_ylabel("altitude [km]")
    ax.legend()

def fig8(Q):
    Q = Q.squeeze()
    E = Q.energy.values
    z = Q.altkm.values
    # species=Q.species.values

    # fg,axs = subplots(1,3,num=8,sharey=True)
    fg = figure()
    # for ax,s in zip(axs,species):
    ax = fg.gca()
    for e in E:
        ax.plot(Q.loc[:, e], z, label=str(e))
    ax.legend()
    ax.grid(True, which="both")
    ax.set_ylim(80, 275)
    ax.set_xscale("log")
    ax.set_xlim(1e-2, 1e5)
    ax.set_title("Ionization Rate")
    ax.set_xlabel("Ionization Rate [cm$^{-3}$ s$^{-1}$]")
    ax.set_ylabel("Altitude [km]")

def fig11(E, chi, Lambda_m, Lambda_i, fignum=11):  # from Sergienko & Ivanov 1993
    # Lambda: Nenergy x Nalt

    def _f11(Lambda, ax, ttxt):
        for e, x, l in zip(E, chi, Lambda):
            ax.plot(x, l, label=str(e))
        ax.set_title(r"$\lambda$ " + ttxt)
        ax.set_xlabel(r"Distance $\chi$")
        ax.set_xlim(0, 3)
        ax.legend()

    fg, axs = subplots(1, 2, sharey=True, num=fignum)
    axs[0].set_ylabel("Function of Dissipation")

    if Lambda_m is not None:
        _f11(Lambda_m, axs[0], "field-aligned flux")

    if Lambda_i is not None:
        _f11(Lambda_i, axs[1], "isotropic flux")

def fig12(E, Cmono, Ciso):
    """
    Energy deposition fitted curves
    """

    def f12(ax, C, E):
        for c, l in zip(C, ("C1", "C2", "C3", "C4")):
            ax.plot(E, c, label=l)
        ax.legend()
        ax.grid(which="both")
        ax.set_ylabel("fitting parameter")
        ax.set_xscale("log")
        ax.grid(True, which="both")
        ax.legend()
        ax.autoscale(True, tight=True, axis="x")

    fg, axs = subplots(2, 1, sharex=True, num=12)

    ax = axs[0]
    f12(ax, Cmono, E)
    ax.set_title("Monodirectional")
    # %%
    ax = axs[1]
    f12(ax, Ciso, E)
    ax.set_xlabel("Energy [eV]")
    ax.set_title("Isotropic Downward Hemisphere")

def fig13(E, afmono, afiso, rngmono, rngiso):

    fg, axs = subplots(2, 1, sharex=True, num=13)
    # %% range
    ax = axs[0]
    ax.plot(E, rngmono, label="monodirectional")
    ax.plot(E, rngiso, label="isotropic")
    ax.set_xlabel("Energy [eV]")
    ax.set_ylabel("Range [g/cm^2]")
    ax.legend(loc="best")
    ax.autoscale(True, tight=True, axis="x")
    ax.set_yscale("log")
    ax.set_ylim(1e-7, 1e-4)
    ax.grid(which="both")
    # %% albedo
    ax = axs[1]
    ax.plot(E, afmono, label="monodirectional")
    ax.plot(E, afiso, label="isotropic")
    ax.set_xlabel("Energy [eV]")
    ax.set_ylabel("Albedo-flux")
    ax.set_xscale("log")
    ax.legend(loc="best")
    ax.autoscale(True, tight=True, axis="x")


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

import glob
import unittest

try:
    # python2 case
    from StringIO import StringIO
except ImportError:
    # python3 case
    from io import StringIO
from os.path import abspath, split, join

from constants import RUNNING_ON_ANDROID

APP_PATH = split(abspath(__file__))[0]

def run_test_suites_into_buffer(suites):
    """Run a suite of unittests but into a buffer so we can read the result."""
    terminal_output = StringIO()
    unittest.TextTestRunner(stream=terminal_output).run(suites)
    return terminal_output.getvalue()

def get_images_with_extension(path=APP_PATH, extension='*.png'):
    """
    Return a list of image files given a path and an file extension.

    .. note:: those image files are supposed to be created by our unittests
              inside the app's root folder.
    """
    return glob.glob(join(path, extension))

def load_kv_from(kv_name):
    """
    Load a kivy's kv file givel a kv filename.

    .. note:: requires `.kv` extension.
    """
    from kivy.lang import Builder

    kv_file = join(APP_PATH, kv_name)
    return Builder.load_file(kv_file)

def raise_error(error):
    """
    A function to notify an error without raising an exception.

    .. warning:: we will try to notify via an kivy's Popup, but if kivy is not
              installed, it will only print an error message.
    """
    try:
        from widgets import ErrorPopup
    except ImportError:
        print('raise_error:',  error)
        return
    ErrorPopup(error_text=error).open()

def get_failed_unittests_from(unittests_output, set_of_tests):
    """Parse unittests output trying to find the failed tests"""
    failed_tests = set()
    for test in set_of_tests:
        if test in unittests_output:
            failed_tests.add(test)
    return failed_tests

def skip_if_not_running_from_android_device(func):
    """
    Skip run of the function in case that we are running the app form android.

    .. note:: this is useful for some kind of tests that are supposed to be run
              from an android device and relies on `pyjnius`.
    """

    def wrapper(*arg, **kwarg):
        if RUNNING_ON_ANDROID:
            return func(*arg, **kwarg)
        raise_error(
            'Function `{func_name}` only available for android devices'.format(
                func_name=func.__name__,
            ),
        )
        return None

    return wrapper

@skip_if_not_running_from_android_device
def get_android_python_activity():
    """
    Return the `PythonActivity.mActivity` using `pyjnius`.

    .. warning:: This function will only be ran if executed from android"""
    from jnius import autoclass

    PythonActivity = autoclass('org.kivy.android.PythonActivity')
    return PythonActivity.mActivity

@skip_if_not_running_from_android_device
def vibrate_with_pyjnius(time=1000):
    """
    Vibrate an android device using `pyjnius`.

    .. warning:: This function will only be ran if executed from android."""
    from jnius import autoclass, cast

    print('Attempting to vibrate with pyjnius')
    ANDROID_VERSION = autoclass('android.os.Build$VERSION')
    SDK_INT = ANDROID_VERSION.SDK_INT

    Context = autoclass("android.content.Context")
    activity = get_android_python_activity()

    vibrator_service = activity.getSystemService(Context.VIBRATOR_SERVICE)
    vibrator = cast("android.os.Vibrator", vibrator_service)

    if vibrator and SDK_INT >= 26:
        print("Using android's `VibrationEffect` (SDK >= 26)")
        VibrationEffect = autoclass("android.os.VibrationEffect")
        vibrator.vibrate(
            VibrationEffect.createOneShot(
                time, VibrationEffect.DEFAULT_AMPLITUDE,
            ),
        )
    elif vibrator:
        print("Using deprecated android's vibrate (SDK < 26)")
        vibrator.vibrate(time)
    else:
        print('Something happened...vibrator service disabled?')

@skip_if_not_running_from_android_device
def set_device_orientation(direction):
    """
    Modifies the app orientation for an android device.

    .. warning:: This function will only be ran if executed from android."""
    if direction not in ('sensor', 'horizontal', 'vertical'):
        print(
            'ERROR: asked to orient to `{direction}`, but we only support: '
            'sensor, horizontal or vertical'.format(direction=direction)
        )
    from jnius import autoclass

    activity = get_android_python_activity()
    ActivityInfo = autoclass('android.content.pm.ActivityInfo')

    if direction == 'sensor':
        activity.setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
    elif direction == 'horizontal':
        activity.setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
    else:
        activity.setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

@skip_if_not_running_from_android_device
def setup_lifecycle_callbacks():
    """
    Register example ActivityLifecycleCallbacks
    """
    from android.activity import register_activity_lifecycle_callbacks

    register_activity_lifecycle_callbacks(
        onActivityStarted=lambda activity: print('onActivityStarted'),
        onActivityPaused=lambda activity: print('onActivityPaused'),
        onActivityResumed=lambda activity: print('onActivityResumed'),
        onActivityStopped=lambda activity: print('onActivityStopped'),
        onActivityDestroyed=lambda activity: print('onActivityDestroyed'),
    )


import secrets
import random

from expert.experiment import Experiment, TaskResponse

from expert.tasks import Task, Consent, Soundcheck, TaskDesc

from expert import socketio

from . import params

from .trialtasks import RatingTask

# Your experiment class must be a subclass of expert.experiment.Experiment,
# but can have any name

class Amelio(Experiment):

    # Title for experiment browser window
    window_title = 'Nonsense word experiment'

    turk_codes = set()

    def __init__(self, *args):
        super().__init__(*args)

        # Example of generating a secure Mechanical Turk code
        # and storing it in the participant's responses

        while True:
            self.turk_code = secrets.token_urlsafe(16)
            if self.turk_code not in self.turk_codes:
                self.turk_codes.add(self.turk_code)
                break
        self.responses.append(
            TaskResponse(self.turk_code, 'TURK_CODE', ''))

        # The first task is created as an instance of the
        # Task class, and assigned to self.task;
        # the first argument is the participant's session ID,
        # and the second is the name of the template to display.
        # Subsequent tasks are added by chaining calls
        # to the .then() method.

        # .then() creates a new instance of the Task class
        # using the arguments it is given. Optionally, the first
        # argument may be a custom sublcass of Task.
        self.task = Task(self, 'welcome')
        # Use built-in Consent class with custom 'consent' template
        (self.task.then(Consent, 'consent')
         #.then(Soundcheck)
         # Use Task class with custom template
         .then('instruct_qnaire')
         # 'qnaire' template receives 'questions' variable containing
         # questionnaire questions
         .then('qnaire', {'questions': params.qnaire_quests})
         .then('instruct_training')
         # Insert sequence of tasks
         .then_all(self.training_tasks()[:4])
         .then('instruct_main')
         .then_all(self.main_tasks()[:4])
         .then('exit_qnaire', {'questions': params.exit_qnaire_quests},
               # Disable main section timeout (set below)
               timeout_secs=-1)
         .then('thankyou', {'turk_code': self.turk_code}))

    def training_tasks(self):
        sounds = []
        with open(self.dir_path / 'stims-training.txt') as f:
            for line in f:
                sound, orth = line.rstrip().split('  ')  # 2 spaces
                sounds.append((sound, orth))
        random.shuffle(sounds)
        tasks = [TaskDesc([RatingTask, sound, orth])
                 for sound, orth in sounds]
        # Set show_prompt=True for first task
        tasks[0].kwargs['show_prompt'] = True
        return tasks

    def main_tasks(self):
        tasks = [TaskDesc([RatingTask, self.profile.stim_sounds[stim], stim])
                 for stim in self.profile.stims]
        # Set timeout for main experiment section
        tasks[0].kwargs['timeout_secs'] = params.timeout_secs
        return tasks


from django.shortcuts import render
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

from item.models import Item, Review
from  item.serializers import (ItemSerializer)

@api_view(["GET", 'POST'])
def item_list(request):
    """
        list of all items  or create new item
        """

    if request.method == 'GET':
        items = Item.objects.all()
        serializer = ItemSerializer(items, many=True)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    elif request.method == 'POST':
        serializer = ItemSerializer(data=request.data)
        data = request.data
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# import logging

# import azure.functions as func

# def main(req: func.HttpRequest) -> func.HttpResponse:
#     logging.info('Python HTTP trigger function processed a request.')

#     name = req.params.get('name')
#     if not name:
#         try:
#             req_body = req.get_json()
#         except ValueError:
#             pass
#         else:
#             name = req_body.get('name')

#     if name:
#         return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
#     else:
#         return func.HttpResponse(
#              "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
#              status_code=200
#         )

import logging

import azure.functions as func
from textblob import TextBlob
import nltk
import os
import json

import urllib
import pickle
import speech_recognition as sr
import os
import json
from moviepy.editor import *
import requests

r= sr.Recognizer()

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        req_body = req.get_json()
    except ValueError:
        pass

    extractedURL =req_body['url']
    outputSentiment ="Nothing"
    try:
        sentiment,extractedText = urlToSentimentConverter(urls = extractedURL)
        print("final sentiment "+str(sentiment))
        return func.HttpResponse(json.dumps(sentiment), mimetype='application/json' )
    except:
        sentiment,extractedText = "error in urlToSentiment","error in urlToSentiment"

def urlToSentimentConverter(urls):
    def textToSentiment(text):
        blob = TextBlob(text)
        polarity = blob.sentiment.polarity
        outputSentiment ="Nothing"
        if(polarity < -0.1):
            outputSentiment ="NEGATIVE, score =  " +str(polarity)
        elif(-0.1<=polarity<=0.1):
            outputSentiment ="NEUTRAL, score =  " +str(polarity)
        elif(polarity>0.1):
            outputSentiment ="POSITIVE, score =  " +str(polarity)
        print("output sentiment = "+str(outputSentiment))
        return(outputSentiment)
    def startConvertion(path='/tmp/convertedAudio.wav', lang='en-IN'):
        with sr.AudioFile(path) as source:
            print('Fetching File')
            audio_text = r.listen(source)
            # recoginize_() method will throw a request error if the API is unreachable, hence using exception handling
            try:

                # using google speech recognition
                print('Converting audio transcripts into text ...')
                text = r.recognize_google(audio_text)
                print('Converted is '+str(text))
                return text

            except:
                print('unable to convert audio to text')
                return "error in text conversion"

    print('Downloading video')
    urllib.request.urlretrieve(urls, '/tmp/downloadedVideo.mp4')

    print('Download completed')

    print("reading video file")
    # my_clip = mp.VideoFileClip(r'/tmp/downloadedVideo.mp4')

    # my_clip.audio.write_audiofile(r"/tmp/my_result.wav")
    # print('writting complete')
    sound = AudioFileClip("/tmp/downloadedVideo.mp4")
    print('writing audio file')
    sound.write_audiofile("/tmp/convertedAudio.wav")
    print('writting complete')

    text = startConvertion(path='/tmp/convertedAudio.wav', lang='en-IN')
    # text = 'that was very nice very very nice keep doing it its great'

    if (text == "error in text conversion"):
        interResult = ["Audio to text failed", ""]
        print(interResult)
        print(type(interResult))
        return str(interResult[0]), text

    else:
        interResult = textToSentiment(text)
        print(interResult)
        print(type(interResult))
        return str(interResult), text


# -*- coding: UTF-8 -*-

import argparse
import os
import time
import pickle
import json
import logging
import math
import copy
import torch
import sys
import dgl
from random import randint, choice

import scipy.sparse
import pandas as pd
import numpy as np

from utils import utils
from torch.nn.utils.rnn import pad_sequence
from torch import nn

class MetaReader(object):
    @staticmethod
    def parse_data_args(parser):
        parser.add_argument('--path', type=str, default='../data/',
                            help='Input data dir.')
        parser.add_argument('--suffix', type=str, default='MeLON',
                            help='Input data dir of MeLON.')
        parser.add_argument('--dataset', type=str, default='Grocery_and_Gourmet_Food',
                            help='Choose a dataset.')
        parser.add_argument('--sep', type=str, default='\t',
                            help='Sep of csv file.')
        parser.add_argument('--train_ratio', type=float, default=0.8,
                            help='Ratio of the train dataset')
        parser.add_argument('--duplicate', type=int, default=1,
                            help='Coalesce duplicate elements in adjacency matrix')
        parser.add_argument('--fname', type=str, default='freq',
                            help='Freq (> 20 records) or whole')
        return parser

    def __init__(self, args):
        self.sep = args.sep
        self.prefix = args.path
        self.suffix = args.suffix
        self.dataset = args.dataset
        self.train_ratio = args.train_ratio
        self.batch_size = args.batch_size
        self.fname = args.fname
        self.random_seed = args.random_seed

        t0 = time.time()
        self._read_data()
        print(self.data_df['user_id'].max(),len(self.data_df['user_id'].unique()))
        print(self.data_df['item_id'].max(),len(self.data_df['item_id'].unique()))

        logging.info('Counting dataset statistics...')
        self.n_users, self.n_items = self.data_df['user_id'].max()+1, self.data_df['item_id'].max()+1
        self.dataset_size = len(self.data_df)
        self.n_batches = math.ceil(self.dataset_size/self.batch_size)
        logging.info('"# user": {}, "# item": {}, "# entry": {}'.format(self.n_users-1, self.n_items-1, self.dataset_size))

        path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname)
        if not os.path.exists(path):
            os.mkdir(path)
        del path

        logging.info('Saving data into mini-batch pickle files')
        self.user_list = self.data_df['user_id'].to_numpy()

        self._save_user_clicked_set()
        self._save_hist_set()
        self._save_mini_batch()
        self._save_last_batch()
        self._save_heterograph()

        del self.data_df

        logging.info('Done! [{:<.2f} s]'.format(time.time() - t0) + os.linesep)

    def _read_data(self):
        logging.info('Reading data from \"{}\", dataset = \"{}\", suffix = \"{}\", fname = \"{}\" '.format(self.prefix, self.dataset, self.suffix, self.fname))
        df = pd.read_csv(os.path.join(self.prefix, self.dataset, self.suffix, self.fname +'.csv'), sep=self.sep)  # Let the main runner decide the ratio of train/test
        self.data_df = df.loc[:, ['user_id', 'item_id']]#.values.astype(np.int64) # (number of items, 2)

    def _save_user_clicked_set(self):
        user_clicked_set_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'user_clicked_set.txt')
        logging.info('Load user_clicked_set')

        try:
            self.user_clicked_set = pickle.load(open(user_clicked_set_path, 'rb'))
            logging.info("Successfully loaded saved user_clicked_set")
        except FileNotFoundError as e:
            logging.info('File not found, create user_clicked_set')
            self.user_clicked_set = self.data_df.groupby(['user_id'])['item_id'].unique().to_dict()
            pickle.dump(self.user_clicked_set, open(user_clicked_set_path, 'wb'))
            logging.info('Saved user_clicked_set')

    def _save_hist_set(self):
        '''Prepare previous interactions of users and items during offline meta-model training.
        '''
        item_hist_set_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'item_hist_set.txt')
        user_hist_set_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'user_hist_set.txt')
        logging.info('Load hist_set')

        try:
            self.item_hist_set = pickle.load(open(item_hist_set_path, 'rb'))
            self.user_hist_set = pickle.load(open(user_hist_set_path, 'rb'))
            logging.info("Successfully loaded saved hist_set")
        except FileNotFoundError as e:
            logging.info('File not found, create hist_set')
            train_df = self.data_df.loc[:int(self.n_batches*self.train_ratio)*self.batch_size,:]
            self.item_hist_set = train_df.groupby(['item_id'])['user_id'].unique().to_dict()
            self.user_hist_set = train_df.groupby(['user_id'])['item_id'].unique().to_dict()
            pickle.dump(self.item_hist_set, open(item_hist_set_path, 'wb'))
            pickle.dump(self.user_hist_set, open(user_hist_set_path, 'wb'))
            logging.info('Saved hist_set')

    def _save_mini_batch(self):
        self.mini_batch_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'mini_batch')
        if not os.path.exists(self.mini_batch_path):
            os.mkdir(self.mini_batch_path)

        for batch_idx in range(self.n_batches):
            ui_batch = torch.from_numpy(self.data_df[batch_idx*self.batch_size:(batch_idx+1)*self.batch_size].values.astype(np.int64)) # (batch_size, 2)
            torch.save(ui_batch, open(os.path.join(self.mini_batch_path, str(batch_idx)+'.pt'), 'wb'))

    def _save_last_batch(self):
        '''Save previous interaction of user and item in current mini-batch for online testing.
        Given user-item interaction (u, i) in current mini-batch, Prepare previous interaction of user and item

        The resulting user-item interactions (torch.LongTensor size of [batch_size*2, 2]) are saved in last_batch_path

            # different user, same item: (u', i), (u', -i)
            # for positive: get user, and pick another used item
            # for negative: get user, and pick random negative item

            # same user, different item: (u, i'), (u, -i')
            # for positive: get user, and pick another used item
            # for negative: get user, and pick random negative item

        Exception handling:
            If a user has no previous interactions, then the current item is selected.
            If an item has no previous interactions, then the current user is selected.
            -> Randomly sample previous user/item
        Prepare (torch.LongTensor size of [batch_size*2, 2])
        '''

        self.last_batch_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'last_batch')
        if not os.path.exists(self.last_batch_path):
            os.mkdir(self.last_batch_path)

        test_start_batch_idx = int(self.n_batches*self.train_ratio)
        train_df = self.data_df.loc[:test_start_batch_idx*self.batch_size,:]

        ui_last = {u:None for u in range(self.n_users)}
        ui_last_ = train_df.groupby(['user_id'])['item_id'].unique().apply(lambda x: x[-1]).to_dict()
        ui_last.update(ui_last_)

        iu_last = {i:None for i in range(self.n_items)}
        iu_last_ = train_df.groupby(['item_id'])['user_id'].unique().apply(lambda x: x[-1]).to_dict()
        iu_last.update(iu_last_)

        for batch_idx in range(test_start_batch_idx, self.n_batches):
            user_id, item_id = torch.from_numpy(self.data_df[batch_idx*self.batch_size:(batch_idx+1)*self.batch_size].values.astype(np.int64)).T # (batch_size, 2)

            # same user, different item: (u, i'), (u, -i')
            # for positive: get user, and pick user's last item
            # for negative: get user, and pick random negative item
            pos_items_u = torch.zeros(size=(len(user_id), 1), dtype=torch.int64)
            neg_items_u = torch.zeros(size=(len(user_id), 1), dtype=torch.int64)
            for idx, user in enumerate(user_id):
                user_clicked_set = copy.deepcopy(self.user_clicked_set[user.item()])
                last_item = ui_last[user.item()]
                pos_items_u[idx] = last_item if last_item is not None else item_id[idx]
                neg_items_u[idx] = self._randint_w_exclude(user_clicked_set)
            items_u = torch.cat((pos_items_u, neg_items_u), axis=-1)

            # different user, same item: (u', i), (u', -i)
            # for positive: get item's last user, and pick item
            # for negative: get item's last user, and pick random negative item
            user_id_ = torch.zeros_like(user_id)
            for idx, item in enumerate(item_id): # pick u'
                last_user = iu_last[item.item()]
                user_id_[idx] = last_user if last_user is not None else user_id[idx]

            neg_items_u_ = torch.zeros(size=(len(user_id), 1), dtype=torch.int64)
            for idx, user in enumerate(user_id_):
                user_clicked_set = copy.deepcopy(self.user_clicked_set[user.item()])
                neg_items_u_[idx] = self._randint_w_exclude(user_clicked_set)
            items_u_ = torch.cat((item_id.reshape(-1, 1), neg_items_u_), axis=-1)

            # Update last interaction history
            for user, item in zip(user_id, item_id):
                ui_last[user.item()] = item.item()
                iu_last[item.item()] = user.item()

            # Save last interaction mini-batch
            user_id = torch.cat((user_id, user_id_), axis=0)
            item_id = torch.cat((items_u, items_u_), axis=0)

            last_batch = {'user_id': user_id, # [batch_size*2,]
                          'item_id': item_id} # [batch_size*2, 2]

            torch.save(last_batch, open(os.path.join(self.last_batch_path, str(batch_idx)+'.pt'), 'wb'))

    def _randint_w_exclude(self, clicked_set):
        randItem = randint(1, self.n_items-1)
        return self._randint_w_exclude(clicked_set) if randItem in clicked_set else randItem

    def _save_heterograph(self):
        self.graph_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'heterograph_train.bin')
        logging.info('Load heterograph_train')
        try:
            g_list, _ = dgl.load_graphs(self.graph_path,[0])
            self.g = g_list[0]
            logging.info("Successfully loaded heterograph_train")
        except Exception as e:
            logging.info('File not found, create heterograph_train')
            u, i = self.data_df[:int(self.n_batches*self.train_ratio)*self.batch_size].values.T
            self.g = dgl.heterograph({('user', 'u_to_i', 'item'): (u, i),
                                      ('item', 'i_to_u', 'user'): (i, u)},
                                      num_nodes_dict={'user':self.n_users, 'item':self.n_items})
            dgl.save_graphs(self.graph_path, self.g)
            logging.info('Successfully saved heterograph_train')

    # Below are deprecated methods
    def _save_adj_batch(self):
        """Generate user/item history indices/counts (torch.LongTensor) for each batch and save them.
        Process:

            Preparation
            1. Construct offline user-item interaction matrix (scipy.sparse.csr_matrix)

            For each offline batch
            1. Index user/item for each batch and their value
            2. Pad_sequence
            3. Save them

            For each online batch
            1. Change offline matrix to LIL (scipy.sparse.lil_matrix)
            2. Increment user/item interaction
            3. Index user/item for each batch
            4. Construct batch matrix (torch.sparse.FloatTensor)
            5. Save them

        """

        # Preparation
        if self.adj is None:
            self._prepare_adj()

        # Offline
        self.adj_batch_path = os.path.join(self.prefix, self.dataset, self.suffix, self.fname, 'adj_batch')
        if not os.path.exists(self.adj_batch_path):
            os.mkdir(self.adj_batch_path)

        for batch_idx in range(int(self.n_batches*self.train_ratio)):
            users, items = self.adj_node_idx[batch_idx*self.batch_size:(batch_idx+1)*self.batch_size].T

            self._save_hist_seq(users, batch_idx, 'u')
            self._save_hist_seq(items, batch_idx, 'i', transpose=True)

        # Online
        for batch_idx in range(int(self.n_batches*self.train_ratio), self.n_batches):
            # Add new interactions
            self.adj = self.adj.tolil()
            for user, item in self.adj_node_idx[batch_idx*self.batch_size:(batch_idx+1)*self.batch_size]:
                self.adj[user, item] += 1
            self.adj = self.adj.tocsr()

            users, items = self.adj_node_idx[batch_idx*self.batch_size:(batch_idx+1)*self.batch_size].T

            self._save_hist_seq(users, batch_idx, 'u')
            self._save_hist_seq(items, batch_idx, 'i', transpose=True)

    def _save_hist_seq(self, batch, batch_idx, msg, transpose=False):
        indices = []
        data = []
        adj = self.adj.T if transpose else self.adj
        for i in batch:
            indices.append(torch.from_numpy(adj.getrow(i).indices))
            data.append(torch.from_numpy(adj.getrow(i).data))

        indices = pad_sequence(indices, batch_first=True, padding_value=0)
        data = pad_sequence(data, batch_first=True, padding_value=0)

        torch.save(indices, os.path.join(self.adj_batch_path, msg+'_idx'+str(batch_idx)+'.pt'))
        torch.save(data, os.path.join(self.adj_batch_path, msg+'_val'+str(batch_idx)+'.pt'))

    def update_adj(self, batch_idx):
        """Add current batch to adjacency matrix for online update"""
        if self.cur_idx == batch_idx:
            logging.info('Adjacency matrix not updated')
            return

        new_indices = torch.cat((self.adj._indices(), self.adj_node_idx[batch_idx:batch_idx+batch_size].T), axis=1)
        new_vals = torch.cat((self.adj._values(), self.adj_edge_val[batch_idx:batch_idx+batch_size]))
        self.adj = torch.sparse_coo_tensor(new_indices, new_vals)
        self.coalesce()

    def init_adj(self):
        self.cur_idx = int(self.n_batches*self.train_ratio)*self.batch_size # number of offline items
        self.adj = scipy.sparse.csr_matrix((self.adj_edge_val[:self.cur_idx],
                                            self.adj_node_idx[:self.cur_idx].T),
                                            shape=(self.n_users, self.n_items))
        logging.info('Adjacency matrix created with type: %s and shape: %s' %(str(type(self.adj)), str(self.adj.shape)))

    def _prepare_adj(self):
        logging.info('Preparing adjacency matrix')
        #self.adj_node_idx = torch.from_numpy(self.data_df.loc[:, ['user_id', 'item_id']].values).to(dtype=torch.int32) # (number of items, 2)
        #self.adj_edge_val = torch.ones(len(self.adj_node_idx), dtype=torch.int16) # (number_of_items)
        self.adj_node_idx = self.data_df.loc[:, ['user_id', 'item_id']].values.astype(np.int64) # (number of items, 2)
        self.adj_edge_val = np.ones(len(self.adj_node_idx), dtype=np.int16) # (number_of_items)

        self.init_adj()

    # Deprecated
    def _coalesce(self):
        """Coalesce duplicate edges into single (one-valued) edge.
        Require adj. matrix (torch.sparse_coo_tensor)
        """
        self.adj = self.adj.coalesce()
        assert self.adj.is_coalesced()

        if self.duplicate == 0: # No duplicate edge: edge value is always one
            self.adj = torch.sparse_coo_tensor(self.adj._indices(), self.adj._values().fill_(1)).coalesce()

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    parser = argparse.ArgumentParser()
    parser = MetaReader.parse_data_args(parser)
    args, extras = parser.parse_known_args()

    args.path = '../../data/'
    corpus = MetaReader(args)

    corpus_path = os.path.join(args.path, args.dataset, 'mesia', 'Corpus.pkl')
    logging.info('Save corpus to {}'.format(corpus_path))
    pickle.dump(corpus, open(corpus_path, 'wb'))


bl_info = {
	"name": "Motion Transfer",
	"author": "Grey Ruessler",
	"version": (1, 1, 0),
	"blender": (2, 80, 0),
	"location": "Search > Motion Transfer",
	"description": "Transfer all animations from the selected armature to the active armature",
	"warning": "",
	"wiki_url": "",
	"category": "Object",
}

import bpy
from mathutils import Matrix

def GetWorldSpaceBonePosition(ob,bone):
	mat = ob.matrix_world @ bone.matrix_local
	loc, rot, scale = mat.decompose()
	return loc

def GetClosestBone(armature,pos,*args):
	biggestLength = 999999999
	if len(args)>=1:
		biggestLength = args[0]
	retVal = None
	for bone in armature.data.bones:
		wsPos = GetWorldSpaceBonePosition(armature,bone)
		localVec = (wsPos-pos)
		if localVec.length < biggestLength:
			retVal = bone
			biggestLength = localVec.length
	return retVal

class MotionTransfer(bpy.types.Operator):
	bl_idname = "armature.motion_transfer"
	bl_label = "Motion Transfer"
	bl_options = {'REGISTER', 'UNDO'}

	searchRadius: bpy.props.FloatProperty(name="Bone Search Radius", description = "If there isn't a matching bone name on the source, we search this far from the head", default = 1 )
	searchBlacklist: bpy.props.StringProperty(name="Bone Search Blacklist", description = "Ignore bones containing these parameters, separated by commas", default = "dummy" )
	cleanTransfer: bpy.props.BoolProperty(name="Clean Transfer", description = "Remove all bones which aren't in the target skeleton?", default = False )

	def exec(self,context,skeleton_source,skeleton_target):

		wm = context.window_manager
		wm.progress_begin(0, 100)
		wm.progress_update(0)

		boneParentsOG = {}
		boneLinks = {}
		bonesToClean = {}
		targetBones = {}

		#Setup source and target

		source = skeleton_source
		target = skeleton_target

		context.view_layer.objects.active = source
		context.object.data.pose_position = 'REST'
		context.view_layer.objects.active = target
		context.object.data.pose_position = 'POSE'

		context.view_layer.objects.active = target
		bpy.ops.object.mode_set(mode='POSE')

		#Save parents

		for bone in target.data.bones:
			if not bone.parent is None:
				boneParentsOG[bone.name] = bone.parent.name
			else:
				boneParentsOG[bone.name] = "None"

		#Prevent duplicates and link same-named bones

		for bone in source.data.bones:
			if bone.name in target.data.bones:
				boneLinks[bone.name] = bone.name + "_src"
				bonesToClean[bone.name+"_src"] = True
				bone.name = bone.name + "_src"

		#Build link cache

		blacklistTable = self.searchBlacklist.split(",")
		if blacklistTable is None:
			if len(self.searchBlacklist)>0:
				blacklistTable = [self.searchBlacklist]
			else:
				blacklistTable = []

		for bone in target.data.bones:
			targetBones[bone.name] = True
			if not bone in boneLinks:
				doLink = True
				for blacklistString in blacklistTable:
					if len(blacklistString)>=1 and bone.name.find(blacklistString)!=-1:
						print("discovered: " + blacklistString)
						doLink = False
				if doLink:
					closestBone = GetClosestBone(source,GetWorldSpaceBonePosition(target,bone),self.searchRadius)
					if closestBone is not None:
						boneLinks[bone.name] = closestBone.name
						bonesToClean[closestBone.name] = True

		#Apply target armature modifier, make them target source

		for ob in context.view_layer.objects:
			ob.select_set(state=False)

		for ob in context.view_layer.objects:
			ob.select_set(state=True)
			#context.view_layer.objects.active = ob
			for mod in ob.modifiers:
				if mod.type == "ARMATURE":
					if mod.object == target:
						bpy.ops.object.modifier_apply(apply_as='DATA', modifier = mod.name )
						ob.modifiers.new(name = 'Skeleton', type = 'ARMATURE')
						ob.modifiers['Skeleton'].object = source
			ob.select_set(state=False)

		#Merge a duplicate of the target into source

		target.select_set(state=True)
		context.view_layer.objects.active = target
		bpy.ops.pose.armature_apply()

		bpy.ops.object.mode_set(mode='OBJECT')
		target_dupe = target.copy()
		target_dupe.data = target.data.copy()
		target_dupe.animation_data_clear()
		context.collection.objects.link(target_dupe)
		target.select_set(state=False)
		source.select_set(state=True)
		target_dupe.select_set(state=True)
		context.view_layer.objects.active = source
		bpy.ops.object.join()
		source.select_set(state=False)
		target.select_set(state=True)
		context.view_layer.objects.active = target
		#now clean and prepare targe to become our final skeleton
		bpy.ops.object.mode_set(mode='EDIT')
		for bone in target.data.edit_bones:
			target.data.edit_bones.remove(bone)
		bpy.ops.object.mode_set(mode='OBJECT')
		context.view_layer.objects.active = source
		source.select_set(state=True)
		target.select_set(state=False)
		#Reparent

		bpy.ops.object.mode_set(mode='EDIT')

		for bone in source.data.edit_bones:
			if bone.name in boneLinks:
				linkedBone = boneLinks[bone.name]
				if linkedBone in source.data.edit_bones:
					bone.parent = source.data.edit_bones[ linkedBone ]

		bpy.ops.object.mode_set(mode='POSE')
		context.object.data.pose_position = 'POSE'

		for a in bpy.data.actions:
			for fcu in a.fcurves:
				bone = fcu.data_path.split('"')[1]
				appendedname = bone + "_src"
				if appendedname in source.data.bones:
					fcu.data_path = fcu.data_path.replace( bone, bone+"_src" )

		wm.progress_update(5)

		#Duplicate source into target as final

		bpy.ops.object.mode_set(mode='OBJECT')

		source.animation_data.action = None

		src_dupe = source.copy()
		src_dupe.data = source.data.copy()
		context.collection.objects.link(src_dupe)

		final = target
		source.select_set(state=False)
		src_dupe.select_set(state=True)
		final.select_set(state=True)
		context.view_layer.objects.active = final
		bpy.ops.object.join()

		#Reparent final skeleton to the original target specs

		bpy.ops.object.mode_set(mode='EDIT')

		for bone in final.data.edit_bones:
			par = bone.parent
			if par is not None:
				if bone.name in boneParentsOG:
					parBoneName = boneParentsOG[bone.name]
					if parBoneName in final.data.edit_bones:
						bone.parent = final.data.edit_bones[parBoneName]

		if self.cleanTransfer:
			for bone in final.data.edit_bones:
				if not bone.name in targetBones:
					final.data.edit_bones.remove( bone )
		else:
			for bone in final.data.edit_bones:
				if bone.name in bonesToClean:
					final.data.edit_bones.remove( bone )

		bpy.ops.object.mode_set(mode='POSE')

		#Remove obsolete constraints

		for bone in final.pose.bones:
			for c in bone.constraints:
				bone.constraints.remove( c )

		#Copy positions/rotations from source, for baking

		for bone in final.pose.bones:
			if bone.name in source.pose.bones:
				nc = bone.constraints.new(type='COPY_ROTATION')
				nc.target = source
				nc.subtarget = bone.name
				nc.influence = 1
				nc_pos = bone.constraints.new(type='COPY_LOCATION')
				nc_pos.target = source
				nc_pos.subtarget = bone.name
				nc_pos.influence = 1

		wm.progress_update(10)

		#Bake animation data

		actionCache = {}

		for a in bpy.data.actions:
			if not a.name in actionCache:
				actionCache[a.name] = True

		actionCount = len(actionCache)

		counter = 0
		for namev in actionCache:
			counter += 1
			a = bpy.data.actions.get( namev )
			lenv = 1
			for fcu in a.fcurves:
				rng = fcu.range()
				lenv = max(rng[1],lenv)
			newName = a.name
			a.name = "old_" + a.name
			source.animation_data.action = a
			#make the new one
			bakeaction = bpy.data.actions.new( name = newName )
			bakeaction.use_fake_user = True
			final.animation_data.action = bakeaction
			bpy.ops.nla.bake(frame_start=0, frame_end=lenv, only_selected=False, visual_keying=True, clear_constraints=False, use_current_action=True, bake_types={'POSE'})
			#remove the old one
			a.use_fake_user = False
			source.animation_data.action = None
			a.user_clear()
			bpy.data.actions.remove( a )
			wm.progress_update(10 + counter / actionCount * 85)

		#Cleanup Source

		for bone in final.pose.bones:
			for c in bone.constraints:
				bone.constraints.remove( c )

		for ob in context.view_layer.objects:
			if ob.type == "MESH":
				for mod in ob.modifiers:
					if mod.type == "ARMATURE":
						ob.modifiers.remove(mod)
				mod = ob.modifiers.new(name = 'Skelemod', type = 'ARMATURE')
				mod.object = final
				ob.parent = final

		final.select_set(state=False)
		source.select_set(state=True)
		context.view_layer.objects.active = source
		bpy.ops.object.delete()
		context.view_layer.objects.active = target
		target.select_set(state=True)
		bpy.ops.object.mode_set(mode='POSE')

		#fix vertex groups

		for poseBone in target.pose.bones:
			poseBone.name = poseBone.name + "_src"
			context.view_layer.update()
			poseBone.name = poseBone.name[0:-4]
		context.view_layer.update()
		wm.progress_update(100)

	@classmethod
	def poll(cls, context):
		numSelected = 0
		for ob in context.view_layer.objects:
			if ob.select_get() and ob.type=='ARMATURE':
				numSelected = numSelected + 1
		return numSelected>=2

	def execute(self, context):
		src = None
		trg = context.view_layer.objects.active
		for ob in context.view_layer.objects:
			if ob != trg and ob.select_get() and ob.type=='ARMATURE':
				src = ob
		self.exec(context,src,trg)
		return {'FINISHED'}

	def invoke(self, context, event):
		wm = context.window_manager
		return wm.invoke_props_dialog(self, width=(640 * bpy.context.preferences.system.pixel_size))

def menu_func(self, context):
	self.layout.operator(MotionTransfer.bl_idname)

def register():
	bpy.utils.register_class(MotionTransfer)
	bpy.types.VIEW3D_MT_pose.append(menu_func)
	bpy.types.VIEW3D_MT_object.append(menu_func)

def unregister():
	bpy.utils.unregister_class(MotionTransfer)
	bpy.types.VIEW3D_MT_pose.remove(menu_func)
	bpy.types.VIEW3D_MT_object.remove(menu_func)

if __name__ == "__main__":
	register()


from datetime import datetime
import iso8601
import json
from collections import OrderedDict
import hashlib
from typing import List, Dict, Tuple, Union
import numpy as np
from io import BytesIO
import uuid
import logging

from .objects import Phrase, PhraseType, KeyphraseType, EntityType, SegmentType

logger = logging.getLogger(__name__)

class KeyphraseUtils(object):
    def __init__(self, mind_dir: str, graph_filter_object=None, mind_store=None):
        self.gfilter = graph_filter_object
        self.mind_store = mind_store
        self.mind_dir = mind_dir

    def hash_phrase(self, phrase: str) -> str:
        hash_object = hashlib.md5(phrase.encode())
        hash_str = hash_object.hexdigest()
        return hash_str

    def hash_sha_object(self) -> str:
        uid = uuid.uuid4()
        uid = str(uid)
        hash_object = hashlib.sha1(uid.encode())
        hash_str = hash_object.hexdigest()
        return hash_str

    def map_embeddings_to_phrase(
        self, phrase_list: List, embedding_list: List
    ) -> Tuple[Dict, Dict]:
        phrase_hash_dict = dict(zip(map(self.hash_phrase, phrase_list), phrase_list))
        phrase_embedding_dict = dict(
            zip(map(self.hash_phrase, phrase_list), embedding_list)
        )

        return phrase_hash_dict, phrase_embedding_dict

    def serialize_to_npz(self, embedding_dict: Dict, file_name: str):
        np.savez_compressed(file_name, **embedding_dict)

        return file_name + ".npz"

    def deserialize_from_npz(self, file_name: Union[str, bytes]):
        if isinstance(file_name, bytes):
            file_name = BytesIO(file_name)

        npz_file = np.load(file_name)

        return npz_file

    def format_time(self, tz_time, datetime_object=False):
        iso_time = iso8601.parse_date(tz_time)
        ts = iso_time.timestamp()
        ts = datetime.utcfromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S:%f")

        if datetime_object:
            ts = datetime.fromisoformat(ts)
        return ts

    def sort_by_value(self, item_list, key=1, order="desc"):
        """
        A utility function to sort lists by their value.
        Args:
            key:
            item_list:
            order:

        Returns:

        """

        if order == "desc":
            sorted_list = sorted(item_list, key=lambda x: x[key], reverse=True)
        else:
            sorted_list = sorted(item_list, key=lambda x: x[key], reverse=False)

        return sorted_list

    def sort_dict_by_value(self, dict_var, order="desc", key=None):
        """
        A utility function to sort lists by their value.
        Args:
            item_list:
            order:

        Returns:

        """
        item_list = dict_var.items()
        if order == "desc":
            if key is not None:
                sorted_list = sorted(
                    item_list, key=lambda x: (x[1][key], x[0]), reverse=True
                )
            else:
                sorted_list = sorted(
                    item_list, key=lambda x: (x[1], x[0]), reverse=True
                )
        else:
            if key is not None:
                sorted_list = sorted(
                    item_list, key=lambda x: (x[1][key], x[0]), reverse=False
                )
            else:
                sorted_list = sorted(
                    item_list, key=lambda x: (x[1], x[0]), reverse=False
                )

        return OrderedDict(sorted_list)

    def write_to_json(self, data, file_name="keyphrase_validation"):
        with open(file_name + ".json", "w", encoding="utf-8") as f_:
            json.dump(data, f_, ensure_ascii=False, indent=4)

        return file_name + ".json"

    def read_segments(self, segment_object: SegmentType):

        segment_list = []

        for segment in segment_object:
            segment_list.append(segment.originalText)

        return segment_list

    def post_process_output(
        self,
        session_id: str,
        phrase_object: Phrase,
        preserve_singlewords=False,
        dict_key="descriptive",
        filter_by_graph: bool = False,
    ) -> Phrase:

        # Post-process entities
        entity_object = phrase_object.entities
        keyphrase_object = phrase_object.keyphrases

        processed_entities = self.post_process_entities(entity_object, keyphrase_object)

        # Place the single keywords in the end of the list.
        multiphrase_object_list = [
            multi_keyphrase
            for multi_keyphrase in keyphrase_object
            if len(multi_keyphrase.originalForm.split()) > 1
        ]
        singlephrase_object_list = [
            single_keyphrase
            for single_keyphrase in keyphrase_object
            if len(single_keyphrase.originalForm.split()) == 1
        ]

        phrase_object.entities = processed_entities
        phrase_object.keyphrases = multiphrase_object_list

        if preserve_singlewords:
            phrase_object.keyphrases.extend(singlephrase_object_list)

        if filter_by_graph:
            try:
                phrase_object = self._graph_filtration(
                    phrase_object, session_id=session_id
                )
            except Exception:
                phrase_object = phrase_object
                logger.warning("No graph filtration is performed")

        return phrase_object

    def _graph_filtration(self, phrase_object: Phrase, session_id: str,) -> Phrase:
        filtered_entities = []
        final_dropped_entities = []
        filtered_keyphrases = []
        final_dropped_keyphrases = []

        # Filter entities by Entity graph
        entity_graph = self.mind_store.get_object(key=session_id)
        if entity_graph is None:
            mind_id = session_id.split(":")[-1]
            mind_graph_path = self.mind_dir + mind_id + "/kp_entity_graph.pkl"
            try:
                mind_filter_graph = self.gfilter.download_mind(
                    graph_file_path=mind_graph_path
                )
                try:
                    self.mind_store.set_object(key=session_id, object=mind_filter_graph)
                    entity_graph = self.mind_store.get_object(key=session_id)
                    mind_filter_graph.clear()

                except Exception as e:
                    logger.warning(
                        "Unable to set the entity graph to redis ... Retrying",
                        extra={"warn": e},
                    )
                    try:
                        self.mind_store.delete_key(key=session_id)
                        self.mind_store.set_object(
                            key=session_id, object=mind_filter_graph
                        )
                        entity_graph = self.mind_store.get_object(key=session_id)
                    except Exception as e:
                        logger.warning(
                            "Error while setting entity graph object", extra={"warn": e}
                        )
                        entity_graph = mind_filter_graph
                        mind_filter_graph.clear()
                        # raise

            except Exception as e:
                logger.error("Unable to download entity graph", extra={"err": e})
                raise

        segment_text = phrase_object.originalText
        entity_object = phrase_object.entities
        keyphrase_object = phrase_object.keyphrases

        keyphrases = [kp.originalForm for kp in keyphrase_object]
        entity_phrases = [entity.originalForm for entity in entity_object]

        processed_entities, dropped_entities = self.gfilter.filter_entities(
            phrase=entity_phrases,
            segment_text_list=[segment_text],
            kp_graph=entity_graph,
        )
        processed_keyphrases, dropped_keyphrases = self.gfilter.filter_keyphrases(
            phrase=keyphrases, segment_text_list=[segment_text], kp_graph=entity_graph
        )

        filtered_entities.extend([ent for ent in processed_entities])
        final_dropped_entities.extend([ent for ent in dropped_entities])
        filtered_keyphrases.extend([kp for kp in processed_keyphrases])
        final_dropped_keyphrases.extend([kp for kp in dropped_keyphrases])

        try:
            for phrase in entity_object:
                if (
                    phrase.originalForm in dropped_entities
                    or phrase.value in dropped_entities
                ):
                    phrase.to_remove = True

            for phrase in keyphrase_object:
                if (
                    phrase.originalForm in dropped_keyphrases
                    or phrase.value in dropped_keyphrases
                ):
                    phrase.to_remove = True

        except Exception as e:
            logger.warning(
                "Unable to post-process keyphrases and entities", extra={"warn": e}
            )

        finally:
            entity_graph.clear()

        logger.debug(
            "Processed keyphrases & entities by ENT-KP Graph",
            extra={
                "filteredKeyphrases": filtered_keyphrases,
                "droppedKeyphrases": final_dropped_keyphrases,
                "filteredEntities": filtered_entities,
                "droppedEntities": final_dropped_entities,
            },
        )

        return phrase_object

    def post_process_entities(
        self, entity_list: EntityType, keyphrase_list: KeyphraseType
    ) -> EntityType:

        processed_entities = []

        # Remove duplicates from the single phrases which are occurring in multi-keyphrases
        multi_phrases = [
            phrases for phrases in entity_list if len(phrases.originalForm.split()) > 1
        ]
        single_phrase = [
            phrases for phrases in entity_list if len(phrases.originalForm.split()) == 1
        ]
        for kw_obj in single_phrase:
            for kw_m_obj in multi_phrases:
                r = kw_m_obj.originalForm.find(kw_obj.originalForm)
                if r > -1:
                    try:
                        single_phrase.remove(kw_obj)
                    except Exception:
                        continue

        # Remove same word occurrences in a multi-keyphrase
        for multi_key_obj in multi_phrases:
            kw_m = multi_key_obj.originalForm.split()
            original_kw_m_len = len(kw_m)
            unique_kp_list = list(dict.fromkeys(kw_m))
            unique_kp_len = len(unique_kp_list)

            if original_kw_m_len != unique_kp_len:
                multi_key_obj.to_remove = True

        # Remove the entities which already occur in keyphrases
        processed_entities.extend(single_phrase)
        for keyphrase_obj in keyphrase_list:
            keyphrase = keyphrase_obj.originalForm

            for entities_obj in processed_entities:
                entities = entities_obj.originalForm

                if entities in keyphrase or entities.lower() in keyphrase:
                    entities_obj.related_to_keyphrase = True

        return processed_entities

    def limit_phrase_list(
        self,
        entities_object: EntityType,
        keyphrase_object: KeyphraseType,
        phrase_limit: int = 10,
        entities_limit: int = 5,
        entity_quality_score: int = 0,
        keyphrase_quality_score: int = 0,
        remove_phrases: bool = False,
        rank_by: str = "pagerank",
        sort_by: str = "loc",
        final_sort: bool = False,
    ) -> Union[
        Tuple[Dict[str, float], EntityType, KeyphraseType],
        Tuple[EntityType, KeyphraseType],
    ]:

        if remove_phrases:
            for entity_obj in entities_object:
                preference_value = entity_obj.preference
                boosted_score = entity_obj.score.boosted_sim
                norm_boosted_score = entity_obj.score.norm_boosted_sim

                entity_score = boosted_score
                # Use normalized boosted score for all phrases when highlight segments come in
                if final_sort:
                    entity_score = norm_boosted_score

                # Check for relevance scores if the entity type is other than Organization or Product
                if preference_value > 2 and preference_value != 5:
                    if (
                        len(entities_object) >= 2
                        and entity_score <= entity_quality_score
                    ):
                        entity_obj.to_remove = True
                    else:
                        continue
                else:
                    if entity_score > 0 and entity_obj.related_to_keyphrase is not True:
                        entity_obj.to_remove = False

            for kp_object in keyphrase_object:
                boosted_score = kp_object.score.boosted_sim
                norm_boosted_score = kp_object.score.norm_boosted_sim

                keyphrase_score = boosted_score
                if final_sort:
                    keyphrase_score = norm_boosted_score

                if keyphrase_score <= keyphrase_quality_score:
                    kp_object.to_remove = True

        ranked_entities_object, ranked_keyphrase_object = self._sort_phrase_dict(
            keyphrase_object=keyphrase_object,
            entities_object=entities_object,
            rank_by=rank_by,
            final_sort=final_sort,
        )

        if final_sort:
            ranked_entities_object, ranked_keyphrase_object = self._slice_phrase_dict(
                entities_object=ranked_entities_object,
                keyphrase_object=ranked_keyphrase_object,
                phrase_limit=phrase_limit,
                entities_limit=entities_limit,
            )

            # Convert List[Objects] to dictionary for uniform sorting
            ranked_entities_dict = {
                ent_obj.originalForm: ent_obj.score.loc
                for ent_obj in ranked_entities_object
            }
            ranked_keyphrase_dict = {
                kp_obj.originalForm: kp_obj.score.loc
                for kp_obj in ranked_keyphrase_object
            }

            final_result_dict = {**ranked_entities_dict, **ranked_keyphrase_dict}

            # Sort chronologically
            sorted_phrase_dict = self.sort_dict_by_value(
                dict_var=final_result_dict, order="asc"
            )

            return sorted_phrase_dict, ranked_entities_object, ranked_keyphrase_object

        else:
            return ranked_entities_object, ranked_keyphrase_object

    def _sort_phrase_dict(
        self,
        keyphrase_object: KeyphraseType,
        entities_object: EntityType,
        final_sort,
        rank_by="boosted_sim",
    ) -> Tuple[EntityType, KeyphraseType]:

        # Sort by rank/scores
        ranked_keyphrase_object = sorted(
            keyphrase_object,
            key=lambda keyphrase: keyphrase.score.boosted_sim,
            reverse=True,
        )
        if rank_by == "pagerank":
            ranked_keyphrase_object = sorted(
                keyphrase_object,
                key=lambda keyphrase: keyphrase.score.pagerank,
                reverse=True,
            )

        # Sort Entities by preference
        ranked_entities_object = sorted(
            entities_object, key=lambda entity: entity.preference
        )

        if final_sort:
            ranked_entities_object = sorted(
                entities_object,
                key=lambda entity: entity.score.norm_boosted_sim,
                reverse=True,
            )

        return ranked_entities_object, ranked_keyphrase_object

    def _slice_phrase_dict(
        self,
        entities_object: EntityType,
        keyphrase_object: KeyphraseType,
        phrase_limit=10,
        entities_limit=5,
    ) -> Tuple[EntityType, KeyphraseType]:

        word_limit = phrase_limit - entities_limit

        filtered_entities_object = [
            ent_obj
            for ent_obj in entities_object
            if ent_obj.related_to_keyphrase is not True and ent_obj.to_remove is False
        ]
        filtered_keyphrase_object = [
            kp_obj for kp_obj in keyphrase_object if kp_obj.to_remove is not True
        ]

        if len(filtered_entities_object) >= entities_limit:
            modified_entity_object = filtered_entities_object[:entities_limit]
            modified_keyphrase_object = filtered_keyphrase_object[:word_limit]

        else:
            num_of_entities = len(filtered_entities_object)
            modified_entity_object = filtered_entities_object[:num_of_entities]
            difference = phrase_limit - num_of_entities
            modified_keyphrase_object = filtered_keyphrase_object[:difference]

        return modified_entity_object, modified_keyphrase_object


"""
We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once.
For example, 2143 is a 4-digit pandigital and is also prime.

What is the largest n-digit pandigital prime that exists?
"""

from itertools import permutations

def isprime(x):
    for i in range(2, x):
        if x % i == 0:
            return False
    return True

listofallpandigitalnumbers = list()
listofallpandigitalprimes = list()
for i in [4,7]:#other n-digit pantigital numbers cannot be prime because they are divisible by 3
    list1 = list(permutations(list(range(1, i + 1))))
    for j in list1:
        number = 0
        for k in j:
            number *= 10
            number += k
        if number%2!=0:
            listofallpandigitalnumbers.append(number)
for i in listofallpandigitalnumbers:
    if isprime(i):
        listofallpandigitalprimes.append(i)
print(max(listofallpandigitalprimes))


import math
import matplotlib.pyplot as plt
from matplotlib import animation
g=9.8
#calculate the trajectory
def DampedDriven(omega0,theta0,q,FD,omegaD,l,T):#q is related to damping force, while FD and omegaD is related to the driving force. the length of the rod is l.T is the interest time.
    dt=0.001
    t=0
    omega,theta = omega0,theta0
    motion=[[]for i in range(3)]
    motion[0].append(omega)
    motion[1].append(theta)
    motion[2].append(t)
    while t<= T:
        omega = omega+(-g*theta/l-q*omega+FD* math.sin(omegaD*t))*dt
        theta = theta+omega*dt
        t = t+dt
        motion[0].append(omega)
        motion[1].append(theta)
        motion[2].append(t)
    return motion

#Fig.1.damped pendulum without driving force
d=DampedDriven(0,0.2,1,0,0,1,10)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label='q=1')
d=DampedDriven(0,0.2,3,0,0,1,10)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label='q=3')
d=DampedDriven(0,0.2,9.8**0.5*2,0,0,1,10)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label='q='+r'$2\sqrt{g/l}$')
d=DampedDriven(0,0.2,10,0,0,1,10)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label='q=10')
d=DampedDriven(0,0.2,30,0,0,1,10)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label='q=30')
plt.xlim(0,10)
plt.grid(True,color='k')
plt.title('Fig.1 Damped Pendulum')
plt.xlabel('Time(s)')
plt.ylabel(r'$\theta$(radius)')
plt.legend()
plt.show()

#Fig.2 damped driven pendulum, also known as linear forced pendulum.(omega0=0,theta0=0.2,q=1,FD=0.4or0.8or2,,omegaD=2,l=1,T=20
d=DampedDriven(0,0.2,1,0.4,1,1,20)#(omega0,theta0,q,FD,omegaD,l,T)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label=r'$F_D=0.4,\Omega_D=1$')
d=DampedDriven(0,0.2,1,0.4,2,1,20)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label=r'$F_D=0.4,\Omega_D=2$')
d=DampedDriven(0,0.2,1,0.8,2,1,20)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label=r'$F_D=0.8,\Omega_D=2$')
d=DampedDriven(0,0.2,1,2,2.0,1,20)
plt.plot(d[2],d[1],linestyle='-',linewidth=1.0,label=r'$F_D=2.0,\Omega_D=2$')
plt.text(13,-0.35,r'$\theta_0=0.2,q=1,l=1$')
plt.xlim(0,20)
plt.title('Fig.2 Damped Driven Pendulum')
plt.xlabel('Time(s)')
plt.ylabel(r'$\theta$(radius)')
plt.grid(True,color='k')
plt.legend()
plt.show()

#animated figure
def findmaximum(a,b):
    if a>b:
        return a
    else:
        return b

A=0
OMEGA=0
# first set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 20), ylim=(-0.20,0.25))
line, = ax.plot([], [], lw=1.5)
plt.title('Damped Driven Pendulum')
plt.xlabel('Time(s)')
plt.ylabel(r'$\theta$(rad)')
plt.grid(True,color='k')
note = ax.text(10,0.1,'',fontsize=12)
note1= ax.text(10,-0.1,'',fontsize=12,color='red')
# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    note.set_text('')
    note1.set_text('')
    return line,note,note1
# animation function.  this is called sequentially
def animate(j):
    global A,OMEGA
    dis=DampedDriven(0,0.2,1,0.2,0.1*j,1,20) #(omega0,theta0,q,FD,omegaD,l,T).dt=0.001,so the length of x,y is 20/dt=20000
    x = dis[2]
    y = dis[1]
    amplitude=reduce(findmaximum,y[10000:])#suppose 10 seconds leter, the motion is almost periodic
    if amplitude>A:
        A,OMEGA=amplitude,0.1*j
    line.set_data(x, y)
    note.set_text(r'$\theta_0=0.2,q=1,F_D=0.2,l=1$'+'\ndriving frequency'+r'$\Omega_D$'+':%s(Hz)'%(0.1*j)+'\namplitude:%s(rad)'%amplitude)
    note1.set_text('resonance'+'\ndriving frequency:%s(Hz)'%OMEGA+'\namplitude:%s(rad)'%A)
    return line,note,note1
anim1=animation.FuncAnimation(fig, animate, init_func=init, frames=130, interval=50)#, blit=True)
#anim1.save('/home/shangguan/computationalphysics_N2013301020076/ex8_ch3.7/try/haha.png')
plt.show()


from functools import partial

import torch
import torch.nn as nn

from .basic import ConvUnit, BaseMultiReturn

# https://github.com/pytorch/vision/blob/main/torchvision/models/resnet.py
# return _resnet(Bottleneck, [3, 4, 6, 3], weights, progress, **kwargs)
# return _resnet(Bottleneck, [3, 8, 36, 3], weights, progress, **kwargs)

class Bottleneck(nn.Module):

    def __init__(self, cin, width, stride, bn):
        super().__init__()
        w = width
        cout = w * 4
        self.u1 = ConvUnit(cin, w, 1, 1, 0, 'relu', bn)
        self.u2 = ConvUnit(w, w, 3, stride, 1, 'relu', bn)
        self.u3 = ConvUnit(w, cout, 1, 1, 0, 'relu', bn)
        if stride > 1 or cin != cout:
            self.downsample = ConvUnit(cin, cout, 1, stride, 0, activ=None, bn=bn)

    def forward(self, x):
        y = x if not hasattr(self, 'downsample') else self.downsample(x)
        x = self.u1(x)
        x = self.u2(x)
        x = self.u3(x, add=y)
        return x

class ResNet(BaseMultiReturn):

    def get_res_layer(self, cin, cout, stride, bn, count):
        blocks = [Bottleneck(cin, cout, stride, bn)]
        blocks.extend([Bottleneck(cout * 4, cout, 1, bn) for _ in range(1, count)])
        return nn.Sequential(*blocks)

    def __init__(self, block_counts, retidx=[1, 2, 3, 4], bn=1e-05, num_freeze=None):
        super().__init__(retidx)
        self.layers = nn.Sequential(
            nn.Sequential(
                ConvUnit(3, 64, k=7, s=2, p=3, activ='relu', bn=bn), # input_size/2
                nn.MaxPool2d(kernel_size=3, stride=2, padding=1)     # input_size/4
            ),
            self.get_res_layer(64, 64, 1, bn, block_counts[0]),   # C2 (input_size/4)
            self.get_res_layer(256, 128, 2, bn, block_counts[1]), # C3 (input_size/8)
            self.get_res_layer(512, 256, 2, bn, block_counts[2]), # C4 (input_size/16)
            self.get_res_layer(1024, 512, 2, bn, block_counts[3]) # C5 (imput_size/32)
        )
        if num_freeze:
            super().freeze(num_freeze)

#def ResNet50(retidx, bn=1e-05):  return ResNet([3, 4, 6, 3], retidx, bn)
#def ResNet152(retidx, bn=1e-05): return ResNet([3, 8, 36, 3], retidx, bn)
ResNet50 = partial(ResNet, block_counts=[3, 4, 6, 3])
ResNet152 = partial(ResNet, block_counts=[3, 8, 36, 3])


import requests
import random
from utils import log_settings
import logging as log
import json

def findPlayMaster(myclient):
	mydb = myclient["resources"]
	pm = mydb["playmaster"]

	elem = pm.find({})
	log.info(elem)
	mylist = elem[0]['list']

	if len(mylist) == 0:
		log.critical("No playmasters found")

	pos = random.randint(0,len(mylist)-1)

	address = {}
	address['hostname'] = mylist[pos]['hostname']
	address['game_port'] = mylist[pos]['game_port']
	address['cmd_port'] = mylist[pos]['cmd_port']

	log.info(address)

	return address

def assignPlay(pair, hostname, port):

	url = 'http://'+str(hostname)+':'+str(port)
	headers = {'Content-Type': 'application/json'}
	data = json.dumps(pair)

	r = requests.post(url = url, data = data, headers=headers)

	return r.status_code


#!/usr/bin/env python3

import numpy as np
import cv2 as cv
import glob
import pickle
import argparse

#program derived from Nico Nielsen at https://raw.githubusercontent.com/niconielsen32/ComputerVision/master/cameraCalibration.py

################ FIND CHESSBOARD CORNERS - OBJECT POINTS AND IMAGE POINTS #############################

# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--path", required=False, default='./',
        help="path to parameter file. default is ./")
ap.add_argument("-v", "--video", required=True, type=str,
        help="file name for video to undistort")
ap.add_argument("-w", "--watch", required=False, default=0, type=int,
        help="whether (1) or not (0) to watch video while writing. Default = 1")
ap.add_argument("-d", "--delay", required=False, default=0, type=float,
        help="delay time between frames for slo-mo")
ap.add_argument("-pre", "--prefix", required=True, type=str,
        help="prefix name for parameters file ending in .p")
ap.add_argument("-o", "--outfile", required=True, type=str,
        help="outfile for video name not including extension")
ap.add_argument ('-fr', '--frameSize', nargs=2, type=int, action = 'append', required=True,
        help="need to specify frame size of video e.g. -c 640 480")

args = vars(ap.parse_args())
delay = args["delay"]
watch = args["watch"]
video = args["video"]
prefix = args["prefix"]
outfile = args["outfile"]
dir_path = args["path"]
frameSize = args["frameSize"]
frameSize = tuple(frameSize[0])

########## READ PICKLE PARAM FILE########################
infile = dir_path + prefix + ".p"
print("Opening infile ", infile)
calib_result_pickle = pickle.load( open(infile, "rb" ) )

cameraMatrix = calib_result_pickle["cameraMatrix"]
dist = calib_result_pickle["dist"]
rvecs = calib_result_pickle["rvecs"]
tvecs = calib_result_pickle["tvecs"]

############## UNDISTORTION #####################################################
def undistort(img, cameraMatrix, dist) :
    h,  w = img.shape[:2]
    newCameraMatrix, roi = cv.getOptimalNewCameraMatrix(cameraMatrix, dist, (w,h), 1, (w,h))

    # Undistort
    dst = cv.undistort(img, cameraMatrix, dist, None, newCameraMatrix)

    ## crop the image to remove black sections of the image
    #x, y, w, h = roi
    #dst = dst[y:y+h, x:x+w]

    ## Undistort with Remapping
    #This is a different algorithm for remapping -- not sure of the resulting differences though
    #mapx, mapy = cv.initUndistortRectifyMap(cameraMatrix, dist, None, newCameraMatrix, (w,h), 5)
    #dst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)

    ## crop the image
    #x, y, w, h = roi
    #dst = dst[y:y+h, x:x+w]
    return(dst)

#*******************
# Open video to undistort and save
cap = cv.VideoCapture(video)

#should check here to make sure video files contains 3 letter extension
vidoutfile = outfile + "_undis.mkv"

out = cv.VideoWriter(vidoutfile,cv.VideoWriter_fourcc('H','2','6','4'), 30, frameSize)

print("Undistorting fish eye video and writing to " + vidoutfile)
_img_shape = None

while(cap.isOpened()):
    succes, frame = cap.read()

    if succes == True:
        if _img_shape == None:
            _img_shape = frame.shape[:2]
        else:
            assert _img_shape == frame.shape[:2], "All images must share the same size."

        # Undistort and rectify images

        uframe = undistort(frame, cameraMatrix, dist)

        #If watch variable is true
        # Show the frames
        if watch == 1:
          cv.imshow("frame", uframe)
          # Hit "q" to close the window
          if cv.waitKey(1) & 0xFF == ord('q'):
              break

        #write the frame to outfile
        out.write(uframe)

    else:
        break
# Release and destroy all windows before termination
cap.release()
cv.destroyAllWindows()


import numpy as np
import pylab

from uxdconverter.ui.controller import Controller
from uxdconverter.plugin.stress.fit import CorrelatedTwoPeakFit
from uxdconverter.plugin.stress.psi_fit import LinearPsiFit
from uxdconverter.measurement import Measurements
from uxdconverter.operation import MultiMerger, MeasurementMerger, ErrorCalculation

from collections import defaultdict
from skipi.function import Function, NullFunction

NAME = 'stress'

class StressAnalysis(object):
    def __init__(self, controller: Controller):
        self._c = controller
        self._fitters = {}

    def group_measurements_by_psi(self, measurements):

        mss = measurements.get_measurements()

        grouped = defaultdict(list)

        for ms in mss:
            grouped[round(ms.get_psi(), 2)].append(ms)

        return grouped

    def merge_group(self, group):
        multi_merge = MultiMerger(MeasurementMerger())
        merged = {}
        for psi, mss in group.items():
            merge = multi_merge.merge(mss)
            merge = ErrorCalculation().manipulate(merge, self._c._settings_controller.get_measurement_context())
            theta, dtheta, counts, dcounts = zip(*merge.get_data())
            theta = np.array(theta)
            dx = Function.to_function(theta, dtheta)
            dy = Function.to_function(theta, dcounts)
            merged[psi] = Function.to_function(theta, counts, dx=dx, dy=dy)

        return merged

    def analyze(self):
        measurements = self._c.measurements # type: uxdconverter.measurement.Measurements
        psi_measurement_dict = self.merge_group(self.group_measurements_by_psi(measurements))

        wavelength_k1 = 0.70931724
        wavelength_k2 = 0.71360728

        psis = []
        thetas = []

        for psi, fctn in psi_measurement_dict.items():
            if not( psi in self._fitters.keys()):
                self._fitters[psi] = CorrelatedTwoPeakFit(fctn, wavelength_k1, wavelength_k2)

            fitter = self._fitters[psi]

            fit = fitter.get_fit()
            fitter.plot()
            print(fit.fit_report(show_correl=False))
            if fit.redchi > 1000:
                continue

            psis.append(psi)
            thetas.append(fitter.get_peak_position())

        pylab.show()
        pylab.figure()
        pylab.xlabel("$sin^2(\psi)$")
        pylab.ylabel("lattice spacing $[\AA]$")

        f = Function.to_function(psis, np.array(thetas))
        trafo_to_lattice = lambda psi, theta: wavelength_k1 / (2 * np.sin(np.deg2rad(theta)))
        dy_traf = lambda psi, theta: np.abs(trafo_to_lattice(psi, theta) / np.tan(np.deg2rad(theta)))
        dy_scale = f.transform(dy_traf)
        dy_traf = lambda psi, dtheta: dtheta * dy_scale(psi)

        f = f.transform(trafo_to_lattice, trafo_dy=dy_traf)

        if f.get_dom().min() < 0:
            fneg = self._to_sin_sqr(f.vremesh((None, 0)))
        else:
            fneg = NullFunction(f.get_dom())

        if f.get_dom().max() > 0:
            fpos = self._to_sin_sqr(f.vremesh((0, None), dstart=-1))
        else:
            fpos = NullFunction(f.get_dom())

        fpos.plot(label='$\psi \geq 0$')
        fneg.plot(label='$\psi < 0$')

        self.analyze_psi(fpos)
        self.analyze_psi(fneg)

        pylab.show()

        return f

    def _to_sin_sqr(self, fctn):
        psi = fctn.get_domain()
        theta = fctn.eval()
        sinsqrd = np.fromiter(map(lambda x: np.sin(np.deg2rad(x)) ** 2, psi), float)
        dy = fctn.dy
        if not dy.is_null():
            dy = Function.to_function(sinsqrd, dy.eval())

        return Function.to_function(sinsqrd, theta, dy=dy)

    def plot_lin_fit(self, fit, function):
        comps = fit.eval_components(x=function.get_domain())
        pylab.plot(function.get_domain(), comps['Lin_'])

    def analyze_psi(self, f):
        if f.is_null():
            return

        fit = LinearPsiFit(f).get_fit()
        print(fit.fit_report(show_correl=False))
        self.plot_lin_fit(fit, f)


"""
Read robustness.json

@author: lukasfischer

"""

import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
import warnings; warnings.simplefilter('ignore')
import yaml
import json
import seaborn as sns
sns.set_style('white')
import os
with open('./loc_settings.yaml', 'r') as f:
    content = yaml.load(f)

def roi_robustness_calculation(fig_datasets, fname, fformat='png', subfolder=[]):

    avg_robustness = []
    avg_robustness_openloop = []

    # run through every dataset and append ROIs to matrices
    for r in figure_datasets:
        print(r)
        mouse = r[0]
        session = r[1]
        ol_session = r[2]

        robustness_short = []
        robustness_short_openloop = []
        robustness_long = []
        robustness_long_openloop = []

        with open(content['figure_output_path'] + mouse+session + os.sep + 'roi_classification.json') as f:
            roi_classification = json.load(f)
        with open(content['figure_output_path'] + mouse+ol_session + os.sep + 'roi_classification.json') as f:
            roi_classification_openloop = json.load(f)

        with open(content['figure_output_path'] + mouse+session + os.sep + 'roi_robustness.json') as f:
            roi_robustness = json.load(f)
        with open(content['figure_output_path'] + mouse+ol_session + os.sep + 'roi_robustness.json') as f:
            roi_robustness_openloop = json.load(f)

        for i in roi_classification['task_engaged_short']:
            robustness_short.append(roi_robustness['robustness_short'][i])
            robustness_short_openloop.append(roi_robustness_openloop['robustness_short'][i])

        for i in roi_classification['task_engaged_long']:
            robustness_long.append(roi_robustness['robustness_long'][i])
            robustness_long_openloop.append(roi_robustness_openloop['robustness_long'][i])

        # robustness_long = roi_robustness['robustness_long']
        # robustness_long_openloop = roi_robustness_openloop['robustness_long']
        avg_robustness.append(np.nanmean(robustness_short))
        avg_robustness.append(np.nanmean(robustness_long))
        avg_robustness_openloop.append(np.nanmean(robustness_short_openloop))
        avg_robustness_openloop.append(np.nanmean(robustness_long_openloop))

    avg_robustness_mean = np.nanmean(avg_robustness)
    avg_robustness_sem = np.nanstd(avg_robustness)/np.sqrt(len(avg_robustness))

    avg_robustness_openloop_mean = np.nanmean(robustness_short_openloop)
    avg_robustness_openloop_sem = np.nanstd(robustness_short_openloop)/np.sqrt(len(robustness_short_openloop))

    print(avg_robustness_mean,avg_robustness_openloop_mean)
    print(stats.ttest_ind(avg_robustness,avg_robustness_openloop))

    fig = plt.figure(figsize=(4,6))
    ax1 = plt.subplot(111)
    ax1.set_xlim([0,3.5])
    ax1.set_ylim([0.2,0.5])
    bar_width = 0.5

    ax1.bar([1-bar_width,2.5-bar_width],[avg_robustness_mean,avg_robustness_openloop_mean], bar_width, color='k', yerr=[avg_robustness_sem,avg_robustness_openloop_sem], ecolor='0.5')

    ax1.set_xticks([0.5,1.7])
    ax1.set_xticklabels(['navigation', 'openloop movie'], rotation=45, fontsize=20)

    ax1.spines['top'].set_visible(False)
    ax1.spines['right'].set_visible(False)

    fig.tight_layout()
    #
    if not os.path.isdir(content['figure_output_path'] + subfolder):
        os.mkdir(content['figure_output_path'] + subfolder)
    fname = content['figure_output_path'] + subfolder + os.sep + fname + '.' + fformat
    print(fname)
    try:
        fig.savefig(fname, format=fformat)
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback,
                              limit=2, file=sys.stdout)

if __name__ == "__main__":

    figure_datasets = [['LF170110_2','Day20170331','Day20170331_openloop',87],['LF170222_1','Day20170615','Day20170615_openloop',96],
    ['LF170420_1','Day20170719','Day20170719_openloop',95],['LF170421_2','Day20170719','Day20170719_openloop',68],['LF170421_2','Day20170720','Day20170720_openloop',45],['LF170613_1','Day201784','Day201784_openloop',77]]

    #figure_datasets = [['LF170110_2','Day20170331','Day20170331_openloop',87]]

    #figure output parameters
    subfolder = 'roi_fractions'
    fname = 'roi_robustness_all'
    fformat = 'svg'

    print('ALL:')
    roi_robustness_calculation(figure_datasets, fname, fformat, subfolder)

    figure_datasets = [['LF170110_2','Day20170331','Day20170331_openloop',87],['LF170613_1','Day201784','Day201784_openloop',77]]

    #figure output parameters
    subfolder = 'roi_fractions'
    fname = 'roi_robustness_l23'
    fformat = 'svg'

    print('L2/3:')
    roi_robustness_calculation(figure_datasets, fname, fformat, subfolder)

    figure_datasets = [['LF170222_1','Day20170615','Day20170615_openloop',96],['LF170420_1','Day20170719','Day20170719_openloop',95],['LF170421_2','Day20170719','Day20170719_openloop',68],['LF170421_2','Day20170720','Day20170720_openloop',45]]

    #figure output parameters
    subfolder = 'roi_fractions'
    fname = 'roi_robustness_l5'
    fformat = 'svg'

    print('5:')
    roi_robustness_calculation(figure_datasets, fname, fformat, subfolder)

    figure_datasets = [['LF170214_1','Day201777','Day201777_openloop',112],['LF170214_1','Day2017714','Day2017714_openloop',165]]

    subfolder = 'roi_fractions'
    fname = 'roi_robustness_V1'
    fformat = 'svg'

    roi_robustness_calculation(figure_datasets, fname, fformat, subfolder)


"""
93. 复原 IP 地址
给定一个只包含数字的字符串，用以表示一个 IP 地址，返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。

有效 IP 地址 正好由四个整数（每个整数位于 0 到 255 之间组成，且不能含有前导 0），整数之间用 '.' 分隔。

例如："0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址，但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。

示例 1：

输入：s = "25525511135"
输出：["255.255.11.135","255.255.111.35"]
示例 2：

输入：s = "0000"
输出：["0.0.0.0"]
示例 3：

输入：s = "1111"
输出：["1.1.1.1"]
示例 4：

输入：s = "010010"
输出：["0.10.0.10","0.100.1.0"]
示例 5：

输入：s = "101023"
输出：["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

提示：

0 <= s.length <= 3000
s 仅由数字组成

tag: 字符串 回溯
"""
from typing import List

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        return self.restore(s, 4)

    def restore(self, s: str, count: int) -> List[str]:
        if len(s) < count:
            return []
        if count < 1:
            return []
        if count == 1:
            if len(s) > 3:
                return []
            if s[0] == '0' and len(s) > 1:
                return []
            if int(s) > 255:
                return []
            return [s]
        ret = []
        tmp = []
        if s[0] == '0':
            tmp.append([s[0], s[1:]])
        else:
            tmp.append([s[:1], s[1:]])
            tmp.append([s[:2], s[2:]])
            if int(s[:3]) <= 255:
                tmp.append([s[:3], s[3:]])
        for head, tail in tmp:
            tail_ret_list = self.restore(tail, count - 1)
            if tail_ret_list:
                for tail_ret in tail_ret_list:
                    ret.append('.'.join([head, tail_ret]))
        return ret

if __name__ == '__main__':
    solution = Solution()
    s = "25525511135"
    print(solution.restoreIpAddresses(s))
    s = "0000"
    print(solution.restoreIpAddresses(s))
    s = "010010"
    print(solution.restoreIpAddresses(s))
    s = "101023"
    print(solution.restoreIpAddresses(s))