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

import operator
import warnings

from collections import namedtuple
from warnings import warn

import numpy as np

__copyright__ = 'Copyright 2017'
__author__ = u'Bsc. Manuel Aguado Martínez'

Stats = namedtuple('Stats', [

    # Rate curves
    'thrs',  # Thresholds
    'fmr',  # False match rates
    'fnmr',  # False non-match rates
    'auc',  # Area under the ROC curve
    'j_index',  # Youden's index
    'j_index_th',  # Youden's index threshold
    'mccoef',  # Matthew correlation coefficient
    'mccoef_th',  # Matthew correlation coefficient threshold

    # Operation points
    'fmr0',  # Zero false math rate
    'fmr1000',  # 1000 false match rate
    'fmr100',  # 100 false match rate
    'fmr20',  # 20 false match rate
    'fmr10',  # 10 false match rate
    'fnmr0',  # 0 false non-match rate

    # Operation points thresholds
    'fmr0_th',  # Zero false math rate threshold
    'fmr1000_th',  # 1000 false match rate threshold
    'fmr100_th',  # 100 false match rate threshold
    'fmr20_th',  # 20 false match rate threshold
    'fmr10_th',  # 10 false match rate threshold
    'fnmr0_th',  # 0 false non-match rate threshold

    # Scores distributions
    'gen_scores',  # Genuine scores
    'imp_scores',  # Impostor scores
    'gmean',  # Genuine scores mean
    'gstd',  # Genuine scores standard deviation
    'imean',  # Impostor scores mean
    'istd',  # Impostor scores standard deviation
    'decidability',  # Decidability score

    # Values of EER
    'eer',  # Equal error rate
    'eer_low',  # Equal error rate (low)
    'eer_high',  # Equal error rate (high)
    'eer_th'  # The threshold for which eer_low and eer_high were calculated
])

def calculate_roc_hist(gscores, iscores, ds_scores=False, rates=True):
    """Calculates FMR, FNMR for impostor scores in histogram format

    @param gscores: Genuine matching scores
    @type gscores: list
    @param iscores: Impostor matching scores
    @type giscores: list
    @param ds_scores: Indicates whether input scores are
        dissimilarity scores
    @type ds_scores: bool
    @param rates: Indicates whether to return error rates instead
        of error values
    @type rates: bool

    @return: (thresholds, FMR, FNMR) or (thresholds, FM, FNM)
    @rtype: tuple
    """
    match_thr = 0
    maximum_thr = max([max(gscores), len(gscores),
                       max(iscores), len(iscores)])

    gscores_number = float(len(gscores))
    iscores_number = float(sum(iscores))
    iscores = np.cumsum(iscores)

    thresholds = []
    fm_rates = []
    fnm_rates = []

    while match_thr <= maximum_thr:
        if 0 < match_thr < len(iscores):
            if ds_scores:
                false_match = iscores[match_thr - 1]
            else:
                false_match = iscores_number - iscores[match_thr - 1]
        elif match_thr == 0:
            if ds_scores:
                false_match = 0
            else:
                false_match = iscores_number  # Accepting everyone
        else:
            if ds_scores:
                false_match = iscores_number
            else:
                false_match = 0

        fm_rates.append(false_match)

        # List convertion for Python3 compatibility
        if ds_scores:
            fnm = len(list(filter(lambda s: s > match_thr, gscores)))
        else:
            fnm = len(list(filter(lambda s: s < match_thr, gscores)))
        fnm_rates.append(fnm)

        thresholds.append(match_thr)
        match_thr += 1

    if rates:
        fm_rates = np.array(fm_rates) / iscores_number
        fnm_rates = np.array(fnm_rates) / gscores_number
    else:
        fm_rates = np.array(fm_rates)
        fnm_rates = np.array(fnm_rates)

    return thresholds, fm_rates, fnm_rates

def calculate_roc(gscores, iscores, ds_scores=False, rates=True):
    """Calculates FMR, FNMR

    @param gscores: Genuine matching scores
    @type gscores: Union[list, ndarray]
    @param iscores: Impostor matching scores
    @type giscores: Union[list, ndarray]
    @param ds_scores: Indicates whether input scores are
        dissimilarity scores
    @type ds_scores: bool
    @param rates: Indicates whether to return error rates instead
        of error values
    @type rates: bool

    @return: (thresholds, FMR, FNMR) or (thresholds, FM, FNM)
    @rtype: tuple
    """
    if isinstance(gscores, list):
        gscores = np.array(gscores, dtype=np.float64)

    if isinstance(iscores, list):
        iscores = np.array(iscores, dtype=np.float64)

    if gscores.dtype == np.int:
        gscores = np.float64(gscores)

    if iscores.dtype == np.int:
        iscores = np.float64(iscores)

    if ds_scores:
        gscores = gscores * -1
        iscores = iscores * -1

    gscores_number = len(gscores)
    iscores_number = len(iscores)

    # Labeling genuine scores as 1 and impostor scores as 0
    gscores = zip(gscores, [1] * gscores_number)
    iscores = zip(iscores, [0] * iscores_number)

    # Python3 compatibility
    gscores = list(gscores)
    iscores = list(iscores)

    # Stacking scores
    scores = np.array(sorted(gscores + iscores, key=operator.itemgetter(0)))
    cumul = np.cumsum(scores[:, 1])

    # Grouping scores
    thresholds, u_indices = np.unique(scores[:, 0], return_index=True)

    # Calculating FNM and FM distributions
    fnm = cumul[u_indices] - scores[u_indices][:, 1]  # rejecting s < t
    fm = iscores_number - (u_indices - fnm)

    # Calculating FMR and FNMR
    if rates:
        fnm_rates = fnm / gscores_number
        fm_rates = fm / iscores_number
    else:
        fnm_rates = fnm
        fm_rates = fm

    if ds_scores:
        return thresholds * -1, fm_rates, fnm_rates

    return thresholds, fm_rates, fnm_rates

def calculate_roc_auc(fmr, fnmr):
    """Calculates the area under a ROC curve

    @param fmr: False Match Rates
    @type fmr: ndarray
    @param fnmr: False Non-Match Rates
    @type fnmr: ndarray

    @returns: Area under the ROC curve
    @rtype: float
    """
    x1 = fmr[:-1]
    x2 = fmr[1:]

    tpr = 1 - fnmr
    y1 = tpr[:-1]
    y2 = tpr[1:]

    auc = ((x1 - x2) * (y1 + (y2 - y1) / 2)).sum()

    if auc < 0.5:
        warn("It is possible that you had set the wrong score"
             " type. Please consider reviewing if you are using"
             " dissimilarity or similarity scores")

    return auc

def get_fnmr_op(fmr, fnmr, op):
    """Returns the value of the given FNMR operating point

    Definition:
    ZeroFNMR: is defined as the lowest FMR at which no non-false matches occur.

    Others FNMR operating points are defined in a similar way.

    @param fmr: False Match Rates
    @type fmr: ndarray
    @param fnmr: False Non-Match Rates
    @type fnmr: ndarray
    @param op: Operating point
    @type op: float

    @returns: Index, The lowest FMR at which the probability of FNMR == op
    @rtype: float
    """
    temp = abs(fnmr - op)
    min_val = np.min(temp)
    index = np.where(temp == min_val)[0][-1]
    return index, fmr[index]

def get_fmr_op(fmr, fnmr, op):
    """Returns the value of the given FMR operating point

    Definition:
    ZeroFMR: is defined as the lowest FNMR at which no false matches occur.

    Others FMR operating points are defined in a similar way.

    @param fmr: False Match Rates
    @type fmr: ndarray
    @param fnmr: False Non-Match Rates
    @type fnmr: ndarray
    @param op: Operating point
    @type op: float

    @returns: Index, The lowest FNMR at which the probability of FMR == op
    @rtype: float
    """
    index = np.argmin(abs(fmr - op))
    return index, fnmr[index]

def get_eer_values(fmr, fnmr):
    """Returns the value of the Equal Error Rate

    Equal Error Rate (EER): is the point where FNMR(t) = FMR(t).
    In practice the score distribution are not continuous so and interval
    is returned instead. The EER value will be set as the midpoint of
    this interval.

    The interval will be defined as:
    [EERlow, EERhigh] = min(fnmr[t], fmr[t]), max(fnmr[t], fmr[t])
    where t = argmin(abs(fnmr - fmr))

    The EER value is computed as (EERlow + EERhigh) / 2

    Reference:
    Maio, D., Maltoni, D., Cappelli, R., Wayman, J. L., & Jain, A. K. (2002).
    FVC2000: Fingerprint verification competition. IEEE Transactions on
    Pattern Analysis and Machine Intelligence, 24(3), 402-412.

    @param fmr: False Match Rates (FMR)
    @type fmr: ndarray
    @param fnmr: False Non-Match Rates (FNMR)
    @type fnmr: ndarray
    @param op: Operation point
    @type op: float

    @returns: index for EERlow and EERhigh, EERlow, EERhigh, EER
    @rtype: tuple
    """
    diff = fmr - fnmr
    t2 = np.where(diff <= 0)[0]

    if len(t2) > 0:
        t2 = t2[0]
    else:
        warnings.warn('It seems that the FMR and FNMR curves'
                      ' do not intersect each other. Did you mean'
                      ' to use dissimilarity scores?', RuntimeWarning)
        return 0, 1, 1, 1

    t1 = t2 - 1 if diff[t2] != 0 and t2 != 0 else t2

    if fmr[t1] + fnmr[t1] <= fmr[t2] + fnmr[t2]:
        return t1, fnmr[t1], fmr[t1], (fnmr[t1] + fmr[t1]) / 2
    else:
        return t2, fmr[t2], fnmr[t2], (fnmr[t2] + fmr[t2]) / 2

    # index = np.argmin(abs(fmr - fnmr))
    # eer = np.abs(fnmr[index] + fmr[index]) / 2.0
    # return min(fnmr[index], fmr[index]), max(fnmr[index], fmr[index]), eer

def get_decidability_value(gmean, gstd, imean, istd):
    """ The decidability score (d') or decision-making power used in NICE:II
    evauation protocol for iris, it is a measure of the separation between
    genuine and impostor distributions. Higher d' values indicate better
    separation. It is also called the sensitivity index.

    @param gmean: The mean value of the genuine scores
    @type gmean: float
    @param imean: The mean value of the impostor scores
    @type imean: float
    @param gstd: The standard deviation value of the genuine scores
    @type gstd: float
    @param istd: The standard deviation value of the impostor scores
    @type istd: float

    @returns: The decidability value
    @rtype: float
    """
    if gstd == 0 and istd == 0:
        return 1
    return abs(gmean - imean) / np.sqrt(0.5 * (gstd ** 2 + istd ** 2))

def get_youden_index(fmr, fnmr):
    """Computes the Youden's index and the corresponding threshold

    Reference:
    Youden, W. J. (1950). "Index of rating diagnostic tests". Cancer. 3: 32-35

    @param fmr: False Match Rates (FMR)
    @type fmr: ndarray
    @param fnmr: False Non-Match Rates (FNMR)
    @type fnmr: ndarray

    @returns: Youden's Index, threshold
    @rtype: tuple
    """
    # J = sensitivity + specificity -1
    # sensitivity = 1 - fnmr
    # specificity = 1 - fmr
    # J = 1 - fnmr + 1 - fmr - 1
    # J = 1 - fnmr - fmr
    j = 1 - fnmr - fmr
    th = np.argmax(j)
    return j[th], th

def get_matthews_ccoef(fm, fnm, gnumber, inumber):
    """Estimate the maximum Matthews Correlation Coefficient
    given the values of false match (false positives) and false
    non-match (false negatives) for all possible thresholds

    @param fm: False Positives for all possible thresholds
    @type fm: ndarray
    @param fnm: False Negatives for all possible thresholds
    @type fnm: ndarray
    @param gnumber: The number of positive samples
    @type gnumber: int
    @param inumber: The number of negative samples
    @type inumber: int

    @returns: (Matthews Correlation Coefficient, threshold)
    @rtype: tuple
    """
    tn = inumber - fm
    tp = gnumber - fnm

    numerator = tp * tn - fm * fnm

    # Calculating sqrt for each element instead of only once to
    # all denominator to avoid overflow in some cases
    denominator_a = np.sqrt((tp + fm)) * np.sqrt((tp + fnm))
    denominator_b = np.sqrt((tn + fm)) * np.sqrt((tn + fnm))
    denominator = denominator_a * denominator_b

    denominator[denominator == 0] = 1

    all_mcc = numerator / denominator

    th = np.argmax(all_mcc)
    return all_mcc[th], th


import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

url = "http://[2605:fd00:4:1001:f816:3eff:feb2:3536]/"

class TestInvitationReceived(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()

    def test_invitation_received(self):
        driver = self.driver
        # login first
        driver.get(url)
        # enter Username credential
        elem1 = driver.find_element_by_xpath("/html/body/div/div/div/div/div[2]/div[2]/div/div/div[2]/div/input")
        assert elem1 != None
        elem1.send_keys("zuhao")
        elem1.send_keys(Keys.ENTER)
        # enter Password credential
        elem2 = driver.find_element_by_xpath("/html/body/div/div/div/div/div[2]/div[2]/div/div/div[3]/div/input")
        assert elem2 != None
        elem2.send_keys("5201314mwxely")
        elem2.send_keys(Keys.ENTER)
        # click Log in button
        elem3 = driver.find_element_by_xpath("/html/body/div/div/div/div/div[2]/div[2]/div/div/button/span[1]")
        assert elem3 != None
        elem3.click()
        # wait for redirection to the homepage
        driver.implicitly_wait(10)
        # go to invitation_received component
        elem4 = driver.find_element_by_xpath("/html/body/div/div/div[2]/div[1]/div/div[3]/a")
        elem4.click()
        # check if received invitations exist in the table
        elem5 = driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div[2]/div/div[2]/div[2]/div/div/div/table/tbody/tr[1]/td[1]")
        assert elem5 != None
        assert elem5.text != None   # check by Invitation Id
        # check Accept button
        # elem6 = driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div[2]/div/div[2]/div[2]/div/div/div/table/tbody/tr[1]/td[5]/div/button[1]/span[1]")
        # assert elem6 != None
        # assert elem6.text == "Accept"
        # check Decline button
        # elem7 = driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div[2]/div/div[2]/div[2]/div/div/div/table/tbody/tr[1]/td[5]/div/button[2]/span[1]")
        # assert elem7 != None
        # assert elem7.text == "Decline"

    def tearDown(self):
        self.driver.close()

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


import os
from os import listdir
from multiprocessing import Process

import logging
from wand.image import Image

"""

script for sequential editing the pictures

@author: Daniel Schnurpfeil
@version: 1.1.0
"""

class Edith(Process):

    def __init__(self, style, dir_size=None):
        super().__init__()
        self.style = style
        self.dir_size = len(listdir("../../original_data/" + self.style))

    def run(self) -> None:
        super().run()
        # bez pripony
        folder = self.style
        purpose = ['train', 'val']

        #
        path = '../../ready_data/' + purpose[0] + '/' + folder + '/'
        logging.info(folder + " start")
        directory = listdir("../../original_data/" + folder)
        for i in range(int(self.dir_size * 0.80)):
            process_img("../../original_data/" + folder + "/" + directory[i], path, directory[i])

            # logging.info(self.style + " current picture: " + i.__str__())

        path = '../../ready_data/' + purpose[1] + '/' + folder + '/'
        logging.info(folder + " val")
        for i in range(
                int(self.dir_size * 0.80),
                int(self.dir_size)):
            process_img("../../original_data/" + folder + "/" + directory[i], path, directory[i])
            # logging.info(self.style + " current picture: " + i.__str__())
        logging.info(folder + " end")

def process_img(img, path, file_name):
    # rotated_names = []
    # all_names = []
    img = img.replace(".jpg", "")
    path += file_name.replace(".jpg", "")

    new_names = [copy(img, path),
                 mirror(img, path),
                 blur(img, path),
                 noise(img, path)
                 ]

    # for name in new_names:
    #     rotated_names.append(rotate_left(name, name))
    #     rotated_names.append(rotate_right(name, name))

    # for name in rotated_names:
    #     all_names.append(crop_left(name, name))
    #     all_names.append(crop_right(name, name))

    # for name in all_names:
    #     prepare(name, name)

    # for name in rotated_names:
    #     prepare(name, name)

    for name in new_names:
        prepare(name, name)

def prepare(filename, destination):
    """

    :param destination: output
    :param filename: input
    :return: new name
    """
    with Image(filename=filename + ".jpg") as i:
        i.resize(500, 500)  # 400 - 600 px strany
        i.save(filename=destination + ".jpg")

def copy(filename, destination):
    name = str(destination)
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            i.save(filename=name + ".jpg")

    return name

def rotate_right(filename, destination):
    """
    rotate_right by 10 degrees
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_rot_right")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            i.rotate(10)

            width, heigth = aspect(float(img.width), float(img.height),
                                   float(i.width), float(i.height))
            # print(width, heigth)

            i.crop(width=int(width), height=int(heigth), gravity='center')
            i.save(filename=name + ".jpg")
    return name

def rotate_left(filename, destination):
    """
    rotate_left by 10 degrees
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_rot_left")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            i.rotate(-10)

            width, heigth = aspect(float(img.width), float(img.height),
                                   float(i.width), float(i.height))

            i.crop(width=int(width), height=int(heigth), gravity='center')
            i.save(filename=name + ".jpg")
    return name

def aspect(width, height, aspect_x, aspect_y):
    """
    calculates picture to crops to fit after rotate
    :param width: ...
    :param height: ...
    :param aspect_x: rotated width
    :param aspect_y: rotated height
    :return: new width, new height
    """
    old_ratio = width / height
    new_ratio = aspect_x / aspect_y
    if old_ratio < 1:
        old_ratio = height / width
        new_ratio = aspect_y / aspect_x
    reduction_x = aspect_x - width
    reduction_y = aspect_y - height
    if abs(old_ratio - new_ratio) < 0.1:
        if new_ratio > old_ratio:
            return width / new_ratio - reduction_x, \
                   height / new_ratio - reduction_y  # same width, shorter height
        else:
            return width / new_ratio - reduction_x, \
                   height / new_ratio - reduction_y  # shorter width, same height

    elif new_ratio > old_ratio:
        return width / new_ratio, height / new_ratio  # same width, shorter height
    else:
        return width / new_ratio, height / new_ratio  # shorter width, same height

def crop_left(filename, destination):
    """
    crops top or left
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_crop_left")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            if img.width > img.height:
                i.crop(left=int(img.width * 0.1))
            else:
                i.crop(top=int(img.height * 0.1))
            i.save(filename=name + ".jpg")
    return name

def crop_right(filename, destination):
    """
    crops bottom or right
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_crop_right")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            if img.width > img.height:
                i.crop(right=int(img.width * 0.9))
            else:
                i.crop(bottom=int(img.height * 0.9))
            i.save(filename=name + ".jpg")
    return name

def mirror(filename, destination):
    """
    makes mirror
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_mirror")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            i.flop()
            i.save(filename=name + ".jpg")
    return name

def noise(filename, destination):
    """
    adds noise
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_noise")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            i.modulate(brightness=60.0, saturation=35, hue=100)
            i.noise('multiplicative_gaussian')
            i.save(filename=name + ".jpg")
    return name

def blur(filename, destination):
    """
    makes motion blur
    :param destination: output
    :param filename: input
    :return: new name
    """
    name = str(destination + "_blur")
    with Image(filename=filename + ".jpg") as img:
        # print(name)
        with img.clone() as i:
            i.motion_blur(radius=5, sigma=10, angle=2)
            i.save(filename=name + ".jpg")
    return name

def make_folders():
    import os

    from training_scripts.preprocesing_imgs.checker.loader import load_styles

    if "ready_data" in os.listdir("../../") and os.path.isdir("../../ready_data"):
        for style in load_styles("styles_list.txt"):
            os.path.isdir("../../ready_data/train/" + style)
            os.path.isdir("../../ready_data/val/" + style)
        return
    else:
        os.mkdir("../../ready_data")
        os.mkdir("../../ready_data/train/")
        os.mkdir("../../ready_data/val/")
        for style in load_styles("styles_list.txt"):
            os.mkdir("../../ready_data/train/" + style)
            os.mkdir("../../ready_data/val/" + style)

def main():
    logging.basicConfig(format='[%(levelname)s] - %(asctime)s - %(message)s',
                        level='INFO')

    make_folders()

    # set MAGICK_HOME /opt/homebrew/Cellar/imagemagick@6/6.9.12-86_1
    # if is magic not found

    minimum = 0  # magic number
    Edith('art_nouveau', minimum).start()
    Edith('asian', minimum).start()
    Edith('baroque', minimum).start()
    Edith('brutalist', minimum).start()
    Edith('cubism', minimum).start()
    Edith('functionalism', minimum).start()
    Edith('gothic', minimum).start()
    Edith('islamic', minimum).start()
    Edith('renaissance', minimum).start()
    Edith('romanesque', minimum).start()

if __name__ == '__main__':
    main()


from gns3server.web.route import Route
from gns3server.controller import Controller
from gns3server.schemas.node import NODE_OBJECT_SCHEMA
from gns3server.schemas.template import TEMPLATE_USAGE_SCHEMA

import hashlib
import json

from gns3server.schemas.template import (
    TEMPLATE_OBJECT_SCHEMA,
    TEMPLATE_UPDATE_SCHEMA,
    TEMPLATE_CREATE_SCHEMA
)

import logging
log = logging.getLogger(__name__)

class TemplateHandler:
    """
    API entry points for template management.
    """

    @Route.post(
        r"/templates",
        description="Create a new template",
        status_codes={
            201: "Template created",
            400: "Invalid request"
        },
        input=TEMPLATE_CREATE_SCHEMA,
        output=TEMPLATE_OBJECT_SCHEMA)
    def create(request, response):

        controller = Controller.instance()
        template = controller.template_manager.add_template(request.json)
        # Reset the symbol list
        controller.symbols.list()
        response.set_status(201)
        response.json(template)

    @Route.get(
        r"/templates/{template_id}",
        status_codes={
            200: "Template found",
            400: "Invalid request",
            404: "Template doesn't exist"
        },
        description="Get an template",
        output=TEMPLATE_OBJECT_SCHEMA)
    def get(request, response):

        request_etag = request.headers.get("If-None-Match", "")
        controller = Controller.instance()
        template = controller.template_manager.get_template(request.match_info["template_id"])
        data = json.dumps(template.__json__())
        template_etag = '"' + hashlib.md5(data.encode()).hexdigest() + '"'
        if template_etag == request_etag:
            response.set_status(304)
        else:
            response.headers["ETag"] = template_etag
            response.set_status(200)
            response.json(template)

    @Route.put(
        r"/templates/{template_id}",
        status_codes={
            200: "Template updated",
            400: "Invalid request",
            404: "Template doesn't exist"
        },
        description="Update an template",
        input=TEMPLATE_UPDATE_SCHEMA,
        output=TEMPLATE_OBJECT_SCHEMA)
    def update(request, response):

        controller = Controller.instance()
        template = controller.template_manager.get_template(request.match_info["template_id"])
        # Ignore these because we only use them when creating a template
        request.json.pop("template_id", None)
        request.json.pop("template_type", None)
        request.json.pop("compute_id", None)
        request.json.pop("builtin", None)
        template.update(**request.json)
        response.set_status(200)
        response.json(template)

    @Route.delete(
        r"/templates/{template_id}",
        parameters={
            "template_id": "template UUID"
        },
        status_codes={
            204: "Template deleted",
            400: "Invalid request",
            404: "Template doesn't exist"
        },
        description="Delete an template")
    def delete(request, response):

        controller = Controller.instance()
        controller.template_manager.delete_template(request.match_info["template_id"])
        response.set_status(204)

    @Route.get(
        r"/templates",
        description="List of template",
        status_codes={
            200: "Template list returned"
        })
    def list(request, response):

        controller = Controller.instance()
        response.json([c for c in controller.template_manager.templates.values()])

    @Route.post(
        r"/templates/{template_id}/duplicate",
        parameters={
            "template_id": "Template UUID"
        },
        status_codes={
            201: "Template duplicated",
            400: "Invalid request",
            404: "Template doesn't exist"
        },
        description="Duplicate an template",
        output=TEMPLATE_OBJECT_SCHEMA)
    async def duplicate(request, response):

        controller = Controller.instance()
        template = controller.template_manager.duplicate_template(request.match_info["template_id"])
        response.set_status(201)
        response.json(template)

    @Route.post(
        r"/projects/{project_id}/templates/{template_id}",
        description="Create a node from a template",
        parameters={
            "project_id": "Project UUID",
            "template_id": "Template UUID"
        },
        status_codes={
            201: "Node created",
            404: "The project or template doesn't exist"
        },
        input=TEMPLATE_USAGE_SCHEMA,
        output=NODE_OBJECT_SCHEMA)
    async def create_node_from_template(request, response):

        controller = Controller.instance()
        project = controller.get_project(request.match_info["project_id"])
        node = await project.add_node_from_template(request.match_info["template_id"],
                                                    x=request.json["x"],
                                                    y=request.json["y"],
                                                    name=request.json.get("name"),
                                                    compute_id=request.json.get("compute_id"))
        response.set_status(201)
        response.json(node)


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

data = np.load("mnist.npz")
traind = data["arr_0"]
trainl = data["arr_2"]

# 1a)
print(np.argmax(traind[:, 0, 0]))  # --> 0
# 1b)
print(traind.mean(axis=2))  # long output! shape (60000,28)
# 1c)
print(traind.sum(axis=1))  # long output! shape (60000,28)

# 2a)
f, ax = plt.subplots(1, 1)
x_data = np.linspace(1, 5, 100)
y_data = 1. / x_data
ax.plot(x_data, y_data)
plt.show()
# 2b)
f, ax = plt.subplots(1, 1)
x_data = np.linspace(1, 5, 100)
y_data = 1. / x_data
ax.bar(x_data, y_data)
plt.show()
# 2c)
f, ax = plt.subplots(1, 1)
x_data = np.linspace(1, 5, 100)
y_data_1 = 1. / x_data
y_data_2 = np.sqrt(x_data)
ax.plot(x_data, y_data_1)
ax.plot(x_data, y_data_2)
plt.show()

# 3a)
indices = [5, 6, 7]
f, ax = plt.subplots(1, 3)

for i, index in enumerate(indices):
    ax[i].imshow(traind[index])
plt.show()

# 3b)
means = traind.mean(axis=(1, 2))
x_data = np.linspace(0, 60000, 60000)
f, ax = plt.subplots(1, 1)
ax.scatter(x_data, means)
plt.show()

# 3c)
means = traind.mean(axis=(1, 2))
mask = (means > 0.3)
strongImgs = traind[mask, :, :]

f, ax = plt.subplots(1, 3)
for i in range(0, 3):
    ax[i].imshow(strongImgs[i])
plt.show()

# 3d)
indices = np.random.randint(0, 60000, 10)
f, ax = plt.subplots(1, 10)

for i, index in enumerate(indices):
    ax[i].imshow(traind[index])
plt.show()

# 3e)
# create mask for images of class 5
numerical_classes = trainl.argmax(axis=1)
# gives a boolean array of 60000 entries
mask = (numerical_classes == 5)

# copy out all samples using the boolean array: mask indexing!
samples5 = traind[mask, :, :]

# display first 5 images of class 5
f, ax = plt.subplots(1, 10)
for i in range(0, 10):
    ax[i].imshow(samples5[i])
plt.show()


from django.urls import path, include
from .views import *

urlpatterns = [
    path("register/", register_view, name="register"),
    path("login/", login_view, name="login"),
    path("logout/", user_logout, name="logout"),
    path('edit_profile/', edit_profile, name='edit_profile'),
    path('profile/<str:username>/', profile, name='profile'),
    path('laboratory_seven/', laboratory_seven, name='lab7'),
    path('create_record/', create_record, name='create_record'),
    path('delete_record/<int:el_id>', delete_rec, name='delete_rec'),
    path('update_record/<int:pk>/', UpdateRecord.as_view(), name='update_record'),
]


import streamlit as st
import functions

todos = functions.get_todos()

def add_todo():
    this_todo = st.session_state["new_todo"] + "\n"
    todos.append(this_todo)
    functions.write_todos(todos)
    st.session_state["new_todo"] = ""

st.title("My todo app")
for i, todo in enumerate(todos):
    checkbox = st.checkbox(todo, key=todo)
    if checkbox == True:
        todos.pop(i)
        functions.write_todos(todos)
        del st.session_state[todo]
        st.experimental_rerun()
st.text_input(label="Enter a todo", placeholder="Add a new todo",
              on_change=add_todo, key="new_todo",value=st.session_state.get("new_todo",""))


import argparse
import cv2
import face_recognition
import numpy as np

from image_face_encoding import encode_face
from utils.logger import logger
from utils.text_to_image import text_to_image

def get_euclidean_distance(face1_vector, face2_vector):
    # Load the two feature vectors
    feature_vector1 = np.array(face1_vector)
    feature_vector2 = np.array(face2_vector)
    # Calculate the Euclidean distance between the two feature vectors
    euclidean_distance = np.sqrt(np.sum((feature_vector1 - feature_vector2) ** 2))
    return euclidean_distance

def is_match(face1_vector, face2_vector, match_threshold=0.8):
    euclidean_distance = get_euclidean_distance(face1_vector, face2_vector)
    logger.info(f'Euclidean distance is {euclidean_distance}')
    if euclidean_distance < (1 - match_threshold):
        return True
    else:
        return False

def main(args):
    logger.info(f'Arguments passed are, {args}')
    image1 = args.get('image1')
    image2 = args.get('image2')
    output = args.get('output')
    threshold = args.get('threshold')
    face1_object = encode_face(image1, output)
    face2_object = encode_face(image2, output)

    face_distance = face_recognition.face_distance(np.array(face1_object[0].get('vector')),
                                                   np.array(face2_object[0].get('vector'))
                                                   )
    logger.info(f'Face distance {face_distance}')

    if is_match(face1_object[0].get('vector'), face2_object[0].get('vector'), threshold):
        logger.info(f'{image1} and {image2} are a match!')
    else:
        logger.info(f'Oops! {image1} and {image2} are not same!')
    return 0

from face_recognition import api
from face_recognition import face_recognition_cli
from face_recognition import face_detection_cli
import os

def main2(args):
    image1 = args.get('image1')
    image2 = args.get('image2')
    threshold = args.get('threshold')
    img_a1 = api.load_image_file(image1)
    img_a2 = api.load_image_file(image2)
    face_encoding_a1 = api.face_encodings(img_a1)[0]
    face_encoding_a2 = api.face_encodings(img_a2)[0]
    faces_to_compare = [
        face_encoding_a1]
    match_results = api.compare_faces(faces_to_compare, face_encoding_a2, tolerance=(1 - threshold))
    distance_results = api.face_distance(faces_to_compare, face_encoding_a2)
    logger.info(f"Matched: {match_results[0]}, Distance: {distance_results[0]}")

    match_distance_image = text_to_image(f'\n' +
                                         f'Distance = {distance_results[0]}'
                                         f'\n' +
                                         f'Matched = {match_results[0]}'
                                         f'\n')

    image1_display = cv2.imread(image1)
    image2_display = cv2.imread(image2)
    display_images = [image1_display, match_distance_image, image2_display,]
    rows = max([img.shape[0] for img in display_images])
    cols = sum([img.shape[1] for img in display_images])
    # Create a black canvas to hold the images
    canvas = np.zeros((rows, cols, 3), dtype=np.uint8)
    # Copy each image onto the canvas
    x_offset = 0
    for img in display_images:
        h, w = img.shape[:2]
        canvas[:h, x_offset:x_offset + w] = img
        x_offset += w
    cv2.imshow('Face Match Canvas', canvas)
    cv2.waitKey(20000)
    cv2.destroyAllWindows()

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i1", "--image1", required=True,
                help="path to directory of image1 for comparing")
ap.add_argument("-i2", "--image2", required=False,
                help="path to directory of image2 for comparing")
ap.add_argument("-d", "--detection-method", type=str, default="cnn",
                help="face detection model to use: either `hog` or `cnn`")
ap.add_argument(
    "-t",
    "--threshold",
    required=True,
    type=float,
    choices=[
        0.1,
        0.2,
        0.3,
        0.4,
        0.5,
        0.6,
        0.7,
        0.8,
        0.9],
    help="Threshold to reject images with almost same size faces")
ap.add_argument("-o", "--output", required=False,
                help="path to output directory to save output files")

# Main method starts here.
if __name__ == '__main__':
    args = vars(ap.parse_args())
    exit(main2(args))


from datetime import datetime
import pooler
import time
from openerp.tools.translate import _
from openerp.addons.account_report_lib.account_report_base import accountReportbase

class Parser(accountReportbase):

    def __init__(self, cr, uid, name, context):
        super(Parser, self).__init__(cr, uid, name, context=context)
        self.pool = pooler.get_pool(self.cr.dbname)
        self.cursor = self.cr
        self.localcontext.update({
            'time': time,
            'cr' : cr,
            'uid': uid,
            'storage':{},
            'set_data_template':self.set_data_template,
            'opening_quantity':0.0,
            'final_cost':0.0,
            'final_quantity':0.0,
            'display_locations':self.display_locations,
            'get_order_product':self.get_order_product,
            'is_product_dictionary':self.is_product_dictionary,
            'get_order_product': self.get_order_product,
            'get_name_product':self.get_name_product,
            'get_location_name': self.get_location_name,
            'set_opening_quantity': self.set_opening_quantity,
            'return_opening_quantity': self.return_opening_quantity,
            'get_opening_cost': self.get_opening_cost,
            'get_include_costs':self.get_include_costs,
            'get_data_stock_moves':self.get_data_stock_moves,
            'return_final_cost':self.return_final_cost,
            'get_final_quantity':self.get_final_quantity,
        })

    #================== GET AND SET =======================#
    def get_name_product(self, product_id):
        product_product_obj = self.pool.get('product.product')
        product = product_product_obj.browse(self.cr, self.uid, product_id)
        name = product.name
        if product.code:
            name = product.code + ' - ' + product.name
        return name

    def get_location_name(self, location_id):
        return self.pool.get('stock.location').browse(self.cr, self.uid, location_id).complete_name

    def get_product_ids(self, data):
        return self._get_info(data,'product_ids', 'product.product')

    def get_location_ids(self, data):
        return self._get_info(data,'location_ids', 'stock.location')

    def get_include_costs(self, data):
        return self._get_form_param('include_costs', data)

    def set_opening_quantity(self, data, product_id, location_id):
        date_from = self.get_date_from(data)
        opening_quantity = self.get_opening_quantity(self.cr, self.uid, data, product_id, location_id)
        self.localcontext['opening_quantity'] = opening_quantity
        return opening_quantity

    def return_opening_quantity(self):
        return self.localcontext['opening_quantity']

    def return_final_cost(self):
        return self.localcontext['final_cost']

    def get_final_quantity(self):
        return self.localcontext['final_quantity']

    def get_order_product(self, data):
        product_ids = []

        if not self.get_product_ids(data):
            product_ids = self.pool.get('product.product').search(self.cr, self.uid, [], order="code ASC")
            return self.pool.get('product.product').browse(self.cr, self.uid, product_ids)
        else:
           return self.get_product_ids(data) #browse record list

    def is_product_dictionary(self, product_id):
        if product_id in self.localcontext['storage']['result'].keys():
            return True
        else:
            return False

    def set_data_template(self, data):
        result = self.get_dict_result(data)
        dict_update = {'result': result,}
        self.localcontext['storage'].update(dict_update)
        return False

    #=========================================================#

    #================ DISPLAY DATA ===========================#
    def display_locations(self, data):
       name = ''

       if not self.get_location_ids(data): #It means that non-one was selected
           return _('All locations')
       else:
           locations = self.get_location_ids(data)
           for location in locations:
               name += location.complete_name + ' , '
           return name
    #===========================================================#

    """Build parameters. Extract information from wizard. """
    def built_parameters(self, data):
        product_ids = []
        location_ids = []

        date_from = self.get_date_from(data)
        date_to = self.get_date_to(data)
        include_costs = self.get_include_costs(data)

        #If user doesn't select any product, get all products
        x = self.get_product_ids(data)
        if not self.get_product_ids(data):
            product_ids = self.pool.get('product.product').search(self.cr, self.uid, [])
        else:
            for product in self.get_product_ids(data):
                product_ids.append(product.id)

        #If user doesnt's select any location, get all locations
        if not self.get_location_ids(data):
            location_ids = self.pool.get('stock.location').search(self.cr, self.uid, [])
        else:
            for location in self.get_location_ids(data):
                location_ids.append(location.id)

        return date_from, date_to, include_costs, product_ids, location_ids

    """"
        Classified all stock_moves by product and location
    """
    def get_dict_result(self, data):
        result = {}
        stock_move_obj = self.pool.get('stock.move')

        #parameters
        date_from, date_to, include_costs, product_ids, location_ids = self.built_parameters(data)

        #Get stock_move
        stock_move_ids = stock_move_obj.search(self.cr, self.uid, ['&', '&', '&', ('date','>=',date_from), ('date','<=',date_to), ('product_id', 'in', product_ids), '|',('location_id', 'in', location_ids), ('location_dest_id', 'in', location_ids)], order="date asc")
        stock_moves = stock_move_obj.browse(self.cr, self.uid, stock_move_ids)

        #Classified stock by product and location
        for stock in stock_moves:
            if stock.product_id.id not in result.keys():
                result[stock.product_id.id] = {}
            if stock.location_id.id not in result[stock.product_id.id].keys():
                result[stock.product_id.id][stock.location_id.id] = []
            if stock.location_dest_id.id not in result[stock.product_id.id].keys():
                result[stock.product_id.id][stock.location_dest_id.id] = []
            result[stock.product_id.id][stock.location_id.id].append(stock)
            result[stock.product_id.id][stock.location_dest_id.id].append(stock)
        return result

    """Get data for a each stock_move. Keep this information in a dictionary,
       where id is stock_move id
    """
    def get_data_stock_moves(self, opening_quantity, product_id, location_id, stock_move_list, data):
        stock_move_final = {}
        product_price_history_obj = self.pool.get('product.price.history')

        #Initialize final_quantity
        self.localcontext['final_quantity'] = opening_quantity

        for stock_move in stock_move_list:
            final_quantity = self.get_product_quantity(stock_move, location_id, opening_quantity)

            if self.get_include_costs(data):
                final_cost = self.get_opening_cost(data, product_id, opening_quantity)
            sign = 1
            stock_move_dic = {'date': stock_move.date, 'type': stock_move.origin or '',}

            #Final Quantity
            if stock_move.location_id.id == location_id:
                stock_move_dic.update ({'quantity_input': 0.00, 'quantity_output': stock_move.product_qty})
                self.localcontext['final_quantity'] -= stock_move.product_qty
                stock_move_dic.update({'final_quantity': self.localcontext['final_quantity']})
                sign = -1
            elif stock_move.location_dest_id.id == location_id:
                stock_move_dic.update ({'quantity_input': stock_move.product_qty, 'quantity_output': 0.00})
                self.localcontext['final_quantity'] += stock_move.product_qty
                stock_move_dic.update({'final_quantity': self.localcontext['final_quantity']})

            if self.get_include_costs(data):
                #Result of standard_price is a dictionary, where keys are product_id and value in field_names, in this case, 'standard_price'
                standard_price = product_price_history_obj._get_historic_price(self.cr, self.uid, [stock_move.product_id.id], datetime=stock_move.date, field_names=['standard_price'])
                if standard_price[stock_move.product_id.id]['standard_price'] == 0:
                    standard_price = self.pool.get('product.product').browse(self.cr, self.uid, stock_move.product_id.id).standard_price
                    total = stock_move.product_qty * standard_price
                else:
                    standard_price = standard_price[stock_move.product_id.id]['standard_price']
                    total = stock_move.product_qty * standard_price
                final_cost += total * sign
                #update final_cost
                self.localcontext['final_cost'] = final_cost
                stock_move_dic.update ({'standard_price': standard_price, 'total': total, 'final_cost': final_cost})

            #Return a dictionary, where key is stock_move_id and all values related with that stock_move
            stock_move_final[stock_move.id] =  stock_move_dic

        dict_update={'stock_moves': stock_move_final}
        self.localcontext['storage'].update(dict_update)

    def get_opening_quantity(self, cr, uid, data, product_id, location_id):
        opening_quantity = 0.00
        stock_move_obj = self.pool.get('stock.move')

        date_from = self.get_date_from(data)
        stock_move_ids = stock_move_obj.search(cr, uid, ['&', '&', ('date','<',date_from), ('product_id', '=', product_id), '|',('location_id', '=', location_id), ('location_dest_id', '=', location_id)])
        stock_moves = stock_move_obj.browse(cr, uid, stock_move_ids)

        for stock_move in stock_moves:
            opening_quantity = self.get_product_quantity(stock_move, location_id, opening_quantity)
        return opening_quantity

    def get_opening_cost(self, data, product_id, opening_quantity):
        product_price_history_obj = self.pool.get('product.price.history')
        date_from = self.get_date_from(data)
        date= datetime.strptime(date_from, "%Y-%m-%d")
        standard_price = product_price_history_obj._get_historic_price(self.cr, self.uid, [product_id], datetime=date, field_names=['standard_price'])
        opening_cost = standard_price[product_id]['standard_price'] * opening_quantity
        return opening_cost

    def get_product_quantity(self, stock_move, location_id, quantity):
        if stock_move.location_id.id == location_id:
            quantity = quantity - stock_move.product_qty
        elif stock_move.location_dest_id.id == location_id:
            quantity = quantity + stock_move.product_qty
        return quantity


import asyncio
import contextlib
import os
import sys
from asyncio import Queue

from Util import write_util, read_util, write_from_queue
import aiofiles.threadpool as nbt

async def read_handler(reader):
    """Read handler for concurrent read"""
    async for data in read_util(reader):
        print(f'Received: {data.decode()!r}')

async def stream_to_queue(file, write_queue):
    """Function to save streams to queue"""
    loop = asyncio.get_event_loop()
    async for message in nbt.wrap(file, loop=loop):  # non blocking io read
        await write_queue.put(message.encode())

async def main(file):
    reader, writer = await asyncio.open_connection(
        os.environ["SERVER_HOST"],
        os.environ["SERVER_PORT"])

    write_queue = Queue()
    rh = asyncio.create_task(read_handler(reader))  # concurrent reading
    wh = asyncio.create_task(write_from_queue(writer, write_queue))  # concurrent write from queue
    ch = asyncio.create_task(stream_to_queue(file, write_queue))  # concurrent stdin to queue

    done, pending = await asyncio.wait([rh,
                                        wh,
                                        ch],
                                       return_when=asyncio.FIRST_COMPLETED)

    print("Closing connection")  # reaches when we cancel the connection
    for task in pending:  # closing the pending connections
        task.cancel()

if __name__ == "__main__":
    asyncio.run(main(sys.stdin))  # check why stdin works not input, does not strip new line


import torch
import utils
import argparse
from torch.utils.tensorboard import SummaryWriter
import os
import torchvision
import tqdm
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
import pytorch_warmup as warmup
from sklearn.metrics import f1_score
import torch.nn.functional as F
import torch.nn as nn
import math

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--config_file',required=True,type=str)
parser.add_argument('--local_rank',type=int,default=-1)
parser.add_argument('--use_ddp',action='store_true',default=False)

class selfattention(nn.Module):
    def __init__(self, inplanes):
        super(selfattention, self).__init__()

        self.interchannel = inplanes
        self.inplane = inplanes
        self.g = nn.Conv2d(inplanes, inplanes, kernel_size=1, stride=1, padding=0)
        self.theta = nn.Conv2d(inplanes, self.interchannel, kernel_size=1, stride=1, padding=0)
        self.phi = nn.Conv2d(inplanes, self.interchannel, kernel_size=1, stride=1, padding=0)
        self.act = nn.LeakyReLU(0.1)

    def forward(self, x):
        b, c, h, w = x.size()
        g_y = self.g(x).view(b, c, -1)  # BXcXN
        theta_x = self.theta(x).view(b, self.interchannel, -1)
        theta_x = F.softmax(theta_x, dim=-1)  # softmax on N
        theta_x = theta_x.permute(0, 2, 1).contiguous()  # BXNXC'

        phi_x = self.phi(x).view(b, self.interchannel, -1)  # BXC'XN

        similarity = torch.bmm(phi_x, theta_x)  # BXc'Xc'

        g_y = F.softmax(g_y, dim=1)
        attention = torch.bmm(similarity, g_y)  # BXCXN
        attention = attention.view(b, c, h, w).contiguous()
        y = self.act(x + attention)
        return y

class BasicBlockNormal(nn.Module):
    expansion = 1

    def __init__(self, inplanes, planes, stride=1, downsample=None):
        super(BasicBlockNormal, self).__init__()

        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = nn.Conv2d(inplanes,planes,3,stride,1)
        self.relu = nn.LeakyReLU(negative_slope=0.1,inplace=True)
        self.conv2 = nn.Conv2d(planes,planes,3,1,1)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.relu(out)

        out = self.conv2(out)
        #out = self.relu(out)
        if self.downsample is not None:
            identity = self.downsample(x)
        out = (out + identity)
        return self.relu(out)

class FaceCycleBackboneSwapCLR(torch.nn.Module):
    def __init__(self):
        super(FaceCycleBackboneSwapCLR, self).__init__()

        self.conv1 = nn.Sequential(nn.Conv2d(3, 64, 7, 2, 3, bias=True),
                                   nn.LeakyReLU(negative_slope=0.1),
                                   nn.Conv2d(64, 64, 3, 1, 1, bias=True),
                                   nn.LeakyReLU(negative_slope=0.1))

        self.layer1 = nn.Sequential(nn.Conv2d(64, 64, 3, 1, 1, bias=True),
                                    nn.LeakyReLU(negative_slope=0.1),
                                    selfattention(64),
                                    nn.Conv2d(64, 64, 3, 1, 1, bias=True),
                                    nn.LeakyReLU(negative_slope=0.1))  # 64

        self.layer2_1 = nn.Sequential(nn.Conv2d(64, 128, 3, 2, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1),
                                      selfattention(128),
                                      nn.Conv2d(128, 128, 3, 1, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1), )  # 64

        self.resblock1 = BasicBlockNormal(128, 128)
        self.resblock2 = BasicBlockNormal(128, 128)

        self.layer2_2 = nn.Sequential(nn.Conv2d(128, 128, 3, 2, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1),
                                      nn.Conv2d(128, 128, 3, 1, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1), )  # 64

        self.layer3_1 = nn.Sequential(nn.Conv2d(128, 256, 3, 2, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1),
                                      nn.Conv2d(256, 128, 3, 1, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1), )  # 64

        self.layer3_2 = nn.Sequential(nn.Conv2d(128, 256, 3, 1, 1, bias=True),  # stride 2 for 128x128
                                      nn.LeakyReLU(negative_slope=0.1),
                                      nn.Conv2d(256, 128, 3, 1, 1, bias=True),
                                      nn.LeakyReLU(negative_slope=0.1),
                                      )  # 64
        #self.fc = nn.Identity()
        # self.exp_fc = nn.Sequential(nn.Linear(2048, 2048),
        #                             nn.ReLU(),
        #                             nn.Linear(2048, 512),
        #                             nn.BatchNorm1d(512))
        #
        # self.pose_fc = nn.Sequential(nn.Linear(2048, 2048),
        #                              nn.ReLU(),
        #                              nn.Linear(2048, 512),
        #                              nn.BatchNorm1d(512))

        #self.decoder = Generator(d_model=512)
        self.linear_classifier = torch.nn.Sequential(torch.nn.BatchNorm1d(config['linear_dim']),nn.Linear(6272, 3)).cuda()

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
                if m.bias is not None:
                    m.bias.data.zero_()
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()
            elif isinstance(m, nn.Linear):
                m.weight.data.normal_(0, 0.01)
                m.bias.data.zero_()

    def forward(self, x):
        #encoder
        '''

        :param x: [batch,3,64,64]
        :return:
        '''
        out_1 = self.conv1(x) # [batch,64,32,32]
        out_1 = self.layer1(out_1) # [batch,64,32,32]
        out_2 = self.layer2_1(out_1) # [batch,128,16,16]
        out_2 = self.resblock1(out_2) # [batch,128,16,16]
        out_2 = self.resblock2(out_2) # [batch,128,16,16]
        out_2 = self.layer2_2(out_2) # [batch,128,8,8]
        out_3 = self.layer3_1(out_2) # [batch,256,4,4]
        out_3 = self.layer3_2(out_3).view(x.size()[0],-1)

        red = self.linear_classifier(out_3)
        #print(out_3.size())
        # expcode = self.fc(out_3) # [batch,256]
        #out_3 = self.fc(out_3)
        #exp_fea = self.exp_fc(out_3)
        #pose_fea = self.pose_fc(out_3)
        #fea = torch.cat([exp_fea,pose_fea],dim=1)
        #fea = exp_fea + pose_fea
        #return fea
        #return out_3
        #return exp_fea
        #return pose_fea
        #return exp_fea,pose_fea
        #return expcode
        return red

def eval(config,val_loader,model):
    cos_dis = torch.nn.CosineSimilarity(dim=1, eps=1e-6)
    label_list = []
    pred_list = []
    prob = []
    theta = config['theta']

    for i, data in tqdm.tqdm(enumerate(val_loader)):
        label = data['label']

        fea1, fea2 = model.linear_eval_id(data)
        pred = cos_dis(fea1, fea2)
        pred_bool = torch.zeros_like(pred)

        pred_bool[pred >= theta] = 1.
        pred_bool[pred<theta] = -1.
        pred_list.extend(pred_bool.tolist())
        prob.extend(pred.tolist())
        label_list.extend(label.tolist())

    acc_count = 0
    for i in range(len(label_list)):
        print('index: {},\t pred: {},\t prob: {},\t label: {}'.format(i + 1, pred_list[i], prob[i], label_list[i]))
        if pred_list[i] == label_list[i]:
            acc_count += 1

    linear_acc = acc_count / len(label_list)
    return linear_acc

def linear_eval(config,train_loader,val_loader,model,logger):
    best_linear_acc = 100.
    #theta = config['theta']
    if config['pose'] == 'all':
        config['out_dim']=3
    #linear_classifier = torch.nn.Linear(in_features=config['linear_dim'],out_features=config['out_dim']).cuda()
    #linear_classifier = FaceCycleBackboneSwapCLR().cuda()
    linear_classifier = torch.nn.Sequential(torch.nn.BatchNorm1d(num_features=config['linear_dim']),torch.nn.Linear(in_features=config['linear_dim'],out_features=config['out_dim'])).cuda()
    #linear_classifier.weight.data.normal_(mean=0.0,std=0.01)
    #linear_classifier.bias.data.zero_()
    optimizer = torch.optim.AdamW(linear_classifier.parameters(),lr=config['linear_lr'])
    #model = torchvision.models.resnet18(pretrained=False).cuda()
    #optimizer = torch.optim.Adam(model.model.parameters(), lr=config['linear_lr'])
    #optimizer = torch.optim.Adam(model.model.parameters(),lr=config['linear_lr'])
    lr_schduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=config['eval_epochs'])
    #criterizer = torch.nn.CosineEmbeddingLoss(margin=theta).cuda()
    #criterizer = torch.nn.MSELoss().cuda()
    criterizer = torch.nn.L1Loss()

    if config['linear_eval']:
        for eval_step in range(config['eval_epochs']):
            train_count = 0.
            train_loss = 0.
            cos_dis = torch.nn.CosineSimilarity(dim=1, eps=1e-6)
            label_list = []
            pred_list = []
            prob = []
            linear_classifier.train()
            model.model.train()
            train_loss_list = []
            for i, data in tqdm.tqdm(enumerate(train_loader)):
                label = data['label'].float().cuda()
                #print(label)
                #print(label.size())
                fea = model.linear_forward(data)
                pred = linear_classifier(fea)
                #print(fea1.size())
                loss = criterizer(pred,label)
                #print(loss.item())
                #print(loss)

                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                #train_loss += loss.item()
                train_loss_list.append(loss.item())

            #avg_train_loss = train_loss / train_count
            #acc_count = 0.
            #lr_schduler.step()
            #for i in range(len(label_list)):
            #    if pred_list[i] == label_list[i]:
            #        acc_count += 1
            #train_linear_acc = acc_count / len(label_list)

            linear_classifier.eval()
            model.model.eval()
            eval_loss_list = []
            eval_pitch_loss_list = []
            eval_yaw_loss_list = []
            eval_roll_loss_list = []
            for i,data in tqdm.tqdm(enumerate(val_loader)):
                label = data['label'].float().cuda()

                #fea1,fea2 = model.linear_forward_id(data)

                with torch.no_grad():
                    #fea = data['img_normal'].cuda()
                    fea = model.linear_forward(data)
                    #fea1 = F.normalize(fea1,dim=1)
                    #fea2 = F.normalize(fea2,dim=1)
                    #fea1 = model(data['img_normal1'].cuda())
                    #fea2 = model(data['img_normal2'].cuda())
                    pred = linear_classifier(fea)

                    #label_angle = label * 180 / np.pi
                    #fea = fea * 180 / np.pi
                    loss = criterizer(pred,label)
                    eval_loss_list.append(loss.item())

                    loss_pitch = criterizer(pred[:,0],label[:,0])
                    loss_yaw = criterizer(pred[:,1],label[:,1])
                    loss_roll = criterizer(pred[:,2],label[:,2])
                    eval_pitch_loss_list.append(loss_pitch.item())
                    eval_yaw_loss_list.append(loss_yaw.item())
                    eval_roll_loss_list.append(loss_roll.item())

            avg_train_loss = np.mean(train_loss_list)
            avg_eval_loss = np.mean(eval_loss_list)
            avg_eval_pitch_loss = np.mean(eval_pitch_loss_list)
            avg_eval_yaw_loss = np.mean(eval_yaw_loss_list)
            avg_eval_roll_loss = np.mean(eval_roll_loss_list)
            txt = 'eval step: {},\t train loss: {},\t eval loss: {},\t pitch loss: {},\t yaw loss: {},\t roll loss: {}'.format(eval_step,avg_train_loss,avg_eval_loss,avg_eval_pitch_loss,avg_eval_yaw_loss,avg_eval_roll_loss)
            print(txt)
            #logger.add_scalar('linear_train_acc_id',train_linear_acc,eval_step)
            logger.add_scalar('linear_train_loss_pose',avg_train_loss,eval_step)
            #logger.add_scalar('linear_eval_acc_id',eval_acc,eval_step)
            logger.add_scalar('linear_eval_loss_pose',avg_eval_loss,eval_step)

            if avg_eval_loss < best_linear_acc:
                best_linear_acc = avg_eval_loss
                model_state = model.model.state_dict()
                linear_state = linear_classifier.state_dict()
                for k in list(linear_state.keys()):
                    model_state[k] = linear_state[k]
                utils.save_checkpoint({
                    'epoch': eval_step + 1,
                    'state_dict': model_state,
                }, config)
    else:
        best_linear_acc = eval(config,val_loader,model)
    return best_linear_acc

def main(config,logger):
    model = utils.create_model(config)

    train_dataset = utils.create_dataset(config,'train')
    test_dataset = utils.create_dataset(config,'test')

    train_loader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=config['batch_size'],
        num_workers=config['num_threads'],
        pin_memory=True,
        drop_last=False,
        shuffle=True
    )
    test_loader = torch.utils.data.DataLoader(
        test_dataset,
        batch_size=config['batch_size'],
        num_workers=config['num_threads'],
        pin_memory=True,
        drop_last=False,
        shuffle=True
    )
    linear_acc = linear_eval(config,train_loader,test_loader,model,logger)
    print('test linear acc is : {}'.format(linear_acc))
    exit(0)

if __name__ == '__main__':
    opt = parser.parse_args()

    config = utils.read_config(opt.config_file)
    utils.init(config,opt.local_rank,opt.use_ddp)
    logger = SummaryWriter(log_dir=os.path.join(config['log_path'], config['experiment_name']),
                           comment=config['experiment_name'])

    main(config, logger)

    logger.close()