#!/usr/bin/env python
# -*- coding: utf-8 -*-
import csv
import tweepy
from config import *
from textblob import TextBlob

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)

def find_tweets(key_word, tweets_quantity_to_get, user_to_avoid, max_id=''):
    tweets_list = []
    tweets_quantity = 0
    counter = 0

    public_tweets = api.search(str(key_word), count=99)
    while tweets_quantity < tweets_quantity_to_get:

        length = len(public_tweets)
        for tweet in public_tweets:
            counter += 1

            if tweet._json['user']['name'] != str(user_to_avoid):
                tweets_list.append({'message_id': tweet._json['id'], 'message_text': tweet.text})
                tweets_quantity += 1

            if counter == length:
                max_id = tweet._json['id']
                counter = 0
                public_tweets = api.search(str(key_word), count=99, max_id=max_id)
                break

    return tweets_list

def make_csv(csv_name, tweets_list):
    csv_name = '{}.csv'.format(str(csv_name))
    with open(csv_name, 'w', encoding='utf-8') as f:
        f = csv.writer(f, delimiter=';', quotechar='"', quoting=csv.QUOTE_MINIMAL)
        for i in tweets_list:
            f.writerow([str(i['message_id']), str(i['message_text'])])


import time

import numpy as np
import numpy.fft as fft
import pandas as pd

import scipy.signal as signal
import scipy.io.wavfile as wav

import simpleaudio as sa
import sounddevice as sd

import matplotlib.pyplot as plt

def get_chirp(signal_length=1.0, impulse_length=0.3, tukey_length=0.05, freq=(200, 4000), sample_rate=48000, method="linear"):
    signal_wave = np.zeros(int(sample_rate * signal_length), np.float32)

    chirp_wave = np.arange(0, impulse_length * sample_rate, dtype=np.float32)
    chirp_wave = chirp_wave / np.max(chirp_wave)
    chirp_wave = signal.chirp(chirp_wave, freq[0], 1, freq[1], phi=-90, method=method)
    #chirp_wave = signal.tukey(len(chirp_wave), alpha=1) * chirp_wave
    chirp_wave = signal.tukey(len(chirp_wave), alpha=(tukey_length * 2)/impulse_length) * chirp_wave

    signal_wave[0:len(chirp_wave)] = chirp_wave

    return signal_wave

def mean_fft(wave, window_size = 4800):

    fft_signal = np.full(window_size, 0, dtype=np.complex)
    counter = 0

    for start in range(0, len(wave) - window_size, int(window_size / 2)):
        temp = fft.fft(signal.tukey(window_size, alpha=0.1) * wave[start:start+window_size])
        fft_signal = fft_signal + temp
        counter += 1

    fft_signal = fft_signal / counter

    return fft_signal

if __name__ == "__main__":
    methods = [
        "linear",
        #"quadratic",
        #"logarithmic",
        #"hyperbolic"
    ]
    lengths = [0.5]

    for length in lengths:
        for method in methods:
            wave = get_chirp(1.5, length, method=method)

            # same
            _, rec1 = wav.read("ISAS Labor/2/2/linear_0.5s_rec.wav")
            _, rec2 = wav.read("ISAS Labor/2/3/linear_0.5s_rec.wav")
            #_, rec3 = wav.read("ISAS Labor/3/3/linear_0.5s_rec.wav")

            # different place
            #_, rec1 = wav.read("ISAS Labor/2/2/linear_0.5s_rec.wav")
            #_, rec2 = wav.read("ISAS Labor/3/1/linear_0.5s_rec.wav")
            #_, rec3 = wav.read("ISAS Labor/3/2/linear_0.5s_rec.wav")

            # different room
            #_, rec1 = wav.read("ISAS Labor/2/2/linear_0.5s_rec.wav")
            #_, rec2 = wav.read("ISAS Raum Daniel Up/2/linear_0.5s_rec.wav")
            #_, rec3 = wav.read("ISAS Flur Gross/1/1/linear_0.5s_rec.wav")

            rec1 = np.array(rec1 / 32767.0, dtype=np.float)
            rec2 = np.array(rec2 / 32767.0, dtype=np.float)
            #rec3 = np.array(rec3 / 32767.0, dtype=np.float)

            audio = fft.ifft(fft.fft(rec2) / fft.fft(wave))
            audio = np.int16(np.absolute(audio)/np.max(np.absolute(audio)) * 32767)
            wav.write("response.wav".format(method, length), 48000, audio)

            plt.plot(np.arange(len(wave)) / 48000.0, wave, alpha=0.75, label="Reference Signal")
            plt.plot(np.arange(len(rec1)) / 48000.0, rec1, alpha=0.75, label="Recorded Signal")
            #plt.plot(np.arange(len(rec2)), rec2, alpha=0.33)
            plt.legend(loc="lower right")
            plt.xlabel("Time (s)")
            plt.ylabel("Signal")
            plt.savefig("signal-{}-{}s.png".format(method, length), dpi=300)
            plt.close()

            fft_wave = mean_fft(wave)
            fft_rec1 = mean_fft(rec1)
            fft_rec2 = mean_fft(rec2)
            #fft_rec3 = mean_fft(rec3)

            #fft_wave = fft.fft(wave)
            #fft_rec1 = fft.fft(rec1)
            #fft_rec2 = fft.fft(rec2)

            fft_response1 = fft_rec1 / fft_wave
            fft_response2 = fft_rec2 / fft_wave
            #fft_response3 = fft_rec3 / fft_wave

            plt.plot((np.arange(len(fft_wave)) - len(fft_wave) / 2.0) * 10, np.absolute(fft_wave), color="blue", alpha=0.33)
            plt.plot((np.arange(len(fft_rec1)) - len(fft_rec1) / 2.0) * 10, np.absolute(fft_rec1), color="orange", alpha=0.33)
            plt.plot((np.arange(len(fft_rec2)) - len(fft_rec2) / 2.0) * 10, np.absolute(fft_rec2), color="green", alpha=0.33)
            plt.savefig("freq-{}-{}s.png".format(method, length))
            #plt.show()
            plt.close()

            plt.scatter((np.arange(len(fft_response1)) - len(fft_response1)/2.0) * 10, np.angle(fft_response1), color="blue", alpha=0.75, s=1)
            plt.scatter((np.arange(len(fft_response2)) - len(fft_response2)/2.0) * 10, np.angle(fft_response2), color="orange", alpha=0.75, s=1)
            #plt.scatter(np.arange(len(fft_recorded)) - len(fft_wave)/2.0, np.angle(fft_recorded) - np.angle(fft_wave), color="red", alpha=0.5)
            plt.xlabel("Frequency (Hz)")
            plt.ylabel("Phase")
            plt.savefig("phase-{}-{}s.png".format(method, length), dpi=300)
            #plt.show()
            plt.close()

            y11 = np.ma.masked_where(np.absolute(fft_response1) <= np.percentile(np.absolute(fft_response1), 99), np.absolute(fft_response1))
            y12 = np.ma.masked_where(np.absolute(fft_response1) >= np.percentile(np.absolute(fft_response1), 99), np.absolute(fft_response1))

            y21 = np.ma.masked_where(np.absolute(fft_response2) <= np.percentile(np.absolute(fft_response2), 99), np.absolute(fft_response2))
            y22 = np.ma.masked_where(np.absolute(fft_response2) >= np.percentile(np.absolute(fft_response2), 99), np.absolute(fft_response2))

            #y31 = np.ma.masked_where(np.absolute(fft_response3) <= np.percentile(np.absolute(fft_response3), 90), np.absolute(fft_response3))
            #y32 = np.ma.masked_where(np.absolute(fft_response3) >= np.percentile(np.absolute(fft_response3), 90), np.absolute(fft_response3))

            x = (np.arange(len(fft_response1)) - len(fft_response1) / 2.0) * 10

            plt.figure(figsize=(12,5))
            plt.plot(x, np.absolute(fft_response1), alpha=0.35, linewidth=2)
            plt.plot(x, np.absolute(fft_response2), alpha=0.35, linewidth=2)
            plt.scatter(x, y11, alpha=1, s=10, label="Highest 1% Reference Signal")
            plt.scatter(x, y21, alpha=1, s=10, label="Highest 1% Same Position")
            #plt.plot(x, y31, alpha=0.66)
            #plt.plot(x, np.real(fft_response1), label="real", color="red", alpha=0.75)
            #plt.plot(x, np.imag(fft_response1), label="imaginary", color="green", alpha=0.75)

            #plt.plot(x, np.absolute(fft_response1), alpha=0.75)
            #plt.plot(x, np.absolute(fft_response2), alpha=0.75)
            #plt.plot((np.arange(len(fft_response12)) - len(fft_response12) / 2.0) * 10, np.absolute(fft_response12), alpha=0.5)
            #plt.plot((np.arange(len(fft_response21)) - len(fft_response21) / 2.0) * 10, np.absolute(fft_response21), alpha=0.5)
            #plt.plot((np.arange(len(fft_response22)) - len(fft_response22) / 2.0) * 10, np.absolute(fft_response22), alpha=0.5)
            #dots = np.where(np.absolute(fft_response1) > np.percentile(np.absolute(fft_response1), 99))[0] - len(fft_response1) / 2
            #plt.scatter(dots, np.full(len(dots), 300), color="black", alpha=0.5)
            #dots = np.where(np.absolute(fft_response2) > np.percentile(np.absolute(fft_response2), 99))[0] - len(fft_response2) / 2
            #plt.scatter(dots, np.full(len(dots), 300), color="red", alpha=0.5)
            #plt.legend(loc="upper left")
            plt.xlim((1500, 17000))
            plt.ylim((0, 500))
            plt.xlabel("Frequency (Hz)")
            plt.ylabel("Magnitude")
            plt.savefig("response-{}-{}s.png".format(method, length), dpi=300)
            #plt.show()
            plt.close()


import pandas as pd
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.metrics import confusion_matrix

def main():
    np.random.seed(0)
    #Get data info
    Xtrain,Xtest,Ytrain,Ytest=get_data_info()
    #V: Weight Matrix from input layer to hidden layer   an: pre synaptic hidden layer   Zn: post synaptic hidden layer
    #W:Weight matrix from hidden layer to output layer   bn: pre synaptic output layer   Yn : post synaptic output layer
    V,W,an,Zn,bn,Yn=neuralmodel(Xtrain,Ytrain)
    evaluationmetrics(Ytrain,Yn)
    ################### RUN TEST DATA ##############################
    print("------------------------------------------------------------")
    print("TEST DATA")
    an,Zn,bn,Yn=forwardpropagation(V,W,Xtest)
    cost=calculate_cost(Yn,Ytest)
    print("Cost of test data is: "+str(cost))
    evaluationmetrics(Ytest,Yn)

def neuralmodel(Xtrain,Ytrain):
    V,W=initialise_parameter(Xtrain)
    iterations=0
    cost = 0
    previous_cost = 0
    while(previous_cost - cost > 0.000001 or iterations <2):
        iterations += 1
        previous_cost = cost
        an,Zn,bn,Yn=forwardpropagation(V,W,Xtrain)
        cost=calculate_cost(Yn,Ytrain)
        # print(cost)
        dW1,DW2=backwardpropagation(V,W,an,Zn,bn,Yn,Xtrain,Ytrain)
        V,W=updategradients(V,W,dW1,DW2)
    print("TRAIN DATA")
    print("Cost of train data is: "+str(cost))
    print("Number of epochs: "+str(iterations))
    return V,W,an,Zn,bn,Yn

def get_data_info():
    df=pd.read_csv("iris.data.csv",header=None)
    df = df[df[4]!="Iris-setosa"]
    df[4] = [0 if x =='Iris-virginica' else 1 for x in df[4]]
    df_norm = (df.iloc[:,1:5] - df.iloc[:,1:5].mean()) / (df.iloc[:,1:5].std())
    # Add bias
    df_norm.insert(0,'bias',1)
    l_col=df_norm.shape[1]
    X_df=df_norm.iloc[:,0:l_col]
    Y_df=df.iloc[:,-1]
    Xtrain_df,Xtest_df,Ytrain_df,Ytest_df=train_test_split(X_df,Y_df,test_size=0.2, shuffle=True, random_state=1)
    Xtrain=np.array(Xtrain_df)
    Xtest=np.array(Xtest_df)
    Ytrain=np.array(Ytrain_df)
    Ytest=np.array(Ytest_df)
    return Xtrain,Xtest,Ytrain,Ytest

def initialise_parameter(Xtrain):
    n_h=5
    n_y=1
    Xtrain=np.transpose(Xtrain)
    n_x=Xtrain.shape[0]
    print("n_x")
    print(n_x)
    V = np.random.randn(n_h, n_x)   *0.01 # random weights between -1 to +1 and n_x contains bias too(already added in the function get_data_info)
    W = np.random.randn(n_y, n_h+1) *0.01
    print(V.shape)
    return V,W

def forwardpropagation(V,W,Xtrain):
    an = np.dot(V,np.transpose(Xtrain))
    Zn=sigmoid(an)

    Zn=np.insert(Zn,0,1,axis=0)
    bn=np.dot(W, Zn)
    Yn = sigmoid(bn)

    return an,Zn,bn,Yn

def sigmoid(Z1):
    return 1/(1+np.exp(-Z1))

def calculate_cost(Yn,Ytrain):
    N=Ytrain.shape[0]
    prob=np.multiply(np.log(Yn), Ytrain) + np.multiply((1 - Ytrain), np.log(1 - Yn)) ## cross entropy  for classification
    cost=-np.sum(prob)/N
    return cost

def backwardpropagation(V,W,an,Zn,bn,Yn,Xtrain,Ytrain):
    error=Yn-Ytrain
    delta_njV=np.dot(np.transpose(W),error)*Zn*(1-Zn)
    DW1=np.dot(delta_njV[1:],Xtrain)
    DW2=np.dot(error,np.transpose(Zn))
    return DW1,DW2

def updategradients(V,W,dW1,DW2):
    alpha =0.01
    V = V - alpha * dW1
    W = W - alpha * DW2
    return V,W

def evaluationmetrics(Actual,predicted):
    Lpredicted=len(predicted[0])
    Actual=Actual.reshape(len(Actual),1)
    predicted[predicted>=0.5]=1
    predicted[predicted<0.5]=0
    predicted=predicted.reshape(Lpredicted,1)
    conf_matrix=confusion_matrix(Actual,predicted, labels=None, sample_weight=None, normalize=None)
    print("Confusion Matrix")
    print(conf_matrix)
    total=sum(sum(conf_matrix))
    sensitivity1 = conf_matrix[0,0]/(conf_matrix[0,0]+conf_matrix[0,1])
    print('Sensitivity : ', sensitivity1 )
    specificity1 = conf_matrix[1,1]/(conf_matrix[1,0]+conf_matrix[1,1])
    print('Specificity : ', specificity1)
    accuracy1=(conf_matrix[0,0]+conf_matrix[1,1])/total
    print ('Accuracy : ', accuracy1*100)

if __name__ == "__main__":
    main()


from django.http.request import split_domain_port
from django.utils.text import slugify
from rest_framework.serializers import (
    ModelSerializer,
    CurrentUserDefault,
    Serializer)
from rest_framework import serializers

from accounts.serializers import SimpleUserReadOnlySerializer
from contacts.models import Person
from .models import (
    FormDocumentResponse,
    FormDocumentTemplate,
    FormDocumentResponseAttachment,
    FixedFormDocument,
    DocumentSignature)

from emails.apis import send_form_resume_link
try:
    # python 2
    from urlparse import urlparse
except ImportError:
    # Python 3
    from urllib.parse import urlparse

class FormDocumentTemplateListSerializer(ModelSerializer):
    created_by = serializers.ReadOnlyField(source='owner.get_full_name')
    status = serializers.ReadOnlyField(source='get_status_display')
    subdomain = serializers.CharField(source='owner.site.domain', read_only=True)
    class Meta:
        model = FormDocumentTemplate
        fields = (
            'id',
            'title',
            'slug',
            'created',
            'created_by',
            'status',
            'subdomain',
        )

class FormDocumentCreateSerializer(ModelSerializer):
    class Meta:
        model = FormDocumentTemplate
        fields = (
            'id',
            'title',
            'slug',
            'status',
            'uploaded_document',
            'form_data',
            'document_mapping',
            'form_config',
            'access_code',
        )
        extra_kwargs = {
            'title': {'write_only': True},
            'uploaded_document': {'write_only': True},
            'status': {'write_only': True},
            'form_data': {'write_only': True},
            'document_mapping': {'write_only': True},
            'form_config': {'write_only': True},
            'access_code': {'write_only': True}
        }

    def validate_slug(self, value):
        value = slugify(value)
        form_template_id = self.initial_data.get('id', None)
        exclude_filters = {}
        if form_template_id:
            exclude_filters = {'pk': self.initial_data['id']}

        if FormDocumentTemplate.objects.exclude(**exclude_filters).filter(slug=value).exists():
            raise serializers.ValidationError('Same URL exists')
        return value

class FormDocumentDetailSerializer(ModelSerializer):
    """
    FormDocumentDetailSerializer used to get details of Form
    """
    uploaded_document = serializers.FileField(write_only=True, required=False)
    assets_urls = serializers.SerializerMethodField()
    is_access_code_protected = serializers.BooleanField(read_only=True)
    form_data = serializers.SerializerMethodField()
    document_mapping = serializers.SerializerMethodField()
    subdomain = serializers.CharField(source='owner.site.domain', read_only=True)

    class Meta:
        model = FormDocumentTemplate
        fields = (
            'id',
            'title',
            'slug',
            'status',
            'uploaded_document',
            'form_data',
            'form_config',
            'document_mapping',
            'assets_urls',
            'is_access_code_protected',
            'subdomain',
        )

    def get_assets_urls(self, instance):
        if self._is_access_code_verified(instance):
            return map(lambda x: {
                # todo: Unit tests
                # This needs absolute uri, as our frontend server and backend server uses different port
                # Without absolute uri, the requests will be send to front-end address while it should
                # be in the backend
                'url': self.context['request'].build_absolute_uri(x.image.url),
                'width': x.cached_image_width,
                'height': x.cached_image_height,
            }, instance.form_assets.all())
        else:
            return None

    def _is_access_code_verified(self, instance):
        if self.instance.is_access_code_protected():
            user = CurrentUserDefault()
            if getattr(user, 'id', None) == instance.owner.id:
                return True
            if self.context['request'].query_params.get('access_code') == instance.access_code:
                return True
            else:
                return False
        else:
            return True

    def get_form_data(self, instance):
        if self._is_access_code_verified(instance):
            return instance.form_data
        return None

    def get_document_mapping(self, instance):
        if self._is_access_code_verified(instance):
            return instance.document_mapping
        return None

class FormDocumentLinkSerializer(Serializer):
    first_name = serializers.CharField(required=False)
    last_name = serializers.CharField(required=False)
    email = serializers.EmailField(write_only=True)

class FixedFormDocumentSerializer(FormDocumentDetailSerializer):
    # Todo: rename to form_id
    id = serializers.IntegerField(source='template.pk')
    uploaded_document = serializers.FileField(write_only=True, required=False)
    assets_urls = serializers.SerializerMethodField()
    slug = serializers.SlugField(read_only=True, source='template.slug')
    is_access_code_protected = serializers.BooleanField(read_only=True)
    form_data = serializers.SerializerMethodField()
    document_mapping = serializers.SerializerMethodField()
    number_of_pages = serializers.IntegerField(source='template.number_of_pages')

    class Meta:
        model = FixedFormDocument
        fields = (
            'id',
            'slug',
            'title',
            'number_of_pages',
            'uploaded_document',
            'form_data',
            'form_config',
            'document_mapping',
            'assets_urls',
            'is_access_code_protected',
        )

    def get_assets_urls(self, instance):
        if self._is_access_code_verified(instance):
            return map(lambda x: {
                # todo: Unit tests
                # This needs absolute uri, as our frontend server and backend server uses different port
                # Without absolute uri, the requests will be send to front-end address while it should
                # be in the backend
                'url': self.context['request'].build_absolute_uri(x.image.url),
                'width': x.cached_image_width,
                'height': x.cached_image_height,
            }, instance.template.form_assets.all())
        else:
            return None

    def _is_access_code_verified(self, instance):
        if self.instance.template.is_access_code_protected():
            user = CurrentUserDefault()
            if getattr(user, 'id', None) == instance.template.owner.id:
                return True
            if self.context['request'].query_params.get('access_code') == instance.template.access_code:
                return True
            else:
                return False
        else:
            return True

    def get_form_data(self, instance):
        if self._is_access_code_verified(instance):
            return instance.form_data
        return None

    def get_document_mapping(self, instance):
        if self._is_access_code_verified(instance):
            return instance.document_mapping
        return None

class FormDocumentResponseAttachmentDetailSerializer(serializers.ModelSerializer):
    file_name = serializers.CharField(read_only=True, source='attachment_file_name')
    file_size = serializers.CharField(read_only=True, source='attachment.size')
    file_url = serializers.CharField(read_only=True, source='attachment.url')

    class Meta:
        model = FormDocumentResponseAttachment
        fields = (
            'file_name',
            'file_size',
            'file_url',
        )

class FormDocumentResponseSerializer(ModelSerializer):
    response_id = serializers.ReadOnlyField(source='pk')
    form_id = serializers.ReadOnlyField(source='form_document.pk')
    answers = serializers.JSONField()
    completion_percent = serializers.SerializerMethodField()
    completed_by_name = serializers.SerializerMethodField()
    type = serializers.SerializerMethodField()
    duration_seconds = serializers.SerializerMethodField()
    contact_name = serializers.SerializerMethodField()
    contact_email = serializers.SerializerMethodField()
    contact_phone = serializers.SerializerMethodField()
    attachments = FormDocumentResponseAttachmentDetailSerializer(many=True, read_only=True)

    class Meta:
        model = FormDocumentResponse
        fields = (
            'response_id',
            'form_id',
            'created',
            'answers',
            'completion_percent',
            'completed_by_name',
            'status',
            'type',
            'duration_seconds',
            'contact_name',
            'contact_email',
            'contact_phone',
            'attachments',
        )

    def get_completion_percent(self, instance):
        cached_form = instance.cached_form
        try:
            return float(instance.get_num_of_completed_questions()) / cached_form.get_num_of_questions()
        except ZeroDivisionError:
            return 0

    def get_completed_by_name(self, instance):
        pass

    def get_type(self, instance):
        pass

    def get_duration_seconds(self, instance):
        pass

    def get_contact_name(self, instance):
        pass

    def get_contact_email(self, instance):
        pass

    def get_contact_phone(self, instance):
        pass

class FormResponseListSerializer(ModelSerializer):
    response_id = serializers.ReadOnlyField(source='pk')
    form_id = serializers.ReadOnlyField(source='form_document.pk')
    form_title = serializers.ReadOnlyField(source='form_document.title')
    completion_percent = serializers.SerializerMethodField()
    completed_by_name = serializers.SerializerMethodField()
    contact_email = serializers.SerializerMethodField()
    contact_phone = serializers.SerializerMethodField()
    status = serializers.SerializerMethodField()
    assignee = SimpleUserReadOnlySerializer()

    class Meta:
        model = FormDocumentResponse
        fields = (
            'response_id',
            'form_id',
            'form_title',
            'created',
            'completion_percent',
            'completed_by_name',
            'status',
            'duration_seconds',
            'contact_email',
            'contact_phone',
            'assignee',
        )

    def get_completion_percent(self, instance):
        cached_form = instance.cached_form
        try:
            return float(instance.get_num_of_completed_questions()) / cached_form.get_num_of_questions()
        except ZeroDivisionError:
            return 0

    def get_completed_by_name(self, instance):
        pass

    def get_contact_email(self, instance):
        pass

    def get_contact_phone(self, instance):
        pass

    def get_status(self, instance):
        return instance.get_status_display()

class FormDocumentResponseAttachmentCreateSerializer(serializers.ModelSerializer):

    response_id = serializers.IntegerField(required=False, write_only=True)
    form_id = serializers.IntegerField(required=False, write_only=True)
    file = serializers.FileField(required=True, write_only=True)
    file_name = serializers.ReadOnlyField(source='attachment_file_name')
    attachment_id = serializers.ReadOnlyField(source='pk')

    class Meta:
        model = FormDocumentResponseAttachment
        fields = (
            'response_id',
            'form_id',
            'file',
            'file_name',
            'attachment_id',
        )

    def validate_file(self, value):
        if len(value.name) > 100:
            raise serializers.ValidationError('File name exceeds 100 characters')
        return value

    def validate(self, attrs):
        form_id = attrs.get('form_id', None)
        response_id = attrs.get('response_id', None)
        if form_id is None and response_id is None:
            raise serializers.ValidationError('At least one of form_id or response_id is required')
        return attrs

    def create(self, validated_data):
        form_response = None
        response_id = validated_data.get('response_id')
        form_id = validated_data.get('form_id')
        if response_id:
            form_response = FormDocumentResponse.objects.get(pk=response_id)
        elif form_id:
            form = FormDocumentTemplate.objects.get(
                pk=form_id)
            cached_form = form.compile_form()
            form_response = cached_form.create_empty_response()
        assert isinstance(form_response, FormDocumentResponse)
        instance =  FormDocumentResponseAttachment.objects.create(
            attachment=validated_data['file'],
            response=form_response
        )
        return instance

class FormDocumentResponseResumeLinkSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True, write_only=True)
    response_id = serializers.IntegerField(required=True, write_only=True)
    form_continue_url = serializers.CharField(required=True)

    def validate(self, data):
        response_id = data.get('response_id')
        form_continue_url = data.get('form_continue_url')
        form_response  = FormDocumentResponse.objects.get(pk=response_id)
        subdomain = form_response.form_document.owner.site.domain
        netloc = urlparse(form_continue_url).netloc
        continue_url_origin, _= split_domain_port(netloc)
        if continue_url_origin == subdomain:
            return data
        else:
            raise serializers.ValidationError("Request origin does not match form continue origin")

    def create(self, validated_data):
        response_id = self.validated_data.get('response_id')
        form_response = FormDocumentResponse.objects.get(pk=response_id)
        form_title = form_response.form_document.title
        send_form_resume_link(
            validated_data['email'],
            validated_data['form_continue_url'],
            form_title
        )
        return validated_data

class FormDocumentSigningEmailVerificationSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True, write_only=True)
    response_id = serializers.IntegerField(required=True, write_only=True)
    code = serializers.CharField(required=False, write_only=True)
    display_name = serializers.CharField(required=False, write_only=True)
    is_verified = serializers.SerializerMethodField()

    def get_is_verified(self, inst):
        email = inst['email']
        response = FormDocumentResponse.objects.get(pk=inst['response_id'])
        signatures = DocumentSignature.objects.filter(
            content_type=response.get_ct(), object_id=response.pk
        )
        persons = [s.person for s in signatures]

        results = filter(lambda x: x.email == email and x.is_email_verified is True, persons)
        return len(results) > 0

    def send_email_verification_code(self):
        email = self.validated_data['email']
        display_name = self.validated_data['display_name']
        response = FormDocumentResponse.objects.get(
            pk=self.validated_data['response_id'])

        signatures = DocumentSignature.objects.filter(
            content_type=response.get_ct(), object_id=response.pk
        )
        person_query = signatures.filter(person__email=email)
        if not person_query.exists():
            person = Person.objects.create(
                email=email,
                display_name=display_name
            )
            signature = DocumentSignature.objects.create(
                content_type=response.get_ct(),
                object_id=response.pk,
                person=person
            )

            signature.save()
            person.send_email_verification_code()
        else:
            person_query.get().person.send_email_verification_code()

        return True

    def verify_email_code(self):
        email = self.validated_data['email']
        code = self.validated_data['code']
        response = FormDocumentResponse.objects.get(
            pk=self.validated_data['response_id'])
        signature = DocumentSignature.objects.filter(
            content_type=response.get_ct(), object_id=response.pk,
            person__email=email
        ).get()

        person = signature.person
        if person.verify_email_verification_code(code):
            person.set_email_verified()


from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.custom_rate_limit_entity import CustomRateLimitEntity

T = TypeVar("T", bound="ClientRateLimitSetting")

@_attrs_define
class ClientRateLimitSetting:
    """
    Attributes:
        mode (int): Rate limit mode.
0: Custom mode. Apply the given rate limit value to the client.
1: Rate
            limit profile mode. Find the corresponding rate limit file with rate limit id and apply it to the client.
        rate_limit_profile_id (Union[Unset, str]): Rate limit profile id. Required when ratelimit mode is 1
        custom_rate_limit (Union[Unset, CustomRateLimitEntity]): Custom configuration rate limit.
    """

    mode: int
    rate_limit_profile_id: Union[Unset, str] = UNSET
    custom_rate_limit: Union[Unset, "CustomRateLimitEntity"] = UNSET
    additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        mode = self.mode
        rate_limit_profile_id = self.rate_limit_profile_id
        custom_rate_limit: Union[Unset, Dict[str, Any]] = UNSET
        if not isinstance(self.custom_rate_limit, Unset):
            custom_rate_limit = self.custom_rate_limit.to_dict()

        field_dict: Dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "mode": mode,
            }
        )
        if rate_limit_profile_id is not UNSET:
            field_dict["rateLimitProfileId"] = rate_limit_profile_id
        if custom_rate_limit is not UNSET:
            field_dict["customRateLimit"] = custom_rate_limit

        return field_dict

    @classmethod
    def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
        from ..models.custom_rate_limit_entity import CustomRateLimitEntity

        d = src_dict.copy()
        mode = d.pop("mode")

        rate_limit_profile_id = d.pop("rateLimitProfileId", UNSET)

        _custom_rate_limit = d.pop("customRateLimit", UNSET)
        custom_rate_limit: Union[Unset, CustomRateLimitEntity]
        if isinstance(_custom_rate_limit, Unset):
            custom_rate_limit = UNSET
        else:
            custom_rate_limit = CustomRateLimitEntity.from_dict(_custom_rate_limit)

        client_rate_limit_setting = cls(
            mode=mode,
            rate_limit_profile_id=rate_limit_profile_id,
            custom_rate_limit=custom_rate_limit,
        )

        client_rate_limit_setting.additional_properties = d
        return client_rate_limit_setting

    @property
    def additional_keys(self) -> List[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties


# -*- coding: utf-8 -*-
"""
=================================================================
Title: test.py
Syntax: python test.py
Description: Test the saved NN model to detect the gestures over a real-time video stream that acquires frames. Press
"a" to stop the gesture recognition process
=================================================================
"""

__author__ = "Aparajit Balaji"

# Importing necessary modules

import cv2
import torch
from PIL import Image
from torchvision import transforms

import warnings
warnings.filterwarnings("ignore")

gesture_names = ["none", "play", "stop", "vol-down", "vol-up"]

# Loading the stored model

dl_model = torch.load("gesture_model.pth")
dl_model.eval()

# Transformations to be applied over the image

img_transform = transforms.Compose([
    transforms.Resize(224),
    transforms.ToTensor(),
    transforms.Normalize(mean = [0.485, 0.456, 0.406], std = [0.229, 0.224, 0.225])])

# Opening the webcam

cap = cv2.VideoCapture(0)

# Code to read the frames

if not cap.isOpened():
    print("Cannot open the webcam! Exiting...")
    exit(0)

while cap.isOpened():

    flag, frame = cap.read()

    # A check to see if the frames are captured

    if not flag:
        print("Frame cannot be received! Exiting...")
        break

    # Check whether the process has been stopped/interrupted

    if cv2.waitKey(50) & 0xFF == ord("a"):
        break

    # Creating a window with a rectangular frame inside to recognise the gestures performed

    cv2.namedWindow("Gesture Recognition", cv2.WINDOW_NORMAL)
    cv2.resizeWindow("Gesture Recognition", (640, 480))

    cv2.rectangle(frame, (75, 75), (300, 300), (255, 255, 255), 3)

    img = frame[75:300, 75:300]

    img = img_transform(Image.fromarray(img))
    img = img.view(1, 3, 224, 224)

    pred = dl_model(img)
    class_pred = int(torch.max(pred.data, 1)[1].numpy())

    cv2.putText(frame, f"The predicted gesture is {gesture_names[class_pred]}", (200, 250), 0, 0.7,
                (255, 255, 0), 2, cv2.LINE_AA)

    cv2.imshow("Gesture Recognition", frame)

cap.release()
cv2.destroyAllWindows()


from google.appengine.ext import bulkload
from google.appengine.api import datastore_types
from google.appengine.ext import search
from google.appengine.ext import db
from google.appengine.api import datastore_entities
from google.appengine.api import datastore

from google.appengine.api.datastore_errors import NeedIndexError

import logging
from flyingsim import models

class AirportLoader(bulkload.Loader):
  def __init__(self):
    # Our 'Person' entity contains a name string and an email
    logging.error("init self")
    self.sequence_nr=1
    bTry=True
    while bTry:
        try:
            lastAirport = models.Airport.all().order('-sequence_nr').fetch(1)
            bTry=False
            if lastAirport:
                self.sequence_nr=lastAirport[0].sequence_nr

        except OSError:
            logging.error("Got OS error")
        except NeedIndexError:
            bTry=False

    bulkload.Loader.__init__(self, 'Airport',
                         [('icao_id', str),
                          ('iata_id', str),
                          ('name', str),
                          ('point',lambda x: db.GeoPt(x.split(":")[0],x.split(":")[1])),
                          ('country_code', str),
                          ('country', str),
                          ])

  def HandleEntity(self, entity):
    logging.error ("HandleEntity %s " ,entity)

    #airport = models.Airport(name=entity['name'],icao_id=entity['icao_id'],iata_id=entity['iata_id'],point=entity['point'])
    #models.Airport(name="Stavanger",icao_id="SVG",point=GeoPt(70.10,71.20))
    #airport.put()
    #event.update(entity)
    countryStr=entity['country']
    if countryStr:
        bTry=True
        while bTry:
            try:
                countryObj = models.Country.gql("Where name=:1",countryStr).get()
                bTry=False
            except OSError:
                logging.error("Got OS error")

        if not countryObj:
            countryObj=models.Country(name=countryStr, code=entity['country_code'])
            #logging.error ("Storing country %s " ,countryStr)
            bTry=True
            while bTry:
                try:
                    countryObj.put()
                    bTry=False
                except OSError:
                    logging.error("Got OS error")

        #logging.error ("country %s " ,countryObj[0])

        #TEMP removed to check performance
        #entity['country']=countryObj.key()

    del entity['country_code']
    point=entity['point']
    entity['pointLat']=int(point.lat)
    entity['pointLon']=int(point.lon)
    entity = search.SearchableEntity(entity)
    #required in order to retrieve more than 1000 elements
    entity['sequence_nr']=self.sequence_nr
    self.sequence_nr= self.sequence_nr +1

    logging.error ("entity right before return %s " ,entity)
    return entity

  #def HandleEntity(self, entity):
  #  event = datastore_entities.Event(entity.title)
  #  event.update(entity)
  #  creator = event['creator']
  #  if creator:
  #    contact = datastore.Query('Contact', {'title': creator}).Get(1)
  #    if not contact:
  #      contact = [datastore_entities.Contact(creator)]
  #      datastore.Put(contact[0])
  #    event['author'] = contact[0].key()
  #  return event

if __name__ == '__main__':
  bulkload.main(AirportLoader())


import pytest
import numpy as np
import os
import sys
import pyCGM_Single.pyCGM_Helpers as pyCGM_Helpers
import pyCGM_Single.pycgmStatic as pycgmStatic
import pyCGM_Single.pycgmIO as pycgmIO
import pyCGM_Single.pycgmCalc as pycgmCalc

rounding_precision = 6

class TestPycgmStaticUtils():
    """
    This class tests the utils functions in pycgmStatic.py:
    rotmat
    getDist
    getStatic
    average
    IADcalculation
    headoffCalc
    staticCalculation
    getankleangle
    norm2d
    norm3d
    normDiv
    matrixmult
    cross
    """
    nan_3d = [np.nan, np.nan, np.nan]
    rand_coor = [np.random.randint(0, 10), np.random.randint(0, 10), np.random.randint(0, 10)]

    @pytest.mark.parametrize(["x", "y", "z", "expected_results"], [
        (0.0, 0.0, 180, [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]),
        (0, 0, 0, [[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
        (90, 0, 0, [[1, 0, 0], [0, 0, -1], [0, 1, 0]]),
        (0, 135, 0, [[-0.70710678, 0, 0.70710678], [0, 1, 0], [-0.70710678, 0, -0.70710678]]),
        (0, 0, -60, [[0.5, 0.8660254, 0], [-0.8660254, 0.5, 0], [0, 0, 1]]),
        (90, 0, 90, [[0, -1, 0], [0, 0, -1], [1, 0, 0]]),
        (0, 150, -30, [[-0.75, -0.4330127, 0.5], [-0.5, 0.8660254, 0], [-0.4330127, -0.25, -0.8660254]]),
        (90, 180, -90, [[0, -1, 0], [0, 0, 1], [-1, 0, 0]])])
    def test_rotmat(self, x, y, z, expected_results):
        """
        This test provides coverage of the rotmat function in pycgmStatic.py, defined as rotmat(x, y, z)
        where x, y, and z are all floats that represent the angle of rotation in a particular dimension.

        This test takes 4 parameters:
        x: angle to be rotated in the x axis
        y: angle to be rotated in the y axis
        z: angle to be rotated in the z axis
        expected_results: the expected rotation matrix from calling rotmat on x, y, and z. This will be a transformation
        matrix that can be used to perform a rotation in the x, y, and z directions at the values inputted.
        """
        result = pycgmStatic.rotmat(x, y, z)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_rotmat_datatypes(self):
        """
        This test provides coverage of the rotmat function in pycgmStatic.py, defined as rotmat(x, y, z)
        where x, y, and z are all floats that represent the angle of rotation in a particular dimension.

        This test checks that the resulting output from calling rotmat is correct when called with ints or floats.
         """
        result_int = pycgmStatic.rotmat(0, 150, -30)
        result_float = pycgmStatic.rotmat(0.0, 150.0, -30.0)
        expected_results = [[-0.75, -0.4330127, 0.5], [-0.5, 0.8660254, 0], [-0.4330127, -0.25, -0.8660254]]

        np.testing.assert_almost_equal(result_int, expected_results, rounding_precision)
        np.testing.assert_almost_equal(result_float, expected_results, rounding_precision)

    @pytest.mark.parametrize(["p0", "p1", "expected_results"], [
        ([0, 0, 0], [1, 0, 0], 1),
        ([0, 5, 0], [0, 0, 0], 5),
        ([0, 0, 0], [0, 0, -8], 8),
        ([0, 0, 0], [0, 3, 4], 5),
        ([8, 0, -3], [0, 0, 0], 8.54400374531753),
        ([0, 4, 0], [0, 0, 2], 4.47213595499958),
        ([1, 0, 3], [0, -2, 8], 5.477225575051661),
        ([3, 3, 0], [3, 0, 3], 4.242640687119285),
        ([7, 0, -4], [7, 0, 2], 6),
        ([7, -2, 5], [1, -4, 9], 7.483314773547883)])
    def test_getDist(self, p0, p1, expected_results):
        """
        This test provides coverage of the getDist function in pycgmStatic.py, defined as getDist(p0, p1)

        This test takes 3 parameters:
        p0: position of first x,y,z coordinate
        p1: position of second x,y,z coordinate
        expected_results: the expected result from calling getDist on p0 and p1. This will be the distance between p0 and p1

        Given the points p0 and p1, the distance between them is defined as:
        .. math::
            distance = \sqrt{(p0_x-p1_x)^2 + (p0_y-p1_y)^2 + (p0_z-p1_z)^2}
        where :math:`p0_x` is the x-coordinate of the point p0

        This unit test ensures that:
        - the distance is measured correctly when some coordinates are the same, all coordinates are the same, and all
        coordinates are different
        - the distance is measured correctly given positive, negative and zero values
        """
        result = pycgmStatic.getDist(p0, p1)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_getDist_datatypes(self):
        """
        This test provides coverage of the getDist function in pycgmStatic.py, defined as getDist(p0, p1)

        This test checks that the resulting output from calling getDist is correct when called with a list of ints,
        a numpy array of ints, a list of floats, and a numpy array of floats.
        """
        p0_int = [7, -2, 5]
        p1_int = [1, -4, 9]
        p0_float = [7.0, -2.0, 5.0]
        p1_float = [1.0, -4.0, 9.0]
        expected_results = 7.483314773547883

        # Check that calling getDist on a list of ints yields the expected results
        result_int_list = pycgmStatic.getDist(p0_int, p1_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling getDist on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.getDist(np.array(p0_int, dtype='int'), np.array(p1_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling getDist on a list of floats yields the expected results
        result_float_list = pycgmStatic.getDist(p0_float, p1_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling getDist on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.getDist(np.array(p0_float, dtype='float'), np.array(p1_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["list", "expected_results"], [
        ([0], 0),
        ([3], 3),
        ([-1], -1),
        ([1, 2], 1.5),
        ([-1, 3], 1),
        ([-3, 1], -1),
        ([-2, 0, 2], 0),
        ([1, 2, 3, 4, 5], 3),
        ([-1, -2, -3, -4, -5], -3),
        ([0.1, 0.2, 0.3, 0.4, 0.5], 0.3)])
    def test_average(self, list, expected_results):
        """
        This test provides coverage of the average function in pycgmStatic.py, defined as average(list)

        This test takes 2 parameters:
        list: list or array of values
        expected_results: the expected result from calling average on list. This will be the average of all the values given in list
        """
        result = pycgmStatic.average(list)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_average_datatypes(self):
        """
        This test provides coverage of the average function in pycgmStatic.py, defined as average(list)

        This test checks that the resulting output from calling average is correct when called with a list of ints,
        a numpy array of ints, a list of floats, and a numpy array of floats.
        """
        list_int = [-1, -2, -3, -4, -5]
        list_float = [-1.0, -2.0, -3.0, -4.0, -5.0]
        expected_results = -3

        # Check that calling average on a list of ints yields the expected results
        result_int_list = pycgmStatic.average(list_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling average on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.average(np.array(list_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling average on a list of floats yields the expected results
        result_float_list = pycgmStatic.average(list_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling average on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.average(np.array(list_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["frame", "expected_results"], [
        ({'RASI': np.array([0, 0, 0]), 'LASI': np.array([0, 0, 0])}, 0),
        ({'RASI': np.array([1, 0, 0]), 'LASI': np.array([0, 0, 0])}, 1),
        ({'RASI': np.array([0, 0, 0]), 'LASI': np.array([2, 0, 0])}, 2),
        ({'RASI': np.array([0, 1, 0]), 'LASI': np.array([0, 1, 0])}, 0),
        ({'RASI': np.array([4, 0, 0]), 'LASI': np.array([2, 0, 0])}, 2),
        ({'RASI': np.array([4, 0, 0]), 'LASI': np.array([-2, 0, 0])}, 6),
        ({'RASI': np.array([0, 2, 1]), 'LASI': np.array([0, 4, 1])}, 2),
        ({'RASI': np.array([-5, 3, 0]), 'LASI': np.array([0, 3, 0])}, 5),
        ({'RASI': np.array([0, 3, -6]), 'LASI': np.array([0, 2, -5])}, 1.4142135623730951),
        ({'RASI': np.array([-6, 4, 0]), 'LASI': np.array([0, 6, -8])}, 10.198039027185569),
        ({'RASI': np.array([7, 2, -6]), 'LASI': np.array([3, -7, 2])}, 12.68857754044952),
        # Testing that when frame is composed of lists of ints
        ({'RASI': [7, 2, -6], 'LASI': [3, -7, 2]}, 12.68857754044952),
        # Testing that when frame is composed of numpy arrays of ints
        ({'RASI': np.array([7, 2, -6], dtype='int'), 'LASI': np.array([3, -7, 2], dtype='int')}, 12.68857754044952),
        # Testing that when frame is composed of lists of floats
        ({'RASI': [7.0, 2.0, -6.0], 'LASI': [3.0, -7.0, 2.0]}, 12.68857754044952),
        # Testing that when frame is composed ofe numpy arrays of floats
        ({'RASI': np.array([7.0, 2.0, -6.0], dtype='float'), 'LASI': np.array([3.0, -7.0, 2.0], dtype='float')}, 12.68857754044952)])
    def test_IADcalculation(self, frame, expected_results):
        """
        This test provides coverage of the IADcalculation function in pycgmStatic.py, defined as IADcalculation(frame)

        This test takes 2 parameters:
        frame: dictionary of marker lists
        expected_results: the expected result from calling IADcalculation on frame. This is the Inter ASIS Distance
        (IAD), or the distance between the two markers RASI and LASI in frame.

        Given the markers RASI and LASI in frame, the Inter ASIS Distance is defined as:
        .. math::
            InterASISDist = \sqrt{(RASI_x-LASI_x)^2 + (RASI_y-LASI_y)^2 + (RASI_z-LASI_z)^2}
        where :math:`RASI_x` is the x-coordinate of the RASI marker in frame

        This unit test ensures that:
        - the distance is measured correctly when some coordinates are the same, all coordinates are the same, and all
        coordinates are different
        - the distance is measured correctly given positive, negative and zero values
        - the resulting output is correct when frame is composed of lists of ints, numpy arrays of ints, lists of
        floats, and numpy arrays of floats.
        """
        result = pycgmStatic.IADcalculation(frame)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    @pytest.mark.parametrize(["xRot", "yRot", "zRot", "expected_results"], [
        (0, 0, 0, [0]),
        # X rotations
        (90, 0, 0, [0]), (30, 0, 0, [0]), (-30, 0, 0, [0]), (120, 0, 0, [0]), (-120, 0, 0, [0]), (180, 0, 0, [0]),
        # Y rotations
        (0, 90, 0, [-1.570796]), (0, 30, 0, [-0.523599]), (0, -30, 0, [0.523599]), (0, 120, 0, [1.047198]), (0, -120, 0, [-1.047198]), (0, 180, 0, [0]),
        # Z rotations
        (0, 0, 90, [0]), (0, 0, 30, [0]), (0, 0, -30, [0]), (0, 0, 120, [0]), (0, 0, -120, [0]), (0, 0, 180, [0]),
        # Multiple Rotations
        (150, 30, 0, [-0.523599]), (45, 0, 60, [0.713724]), (0, 90, 120, [1.570796]), (135, 45, 90, [-0.955317])])
    def test_headoffCalc(self, xRot, yRot, zRot, expected_results):
        """
        This test provides coverage of the headoffCalc function in pycgmStatic.py, defined as headoffCalc(axisP, axisD)

        This test takes 3 parameters:
        axisP: the unit vector of axisP, the position of the proximal axis
        axisD: the unit vector of axisD, the position of the distal axis
        expected_results: the expected result from calling headoffCalc on axisP and axisD. This returns the y-rotation
        from a rotational matrix calculated by matrix multiplication of axisD and the inverse of axisP. This angle is in
        radians, not degrees.

        The y angle is defined as:
        .. math::
            \[ result = \arctan{\frac{M[0][2]}{M[2][2]}} \]
        where M is the rotation matrix produced from multiplying axisD and :math:`axisP^{-1}`

        This unit test ensures that:
        - Rotations in only the x or z direction will return a angle of 0
        - Rotations in only the y direction will return the same angle
        - Rotations in multiple axes will return a value based off of the all the rotations used in the rotation matrix
        """
        # Create axisP as a rotational matrix using the x, y, and z rotations given
        axisP = pycgmStatic.rotmat(xRot, yRot, zRot)
        axisD = pycgmStatic.rotmat(0, 0, 0)
        result = pycgmStatic.headoffCalc(axisP, axisD)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_headoffCalc_datatypes(self):
        """
        This test provides coverage of the headoffCalc function in pycgmStatic.py, defined as headoffCalc(axisP, axisD)

        This test checks that the resulting output from calling headoffCalc is correct when called with a list of ints,
        a numpy array of ints, a list of floats, and a numpy array of floats.
        """
        axisD = pycgmStatic.rotmat(0, 0, 0)
        axisP_floats = pycgmStatic.rotmat(90, 90, 90)
        axisP_ints = [[int(y) for y in x] for x in axisP_floats]
        expected_results = [1.570796]

        # Check that calling headoffCalc on a list of ints yields the expected results
        result_int_list = pycgmStatic.headoffCalc(axisP_ints, axisD)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling headoffCalc on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.headoffCalc(np.array(axisP_ints, dtype='int'), np.array(axisD, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling headoffCalc on a list of floats yields the expected results
        result_float_list = pycgmStatic.headoffCalc(axisP_floats, axisD)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling headoffCalc on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.headoffCalc(np.array(axisP_floats, dtype='float'), np.array(axisD, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["frame", "ankle_JC", "flat_foot", "vsk", "expected_results"], [
        # Test from running sample data
        ({'RTOE': np.array([433.33508301, 354.97229004, 44.27765274]),
          'LTOE': np.array([31.77310181, 331.23657227, 42.15322876]),
          'RHEE': np.array([381.88534546, 148.47607422, 49.99120331]),
          'LHEE': np.array([122.18766785, 138.55477905, 46.29433441])},
         [np.array([397.45738291, 217.50712216, 87.83068433]), np.array([112.28082818, 175.83265027, 80.98477997]),
          [[np.array(rand_coor), np.array([396.73749179, 218.18875543, 87.69979179]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([111.34886681, 175.49163538, 81.10789314]), np.array(rand_coor)]]],
         False,
         {},
         [[-0.015688860223839234, 0.2703999495115947, -0.15237642705642993],
          [0.009550866847196991, 0.20242596489042683, -0.019420801722458948]]),
        # Testing with zeros for all params
        ({'RTOE': np.array([0, 0, 0]), 'LTOE': np.array([0, 0, 0]),
          'RHEE': np.array([0, 0, 0]), 'LHEE': np.array([0, 0, 0])},
         [np.array([0, 0, 0]), np.array([0, 0, 0]),
          [[np.array(rand_coor), np.array([0, 0, 0]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([0, 0, 0]), np.array(rand_coor)]]],
         False,
         {},
         [nan_3d, nan_3d]),
        # Testing with values for frame
        ({'RTOE': np.array([1, -4, -1]), 'LTOE': np.array([1, -1, -5]),
          'RHEE': np.array([1, -7, -4]), 'LHEE': np.array([-6, -5, 1])},
         [np.array([0, 0, 0]), np.array([0, 0, 0]),
          [[np.array(rand_coor), np.array([0, 0, 0]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([0, 0, 0]), np.array(rand_coor)]]],
         False,
         {},
         [nan_3d, nan_3d]),
        # Testing with values for ankle_JC
        ({'RTOE': np.array([0, 0, 0]), 'LTOE': np.array([0, 0, 0]),
          'RHEE': np.array([0, 0, 0]), 'LHEE': np.array([0, 0, 0])},
         [np.array([3, 3, -2]), np.array([5, 9, -4]),
          [[np.array(rand_coor), np.array([6, -9, 9]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([-5, 6, 9]), np.array(rand_coor)]]],
         False,
         {},
         [nan_3d, nan_3d]),
        # Testing with values for vsk
        ({'RTOE': np.array([0, 0, 0]), 'LTOE': np.array([0, 0, 0]),
          'RHEE': np.array([0, 0, 0]), 'LHEE': np.array([0, 0, 0])},
         [np.array([0, 0, 0]), np.array([0, 0, 0]),
          [[np.array(rand_coor), np.array([0, 0, 0]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([0, 0, 0]), np.array(rand_coor)]]],
         False,
         {'RightSoleDelta': 0.64, 'LeftSoleDelta': 0.19},
         [nan_3d, nan_3d]),
        # Testing with values for frame and ankle_JC
        ({'RTOE': np.array([1, -4, -1]), 'LTOE': np.array([1, -1, -5]),
          'RHEE': np.array([1, -7, -4]), 'LHEE': np.array([-6, -5, 1])},
         [np.array([3, 3, -2]), np.array([5, 9, -4]),
          [[np.array(rand_coor), np.array([6, -9, 9]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([-5, 6, 9]), np.array(rand_coor)]]],
         False,
         {},
         [[-0.590828, -0.802097, -0.554384], [0.955226, 0.156745, 0.166848]]),
        # Testing with values for frame, ankle_JC, and vsk
        ({'RTOE': np.array([1, -4, -1]), 'LTOE': np.array([1, -1, -5]),
          'RHEE': np.array([1, -7, -4]), 'LHEE': np.array([-6, -5, 1])},
         [np.array([3, 3, -2]), np.array([5, 9, -4]),
          [[np.array(rand_coor), np.array([6, -9, 9]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([-5, 6, 9]), np.array(rand_coor)]]],
         False,
         {'RightSoleDelta': 0.64, 'LeftSoleDelta': 0.19},
         [[-0.590828, -0.802097, -0.554384], [0.955226, 0.156745, 0.166848]]),
        # Testing with values for frame, ankle_JC, vsk and flat_foot = True
        ({'RTOE': np.array([1, -4, -1]), 'LTOE': np.array([1, -1, -5]),
          'RHEE': np.array([1, -7, -4]), 'LHEE': np.array([-6, -5, 1])},
         [np.array([3, 3, -2]), np.array([5, 9, -4]),
          [[np.array(rand_coor), np.array([6, -9, 9]), np.array(rand_coor)],
           [np.array(rand_coor), np.array([-5, 6, 9]), np.array(rand_coor)]]],
         True,
         {'RightSoleDelta': 0.64, 'LeftSoleDelta': 0.19},
         [[0.041042018208567545, -0.3065439019577841, -0.3106927663413161], [0.39326377295256626, 0.5657243847333632, 0.2128595189127902]]),
        # Testing that when frame and ankle_JC are composed of lists of ints and vsk values are ints
        ({'RTOE': [1, -4, -1], 'LTOE': [1, -1, -5], 'RHEE': [1, -7, -4], 'LHEE': [-6, -5, 1]},
         [[3, 3, -2], [5, 9, -4],
          [[rand_coor, [6, -9, 9], rand_coor],
           [rand_coor, [-5, 6, 9], rand_coor]]],
         True,
         {'RightSoleDelta': 1, 'LeftSoleDelta': -1},
         [[0.041042018208567545, -0.30654390195778408, -0.30110158620693045],
          [00.3932637729525662, 0.56572438473336295, 0.22802611517428609]]),
        # Testing that when frame and ankle_JC are composed of numpy arrays of ints and vsk values are ints
        ({'RTOE': np.array([1, -4, -1], dtype='int'), 'LTOE': np.array([1, -1, -5], dtype='int'),
          'RHEE': np.array([1, -7, -4], dtype='int'), 'LHEE': np.array([-6, -5, 1], dtype='int')},
         [np.array([3, 3, -2], dtype='int'), np.array([5, 9, -4], dtype='int'),
          [np.array([rand_coor, [6, -9, 9], rand_coor], dtype='int'),
           np.array([rand_coor, [-5, 6, 9], rand_coor], dtype='int')]],
         True,
         {'RightSoleDelta': 1, 'LeftSoleDelta': -1},
         [[0.041042018208567545, -0.30654390195778408, -0.30110158620693045],
          [00.3932637729525662, 0.56572438473336295, 0.22802611517428609]]),
        # Testing that when frame and ankle_JC are composed of lists of floats and vsk values are floats
        ({'RTOE': [1.0, -4.0, -1.0], 'LTOE': [1.0, -1.0, -5.0], 'RHEE': [1.0, -7.0, -4.0], 'LHEE': [-6.0, -5.0, 1.0]},
         [[3.0, 3.0, -2.0], [5.0, 9.0, -4.0],
          [[rand_coor, [6.0, -9.0, 9.0], rand_coor],
           [rand_coor, [-5.0, 6.0, 9.0], rand_coor]]],
         True,
         {'RightSoleDelta': 1.0, 'LeftSoleDelta': -1.0},
         [[0.041042018208567545, -0.30654390195778408, -0.30110158620693045],
          [00.3932637729525662, 0.56572438473336295, 0.22802611517428609]]),
        # Testing that when frame and ankle_JC are composed of numpy arrays of floats and vsk values are floats
        ({'RTOE': np.array([1.0, -4.0, -1.0], dtype='float'), 'LTOE': np.array([1.0, -1.0, -5.0], dtype='float'),
          'RHEE': np.array([1.0, -7.0, -4.0], dtype='float'), 'LHEE': np.array([-6.0, -5.0, 1.0], dtype='float')},
         [np.array([3.0, 3.0, -2.0], dtype='float'), np.array([5.0, 9.0, -4.0], dtype='float'),
          [np.array([rand_coor, [6.0, -9.0, 9.0], rand_coor], dtype='float'),
           np.array([rand_coor, [-5.0, 6.0, 9.0], rand_coor], dtype='float')]],
         True,
         {'RightSoleDelta': 1.0, 'LeftSoleDelta': -1.0},
         [[0.041042018208567545, -0.30654390195778408, -0.30110158620693045],
          [00.3932637729525662, 0.56572438473336295, 0.22802611517428609]])])
    def test_staticCalculation(self, frame, ankle_JC, flat_foot, vsk, expected_results):
        """
        This test provides coverage of the staticCalculation function in pycgmStatic.py, defined as staticCalculation(frame, ankle_JC, knee_JC, flat_foot, vsk)

        This test takes 5 parameters:
        frame: dictionary of marker lists
        ankle_JC: array containing the x,y,z axes marker positions of the ankle joint center
        flat_foot: boolean indicating if the feet are flat or not
        vsk: dictionary containing subject measurements from a VSK file
        expected_results: the expected result from calling staticCalculation on frame, ankle_JC, flat_foot, and vsk

        This function first calculates the anatomically incorrect foot axis by calling uncorrect_footaxis. It then
        calculates the anatomically correct foot joint center and axis using either rotaxis_footflat or
        rotaxis_nonfootflat depending on if foot_flat is True or False. It then does some array manipulation and calls
        getankleangle with the anatomically correct and anatomically incorrect axes, once for the left and once for the
        right, to calculate the offset angle between the two axes.

        This test ensures that:
        - Different offset angles are returned depending on whether flat_foot is True or not
        - The resulting output is correct when frame and ankle_JC are composed of lists of ints, numpy arrays of ints,
        lists of floats, and numpy arrays of floats and when the vsk values are ints and floats.
        """
        result = pycgmStatic.staticCalculation(frame, ankle_JC, None, flat_foot, vsk)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    @pytest.mark.parametrize(["xRot", "yRot", "zRot", "expected_results"], [
        (0, 0, 0, [0, 0, 0]),
        # X rotations
        (90, 0, 0, [-1.570796, 0, 0]), (30, 0, 0, [-0.523599, 0, 0]), (-30, 0, 0, [0.523599, 0, 0]),
        (120, 0, 0, [-1.047198, 0, 0]), (-120, 0, 0, [1.047198, 0, 0]), (180, 0, 0, [0, 0, 0]),
        # Y rotations
        (0, 90, 0, [0, -1.570796, 0]), (0, 30, 0, [0, -0.523599, 0]), (0, -30, 0, [0, 0.523599, 0]),
        (0, 120, 0, [0, 1.047198, 0]), (0, -120, 0, [0, -1.047198, 0]), (0, 180, 0, [0, 0, 0]),
        # Z rotations
        (0, 0, 90, [0, 0, -1.570796]), (0, 0, 30, [0, 0, -0.523599]), (0, 0, -30, [0, 0, 0.523599]),
        (0, 0, 120, [0, 0, 1.047198]), (0, 0, -120, [0, 0, -1.047198]), (0, 0, 180, [0, 0, 0]),
        # Multiple Rotations
        (150, 30, 0, [-0.447832,  0.588003,  0.281035]), (45, 0, 60, [-0.785398, -0, -1.047198]),
        (0, 90, 120, [0, -1.570796,  1.047198]), (135, 45, 90, [-0.523599,  0.955317, -0.955317])])
    def test_getankleangle(self, xRot, yRot, zRot, expected_results):
        """
        This test provides coverage of the getankleangle function in pycgmStatic.py, defined as getankleangle(axisP, axisD)

        This test takes 3 parameters:
        axisP: the unit vector of axisP, the position of the proximal axis
        axisD: the unit vector of axisD, the position of the distal axis
        expected_results: the expected result from calling getankleangle on axisP and axisD. This returns the x, y, z angles
        from a XYZ Euler angle calculation from a rotational matrix. This rotational matrix is calculated by matrix
        multiplication of axisD and the inverse of axisP. This angle is in radians, not degrees.

        The x, y, and z angles are defined as:
        .. math::
            \[ x = \arctan{\frac{M[2][1]}{\sqrt{M[2][0]^2 + M[2][2]^2}}} \]
            \[ y = \arctan{\frac{-M[2][0]}{M[2][2]}} \]
            \[ z = \arctan{\frac{-M[0][1]}{M[1][1]}} \]
        where M is the rotation matrix produced from multiplying axisD and :math:`axisP^{-1}`

        This test ensures that:
        - A rotation in one axis will only effect the resulting angle in the corresponding axes
        - A rotation in multiple axes can effect the angles in other axes due to XYZ order
        """
        # Create axisP as a rotatinal matrix using the x, y, and z rotations given
        axisP = pycgmStatic.rotmat(xRot, yRot, zRot)
        axisD = pycgmStatic.rotmat(0, 0, 0)
        result = pycgmStatic.getankleangle(axisP, axisD)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_getankleangle_datatypes(self):
        """
        This test provides coverage of the getankleangle function in pycgmStatic.py, defined as getankleangle(axisP, axisD)

        This test checks that the resulting output from calling getankleangle is correct when called with a list of ints,
        a numpy array of ints, a list of floats, and a numpy array of floats.
        """
        axisD = pycgmStatic.rotmat(0, 0, 0)
        axisP_floats = pycgmStatic.rotmat(90, 90, 90)
        axisP_ints = [[int(y) for y in x] for x in axisP_floats]
        expected_results = [0, -1.570796, 0]

        # Check that calling getankleangle on a list of ints yields the expected results
        result_int_list = pycgmStatic.getankleangle(axisP_ints, axisD)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling getankleangle on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.getankleangle(np.array(axisP_ints, dtype='int'), np.array(axisD, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling getankleangle on a list of floats yields the expected results
        result_float_list = pycgmStatic.getankleangle(axisP_floats, axisD)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling getankleangle on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.getankleangle(np.array(axisP_floats, dtype='float'), np.array(axisD, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["v", "expected_results"], [
        ([-9944.089508486479, -20189.20612828088, 150.42955108569652], 22505.812344655435),
        ([0, 0, 0], 0),
        ([2, 0, 0], 2),
        ([0, 0, -1], 1),
        ([0, 3, 4], 5),
        ([-3, 0, 4], 5),
        ([6, -8, 0], 10),
        ([-5, 0, -12], 13),
        ([1, -1, np.sqrt(2)], 2)])
    def test_norm2d(self, v, expected_results):
        """
        This test provides coverage of the norm2d function in pycgmStatic.py, defined as norm2d(v) where v is a 3D vector.

        This test takes 2 parameters:
        v: 3D vector
        expected_results: the expected result from calling norm2d on v. This will be the value of the normalization of vector v,
        returned as a float.

        Given the vector v, the normalization is defined by:
        normalization = :math:`\sqrt{v_x^2 + v_y^2 + v_z^2}`
        where :math:`v_x` is the x-coordinate of the vector v
        """
        result = pycgmStatic.norm2d(v)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_norm2d_datatypes(self):
        """
        This test provides coverage of the norm2d function in pycgmStatic.py, defined as norm2d(v) where v is a 3D vector.

        This test checks that the resulting output from calling norm2d is correct when called with a list of ints, a
        numpy array of ints, a list of floats, and a numpy array of floats.
        """
        v_int = [6, 0, -8]
        v_float = [6.0, 0, -8.0]
        expected_results = 10

        # Check that calling norm2d on a list of ints yields the expected results
        result_int_list = pycgmStatic.norm2d(v_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling norm2d on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.norm2d(np.array(v_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling norm2d on a list of floats yields the expected results
        result_float_list = pycgmStatic.norm2d(v_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling norm2d on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.norm2d(np.array(v_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["v", "expected_results"], [
        ([-212.5847168, 28.09841919, -4.15808105], np.array(214.47394390603984)),
        ([0, 0, 0], np.array(0)),
        ([2, 0, 0], np.array(2)),
        ([0, 0, -1], np.array(1)),
        ([0, 3, 4], np.array(5)),
        ([-3, 0, 4], np.array(5)),
        ([-6, 8, 0], np.array(10)),
        ([-5, 0, -12], np.array(13)),
        ([1, -1, np.sqrt(2)], np.array(2))])
    def test_norm3d(self, v, expected_results):
        """
        This test provides coverage of the norm3d function in pycgmStatic.py, defined as norm3d(v) where v is a 3D vector.

        This test takes 2 parameters:
        v: 3D vector
        expected_results: the expected result from calling norm3d on v. This will be the normalization of the vector v,
        inside of a numpy array.

        Given the vector v, the normalization is defined by:
        normalization = :math:`\sqrt{v_x^2 + v_y^2 + v_z^2}`
        where :math:`v_x` is the x-coordinate of the vector v
        """
        result = pycgmStatic.norm3d(v)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_norm3d_datatypes(self):
        """
        This test provides coverage of the norm3d function in pycgmStatic.py, defined as norm3d(v) where v is a 3D vector.

        This test checks that the resulting output from calling norm3d is correct when called with a list of ints, a
        numpy array of ints, a list of floats, and a numpy array of floats.
        """
        v_int = [-6, 0, 8]
        v_float = [-6.0, 0, 8.0]
        expected_results = np.array(10)

        # Check that calling norm3d on a list of ints yields the expected results
        result_int_list = pycgmStatic.norm3d(v_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling norm3d on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.norm3d(np.array(v_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling norm3d on a list of floats yields the expected results
        result_float_list = pycgmStatic.norm3d(v_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling norm3d on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.norm3d(np.array(v_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["v", "expected_results"], [
        ([-212.5847168, 28.09841919, -4.15808105], np.array([-4.62150006e-03,  6.10847515e-04, -9.03948887e-05])),
        ([0, 0, 0], np.array([np.nan, np.nan, np.nan])),
        ([2, 0, 0], np.array([0.5, 0, 0])),
        ([0, 0, -1], np.array([0, 0, -1])),
        ([0, 3, 4], np.array([0, 0.12, 0.16])),
        ([-3, 0, 4], np.array([-0.12, 0, 0.16])),
        ([-6, 8, 0], np.array([-0.06, 0.08, 0])),
        ([-5, 0, -12], np.array([-0.0295858, 0, -0.07100592])),
        ([1, -1, np.sqrt(2)], np.array([0.25, -0.25, 0.35355339]))
    ])
    def test_normDiv(self, v, expected_results):
        """
        This test provides coverage of the normDiv function in pycgmStatic.py, defined as normDiv(v) where v is a 3D vector.
        This test takes 2 parameters:
        v: 3D vector
        expected_results: the expected result from calling norm3d on v. This function returns the wrong result. It is supposed
        to return the normalization division, but in the function divides the vector by the normalization twice.

        Given the vector v, the normalization is defined by:
        normalization = :math:`\sqrt{v_x^2 + v_y^2 + v_z^2}`
        where :math:`v_x` is the x-coordinate of the vector v

        The mathematically correct result would be defined by:
        .. math::
            \[ result = [\frac{v_x}{norm}, \frac{v_y}{norm}, \frac{v_z}{norm}] \]

        But this function has an error where it divides the vector twice:
        .. math::
            \[ result = [\frac{v_x}{norm^2}, \frac{v_y}{norm^2}, \frac{v_z}{norm^2}] \]
        """
        result = pycgmStatic.normDiv(v)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_normDiv_datatypes(self):
        """
        This test provides coverage of the normDiv function in pycgmStatic.py, defined as normDiv(v) where v is a 3D vector.

        This test checks that the resulting output from calling normDiv is correct when called with a list of ints, a
        numpy array of ints, a list of floats, and a numpy array of floats.
        """
        v_int = [-6, 0, 8]
        v_float = [-6.0, 0, 8.0]
        expected_results = np.array([-0.06, 0, 0.08])

        # Check that calling normDiv on a list of ints yields the expected results
        result_int_list = pycgmStatic.normDiv(v_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling normDiv on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.normDiv(np.array(v_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling normDiv on a list of floats yields the expected results
        result_float_list = pycgmStatic.normDiv(v_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling normDiv on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.normDiv(np.array(v_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["A", "B", "expected_results"], [
        ([[1, 0, 0], [0, 1.0, -0.0], [0, 0.0, 1.0]], [[1.0, 0, 0.0], [0, 1, 0], [-0.0, 0, 1.0]], [[1.0, 0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]),
        ([[1]], [[1]], [[1]]),
        # Invalid matrix dimensions
        ([[1, 2]], [[1]], [[1]]),
        ([[2], [1]], [[1, 2]], [[2, 4], [1, 2]]),
        # Invalid matrix dimensions
        ([[1, 2, 0], [0, 1, 2]], [[2, 1], [1, 4]], [[4, 9], [1, 4]]),
        ([[11, 12, 13], [14, 15, 16]], [[1, 2], [3, 4], [5, 6]], [[112, 148], [139, 184]]),
        ([[1, 2, 3], [4, 5, 6]], [[7, 8], [9, 10], [11, 12]], [[58, 64], [139, 154]])])
    def test_matrixmult(self, A, B, expected_results):
        """
        This test provides coverage of the matrixmult function in pyCGM.py, defined as matrixmult(a, b)
        where a and b are both lists that represent a matrix to be multiplied.

        This test takes 3 parameters:
        A: a matrix, 2D array format
        B: a matrix, 2D array format
        expected_results: the expected matrix from calling matrixmult on A and B. This is the result of multiplying the two
        matrices A and B. It gives the correct result for multiplying two valid matrices, but still gives a result
        in some cases when the two matrices can't be multiplied. For two matrices to be multiplied, len(A[0]) need to
        be equal to len(B), but this function gives an output even when this isn't true
        """
        result = pycgmStatic.matrixmult(A, B)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_matrixmult_datatypes(self):
        """
        This test provides coverage of the matrixmult function in pycgmStatic.py, defined as matrixmult(a, b)
        where a and b are both lists that represent a matrix to be multiplied.

        This test checks that the resulting output from calling matrixmult is correct when called with a list of ints,
        a numpy array of ints, a list of floats, and a numpy array of floats.
        """
        A_int = [[1, 2, 0], [0, 1, 2]]
        B_int = [[2, 1], [1, 4]]
        A_float = [[1.0, 2.0, 0.0], [0.0, 1.0, 2.0]]
        B_float = [[2.0, 1.0], [1.0, 4.0]]
        expected_results = [[4, 9], [1, 4]]

        # Check that calling matrixmult on a list of ints yields the expected results
        result_int_list = pycgmStatic.matrixmult(A_int, B_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling matrixmult on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.matrixmult(np.array(A_int, dtype='int'), np.array(B_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling matrixmult on a list of floats yields the expected results
        result_float_list = pycgmStatic.matrixmult(A_float, B_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling matrixmult on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.matrixmult(np.array(A_float, dtype='float'), np.array(B_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

    @pytest.mark.parametrize(["a", "b", "expected_results"], [
        ([0.13232936, 0.98562946, -0.10499292], [-0.99119134, 0.13101088, -0.01938735],
         [-0.005353527183234709, 0.10663358915485248, 0.994283972218527]),
        ([0, 0, 0], [0, 0, 0], [0, 0, 0]),
        ([1, 1, 1], [1, 1, 1], [0, 0, 0]),
        ([0, 0, -2], [0, 4, 0], [8, 0, 0]),
        ([0, 0, 4], [-0.5, 0, 0], [0, -2, 0]),
        ([-1.5, 0, 0], [0, 4, 0], [0, 0, -6]),
        ([1, 0, 1], [0, 1, 0], [-1, 0, 1]),
        ([1, 2, 3], [3, 2, 1], [-4, 8, -4]),
        ([-2, 3, 1], [4, -1, 5], [16, 14, -10])])
    def test_cross(self, a, b, expected_results):
        """
        This test provides coverage of the cross function in pycgmStatic.py, defined as cross(a, b) where a and b are both 3D vectors.

        This test takes 3 parameters:
        a: 3D vector
        b: 3D vector
        expected_results: the expected result from calling cross on a and b. This result is the cross product of the vectors
        a and b.
        """
        result = pycgmStatic.cross(a, b)
        np.testing.assert_almost_equal(result, expected_results, rounding_precision)

    def test_cross_datatypes(self):
        """
        This test provides coverage of the cross function in pycgmStatic.py, defined as cross(a, b) where a and b are both 3D vectors.

        This test checks that the resulting output from calling cross is correct when called with a list of ints, a numpy
        array of ints, a list of floats, and a numpy array of floats.
        """
        A_int = [-2, 3, 1]
        A_float = [-2.0, 3.0, 1.0]
        B_int = [4, -1, 5]
        B_float = [4.0, -1.0, 5.0]
        expected_results = [16, 14, -10]

        # Check that calling cross on a list of ints yields the expected results
        result_int_list = pycgmStatic.cross(A_int, B_int)
        np.testing.assert_almost_equal(result_int_list, expected_results, rounding_precision)

        # Check that calling cross on a numpy array of ints yields the expected results
        result_int_nparray = pycgmStatic.cross(np.array(A_int, dtype='int'), np.array(B_int, dtype='int'))
        np.testing.assert_almost_equal(result_int_nparray, expected_results, rounding_precision)

        # Check that calling cross on a list of floats yields the expected results
        result_float_list = pycgmStatic.cross(A_float, B_float)
        np.testing.assert_almost_equal(result_float_list, expected_results, rounding_precision)

        # Check that calling cross on a numpy array of floats yields the expected results
        result_float_nparray = pycgmStatic.cross(np.array(A_float, dtype='float'), np.array(B_float, dtype='float'))
        np.testing.assert_almost_equal(result_float_nparray, expected_results, rounding_precision)

class TestPycgmStaticGetStatic():
    """
    This class tests the getStatic function in pycgmStatic.py:
    """

    @classmethod
    def setup_class(cls):
        """
        Called once for all tests. Loads filenames to be used for testing getStatic() from SampleData/ROM/.
        """
        cwd = os.getcwd()
        if (cwd.split(os.sep)[-1] == "pyCGM_Single"):
            parent = os.path.dirname(cwd)
            os.chdir(parent)
        cls.cwd = os.getcwd()

        dynamic_trial, static_trial, vsk_file, _, _ = pyCGM_Helpers.getfilenames(x=2)
        cls.motion_data = pycgmIO.loadData(os.path.join(cls.cwd, static_trial))
        cls.vsk_data_original = pycgmIO.loadVSK(os.path.join(cls.cwd, vsk_file), dict=False)
        cls.vsk_data = cls.vsk_data_original.copy()

    def setup_method(self):
        """
        Called once before all tests in TestPycgmStaticGetStatic. Resets the vsk_data dictionary to its original state
        as returned from pycgmIO.loadVSK from the file SampleData/ROM/Sample_SM.vsk.
        """
        self.vsk_data = self.vsk_data_original.copy()

    @pytest.mark.parametrize("key", [
        ('LeftLegLength'),
        ('RightLegLength'),
        ('Bodymass'),
        ('LeftAsisTrocanterDistance'),
        ('InterAsisDistance'),
        ('LeftTibialTorsion'),
        ('RightTibialTorsion'),
        ('LeftShoulderOffset'),
        ('RightShoulderOffset'),
        ('LeftElbowWidth'),
        ('RightElbowWidth'),
        ('LeftWristWidth'),
        ('RightWristWidth'),
        ('LeftHandThickness'),
        ('RightHandThickness')])
    def test_getStatic_required_markers(self, key):
        """
        This function tests that an exception is raised when removing given keys from the vsk_data dictionary. All
        of the tested markers are required to exist in the vsk_data dictionary to run pycgmStatic.getStatic(), so
        deleting those keys should raise an exception.
        """
        del self.vsk_data[key]
        with pytest.raises(Exception):
            pycgmStatic.getStatic(self.motion_data, self.vsk_data)

    @pytest.mark.parametrize("key", [
        ('RightKneeWidth'),
        ('LeftKneeWidth'),
        ('RightAnkleWidth'),
        ('LeftAnkleWidth')])
    def test_getStatic_zero_markers(self, key):
        """
        This function tests that when deleting given keys from the vsk_data dictionary, the value in the resulting
        calSM is 0. All of the tested markers are set to 0 if they don't exist in pycgmStatic.getStatic(), so
        deleting these keys should not raise an exception.
        """
        del self.vsk_data[key]
        result = pycgmStatic.getStatic(self.motion_data, self.vsk_data)
        np.testing.assert_almost_equal(result[key], 0, rounding_precision)

    @pytest.mark.parametrize(["key", "keyVal"], [
        ('Bodymass', 95),
        ('InterAsisDistance', 28),
        ('RightKneeWidth', -11),
        ('LeftKneeWidth', 30),
        ('RightAnkleWidth', -41),
        ('LeftAnkleWidth', -5),
        ('LeftTibialTorsion', 28),
        ('RightTibialTorsion', -37),
        ('LeftShoulderOffset', 48),
        ('RightShoulderOffset', 93),
        ('LeftElbowWidth', -10),
        ('RightElbowWidth', -4),
        ('LeftWristWidth', 71),
        ('RightWristWidth', 9),
        ('LeftHandThickness', 15),
        ('RightHandThickness', -21),
        ('InterAsisDistance', -10)])
    def test_getStatic_marker_assignment(self, key, keyVal):
        """
        This function tests that when assigning a value to the given keys from the vsk_data dictionary, the value in
        the resulting calSM corresponds. All of the tested markers are assigned to calSM in pycgmStatic.getStatic()
        """
        self.vsk_data[key] = keyVal
        result = pycgmStatic.getStatic(self.motion_data, self.vsk_data)
        np.testing.assert_almost_equal(result[key], keyVal, rounding_precision)

    @pytest.mark.parametrize(["LeftLegLength", "RightLegLength", "MeanLegLengthExpected"], [
        (0, 0, 0),
        (0, 40, 20),
        (-34, 0, -17),
        (-15, 15, 0),
        (5, 46, 25.5)])
    def test_getStatic_MeanLegLength(self, LeftLegLength, RightLegLength, MeanLegLengthExpected):
        """
        This function tests that pycgmStatic.getStatic() properly calculates calSM['MeanLegLength'] by averaging the
        values in vsk_data['LeftLegLength'] and vsk_data['RightLegLength']
        """
        self.vsk_data['LeftLegLength'] = LeftLegLength
        self.vsk_data['RightLegLength'] = RightLegLength
        result = pycgmStatic.getStatic(self.motion_data, self.vsk_data)
        np.testing.assert_almost_equal(result['MeanLegLength'], MeanLegLengthExpected, rounding_precision)

    @pytest.mark.parametrize(["leftVal", "rightVal", "leftExpected", "rightExpected"], [
        # Test where left and right are 0
        (0, 0, 72.512, 72.512),
        # Test where left is 0
        (85, 0, 72.512, 72.512),
        # Test where right is 0
        (0, 61, 72.512, 72.512),
        # Test where left and right aren't 0
        (85, 61, 85, 61)])
    def test_getStatic_AsisToTrocanterMeasure(self, leftVal, rightVal, leftExpected, rightExpected):
        """
        Tests that if LeftAsisTrocanterDistance or RightAsisTrocanterDistance are 0 in the input vsk dictionary, their
        corresponding values in calSM will be calculated from LeftLegLength and RightLegLength, but if they both have
        values than they will be assigned from the vsk dictionary
        """
        self.vsk_data['LeftAsisTrocanterDistance'] = leftVal
        self.vsk_data['RightAsisTrocanterDistance'] = rightVal
        result = pycgmStatic.getStatic(self.motion_data, self.vsk_data)
        np.testing.assert_almost_equal(result['L_AsisToTrocanterMeasure'], leftExpected, rounding_precision)
        np.testing.assert_almost_equal(result['R_AsisToTrocanterMeasure'], rightExpected, rounding_precision)

    def test_getStatic_InterAsisDistance(self):
        """
        This function tests that when pycgmStatic.getStatic() is called with vsk_data['InterAsisDistance'] is 0, that
        the value for calSM['InterAsisDistance'] is calculated from motionData
        """
        self.vsk_data['InterAsisDistance'] = 0
        result = pycgmStatic.getStatic(self.motion_data, self.vsk_data)
        np.testing.assert_almost_equal(result['InterAsisDistance'], 215.9094195515741, rounding_precision)

    def test_gen(self):
        """
        This function tests that the correct values are returned in calSM['RightStaticRotOff'],
        calSM['RightStaticPlantFlex'], calSM['LeftStaticRotOff'], calSM['LeftStaticPlantFlex'], and calSM['HeadOffset'].
        All of these values are calculated from calls to staticCalculation and staticCalculationHead for every frame
        in motionData
        """
        result = pycgmStatic.getStatic(self.motion_data, self.vsk_data)
        np.testing.assert_almost_equal(result['RightStaticRotOff'], 0.015683497632642041, rounding_precision)
        np.testing.assert_almost_equal(result['RightStaticPlantFlex'], 0.27024179070027576, rounding_precision)
        np.testing.assert_almost_equal(result['LeftStaticRotOff'], 0.0094029102924030206, rounding_precision)
        np.testing.assert_almost_equal(result['LeftStaticPlantFlex'], 0.20251085737834015, rounding_precision)
        np.testing.assert_almost_equal(result['HeadOffset'], 0.25719904693106527, rounding_precision)


import json

from django.core.paginator import Paginator
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404

from .models import Ingredient, IngredientQuantity

def assembly_ingredients(ingredients_names, ingredients_values):
    """ Функция получает два списка (список имен ингридиентов и их колличеством),
        создает объекты в таблице IngredientQuantity если таких нет,
        и возвращает список всех созданных объектов.
    """
    ingredients_list = []
    for n, name in enumerate(ingredients_names):
        try:
           ingredient = Ingredient.objects.get(name=name)
        except Ingredient.DoesNotExist:
            return []
        ingr_quan, created = IngredientQuantity.objects.get_or_create(
            defaults={
                'ingredient': ingredient,
                'quantity': ingredients_values[n],
            },
            ingredient=ingredient,
            quantity=ingredients_values[n]
        )
        ingredients_list.append(ingr_quan)

    return ingredients_list

def get_paginator(request, objs):
    """ Пагинатор для использования в различных представлениях. """
    get_copy = request.GET.copy()
    parameters = get_copy.pop('page', True) and get_copy.urlencode()
    paginator = Paginator(objs, 6)
    last_page = paginator.num_pages
    page_number = request.GET.get('page', 1)
    page = paginator.get_page(page_number)
    is_paginator = page.has_other_pages()
    if page.has_previous():
        prev_url = '?page={}'.format(page.previous_page_number())
    else:
        prev_url = ''

    if page.has_next():
        next_url = '?page={}'.format(page.next_page_number())
    else:
        next_url = ''

    return is_paginator, prev_url, next_url, parameters, last_page, page

def get_id_recipe(request):
    """ Функция получает id рецепта из тела запроса. """
    body = json.loads(request.body)
    return  body.get('id')

def change_ingredients(ingredients_list, ingredients, recipe):
    """ Функция меняет список ингридиентов рецепта, если он был изменен. """
    if ingredients_list != list(ingredients) and ingredients_list:
        ingredients.delete()
        recipe.ingredients.add(*ingredients_list)

def get_author(request, author):
    """ Функция возвращает автора для создания объекта подписки """
    if author is None:
        recipe_id = get_id_recipe(request)
        author = get_object_or_404(Recipe.objects.select_related('author'), id=recipe_id).author
    else:
        author = get_object_or_404(User, username=author)

    return author


import json
import urllib
from collections import defaultdict

class Argument:

    @classmethod
    def get(cls, cursor, tbl_ext, fid, args_method, func_ep, payload):

        query = "SELECT * FROM `{}func_arg` WHERE".format(tbl_ext)
        query = "{} published=1 AND func_id='{}'".format(query, fid)
        cursor.execute(query)
        result = cursor.fetchall()

        errors = []
        arguments = defaultdict()
        if result is not None:
            for row in result:
                arg_key      = row['arg_key']
                arg_type     = row['arg_type']
                req_arg_key  = row['req_arg_key']
                req_arg_type = row['req_arg_type']
                is_required  = row['is_required']

                if arg_key not in payload and is_required == 1:
                    errors.append({"missingValue": "Field or value is missing for {}.".format(arg_key)})
                elif arg_key in payload:
                    payload_val  = payload[arg_key]
                    payload_type = type(payload_val).__name__
                    if arg_type == payload_type:
                        get_arg = getattr(cls, "type_"+req_arg_type)(payload_val, is_required)
                        if get_arg is not None:
                            arguments[req_arg_key] = get_arg
                        else:
                            errors.append({"missingValue": "Field or value is missing for {}.".format(arg_key)})
                    else:
                        errors.append({"missingType": "Invalid data type for {}.".format(arg_key)})
            if len(errors) < 1:
                arguments = getattr(cls, "ep_"+args_method)(func_ep, arguments)
        else:
            errors.append({"internalError": "Error in Argument"})
        if len(errors) > 0:
            arguments['errors'] = errors

        return arguments

    @classmethod
    def type_comma(cls, data, required):
        return None if required==1 and len(data)<1 else ",".join(data)

    @classmethod
    def type_list(cls, data, required):
        return None if required==1 and len(data)<1 else data

    @classmethod
    def type_dict(cls, data, required):
        return None if required==1 and len(data)<1 else json.loads(data)

    @classmethod
    def type_integer(cls, data, required):
        return None if required==1 and len(data)<1 else int(data)

    @classmethod
    def type_float(cls, data, required):
        return None if required==1 and len(data)<1 else float(data)

    @classmethod
    def type_bool(cls, data, required):
        return None if required==1 and len(data)<1 else bool(data)

    @classmethod
    def type_str(cls, data, required):
        return None if required==1 and len(data)<1 else str(data)

    @classmethod
    def ep_POST(cls, func_ep, args):
        if func_ep.find("=") > 0:
            new_arg = func_ep.split("=")
            args.update({new_arg[0]: new_arg[1]})
            func_ep = ""
        return {"func_ep": func_ep, "args": args}

    @classmethod
    def ep_GET(cls, func_ep, args):
        ep = "{}&{}".format(func_ep, urllib.parse.urlencode(args))
        return {"func_ep": ep, "args": None}