import numpy

from moderngl_window.opengl.vao import VAO
from moderngl_window.geometry import AttributeNames

def cube(
    size=(1.0, 1.0, 1.0),
    center=(0.0, 0.0, 0.0),
    normals=True,
    uvs=True,
    name=None,
    attr_names=AttributeNames,
) -> VAO:
    """Creates a cube VAO with normals and texture coordinates

    Keyword Args:
        width (float): Width of the cube
        height (float): Height of the cube
        depth (float): Depth of the cube
        center: center of the cube as a 3-component tuple
        normals: (bool) Include normals
        uvs: (bool) include uv coordinates
        name (str): Optional name for the VAO
        attr_names (AttributeNames): Attribute names
    Returns:
        A :py:class:`moderngl_window.opengl.vao.VAO` instance
    """
    width, height, depth = size
    width, height, depth = width / 2.0, height / 2.0, depth / 2.0

    # fmt: off
    pos = numpy.array([
        center[0] + width, center[1] - height, center[2] + depth,
        center[0] + width, center[1] + height, center[2] + depth,
        center[0] - width, center[1] - height, center[2] + depth,
        center[0] + width, center[1] + height, center[2] + depth,
        center[0] - width, center[1] + height, center[2] + depth,
        center[0] - width, center[1] - height, center[2] + depth,
        center[0] + width, center[1] - height, center[2] - depth,
        center[0] + width, center[1] + height, center[2] - depth,
        center[0] + width, center[1] - height, center[2] + depth,
        center[0] + width, center[1] + height, center[2] - depth,
        center[0] + width, center[1] + height, center[2] + depth,
        center[0] + width, center[1] - height, center[2] + depth,
        center[0] + width, center[1] - height, center[2] - depth,
        center[0] + width, center[1] - height, center[2] + depth,
        center[0] - width, center[1] - height, center[2] + depth,
        center[0] + width, center[1] - height, center[2] - depth,
        center[0] - width, center[1] - height, center[2] + depth,
        center[0] - width, center[1] - height, center[2] - depth,
        center[0] - width, center[1] - height, center[2] + depth,
        center[0] - width, center[1] + height, center[2] + depth,
        center[0] - width, center[1] + height, center[2] - depth,
        center[0] - width, center[1] - height, center[2] + depth,
        center[0] - width, center[1] + height, center[2] - depth,
        center[0] - width, center[1] - height, center[2] - depth,
        center[0] + width, center[1] + height, center[2] - depth,
        center[0] + width, center[1] - height, center[2] - depth,
        center[0] - width, center[1] - height, center[2] - depth,
        center[0] + width, center[1] + height, center[2] - depth,
        center[0] - width, center[1] - height, center[2] - depth,
        center[0] - width, center[1] + height, center[2] - depth,
        center[0] + width, center[1] + height, center[2] - depth,
        center[0] - width, center[1] + height, center[2] - depth,
        center[0] + width, center[1] + height, center[2] + depth,
        center[0] - width, center[1] + height, center[2] - depth,
        center[0] - width, center[1] + height, center[2] + depth,
        center[0] + width, center[1] + height, center[2] + depth,
    ], dtype=numpy.float32)

    if normals:
        normal_data = numpy.array([
            -0, 0, 1,
            -0, 0, 1,
            -0, 0, 1,
            0, 0, 1,
            0, 0, 1,
            0, 0, 1,
            1, 0, 0,
            1, 0, 0,
            1, 0, 0,
            1, 0, 0,
            1, 0, 0,
            1, 0, 0,
            0, -1, 0,
            0, -1, 0,
            0, -1, 0,
            0, -1, 0,
            0, -1, 0,
            0, -1, 0,
            -1, -0, 0,
            -1, -0, 0,
            -1, -0, 0,
            -1, -0, 0,
            -1, -0, 0,
            -1, -0, 0,
            0, 0, -1,
            0, 0, -1,
            0, 0, -1,
            0, 0, -1,
            0, 0, -1,
            0, 0, -1,
            0, 1, 0,
            0, 1, 0,
            0, 1, 0,
            0, 1, 0,
            0, 1, 0,
            0, 1, 0,
        ], dtype=numpy.float32)

    if uvs:
        uvs_data = numpy.array([
            1, 0,
            1, 1,
            0, 0,
            1, 1,
            0, 1,
            0, 0,
            1, 0,
            1, 1,
            0, 0,
            1, 1,
            0, 1,
            0, 0,
            1, 1,
            0, 1,
            0, 0,
            1, 1,
            0, 0,
            1, 0,
            0, 1,
            0, 0,
            1, 0,
            0, 1,
            1, 0,
            1, 1,
            1, 0,
            1, 1,
            0, 1,
            1, 0,
            0, 1,
            0, 0,
            1, 1,
            0, 1,
            1, 0,
            0, 1,
            0, 0,
            1, 0
        ], dtype=numpy.float32)
    # fmt: on

    vao = VAO(name or "geometry:cube")

    # Add buffers
    vao.buffer(pos, "3f", [attr_names.POSITION])
    if normals:
        vao.buffer(normal_data, "3f", [attr_names.NORMAL])
    if uvs:
        vao.buffer(uvs_data, "2f", [attr_names.TEXCOORD_0])

    return vao


# pyinstaller --hidden-import=scipy._lib.messagestream myscript.py
import socket
from time import sleep
from threading import Thread
import re
from decimal import Decimal, ROUND_HALF_UP
import sqlite_3
import mbservertest
# from PySide2.QtWidgets import QApplication
import My_global
import os
from logger import _logging as log
from math import sin, cos, pi, hypot
import numpy as np

class TM(Thread):
    def __init__(self, action, mode=''):
        Thread.__init__(self)
        self.k = log()
        self.log = self.k.Getlogger("TM.log")
        # self.rule = re.compile(r"[A-Z]+/-}")
        self.rule = re.compile(r"{.+}")
        self.rule1 = re.compile(r"d+")
        self.rule2 = re.compile(r"[A-Z]+")
        self.rulelist = action.split('-')
        self.log.info(self.rulelist)
        self.mode = self.rulelist[0]
        # self.action = self.rulelist[1]
        self.action = action
        self.ac_list = self.action.split("-")
        self.log.info([self.action,self.mode])
        self.sockClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sockClient.settimeout(3)
        self.sockClient.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 60 * 1000, 30 * 1000))
        with open(os.getcwd()+"/IP.txt") as f:
            self.IP = f.read().strip()
        self.log.info(str(self.IP))
        try:
            # self.sockClient.connect(('localhost', 5890))
            self.sockClient.connect((self.IP, 5890))
            self.Disconnect = True
        except:
            self.Disconnect = False
            self.log.info("Robot Not Connect!")

    def xor_strings(self, rulsult):#驗證碼生成
        # self.log.info(rulsult)
        tmp = ord(rulsult[0])
        for i in range(1, len(rulsult)):
            tmp = tmp ^ ord(rulsult[i])

        if len(hex(tmp)[2:]) == 1:
            return "0" + str(hex(tmp))[2:]

        return str(hex(tmp))[2:]

    def SendTMSCT(self, data): #組合Listen訊息
        ID = str(0)
        Len = str(1 + len(ID) + len(data))
        cmd = "TMSCT," + Len + ",0," + data + ","
        checksum = self.xor_strings(cmd)
        self.log.info("$" + cmd + "*" + checksum + "\r\n")
        return "$" + cmd + "*" + checksum + "\r\n"

    def run(self):
        global M0, M1, theta
        self.TMloop = True
        if self.Disconnect == False:
            self.TMloop = False
        self.sql = sqlite_3.My_sqlite()
        self.log.info('CONNECTTM IN LOOP')
        self.tmp = {"D":"A", "C":"B", "B":"C", "A":"D"}
        print(self.ac_list)
        if self.ac_list[7] == "Z":
            pass
        else:
            if self.ac_list[1][:2] == "RK" or self.ac_list[1][:2] == "EQ":#確認訊息

                if self.ac_list[1][:2] == "RK":#停車點判斷
                    if self.ac_list[1][:3] == "RK1":

                        if int(self.ac_list[3]) > 3:
                            if not 2 * ord(self.tmp[self.ac_list[7]]) - 66 <= ord(self.ac_list[2]) + 1 <= 2 * ord(
                                    self.tmp[self.ac_list[7]]) - 65:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                        else:
                            if not 2 * ord(self.tmp[self.ac_list[7]]) - 65 <= ord(self.ac_list[2]) \
                                   <= 2 * ord(self.tmp[self.ac_list[7]]) - 64:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                    else:

                        if int(self.ac_list[3]) > 3:
                            if not 2 * ord(self.ac_list[7]) - 66 <= ord(self.ac_list[2]) + 1 <= 2 * ord(
                                    self.ac_list[7]) - 65:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                        else:
                            if not 2 * ord(self.ac_list[7]) - 65 <= ord(self.ac_list[2]) <= 2 * ord(self.ac_list[7]) - 64:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False

                else:
                    if self.ac_list[7] != self.ac_list[2]:
                        self.log.info("停車點與夾取點不相符")
                        self.TMloop = False

            elif self.ac_list[4][:2] == "RK" or self.ac_list[4][:2] == "EQ":

                if self.ac_list[4][:2] == "RK":
                    if self.ac_list[4][:3] == "RK1":
                        if int(self.ac_list[6]) > 3:
                            if not 2 * ord(self.tmp[self.ac_list[7]]) - 66 <= ord(self.ac_list[5]) + 1 <= 2 * ord(
                                    self.tmp[self.ac_list[7]]) - 65:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                        else:
                            if not 2 * ord(self.tmp[self.ac_list[7]]) - 65 <= ord(self.ac_list[5]) \
                                   <= 2 * ord(self.tmp[self.ac_list[7]]) - 64:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                    else:

                        if int(self.ac_list[6]) > 3:
                            if not 2 * ord(self.ac_list[7]) - 66 <= ord(self.ac_list[5]) + 1 <= 2 * ord(
                                    self.ac_list[7]) - 65:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                        else:
                            if not 2 * ord(self.ac_list[7]) - 65 <= ord(self.ac_list[5]) <= 2 * ord(self.ac_list[7]) - 64:
                                self.log.info("停車點與夾取點不相符")
                                self.TMloop = False
                else:
                    if self.ac_list[7] != self.ac_list[5]:
                        self.log.info("停車點與夾取點不相符")
                        self.TMloop = False
            else:
                self.log.info("參數錯誤")
                self.TMloop = False
        self.Disconnecttimes = 0
        mbsev = mbservertest.mbclient()
        while self.TMloop:
            if self.Disconnecttimes == 5:
                self.TMloop = False
            if mbsev.Robotstop() == 0 or mbsev.Robotstop() == None:#判斷ROBOT可否執行
                self.TMloop = False
            # print("============")
            try:
                sleep(0.5)
                # try:
                offset = []
                self.sockClient.sendall("$TMSTA,2,00,*41\r\n".encode())
                a_1 = self.sockClient.recv(1024).decode()
                a = a_1.split(",")
                # a = [0,0,0,"true","Start"]
                if a_1.strip() != "" or len(a) == 6:#是否可以發送訊息
                    # print(a)
                    if a[3] == "true":
                        if a[4] == "Start":

                            if self.mode == "HOME" or self.mode == "BARCODE" or self.mode == "CHECK":#要資料
                                self.sockClient.sendall(self.SendTMSCT('var_data = "' + self.action + '"\r\nScriptExit()').encode())
                            elif self.mode == "BARCODE":
                                # self.log.info(1)
                                self.sockClient.sendall(
                                    self.SendTMSCT('var_data = "' + self.action + '"\r\nScriptExit()').encode())

                            # else:
                            #     self.sockClient.sendall(self.SendTMSCT('var_test = "' + str(self.action) + '"\r\nScriptExit()').encode())
                            #     self.log.info('var_test = "' + str(self.action) + '"\r\nScriptExit()')

                            self.TMloop = False
                            if self.mode == "SET" or self.mode == "SET_G_MASTER" or self.mode == "SET_L_MASTER":#紀錄點為
                                self.TMloop = True
                                self.TM_str = ''
                                self.sockClient.sendall(self.SendTMSCT('var_data = "' + self.action +'"\r\nScriptExit()').encode())
                            elif self.mode == "PUT" or self.mode == "Catch" or self.mode == "MIX" :#執行動作

                                self.TMloop = True
                                self.sockClient.sendall(self.SendTMSCT(
                                    'var_data = "' + self.action + '"\r\nScriptExit()').encode())

                                # print(self.sockClient.recv(1024).decode())
                                # print(self.sockClient.recv(1024).decode())
                                # print(self.sockClient.recv(1024).decode())
                                # print(self.sockClient.recv(1024).decode())
                                # app = QApplication(sys.argv)
                                # Login_1 = GTAGV.GTAGV()
                                # Login_1.show()
                                # app.exec_()
                                # self.data = Login_1.data
                                # for i in self.data:
                                #     self.TM_str = self.TM_str + ',' + i
                                # self.sockClient.sendall(self.SendTMSCT('var_locate = "' + self.TM_str + '"').encode())

                        elif a[4] == "give_pos_data":#獲取點為
                            self.log.info("give_pos_data")
                            Cycle = True
                            self.sockClient.sendall(self.SendTMSCT('ListenSend(90, var_allpos)').encode())
                            while Cycle:
                                b = self.sockClient.recv(1024).decode()
                                a = b.split(",")
                                # self.log.info(b)
                                if len(a) > 3:
                                    if a[2] == '90':
                                        self.log.info(a)
                                        self.log.info(self.rule.findall(b)[0])
                                        c = self.rule.findall(b)[0]
                                        c = c.replace("}","").split("{")
                                        c = [i.split(",") for i in c]
                                        self.log.info(c)
                                        c.pop(0)
                                        self.log.info(c)
                                        if c[0][0] == "":#判斷QRCODE是否有照到
                                            raise Exception("QRCODE NOT FOUND")
                                        else:
                                            offset.append(c[0][0])

                                        for i in range(1,len(c)):
                                            offset.append(str(c[i]).
                                                        replace('[', "").replace(']', '').replace("'",""))

                                        # for j in range(2, len(c)):
                                        #     # print(j)
                                        #     print(c[j])
                                        #     if c[j][0] == '':
                                        #         offset.append("")
                                        #     else:
                                        #         offset.append(
                                        #             str([float(Decimal(c[1][i]) - Decimal(c[j][i])) for i in
                                        #                  range(len(c[1]))]).
                                        #                 replace('[', "").replace(']', ''))
                                        # offset.pop(0)
                                        global_2_1 = offset
                                        self.log.info(offset)
                                        if len(offset) < 9:
                                            for i in range(8 - len(offset)):
                                                offset.append('')

                                        self.log.info(offset)
                                        # os.makedirs(os.getcwd()+'\\pos', exist_ok=True)
                                        # with open(os.getcwd()+'\\pos\\'+c[0][0] + '.txt','w+') as f:
                                        #     f.write(str(offset).strip("['']"))
                                        # if self.mode == "SET_L_MASTER":
                                        #     global_1_1 = self.sql.Get_TM_all("G_Master")[0]
                                        #     for i in range(4):
                                        #         global_1_1.pop(3)
                                        #
                                        #     global_1 = ["", "", ""]
                                        #     global_1[0] = global_1_1[0].split(",")
                                        #     global_1[1] = global_1_1[1].split(",")
                                        #     global_1[2] = global_1_1[2].split(",")
                                        #     global_2 = ["", "", ""]
                                        #     global_2[0] = global_2_1[0].split(",")
                                        #     global_2[1] = global_2_1[1].split(",")
                                        #     global_2[2] = global_2_1[2].split(",")
                                        #
                                        #
                                        #     for i in range(3):
                                        #         print(chr(65 + i))
                                        #         if i != 2:
                                        #             print(self.euclidean(global_1[i][0], global_1[i + 1][0], global_1[i][1],
                                        #                          global_1[i + 1][1]))
                                        #             print(self.euclidean(global_2[i][0], global_2[i + 1][0], global_2[i][1],
                                        #                          global_2[i + 1][1]))
                                        #             print(
                                        #                 "------------------------------------------------------------------------")
                                        #         else:
                                        #             print(self.euclidean(global_1[i][0], global_1[i - 2][0], global_1[i][1],
                                        #                          global_1[i - 2][1]))
                                        #             print(self.euclidean(global_2[i][0], global_2[i - 2][0], global_2[i][1],
                                        #                          global_2[i - 2][1]))
                                        #             print(
                                        #                 "------------------------------------------------------------------------")
                                        #
                                        #     for i in range(len(global_1)):
                                        #         for j in range(len(global_1[i])):
                                        #             if j < 3:
                                        #                 global_1[i][j] = Decimal(global_1[i][j])
                                        #             else:
                                        #                 if Decimal(global_1[i][j]) < 0:
                                        #                     global_1[i][j] = Decimal(global_1[i][j]) + Decimal(360)
                                        #                 else:
                                        #                     global_1[i][j] = Decimal(global_1[i][j])
                                        #     for i in range(len(global_2)):
                                        #         for j in range(len(global_2[i])):
                                        #             if j < 3:
                                        #                 global_2[i][j] = Decimal(global_2[i][j])
                                        #             else:
                                        #                 if Decimal(global_2[i][j]) < 0:
                                        #                     global_2[i][j] = Decimal(global_2[i][j]) + Decimal(360)
                                        #                 else:
                                        #                     global_2[i][j] = Decimal(global_2[i][j])
                                        #
                                        #     global_1 = np.array(global_1)
                                        #     global_2 = np.array(global_2)
                                        #
                                        #     #距離計算
                                        #     for i in range(3):
                                        #         self.log.info(chr(65 + i))
                                        #         if i != 2:
                                        #             self.log.info(self.euclidean(global_1[i], global_1[i + 1]))
                                        #             self.log.info(self.euclidean(global_2[i], global_2[i + 1]))
                                        #
                                        #             self.log.info(
                                        #                 "------------------------------------------------------------------------")
                                        #         else:
                                        #             self.log.info(self.euclidean(global_1[i], global_1[i - 2]))
                                        #             self.log.info(self.euclidean(global_2[i], global_2[i - 2]))
                                        #             self.log.info(
                                        #                 "------------------------------------------------------------------------")
                                        #
                                        #     self.log.info(
                                        #         "------------------------------------------------------------------------")
                                        #
                                        #     v1_1 = global_1[0] - global_1[1]
                                        #     for j in range(len(v1_1)):
                                        #         if Decimal(v1_1[j]) < 0:
                                        #             v1_1[j] = Decimal(v1_1[j]) + Decimal(360)
                                        #         else:
                                        #             v1_1[j] = Decimal(v1_1[j])
                                        #
                                        #
                                        #
                                        #     self.log.info("V1", v1_1)
                                        #     self.log.info(
                                        #         "------------------------------------------------------------------------")
                                        #     v2_1 = global_2[0] - global_2[1]
                                        #     for j in range(len(v2_1)):
                                        #         if Decimal(v2_1[j]) < 0:
                                        #             v2_1[j] = Decimal(v2_1[j]) + Decimal(360)
                                        #         else:
                                        #             v2_1[j] = Decimal(v2_1[j])
                                        #
                                        #     print("V2", v2_1)
                                        #     V1 = [v1_1[0], v1_1[1]]
                                        #     V2 = [v2_1[0], v2_1[1]]
                                        #     theta = self.clockwise_angle(V1, V2)
                                        #     self.log.info(
                                        #         "------------------------------------------------------------------------")
                                        #     self.log.info("theta", theta * 180 / np.pi)
                                        #
                                        #     a = global_1[0] - global_2[0]
                                        #
                                        #     b = global_1[1] - global_2[1]
                                        #
                                        #     c = global_1[2] - global_2[2]
                                        #
                                        #     print(a,b,c)
                                        # # 判斷偏移大小
                                        # for i in range(2):
                                        #     if abs(a[i] - b[i]) > Decimal("0.8"):
                                        #         print("hia")
                                        #     if abs(b[i] - c[i]) > Decimal("0.8"):
                                        #         print("hib")
                                        #     if abs(c[i] - a[i]) > Decimal("0.8"):
                                        #         print("hic")
                                        #
                                        #     a = np.array([a, b, c])
                                        #
                                        #     a = np.mean(a, axis=0) #算術平均
                                        #
                                        #     offset_x = float(a[0].quantize(Decimal('.00'), ROUND_HALF_UP))
                                        #     offset_y = float(a[1].quantize(Decimal('.00'), ROUND_HALF_UP))
                                        #
                                        #     self.sql.Ins_TM([offset_x, offset_y, theta])
                                        #
                                        #     self.weight(global_1,global_2)
                                        # else:
                                        self.sql.Ins_TM(offset)#插入SQLITE
                                        self.sockClient.sendall(self.SendTMSCT('ScriptExit()').encode())#退出LISTEN
                                        Cycle = False
                            # sleep(3)
                            # self.sockClient.sendall(self.SendTMSCT('ScriptExit()').encode())
                            # print(self.sockClient.recv(1024))
                            self.TMloop = False
                            self.log.info('bye')
                        elif a[4] == "give_pos_data_2":#執行動作
                            self.sockClient.sendall(self.SendTMSCT('ListenSend(90, var_allpos)').encode())#發送執行命令
                            while True:
                                b = self.sockClient.recv(1024).decode()
                                a = b.split(",")
                                # self.log.info(a)
                                if len(a) > 3:
                                    if a[2] == '90':
                                        self.log.info(b)
                                        c = self.rule.findall(b)[0]
                                        self.log.info(c)
                                        c = c.replace("}", "").split("{")
                                        c.pop(0)
                                        c[1] = c[1].split(",")

                                        self.log.info(c)
                                        print(self.ac_list)
                                        try:
                                            RK1_1 = [0, 8, 9, 10, 1, 2, 3 ]
                                            RK1_2 = [0, 11, 12, 4, 5]
                                            RK1_3 = [0, 13, 14, 6, 7]
                                            RK2_1 = [0, 1, 2, 3, 6, 7, 8]
                                            RK2_2 = [0, 4, 5, 9, 10]

                                            # d = self.sql.Get_TM(c[0][0])[0][int(self.ac_list[1])]
                                            if self.ac_list[1][:2] == "RK" or self.ac_list[1][:2] == "EQ":#計算欲到達格子
                                                self.tmp = int(self.ac_list[3])
                                                self.tmp1 = (ord(self.ac_list[2]) - 65) % 2
                                                if self.ac_list[1][:2] == "RK":
                                                    if self.ac_list[1][:3] == "RK1":
                                                            try:
                                                                self.pos = RK1_1.index(self.tmp1 * 7 + self.tmp)
                                                            except:
                                                                try:
                                                                    self.pos = RK1_2.index(self.tmp1 * 7 + self.tmp)
                                                                except:
                                                                    self.pos = RK1_3.index(self.tmp1 * 7 + self.tmp)
                                                    else:
                                                        try:
                                                            self.pos = RK2_1.index(self.tmp1 * 5 + self.tmp)
                                                        except:
                                                            self.pos = RK2_2.index(self.tmp1 * 5 + self.tmp)
                                                else:
                                                    self.pos = self.tmp

                                            elif self.ac_list[4][:2] == "RK" or self.ac_list[4][:2] == "EQ":#計算欲到達格子
                                                self.tmp = int(self.ac_list[6])
                                                self.tmp1 = (ord(self.ac_list[5]) - 65) % 2
                                                if self.ac_list[4][:2] == "RK":
                                                    if self.ac_list[4][:3] == "RK1":
                                                        try:
                                                            self.pos = RK1_1.index(self.tmp1 * 7 + self.tmp)
                                                        except:
                                                            try:
                                                                self.pos = RK1_2.index(self.tmp1 * 7 + self.tmp)
                                                            except:
                                                                self.pos = RK1_3.index(self.tmp1 * 7 + self.tmp)
                                                    else:
                                                        try:
                                                            self.pos = RK2_1.index(self.tmp1 * 5 + self.tmp)
                                                        except:
                                                            self.pos = RK2_2.index(self.tmp1 * 5 + self.tmp)
                                                else:
                                                    self.pos = self.tmp

                                            self.log.info(self.tmp1 * 7 + self.tmp)
                                            print(c[0])
                                            M1 = self.sql.Get_TM(c[0])[0][self.pos+1]
                                            M0 = self.sql.Get_TM(c[0])[0][1]
                                            # M1 = self.sql.Get_TM("M0_M4")[0][2]
                                            # M0 = self.sql.Get_TM("M0_M4")[0][1]
                                            # G_Master = self.sql.Get_TM_all("G_Master")[0]
                                            # L_Master = self.sql.Get_TM_all("L_Master")[0]
                                        except Exception as e:
                                            print(e)
                                            My_global.set_error(str(e))
                                            while True:
                                                if My_global.get_error() == None:
                                                    break
                                                sleep(0.5)
                                        self.log.info(str(M1))
                                        self.log.info(str(self.pos+1))
                                        if M1:
                                            M1 = M1.split(",")
                                            M0 = M0.split(",")
                                            c = c[1]
                                            self.log.info("M1="+str(M1))
                                            self.log.info("M0="+str(M0))
                                            self.log.info("M0'"+str(c))

                                            #旋轉矩陣計算
                                            angle = -(Decimal(c[5]) - Decimal(M0[5]))

                                            M0x = Decimal(M0[0]) * Decimal(cos(angle * Decimal(pi) / 180)) + Decimal(
                                                M0[1]) * Decimal(sin(angle * Decimal(pi) / 180))
                                            M0y = Decimal(M0[1]) * Decimal(cos(angle * Decimal(pi) / 180)) - Decimal(
                                                M0[0]) * Decimal(sin(angle * Decimal(pi) / 180))
                                            dx = Decimal(c[0]) - M0x
                                            dy = Decimal(c[1]) - M0y
                                            x = Decimal(M1[0]) * Decimal(cos(angle * Decimal(pi) / 180)) + Decimal(
                                                M1[1]) * Decimal(sin(angle * Decimal(pi) / 180)) + dx
                                            y = Decimal(M1[1]) * Decimal(cos(angle * Decimal(pi) / 180)) - Decimal(
                                                M1[0]) * Decimal(sin(angle * Decimal(pi) / 180)) + dy

                                            # print("------")
                                            # print(str(M1[1]))
                                            # print(str(cos(angle)))
                                            # print(str(M1[0]))
                                            # print(str(sin(angle)))
                                            # print(str(Decimal(M0[1]) -  Decimal(c[1])))
                                            # print("------")
                                            self.log.info("angle=" + str(angle))

                                            data = str([float(x.quantize(Decimal('.00'), ROUND_HALF_UP)), float(y.quantize(Decimal('.00'), ROUND_HALF_UP)),
                                                        c[2],  M1[3],  M1[4],  float(Decimal(M1[5])-Decimal(angle))]).replace("[", "{").replace("]", "}").replace("'", "")

                                            self.log.info("data" + data)
                                        else:
                                            data = ''
                                            self.log.info("找不到輸入的QRcode")
                                        break
                            # sleep(0.5)
                            self.sockClient.sendall(self.SendTMSCT('var_targetpos = ' + data +'\r\nScriptExit()').encode())
                            # self.sockClient.sendall(self.SendTMSCT('ScriptExit()').encode())
                            self.log.info('var_targetpos = ' + data +'\r\nScriptExit()')
                            print(self.sockClient.recv(1024).decode())
                            self.TMloop = False
            except socket.error as e:
                print(e)
                self.k.Del_logging()
                self.k.Getlogger("TM.log")
                self.sockClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.sockClient.settimeout(3)
                self.sockClient.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 60 * 1000, 30 * 1000))
                with open(os.getcwd() + "/IP.txt") as f:
                    self.IP = f.read().strip()
                try:
                    # self.sockClient.connect(('localhost', 5890))
                    self.Disconnecttimes = 0
                    self.sockClient.connect((self.IP, 5890))
                    self.Disconnect = True
                except:
                    self.Disconnecttimes += 1
                    self.Disconnect = False
                    self.log.info("Robot Not Connect!")

            # except socket.error:
            #     break
            # except Exception as e:
            #     self.log.info(e)
            #     # self.log.info('var_test = "' + str(self.action) + '"\r\nScriptExit()')
            #     break
        mbsev.conn.close()
        self.sockClient.close()
        self.log.info('CONNECTTM OUT LOOP')
        self.k.Del_logging()
        sleep(0.1)

    def Average(self, lst):
        return sum(lst) / len(lst)

    def clockwise_angle(self,v1, v2):
        x1, y1 = v1
        x2, y2 = v2
        dot = float(x1 * x2 + y1 * y2)
        det = float(x1 * y2 - y1 * x2)
        theta = np.arctan2(det, dot)
        theta = theta if theta > 0 else 2 * np.pi + theta
        return theta

    def euclidean(self, p1, p2):
        _p1 = np.array([p1[0], p1[1]])
        _p2 = np.array([p2[0], p2[1]])
        p3 = p2 - p1
        return hypot(p3[0], p3[1])

    def weight(self, G1, G2):
        g1_avg = []
        g2_avg = []
        for i in range(3):
            g1_avg.append(G1[i] - G1[0])
            g2_avg.append(G2[i] - G2[0])
        g1_avg = np.mean(g1_avg, axis=0)
        g2_avg = np.mean(g2_avg, axis=0)
        return [g2_avg[0] - g1_avg[0], g2_avg[1] - g1_avg[1]]

if __name__ == '__main__':
    a = TM("MIX-MR1-A-01-EQ1-A-01-Z","123")
    a.start()


#!/usr/bin/env python
"""Train VAE-GAN."""
import os
import sys
import logging
import argparse

import torch
import numpy as np

import spml.dataloader
import spml.models.vae_gan
import spml.trainer.vae_gan

_LG = logging.getLogger(__name__)
_THIS_DIR = os.path.dirname(__file__)

def _parse_args():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
        '--train-flist', required=True,
        help='Path to text file with list of trainig image paths.'
    )
    parser.add_argument(
        '--test-flist', required=True,
        help='Path to text file with list of test image paths.'
    )
    parser.add_argument(
        '--data-dir', required=True,
        help='Directory where train/test images are found.',
    )
    parser.add_argument(
        '--output-dir', '-o',
        default=os.path.join(_THIS_DIR, 'results', 'output'),
    )
    parser.add_argument(
        '--epoch', type=int, default=10,
    )
    parser.add_argument(
        '--lr', type=float, default=1e-4,
        help='Learning rate'
    )
    parser.add_argument(
        '--batch-size', type=int, default=64,
        help='Batch size',
    )
    parser.add_argument(
        '--checkpoint',
        help='Checkpoint file for resume training',
    )
    parser.add_argument(
        '--debug', action='store_true',
    )
    parser.add_argument(
        '--no-cuda', action='store_true',
    )
    return parser.parse_args()

def _get_samples(num_features, device, batch_size=32, seed=0):
    rng = np.random.RandomState(seed)
    samples = rng.randn(batch_size, num_features)
    return torch.tensor(samples, device=device).float().to(device)

def _load_keyframe_flist(flist):
    ret = []
    with open(flist, 'r') as fileobj:
        for line in fileobj:
            line = line.strip()
            if not line or line.startswith('#'):
                continue
            path, _ = line.split('\t')
            ret.append(path)
    return ret

def _get_trainer(args):
    device = torch.device(
        'cuda' if torch.cuda.is_available() and not args.no_cuda else 'cpu')

    # Aspect ratio of Switch is 16:9, so we use 16 x 9 x C as size of encoded
    # features.
    # Each decoding block performs downsampling by x2 then -1. So for level-3
    # convolution, input size is (f(f(f(16))), f(f(f(9)))) = (121, 65)
    # where f(x) = 2x - 1
    scale = (121, 65)
    n_latent = 1024
    train_loader = spml.dataloader.get_dataloader(
        _load_keyframe_flist(args.train_flist), args.data_dir,
        args.batch_size, scale)
    # To output the same image over epochs to observe evolution of model,
    # disable shuffle and fix batch_size to 16 (unless smaller value is
    # provided via command line when batch does not fit on GPU memory)
    test_loader = spml.dataloader.get_dataloader(
        _load_keyframe_flist(args.test_flist), args.data_dir,
        min(16, args.batch_size), scale, shuffle=False,
    )
    model = spml.models.vae_gan.get_model(n_latent)
    opt = torch.optim.Adam
    optimizers = {
        'encoder': opt(model.vae.encoder.parameters(), lr=args.lr),
        'decoder': opt(model.vae.decoder.parameters(), lr=args.lr),
        'discriminator': opt(model.discriminator.parameters(), lr=args.lr),
    }
    samples = _get_samples(n_latent, device)
    trainer = spml.trainer.vae_gan.Trainer(
        model, optimizers, train_loader, test_loader, device, args.output_dir,
        samples=samples,
    )
    if args.checkpoint:
        trainer.load(args.checkpoint)
    return trainer

def _run_main(args):
    trainer = _get_trainer(args)
    _LG.info('\n%s', trainer)
    _LG.info('Batch size: %s', args.batch_size)
    trainer.test()
    trainer.generate()
    for _ in range(args.epoch):
        trainer.train_one_epoch()

def _main():
    args = _parse_args()
    os.makedirs(args.output_dir, exist_ok=True)
    _init_logger(args.debug, os.path.join(args.output_dir, 'train.log'))

    # Wrap main process so that stack trace shows up in log file.
    try:
        _run_main(args)
    except Exception:  # pylint: disable=broad-except
        _LG.exception('Unexpected error occured.')
        sys.exit(1)

def _init_logger(debug, logfile=None):
    format_ = (
        '%(asctime)s: %(levelname)5s: %(message)s' if not debug else
        '%(asctime)s: %(levelname)5s: %(funcName)10s: %(lineno)d %(message)s'
    )

    logging.basicConfig(
        format=format_,
        level=logging.DEBUG if debug else logging.INFO,
    )
    logging.getLogger('PIL').setLevel(logging.WARNING)

    if logfile:
        handler = logging.FileHandler(logfile)
        handler.setLevel(logging.INFO)
        formatter = logging.Formatter(format_)
        handler.setFormatter(formatter)
        logging.getLogger().addHandler(handler)

if __name__ == '__main__':
    _main()


# coding=utf-8
# This software includes the work that is distributed in the MIT License
# https://opensource.org/licenses/mit-license.php
import pypianoroll
import glob
import pickle
import gc
import os
from tqdm import tqdm
import numpy as np
from multiprocessing import Pool
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--dataset", help="source dir", default='lpd_5' )
parser.add_argument("--process", help="num process", type=int, default=8 )
parser.add_argument("--da", help="modulation for data augumantation (0-11)", type=int, default=5 )
parser.add_argument("--combine", help="combine data", type=int, default=50000 )
parser.add_argument("--output", help="output name", required=True )
args = parser.parse_args()

assert args.dataset=='lpd_5' or args.dataset=='lpd_17', 'Dataset requid "lpd_5" or "lpd_7"'

if args.dataset=='lpd_5':
    tracks = ['Drums', 'Piano', 'Guitar', 'Bass', 'Strings']
    if os.path.isdir('lpd_5/lpd_5_full'):
        datas = 'lpd_5/lpd_5_full/*/*.npz'
    elif os.path.isdir('lpd_5/lpd_5_cleansed'):
        datas = 'lpd_5/lpd_5_cleansed/*/*/*/*/*.npz'
    else:
        print('invalid dataset')
        exit()
else:
    tracks = ['Drums', 'Piano', 'Chromatic Percussion', 'Organ', 'Guitar', 'Bass', 'Strings', 'Ensemble', 'Brass', 'Reed', 'Pipe', 'Synth Lead', 'Synth Pad', 'Synth Effects', 'Ethnic', 'Percussive', 'Sound Effects']
    if os.path.isdir('lpd_17/lpd_17_full'):
        datas = 'lpd_17/lpd_17_full/*/*.npz'
    elif os.path.isdir('lpd_17/lpd_17_cleansed'):
        datas = 'lpd_17/lpd_17_cleansed/*/*/*/*/*.npz'
    else:
        print('invalid dataset')
        exit()

trc_len = len(tracks)
trc_idx = sorted(list(range(trc_len)), key=lambda x:0 if tracks[x]=='Bass' else 1) # fist 3 is: Bass, Drums, Piano
trc_avg_c = [[0,0] for _ in tracks]

pianoroll_files = []
note_size = 84
note_offset = 24
time_note = note_size*trc_len + 1
end_note = note_size*trc_len + 2
print('step 1/3.')
for fn in tqdm(glob.glob(datas)):
    pianoroll_files.append(fn)
    m = pypianoroll.load(fn)
    pr = m.get_stacked_pianoroll()
    pr = pr[:,:,trc_idx]
    p = np.where(pr != 0)
    for i in np.argsort(p[0]):
        trc_avg_c[p[2][i]][0] += p[1][i]
        trc_avg_c[p[2][i]][1] += 1
    del m, pr, p

trc_avg = [((trc_avg_c[i][0] / trc_avg_c[i][1]) if trc_avg_c[i][1] > 0 else 60) for i in range(trc_len)]
del trc_avg_c
gc.collect()

print('step 2/3.')
def _run(fn):
    seq = []
    m = pypianoroll.load(fn)
    step = m.beat_resolution // 4  # 16 beat minimum
    pr = m.get_stacked_pianoroll()
    pr = pr[:,:,trc_idx]
    p = np.where(pr != 0)
    cur_avg_c = [[0,0] for _ in tracks]
    for i in range(len(p[0])):
        cur_avg_c[p[2][i]][0] += p[1][i]
        cur_avg_c[p[2][i]][1] += 1
    cur_avg = [((cur_avg_c[i][0] / cur_avg_c[i][1]) if cur_avg_c[i][1] > 0 else 60) for i in range(trc_len)]
    modulation = [0] + (np.random.permutation(11)+1).tolist()
    current_seq = []
    def _current(cur_seq):
        cur = []
        for c in sorted(cur_seq):
            if not (c >= note_size and c < note_size*2):
                cur.append(c)
        for c in sorted(cur_seq):
            if (c >= note_size and c < note_size*2):
                cur.append(c)
        return cur # Bass, Piano, etc..., Drums
    for s in modulation[:args.da+1]:  # Data augumantation
        pos = 0
        for i in np.argsort(p[0]):
            if p[0][i] % step != 0:
                continue
            if pos < p[0][i]:
                for _ in range(pos,p[0][i],step):
                    seq.extend(_current(current_seq))
                    seq.append(time_note)
                    current_seq = []
            pos = p[0][i]
            j = p[1][i]
            t = p[2][i]

            shift = 0
            if t != 1:
                if cur_avg[t] + s < trc_avg[t] + 6:
                    shift = s
                else:
                    shift = s-12

            j = j + shift
            if j < 0:
                j += 12
            if j > 0x7f:
                j -= 12
            j -= note_offset
            if j < 0:
                j = 0
            if j > note_size:
                j = note_size-1
            note = t*note_size + j
            current_seq.append(note)
        seq.extend(_current(current_seq))
        seq.append(time_note)
        seq.append(end_note)
        current_seq = []
    with open(fn+'.tmp', mode='wb') as f:
        pickle.dump(seq, f)

with tqdm(total=len(pianoroll_files)) as t:
    with Pool(args.process) as p:
        for _ in p.imap_unordered(_run, pianoroll_files):
            t.update(1)

numfiles = 0
chunks = []
current_chunk = []
print('step 3/3.')
for fn in tqdm(pianoroll_files):
    with open(fn+'.tmp', mode='rb') as f:
        file_chunk = pickle.load(f)
    for note in file_chunk:
        current_chunk.append(note)
        if len(current_chunk) > args.combine:
            chunks.append(np.stack(current_chunk))
            current_chunk = []
    if len(chunks) > 32000:
        numfiles += 1
        np.savez_compressed(args.output+'_%02d.npz'%numfiles, *chunks)
        chunks = []
numfiles += 1
chunks.append(current_chunk)
np.savez_compressed(args.output+'_%02d.npz'%numfiles, *chunks)
chunks = []
with open(args.output+'.trc', 'w') as f:
    f.write(','.join([tracks[t] for t in trc_idx]))


import numpy as np
import torch
from torch import nn
import os
from collections import OrderedDict
from torch.autograd import Variable
import util.util as util
from collections import OrderedDict
from torch.autograd import Variable
import itertools
import util.util as util
from util.image_pool import ImagePool
from .base_model import BaseModel
import random
from . import networks
import sys

class SingleModel(BaseModel):
    def name(self):
        return 'SingleGANModel'

    def initialize(self, opt):
        BaseModel.initialize(self, opt)

        nb = opt.batchSize
        size = opt.fineSize
        self.opt = opt
        self.input_A = self.Tensor(nb, opt.input_nc, size, size)
        self.input_B = self.Tensor(nb, opt.output_nc, size, size)
        self.input_img = self.Tensor(nb, opt.input_nc, size, size)
        self.input_A_gray = self.Tensor(nb, 1, size, size)

        if opt.vgg > 0:
            self.vgg_loss = networks.PerceptualLoss(opt)
            if self.opt.IN_vgg:
                self.vgg_patch_loss = networks.PerceptualLoss(opt)
                self.vgg_patch_loss.cuda()
            self.vgg_loss.cuda()
            self.vgg = networks.load_vgg16("./model", self.gpu_ids)
            self.vgg.eval()
            for param in self.vgg.parameters():
                param.requires_grad = False
        elif opt.fcn > 0:
            self.fcn_loss = networks.SemanticLoss(opt)
            self.fcn_loss.cuda()
            self.fcn = networks.load_fcn("./model")
            self.fcn.eval()
            for param in self.fcn.parameters():
                param.requires_grad = False
        # load/define networks
        # The naming conversion is different from those used in the paper
        # Code (paper): G_A (G), G_B (F), D_A (D_Y), D_B (D_X)

        skip = True if opt.skip > 0 else False
        self.netG_A = networks.define_G(opt.input_nc, opt.output_nc,
                                        opt.ngf, opt.which_model_netG, opt.norm, not opt.no_dropout, self.gpu_ids, skip=skip, opt=opt)
        # self.netG_B = networks.define_G(opt.output_nc, opt.input_nc,
        #                                 opt.ngf, opt.which_model_netG, opt.norm, not opt.no_dropout, self.gpu_ids, skip=False, opt=opt)

        if self.isTrain:
            use_sigmoid = opt.no_lsgan
            self.netD_A = networks.define_D(opt.output_nc, opt.ndf,
                                            opt.which_model_netD,
                                            opt.n_layers_D, opt.norm, use_sigmoid, self.gpu_ids, False)
            if self.opt.patchD:
                self.netD_P = networks.define_D(opt.input_nc, opt.ndf,
                                            opt.which_model_netD,
                                            opt.n_layers_patchD, opt.norm, use_sigmoid, self.gpu_ids, True)
        if not self.isTrain or opt.continue_train:
            which_epoch = opt.which_epoch
            self.load_network(self.netG_A, 'G_A', which_epoch)
            # self.load_network(self.netG_B, 'G_B', which_epoch)
            if self.isTrain:
                self.load_network(self.netD_A, 'D_A', which_epoch)
                if self.opt.patchD:
                    self.load_network(self.netD_P, 'D_P', which_epoch)

        if self.isTrain:
            self.old_lr = opt.lr
            # self.fake_A_pool = ImagePool(opt.pool_size)
            self.fake_B_pool = ImagePool(opt.pool_size)
            # define loss functions
            if opt.use_wgan:
                self.criterionGAN = networks.DiscLossWGANGP()
            else:
                self.criterionGAN = networks.GANLoss(use_lsgan=not opt.no_lsgan, tensor=self.Tensor)
            if opt.use_mse:
                self.criterionCycle = torch.nn.MSELoss()
            else:
                self.criterionCycle = torch.nn.L1Loss()
            self.criterionL1 = torch.nn.L1Loss()
            self.criterionIdt = torch.nn.L1Loss()
            # initialize optimizers
            self.optimizer_G = torch.optim.Adam(self.netG_A.parameters(),
                                                lr=opt.lr, betas=(opt.beta1, 0.999))
            self.optimizer_D_A = torch.optim.Adam(self.netD_A.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))
            if self.opt.patchD:
                self.optimizer_D_P = torch.optim.Adam(self.netD_P.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))

        print('---------- Networks initialized -------------')
        networks.print_network(self.netG_A)
        # networks.print_network(self.netG_B)
        if self.isTrain:
            networks.print_network(self.netD_A)
            if self.opt.patchD:
                networks.print_network(self.netD_P)
            # networks.print_network(self.netD_B)
        if opt.isTrain:
            self.netG_A.train()
            # self.netG_B.train()
        else:
            self.netG_A.eval()
            # self.netG_B.eval()
        print('-----------------------------------------------')

    def set_input(self, input):
        AtoB = self.opt.which_direction == 'AtoB'
        input_A = input['A' if AtoB else 'B']
        input_B = input['B' if AtoB else 'A']
        input_img = input['input_img']
        input_A_gray = input['A_gray']
        self.input_A.resize_(input_A.size()).copy_(input_A)
        self.input_A_gray.resize_(input_A_gray.size()).copy_(input_A_gray)
        self.input_B.resize_(input_B.size()).copy_(input_B)
        self.input_img.resize_(input_img.size()).copy_(input_img)
        self.image_paths = input['A_paths' if AtoB else 'B_paths']

    def test(self):
        self.real_A = Variable(self.input_A, volatile=True)
        self.real_A_gray = Variable(self.input_A_gray, volatile=True)
        if self.opt.noise > 0:
            self.noise = Variable(torch.cuda.FloatTensor(self.real_A.size()).normal_(mean=0, std=self.opt.noise/255.))
            self.real_A = self.real_A + self.noise
        if self.opt.input_linear:
            self.real_A = (self.real_A - torch.min(self.real_A))/(torch.max(self.real_A) - torch.min(self.real_A))
        # print(np.transpose(self.real_A.data[0].cpu().float().numpy(),(1,2,0))[:2][:2][:])
        if self.opt.skip == 1:
            self.fake_B, self.latent_real_A = self.netG_A.forward(self.real_A, self.real_A_gray)
        else:
            self.fake_B = self.netG_A.forward(self.real_A, self.real_A_gray)
        # self.rec_A = self.netG_B.forward(self.fake_B)

        self.real_B = Variable(self.input_B, volatile=True)

    def predict(self):
        self.real_A = Variable(self.input_A, volatile=True)
        self.real_A_gray = Variable(self.input_A_gray, volatile=True)
        if self.opt.noise > 0:
            self.noise = Variable(torch.cuda.FloatTensor(self.real_A.size()).normal_(mean=0, std=self.opt.noise/255.))
            self.real_A = self.real_A + self.noise
        if self.opt.input_linear:
            self.real_A = (self.real_A - torch.min(self.real_A))/(torch.max(self.real_A) - torch.min(self.real_A))
        # print(np.transpose(self.real_A.data[0].cpu().float().numpy(),(1,2,0))[:2][:2][:])
        if self.opt.skip == 1:
            self.fake_B, self.latent_real_A = self.netG_A.forward(self.real_A, self.real_A_gray)
        else:
            self.fake_B = self.netG_A.forward(self.real_A, self.real_A_gray)
        # self.rec_A = self.netG_B.forward(self.fake_B)

        real_A = util.tensor2im(self.real_A.data)
        fake_B = util.tensor2im(self.fake_B.data)
        A_gray = util.atten2im(self.real_A_gray.data)
        # rec_A = util.tensor2im(self.rec_A.data)
        # if self.opt.skip == 1:
        #     latent_real_A = util.tensor2im(self.latent_real_A.data)
        #     latent_show = util.latent2im(self.latent_real_A.data)
        #     max_image = util.max2im(self.fake_B.data, self.latent_real_A.data)
        #     return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('latent_real_A', latent_real_A),
        #                     ('latent_show', latent_show), ('max_image', max_image), ('A_gray', A_gray)])
        # else:
        #     return OrderedDict([('real_A', real_A), ('fake_B', fake_B)])
        # return OrderedDict([('fake_B', fake_B)])
        return OrderedDict([('real_A', real_A), ('fake_B', fake_B)])

    # get image paths
    def get_image_paths(self):
        return self.image_paths

    def backward_D_basic(self, netD, real, fake, use_ragan):
        # Real
        pred_real = netD.forward(real)
        pred_fake = netD.forward(fake.detach())
        if self.opt.use_wgan:
            loss_D_real = pred_real.mean()
            loss_D_fake = pred_fake.mean()
            loss_D = loss_D_fake - loss_D_real + self.criterionGAN.calc_gradient_penalty(netD,
                                                real.data, fake.data)
        elif self.opt.use_ragan and use_ragan:
            loss_D = (self.criterionGAN(pred_real - torch.mean(pred_fake), True) +
                                      self.criterionGAN(pred_fake - torch.mean(pred_real), False)) / 2
        else:
            loss_D_real = self.criterionGAN(pred_real, True)
            loss_D_fake = self.criterionGAN(pred_fake, False)
            loss_D = (loss_D_real + loss_D_fake) * 0.5
        # loss_D.backward()
        return loss_D

    def backward_D_A(self):
        fake_B = self.fake_B_pool.query(self.fake_B)
        fake_B = self.fake_B
        self.loss_D_A = self.backward_D_basic(self.netD_A, self.real_B, fake_B, True)
        self.loss_D_A.backward()

    def backward_D_P(self):
        if self.opt.hybrid_loss:
            loss_D_P = self.backward_D_basic(self.netD_P, self.real_patch, self.fake_patch, False)
            if self.opt.patchD_3 > 0:
                for i in range(self.opt.patchD_3):
                    loss_D_P += self.backward_D_basic(self.netD_P, self.real_patch_1[i], self.fake_patch_1[i], False)
                self.loss_D_P = loss_D_P/float(self.opt.patchD_3 + 1)
            else:
                self.loss_D_P = loss_D_P
        else:
            loss_D_P = self.backward_D_basic(self.netD_P, self.real_patch, self.fake_patch, True)
            if self.opt.patchD_3 > 0:
                for i in range(self.opt.patchD_3):
                    loss_D_P += self.backward_D_basic(self.netD_P, self.real_patch_1[i], self.fake_patch_1[i], True)
                self.loss_D_P = loss_D_P/float(self.opt.patchD_3 + 1)
            else:
                self.loss_D_P = loss_D_P
        if self.opt.D_P_times2:
            self.loss_D_P = self.loss_D_P*2
        self.loss_D_P.backward()

    # def backward_D_B(self):
    #     fake_A = self.fake_A_pool.query(self.fake_A)
    #     self.loss_D_B = self.backward_D_basic(self.netD_B, self.real_A, fake_A)
    def forward(self):
        self.real_A = Variable(self.input_A)
        self.real_B = Variable(self.input_B)
        self.real_A_gray = Variable(self.input_A_gray)
        self.real_img = Variable(self.input_img)
        if self.opt.noise > 0:
            self.noise = Variable(torch.cuda.FloatTensor(self.real_A.size()).normal_(mean=0, std=self.opt.noise/255.))
            self.real_A = self.real_A + self.noise
        if self.opt.input_linear:
            self.real_A = (self.real_A - torch.min(self.real_A))/(torch.max(self.real_A) - torch.min(self.real_A))
        if self.opt.skip == 1:
            self.fake_B, self.latent_real_A = self.netG_A.forward(self.real_img, self.real_A_gray)
        else:
            self.fake_B = self.netG_A.forward(self.real_img, self.real_A_gray)
        if self.opt.patchD:
            w = self.real_A.size(3)
            h = self.real_A.size(2)
            w_offset = random.randint(0, max(0, w - self.opt.patchSize - 1))
            h_offset = random.randint(0, max(0, h - self.opt.patchSize - 1))

            self.fake_patch = self.fake_B[:,:, h_offset:h_offset + self.opt.patchSize,
                   w_offset:w_offset + self.opt.patchSize]
            self.real_patch = self.real_B[:,:, h_offset:h_offset + self.opt.patchSize,
                   w_offset:w_offset + self.opt.patchSize]
            self.input_patch = self.real_A[:,:, h_offset:h_offset + self.opt.patchSize,
                   w_offset:w_offset + self.opt.patchSize]
        if self.opt.patchD_3 > 0:
            self.fake_patch_1 = []
            self.real_patch_1 = []
            self.input_patch_1 = []
            w = self.real_A.size(3)
            h = self.real_A.size(2)
            for i in range(self.opt.patchD_3):
                w_offset_1 = random.randint(0, max(0, w - self.opt.patchSize - 1))
                h_offset_1 = random.randint(0, max(0, h - self.opt.patchSize - 1))
                self.fake_patch_1.append(self.fake_B[:,:, h_offset_1:h_offset_1 + self.opt.patchSize,
                    w_offset_1:w_offset_1 + self.opt.patchSize])
                self.real_patch_1.append(self.real_B[:,:, h_offset_1:h_offset_1 + self.opt.patchSize,
                    w_offset_1:w_offset_1 + self.opt.patchSize])
                self.input_patch_1.append(self.real_A[:,:, h_offset_1:h_offset_1 + self.opt.patchSize,
                    w_offset_1:w_offset_1 + self.opt.patchSize])

            # w_offset_2 = random.randint(0, max(0, w - self.opt.patchSize - 1))
            # h_offset_2 = random.randint(0, max(0, h - self.opt.patchSize - 1))
            # self.fake_patch_2 = self.fake_B[:,:, h_offset_2:h_offset_2 + self.opt.patchSize,
            #        w_offset_2:w_offset_2 + self.opt.patchSize]
            # self.real_patch_2 = self.real_B[:,:, h_offset_2:h_offset_2 + self.opt.patchSize,
            #        w_offset_2:w_offset_2 + self.opt.patchSize]
            # self.input_patch_2 = self.real_A[:,:, h_offset_2:h_offset_2 + self.opt.patchSize,
            #        w_offset_2:w_offset_2 + self.opt.patchSize]

    def backward_G(self, epoch):
        pred_fake = self.netD_A.forward(self.fake_B)
        if self.opt.use_wgan:
            self.loss_G_A = -pred_fake.mean()
        elif self.opt.use_ragan:
            pred_real = self.netD_A.forward(self.real_B)

            self.loss_G_A = (self.criterionGAN(pred_real - torch.mean(pred_fake), False) +
                                      self.criterionGAN(pred_fake - torch.mean(pred_real), True)) / 2

        else:
            self.loss_G_A = self.criterionGAN(pred_fake, True)

        loss_G_A = 0
        if self.opt.patchD:
            pred_fake_patch = self.netD_P.forward(self.fake_patch)
            if self.opt.hybrid_loss:
                loss_G_A += self.criterionGAN(pred_fake_patch, True)
            else:
                pred_real_patch = self.netD_P.forward(self.real_patch)

                loss_G_A += (self.criterionGAN(pred_real_patch - torch.mean(pred_fake_patch), False) +
                                      self.criterionGAN(pred_fake_patch - torch.mean(pred_real_patch), True)) / 2
        if self.opt.patchD_3 > 0:
            for i in range(self.opt.patchD_3):
                pred_fake_patch_1 = self.netD_P.forward(self.fake_patch_1[i])
                if self.opt.hybrid_loss:
                    loss_G_A += self.criterionGAN(pred_fake_patch_1, True)
                else:
                    pred_real_patch_1 = self.netD_P.forward(self.real_patch_1[i])

                    loss_G_A += (self.criterionGAN(pred_real_patch_1 - torch.mean(pred_fake_patch_1), False) +
                                        self.criterionGAN(pred_fake_patch_1 - torch.mean(pred_real_patch_1), True)) / 2

            if not self.opt.D_P_times2:
                self.loss_G_A += loss_G_A/float(self.opt.patchD_3 + 1)
            else:
                self.loss_G_A += loss_G_A/float(self.opt.patchD_3 + 1)*2
        else:
            if not self.opt.D_P_times2:
                self.loss_G_A += loss_G_A
            else:
                self.loss_G_A += loss_G_A*2

        if epoch < 0:
            vgg_w = 0
        else:
            vgg_w = 1
        if self.opt.vgg > 0:
            self.loss_vgg_b = self.vgg_loss.compute_vgg_loss(self.vgg,
                    self.fake_B, self.real_A) * self.opt.vgg if self.opt.vgg > 0 else 0
            if self.opt.patch_vgg:
                if not self.opt.IN_vgg:
                    loss_vgg_patch = self.vgg_loss.compute_vgg_loss(self.vgg,
                    self.fake_patch, self.input_patch) * self.opt.vgg
                else:
                    loss_vgg_patch = self.vgg_patch_loss.compute_vgg_loss(self.vgg,
                    self.fake_patch, self.input_patch) * self.opt.vgg
                if self.opt.patchD_3 > 0:
                    for i in range(self.opt.patchD_3):
                        if not self.opt.IN_vgg:
                            loss_vgg_patch += self.vgg_loss.compute_vgg_loss(self.vgg,
                                self.fake_patch_1[i], self.input_patch_1[i]) * self.opt.vgg
                        else:
                            loss_vgg_patch += self.vgg_patch_loss.compute_vgg_loss(self.vgg,
                                self.fake_patch_1[i], self.input_patch_1[i]) * self.opt.vgg
                    self.loss_vgg_b += loss_vgg_patch/float(self.opt.patchD_3 + 1)
                else:
                    self.loss_vgg_b += loss_vgg_patch
            self.loss_G = self.loss_G_A + self.loss_vgg_b*vgg_w
        elif self.opt.fcn > 0:
            self.loss_fcn_b = self.fcn_loss.compute_fcn_loss(self.fcn,
                    self.fake_B, self.real_A) * self.opt.fcn if self.opt.fcn > 0 else 0
            if self.opt.patchD:
                loss_fcn_patch = self.fcn_loss.compute_vgg_loss(self.fcn,
                    self.fake_patch, self.input_patch) * self.opt.fcn
                if self.opt.patchD_3 > 0:
                    for i in range(self.opt.patchD_3):
                        loss_fcn_patch += self.fcn_loss.compute_vgg_loss(self.fcn,
                            self.fake_patch_1[i], self.input_patch_1[i]) * self.opt.fcn
                    self.loss_fcn_b += loss_fcn_patch/float(self.opt.patchD_3 + 1)
                else:
                    self.loss_fcn_b += loss_fcn_patch
            self.loss_G = self.loss_G_A + self.loss_fcn_b*vgg_w
        # self.loss_G = self.L1_AB + self.L1_BA
        self.loss_G.backward()

    # def optimize_parameters(self, epoch):
    #     # forward
    #     self.forward()
    #     # G_A and G_B
    #     self.optimizer_G.zero_grad()
    #     self.backward_G(epoch)
    #     self.optimizer_G.step()
    #     # D_A
    #     self.optimizer_D_A.zero_grad()
    #     self.backward_D_A()
    #     self.optimizer_D_A.step()
    #     if self.opt.patchD:
    #         self.forward()
    #         self.optimizer_D_P.zero_grad()
    #         self.backward_D_P()
    #         self.optimizer_D_P.step()
        # D_B
        # self.optimizer_D_B.zero_grad()
        # self.backward_D_B()
        # self.optimizer_D_B.step()
    def optimize_parameters(self, epoch):
        # forward
        self.forward()
        # G_A and G_B
        self.optimizer_G.zero_grad()
        self.backward_G(epoch)
        self.optimizer_G.step()
        # D_A
        self.optimizer_D_A.zero_grad()
        self.backward_D_A()
        if not self.opt.patchD:
            self.optimizer_D_A.step()
        else:
            # self.forward()
            self.optimizer_D_P.zero_grad()
            self.backward_D_P()
            self.optimizer_D_A.step()
            self.optimizer_D_P.step()

    def get_current_errors(self, epoch):
        D_A = self.loss_D_A.data[0]
        D_P = self.loss_D_P.data[0] if self.opt.patchD else 0
        G_A = self.loss_G_A.data[0]
        if self.opt.vgg > 0:
            vgg = self.loss_vgg_b.data[0]/self.opt.vgg if self.opt.vgg > 0 else 0
            return OrderedDict([('D_A', D_A), ('G_A', G_A), ("vgg", vgg), ("D_P", D_P)])
        elif self.opt.fcn > 0:
            fcn = self.loss_fcn_b.data[0]/self.opt.fcn if self.opt.fcn > 0 else 0
            return OrderedDict([('D_A', D_A), ('G_A', G_A), ("fcn", fcn), ("D_P", D_P)])

    def get_current_visuals(self):
        real_A = util.tensor2im(self.real_A.data)
        fake_B = util.tensor2im(self.fake_B.data)
        real_B = util.tensor2im(self.real_B.data)
        if self.opt.skip > 0:
            latent_real_A = util.tensor2im(self.latent_real_A.data)
            latent_show = util.latent2im(self.latent_real_A.data)
            if self.opt.patchD:
                fake_patch = util.tensor2im(self.fake_patch.data)
                real_patch = util.tensor2im(self.real_patch.data)
                if self.opt.patch_vgg:
                    input_patch = util.tensor2im(self.input_patch.data)
                    if not self.opt.self_attention:
                        return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('latent_real_A', latent_real_A),
                                ('latent_show', latent_show), ('real_B', real_B), ('real_patch', real_patch),
                                ('fake_patch', fake_patch), ('input_patch', input_patch)])
                    else:
                        self_attention = util.atten2im(self.real_A_gray.data)  #自注意
                        return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('latent_real_A', latent_real_A),
                                ('latent_show', latent_show), ('real_B', real_B), ('real_patch', real_patch),
                                ('fake_patch', fake_patch), ('input_patch', input_patch), ('self_attention', self_attention)])
                else:
                    if not self.opt.self_attention:
                        return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('latent_real_A', latent_real_A),
                                ('latent_show', latent_show), ('real_B', real_B), ('real_patch', real_patch),
                                ('fake_patch', fake_patch)])
                    else:
                        self_attention = util.atten2im(self.real_A_gray.data)
                        return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('latent_real_A', latent_real_A),
                                ('latent_show', latent_show), ('real_B', real_B), ('real_patch', real_patch),
                                ('fake_patch', fake_patch), ('self_attention', self_attention)])
            else:
                if not self.opt.self_attention:
                    return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('latent_real_A', latent_real_A),
                                ('latent_show', latent_show), ('real_B', real_B)])
                else:
                    self_attention = util.atten2im(self.real_A_gray.data)
                    return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('real_B', real_B),
                                    ('latent_real_A', latent_real_A), ('latent_show', latent_show),
                                    ('self_attention', self_attention)])
        else:
            if not self.opt.self_attention:
                return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('real_B', real_B)])
            else:
                self_attention = util.atten2im(self.real_A_gray.data)
                return OrderedDict([('real_A', real_A), ('fake_B', fake_B), ('real_B', real_B),
                                    ('self_attention', self_attention)])

    def save(self, label):
        self.save_network(self.netG_A, 'G_A', label, self.gpu_ids)
        self.save_network(self.netD_A, 'D_A', label, self.gpu_ids)
        if self.opt.patchD:
            self.save_network(self.netD_P, 'D_P', label, self.gpu_ids)
        # self.save_network(self.netG_B, 'G_B', label, self.gpu_ids)
        # self.save_network(self.netD_B, 'D_B', label, self.gpu_ids)

    def update_learning_rate(self):

        if self.opt.new_lr:
            lr = self.old_lr/2
        else:
            lrd = self.opt.lr / self.opt.niter_decay
            lr = self.old_lr - lrd
        for param_group in self.optimizer_D_A.param_groups:
            param_group['lr'] = lr
        if self.opt.patchD:
            for param_group in self.optimizer_D_P.param_groups:
                param_group['lr'] = lr
        for param_group in self.optimizer_G.param_groups:
            param_group['lr'] = lr

        print('update learning rate: %f -> %f' % (self.old_lr, lr))
        self.old_lr = lr


import numpy as np
import imutils
import pickle
import cv2
"""Rutas a los archivos necesarios
"""
# Modelo que pasa de una foto de cara a un vector de 128D con la info de la cara
embed_model = "resources/model/openface_nn4.small2.v1.t7"
# Modelo SVC que se encarga de obtener la recta que separa las regiones de caras en el espacio
recognizer_path = "resources/pickle/recognizer.pickle"
# Modelo preentrenado para la detección de rostros en una imagen
model_proto_path = "resources/model/deploy.prototxt"
model_path = "resources/model/res10_300x300_ssd_iter_140000.caffemodel"
"""Cargamos el detector de rostros y el embedder
"""
detector = cv2.dnn.readNetFromCaffe(model_proto_path, model_path)
embedder = cv2.dnn.readNetFromTorch(embed_model)
"""Abrimos el archivo donde hemos guardado a qué cara se corresponde qué vector de datos
    Es decir, las etiquetas
"""
with open("resources/pickle/labels.pickle", "rb") as f:
    inv_labels = pickle.load(f)
    labels = {v: k for k, v in inv_labels.items()}
recognizer = pickle.loads(open(recognizer_path, "rb").read())

# Cargamos y pre-procesamos la imagen, obtenemos sus dimensiones
image = cv2.imread("res/1.jpg")
image = imutils.resize(image, width=600)
(h, w) = image.shape[:2]
# obtenemos el blob de la imagen-->representación abstracta
imageBlob = cv2.dnn.blobFromImage(
    cv2.resize(image, (300, 300)), 1.0, (300, 300),
    (104.0, 177.0, 123.0), swapRB=False, crop=False)
# usamos el detector de caras de OpenCV para detectarlas
detector.setInput(imageBlob)
detections = detector.forward()

# loopeamos las caras
for i in range(0, detections.shape[2]):
    # sacamos la confianza (probabilidad) de cada predicción
    confidence = detections[0, 0, i, 2]
    # si supera nuestro Umbral de confianza
    if confidence > 0.5:
        # coordenadas de la cara detectada
        box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
        (startX, startY, endX, endY) = box.astype("int")
        # recortamos de la imagen la cara detectada
        face = image[startY:endY, startX:endX]
        (fH, fW) = face.shape[:2]
    try:
        faceBlob = cv2.dnn.blobFromImage(face, 1.0 / 255,
                                         (96, 96), (0, 0, 0), swapRB=True, crop=False)
        embedder.setInput(faceBlob)
        vec = embedder.forward()  # contiene la representacion de las 128D de la cara

    except:
        print("Cara corrupta o no centrada en el campo de vision de cámara. Frame corrupto")

    # llamamos a nuestro modelo para que nos de el vector de predicciones
    preds = recognizer.predict_proba(vec)[0]
    j = np.argmax(preds)
    proba = preds[j]
    name = labels[j]
    # dibujamos encima de la foto el rectangulo y la etiqueta
    text = "{}: {:.2f}%".format(name, proba * 100)
    y = startY - 10 if startY - 10 > 10 else startY + 10
    cv2.rectangle(image, (startX, startY), (endX, endY),
                    (0, 0, 255), 2)
    cv2.putText(image, text, (startX, y),
                cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
# mostramos la imagen de salida
cv2.imshow("Prueba reconocimiento sobre imagenes", image)
while True:
    key_pressed=cv2.waitKey(200)
    if cv2.getWindowProperty('Prueba reconocimiento sobre imagenes',cv2.WND_PROP_VISIBLE) < 1:
        break
cv2.destroyAllWindows()


#!/usr/bin/env python3

# Copyright  2020  Yuri Khokhlov, Ivan Medennikov (STC-innovations Ltd)
# Apache 2.0.

"""This script converts TS-VAD output probabilities to a NIST RTTM file.

The segments file format is:
<segment-id> <recording-id> <start-time> <end-time>
The labels file format is:
<segment-id> <speaker-id>

The output RTTM format is:
<type> <file> <chnl> <tbeg> \
        <tdur> <ortho> <stype> <name> <conf> <slat>
where:
<type> = "SPEAKER"
<file> = <recording-id>
<chnl> = "0"
<tbeg> = start time of segment
<tdur> = duration of segment
<ortho> = "<NA>"
<stype> = "<NA>"
<name> = <speaker-id>
<conf> = "<NA>"
<slat> = "<NA>"
"""

import os
import argparse
import regex as re
import numpy as np
from scipy import signal, ndimage
from kaldiio import ReadHelper

class Segment:
    def __init__(self, begin, end, label):
        self.begin = begin
        self.end = end
        self.label = label

    def length(self):
        return self.end - self.begin

class VadProbSet:
    def __init__(self, vad_rspec, reg_exp):
        data = dict()
        prev = -1
        with ReadHelper(vad_rspec) as reader:
            for utid, prob in reader:
                result = reg_exp.match(utid)
                assert result is not None, 'Wrong utterance ID format: \"{}\"'.format(utid)
                sess_indx = result.group(1)
                spkr = result.group(2)

                result = reg_exp.match(sess_indx)
                assert result is not None, 'Wrong utterance ID format: \"{}\"'.format(sess_indx)
                sess = result.group(1)
                indx = int(result.group(2))

                sess = sess + '-' + spkr

                if sess not in data.keys():
                    assert indx == 1
                    prev = -1
                    data[sess] = list()
                assert indx >= prev
                data[sess].append(prob)
                prev = indx
            reader.close()
        print('  loaded {} sessions'.format(len(data)))
        print('  combining fragments')
        self.data = dict()
        for sess, items in data.items():
            self.data[sess] = np.hstack(items)

    def apply_filter(self, window, threshold, threshold_first):
        for sess in self.data.keys():
            if threshold_first:
                self.data[sess] = np.vectorize(lambda value: 1.0 if value > threshold else 0.0)(self.data[sess]).astype(dtype=np.int32)
                if window > 1:
                    self.data[sess] = signal.medfilt(self.data[sess], window).astype(dtype=np.int32)
            else:
                if window > 1:
                    self.data[sess] = signal.medfilt(self.data[sess], window)
                self.data[sess] = np.vectorize(lambda value: 1.0 if value > threshold else 0.0)(self.data[sess]).astype(dtype=np.int32)

    def convert(self, frame_shift,  min_silence, min_speech, out_rttm):
        min_silence = int(round(min_silence / frame_shift))
        min_speech = int(round(min_speech / frame_shift))
        with open(out_rttm, 'wt', encoding='utf-8') as wstream:
            for sess, prob in self.data.items():
                print('  session: {}  num_frames: {}  duration: {:.2f} hrs'.format(sess, len(prob), len(prob) * frame_shift / 60 / 60))
                segments = list()
                for i, label in enumerate(prob):
                    if (len(segments) == 0) or (segments[-1].label != label):
                        segments.append(Segment(i, i + 1, label))
                    else:
                        segments[-1].end += 1
                if (min_silence > 0) or (min_speech > 0):
                    items = segments
                    segments = list()
                    for segm in items:
                        if len(segments) == 0:
                            segments.append(segm)
                        elif segm.label == segments[-1].label:
                            segments[-1].end = segm.end
                        else:
                            min_length = min_silence if segm.label == 0 else min_speech
                            if segm.length() < min_length:
                                segments[-1].end = segm.end
                            else:
                                segments.append(segm)
                for segm in segments:
                    if segm.label == 1:
                        begin = frame_shift * segm.begin
                        length = frame_shift * segm.length()
                        result = reg_exp.match(sess)
                        assert result is not None, 'Wrong format: \"{}\"'.format(sess)
                        utid = result.group(1)
                        spk = result.group(2)
                        wstream.write('SPEAKER {} 1 {:7.3f} {:7.3f} <NA> <NA> {} <NA> <NA>\n'.format(utid, begin, length, spk))
        wstream.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Usage: convert_prob_to_wa.py <vad-rspec> <rttm>')
    parser.add_argument("--frame_shift", "-s", type=float, default=0.010)
    parser.add_argument("--reg_exp", "-x", type=str, default=r'^(\S+)-(\d+)$')
    parser.add_argument("--window", "-w", type=int, default=1)
    parser.add_argument("--threshold", "-t", type=float, default=0.5)
    parser.add_argument("--threshold_first", "-r", action="store_true")
    parser.add_argument("--min_silence", "-k", type=float, default=0.0)
    parser.add_argument("--min_speech", "-m", type=float, default=0.0)
    parser.add_argument('vad_rspec', type=str)
    parser.add_argument('out_rttm', type=str)
    args = parser.parse_args()

    print('Options:')
    print('  Frame shift in sec:  {}'.format(args.frame_shift))
    print('  Utterance ID regexp: {}'.format(args.reg_exp))
    print('  Med. filter window:  {}'.format(args.window))
    print('  Prob. threshold:     {}'.format(args.threshold))
    print('  Apply thresh. first: {}'.format(args.threshold_first))
    print('  Min silence length:  {}'.format(args.min_silence))
    print('  Min speech length:   {}'.format(args.min_speech))
    print('  VAD rspec:           {}'.format(args.vad_rspec))
    print('  Output rttm file:    {}'.format(args.out_rttm))

    reg_exp = re.compile(args.reg_exp)

    parent = os.path.dirname(os.path.abspath(args.out_rttm))
    if not os.path.exists(parent):
        os.makedirs(parent)

    print('Loading VAD probabilities')
    vad_prob = VadProbSet(args.vad_rspec, reg_exp)

    print('Applying filtering')
    vad_prob.apply_filter(args.window, args.threshold, args.threshold_first)

    print('Writing rttm')
    vad_prob.convert(args.frame_shift, args.min_silence, args.min_speech, args.out_rttm)


# -*- coding: utf-8 -*-
"""
SVGPATH2MPL
~~~~~~~~~~~
Parse SVG path definition strings into matplotlib Path objects.
A path in SVG is defined by a 'path' element which contains a
``d="(path data)"`` attribute that contains moveto, line, curve (both
cubic and quadratic Béziers), arc and closepath instructions. See the SVG
Path specification at <https://www.w3.org/TR/SVG/paths.html>.

:copyright: (c) 2016, Nezar Abdennur.
:license: BSD.

"""
from __future__ import division, print_function
from math import sin, cos, sqrt, degrees, radians, acos
import re

from matplotlib.path import Path
import matplotlib.transforms as transforms
import numpy as np

__version__ = '1.0.0'
__all__ = ['parse_path']

COMMANDS = set('MmZzLlHhVvCcSsQqTtAa')
UPPERCASE = set('MZLHVCSQTA')

COMMAND_RE = re.compile(r"([MmZzLlHhVvCcSsQqTtAa])")
FLOAT_RE = re.compile(r"[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?")

COMMAND_CODES = {
    'M': (Path.MOVETO,),    # moveto
    'L': (Path.LINETO,),    # line
    'H': (Path.LINETO,),    # shorthand for horizontal line
    'V': (Path.LINETO,),    # shorthand for vertical line
    'Q': (Path.CURVE3,)*2,  # quadratic bezier
    'T': (Path.CURVE3,)*2,  # shorthand for smooth quadratic bezier
    'C': (Path.CURVE4,)*3,  # cubic bezier
    'S': (Path.CURVE4,)*3,  # shorthand for smooth cubic bezier
    'Z': (Path.CLOSEPOLY,), # closepath
    'A': None               # arc
}

PARAMS = {
    'M': 2, # moveto
    'L': 2, # line
    'H': 1, # shorthand for horizontal line
    'V': 1, # shorthand for vertical line
    'Q': 4, # quadratic bezier
    'T': 4, # shorthand for smooth quadratic bezier
    'C': 6, # cubic bezier
    'S': 6, # shorthand for smooth cubic bezier
    'Z': 0, # closepath
    'A': 7  # arc
}

def endpoint_to_center(start, radius, rotation, large, sweep, end):
    """
    Translates the "endpoint" parameterization of an elliptical arc used by
    the SVG spec to the "center" parameterization.

    Parameters
    ----------
    start : complex
        Starting point (x1, y1).
    radius : complex
        Two elliptical radii (rx, ry).
    rotation : float
        Angle from the x-axis of the current coordinate system to the x-axis of
        the ellipse.
    large : bool
        False if an arc spanning < 180 degrees is to be drawn, True if an arc
        spanning >= 180 degrees is to be drawn.
    sweep : bool
        If sweep-flag is True, then the arc will be drawn in a "positive-angle"
        direction from start to end.
    end : complex
        End point (x2, y2).

    Returns
    -------
    radius : complex
        Radii of the ellipse (rx, ry), potentially corrected if out-of-range.
    center : complex
        Center of the ellipse (xc, yc).
    theta1, theta2 : float
        Start and end angles of an arc on the unit circle prior to being
        stretched and rotated into an elliptical arc.

    Notes
    -----
    See [1]_, `svg.path <https://github.com/regebro/svg.path>`_, and this
    `SO question <https://stackoverflow.com/q/197649>`_.

    References
    ----------

    .. [1] http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes

    """
    # Step 1: compute x1prim, y1prim
    cosr = cos(radians(rotation))
    sinr = sin(radians(rotation))
    dx = (start.real - end.real) / 2
    dy = (start.imag - end.imag) / 2
    x1prim = cosr * dx + sinr * dy
    y1prim = -sinr * dx + cosr * dy
    x1prim_sq = x1prim * x1prim
    y1prim_sq = y1prim * y1prim

    rx = abs(radius.real)
    ry = abs(radius.imag)
    rx_sq = rx * rx
    ry_sq = ry * ry

    # Correct out of range radii
    radius_scale = (x1prim_sq / rx_sq) + (y1prim_sq / ry_sq)
    if radius_scale > 1:
        radius_scale = sqrt(radius_scale)
        rx *= radius_scale
        ry *= radius_scale
        rx_sq = rx * rx
        ry_sq = ry * ry
    else:
        # SVG spec only scales UP
        radius_scale = 1
    radius = rx + ry * 1j

    # Step 2: compute cxprim, cyprim
    t1 = rx_sq * y1prim_sq
    t2 = ry_sq * x1prim_sq
    c = sqrt(abs((rx_sq * ry_sq - t1 - t2) / (t1 + t2)))
    if large == sweep:
        c = -c
    cxprim = c * rx * y1prim / ry
    cyprim = -c * ry * x1prim / rx

    # Step 3: compute the center from cxprim, cyprim
    center = complex(
        (cosr * cxprim - sinr * cyprim) + ((start.real + end.real) / 2),
        (sinr * cxprim + cosr * cyprim) + ((start.imag + end.imag) / 2),
    )

    # Step 4: compute theta and delta_theta
    ux = (x1prim - cxprim) / rx
    uy = (y1prim - cyprim) / ry
    vx = (-x1prim - cxprim) / rx
    vy = (-y1prim - cyprim) / ry
    n = sqrt(ux * ux + uy * uy)
    p = ux
    theta = degrees(acos(p / n))
    if uy < 0:
        theta = -theta
    theta = theta % 360

    n = sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy))
    p = ux * vx + uy * vy
    d = p / n
    # In certain cases the above calculation can through inaccuracies
    # become just slightly out of range, f ex -1.0000000000000002.
    d = np.clip(d, -1.0, 1.0)

    delta = degrees(acos(d))
    if (ux * vy - uy * vx) < 0:
        delta = -delta
    delta = delta % 360
    if not sweep:
        if delta > 0:
            delta -= 360

    return radius, center, theta, theta + delta

def arc_path(start, radius, rotation, large, sweep, end):
    """
    Generate an elliptical arc path given an endpoint parameterization.

    Uses matplotlib to draw the arc using quadratic Bezier curves.

    Parameters
    ----------
    start : complex
        Starting point (x1, y1).
    radius : complex
        Two elliptical radii (rx, ry).
    rotation : float
        Angle from the x-axis of the current coordinate system to the x-axis of
        the ellipse.
    large : bool
        False if an arc spanning < 180 degrees is to be drawn, True if an arc
        spanning >= 180 degrees is to be drawn.
    sweep : bool
        If sweep-flag is True, then the arc will be drawn in a "positive-angle"
        direction from start to end.
    end : complex
        End point (x2, y2).

    Returns
    -------
    codes : array (n,)
        Command codes
    verts : array (n,2)
        Vertices

    Notes
    -----
    We first perform a conversion to center parameterization and generate
    a circular arc at the origin. Then we apply scaling, translation and
    rotation.

    One can think of an ellipse as a circle that has been stretched and then
    rotated. Start by making an arc along the unit circle from `theta1` to
    `theta2`, centered at `center`. Then scale the circle along the x and y
    axes according to the given radii. Finally, rotate the arc around the
    center through the given angle `rotation`.

    """
    radius, center, theta1, theta2 = endpoint_to_center(
        start,
        radius,
        rotation,
        large,
        sweep,
        end
    )

    # Create an arc on the unit circle
    # Matplotlib does this using CURVE4 operations
    # https://matplotlib.org/stable/_modules/matplotlib/path.html#Path.arc
    if theta2 > theta1:
        arc = Path.arc(theta1=theta1, theta2=theta2)
        reverse_path = False
    else:
        arc = Path.arc(theta1=theta2, theta2=theta1)
        reverse_path = True

    # Transform it into an elliptical arc:
    # * scale the minor and major axes
    # * translate it to the center
    # * rotate the x-axis of the ellipse from the x-axis of the current
    #   coordinate system
    trans = (
        transforms.Affine2D()
        .scale(radius.real, radius.imag)
        .translate(center.real, center.imag)
        .rotate_deg_around(center.real, center.imag, rotation)
    )
    arc = trans.transform_path(arc)
    codes = np.array(arc.codes)
    verts = np.array(arc.vertices)

    # Make sure we are drawing from start to end
    if reverse_path:
        verts = verts[::-1, :]

    # Change the initial MOVETO operation into a LINETO to connect to the
    # previous path
    codes[0] = Path.LINETO

    return codes, verts

def _tokenize_path(pathdef):
    for x in COMMAND_RE.split(pathdef):
        if x in COMMANDS:
            yield x
        for token in FLOAT_RE.findall(x):
            yield token

def _next_pos(elements):
    return float(elements.pop()) + float(elements.pop()) * 1j

def _parse_path(pathdef, current_pos):
    # In the SVG specs, initial movetos are absolute, even if specified as 'm'.
    # This is the default behavior here as well. But if you pass in a
    # current_pos variable, the initial moveto will be relative to that
    # current_pos. This is useful.
    elements = list(_tokenize_path(pathdef))
    # Reverse for easy use of .pop()
    elements.reverse()

    start_pos = None
    command = None

    while elements:

        # 1. Determine the current command

        if elements[-1] in COMMANDS:
            # New command.
            last_command = command  # Used by S and T
            command = elements.pop()
            absolute = command in UPPERCASE
            command = command.upper()
        else:
            # Implicit command.
            # If this element starts with numbers, it is an implicit command
            # and we don't change the command. Check that it's allowed:
            if command is None:
                raise ValueError(
                    "Unallowed implicit command in {}, position {}".format(
                        pathdef, len(pathdef.split()) - len(elements))
                    )
            last_command = command  # Used by S and T

        # 2. Parse the current command

        # MOVETO
        if command == 'M':
            pos = _next_pos(elements)
            if absolute:
                current_pos = pos
            else:
                current_pos += pos

            # when M is called, reset start_pos
            # This behavior of Z is defined in svg spec:
            # http://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand
            start_pos = current_pos

            yield COMMAND_CODES['M'], [(current_pos.real, current_pos.imag)]

            # Implicit moveto commands are treated as lineto commands.
            # So we set command to lineto here, in case there are
            # further implicit commands after this moveto.
            command = 'L'

        # CLOSEPATH
        elif command == 'Z':
            # path closure
            if current_pos != start_pos:
                verts = [(start_pos.real, start_pos.imag)]
                yield COMMAND_CODES['L'], verts

            # mpl.Path: a point is required but ignored
            verts = [(start_pos.real, start_pos.imag)]
            yield COMMAND_CODES['Z'], verts

            current_pos = start_pos
            start_pos = None
            command = None  # You can't have implicit commands after closing.

        # LINETO
        elif command == 'L':
            pos = _next_pos(elements)
            if not absolute:
                pos += current_pos
            verts = [(pos.real, pos.imag)]
            yield COMMAND_CODES['L'], verts
            current_pos = pos

        # HORIZONTAL_PATHTO
        elif command == 'H':
            x = elements.pop()
            pos = float(x) + current_pos.imag * 1j
            if not absolute:
                pos += current_pos.real
            verts = [(pos.real, pos.imag)]
            yield COMMAND_CODES['H'], verts
            current_pos = pos

        # VERTICAL_PATHTO
        elif command == 'V':
            y = elements.pop()
            pos = current_pos.real + float(y) * 1j
            if not absolute:
                pos += current_pos.imag * 1j
            verts = [(pos.real, pos.imag)]
            yield COMMAND_CODES['V'], verts
            current_pos = pos

        # CUBIC_BEZIER
        elif command == 'C':
            control1 = _next_pos(elements)
            control2 = _next_pos(elements)
            end = _next_pos(elements)
            if not absolute:
                control1 += current_pos
                control2 += current_pos
                end += current_pos
            verts = [
                 (control1.real, control1.imag),
                 (control2.real, control2.imag),
                 (end.real, end.imag)
            ]
            yield COMMAND_CODES['C'], verts
            current_pos = end

        # SMOOTH_CUBIC_BEZIER
        elif command == 'S':
            # Smooth curve. First control point is the "reflection" of
            # the second control point in the previous path.
            if last_command not in 'CS':
                # If there is no previous command or if the previous command
                # was not an C, c, S or s, assume the first control point is
                # coincident with the current point.
                control1 = current_pos
            else:
                # The first control point is assumed to be the reflection of
                # the second control point on the previous command relative
                # to the current point.
                last_control = control2
                control1 = current_pos + current_pos - last_control
            control2 = _next_pos(elements)
            end = _next_pos(elements)
            if not absolute:
                control2 += current_pos
                end += current_pos
            verts = [
                (control1.real, control1.imag),
                (control2.real, control2.imag),
                (end.real, end.imag)
            ]
            yield COMMAND_CODES['S'], verts
            current_pos = end

        # QUADRATIC_BEZIER
        elif command == 'Q':
            control = _next_pos(elements)
            end = _next_pos(elements)
            if not absolute:
                control += current_pos
                end += current_pos
            verts = [
                (control.real, control.imag),
                (end.real, end.imag)
            ]
            yield COMMAND_CODES['Q'], verts
            current_pos = end

        # SMOOTH_QUADRATIC_BEZIER
        elif command == 'T':
            # Smooth curve. Control point is the "reflection" of
            # the second control point in the previous path.
            if last_command not in 'QT':
                # If there is no previous command or if the previous command
                # was not an Q, q, T or t, assume the first control point is
                # coincident with the current point.
                control = current_pos
            else:
                # The control point is assumed to be the reflection of
                # the control point on the previous command relative
                # to the current point.
                last_control = control
                control = current_pos + current_pos - last_control
            end = _next_pos(elements)
            if not absolute:
                end += current_pos
            verts = [
                (control.real, control.imag),
                (end.real, end.imag)
            ]
            yield COMMAND_CODES['T'], verts
            current_pos = end

        # ELLIPTICAL_ARC
        elif command == 'A':
            radius = _next_pos(elements)
            rotation = float(elements.pop())
            large = float(elements.pop())
            sweep = float(elements.pop())
            end = _next_pos(elements)

            if not absolute:
                end += current_pos

            if current_pos == end:
                # This is equivalent of omitting the segment, so do nothing
                continue
            elif radius.real == 0 or radius.imag == 0:
                # This should be treated as a straight line
                verts = [(end.real, end.imag)]
                yield COMMAND_CODES['L'], verts
            else:
                codes, verts = arc_path(
                    current_pos, radius, rotation, large, sweep, end
                )
                yield codes, verts

            current_pos = end

def parse_path(pathdef, current_pos=0 + 0j):
    """
    Parse an SVG path definition string into a matplotlib Path object.

    Parameters
    ----------
    pathdef : str
        SVG path 'd' attribute, e.g. 'M 100 100 L 300 100 L 200 300 z'.
    current_pos : complex, optional
        Coordinates of the starting position of the path, given as a complex
        number. When provided, an initial moveto operation will be intepreted
        as relative to this position even if given as M.

    Returns
    -------
    :class:`matplotlib.path.Path` instance

    See also
    --------
    matplotlib.path.Path
    matplotlib.patches.PathPatch
    matplotlib.collections.PathCollection
    matplotlib.transforms

    """
    codes = []
    verts = []
    for c, v in _parse_path(pathdef, current_pos):
        codes.extend(c)
        verts.extend(v)
    return Path(verts, codes)