"""
Driver module for NI USB-6259 DAQ
"""
from __future__ import division
import ctypes
import numpy
nidaq = ctypes.windll.nicaiu # load the DLL

##############################
# Setup some typedefs and constants
# to correspond with values in
# C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h
# the typedefs
int32 = ctypes.c_long
uInt32 = ctypes.c_ulong
uInt64 = ctypes.c_ulonglong
float64 = ctypes.c_double
TaskHandle = uInt32
# the constants
DAQmx_Val_Cfg_Default = int32(-1)
DAQmx_Val_Volts = 10348
DAQmx_Val_Rising = 10280
DAQmx_Val_FiniteSamps = 10178
DAQmx_Val_ContSamps = 10123
DAQmx_Val_GroupByChannel = 0
##############################
def CHK(err):
    """a simple error checking routine"""
    if err < 0:
        buf_size = 100
        buf = ctypes.create_string_buffer('\000' * buf_size)
        nidaq.DAQmxGetErrorString(err,ctypes.byref(buf),buf_size)
        raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(buf.value)))

#### Device class
class NIDAQ():
    voltlimits = [10, 5, 2, 1, 0.5, 0.2, 0.1]

    def __init__(self, name="Dev1"):
        self.name = name

    def createTask(self, channel="ai0", maxsample=1000, rate=1000, voltlimit=10.0, finite=True, *args, **kwargs):
        return Task(self, channel, maxsample, rate, voltlimit, finite, *args, **kwargs)

#### Task class
class Task():
    # voltlimits = [10, 5, 2, 1, 0.5, 0.2, 0.1]

    def __init__(self, device, channel="ai0", maxsample=1000, rate=1000, voltlimit=10.0, finite=True):
        """ Set up a voltage measurement task """
        self.taskHandle = TaskHandle(0)
        self.device = device
        self.channelName = "%s/%s" %(device.name, channel)
        self.maxsample = maxsample
        self.finite = finite
        CHK(nidaq.DAQmxCreateTask("",ctypes.byref(self.taskHandle)))
        CHK(nidaq.DAQmxCreateAIVoltageChan(self.taskHandle,
                                           self.channelName,
                                           "",
                                           DAQmx_Val_Cfg_Default,
                                           float64(-voltlimit),
                                           float64(voltlimit),
                                           DAQmx_Val_Volts,
                                           None
                                           )
            )
        samples = DAQmx_Val_FiniteSamps if self.finite else DAQmx_Val_ContSamps
        CHK(nidaq.DAQmxCfgSampClkTiming(self.taskHandle,
                                        "",
                                        float64(rate),
                                        DAQmx_Val_Rising,
                                        samples,
                                        uInt64(self.maxsample)
                                        )
            )

    def SetTrigger(self, triggerchannel="PFI0"):
        channel = triggerchannel
        CHK(nidaq.DAQmxCfgDigEdgeStartTrig(self.taskHandle,
                                           channel,
                                           DAQmx_Val_Rising
                                           )
            )

    def Start(self):
        """ Start the task """
        # Seems to take about 70ms to run this. Why?
        CHK(nidaq.DAQmxStartTask(self.taskHandle))

    def Stop(self):
        """ Stop the task """
        if self.taskHandle != 0:
            nidaq.DAQmxStopTask(self.taskHandle)

    def Read(self, num=None):
        """ Read values """
        if num is None:
            num = self.maxsample
        read = int32()
        data = numpy.zeros((self.maxsample,), dtype=numpy.float64)
        CHK(nidaq.DAQmxReadAnalogF64(self.taskHandle,
                                     self.maxsample,
                                     float64(num),
                                     DAQmx_Val_GroupByChannel,
                                     data.ctypes.data,
                                     self.maxsample,
                                     ctypes.byref(read),
                                     None)
            )
        return (read, data)

    def Close(self):
        """ Close the task """
        if self.taskHandle != 0:
            self.Stop()
            nidaq.DAQmxClearTask(self.taskHandle)

    def Wait(self):
        """ Wait until task is done """
        CHK(nidaq.DAQmxWaitUntilTaskDone(self.taskHandle, float64(120)))

if __name__ == "__main__":
    """
    Example code to try this class: record 1s worth of 1000 voltage datapoints on AI0
    """
    import pylab as pl
    import time
    dev = NIDAQ()
    sample = 10000
    rate = sample
    task0 = dev.createTask(channel="ai1", maxsample=sample, rate=rate, voltlimit=0.5)

    task0.Start()
    read, data = task0.Read()
    task0.Stop()

    totaltime = sample / rate
    times = numpy.linspace(0, totaltime, sample)
    task0.Close()
    pl.plot(times, data)
    pl.xlabel("Time (s)")
    pl.ylabel("Recorded signal (V)")
    pl.show()


import argparse
import time

import cv2
import numpy as np

from classifier.face_classifier import FaceClassifier
from detection.face_detector import FaceDetector
from embeddings.face_embeddings import FaceEmbeddings
from face_recognition_train import models

def main():
    ap = argparse.ArgumentParser()
    try:
        models.remove("all")
    finally:
        ap.add_argument("-clf", "--classifier", default="svm", const="svm", nargs='?', choices=models,
                        help=f"classificador responsavel pelo reconhecimento facial ({models})")
        args = vars(ap.parse_args())

    face_detector = FaceDetector()
    face_recognition = FaceEmbeddings()
    face_classifier = FaceClassifier(model_name=args["classifier"])

    video_capture = cv2.VideoCapture(0)
    prev_time = 0
    cv2.namedWindow("Video", cv2.WINDOW_NORMAL)

    print('Iniciando reconhecimento!')
    while True:

        ret, frame = video_capture.read()
        # if not ret:
        #     break

        frame = cv2.resize(frame, (0, 0), fx=1, fy=1)  # resize frame (optional)
        curr_time = time.time()  # calc fps

        frame = frame[:, :, 0:3]

        boxes, scores = face_detector.detect(frame)

        if boxes is not None and scores is not None:
            boxes = boxes[np.where(scores > 0.6)]
            scores = scores[np.where(scores > 0.6)]
            # detections = face_detector.detect(frame)
            # detections = detections[np.where(detections[:, 4] > 0.5)]
            print('Faces detectadas: %d' % len(boxes))

            if len(boxes) > 0:
                for x1, y1, x2, y2 in boxes:
                    if x2 - x1 < 30 or y2 - y1 < 30:
                        continue

                    cropped_face = frame[y1:y2, x1:x2, :]
                    # cv2.imshow(f"Deteccao", cropped_face)
                    # cv2.waitKey(0)

                    pre_processed_face = face_detector.pre_process(cropped_face)

                    if pre_processed_face is None:
                        continue

                    feature = face_recognition.describe(pre_processed_face)
                    name, prob = face_classifier.classify(feature)

                    cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)

                    # plot result idx under box
                    text_x = x1 - 5
                    text_y = y2 + 15

                    def legenda(text: str):
                        cv2.putText(frame, text, (text_x, text_y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,
                                    (0, 0, 255), thickness=1, lineType=2)

                    if args["classifier"] == "svm":
                        legenda(f"{name} ({prob})") if prob >= 0.25 else legenda(f"Desconhecido")

                    elif args["classifier"] == "mlp":
                        legenda(f"{name} ({prob})") if prob >= 0.95 else legenda(f"Desconhecido")

                    else:
                        legenda(f"{name} ({prob})")

            else:
                print('Unable to align')

        sec = curr_time - prev_time
        prev_time = curr_time
        fps = 1 / sec
        fps_str = 'FPS: %2.3f' % fps
        print(fps_str)
        text_fps_x = len(frame[0]) - 150
        text_fps_y = 20
        cv2.putText(frame, fps_str, (text_fps_x, text_fps_y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 0, 0),
                    thickness=1, lineType=2)

        cv2.imshow('Video', frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    video_capture.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()


"""
Acoustical component
--------------------

This is an abstract base class for acoustical components.

"""

import numpy as np
from .component import Component
from ..base import Attribute

class ComponentAcoustical(Component):
    """Abstract base class for acoustical components.
    """

    # @property
    # def subsystem_long(self):
    # """Subsystem for longitudinal waves.
    # """
    # for obj in self.linked_subsystems:
    # if isinstance(

    @property
    def pressure(self):
        """Pressure within the component :math:`p_{component}`.

        :rtype: :class:`numpy.ndarray`

        This is the sum of all subsystems velocities.
        """
        return sum(subsystem.pressure for subsystem in self.linked_subsystems)

    @property
    def pressure_level(self):
        """
        Sound pressure level :math:`L_p`.

        :rtype: :class:`numpy.ndarray`

        .. seealso:: :attr:`seapy.subsystems.subsystemacoustical.SubsystemAcoustical`

        .. math:: L_p = 20 \\log_{10}{\\left( \\frac{p}{p_0} \\right)}

        .. seealso:: :attr:`seapy.system.System.reference_pressure`

        """
        return 20.0 * np.log10(self.pressure / self.system.reference_pressure)


# - coding: utf-8 -*-
# python 3.5

import numpy as np
import cv2
import os
import random

BKroot = "/home/shinpoi/dataset/backgrounds"
ITEMroot = "/home/shinpoi/dataset/humans/"

def histogram_matching(srcArr, dstArr, srcPNG=True):
    src_HSV = cv2.cvtColor(srcArr, cv2.COLOR_RGB2HSV)
    srcHist = cv2.calcHist((src_HSV,), (2,), None, (256,), (0, 256)).reshape((-1,))
    if srcPNG:
        srcHist[0] = 0
    srcHist /= sum(srcHist)
    srcHistMap = np.zeros(256, dtype=np.float32)
    for i in range(len(srcHist)):
        srcHistMap[i] = sum(srcHist[:i])

    dst_HSV = cv2.cvtColor(dstArr, cv2.COLOR_RGB2HSV)
    dstHist = cv2.calcHist((dst_HSV,), (2,), None, (256,), (0, 256)).reshape((-1,))
    dstHist /= sum(dstHist)
    dstHistMap = np.zeros(256, dtype=np.float32)
    for i in range(len(dstHist)):
        dstHistMap[i] = sum(dstHist[:i])

    HistMap = np.zeros(256, dtype=np.uint8)
    for i in range(256):
        minMap = 1
        minTag = None
        for j in range(256):
            if minMap > abs(srcHistMap[i] - dstHistMap[j]):
                minMap = abs(srcHistMap[i] - dstHistMap[j])
                minTag = j
        HistMap[i] = minTag
        # flatten??? may be...
        if i > 100000:
            if HistMap[i] < HistMap[i-1]:
                HistMap[i] = HistMap[i-1]
            if HistMap[i] == HistMap[i-1] == HistMap[i-2] == HistMap[i-3]:
                HistMap[i] += 1

    for i in range(src_HSV.shape[0]):
        for j in range(src_HSV.shape[1]):
            if src_HSV[i, j, 2] == 0:
                continue
            else:
                src_HSV[i, j, 2] = HistMap[src_HSV[i, j, 2]]
    return cv2.cvtColor(src_HSV, cv2.COLOR_HSV2RGB)

def reshape_item(imgArr, maxsize=448, min_t=0.4, filip_rate=0.5):
    if imgArr.shape[0] > imgArr.shape[1]:
        max_t = (maxsize/imgArr.shape[1])*0.8 - min_t
    else:
        max_t = (maxsize/imgArr.shape[0])*0.8 - min_t

    times = min_t + random.random()*max_t
    imgArr = cv2.resize(imgArr, (int(imgArr.shape[1]*times), int(imgArr.shape[0]*times)))

    # flip
    if random.random() < filip_rate:
        imgArr = cv2.flip(imgArr, 1)
    return imgArr

class ImageGenerator(object):
    def __init__(self, bk_root, item_root, max_img_size=448, batch_size=16):
        self.bk_root = bk_root
        self.item_root = item_root
        self.batch_size = batch_size
        self.max_img_size = max_img_size
        self.bk_list = []
        self.images_pool = None
        self.items_pool_rgba = []
        self.n_bk = 0
        self.BKindex = None

    def init_all(self, backup=None):
        if not backup:
            self.init_backgrounds_pool()
        self.init_BKimages_pool(backup=backup)
        self.init_items_pool()
        self.init_BKindex()

    def init_backgrounds_pool(self):
        for i in os.walk(self.bk_root):
            root, folder, files = i
            for f in files:
                if f.endswith(".jpg"):
                    dir_ = root + "/" + f
                    self.bk_list.append(dir_)
        self.n_bk = len(self.bk_list)
        print("init_backgrounds_pool() end")

    # sepcial
    def init_BKimages_pool(self, backup=None):
        self.bk_list = np.random.permutation(self.bk_list)
        if backup:
            bk = np.load(backup)
            self.n_bk = len(bk)
            return bk

        self.n_bk = 32000  # test mode
        max_img_size = self.max_img_size
        self.images_pool = np.zeros((self.n_bk, max_img_size, max_img_size, 3), dtype=np.uint8)
        n = 0
        for dir_ in self.bk_list[:self.n_bk]:
            img = cv2.imread(dir_)
            if img.shape[0] == 270:
                st = random.randint(0, 210) # 480-270
                img = cv2.resize(img[:, st: st+270], (max_img_size, max_img_size))
            elif img.shape[0] == 720:
                st = random.randint(0, 560) # 1280-720
                img = cv2.resize(img[:, st: st+720], (max_img_size, max_img_size))
            else:
                print("ignore %s. shape:(%d, %d)" % (dir_, img.shape[0], img.shape[1]))
                continue
            self.images_pool[n] = img
            n += 1
            if n%500 == 0:
                print("%d/%d" % (n, self.n_bk))
        if n != self.n_bk:
            print("has igroned images!!")
            self.n_bk = n
            self.images_pool = self.images_pool[:n]
        print("init_BKimages_pool() end, get %d images" % n)

    # special
    def init_items_pool(self):
        item_list = []
        for i in os.walk(self.item_root):
            root, folder, files = i
            for f in files:
                if f.endswith(".png"):
                    dir_ = root + "/" + f
                    item_list.append(dir_)
        self.items_pool_rgba = [[] for i in range(10)]

        for dir_ in item_list:
            if "blue_1" in dir_:
                self.items_pool_rgba[0].append(cv2.imread(dir_, -1))
            elif "blue_2" in dir_:
                self.items_pool_rgba[1].append(cv2.imread(dir_, -1))
            elif "blue_3" in dir_ or "blue_4" in dir_:
                self.items_pool_rgba[2].append(cv2.imread(dir_, -1))
            elif "blue_5" in dir_:
                self.items_pool_rgba[3].append(cv2.imread(dir_, -1))
            elif "blue_6" in dir_:
                self.items_pool_rgba[4].append(cv2.imread(dir_, -1))
            elif "orange_1" in dir_:
                self.items_pool_rgba[5].append(cv2.imread(dir_, -1))
            elif "orange_2" in dir_:
                self.items_pool_rgba[6].append(cv2.imread(dir_, -1))
            elif "orange_3" in dir_ or "orange_4" in dir_:
                self.items_pool_rgba[7].append(cv2.imread(dir_, -1))
            elif "orange_5" in dir_:
                self.items_pool_rgba[8].append(cv2.imread(dir_, -1))
            elif "orange_6" in dir_:
                self.items_pool_rgba[9].append(cv2.imread(dir_, -1))
        print("init_items_pool() end")

    def compose_img(self, item, background, hm_rate=0.8):
        rgba = item.copy()
        bk = background.copy()
        bk_rows, bk_cols, ch = background.shape
        if random.random() <= hm_rate:
            rgba[:, :, :3] = histogram_matching(rgba[:, :, :3], background)
        # insert coordinate
        hum_rows, hum_cols, ch = rgba.shape
        lim_rows = int((bk_rows - hum_rows)/2)
        lim_cols = bk_cols - hum_cols
        row_start = int(lim_rows*random.random()) + lim_rows
        col_start = int(lim_cols*random.random())

        # create mask
        mask = cv2.GaussianBlur(rgba[:, :, 3], (1, 1), 1)
        mask_inv = cv2.bitwise_not(mask)
        mask = np.array(mask, dtype=np.float32)/255
        mask_inv = np.array(mask_inv, dtype=np.float32)/255
        mask.resize((hum_rows, hum_cols, 1))
        mask_inv.resize((hum_rows, hum_cols, 1))
        mask = np.concatenate((mask, mask, mask), axis=2)
        mask_inv = np.concatenate((mask_inv, mask_inv, mask_inv), axis=2)

        # insert
        # print(row_start, col_start, hum_rows, hum_cols)
        bk_part = bk[row_start:row_start+hum_rows, col_start:col_start+hum_cols]
        bk[row_start:row_start + hum_rows, col_start:col_start + hum_cols] = \
np.array(bk_part * mask_inv + rgba[:, :, :3] * mask, dtype=np.uint8)

        # t
        x = (2*row_start + hum_rows)/bk_rows/2
        y = (2*col_start + hum_cols)/bk_cols/2
        h = hum_rows/bk_rows
        w = hum_cols/bk_cols
        t = [{'x':x, 'y':y, 'w':w, 'h':h, 'label':None, 'one_hot_label':None }]

        return bk, t

    def init_BKindex(self):
        self.BKindex = np.arange(0, self.n_bk, 1, dtype=np.int32)
        self.BKindex = np.random.permutation(self.BKindex)

    def create_batch(self, batch_size=None, index=0, reuse=0, reuserate=2, img_size=None):
        if not img_size:
            img_size = self.max_img_size
        if not batch_size:
            batch_size = self.batch_size

        if 2*batch_size > self.n_bk:
            self.init_BKindex()
            if (reuse != 0) and (reuse % reuserate == 0):
                self.init_BKimages_pool()
            index = 0
            reuse += 1

        for i in range(batch_size, img_size):
            batch = np.zeros((batch_size, 3, img_size, img_size), dtype=np.float32)
            tt = []
            BKimg_list = self.BKindex[index: index+batch_size]
            index += batch_size
            n = 0
            for i in BKimg_list:
                cla = random.randint(0, 9)
                item = random.sample(self.items_pool_rgba[cla], 1)
                x, t = self.compose_img(item[0], self.images_pool[i])
                if not x.shape[0] == img_size:
                    x = cv2.resize(x, (img_size, img_size))
                batch[n] = x.transpose((2, 0, 1))
                t[0]['label'] = cla
                oh = np.zeros(10, dtype=np.float32)
                oh[cla] = 1
                t[0]['one_hot_label'] = oh
                tt.append(t)
                n += 1
            return batch/255, tt
    """
    def save_imgspool_backup(self):
        print("start backup")
        np.save("img_pools.npy", self.images_pool)
        print("backup: img_pools.npy")
    """

"""
import image_generator_2 as ig
gen = ig.ImageGenerator(ig.BKroot, ig.ITEMroot)
gen.init_all()
x, t = gen.create_batch()
"""


# oculus.py
#
# This program collects head orientation data from an Oculus Rift and streams
# it over virtual COM port.
#
# The ovr libraries used are from github.com/cmbruns/pyovr and this project
# builts on top of the example code there for interfacing with the Oculus.

# Libraries
import sys
import time
import serial
import numpy as np
from threading import Thread, Lock
import ovr
import inputs

# Local files
import utility as util
from tx import Transmitter

def init_oculus():
    '''
    Initialize a session with the Oculus Rift. The session will allow us to
    query it for data
    '''
    ovr.initialize(None)
    session, luid = ovr.create()
    print("Connected to Oculus")
    return session

def clamp(n, min, max):
    '''
    n is returned if it is in range [min, max], otherwise the closest of min and
    max to n is returned
    '''

    return min if n < min else max if n > max else n

lock = Lock()
def gamepad_loop():
    '''
    Reads from the Xbox controller
    '''

    # Read from gamepad forever, and store the y data (vertical deviation of
    # left thumbstick) in the global variable, protected by a lock
    print("Starting gamepad loop")
    global y_data, x_data
    y_data = 0
    x_data = 0
    while 1:
        events = inputs.get_gamepad()
        sys.stdout.flush()
        event = events[-1]
        if lock.acquire(True):
            if event.code == 'ABS_Y':
                y_data = event.state
            elif event.code == 'ABS_X':
                x_data = event.state
            lock.release()

def stream_loop(session, tx, dryrun=False):
    '''
    Collect head orientation data from the Oculus Rift and stream it to the
    microcontroller, forever.

    Parameters
    ----------
    session : pointer to HmdDesc
        Interface for the head-moounted device
    tx : tx.Transmitter
        Interface for serial port
    dryrun : bool
        If True, runs the test mode of the loop where there is no MCU
        communication
    '''

    print_after = 10
    count = 0
    print("Starting stream loop")
    yvel = 0
    xvel = 0
    while True:
        # Query the HMD for the current tracking state.
        ts  = ovr.getTrackingState(session, ovr.getTimeInSeconds(), True)
        if ts.StatusFlags & (ovr.Status_OrientationTracked | ovr.Status_PositionTracked):
            pose = ts.HeadPose
            angles = np.array(pose.ThePose.Orientation.getEulerAngles())* 180 / np.pi
            pitch = np.round(angles[0] * -1 + 90)
            yaw = np.round(angles[1] + 90)

            # Don't allow values outside the range of the servos
            pitch = clamp(pitch, 0, 180)
            yaw = clamp(yaw, 0, 180)

            # Get data from gamepad thread
            if lock.acquire(True):
                yvel = y_data * 127 / 32768.0 # Scale to int8_t
                xvel = x_data * 127 / 32768.0 # Scale to int8_t
                lock.release()

            if count % print_after == 0:
                print("Pitch: {0}| Yaw: {1}| Yvel: {2} | Xvel: {3}".format(pitch, yaw, yvel, xvel))

            if not dryrun:
                tx.transmit(pitch=pitch, yaw=yaw, yvel=yvel, xvel=xvel)

            sys.stdout.flush()
            count = count + 1
        time.sleep(0.010)

def exit(session):
    '''
    Exit program.

    Parameters
    ----------
    session : pointer to HmdDesc
        Interface for the head-moounted device
    '''

    ovr.destroy(session)
    ovr.shutdown()

def main():
    args = util.parse_args()
    session = init_oculus()

    port = args['port']
    baud = args['baud']
    dryrun = args['dryrun']

    gp = inputs.devices.gamepads
    if len(gp) == 0 or 'microsoft' not in str(gp[0]).lower():
        print("Xbox controller not detected")
        exit(session)
        return

    # Read from the gamepad in a different thread since the inputs library
    # blocks program execution
    try:
        gamepad_thread = Thread(target=gamepad_loop)
        gamepad_thread.daemon = True
        gamepad_thread.start()

        # If we are developing, we don't worry about the serial port
        if dryrun:
            stream_loop(session, -1, True)

        num_tries = 0
        while(True):
            try:
                with serial.Serial(port, baud, timeout=0) as ser:
                    print("Connected to embedded")
                    tx = Transmitter(ser)
                    stream_loop(session, tx)

            except serial.serialutil.SerialException as e:
                if(num_tries % 100 == 0):
                    if(str(e).find("FileNotFoundError")):
                        print("Port not found. Retrying...(attempt {0})".format(num_tries))
                    else:
                        print("Serial exception. Retrying...(attempt {0})".format(num_tries))

                time.sleep(0.01)
                num_tries = num_tries + 1
    except (KeyboardInterrupt, SystemExit) as e:
        print("Interrupted: {0}".format(e))
        pass

    exit(session)

if __name__ == "__main__":
    main()
    sys.exit(0)


import tensorflow as tf
import numpy as np
from tensorflow.contrib import slim
from configs import CLASS

class YOLONET(object):
    def __init__(self, is_training=True):
        self.is_training = is_training
        self.classes = CLASS
        self.class_num = len(self.classes)
        self.image_size = 448
        self.cell_size = 7
        self.boxes_per_cell = 2
        self.leaky_alpha = 0.1  # 激活函数leaky_relu
        self.keep_prob = 0.5
        self.output_size = self.cell_size * self.cell_size * (5 * self.boxes_per_cell + self.class_num)
        # 权重系数
        self.class_scale = 1
        self.object_confidence_scale = 1
        self.no_object_confidence_scale = 0.5
        self.coord_scale = 5

        # 1. 图像占位符
        self.images = tf.placeholder(dtype=tf.float32, name='images',
                                     shape=[None, self.image_size, self.image_size, 3])
        # 2. 推断过程(不包含损失函数)
        self.inference = self.build_network(images=self.images,
                                            output_size=self.output_size)
        if self.is_training:
            # 3. 标签占位符
            self.labels = tf.placeholder(tf.float32, name='labels',
                                         shape=[None, self.cell_size, self.cell_size, 5 + self.class_num])
            # 4. 损失函数层(还没有写)
            self.loss_layer(predicts=self.inference, labels=self.labels)
            self.total_loss = tf.losses.get_total_loss()
            tf.summary.scalar('total loss', self.total_loss)

    def build_network(self,
                      images,
                      output_size,
                      scope='yolo_net'):
        with tf.name_scope(scope):
            with slim.arg_scope(
                    [slim.conv2d, slim.fully_connected],
                    activation_fn=YOLONET.leaky_relu(self.leaky_alpha),
                    weights_regularizer=slim.l2_regularizer(0.0005),
                    weights_initializer=tf.truncated_normal_initializer(0.0, 0.01)):
                net = tf.pad(images,
                             np.array([[0, 0], [3, 3], [3, 3], [0, 0]]),
                             name='pad_1')
                net = slim.conv2d(net, 64, 7, 2, padding='VALID', scope='conv_2')
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_3')
                net = slim.conv2d(net, 192, 3, scope='conv_4')
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_5')
                net = slim.conv2d(net, 128, 1, scope='conv_6')
                net = slim.conv2d(net, 256, 3, scope='conv_7')
                net = slim.conv2d(net, 256, 1, scope='conv_8')
                net = slim.conv2d(net, 512, 3, scope='conv_9')
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_10')
                net = slim.conv2d(net, 256, 1, scope='conv_11')
                net = slim.conv2d(net, 512, 3, scope='conv_12')
                net = slim.conv2d(net, 256, 1, scope='conv_13')
                net = slim.conv2d(net, 512, 3, scope='conv_14')
                net = slim.conv2d(net, 256, 1, scope='conv_15')
                net = slim.conv2d(net, 512, 3, scope='conv_16')
                net = slim.conv2d(net, 256, 1, scope='conv_17')
                net = slim.conv2d(net, 512, 3, scope='conv_18')
                net = slim.conv2d(net, 512, 1, scope='conv_19')
                net = slim.conv2d(net, 1024, 3, scope='conv_20')
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_21')
                net = slim.conv2d(net, 512, 1, scope='conv_22')
                net = slim.conv2d(net, 1024, 3, scope='conv_23')
                net = slim.conv2d(net, 512, 1, scope='conv_24')
                net = slim.conv2d(net, 1024, 3, scope='conv_25')
                net = slim.conv2d(net, 1024, 3, scope='conv_26')
                net = tf.pad(net,
                             np.array([[0, 0], [1, 1], [1, 1], [0, 0]]), name='pad_27')
                net = slim.conv2d(net, 1024, 3, 2, padding='VALID', scope='conv_28')
                net = slim.conv2d(net, 1024, 3, scope='conv_29')
                net = slim.conv2d(net, 1024, 3, scope='conv_30')
                # NhWC变为NCHW,以矩阵最后个axis为方向展开
                net = tf.transpose(net, [0, 3, 1, 2], name='trans_31')
                net = slim.flatten(net, scope='flat_32')
                net = slim.fully_connected(net, 512, scope='fc_33')
                net = slim.fully_connected(net, 4096, scope='fc_34')
                net = slim.dropout(net, keep_prob=self.keep_prob,
                                   is_training=self.is_training,
                                   scope='dropout_35')
                net = slim.fully_connected(net,
                                           output_size,
                                           activation_fn=None,
                                           scope='fc_36')
                # [Batch, 7, 7, 30] reshape 预测结果
                net = tf.reshape(net, name='predicts', shape=[-1, self.cell_size, self.cell_size,
                                                              5 * self.boxes_per_cell + self.class_num])
        return net

    def loss_layer(self, predicts, labels, scope='loss'):
        """

        Args:
            predicts: 网络的输出 [Batch, 7, 7, 30]
            labels: label[Batch, 7, 7, 25], [Batch, (h方向), (w方向), 25]
                    为与计算机存储图片格式相同,我们存储标签的时候先按 h / w 顺序存储.
        """
        with tf.name_scope('Predict_Tensor'):
            ############## 预测 ##############
            """
            1. 预测坐标: x, y 基于cell, sqrt(w), sqrt(h) 基于全图 (0-1)范围内
            2. 2个bounding box,拥有2个坐标以及置信度
            """
            # 1. Bounding box 坐标预测 [batch, 7, 7, :8] >> shape=[batch, 7, 7, 2, 4]
            pre_boxes = tf.reshape(predicts[..., : 4 * self.boxes_per_cell],
                                   shape=[-1, self.cell_size, self.cell_size, self.boxes_per_cell, 4])
            # 2. Bounding box 置信度预测 [batch, 7, 7, 8:10] >> shape=[batch, 7, 7, 2]
            pre_confidence = predicts[..., 4 * self.boxes_per_cell: 5 * self.boxes_per_cell]
            # 3. class 类别预测 [batch, 7, 7, 10:] >> shape=[batch, 7, 7, 20]
            pre_class = predicts[..., 5 * self.boxes_per_cell:]
        with tf.name_scope('Label_Tensor'):
            ############## 标签 ##############
            """
            1. 标签坐标: x,y,w,h 均基于全图(0-1)
            """
            # 1. box response_label [batch, 7, 7, 0]  >> shape=[batch,7, 7, 1]
            # lab_response 只负责标记cell中是否有object,置信度标签需要跟IOU实时计算
            lab_response = tf.expand_dims(labels[..., 0], -1)
            # 2. box 坐标label [batch, 7, 7, 1:5] >> shape=[batch, 7, 7, 2, 4]
            lab_boxes = tf.reshape(labels[..., 1:5],
                                   shape=[-1, self.cell_size, self.cell_size, 1, 4])
            lab_boxes = tf.tile(lab_boxes, [1, 1, 1, self.boxes_per_cell, 1])
            # 3. class 类别标签 [batch, 7, 7, 5:] >> shape=[batch, 7, 7, 20]
            lab_class = labels[..., 5:]

        ############## 损失函数 ##############
        with tf.variable_scope(scope):
            # 1. 类别损失
            class_loss = self.class_loss(pre_class, lab_class, lab_response)
            # 2. 坐标转换基于cell的x, y, sqrt(w), sqrt(h) >> 基于全图的x, y, w, h
            global_pre_boxes = self.pre_to_label_coord(pre_boxes)  # [batch, 7, 7, 2, 4]
            # 3. 计算iou shape=[batch, 7, 7, 2]
            iou_pre_label = self.calc_iou(global_pre_boxes, lab_boxes)
            # 4. 目标掩模 / 非目标掩模
            object_mask, no_object_mask = self.mask(iou_pre_label, lab_response)
            # 5. 置信度损失
            object_confidence_loss, no_object_confidence_loss = self.confidence_loss(
                pre_confidence, iou_pre_label, object_mask, no_object_mask)
            # 6. 坐标损失
            coord_loss = self.coord_loss(pre_boxes, lab_boxes, object_mask)

            tf.losses.add_loss(class_loss)
            tf.losses.add_loss(object_confidence_loss)
            tf.losses.add_loss(no_object_confidence_loss)
            tf.losses.add_loss(coord_loss)

            tf.summary.scalar('class_loss', class_loss)
            tf.summary.scalar('object_confidence_loss', object_confidence_loss)
            tf.summary.scalar('no_object_confidence_loss', no_object_confidence_loss)
            tf.summary.scalar('coord_loss', coord_loss)

    def class_loss(self, pre_class, lab_class, lab_response):
        """

        Args:
            pre_class: 预测类别 [batch, 7, 7, 20]
            lab_class: 标签类别 [batch, 7, 7, 20] 20维 one-hot标签
            lab_response: 标记某个Cell中是否有object [batch, 7, 7, 1]
            weight: 权重系数之前说过,类别损失和坐标损失的比重是1 : 5

        Returns:
            类别损失
        """
        # 乘以 label_response 来去除掉没有Object位置多计算出的类别损失
        # 注意一个cell中是否有物体是通过置信度损失来回归的
        # 这种分开的思想让不同位置的参数回归不同属性,而不是把它们融合在一起
        with tf.name_scope('class_loss'):
            delta = lab_response * (pre_class - lab_class)
            class_loss = self.class_scale * tf.reduce_mean(tf.reduce_sum(tf.square(delta), axis=[1, 2, 3]),
                                                           name='class_loss')
        return class_loss

    def confidence_loss(self,
                        pre_confidence,
                        iou_pre_label,
                        object_mask,
                        no_object_mask,
                        ):
        """

        Args:
            pre_confidence: 预测置信度 shape=[batch, 7, 7, 2]
            iou_pre_label: IOU shape=[batch, 7, 7, 2]
            object_mask: 目标掩模 [batch, 7, 7, 2] 有目标的位置是1,其余为0
            no_object_mask: 非目标掩模 [batch, 7, 7, 2] 没有目标的位置是1,其余为0
        """
        with tf.name_scope('Confidence_loss'):
            with tf.name_scope("Object_Confidence_loss"):
                # 用目标掩模进行判断是否有目标
                # 实际是 object_mask * pre_confidence - object_mask * iou_pre_label
                # 我们将式子合并之后变为下面的样子
                object_confidence_delta = object_mask * (pre_confidence - iou_pre_label)
                object_confidence_loss = self.object_confidence_scale * tf.reduce_mean(
                    tf.reduce_sum(tf.square(object_confidence_delta), axis=[1, 2, 3]))
            with tf.name_scope('No_Object_Confidence_loss'):
                # 只要预测出置信度就是错的,我们用掩模抑制
                # 实际是 no_object_mask * pre_confidence - no_object_mask * 0 因为这些位置没有Object,因此iou即为0
                no_object_confidence_delta = no_object_mask * pre_confidence
                no_object_confidence_loss = self.no_object_confidence_scale * tf.reduce_mean(
                    tf.reduce_sum(tf.square(no_object_confidence_delta), axis=[1, 2, 3]))
        return object_confidence_loss, no_object_confidence_loss

    def coord_loss(self,
                   pre_boxes,
                   lab_boxes,
                   object_mask):
        """

        Args:
            pre_boxes: [batch, 7, 7, 2, 4] 基于cell的x, y以及全图 sqrt(w), sqrt(h)
            lab_boxes: [batch, 7, 7, 2, 4] 基于全图的x, y, w, h
            object_mask: [batch, 7, 7, 2]

        Returns:

        """
        with tf.name_scope('Coord_loss'):
            coord_mask = tf.expand_dims(object_mask, axis=-1)
            cell_lab_boxes = self.label_to_pre_cood(lab_boxes)
            coord_delta = coord_mask * (pre_boxes - cell_lab_boxes)
            coord_loss = self.coord_scale * tf.reduce_mean(
                tf.reduce_sum(tf.square(coord_delta), axis=[1, 2, 3, 4]))
        return coord_loss

    def mask(self, iou_pre_label, label_response):
        """

        Args:
            iou_pre_label: 两个 Bounding box 的 IOU [batch, 7, 7, 2]
            label_response: [batch, 7, 7, 1]  0-1

        Returns:
            object_mask: 有目标的掩模,有object并且IOU最高的bounding box [batch, 7, 7, 2]
            no_object_mask: 其余情况

        """
        object_mask = tf.reduce_max(iou_pre_label, axis=-1, keep_dims=True)
        object_mask = tf.cast((iou_pre_label>= object_mask), tf.float32)
        object_mask = object_mask * label_response  # 还需要乘以 response
        no_object_mask = tf.ones_like(object_mask, dtype=tf.float32) - object_mask
        return object_mask, no_object_mask

    def pre_to_label_coord(self, pre_boxes):
        """坐标转换基于cell的x, y, sqrt(w), sqrt(h) >> 基于全图的x, y, w, h"""

        # 1. 沿着axis=2的方向逐渐增大,我们希望shape=[1, 7, 7, 2(bounding box), 1]1
        offset_axis_2 = tf.tile(tf.expand_dims(tf.range(7), axis=0),
                                multiples=[7, 1])
        offset_axis_2 = tf.tile(tf.reshape(offset_axis_2, shape=[1, 7, 7, 1]),
                                multiples=[1, 1, 1, 2])
        # 3. 沿着axis=1的方向变大
        offset_axis_1 = tf.transpose(offset_axis_2, (0, 2, 1, 3))

        w = tf.square(pre_boxes[..., 2])
        h = tf.square(pre_boxes[..., 3])

        # 4. 计算x的时候.因为图像是以h, w格式存储的,也就是 x变化 在axis=2上递增
        global_x = (pre_boxes[..., 0] + tf.to_float(offset_axis_2)) / self.cell_size
        global_y = (pre_boxes[..., 1] + tf.to_float(offset_axis_1)) / self.cell_size
        global_pre_boxes = tf.stack([global_x, global_y, w, h], axis=-1)
        return global_pre_boxes

    def label_to_pre_cood(self, lab_boxes):
        offset_axis_2 = tf.tile(tf.expand_dims(tf.range(7), axis=0),
                                multiples=[7, 1])
        offset_axis_2 = tf.tile(tf.reshape(offset_axis_2, shape=[1, 7, 7, 1]),
                                multiples=[1, 1, 1, 2])
        offset_axis_1 = tf.transpose(offset_axis_2, (0, 2, 1, 3))
        sqrt_w = tf.sqrt(lab_boxes[..., 2])
        sqrt_h = tf.sqrt(lab_boxes[..., 3])
        cell_x = lab_boxes[..., 0] * self.cell_size - tf.to_float(offset_axis_2)
        cell_y = lab_boxes[..., 1] * self.cell_size - tf.to_float(offset_axis_1)
        cell_lab_boxes = tf.stack([cell_x, cell_y, sqrt_w, sqrt_h], axis=-1)
        return cell_lab_boxes

    def calc_iou(self, boxes1, boxes2, scope='IOU'):
        """ 计算训练时候 bounding box 和 label 的IOU

        Args:
            boxes1: 预测 Boxes
                    [Batch, CELL_SIZE, CELL_SIZE, BOXES_PER_CELL, 4] / [x, y, w, h]
            boxes2: label Boxes
                    [Batch, CELL_SIZE, CELL_SIZE, BOXES_PER_CELL, 4] /[x, y, w, h]
            scope: 我们

        Returns:
             IOU: 4-D tensor [BATCH_SIZE, CELL_SIZE, CELL_SIZE, BOXES_PER_CELL]
        """
        with tf.variable_scope(scope):
            """transform (x_center, y_center, w, h) to (x1, y1, x2, y2)
            1. 涉及矩阵操作的时候,Tesnorflow一般只是将前面的维度当做Batch
            2. 不涉及矩阵的操作,我们可以拿出单个元素考虑,之后将其矩阵化
            """
            boxes1_voc = tf.stack([boxes1[..., 0] - boxes1[..., 2] / 2.0,
                                   boxes1[..., 1] - boxes1[..., 3] / 2.0,
                                   boxes1[..., 0] + boxes1[..., 2] / 2.0,
                                   boxes1[..., 1] + boxes1[..., 3] / 2.0],
                                   axis=-1)
            boxes2_voc = tf.stack([boxes2[..., 0] - boxes2[..., 2] / 2.0,
                                   boxes2[..., 1] - boxes2[..., 3] / 2.0,
                                   boxes2[..., 0] + boxes2[..., 2] / 2.0,
                                   boxes2[..., 1] + boxes2[..., 3] / 2.0],
                                   axis=-1)

            # calculate the left up point & right down point
            # [batch, 7, 7, 2, 2] 对应位置最大值, maximum 支持广播,但不能指定轴
            lu = tf.maximum(boxes1_voc[..., :2], boxes2_voc[..., :2])  # x1, y1 max(X_L)
            rd = tf.minimum(boxes1_voc[..., 2:], boxes2_voc[..., 2:])  # x2, y2 min(X_R)

            # [batch, 7, 7, 2, 2]   min(X_R)-max(X_L)
            intersection = tf.maximum(0.0, rd - lu)
            # [batch, 7, 7, 2] 2个bounding box跟label的IOU,因此这里有2个
            inter_square = intersection[..., 0] * intersection[..., 1]

            # calculate the boxs1 square and boxs2 square by w*h
            # [batch, 7, 7, 2] * [batch, 7, 7, 2]
            square1 = boxes1[..., 2] * boxes1[..., 3]
            square2 = boxes2[..., 2] * boxes2[..., 3]
            union_square = tf.maximum(square1 + square2 - inter_square, 1e-10)

        return tf.clip_by_value(inter_square / union_square, 0.0, 1.0)

    @staticmethod
    def leaky_relu(alpha):
        def op(inputs):
            return tf.nn.leaky_relu(inputs, alpha=alpha, name='leaky_relu')
        return op


import cv2
import numpy as np
import pandas as pb
import math
import os
#from fastseg import MobileV3Large, MobileV3Small
#from fastseg.image import colorize, blend
import cv2
#model = MobileV3Small.from_pretrained().cuda()
#model.eval()
import numpy as np
import time
# Open a local image as input
from PIL import Image

import h5py
writer = None

allLabels = []

# get all videos in cv2 object
#video_names = ["Video1", "Video2", "Video3", "Video4"]
#video_names = ["Video5"]
#video_names = ["Video6", "Video7", "Video8", "Video9", "Video10"]
#video_names = ["Video11", "Video12", "Video13", "Video14", "Video15"]
#video_names = ["Video16", "Video17", "Video18", "Video19"]
#video_names = ["Video25"]
#video_names = ["Video21", "Video22", "Video23", "Video24"]

video_names = ["Video26", "Video27", "Video28"]
#VIDEO 6 later

vs_objects = []
h5paths = []
for video in video_names:
    video_path_part_1 = "C:\\Users\\krish\\Downloads\\ScienceFairOrderedVideos\\"
    video_path_part_2 = video
    video_path_part_3 = "_Trim_Trim.mp4"
    video_final_path = video_path_part_1 + video_path_part_2 + video_path_part_3
    vs = cv2.VideoCapture(video_final_path)
    vs_objects.append(vs)
    tempString = "C:\\Code\\fastseg\\" + video + ".hdf5"
    h5paths.append(tempString)

# get all participant data sujign mihir
list_of_names = ["Mihir"] # put all participant names here
data_frames = []
count = 0
composited_indexes = []
indexVSObjects = vs_objects.copy()
for vs in vs_objects:
    tempLabels = []
    f2 = h5py.File(h5paths[vs_objects.index(vs)], "r")
    data = f2['labels'][:]
    allLabels.append(data)
    #vs.release()
    f2.close()
    print(h5paths[vs_objects.index(vs)])
print("finished allLabels creation")
print(*allLabels)
print(len(allLabels))

for name in list_of_names:
    count = 25
    for trial in range(1, 31):
        var_part_1 = name
        var_part_2 = "\Data"
        var_part_3 = str(trial)
        final_df_name = var_part_1 + var_part_2 + var_part_3

        path_part_1 = "C:\\Users\\krish\\Downloads\\Official Participant Data-20210918T182855Z-001\\Official Participant Data\\Adolescent\\Male\\"
        path_part_2 = final_df_name
        path_part_3 = ".csv"
        final_path_name = path_part_1 + path_part_2 + path_part_3
        if os.path.exists(final_path_name):
            data_frame = pb.read_csv(final_path_name)
            data_frames.append(data_frame)

    for vs in vs_objects:
        videoNumber = vs_objects.index(vs)
        total_frames = vs.get(cv2.CAP_PROP_FRAME_COUNT)
        fps = total_frames/25

        x_coordinates = data_frames[count]["Coordinate X"].tolist()
        length_x_1 = len(x_coordinates)
        x_coordinates = [x for x in x_coordinates if math.isnan(x) == False]
        length_x_2 = len(x_coordinates)
        x_coordinates = [round(x) for x in x_coordinates]
        y_coordinates = data_frames[count]["Coordinate Y"].tolist()
        y_coordinates = [y for y in y_coordinates if math.isnan(y) == False]
        y_coordinates = [round(y) for y in y_coordinates]

        num_of_na = length_x_1 - length_x_2
        nested_count = 0
        for x in x_coordinates:
            video_time = data_frames[count]["Decision Time (Updated)"][nested_count + num_of_na]
            print(videoNumber)
            #print(round(fps*video_time) - 1)
            fpsVal = round(fps*video_time) - 1
            if fpsVal >= int(total_frames):
                fpsVal = int(total_frames - 1)
            #print(total_frames)
            #print(type(fpsVal))
            #print(fpsVal)S
            #print(y_coordinates[nested_count])

            composited_index = allLabels[videoNumber][fpsVal][yVal][x]
            composited_indexes.append(composited_index)
            nested_count += 1

        for index in composited_indexes:
            i = composited_indexes.index(index)
            if (index == 0):
                composited_indexes[i] = "road"
            if (index == 1):
                composited_indexes[i] = "sidewalk"
            if (index == 2):
                composited_indexes[i] = "building"
            if (index == 3):
                composited_indexes[i] = "wall"
            if (index == 4):
                composited_indexes[i] = "fence"
            if (index == 5):
                composited_indexes[i] = "pole"
            if (index == 6):
                composited_indexes[i] = "traffic light"
            if (index == 7):
                composited_indexes[i] = "traffic sign"
            if (index == 8):
                composited_indexes[i] = "vegetation"
            if (index == 9):
                composited_indexes[i] = "terrain"
            if (index == 10):
                composited_indexes[i] = "sky"
            if (index == 11):
                composited_indexes[i] = "person"
            if (index == 12):
                composited_indexes[i] = "rider"
            if (index == 13):
                composited_indexes[i] = "car"
            if (index == 14):
                composited_indexes[i] = "truck"
            if (index == 15):
                composited_indexes[i] = "bus"
            if (index == 16):
                composited_indexes[i] = "train"
            if (index == 17):
                composited_indexes[i] = "motorcycle"
            if (index == 18):
                composited_indexes[i] = "bicycle"
        """
        data_frames[count]["Object Viewed"] = composited_indexes
        print(*composited_indexes)
        data_frames[count].to_csv(final_path_name, index=False)
        with open(final_path_name, "a") as filePath:
            wr = csv.writer(fp, dialect='excel')
        """
        var_part_1 = name
        var_part_2 = "\Data"
        var_part_3 = str(count+1)
        final_df_name = var_part_1 + var_part_2 + var_part_3

        path_part_1 = "C:\\Users\\krish\\Downloads\\Official Participant Data-20210918T182855Z-001\\Official Participant Data\\Adolescent\\Male\\"
        path_part_2 = final_df_name
        path_part_3 = ".csv"
        finalPath = path_part_1 + path_part_2 + path_part_3
        if os.path.exists(finalPath):
            df = pb.read_csv(finalPath)
            df['Object Viewed'] = composited_indexes
            df.to_csv(finalPath)

        #csv_file = pb.read_csv(final_path_name)
        #csv_file['Object Viewed Column'] = data_frames[count]["Object Viewed"]
        #csv_file.to_csv(final_path_name, index=False)

        count += 1
        #allLabels = []
        composited_indexes = []

    data_frames = []


from __future__ import division

import traceback
import argparse
import os
import glob
import random
import time
import cv2

import sys
from datetime import datetime
import os

import numpy as np

# Object detection using YOLO4 project
# https://github.com/Tianxiaomo/pytorch-YOLOv4

# Install steps:
# mkdir wights
# gdown https://drive.google.com/file/d/1wv_LiFeCRYwtpkqREPeI13-gPELBDwuJ -O weights/yolov4.pth
# gdown https://drive.google.com/file/d/1fcbR0bWzYfIEdLJPzOsn4R5mlvR6IQyA -O weights/yolov4.conv.137.pth

# Status: nor working

pathToProject='../pytorch-YOLOv4/'
sys.path.insert(0, pathToProject)
os.chdir(pathToProject)

from tool.darknet2pytorch import Darknet
from tool.utils import *
from tool.torch_utils import *

def init_model(transform):

    parser = argparse.ArgumentParser()
    parser.add_argument("--confidence", dest="confidence", help="Object Confidence to filter predictions", default=0.25)
    parser.add_argument("--nms_thresh", dest="nms_thresh", help="NMS Threshhold", default=0.4)
    parser.add_argument("--reso", dest='reso', help=
    "Input resolution of the network. Increase to increase accuracy. Decrease to increase speed",
                        default="160", type=str)
    args, unknown = parser.parse_known_args()

    cfgfile = "./cfg/yolov4.cfg"
    weightsfile = "./weights/yolov4.pth"

    confidence = float(args.confidence)
    nms_thesh = float(args.nms_thresh)
    CUDA = torch.cuda.is_available()
    num_classes = 80
    # bbox_attrs = 5 + num_classes
    class_names = load_class_names("./data/coco.names")

    model = Darknet(cfgfile)
    model.load_weights(weightsfile)

    if CUDA:
        model.cuda()

    model.eval()
    return (model, class_names,CUDA), None

def process_image(transform,processing_model,img):
    tracks = []
    try:
        (model, class_names, CUDA) = processing_model
        sized = cv2.resize(img, (model.width, model.height))
        sized = cv2.cvtColor(sized, cv2.COLOR_BGR2RGB)
        boxes = do_detect(model, sized, 0.5, 0.4, CUDA)

        if len(boxes)>1
            img = plot_boxes_cv2(img, boxes, class_names=class_names)
            tracks = boxes
    except Exception as e:
        track = traceback.format_exc()
        print(track)
        print("YOLO 4 PyTorch Exception",e)
        pass
    return tracks,img


# Copyright 2020 Sanggyu Lee. All rights reserved.
# sanggyu.developer@gmail.com
# Licensed under the MIT License
from . import communication
from . import config

import threading
import traceback
import cv2
import numpy as np
import tkinter
import tkinter.messagebox
import time
import os
import logging
import glob
import math

logger = logging.getLogger("control")
logger.setLevel(logging.DEBUG)
log_handler = logging.StreamHandler()
logger.addHandler(log_handler)

#
# imgpoints = []
# objpoints = []
# objp = np.zeros((9*7, 3), np.float32)
# objp[:,:2] = np.mgrid[0:9, 0:7].T.reshape(-1, 2)
# objp *= 20

mtx = np.array([[309.07332417, 0., 324.4646727],
                [0., 309.49421445, 225.88178544],
                [0., 0., 1.]], dtype=np.float32)
dist = np.array([[-0.28743189, 0.07504807, -0.00050962, 0.00069096, -0.00815296]], dtype=np.float32)
# newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (640, 480), 0, (640, 480))

# imgpoints2 = []
# objpoints2 = []
# criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

mtx2 = np.array([[395.52784006, 0., 239.21418142],
                 [0., 395.130504, 230.42492257],
                 [0., 0., 1.]])
dist2 = np.array([[-0.31976223, 0.10018421, -0.00051188, -0.00091223, -0.01348978]])

# newcameramtx2, roi = cv2.getOptimalNewCameraMatrix(mtx2, dist2, (640, 480), 0, (640, 480))

class BaseControl:
    def __init__(self, graphics):
        self.graphics = graphics
        self.done = False

    def quit(self):
        self.done = True
        # clear All Ongoing Connection and stop

    def hang(self):
        pass

    def process(self, t, _fImg, _rImg, _fLdr, _rLdr):
        self.graphics.plan.pre_process(t, _fImg, _rImg, _fLdr, _rLdr)
        try:
            command = self.graphics.plan.process(t, _fImg, _rImg, _fLdr, _rLdr)
        except Exception as e:
            self.graphics.setCommandText(f'런타임 에러: {str(e)}')
            traceback.print_exc()
            command = 0, 0
        self.graphics.plan.post_process()
        try:
            steer, velocity = command
            assert math.isfinite(steer)
            assert math.isfinite(velocity)
        except:
            error = ValueError(repr(command) + ' is not a valid return for process()')
            self.graphics.setCommandText(f'런타임 에러: {repr(error)}')
            traceback.print_exception(ValueError, error, None)
            command = 0, 0

        self.graphics.setCommand(*command)
        self.graphics.setTime(t)
        return command

    def halt_car(self):
        tkinter.messagebox.showinfo("자주차 종료", "자주차 종료는 주행 모드에서만 가능합니다.")

class DriveControl(BaseControl):
    def __init__(self, graphics, address):
        super().__init__(graphics)
        self.address = address
        self.receiver = communication.VideoStreamSubscriber(*config.image_address)
        self._halt = False
        self._fImg = None
        self._rImg = None
        self._fLdr = None
        self._rLdr = None
        self._live = False
        self._save = False
        self._saveDir = None
        self._startTime = None
        self._thread = threading.Thread(target=self._run, args=())
        self._thread.daemon = True
        self._thread.start()

    def _run(self):
        self.client = None
        try:
            self.client = communication.Client('tcp://%s:%d' % config.address)
            msg, front, rear = self.receiver.receive()
            if self.client.id is None:
                self.graphics.setCommandText('자주차가 사용중입니다.')
                if tkinter.messagebox.askyesno('연결 오류', '자주차가 사용중입니다.\n강제로 연결할까요?'):
                    if self.client.override():
                        self.graphics.btnStartStop['state'] = tkinter.NORMAL
                        self.graphics.setCommandText('자주차에 연결되었습니다.')
                    else:
                        tkinter.messagebox.showinfo('연결 오류', '강제 연결에 실패했습니다.\n 자주차를 재부팅 해주세요.')

            else:
                self.graphics.btnStartStop['state'] = tkinter.NORMAL
                self.graphics.setCommandText('자주차에 연결되었습니다.')
            while not self._halt:
                self._fImg = cv2.imdecode(np.frombuffer(front, dtype='uint8'), -1)
                self._rImg = cv2.imdecode(np.frombuffer(rear, dtype='uint8'), -1)
                self._rImg = cv2.rotate(self._rImg, cv2.ROTATE_180)
                _t, self._fLdr, self._rLdr = msg.split()
                _t, self._fLdr, self._rLdr = float(_t), int(self._fLdr), int(self._rLdr)

                # logger.debug("latency: %.3f"%(time.time()-_t))
                self.graphics.setFrontLidar(self._fLdr)
                self.graphics.setRearLidar(self._rLdr)
                if self._live:
                    t = time.time() - self._startTime
                else:
                    t = 0
                self.t = t
                if self._live and self._save:
                    prefix = "%06.2f %d %d" % (t, self._fLdr, self._rLdr)
                    cv2.imwrite(prefix + ',front.jpg', self._fImg)  # Replace Unix Time with time since run
                    cv2.imwrite(prefix + ',rear.jpg', self._rImg)
                    logging.debug(prefix)

                self._fImg = cv2.undistort(self._fImg, mtx, dist, None, None)
                self._rImg = cv2.undistort(self._rImg, mtx2, dist2, None, None)
                self._rImg = cv2.flip(self._rImg, 1)
                self.graphics.setFrontImage1(self._fImg)
                self.graphics.setRearImage1(self._rImg)

                command = self.process(self.t, self._fImg, self._rImg, self._fLdr, self._rLdr)

                if self._live:
                    rtn = self.client.sendCommand(*command)
                    if not rtn:
                        tkinter.messagebox.showerror('연결 오류', '자주차 연결이 강제로 해제되었습니다.')
                        raise RuntimeError('Connection Reset')
                elif self.client.id is not None:
                    rtn = self.client.sendCommand(0, 0)
                    if not rtn:
                        tkinter.messagebox.showerror('연결 오류', '자주차 연결이 강제로 해제되었습니다.')
                        raise RuntimeError('Connection Reset')

                msg, front, rear = self.receiver.receive()
            # print("Out of While Loop")
            self.client.disconnect()
            # self.client.quit()
        except TimeoutError:
            if not self._halt:
                self.graphics.setCommandText("자주차 연결에 실패했습니다.")
        except RuntimeError:
            if not self._halt:
                self.graphics.setCommandText("자주차 연결이 강제로 해제되었습니다.")
        except Exception as e:
            print("Error in Driving:", e)
            traceback.print_exc()
        finally:
            if not self._halt:
                self.graphics.btnStartStop['state'] = tkinter.DISABLED
                self.graphics.btnDriveSave['state'] = tkinter.NORMAL
                self.graphics.callback_change_save()
                self.graphics.btnModeDrive['state'] = tkinter.NORMAL
                self.graphics.btnModeImage['state'] = tkinter.NORMAL
            self.receiver.close()

    def start(self):
        if self.graphics.runSave.get() and self.graphics.saveLocation is not None:
            self._save = True
            os.chdir(self.graphics.saveLocation)
            if len(glob.glob("*.jpg")) > 0:
                if not tkinter.messagebox.askyesno("주행 저장 실패", "저장 경로에 이미지 파일이 있어 저장할 수 없습니다.\n주행을 계속할까요?"):
                    return False
                else:
                    tkinter.messagebox.showinfo("주행 안내", "주행을 시작합니다.\n이미지를 저장하지 않습니다.")
                    self._save = False
        else:
            self._save = False
        self.graphics.btnDriveSave['state'] = tkinter.DISABLED
        self.graphics.btnFindSavePath['state'] = tkinter.DISABLED
        self.graphics.btnModeDrive['state'] = tkinter.DISABLED
        self.graphics.btnModeImage['state'] = tkinter.DISABLED
        self._startTime = time.time()
        self._live = True

    def stop(self):
        self._live = False
        time.sleep(0.1)
        self.client.sendCommand(0, 0)
        # 2) gracefully disconnect
        self.graphics.btnDriveSave['state'] = tkinter.NORMAL
        self.graphics.callback_change_save()
        self.graphics.btnModeDrive['state'] = tkinter.NORMAL
        self.graphics.btnModeImage['state'] = tkinter.NORMAL

    def quit(self):
        super().quit()
        self._halt = True
        # self.hang()

    def hang(self):
        self._thread.join(1)

    def halt_car(self):
        if self.client is None or self.client.id is None:
            tkinter.messagebox.showinfo("자주차 종료", "자주차 종료는 자주차에 연결된 상태에서만 가능합니다.")
            return
        elif self._live:
            tkinter.messagebox.showinfo("자주차 종료", "자주차 종료는 준비 상태에서만 가능합니다.")
            return
        try:
            exited = self.client.exit()
            self._live = False
            if exited:
                tkinter.messagebox.showinfo("자주차 종료", "자주차가 정상적으로 종료되었습니다.")
            else:
                tkinter.messagebox.showinfo("자주차 종료", "자주차 종료에 실패했습니다.")
        except:
            tkinter.messagebox.showinfo("자주차 종료", "자주차 종료에 실패했습니다.")

class ImageControl(BaseControl):
    def __init__(self, graphics, path):
        super().__init__(graphics)
        self.path = path
        os.chdir(path)
        self.imList = sorted(glob.glob('*.jpg'))
        self.len = len(self.imList) // 2
        if self.len < 1:
            self.graphics.setCommandText('경로에 이미지가 없습니다. 경로를 확인해주세요.')
            return
        self.graphics.setCommandText('프레임 %d장을 확인했습니다.' % self.len)
        self.index = 0
        self._fImg = None
        self._rImg = None
        self._fLdr = None
        self._rLdr = None
        self.t = 0
        self._play = False
        self._thread = None
        self.update(self.index)
        self.graphics.btnStartStop['state'] = tkinter.NORMAL
        self.setBtnStatus(tkinter.NORMAL)

    def play(self):
        self._play = True
        self._thread = threading.Thread(target=self._run, args=())
        self._thread.daemon = True
        self._thread.start()

    def pause(self):
        self._play = False

    def _run(self):
        self.setBtnStatus(tkinter.DISABLED)
        while self._play and self.index < self.len - 1:
            start = time.time()
            self.index += 1
            self.update(self.index)
            nextT = self.getTime(self.index + 1)
            end = time.time()
            if nextT is not None:
                time.sleep(max(nextT - self.t - end + start, 0))
        if self._play:
            self.graphics.callback_start_stop()
        self.setBtnStatus(tkinter.NORMAL)

    def next(self):
        self.index = min(self.index + 1, self.len - 1)
        self.update(self.index)

    def before(self):
        self.index = max(self.index - 1, 0)
        self.update(self.index)

    def next10(self):
        self.index = min(self.index + 10, self.len - 1)
        self.update(self.index)

    def before10(self):
        self.index = max(self.index - 10, 0)
        self.update(self.index)

    def update(self, index):
        try:
            self._fImg = cv2.imread(self.imList[2 * index])
            self._rImg = cv2.imread(self.imList[2 * index + 1])
            msg = self.imList[2 * index].split(',')[0]
            self.t, self._fLdr, self._rLdr = msg.split()
            self.t, self._fLdr, self._rLdr = float(self.t), int(self._fLdr), int(self._rLdr)

            self._fImg = cv2.undistort(self._fImg, mtx, dist, None, None)
            self._rImg = cv2.undistort(self._rImg, mtx2, dist2, None, None)
            self._rImg = cv2.flip(self._rImg, 1)
            self.graphics.setFrontImage1(self._fImg)
            self.graphics.setRearImage1(self._rImg)

            self.graphics.setFrontLidar(self._fLdr)
            self.graphics.setRearLidar(self._rLdr)

            command = self.process(self.t, self._fImg, self._rImg, self._fLdr, self._rLdr)

        except Exception as e:
            print('Error in Imageshow:', e)
            traceback.print_exc()

    def getTime(self, index):
        try:
            if index >= self.len:
                return None
            msg = self.imList[2 * index].split(',')[0]
            t, _, _ = msg.split()
            return float(t)
        except Exception as e:
            print('Error in Imageshow:', e)
            traceback.print_exc()

    def setBtnStatus(self, state):
        self.graphics.btnBefore['state'] = state
        self.graphics.btnBefore10['state'] = state
        self.graphics.btnNext['state'] = state
        self.graphics.btnNext10['state'] = state


import numpy as np
import os
# import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile

# from collections import defaultdict
# from io import StringIO
# from matplotlib import pyplot as plt
# from PIL import Image

import cv2

## Object detection imports
import label_map_util
import visualization_utils as vis_util

class SSD_Detector:

  def __init__(self):
    CWD_PATH = os.getcwd()
    MODEL_FOLDER = 'models'
    MODEL_NAME = 'ssd_mobilenet_v1_model'
    PATH_TO_CKPT = os.path.join(CWD_PATH, MODEL_FOLDER ,MODEL_NAME, 'frozen_inference_graph.pb')
    PATH_TO_LABELS = os.path.join(CWD_PATH, MODEL_FOLDER, MODEL_NAME, 'label_map.pbtxt')

    # 1 - person, 2 - dog, 3 - cat
    NUM_CLASSES = 3

    # ssd engine ready signal
    self.ready = False

    # begin load models
    try:
      self.detection_graph = tf.Graph()
      with self.detection_graph.as_default():
            od_graph_def = tf.GraphDef()
            with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
              serialized_graph = fid.read()
              od_graph_def.ParseFromString(serialized_graph)
              tf.import_graph_def(od_graph_def, name='')

      self.detection_graph.as_default()
    except:
      print('Warning! Failed to load ' + MODEL_NAME + ' frozen graph file (.pb), object detection disabled')

    try:
      label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
      categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)

      self.category_index = label_map_util.create_category_index(categories)
      self.sess = tf.Session(graph=self.detection_graph)
      self.ready = True
    except:
      print('Warning! Failed to load ' + MODEL_NAME + ' label map (.pbtxt), object detection disabled')

  def process_image(self, image_np):
        # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
        image_np_expanded = np.expand_dims(image_np, axis=0)
        image_tensor = self.detection_graph.get_tensor_by_name('image_tensor:0')
        # Each box represents a part of the image where a particular object was detected.
        boxes = self.detection_graph.get_tensor_by_name('detection_boxes:0')
        # Each score represent how level of confidence for each of the objects.
        # Score is shown on the result image, together with the class label.
        scores = self.detection_graph.get_tensor_by_name('detection_scores:0')
        classes = self.detection_graph.get_tensor_by_name('detection_classes:0')

        num_detections = self.detection_graph.get_tensor_by_name('num_detections:0')
        # Actual detection.
        (boxes, scores, classes, num_detections) = self.sess.run([boxes, scores, classes, num_detections],feed_dict={image_tensor: image_np_expanded})

        # Obtain objects detected in the current frame
        objects_detected = vis_util.visualize_boxes_and_labels_on_image_array(image_np,
                                                                              np.squeeze(boxes),
                                                                              np.squeeze(classes).astype(np.int32),
                                                                              np.squeeze(scores),
                                                                              self.category_index,
                                                                              use_normalized_coordinates=True,
                                                                              line_thickness=6)

        # Get the dimension of the frame
        img_height, img_width, dim = image_np.shape

        detected_objs = []

        # iterate it and display on screen
        if type(objects_detected) is list:
          for obj in objects_detected:

              obj_name = obj[0]
              obj_prob = obj[1]

              display_text = obj_name + ": " + str(obj_prob)

              # TODO: make this part more scalable
              if obj_name == "person":
                  display_colour = (255,0,0) # red

                  if obj_name not in detected_objs:
                    detected_objs.append(obj_name)

                  # topleft & bottomright coord of the bbox
                  tl = (int(obj[3]*img_width), int(obj[2]*img_height))
                  br = (int(obj[5]*img_width), int(obj[4]*img_height))

                  # display text coord
                  display_text_coord = (tl[0]+5,tl[1]-10)

                  cv2.putText(image_np,display_text,display_text_coord,0,0.5,display_colour)
                  cv2.rectangle(image_np,tl,br,display_colour,2)

        return image_np, detected_objs


#! /usr/bin/env python

from argparse import ArgumentParser
import pandas as pd
import numpy as np
import sys

def main():
    args = get_args()
    res = pd.concat([read_tg(f, n) for f, n in zip(args.input, args.names or args.input)]) \
        .drop_duplicates(subset=['identifier', 'sample'])
    pivot = res.pivot(index='identifier',
                      columns='sample',
                      values='copy_number')
    pivot.loc[:, "max_change"] = pivot.abs().max(axis="columns")
    if args.sort == 'location':
        sorter = ["chromosome", "begin", "end"]
        ascending = True
    else:
        sorter = 'max_change'
        ascending = False
    print(res[["identifier", "chromosome", "begin", "end", "motif", "gene", "element"]]
          .drop_duplicates()
          .set_index('identifier')
          .join(pivot)
          .sort_values(sorter, ascending=ascending)
          .to_csv(sep="\t", na_rep='.')
          )

def read_tg(tgfile, name):
    df = pd.read_csv(tgfile,
                     sep="\t",
                     comment='#',
                     header=None,
                     converters={'motif': truncate_motif},
                     names=['chromosome', 'begin', 'end', 'motif', 'gene', 'element',
                            'copy_numbers_fwd', 'copy_numbers_rev'])
    df["copy_number"] = (df["copy_numbers_fwd"] + ',' + df["copy_numbers_rev"]
                         ).apply(parse_copy_number_changes)
    df["identifier"] = df["chromosome"] + ":" + df["begin"].astype(str) + "-" + df["motif"]
    df["sample"] = name
    return df

def truncate_motif(motif):
    if len(motif) > 8:
        return motif[:8] + '~'
    else:
        return motif

def parse_copy_number_changes(value):
    return np.median([int(i) if i != '.' else 0 for i in value.split(',')])

def get_args():
    parser = ArgumentParser(description="reformat and combine output of tandem-genotypes")
    parser.add_argument("--input", help="tandem-genotypes output files", nargs='+')
    parser.add_argument("--names", help="name of each dataset", nargs='+')
    parser.add_argument("--sort",
                        help="property to sort on. Default: chromosomal location",
                        choices=['location', 'max'],
                        default='location')
    args = parser.parse_args()
    if not args.names or not len(args.input) == len(args.names):
        sys.exit("ERROR: Need same number of values in --names as tandem-genotypes output files")
    return args

if __name__ == '__main__':
    main()


from sklearn.linear_model import Ridge
import sys
from social_features import get_social_features
from social_features import get_reply_only_social_features
import time
from collections import *
import re
import pickle
import numpy as np
from sklearn.preprocessing import Imputer

def main():

    input_file = sys.argv[1]
    outfile = sys.argv[2]

    base_dir = '../..//working-dir/feature-vectors/'
    clf_file = base_dir + 'social-features.min-5.tsv.support.rf-128.ml-5.feat-0.25.classifier.pkl'
    feat_file = base_dir +  'social-features.min-5.tsv.features.tsv'

    max_lines = -1

    print(('Classifying %d instances from %s using the classifier at %s' \
          % (max_lines, input_file, clf_file)))

    time_sum = 0

    feature_to_index = {}
    with open(feat_file, 'r') as f:
        for line in f:
            cols = line[:-1].split('\t')
            feature_to_index[cols[0]] = int(cols[1])
    num_feats = len(feature_to_index)

    print('loading classifier')
    with open(clf_file, 'rb') as f:
        clf = pickle.load(f)
        clf.n_jobs = 1
        clf.verbose = 0

    header = [ 'instance_id',  'location', 'self-attribute', 'other-attribute', ]
    print(list(clf.classes_))
    # return
    header.append('support')

    with open(input_file) as f, open(outfile, 'w') as outf:

        outf.write('\t'.join(header) + "\n")

        for line_no, line in enumerate(f):
            if line_no == 0:
                continue
            try:
                cols = line[:-1].split('\t')

                post = normalize(cols[0])
                post_id = cols[1]
                poster_id = cols[2]
                reply = normalize(cols[3])
                reply_id = cols[4]
                replier_id = cols[5]
                location = cols[6]
                size = cols[7]
                instance_id = cols[8]
                if len(cols) > 10:
                    identity = cols[9]
                    other_identity = cols[10]
                elif len(cols) > 9:
                    identity = cols[9]
                    other_identity = 'unknown'
                else:
                    identity = 'unknown'
                    other_identity = 'unknown'

                start = time.time()
                feats = get_reply_only_social_features(post, reply)
                if len(feats) == 0:
                    continue

                vec = num_feats * [ 0 ]
                for k, v in feats.items():
                    # Skip  features not seen in training
                    if k not in feature_to_index:
                        continue
                    vec[feature_to_index[k]] = v

                vec = np.array(vec).reshape((1, -1))

                output_row = [ instance_id, location, identity, other_identity ]

                preds = clf.predict(vec)
                pred = str(preds[0])
                output_row.append(pred)

                end = time.time()
                time_sum += end-start

            except BaseException as e:
                print((repr(e)))
                continue

            try:
                outf.write('\t'.join(output_row) + '\n')

                if line_no % 500 == 0:
                    print(('Saw %d instances, average time: %f (%s)' \
                          % (line_no, time_sum / float(line_no), input_file)))
                    outf.flush()
                    # break
                    # outf.flush()

            except BaseException as e:
                print((repr(e)))
                continue

def normalize(text):
    text = text.strip()
    if len(text) > 1:
        text = text[0].upper() + text[1:]

    text = re.sub(r'\bi\b', 'I', text)
    text = re.sub(r'\b([yY])oure\b', r"\1ou're", text)
    text = re.sub(r'\b([yY])ouve\b', r"\1ou've", text)
    text = re.sub(r'\b([wWdD])ont\b', r"\1on't", text)
    text = re.sub(r'\b([tTwW])hats\b', r"\1hat's", text)
    text = re.sub(r'\b[iI]m\b', "I'm", text)
    text = re.sub(r'\bu\b', 'you', text)

    return text

if __name__ == '__main__':
    main()


#!/usr/bin/env python3

# TODO hdf5 overwrite mode, group hierarchy, maybe cache silent identifier

import logging

logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG)

from itertools import product as product

import click

import h5py
import numpy as np

# AP Moyer
import getpy as gp

# maybe no NeRF necessary
# from nerf import iNeRF, NeRF

# Will Sheffler
# from homog import hstub
from xbin import XformBinner as xb

# No direct import of pyrosetta needed for this executable
# import pyrosetta
from pyrosetta.rosetta.core.io.silent import SilentFileData as SilentFileData
from pyrosetta.rosetta.core.io.silent import (
    SilentFileOptions as SilentFileOptions,
)

from hashed_loop import (
    check_no,
    dumb_clean_pose,
    run_pyrosetta_with_flags,
    poses_from_silent,
    pose_from_sfd_tag,
    parse_loop_iter,
    np_rt_from_residues,
    silent_tag_to_poselets,
)

def peptide_dist(res_1, res_2):
    """
    Returns dist C of res_1 to N of res_2

    Intentionally brittle, meant to throw RuntimeError if there's no C/N atoms
    """

    return (res_1.atom("C").xyz() - res_2.atom("N").xyz()).norm()

def parse_xforms_from_poselets(poselets, tag, max_n_mer=20):
    """
    Using 2 res poses to parse all xforms

    We're doing this weird hack because loading poses is big O N^2 on num res,
    so it is programmatically faster to load n/2 poses of size 2 than to load
    one pose of size n on average. If you're reading this docstring and this is
    no longer true, please for goodness sake delete this horror
    """
    n_poselets = len(poselets)
    logging.debug(f"pose size (n_poselets): {n_poselets}")
    xforms_list = []
    loop_data_string_list = []
    for root_i in range(n_poselets):
        pose_1 = poselets[root_i]
        # check for chainbreak, also a proxy for broken pose
        # We can't do all the broken pose checks here, but it filters some egregious things early
        r1 = pose_1.residue(1)
        try:
            dist = peptide_dist(r1, pose_1.residue(2))
            if dist > 1.5:
                # Skip if chainbreak b/w res1/2
                continue
        except RuntimeError as e:
            print(e)
            print(f"error checking poselet: {root_i}")
            print(f"sequence: {poselets[root_i].annotated_sequence()}")
            # if this poselet breaks, skip all rooted on it
            continue
        break_next = False
        for n_mer_end in range(2, max_n_mer):

            if break_next:
                break_next = False
                break
            r2_i = root_i + n_mer_end
            if r2_i >= n_poselets:
                break
            pose_2 = poselets[r2_i]
            r2 = pose_2.residue(1)
            try:
                dist = peptide_dist(r2, pose_2.residue(2))
                if dist > 1.5:
                    # If we detect a chainbreak, we can't take any more stretches from the current root
                    break_next = True

            except RuntimeError as e:
                print(e)
                print(f"error checking poselet: {r2_i}")
                print(f"sequence: {poselets[r2_i].annotated_sequence()}")
                # if this poselet breaks, skip it and all after sharing the same root
                break
            logging.debug("attempting to process xform ...")
            logging.debug(f"start: {root_i +1} end: {r2_i + 1}")

            if not (
                r1.type().is_canonical_aa() and r2.type().is_canonical_aa()
            ):

                logging.debug("invalid anchor residues, not canonical AA")
                continue
            xform = np_rt_from_residues(r1, r2)
            xforms_list.append(xform)
            # small redundancy here on the tag, maybe remove
            # problem is that it's so convenient to just staple these bad boys
            # into a big list as line items later
            loop_data_string_list.append(f"{tag}:{root_i+1}:{r2_i+1}")
    return loop_data_string_list, xforms_list

def setup_xbin_vars(xbin_cart_list, xbin_ori_list, file):
    """
    Just here to make main look cleaner
    """

    if file:
        with open(file, "r") as f:
            file_list = f.read().splitlines()

        xbin_cart_list_additional, xbin_ori_list_additional = zip(
            *[tuple(map(float, l.split())) for l in file_list]
        )
        xbin_cart_list.extend(xbin_cart_list_additional)
        xbin_ori_list.extend(xbin_ori_list_additional)
        xbin_cart_list = list(set(xbin_cart_list))
        xbin_ori_list = list(set(xbin_ori_list))
    if not xbin_cart_list:
        xbin_cart_list = [1.0]
    if not xbin_ori_list:
        xbin_ori_list = [15.0]

    return xbin_cart_list, xbin_ori_list

def parse_xforms_from_tag(sfd, tag, max_n_mer=20):
    """
    Shaving some sort of large animal...

    This is wrapper written to compare poselets to full pose loading
    Unfortunately loading poses two res at a time n times (where n is pose len)
    is faster than loading the pose once WTF just rosetta things
    """
    pose = pose_from_sfd_tag(sfd, tag)
    loop_data_string_list = []
    xforms_list = []
    for begin, end in parse_loop_iter(pose):
        if begin < 1 or end > pose.size():
            continue
        r1 = pose.residue(begin)
        r2 = pose.residue(end)
        logging.debug("attempting to process xform ...")
        logging.debug(f"start: {begin} end: {end}")

        if not (r1.type().is_canonical_aa() and r2.type().is_canonical_aa()):

            logging.debug("invalid anchor residues, not canonical AA")
            continue
        xform = np_rt_from_residues(r1, r2)
        xforms_list.append(xform)
        # small redundancy here on the tag, maybe remove
        # problem is that it's so convenient to just staple these bad boys
        # into a big list as line items later
        loop_data_string_list.append(f"{tag}:{begin}:{end}")
    return loop_data_string_list, xforms_list

# using ifmain for click
@click.command()
@click.argument("silent_file", nargs=1)
@click.option("-r", "--rosetta-flags", "rosetta_flags_file", default="")
@click.option(
    "-c",
    "--xbin-cart-res",
    "xbin_cart_list",
    default=[],
    type=float,
    multiple=True,
    help="cart resl to use for xbin. Default is 1. This option can be used multiple times to make a combination of tables",
)
@click.option(
    "-o",
    "--xbin-ori-res",
    "xbin_ori_list",
    default=[],
    type=float,
    multiple=True,
    help="ori resl to use for xbin. Default is 1. This option can be used multiple times to make a combination of tables",
)
@click.option(
    "-m",
    "--max-frag-len",
    "max_len",
    default=20,
    type=int,
    show_default=True,
    help="the max fragment size to use for building the table",
)
@click.option(
    "-f",
    "--resolution-scan-config-file",
    "scan_file",
    type=click.Path(exists=True),
    help="It is possible to provide a file with cart resl in the first column and ori in the second. This will build all the appropriate hashmaps as well as indexing the keys,values, and strings in a single hdf5 archive. If you provide a file and also specify resolutions on command line this script will use both.",
)
def main(
    silent_file,
    rosetta_flags_file="",
    xbin_cart_list=[],
    xbin_ori_list=[],
    max_len=20,
    scan_file="",
):

    """
    Generates a loop e2e xbin table referencing a silentfile with metadata

    e2e hashtable holds just xbin keys and table entry keys. The table entry
    keys are just arbitrary indices that go to a table referncing a silentfile

    The table is just a list of tags and positions in a text list. The values
    deposited in the getpy dict are a two number coordinate: start index and num entries.
    To find all the appropriate values, just load the txt list into a python list
    and slice it: list[start:start + num_entries].

    """
    run_pyrosetta_with_flags(rosetta_flags_file)

    key_type = np.dtype("i8")
    value_type = np.dtype("i8")
    gp_dict = gp.Dict(key_type, value_type)

    xforms = []
    loop_data_string_list = []

    # silent_name = "loop_structs_out.silent"
    sfd = SilentFileData(
        silent_file, False, False, "binary", SilentFileOptions()
    )

    # for pose in poses_from_silent(silent_file):
    sfd.read_file(silent_file)
    for tag in sfd.tags():
        logging.debug(f"working on tag: {tag}")
        try:
            poses = silent_tag_to_poselets(silent_file, tag, 1, 2)
        except AssertionError:
            logging.debug("assertion in hackload failed, skipping")
            continue
        except RuntimeError:
            logging.debug("Unable to load this fragment in hackload, skipping")
            continue
        tag_loop_data_list, tag_xforms_list = parse_xforms_from_poselets(
            poses, tag, max_n_mer=max_len
        )
        # tag_loop_data_list, tag_xforms_list = parse_xforms_from_tag(
        #     sfd, tag, max_n_mer=max_len
        # )
        loop_data_string_list.extend(tag_loop_data_list)
        xforms.extend(tag_xforms_list)

        logging.debug("loop data loaded")
    xbin_cart_list, xbin_ori_list = setup_xbin_vars(
        xbin_cart_list, xbin_ori_list, scan_file
    )
    logging.debug(f"fragments extracted, building tables")
    logging.debug(
        f"""xbin params:
    c:{xbin_cart_list}
    o:{xbin_ori_list}"""
    )
    for xbin_cart, xbin_ori in product(xbin_cart_list, xbin_ori_list):

        binner = xb(cart_resl=xbin_cart, ori_resl=xbin_ori)
        all_keys_non_unique = binner.get_bin_index(np.array(xforms))

        keys_unique = {}
        for key, loop_data_string in zip(
            all_keys_non_unique, loop_data_string_list
        ):
            if key in keys_unique.keys():
                keys_unique[key].append(loop_data_string)
            else:
                keys_unique[key] = [loop_data_string]

        offset = 0
        strings_master = []
        gp_vals_list = []
        gp_keys_list = []
        for key, strings in keys_unique.items():
            num_strings = len(strings)
            strings_master.extend(strings)
            gp_keys_list.append(key)
            gp_vals_list.append([offset, num_strings])
            offset += num_strings
        gp_keys = np.array(gp_keys_list, dtype=np.int64)
        gp_vals = np.array(gp_vals_list, dtype=np.int64)
        general_vals = gp_vals
        # squash data to fit into getpy_dict
        gp_vals = gp_vals.astype(np.int32).reshape(-1)
        gp_vals = gp_vals.view(np.int64)

        gp_dict[gp_keys] = gp_vals

        gp_dump = f"gp_c{xbin_cart}_o{xbin_ori}.bin"
        gp_dict.dump(gp_dump)

        key_val_data = np.empty((gp_keys.shape[0], 3), dtype=np.int64)
        key_val_data[:, 0] = gp_keys
        key_val_data[:, 1:] = general_vals

        # string_master_file = f"loop_tag_index_c{xbin_cart}_o{xbin_ori}.txt"
        np_strings_master = np.array(strings_master, dtype=np.string_)
        #
        # with open(string_master_file, mode="wt", encoding="utf-8") as f:
        #     f.write("\n".join(strings_master))
        #     f.write("\n")

        # npz_out = "key_val_data.npz"
        # np.savez(npz_out, key_val_data)

        hdf5 = h5py.File("fragment_data.hf5", "a")
        kv_group = hdf5.require_group("key_value_data")
        key_val_ds = kv_group.require_dataset(
            f"key_val_index_cart_{xbin_cart}_ori_{xbin_ori}_nmer_{max_len}",
            key_val_data.shape,
            dtype=key_val_data.dtype,
        )
        key_val_ds[:] = key_val_data
        key_val_ds.attrs.create("cart_resl", data=xbin_cart)
        key_val_ds.attrs.create("ori_resl", data=xbin_ori)
        key_val_ds.attrs.create("max_len", data=max_len)
        key_val_ds.attrs.create(
            "description",
            data="this is a 2XN np array where col1 are the int64 xbin keys and col2/3 are two upcast int32s (row,n_strings) addressing a sequence of strings in a corresponding archive",
        )
        str_group = hdf5.require_group("string_archive")
        string_archive = str_group.require_dataset(
            f"string_archive_cart_{xbin_cart}_ori_{xbin_ori}_nmer_{max_len}",
            np_strings_master.shape,
            dtype=np_strings_master.dtype,
        )
        string_archive[:] = np_strings_master
        string_archive.attrs.create("cart_resl", data=xbin_cart)
        string_archive.attrs.create("ori_resl", data=xbin_ori)
        string_archive.attrs.create("max_len", data=max_len)
        string_archive.attrs.create(
            "description",
            data="Ordered archive of strings describing pose fragments by tag:start:end. The order is addressed by the corresponding key_val dataset",
        )
        # str_id = string_archive.id
        # key_val_ds.attrs.create("string_archive_id", data=str_id)
        hdf5.close()

if __name__ == "__main__":
    main()


import skimage.io as io
import skimage.transform as skt
import numpy as np
from PIL import Image
from src.models.class_patcher import patcher
from src.utils.imgproc import *
from scipy.interpolate import interp1d

class patcher(patcher):
    def __init__(self, body='./body/body_uketsukejo.png', **options):
        super().__init__('受付嬢', body=body, pantie_position=[860, 1671], **options)
        self.mask = io.imread('./mask/mask_uketsukejo.png')

    def convert(self, image):
        pantie = np.array(image)

        patch = np.copy(pantie[-140:-5, 546:, :])
        patch = skt.resize(patch[::-1, ::-1, :], (230, 65), anti_aliasing=True, mode='reflect')
        [pr, pc, d] = patch.shape
        pantie[127 - 5:127 - 5 + pr, :pc, :] = np.uint8(patch * 255)
        front = pantie[:, :300]
        back = pantie[:, 300:-10]
        back[380:] = 0
        front = front[::-1, ::-1]
        back = back[::-1, ::-1]

        def mesh_transform(img, arr):
            [r, c, d] = img.shape
            src_cols = np.linspace(0, c, int(np.sqrt(arr.shape[0])))
            src_rows = np.linspace(0, r, int(np.sqrt(arr.shape[0])))
            src_rows, src_cols = np.meshgrid(src_rows, src_cols)
            src = np.dstack([src_cols.flat, src_rows.flat])[0]
            affin = skt.PiecewiseAffineTransform()
            affin.estimate(arr, src)
            return skt.warp(img, affin)

        front_arr = np.array([
            [280, 144],
            [305, 171],
            [314, 203],
            [314, 241],
            [314, 365],

            [286, 124],
            [330, 141],
            [346, 181],
            [355, 222],
            [427, 350],

            [284, 88],
            [351, 108],
            [378, 131],
            [391, 183],
            [512, 283],

            [263, 74],
            [351, 69],
            [421, 97],
            [454, 135],
            [569, 190],

            [216, -2],
            [406, 0],
            [475, 12],
            [532, 26],
            [623, 88],
        ])
        front_arr[:, 0] -= back.shape[1]

        back_arr = np.array([
            [348, 0],
            [249, 0],
            [158, 11],
            [78, 27],
            [5, 54],

            [348, 72],
            [260, 73],
            [186, 89],
            [118, 111],
            [40, 156],

            [342, 96],
            [290, 124],
            [223, 140],
            [174, 187],
            [100, 250],

            [354, 113],
            [310, 155],
            [274, 189],
            [238, 245],
            [200, 334],

            [378, 146],
            [346, 176],
            [324, 212],
            [320, 245],
            [320, 365],
        ])
        front = np.uint8(mesh_transform(front, front_arr)[:, :-2] * 255)
        back = np.uint8(mesh_transform(back, back_arr)[:, 2:] * 255)
        pantie = np.concatenate((back, front), axis=1)[:-30]
        pantie = np.bitwise_and(pantie, self.mask)
        return Image.fromarray(pantie)