import os
# import cv2
import json
import math
import random
import numpy as np
from format_pascal import catID_to_catName
from format_pascal import catName_to_catID
from format_coco import parse_categories

data_path = '/media/julioarroyo/aspen/data'
coco_path = '/coco/annotations/'
labels_path = '/home/julioarroyo/research_Eli_and_Julio/single-positive-multi-label-julio/data/coco'
SEED = 10

f_train = open(data_path + coco_path + 'instances_train2014.json')
f_val = open(data_path + coco_path + 'instances_val2014.json')
files = {'train' : json.load(f_train), 'val' : json.load(f_val)}

def get_anns_by_imID():
    imID_to_anns = {}
    for phase in ['train', 'val']:
        D = files[phase]
        for i in range(len(D['annotations'])):
            if not D['annotations'][i]['image_id'] in imID_to_anns:
                imID_to_anns[D['annotations'][i]['image_id']] = []
            imID_to_anns[D['annotations'][i]['image_id']].append(D['annotations'][i])
    return imID_to_anns

def get_sum_areas(annotations):
    sum_area = 0
    for ann in annotations:
        sum_area += ann['area']
    return sum_area

def make_biased_matrix(imID_to_anns, bias_type, num_categories, cat_id_to_index):
    for split in ['train', 'val']:
        D = files[split]
        image_id_and_weights = []
        image_id_list = sorted(np.unique([str(D['annotations'][i]['image_id']) for i in range(len(D['annotations']))]))
        image_id_list = np.array(image_id_list, dtype=int)
        image_id_to_index = {image_id_list[i]: i for i in range(len(image_id_list))}

        for im_id in image_id_list:
            weights_i = [0 for _ in range(num_categories)]
            if bias_type == 'size':
                sum_areas = get_sum_areas(imID_to_anns[im_id])
                assert sum_areas > 0
                annotations = imID_to_anns[im_id]
                for j in range(len(annotations)):
                    weight = annotations[j]['area'] / sum_areas
                    cat_id = annotations[j]['category_id']
                    cat_idx = cat_id_to_index[cat_id]
                    weights_i[cat_idx] += weight
            image_id_and_weights.append((im_id, weights_i))

        label_matrix = np.load(os.path.join(labels_path, 'formatted_{}_labels.npy'.format(split)))
        biased_matrix = np.zeros_like(label_matrix)
        for k in range(len(image_id_and_weights)):
            im_id = int(image_id_and_weights[k][0])
            weights = image_id_and_weights[k][1]
            row_idx = image_id_to_index[im_id]
            labels = label_matrix[row_idx][:]
            assert len(labels) == len(weights)
            col_idx = random.choices(range(len(labels)), weights=weights)[0]
            assert label_matrix[row_idx][col_idx] == 1
            biased_matrix[row_idx][col_idx] = 1
        np.save(os.path.join(labels_path,
                             'coco_formatted_{}_{}_{}_labels_obs.npy'.format(split, bias_type, 1)),
                             biased_matrix)

if __name__ == '__main__':
    imID_to_anns = get_anns_by_imID()
    (category_list, cat_id_to_index) = parse_categories(files['train']['categories'])
    bias_type = 'size'
    random.seed(SEED)
    make_biased_matrix(imID_to_anns, bias_type, len(category_list), cat_id_to_index)

# def get_imID_to_dims():
#     imID_to_dims = {}
#     for phase in ['train', 'phase']:
#         f = open(data_path + coco_path + 'instances_{}2014.json'.format(phase))
#         D = json.load(f)
#         for i in range(len(D['images'])):
#             imID_to_dims[D['images'][i]['id']] = [D['images'][i]['width'], D['images'][i]['height']]
#         f.close()
#     return imID_to_dims

# def get_center_bias_norm_const(annotations, imID_to_dims):
#     sum_inv_dist = 0
#     for ann in annotations:
#         center = imID_to_dims[ann['image_id']]
#         x_i = ann['bbox'][0] + ann['bbox'][2]/2 # x-coord. of center of annotation
#         y_i = ann['bbox'][1] + ann['bbox'][3]/2 # y-coord. of center of annotation
#         d_i = math.sqrt((x_i - center[0])**2 + (y_i - center[1])**2)
#         if d_i == 0:
#             d_i = 1
#         sum_inv_dist += 1/d_i
#     return 1/sum_inv_dist

# def get_weights_per_im(imID_to_anns, bias_type):
#     imID_to_catWeights = {}
#     imID_to_annWeights = {}
#     for imID in imID_to_anns:
#         # imID_to_catWeights[imID][i] will be the weight of the (i + 1)-th category as given by D['categories']
#         # reason i + 1 is that pascal_ann.json 1-indexed the categories
#         imID_to_catWeights[imID] = {meta['category_id_to_index'][cat_id] : 0 for cat_id in meta['category_id_to_index']}
#         if bias_type == 'size':
#             sum_areas = get_sum_areas(imID_to_anns[imID])
#             assert sum_areas > 0
#             for i in range(len(imID_to_anns[imID])):
#                 weight = imID_to_anns[imID][i]['area'] / sum_areas
#                 cat_col_idx = meta['category_id_to_index'][imID_to_anns[imID][i]['category_id']]
#                 imID_to_catWeights[imID][cat_col_idx] += weight
#         elif bias_type == 'location':
#             assert False  # TODO: Make location bias work too
#             imID_to_dims = get_imID_to_dims()
#             norm_const = get_center_bias_norm_const(imID_to_anns[imID], imID_to_dims)
#             assert norm_const > 0
#             for j in range(len(imID_to_anns[imID])):
#                 img_ctr = imID_to_dims[imID]
#                 x_i = imID_to_anns[imID][j]['bbox'][0] + imID_to_anns[imID][j]['bbox'][2]/2
#                 y_i = imID_to_anns[imID][j]['bbox'][1] + imID_to_anns[imID][j]['bbox'][3]/2
#                 d_i = math.sqrt((x_i - img_ctr[0])**2 + (y_i - img_ctr[1])**2)
#                 imID_to_annWeights[imID][j] = norm_const/d_i
#                 imID_to_catWeights[imID][imID_to_anns[imID][j]['category_id'] - 1] += norm_const/d_i
#     return (imID_to_catWeights, imID_to_annWeights)

# # def get_weights_per_im(imID_to_anns):

# #     imID_to_catWeights = {}
# #     imID_to_annWeights = {}
# #     for imID in imID_to_anns:
# #         # imID_to_catWeights[imID][i] will be the weight of the (i + 1)-th category as given by D['categories']
# #         # reason i + 1 is that pascal_ann.json 1-indexed the categories
# #         imID_to_catWeights[imID] = [0 for _ in range(20)]
# #         imID_to_annWeights[imID] = [0 for _ in range(len(imID_to_anns[imID]))]
# #         sum_areas = get_sum_areas(imID_to_anns[imID])
# #         assert sum_areas > 0

# #         # START new code
# #         # if bias == 'size':
# #         #     sum_areas = get_sum_areas(imID_to_anns[imID])
# #         #     assert sum_areas > 0
# #         # elif bias == 'location':
# #         #     continue
# #         # END NEW CODE
# #         for i in range(len(imID_to_anns[imID])):
# #             imID_to_catWeights[imID][imID_to_anns[imID][i]['category_id'] - 1] += imID_to_anns[imID][i]['area'] / sum_areas
# #             imID_to_annWeights[imID][i] = imID_to_anns[imID][i]['area'] / sum_areas
# #     return (imID_to_catWeights, imID_to_annWeights)

# def create_image_list(ann_dict, image_list, phase):
#     # TODO: no reason to repeat this code from format_pascal.py
#     # image_list = []
#     for cat_name in catName_to_catID:
#         with open(os.path.join(data_path + '/pascal', 'VOCdevkit', 'VOC2012', 'ImageSets', 'Main', cat_name + '_' + phase + '.txt'), 'r') as f:
#             for line in f:
#                 cur_line = line.rstrip().split(' ')
#                 image_id = cur_line[0]
#                 label = cur_line[-1]
#                 image_fname = image_id + '.jpg'
#                 # if cat occurs, save it in ann_dict, which maps from image to catID that occur in the image
#                 # image_list holds all images with annotated objects in them, classified by train or val
#                 if int(label) == 1:
#                     if image_fname not in ann_dict:
#                         ann_dict[image_fname] = []
#                         image_list[phase].append(image_id)
#                     ann_dict[image_fname].append(catName_to_catID[cat_name])
#     # return image_list

# def observe_bias(label_matrix, imID_to_catWeights, phase, num_observations=1):
#     '''
#     Issue: I want to visualize biased labels. Eli's approach is to have a matrix of ocurrences.
#     So I can get the most likely observation and make a label_matrix. But I won't be able to visualize
#     from that, I need to know which specific annotation is most likely.
#     '''
#     label_matrix_biased = np.zeros_like(label_matrix)
#     (num_images, _) = np.shape(label_matrix_biased)
#     for im_id in imID_to_catWeights:
#         meta[]
#     # for row_idx in range(num_images):
#     #     im_id = meta["row_idx_to_im_id"][phase][row_idx]
#     #     cat_idx_to_weight = imID_to_catWeights[im_id]
#     #     cat_weights = np.zeros_like(label_matrix[row_idx])
#     #     for cat_idx in range(len(cat_weights)):
#     #         cat_weights[cat_idx] = cat_idx_to_weight[cat_idx]
#     #     idx_pos = int(random.choices(label_matrix[row_idx], cat_weights, k=num_observations)[0])
#     #     label_matrix_biased[row_idx][idx_pos] = 1.0
#     return label_matrix_biased

# def get_matrixIdx_to_imID(image_list_ph):
#     matrix_idx_2_im_id = {}
#     for i in range(len(image_list_ph)):
#         matrix_idx_2_im_id[i] = image_list_ph[i]
#     return matrix_idx_2_im_id

# def get_biased_annotations(imID_to_anns, imID_to_annWeights):
#     biased_annotations = {}
#     for curr_image_id in imID_to_anns:
#         curr_weights = imID_to_annWeights[curr_image_id]
#         chosen_annotation = random.choices(imID_to_anns[curr_image_id], curr_weights)
#         biased_annotations[curr_image_id] = chosen_annotation[0]
#     return biased_annotations

# # def visualize_bias(imID_to_anns, biased_annotations):
# #     font = cv2.FONT_HERSHEY_SIMPLEX
# #     font_scale = 0.85
# #     color = (255, 0, 127)
# #     thickness = 2

# #     sample_size = 5
# #     indices = [random.randint(0, len(D['annotations']) - 1) for _ in range(sample_size)]
# #     sample_image_ids = [D['annotations'][idx]['image_id'] for idx in indices]
# #     im_folder_path = '/home/julioarroyo/research Eli and Julio/Biased-training-dataset-generation-for-multilabel-classification/data/pascal/VOCdevkit/VOC2012/JPEGImages/'
# #     for k in range(len(sample_image_ids)):
# #         window_name = 'Visualize biased sampling'
# #         fully_annotated = cv2.imread(im_folder_path + sample_image_ids[k] + '.jpg')
# #         for ann in imID_to_anns[sample_image_ids[k]]:
# #             top_left = (ann['bbox'][0], ann['bbox'][1])
# #             bottom_right = (ann['bbox'][0] + ann['bbox'][2], ann['bbox'][1] + ann['bbox'][3])
# #             fully_annotated = cv2.rectangle(fully_annotated, top_left, bottom_right, color, thickness)
# #             cv2.putText(fully_annotated, catID_to_catName[ann['category_id'] - 1], top_left, font, fontScale=font_scale, color=color, thickness=thickness, lineType=cv2.LINE_AA)
# #         partially_annotated = cv2.imread(im_folder_path + sample_image_ids[k] + '.jpg')
# #         biased_ann = biased_annotations[sample_image_ids[k]]
# #         top_left = (biased_ann['bbox'][0], biased_ann['bbox'][1])
# #         bottom_right = (biased_ann['bbox'][0] + biased_ann['bbox'][2], biased_ann['bbox'][1] + biased_ann['bbox'][3])
# #         partially_annotated = cv2.rectangle(partially_annotated, top_left, bottom_right, color, thickness)
# #         cv2.putText(partially_annotated, catID_to_catName[biased_ann['category_id'] - 1], top_left, font, fontScale=font_scale, color=color, thickness=thickness, lineType=cv2.LINE_AA)

# #         comparison = np.concatenate((fully_annotated, partially_annotated), axis=1)
# #         cv2.imshow(window_name, comparison)
# #         cv2.waitKey()

# def test_observe_bias(imID_to_catWeights):
#     sample_size = 5
#     indices = [random.randint(0, len(D['annotations']) - 1) for _ in range(sample_size)]
#     sample_image_ids = [D['annotations'][idx]['image_id'] for idx in indices]
#     for k in range(len(sample_image_ids)):
#         curr_weights = imID_to_catWeights[sample_image_ids[k]]
#         N = 1000
#         frequencies = [0 for _ in range(20)]
#         for i in range(N):
#             idx_pos = random.choices(list(range(20)), curr_weights)[0]
#             frequencies[idx_pos] += 1
#         max_freq = float('-inf')
#         best_pos = -1
#         for j in range(len(frequencies)):
#             if frequencies[j] > max_freq:
#                 max_freq = frequencies[j]
#                 best_pos = j
#         print('RESULT {}'.format(k))
#         print('Image ID: {}'.format(sample_image_ids[k]))
#         print('Most often labeled category was {}, which was chosen with probability {}'.format(catID_to_catName[best_pos], max_freq/N))
#         print('The weights were {}'.format(curr_weights))

# def test_sampling(N, bias):
#     for phase in ['train', 'val']:
#         full_labels = np.load(os.path.join(labels_path, 'formatted_{}_labels.npy'.format(phase)))
#         misses = 0
#         for i in range(1, 1 + N):
#             single_labels = np.load(os.path.join(labels_path, f'coco_formatted_{phase}_{bias}_{i}_labels_obs.npy'))
#             print('SINGLE SHAPE {} FULL {}'.format(single_labels.shape, full_labels.shape))
#             assert full_labels.shape == single_labels.shape, f'{full_labels.shape} {single_labels.shape} phase {phase}'
#             rows, cols = single_labels.shape
#             print(f'single_labels.shape {single_labels.shape}')
#             for r in range(rows):
#                 for c in range(cols):
#                     if single_labels[r][c] == 1:
#                         if not full_labels[r][c] == 1:
#                             misses += 1
#         print('misses {} for {}'.format(misses, phase))
#     return

# if __name__ == '__main__':
#     mode = 'test'  # 'test' or 'run'
#     bias = 'size'

#     imID_to_anns = get_anns_by_imID()
#     # (cat_list, cat_id_to_index) = parse_categories()
#     (imID_to_catWeights, _) = get_weights_per_im(imID_to_anns, bias)

#     N = 1

#     if mode == 'test':
#         test_sampling(N, bias)
#     else:
#         ann_dict = {}
#         image_list = {'train': [], 'val': []}

#         for i in range(1, N + 1):
#             for phase in ['train', 'val']:
#                 base_path = data_path + 'coco/'
#                 label_matrix = np.load(os.path.join('/home/julioarroyo/research_Eli_and_Julio/single-positive-multi-label-julio/data/coco', 'formatted_{}_labels.npy'.format(phase)))
#                 assert np.max(label_matrix) == 1
#                 assert np.min(label_matrix) == 0

#                 # image_list_ph = create_image_list(ann_dict, phase)
#                 # create_image_list(ann_dict, image_list, phase)
#                 # assert len(image_list[phase]) > 0
#                 # image_list[phase].sort()
#                 # matrix_idx_2_im_id = get_matrixIdx_to_imID(image_list)

#                 # convert label matrix to -1 / +1 format:
#                 label_matrix[label_matrix == 0] = -1

#                 random.seed(SEED)
#                 biased_matrix = observe_bias(label_matrix, imID_to_catWeights, phase)
#                 assert label_matrix.shape == biased_matrix.shape, f'{label_matrix} {biased_matrix}'
#                 np.save(os.path.join('/home/julioarroyo/research_Eli_and_Julio/single-positive-multi-label-julio/data/coco', 'coco_formatted_{}_{}_{}_labels_obs.npy'.format(phase, bias, i)), biased_matrix)

#         # biased_dataset = get_biased_annotations(imID_to_anns, imID_to_annWeights)
#         # visualize_bias(imID_to_anns, biased_dataset)


from __future__ import with_statement
import eg

eg.RegisterPlugin(
    name = "UIRT2",
    author = "Bitmonster",
    version = "1.1",
    kind = "remote",
    guid = "{DEB2BDB1-F7BD-44B1-B5F7-153B54C3A245}",
    canMultiLoad = True,
    description = (
        'Hardware plugin for the '
        'Universal InfraRed Transceiver V2.'
    ),
    icon = (
        "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAaElEQVR42mNkoBAwDgMD"
        "/jMw/IeaRLJhIL1gAw4eOMBg7+AANwQsgYWNrrkR2QWkGALTXE+uAQ1APkgziguQQpU8"
        "F5BiAE4XNEIkGYkJRJghcANgmkmJRpAhjA1QA0jVjORlysDAGwAAHWBIBf4cTRAAAAAA"
        "SUVORK5CYII="
    ),
)

import wx
from threading import Thread, Event
from time import sleep, clock
from binascii import hexlify, unhexlify
from Queue import Queue, Full
from string import hexdigits

# currently unused stuff

#def GetStructTime(code, start):
#    tvalue = (ord(code[start+1]) * 256) + ord(code[start+2])
#    bBits = ord(code[start+3])
#    bHdr1 = ord(code[start+4])
#    bHdr0 = ord(code[start+5])
#    bOff0 = ord(code[start+6])
#    bOff1 = ord(code[start+7])
#    bOn0 = ord(code[start+8])
#    bOn1 = ord(code[start+9])
#    tvalue += bHdr1 + bHdr0
#    for i in range(0, bBits):
#        bit = (ord(code[start + 10 + (i / 8)]) >> (i % 8)) & 1
#        if (i % 2) == 0:
#            if bit:
#                tvalue += bOn1
#            else:
#                tvalue += bOn0
#        else:
#            if bit:
#                tvalue += bOff1
#            else:
#                tvalue += bOff0
#    return tvalue
#
#
#def CalcTime(code):
#    tvalue = 0
#    if code[0] == "\x36":
#        # RAW
#        length = ord(code[1])
#        tvalue = (ord(code[2]) * 256) + ord(code[3])
#        for i in range(4, length + 4):
#            tvalue += ord(code[i])
#        tvalue = tvalue * (ord(code[-2]) & 0x1F)
#        #tvalue -= (ord(code[2]) * 256) + ord(code[3])
#    elif (ord(code[0]) & 0x1F) > 0:
#        # REMSTRUCT1
#        repeat = ord(code[0]) & 0x1F
#        tvalue = GetStructTime(code, 0) * repeat
#        #tvalue -= (ord(code[1]) * 256) + ord(code[2])
#
#    else:
#        # REMSTRUCT2
#        tvalue = GetStructTime(code, 0)
#        repeat = ord(code[26]) & 0x1F
#        tvalue = tvalue + (GetStructTime(code, 26) * repeat)
#    return tvalue * SAMPLE_TIME

def CalcChecksum(data):
    checksum = 0
    for byte in data:
        checksum += ord(byte)
        checksum %= 256
    checksum = (0x100 - checksum) % 256
    return chr(checksum)

class HexValidator(wx.PyValidator):

    def __init__(self, maxLength=100, allowRaw=False):
        self.maxLength = maxLength
        self.allowRaw = allowRaw
        wx.PyValidator.__init__(self)
        self.Bind(wx.EVT_CHAR, self.OnChar)

    def Clone(self):
        return HexValidator(self.maxLength, self.allowRaw)

    def TransferToWindow(self):
        return True

    def TransferFromWindow(self):
        return True

    @eg.LogIt
    def Validate(self, win):
        val = win.GetValue()
        for x in val:
            if x not in hexdigits:
                return False
        return True

    def OnChar(self, event):
        key = event.KeyCode

        if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
            event.Skip()
            return

        textCtrl = self.GetWindow()
        startPos, endPos = textCtrl.GetSelection()
        length = textCtrl.GetLastPosition() - (endPos - startPos)
        if length >= self.maxLength:
            if not wx.Validator_IsSilent():
                wx.Bell()
            return

        if(
            self.allowRaw
            and textCtrl.GetInsertionPoint() == 0
            and chr(key).upper() == "R"
        ):
            textCtrl.WriteText("R")
            return

        if chr(key) in hexdigits:
            textCtrl.WriteText(chr(key).upper())
            return

        if not wx.Validator_IsSilent():
            wx.Bell()

        # Returning without calling event.Skip eats the event before it
        # gets to the text control
        return

class UIRT2(eg.IrDecoderPlugin):

    def __init__(self):
        eg.IrDecoderPlugin.__init__(self, 50.0)
        self.buffer = ""
        self.AddAction(TransmitIR)

    def __start__(self, comport=0):
        serialThread = self.serialThread = eg.SerialThread()
        serialThread.Open(comport, 115200)
        serialThread.Start()
        serialThread.SetRts()
        for dummyCounter in range(3):
            sleep(0.05)
            serialThread.Flush()
            serialThread.Write("\x23\xdd") # get version
            if serialThread.Read(3, 0.2) != "\x01\x04\xFB":
                continue
            serialThread.Write("\x21\xdf") # set RAW mode
            if serialThread.Read(1, 0.1) != "\x21":
                continue
            break
        else:
            serialThread.Close()
            raise self.Exceptions.InitFailed
        self.buffer = ""
        serialThread.SetReadEventCallback(self.OnReceive)
        self.sendQueue = Queue(50)
        self.alive = True
        Thread(target=self.SendLoop).start()

    @eg.LogIt
    def __stop__(self):
        self.alive = False
        self.sendQueue.put((StopIteration, None))
        self.serialThread.SuspendReadEvents()
        self.serialThread.Write("\x20\xe0")
        self.serialThread.Close()

    def __close__(self):
        self.irDecoder.Close()

    #@eg.LogIt
    def OnReceive(self, serialThread):
        self.buffer += serialThread.Read(1024)
        while True:
            terminatorPos = self.buffer.find("\xff")
            #print terminatorPos
            if terminatorPos < 0:
                break
            data = self.buffer[2:terminatorPos+1]
            self.buffer = self.buffer[terminatorPos+1:]
            if len(data) < 2:
                continue
            self.irDecoder.Decode(data, len(data))

    @eg.LogItWithReturn
    def SendLoop(self):
        while self.alive:
            code, event = self.sendQueue.get()
            if code == StopIteration:
                return
            with self.serialThread as serial:
                serial.Write(code)
                sleep(0.05)
                data = serial.Read(1)
                if data != " ":
                    self.PrintError("Error sending IR code to UIRT2")
                data = ""
                startTime = clock()
                while data != "\x21":
                    if (clock() - startTime) > 5.0:
                        self.PrintError("Transmitting timed out")
                        break
                    serial.Write("\x21\xdf")
                    sleep(0.05)
                    data = serial.Read(1)
            event.set()

    def Configure(self, comport=0):
        panel = eg.ConfigPanel()
        portCtrl = panel.SerialPortChoice(comport)
        panel.AddLine("COM-Port:", portCtrl)
        while panel.Affirmed():
            panel.SetResult(portCtrl.GetValue())

class TransmitIR(eg.ActionBase):
    name = "Transmit IR"

    def __call__(self, code, waitUntilFinished=True):
        finishEvent = Event()
        try:
            self.plugin.sendQueue.put((code, finishEvent), False)
        except Full:
            self.PrintError("Too many transmissions pending")
            return
        if waitUntilFinished:
            finishEvent.wait(10.0)

    def GetLabel(self, *dummyArgs):
        return self.name

    def Configure(self, code="", waitUntilFinished=True):
        panel = eg.ConfigPanel()
        code1 = ""
        code2 = ""
        repeatCount = 4
        carrier = 0
        if code:
            code += (48 * "\x00")
            if code[0] == "\x36":
                length = ord(code[1])
                code1 = "R" + hexlify(code[2:length]).upper()
                repeatCount = ord(code[length]) & 0x1F
                carrier = ord(code[length]) >> 6
            else:
                repeatCount = ord(code[0]) & 0x1F
                if repeatCount > 0:
                    carrier = ord(code[0]) >> 6
                    code1 = hexlify(code[1:26]).upper()
                else:
                    repeatCount = ord(code[26]) & 0x1F
                    carrier = ord(code[0]) >> 6
                    code1 = hexlify(code[1:26]).upper()
                    code2 = hexlify(code[27:48]).upper()
        if carrier < 0:
            carrier = 0
        elif carrier > 3:
            carrier = 3
        if repeatCount < 1:
            repeatCount = 1
        elif repeatCount > 31:
            repeatCount = 31
        sizer = wx.FlexGridSizer(4, 2, 5, 5)
        sizer.AddGrowableCol(1)

        sizer.Add(panel.StaticText("Code 1:"), 0, wx.ALIGN_CENTER_VERTICAL)
        code1Ctrl = panel.TextCtrl(
            code1,
            size=(325, -1),
            validator=HexValidator(allowRaw=True),
        )
        sizer.Add(code1Ctrl)

        sizer.Add(panel.StaticText("Code 2:"), 0, wx.ALIGN_CENTER_VERTICAL)
        code2Ctrl = panel.TextCtrl(
            code2,
            size=(275, -1),
            validator=HexValidator()
        )
        sizer.Add(code2Ctrl)

        sizer.Add(panel.StaticText("Repeat:"), 0, wx.ALIGN_CENTER_VERTICAL)
        repeatCtrl = eg.SpinIntCtrl(panel, -1, repeatCount, 1, 31)
        repeatCtrl.SetInitialSize((50, -1))
        sizer.Add(repeatCtrl, 0)

        sizer.Add(panel.StaticText("Carrier:"), 0, wx.ALIGN_CENTER_VERTICAL)
        choices = ('35.7 kHz', '37.0 kHz', '38.4 kHz', '40.0 kHz')
        carrierCtrl = wx.Choice(panel, -1, choices=choices)
        carrierCtrl.SetSelection(3 - carrier)
        sizer.Add(carrierCtrl, 0)

        panel.sizer.Add(sizer, 0, wx.EXPAND)

        panel.sizer.Add((5, 5))
        waitUntilFinishedCtrl = panel.CheckBox(
            waitUntilFinished,
            "Pause till transmission is finished"
        )
        panel.sizer.Add(waitUntilFinishedCtrl)

        while panel.Affirmed():
            code1 = code1Ctrl.GetValue()
            if len(code1) == 0:
                panel.SetResult("", waitUntilFinishedCtrl.GetValue())
                continue
            code2 = code2Ctrl.GetValue()
            repeatCount = repeatCtrl.GetValue()
            carrier = 3 - carrierCtrl.GetSelection()
            if code1[0] == "R":
                data = unhexlify(code1[1:])
                bCmd = repeatCount | (carrier << 6)
                code = "\x36" + chr(len(data) + 2) + data + chr(bCmd)
            elif len(code2) == 0:
                data = unhexlify(code1)
                bCmd = repeatCount | (carrier << 6)
                code = chr(bCmd) + data
            else:
                bCmd = 0 | (carrier << 6)
                bCmd2 = repeatCount | (carrier << 6)
                code = chr(bCmd) + unhexlify(code1) \
                       + chr(bCmd2) + unhexlify(code2)
            panel.SetResult(
                code + CalcChecksum(code),
                waitUntilFinishedCtrl.GetValue()
            )


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

from common import *
import can
from canopen.nmt import NmtError
import pytest
import struct
import time
from Crypto.Hash import SHA224

# Установлено, что на собаке скорости 10000 буфер передатчика собаки не более 182 байт

def align(v, alignnment):
    if v & (alignnment - 1) == 0:
        return v
    return (v & ~(alignnment - 1)) + alignnment

def l2b(l):
    return b''.join(map(lambda v: v.to_bytes(4, 'little'), l))

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

class TestSDOFirmwareRelated(object):
    @staticmethod
    def getkey(header):
        h = SHA224.new()
        h.update(header)
        digestsha224 = h.digest()
        key = [None] * 16
        for i in range(14):
            key[i] = digestsha224[i * 2]

        key[14] = digestsha224[len(digestsha224) - 3]
        key[15] = digestsha224[len(digestsha224) - 1]
        return ''.join(key)

    @classmethod
    def setup_class(cls):
        try:
            with open('app.bin', 'rb') as f:
                cls.raw_firmware = f.read()
        except:
            cls.raw_firmware = None

        try:
            with open('app.deploy', 'rb') as f:
                cls.encrypted_firmware = f.read()
        except:
            cls.encrypted_firmware = None

        test_speed = 125000
        cls.node_id = 16

        set_interface_bitrate(default_bitrate)
        cls.network = create_network()
        reset_network(cls.network)

        # lss prepare node
        lss_waiting_state(cls.network)
        lss_configure_bit_timing(cls.network, test_speed)
        lss_set_node_id(cls.network, cls.node_id)
        cls.network.nmt.state = 'RESET COMMUNICATION'

        cls.network.disconnect()
        set_interface_bitrate(test_speed)
        cls.network = create_network()

        cls.node = canopen.RemoteNode(cls.node_id, 'Bootloader.eds')
        cls.node.associate_network(cls.network)
        try:
            cls.node.nmt.wait_for_bootup(0.5)
        except NmtError:
            pass

    @classmethod
    def teardown_class(cls):
        # lss prepare node
        reset_network(cls.network)
        cls.network.disconnect()
        set_interface_bitrate(default_bitrate)

    # Попытка чтения текущегго приложения должна завершиться ошибкой - доступ - только запись
    def test_read_firmware(self):
        with pytest.raises(canopen.sdo.exceptions.SdoAbortedError) as e_info:
            len(self.node.sdo[0x1f50][1].raw)

        assert str(e_info.value) == 'Code 0x06010001, Attempt to read a write only object'

    @pytest.mark.parametrize('method,result', [
        (0, True),
        (1, True),
        (2, False),
        (-1, False)
    ])
    def test_select_encryption_method(self, method, result):
        if result:
            self.node.sdo[0x1f55][1].raw = method
            assert self.node.sdo[0x1f55][1].raw == method
        else:
            with pytest.raises(Exception) as e_info:
                self.node.sdo[0x1f55][1].raw = method
            if method < 0:
                assert str(e_info.value) == 'Value does not fit in specified type'
            else:
                assert str(e_info.value) == 'Code 0x06090031, Value of parameter written too high'

    # Записываем в область приложения нули блочным способом или нет, если ошибка
    def test_restore_after_invalid_write(self):
        data = bytearray([x & 0xff for x in range(183)])
        try:
            with self.node.sdo[0x1f50][1].open('wb', size=len(data), block_transfer=True) as f:
                f.write(data)
        except can.CanError:
            f.close()
            time.sleep(1.5)
            with self.node.sdo[0x1f50][1].open('wb', size=len(data), block_transfer=False) as f:
                f.write(data)

    # проверяем что в области проверки статуса приложения 0x1f56sub1 0 - invalid application
    def test_invalid_app_crc(self):
        assert self.node.sdo[0x1f56][1].raw == 0

    # Пытаемся запустить неверное приложение, в логе ошибок должен появится код APPLICATION_INCORRECT_OR_NOT_EXISTS
    def test_try_start_invalid_app(self):
        self.node.sdo[0x1F51][1].raw = 1
        error = Error_CODE(self.node.sdo[0x1003][1].raw)
        assert error.code == Error_CODES.APPLICATION_INCORRECT_OR_NOT_EXISTS

    # Сброс лога ошибок
    def test_reset_errors(self):
        self.node.sdo[0x1003][0].raw = 0
        assert self.node.sdo[0x1003][0].raw == 0
        with pytest.raises(canopen.sdo.exceptions.SdoAbortedError) as e_info:
            self.node.sdo[0x1003][1].raw is not None
        assert str(e_info.value) == 'Code 0x08000023, Object dictionary dynamic generation fails or no object ' \
                                    'dictionary is present'

    # Записываем корректный образ приложения
    def common_write_correct_app(self, fm, method):
        if not fm:
            return

        self.node.sdo[0x1f55][1].raw = method

        with self.node.sdo[0x1f50][1].open('wb', size=len(fm), block_transfer=False) as f:
            f.write(fm)
        if Error_CODE(self.node.sdo[0x1003][1].raw).code != Error_CODES.APPLICATION_READY_TO_START:
            raise RuntimeError('Write failed')

    def test_write_correct_raw_app(self):
        self.common_write_correct_app(self.raw_firmware, 0)

    def test_write_correct_encrypted_app(self):
        self.common_write_correct_app(self.encrypted_firmware, 1)

    def get_crc(self):
        fm = self.raw_firmware if self.raw_firmware else self.encrypted_firmware
        return struct.unpack('<I', fm[6 * 4:7 * 4])[0]

    # Сравниваем указанный в образе CRC32 образа приложения с тем, что вернет нам бутлоадер насчитавций фактическое
    # значение
    def test_correct_app_crc(self):
        r_crc = self.node.sdo[0x1f56][1].raw
        assert self.get_crc() == r_crc

    def test_write_incorrect_method(self):
        if self.raw_firmware and self.encrypted_firmware:
            with pytest.raises(RuntimeError) as e_info:
                self.common_write_correct_app(self.encrypted_firmware, 0)
            assert str(e_info.value) == 'Write failed'


import time

import numpy as np
import torch
from torchvision.transforms import functional as tvtf
import imageio
import PIL

from COTR.inference.inference_helper import BASE_ZOOM, THRESHOLD_PIXELS_RELATIVE, get_patch_centered_at, two_images_side_by_side, find_prediction_loop
from COTR.utils import debug_utils, utils
from COTR.utils.constants import MAX_SIZE
from COTR.utils.utils import ImagePatch

class RefinementTask():
    def __init__(self, image_from, image_to, loc_from, loc_to, area_from, area_to, converge_iters, zoom_ins, identifier=None):
        self.identifier = identifier
        self.image_from = image_from
        self.image_to = image_to
        self.loc_from = loc_from
        self.best_loc_to = loc_to
        self.cur_loc_to = loc_to
        self.area_from = area_from
        self.area_to = area_to
        if self.area_from < self.area_to:
            self.s_from = BASE_ZOOM
            self.s_to = BASE_ZOOM * np.sqrt(self.area_to / self.area_from)
        else:
            self.s_to = BASE_ZOOM
            self.s_from = BASE_ZOOM * np.sqrt(self.area_from / self.area_to)

        self.cur_job = {}
        self.status = 'unfinished'
        self.result = 'unknown'

        self.converge_iters = converge_iters
        self.zoom_ins = zoom_ins
        self.cur_zoom_idx = 0
        self.cur_iter = 0
        self.total_iter = 0

        self.loc_to_at_zoom = []
        self.loc_history = [loc_to]
        self.all_loc_to_dict = {}
        self.job_history = []
        self.submitted = False

    @property
    def cur_zoom(self):
        return self.zoom_ins[self.cur_zoom_idx]

    @property
    def confidence_scaling_factor(self):
        if self.cur_zoom_idx > 0:
            conf_scaling = float(self.cur_zoom) / float(self.zoom_ins[0])
        else:
            conf_scaling = 1.0
        return conf_scaling

    def peek(self):
        assert self.status == 'unfinished'
        patch_from = get_patch_centered_at(None, self.loc_from, scale=self.s_from * self.cur_zoom, return_content=False, img_shape=self.image_from.shape)
        patch_to = get_patch_centered_at(None, self.cur_loc_to, scale=self.s_to * self.cur_zoom, return_content=False, img_shape=self.image_to.shape)
        top_job = {'patch_from': patch_from,
                    'patch_to': patch_to,
                    'loc_from': self.loc_from,
                    'loc_to': self.cur_loc_to,
                    }
        return top_job

    def get_task_pilot(self, pilot):
        assert self.status == 'unfinished'
        patch_from = ImagePatch(None, pilot.cur_job['patch_from'].x, pilot.cur_job['patch_from'].y, pilot.cur_job['patch_from'].w, pilot.cur_job['patch_from'].h, pilot.cur_job['patch_from'].ow, pilot.cur_job['patch_from'].oh)
        patch_to   = ImagePatch(None, pilot.cur_job['patch_to'].x, pilot.cur_job['patch_to'].y, pilot.cur_job['patch_to'].w, pilot.cur_job['patch_to'].h, pilot.cur_job['patch_to'].ow, pilot.cur_job['patch_to'].oh)
        query = torch.from_numpy((np.array(self.loc_from) - np.array([patch_from.x, patch_from.y])) / np.array([patch_from.w * 2, patch_from.h]))[None].float()
        self.cur_job = {'patch_from': patch_from,
                        'patch_to': patch_to,
                        'loc_from': self.loc_from,
                        'loc_to': self.cur_loc_to,
                        'img': None,
                        }
        self.job_history.append((patch_from.h, patch_from.w, patch_to.h, patch_to.w))
        assert self.submitted == False
        self.submitted = True
        return None, query

    def get_task_fast(self):
        assert self.status == 'unfinished'
        patch_from = get_patch_centered_at(self.image_from, self.loc_from, scale=self.s_from * self.cur_zoom, return_content=False)
        patch_to = get_patch_centered_at(self.image_to, self.cur_loc_to, scale=self.s_to * self.cur_zoom, return_content=False)
        query = torch.from_numpy((np.array(self.loc_from) - np.array([patch_from.x, patch_from.y])) / np.array([patch_from.w * 2, patch_from.h]))[None].float()
        self.cur_job = {'patch_from': patch_from,
                        'patch_to': patch_to,
                        'loc_from': self.loc_from,
                        'loc_to': self.cur_loc_to,
                        'img': None,
                        }

        self.job_history.append((patch_from.h, patch_from.w, patch_to.h, patch_to.w))
        assert self.submitted == False
        self.submitted = True

        return None, query

    def get_task(self):
        assert self.status == 'unfinished'
        patch_from = get_patch_centered_at(self.image_from, self.loc_from, scale=self.s_from * self.cur_zoom)
        patch_to = get_patch_centered_at(self.image_to, self.cur_loc_to, scale=self.s_to * self.cur_zoom)

        query = torch.from_numpy((np.array(self.loc_from) - np.array([patch_from.x, patch_from.y])) / np.array([patch_from.w * 2, patch_from.h]))[None].float()

        img_from = patch_from.patch
        img_to = patch_to.patch
        assert img_from.shape[0] == img_from.shape[1]
        assert img_to.shape[0] == img_to.shape[1]

        img_from = np.array(PIL.Image.fromarray(img_from).resize((MAX_SIZE, MAX_SIZE), resample=PIL.Image.BILINEAR))
        img_to = np.array(PIL.Image.fromarray(img_to).resize((MAX_SIZE, MAX_SIZE), resample=PIL.Image.BILINEAR))
        img = two_images_side_by_side(img_from, img_to)
        img = tvtf.normalize(tvtf.to_tensor(img), (0.485, 0.456, 0.406), (0.229, 0.224, 0.225)).float()

        self.cur_job = {'patch_from': ImagePatch(None, patch_from.x, patch_from.y, patch_from.w, patch_from.h, patch_from.ow, patch_from.oh),
                        'patch_to': ImagePatch(None, patch_to.x, patch_to.y, patch_to.w, patch_to.h, patch_to.ow, patch_to.oh),
                        'loc_from': self.loc_from,
                        'loc_to': self.cur_loc_to,
                        }

        self.job_history.append((patch_from.h, patch_from.w, patch_to.h, patch_to.w))
        assert self.submitted == False
        self.submitted = True

        return img, query

    def next_zoom(self):
        if self.cur_zoom_idx >= len(self.zoom_ins) - 1:
            self.status = 'finished'
            if self.conclude() is None:
                self.result = 'bad'
            else:
                self.result = 'good'
        self.cur_zoom_idx += 1
        self.cur_iter = 0
        self.loc_to_at_zoom = []

    def scale_to_loc(self, raw_to_loc):
        raw_to_loc = raw_to_loc.copy()
        patch_b = self.cur_job['patch_to']
        raw_to_loc[0] = (raw_to_loc[0] - 0.5) * 2
        loc_to = raw_to_loc * np.array([patch_b.w, patch_b.h])
        loc_to = loc_to + np.array([patch_b.x, patch_b.y])
        return loc_to

    def step(self, raw_to_loc):
        assert self.submitted == True
        self.submitted = False
        loc_to = self.scale_to_loc(raw_to_loc)
        self.total_iter += 1
        self.loc_to_at_zoom.append(loc_to)
        self.cur_loc_to = loc_to
        zoom_finished = False
        if self.cur_zoom_idx == len(self.zoom_ins) - 1:
            # converge at the last level
            if len(self.loc_to_at_zoom) >= 2:
                zoom_finished = np.prod(self.loc_to_at_zoom[:-1] == loc_to, axis=1, keepdims=True).any()
            if self.cur_iter >= self.converge_iters - 1:
                zoom_finished = True
            self.cur_iter += 1
        else:
            # finish immediately for other levels
            zoom_finished = True
        if zoom_finished:
            self.all_loc_to_dict[self.cur_zoom] = np.array(self.loc_to_at_zoom).copy()
            last_level_loc_to = self.all_loc_to_dict[self.cur_zoom]
            if len(last_level_loc_to) >= 2:
                has_loop = np.prod(last_level_loc_to[:-1] == last_level_loc_to[-1], axis=1, keepdims=True).any()
                if has_loop:
                    loop = find_prediction_loop(last_level_loc_to)
                    loc_to = loop.mean(axis=0)
            self.loc_history.append(loc_to)
            self.best_loc_to = loc_to
            self.cur_loc_to = self.best_loc_to
            self.next_zoom()

    def conclude(self, force=False):
        loc_history = np.array(self.loc_history)
        if (force == False) and (max(loc_history.std(axis=0)) >= THRESHOLD_PIXELS_RELATIVE * max(*self.image_to.shape)):
            return None
        return np.concatenate([self.loc_from, self.best_loc_to])

    def conclude_intermedia(self):
        return np.concatenate([np.array(self.loc_history), np.array(self.job_history)], axis=1)


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import collections
import numpy as np
import os
import shutil
import subprocess
import tempfile
import time
from fractions import gcd
from PIL import Image

import logging
logger = logging.getLogger(__name__)

from seqtrack import assess
from seqtrack import data
from seqtrack import geom_np
from seqtrack import helpers
from seqtrack import visualize as vis

FRAME_PATTERN = '%06d.jpeg'

def track(sess, tracker, sequence,
          verbose=False,
          # Visualization options:
          visualize=False,
          vis_dir=None,
          keep_frames=False):
    '''Run an instantiated tracker on a sequence.'''
    assert 0 in sequence.valid_set

    if visualize:
        assert bool(vis_dir)
        assert bool(sequence.name)
        filename = helpers.escape_filename(sequence.name)
        helpers.mkdir_p(vis_dir, 0o755)
        # if not keep_frames:
        #     frame_dir = tempfile.mkdtemp()
        #     logger.debug('write frames to tmp dir: %s', frame_dir)
        # else:
        #     frame_dir = os.path.join(vis_dir, filename)
        #     helpers.mkdir_p(frame_dir)
        frame_dir = os.path.join(vis_dir, filename)
        helpers.mkdir_p(frame_dir)
        _visualize_frame(os.path.join(frame_dir, FRAME_PATTERN % 0),
                         sequence.image_files[0],
                         rect_gt=sequence.rects[0])

    tracker.start(sess, {
        'image': {'file': [sequence.image_files[0]]},
        'rect': [sequence.rects[0]],
        'aspect': [sequence.aspect],
    })

    start = time.time()
    # Durations do not include initial frame.
    duration_with_load = 0

    sequence_len = len(sequence)
    assert(sequence_len >= 2)
    predictions = []
    for t in range(1, sequence_len):
        start_curr = time.time()
        # TODO: Load image separately.
        curr = tracker.next(sess, {
            'image': {'file': [sequence.image_files[t]]},
        })
        duration_with_load += time.time() - start_curr
        # Unpack from batch.
        predictions.append(curr['rect'][0])
        if visualize:
            _visualize_frame(os.path.join(frame_dir, FRAME_PATTERN % t),
                             sequence.image_files[t],
                             rect_gt=(sequence.rects[t] if t in sequence.valid_set else None),
                             rect_pred=predictions[t - 1])

    duration_real = time.time() - start

    if visualize:
        args = [
            'ffmpeg',
            '-loglevel', 'error',
            '-y',  # Overwrite without asking.
            '-nostdin',  # No interaction with user.
            '-i', FRAME_PATTERN,
            '-vf', 'scale=trunc(iw/2)*2:trunc(ih/2)*2',
            os.path.join(os.path.abspath(vis_dir), filename + '.mp4'),  # Output file.
        ]
        try:
            p = subprocess.Popen(args, cwd=frame_dir)
            p.wait()
        except Exception as ex:
            logger.warning('error when calling ffmpeg: %s', str(ex))
        else:
            # If there is no exception, consider removing the frames.
            if not keep_frames:
                shutil.rmtree(frame_dir)

    predictions = np.array(predictions)
    timing = {
        'speed_with_load': (sequence_len - 1) / duration_with_load,
        'speed_real': sequence_len / duration_real,
    }
    return predictions, timing

def track_and_assess(sess, model_inst, sequences, tre_num=1, **kwargs):
    '''
    Args:
        kwargs: For track().

    Returns:
        A dictionary that contains evaluation results.
    '''
    subseqs, tre_groups = _split_tre_all(sequences, tre_num)
    predictions = {}
    timing = {}
    bar = helpers.ProgressMeter(interval_time=1)
    for name in bar(subseqs.keys()):
        # TODO: Cache.
        # If we use a subset of sequences, we need to ensure that the subset is the same?
        # Could re-seed video sampler with global step number?
        predictions[name], timing[name] = track(
            sess, model_inst, subseqs[name], **kwargs)
    return assess.assess_dataset(subseqs, predictions, tre_groups, timing=timing)

def _split_tre_all(sequences, tre_num):
    sequences = list(sequences)

    subseqs = {}
    for sequence in sequences:
        for tre_ind in range(tre_num):
            # subseq_name = subseq['video_name']
            subseq_name = _tre_seq_name(sequence.name, tre_ind, tre_num)
            if subseq_name in subseqs:
                raise RuntimeError('name already exists: \'{}\''.format(subseq_name))
            try:
                subseq = _extract_tre_sequence(sequence, tre_ind, tre_num, subseq_name)
            except RuntimeError as ex:
                logger.warning('sequence \'%s\': could not extract TRE sequence %d of %d: %s',
                               sequence.name, tre_ind, tre_num, str(ex))
                # Still insert None if sequence could not be extracted.
                subseq = None
            subseqs[subseq_name] = subseq

    # Build sequence groups for OPE and TRE mode.
    # TODO: Could add all integer factors here?
    tre_group_nums = set([1, tre_num])  # If tre_num is 1, then only OPE.
    tre_groups = {}
    for tre_group_num in tre_group_nums:
        mode = _mode_name(tre_group_num)
        tre_groups[mode] = {}
        for sequence in sequences:
            seq_name = sequence.name
            tre_groups[mode][seq_name] = []
            for tre_ind in range(tre_group_num):
                subseq_name = _tre_seq_name(seq_name, tre_ind, tre_group_num)
                if subseqs[subseq_name] is not None:
                    tre_groups[mode][seq_name].append(subseq_name)
    return subseqs, tre_groups

def _mode_name(tre_num):
    if tre_num == 1:
        return 'OPE'
    elif tre_num > 1:
        return 'TRE_{}'.format(tre_num)
    else:
        raise RuntimeError('tre_num must be at least one: {}'.format(tre_num))

def _tre_seq_name(seq_name, i, n):
    if i == 0:
        return seq_name
    i, n = _simplify_fraction(i, n)
    return '{}_tre_{}_{}'.format(seq_name, i, n)

def _simplify_fraction(i, n):
    if i == 0:
        assert n != 0
        return 0, 1
    g = gcd(i, n)
    return i // g, n // g

def _extract_tre_sequence(seq, ind, num, subseq_name):
    if ind == 0:
        return seq

    is_valid = seq['label_is_valid']
    num_frames = len(is_valid)
    valid_frames = [t for t in range(num_frames) if is_valid[t]]
    min_t, max_t = valid_frames[0], valid_frames[-1]

    start_t = int(round(float(ind) / num * (max_t - min_t))) + min_t
    # Snap to next valid frame (raises StopIteration if none).
    try:
        start_t = next(t for t in valid_frames if t >= start_t)
    except StopIteration:
        raise RuntimeError('no frames with labels')

    subseq = _extract_interval(seq, start_t, None)
    # subseq['video_name'] = seq['video_name'] + ('-seg{}'.format(ind) if ind > 0 else '')
    subseq['video_name'] = subseq_name

    # if len(subseq['image_files']) < 2:
    #     raise RuntimeError('sequence shorter than two frames')
    # Count number of valid labels after first frame (ground truth).
    num_valid = sum(1 for x in subseq['label_is_valid'][1:] if x)
    if num_valid < 1:
        raise RuntimeError('no frames with labels after first frame')
    return subseq

def _extract_interval(seq, start, stop):
    KEYS_SEQ = ['image_files', 'labels', 'label_is_valid']
    KEYS_NON_SEQ = ['aspect']
    subseq = {}
    subseq.update({k: seq[k][start:stop] for k in KEYS_SEQ})
    subseq.update({k: seq[k] for k in KEYS_NON_SEQ})
    return subseq

def _visualize_frame(dst_file, src_file, **kwargs):
    im = Image.open(src_file)
    if im.mode != 'RGB':
        im = im.convert('RGB')
    im = vis.draw_output(im, **kwargs)
    im.save(dst_file)


from django.contrib import admin
from django.urls import path, re_path
from .views import home, plans, movil, team, features, faq, sendEmail, influencer,  succed, error, ofertas

urlpatterns = [
    path('', home, name="home"),
    path('team/', team, name="team" ),
    path('features/', features, name="features" ),
    path('sendEmail/', sendEmail, name='sendEmail'),
    path('influencers/', influencer, name='influencer'),
    path('succeed/', succed, name='succeed' ),
    path('error/', error, name='error' ),
    path('founders/', ofertas, name='ofertas' ),
    path('app/', movil, name='app' ),
    #path('faq/', faq, name="faq" )

]
"""     path('planes/', plans, name="plans"),
    path('planes/<str:plan>/', plans, name="anual_plans"), """


from urllib.request import urlopen
from bs4 import BeautifulSoup as bs4
'''lnk="https://www.nature.com/articles/s41598-023-28880-x"
url=urlopen(lnk)
soup = bs4(url, 'lxml')
l=[]
str1=''
all_links = soup.findAll("div",attrs={"class":"c-article-section__content","id":"Bib1-content"})
for link in all_links:
    l.append(link)
for i in l:
    str1+=str(i)
with open ("rra_csv.csv","w",encoding="utf-8") as file:
    file.write(str1)'''
str2=''
lnk="rra_csv.csv"
url=open(lnk)
soup= bs4(url,'lxml')
l2=[]
for i in soup.findAll('a'):
    l2.append(i.get("href"))
for i in l2:
    str2+="\n"
    str2+=str(i)
with open ("references.csv","w") as f1:
    f1.write(str2)
f1.close()


from collections import Counter
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: int
        """
        counter = Counter(s)
        odd = 0
        ans = 0
        for char, cnt in counter.iteritems():
            if cnt % 2 == 0:
                ans += cnt
            else:
                odd = 1
                ans += cnt - 1
        return ans + odd


#!/usr/bin/python
#coding=utf8
"""
# Author: shikanon
# Created Time : 2019-06-11 15:53:11

# File Name: features.py
# Description:

"""
import numpy as np
import pandas as pd

class Estimator:
    def __init__(self,name,**kwargs):
        param = "".join("%s:%s/"%(k,kwargs[k]) for k in kwargs)
        self.name = name + "/" + param
        self.baseline_rewards = []
        self.rewards = []
        self.win_probs = []
        self.loss = []

    def to_df(self):
        data = dict()
        data["baseline_rewards"] = self.baseline_rewards
        data["rewards"] = self.rewards
        data["win_probs"] = self.win_probs
        data["loss"] = self.loss
        return pd.DataFrame(data)

    def estimate(self, env):
        # 基准收益
        self.baseline_rewards.append(np.mean(env.history["full_warehouse_income"]))
        # 策略收益
        self.rewards.append(np.mean(env.history["total_reward"])-env.init_money)
        # 胜率
        win_rate = 100*len([r for r in env.history["episode_reward"] if r>0])/len(env.history["episode_reward"])
        self.win_probs.append(win_rate)
        # 最佳收益的误差
        self.loss.append(np.mean(env.history["loss"]))

    def plot(self):
        from IPython import display
        import matplotlib.pyplot as plt
        display.clear_output(wait=True)
        display.display(plt.gcf())
        plt.figure(figsize=(20,10))
        plt.clf()

        plt.title('Estimator %s'%self.name)
        plt.xlabel('Episode')
        plt.ylabel('Duration')

        plt.plot(self.loss)
        plt.text(len(self.loss)-1, self.loss[-1], str(self.loss[-1]))

        # if len(self.rewards) > 0:
        #     plt.plot(self.rewards)
        #     plt.text(len(self.rewards)-1, self.rewards[-1], str(self.rewards[-1]))
        # if len(self.baseline_rewards) > 0:
        #     plt.plot(self.baseline_rewards)
        #     plt.text(len(self.baseline_rewards)-1, self.baseline_rewards[-1], str(self.baseline_rewards[-1]))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# pylint: disable=invalid-name
# pylint: disable=line-too-long
# pylint: disable=multiple-statements
# pylint: disable=too-many-lines
# pylint: disable=wrong-import-position

#-------------------------------------------------------------------------------

'''
This program launches several PHASE processes with a input file list.

This software has been developed by:

    Dpto. Sistemas y Recursos Naturales
    ETSI Montes, Forestal y del Medio Natural
    Universidad Politecnica de Madrid
    https://github.com/ggfhf/

Licence: GNU General Public Licence Version 3.
'''

#-------------------------------------------------------------------------------

import argparse
import pathlib
import os
import sys

import xlib

#-------------------------------------------------------------------------------

def main():
    '''
    Main line of the program.
    '''

    # check the operating system
    xlib.check_os()

    # check the WSL installation
    if sys.platform.startswith('win32'):
        command = 'whoami'
        rc = xlib.run_command(command, xlib.DevNull(), is_script=False)
        if rc == 0:
            pass
        else:
            print('*** ERROR: The WSL 2 is not installed.')
            sys.exit(1)

    # get and check the arguments
    parser = build_parser()
    args = parser.parse_args()
    check_args(args)

    # launch PHASE processes with a input file list
    launch_phase_processes(args.phase_dir, args.processes_number, args.input_dir, args.output_dir, args.iterations_number, args.thinning_interval, args.burn_in, args.other_parameters)

#-------------------------------------------------------------------------------

def build_parser():
    '''
    Build the parser with the available arguments.
    '''

    # create the parser and add arguments
    description = 'Description: This program launches several PHASE processes with a input file list.'
    text = f'{xlib.get_project_name()} v{xlib.get_project_version()} - {os.path.basename(__file__)}\n\n{description}\n'
    usage = f'\r{text.ljust(len("usage:"))}\nUsage: {os.path.basename(__file__)} arguments'
    parser = argparse.ArgumentParser(usage=usage)
    parser._optionals.title = 'Arguments'
    parser.add_argument('--phasedir', dest='phase_dir', help='Path of the directoty of the PHASE application installation (mandatory).')
    parser.add_argument('--processes', dest='processes_number', help=f'Number of process to be launched; default: {xlib.Const.DEFAULT_PROCESSES_NUMBER}.')
    parser.add_argument('--indir', dest='input_dir', help='Path of the directoty where the PHASE application input files are located (mandatory).')
    parser.add_argument('--outdir', dest='output_dir', help='Path of the directoty where the PHASE application output files are generated (mandatory).')
    parser.add_argument('--iterations', dest='iterations_number', help=f'Number of iterations; default: {xlib.Const.DEFAULT_ITERATIONS_NUMBER}.')
    parser.add_argument('--thinning', dest='thinning_interval', help=f'Thinning interval; default: {xlib.Const.DEFAULT_THINNING_INTERVAL}.')
    parser.add_argument('--burnin', dest='burn_in', help=f'Burn-in; default: {xlib.Const.DEFAULT_BURN_IN}.')
    parser.add_argument('--otherparams', dest='other_parameters', help='Other parameters (between quotation marks) to be included in the PHASE run or NONE; default: NONE.')
    parser.add_argument('--verbose', dest='verbose', help=f'Additional job status info during the run: {xlib.get_verbose_code_list_text()}; default: {xlib.Const.DEFAULT_VERBOSE}.')
    parser.add_argument('--trace', dest='trace', help=f'Additional info useful to the developer team: {xlib.get_trace_code_list_text()}; default: {xlib.Const.DEFAULT_TRACE}.')

    # return the paser
    return parser

#-------------------------------------------------------------------------------

def check_args(args):
    '''
    Check the input arguments.
    '''

    # initialize the control variable
    OK = True

    # check "phase_dir"
    if args.phase_dir is None:
        xlib.Message.print('error', '*** The directoty of the PHASE application installation is not indicated in the input arguments.')
        OK = False
    elif not os.path.isdir(args.phase_dir):
        xlib.Message.print('error', f'*** The directory {args.phase_dir} does not exist.')
        OK = False

    # check "processes_number"
    if args.processes_number is None:
        args.processes_number = xlib.Const.DEFAULT_PROCESSES_NUMBER
    elif not xlib.check_int(args.processes_number, minimum=1):
        xlib.Message.print('error', 'The processes number has to be a integer number greater than or equal to 1.')
        OK = False
    else:
        args.processes_number = int(args.processes_number)

    # check "input_dir"
    if args.input_dir is None:
        xlib.Message.print('error', '*** The directoty where the PHASE application input files are located is not indicated in the input arguments.')
        OK = False
    elif not os.path.isdir(args.input_dir):
        xlib.Message.print('error', f'*** The directory {args.input_dir} does not exist.')
        OK = False

    # check "output_dir"
    if args.output_dir is None:
        xlib.Message.print('error', '*** The directoty where the PHASE application output files are generated is not indicated in the input arguments.')
        OK = False
    elif not os.path.isdir(args.output_dir):
        xlib.Message.print('error', f'*** The directory {args.output_dir} does not exist.')
        OK = False

    # check "iterations_number"
    if args.iterations_number is None:
        args.iterations_number = xlib.Const.DEFAULT_ITERATIONS_NUMBER
    elif not xlib.check_int(args.iterations_number, minimum=1):
        xlib.Message.print('error', 'The processes number has to be a integer number greater than or equal to 1.')
        OK = False
    else:
        args.iterations_number = int(args.iterations_number)

    # check "thinning_interval"
    if args.thinning_interval is None:
        args.thinning_interval = xlib.Const.DEFAULT_THINNING_INTERVAL
    elif not xlib.check_int(args.thinning_interval, minimum=1):
        xlib.Message.print('error', 'The processes number has to be a integer number greater than or equal to 1.')
        OK = False
    else:
        args.thinning_interval = int(args.thinning_interval)

    # check "burn_in"
    if args.burn_in is None:
        args.burn_in = xlib.Const.DEFAULT_BURN_IN
    elif not xlib.check_int(args.burn_in, minimum=1):
        xlib.Message.print('error', 'The processes number has to be a integer number greater than or equal to 1.')
        OK = False
    else:
        args.burn_in = int(args.burn_in)

    # check "other_parameters"
    if args.other_parameters is None or args.other_parameters.upper() == 'NONE':
        args.other_parameters = 'NONE'

    # check "verbose"
    if args.verbose is None:
        args.verbose = xlib.Const.DEFAULT_VERBOSE
    elif not xlib.check_code(args.verbose, xlib.get_verbose_code_list(), case_sensitive=False):
        xlib.Message.print('error', f'*** verbose has to be {xlib.get_verbose_code_list_text()}.')
        OK = False
    if args.verbose.upper() == 'Y':
        xlib.Message.set_verbose_status(True)

    # check "trace"
    if args.trace is None:
        args.trace = xlib.Const.DEFAULT_TRACE
    elif not xlib.check_code(args.trace, xlib.get_trace_code_list(), case_sensitive=False):
        xlib.Message.print('error', f'*** trace has to be {xlib.get_trace_code_list_text()}.')
        OK = False
    if args.trace.upper() == 'Y':
        xlib.Message.set_trace_status(True)

    # if there are errors, exit with exception
    if not OK:
        raise xlib.ProgramException('', 'P001')

#-------------------------------------------------------------------------------

def launch_phase_processes(phase_dir, processes_number, input_dir, output_dir, iterations_number,thinning_interval, burn_in, other_parameters):
    '''
    x
    '''

    # initialize the counter of rename files
    input_file_counter = 0

    # build the input file list
    input_file_list = []
    for path in pathlib.Path(input_dir).iterdir():
        if path.is_file():

            # add 1 to the counter of rename files
            input_file_counter += 1

            # add file name to the input file list
            input_file_list.append(os.path.basename(path))

            # print the counter of renamed files
            xlib.Message.print('verbose', f'\rInput files: {input_file_counter}')
    xlib.Message.print('verbose', '\n')

    # set the files number list
    files_number_list = []
    file_number = input_file_counter // processes_number
    remainder = input_file_counter % processes_number
    for i in range(processes_number):
        if i < remainder:
            files_number_list.append(file_number + 1)
        else:
            files_number_list.append(file_number)
    xlib.Message.print('info', f'files_number_list: {files_number_list}')

    # build the path file with input files of each process
    input_files_list_file_list = []
    witherror_file_list = []
    for process_number in range(processes_number):
        input_files_list_file_list.append(f'{output_dir}{os.sep}phase-process-{process_number}-file-list.txt')
        witherror_file_list.append(f'{output_dir}{os.sep}phase-process-{process_number}-unprocessed-files.txt')

    # write input files corrrespondig to each process
    start = 0
    for process_number in range(processes_number):
        try:
            input_files_list_file_id = open(input_files_list_file_list[process_number], mode='w', encoding='iso-8859-1', newline='\n')
        except Exception as e:
            raise xlib.ProgramException(e, 'F003', input_files_list_file_list[process_number])
        end = start + files_number_list[process_number]
        for i in range(start, end):
            input_files_list_file_id.write(f'{input_file_list[i]}\n')
        input_files_list_file_id.close()
        start = end

    # create scripts of PHASE processes
    xlib.Message.print('info', f'{xlib.get_separator()}\n')
    for process_number in range(processes_number):
        xlib.Message.print('info', f'Creating the process script {get_phase_process_script(process_number, output_dir)} ...\n')
        build_phase_process_script(process_number, phase_dir, input_dir, input_files_list_file_list[process_number], witherror_file_list[process_number], output_dir, iterations_number, thinning_interval, burn_in, other_parameters)
        xlib.Message.print('info', 'The script is created.\n')

    # set run permision to the scripts of PHASE processes
    xlib.Message.print('info', f'{xlib.get_separator()}\n')
    for process_number in range(processes_number):
        script = get_phase_process_script(process_number, output_dir)
        xlib.Message.print('info', f'Setting on the run permision of {script} ...\n')
        if sys.platform.startswith('win32'):
            script = xlib.windows_path_2_wsl_path(script)
        command = f'chmod u+x {script}'
        rc = xlib.run_command(command, sys.stdout, is_script=False)
        if rc == 0:
            xlib.Message.print('info', 'The run permision is set.\n')
        else:
            raise xlib.ProgramException('', 'S002', command, rc)

    # create starters of PHASE processes
    xlib.Message.print('info', f'{xlib.get_separator()}\n')
    for process_number in range(processes_number):
        xlib.Message.print('info', f'Creating the process starter {get_phase_process_starter(process_number, output_dir)} ...\n')
        build_phase_process_starter(process_number, output_dir)
        xlib.Message.print('info', 'The script is created.\n')

    # set run permision to the starters of PHASE processes
    xlib.Message.print('info', f'{xlib.get_separator()}\n')
    for process_number in range(processes_number):
        starter = get_phase_process_starter(process_number, output_dir)
        xlib.Message.print('info', f'Setting on the run permision of {starter} ...\n')
        if sys.platform.startswith('win32'):
            starter = xlib.windows_path_2_wsl_path(starter)
        command = f'chmod u+x {starter}'
        rc = xlib.run_command(command, sys.stdout, is_script=False)
        if rc == 0:
            xlib.Message.print('info', 'The run permision is set.\n')
        else:
            raise xlib.ProgramException('', 'S002', command, rc)

    # launch PHASE processes
    xlib.Message.print('info', f'{xlib.get_separator()}\n')
    for process_number in range(processes_number):
        starter = get_phase_process_starter(process_number, output_dir)
        xlib.Message.print('info', f'Launching the process {starter} ...\n')
        if sys.platform.startswith('win32'):
            starter = xlib.windows_path_2_wsl_path(starter)
        command = f'{starter} &'
        rc = xlib.run_command(command, sys.stdout, is_script=True)
        if rc == 0:
            xlib.Message.print('info', 'The script is submitted.\n')
        else:
            raise xlib.ProgramException('', 'S002', command, rc)

#-------------------------------------------------------------------------------

def build_phase_process_script(process_number, phase_dir, input_dir, input_files_list_file, witherror_file_list, output_dir, iterations_number, thinning_interval, burn_in, other_parameters):
    '''
    Build the PHASE process script corresponding to the process number
    '''

    # initialize the control variable and the error list
    OK = True
    error_list = []

    # write the PHASE process script
    try:
        if not os.path.exists(os.path.dirname(get_phase_process_script(process_number, output_dir))):
            os.makedirs(os.path.dirname(get_phase_process_script(process_number, output_dir)))
        with open(get_phase_process_script(process_number, output_dir), mode='w', encoding='iso-8859-1', newline='\n') as script_file_id:
            script_file_id.write( '#!/bin/bash\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'SEP="#########################################"\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write(f'export PATH={phase_dir}:$PATH\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'function init\n')
            script_file_id.write( '{\n')
            script_file_id.write( '    INIT_DATETIME=`date --utc +%s`\n')
            script_file_id.write( '    FORMATTED_INIT_DATETIME=`date --date="@$INIT_DATETIME" "+%Y-%m-%d %H:%M:%S"`\n')
            script_file_id.write( '    echo "$SEP"\n')
            script_file_id.write( '    echo "Script started at $FORMATTED_INIT_DATETIME+00:00."\n')
            script_file_id.write( '}\n')
            if sys.platform.startswith('win32'):
                input_dir = xlib.windows_path_2_wsl_path(input_dir)
                output_dir = xlib.windows_path_2_wsl_path(output_dir)
                input_files_list_file = xlib.windows_path_2_wsl_path(input_files_list_file)
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'function run_phase_process\n')
            script_file_id.write( '{\n')
            script_file_id.write(f'    cd {output_dir}\n')
            script_file_id.write(f'    rm -f {witherror_file_list}\n')
            script_file_id.write(f'    touch {witherror_file_list}\n')
            script_file_id.write( '    while read FILE_NAME; do\n')
            script_file_id.write( '        echo "$SEP"\n')
            script_file_id.write(f'        IN_FILE={input_dir}/$FILE_NAME\n')
            script_file_id.write(f'        OUT_FILE={output_dir}/$FILE_NAME\n')
            script_file_id.write( '        echo "Processing file $IN_FILE ..."\n')
            script_file_id.write( '        BASENAME=`basename $IN_FILE`\n')
            script_file_id.write( '        /usr/bin/time \\\n')
            script_file_id.write(f'            PHASE \\\n')
            script_file_id.write(f'                -d1 \\\n')
            if other_parameters != 'NONE':
                script_file_id.write(f'                {other_parameters} \\\n')
            script_file_id.write( '                $IN_FILE \\\n')
            script_file_id.write( '                $OUT_FILE \\\n')
            script_file_id.write(f'                {iterations_number} \\\n')
            script_file_id.write(f'                {thinning_interval} \\\n')
            script_file_id.write(f'                {burn_in}\n')
            script_file_id.write( '            RC=$?\n')
            script_file_id.write(f'            if [ $RC -ne 0 ]; then echo "$IN_FILE" >> {witherror_file_list}; else echo "The file is processed."; fi\n')
            script_file_id.write(f'    done < {input_files_list_file}\n')
            script_file_id.write( '}\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'function end\n')
            script_file_id.write( '{\n')
            script_file_id.write( '    END_DATETIME=`date --utc +%s`\n')
            script_file_id.write( '    FORMATTED_END_DATETIME=`date --date="@$END_DATETIME" "+%Y-%m-%d %H:%M:%S"`\n')
            script_file_id.write( '    calculate_duration\n')
            script_file_id.write( '    echo "$SEP"\n')
            script_file_id.write( '    echo "Script ended OK at $FORMATTED_END_DATETIME+00:00 with a run duration of $DURATION s ($FORMATTED_DURATION)."\n')
            script_file_id.write( '    echo "$SEP"\n')
            script_file_id.write( '    exit 0\n')
            script_file_id.write( '}\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'function manage_error\n')
            script_file_id.write( '{\n')
            script_file_id.write( '    END_DATETIME=`date --utc +%s`\n')
            script_file_id.write( '    FORMATTED_END_DATETIME=`date --date="@$END_DATETIME" "+%Y-%m-%d %H:%M:%S"`\n')
            script_file_id.write( '    calculate_duration\n')
            script_file_id.write( '    echo "$SEP"\n')
            script_file_id.write( '    echo "ERROR: $1 returned error $2"\n')
            script_file_id.write( '    echo "Script ended WRONG at $FORMATTED_END_DATETIME+00:00 with a run duration of $DURATION s ($FORMATTED_DURATION)."\n')
            script_file_id.write( '    echo "$SEP"\n')
            script_file_id.write( '    exit 3\n')
            script_file_id.write( '}\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'function calculate_duration\n')
            script_file_id.write( '{\n')
            script_file_id.write( '    DURATION=`expr $END_DATETIME - $INIT_DATETIME`\n')
            script_file_id.write( '    HH=`expr $DURATION / 3600`\n')
            script_file_id.write( '    MM=`expr $DURATION % 3600 / 60`\n')
            script_file_id.write( '    SS=`expr $DURATION % 60`\n')
            script_file_id.write( '    FORMATTED_DURATION=`printf "%03d:%02d:%02d\\n" $HH $MM $SS`\n')
            script_file_id.write( '}\n')
            script_file_id.write( '#-------------------------------------------------------------------------------\n')
            script_file_id.write( 'init\n')
            script_file_id.write( 'run_phase_process\n')
            script_file_id.write( 'end\n')
    except Exception as e:
        error_list.append(f'*** EXCEPTION: "{e}".')
        error_list.append(f'*** ERROR: The file {get_phase_process_script(process_number, output_dir)} can not be created.')
        OK = False

    # return the control variable and the error list
    return (OK, error_list)

#-------------------------------------------------------------------------------

def build_phase_process_starter(process_number, output_dir):
    '''
    Build the starter of the PHASE process script corresponding to the process number.
    '''

    # initialize the control variable and the error list
    OK = True
    error_list = []

    # write the ddRADseq simulation process starter
    try:
        if not os.path.exists(os.path.dirname(get_phase_process_starter(process_number, output_dir))):
            os.makedirs(os.path.dirname(get_phase_process_starter(process_number, output_dir)))
        with open(get_phase_process_starter(process_number, output_dir), mode='w', encoding='iso-8859-1', newline='\n') as file_id:
            file_id.write( '#!/bin/bash\n')
            file_id.write( '#-------------------------------------------------------------------------------\n')
            phase_process_script = get_phase_process_script(process_number, output_dir)
            log_file = get_log_file(process_number, output_dir)
            if sys.platform.startswith('win32'):
                phase_process_script = xlib.windows_path_2_wsl_path(phase_process_script)
                log_file = xlib.windows_path_2_wsl_path(log_file)
            file_id.write(f'{phase_process_script} &>{log_file} &\n')
    except Exception as e:
        error_list.append(f'*** EXCEPTION: "{e}".')
        error_list.append(f'*** ERROR: The file {get_phase_process_starter(process_number, output_dir)} can not be created')
        OK = False

    # return the control variable and the error list
    return (OK, error_list)

#-------------------------------------------------------------------------------

def get_phase_process_script(process_number, output_dir):
    '''
    Get the PHASE process script path corresponding to the process number.
    '''

    # assign the PHASE script path
    phase_process_script = f'{output_dir}{os.sep}phase-process-{process_number}.sh'

    # return the PHASE script path
    return phase_process_script

#-------------------------------------------------------------------------------

def get_phase_process_starter(process_number, output_dir):
    '''
    Get the PHASE process starter path corresponding to the process number.
    '''

    # assign the PHASE process starter path
    phase_process_starter = f'{output_dir}{os.sep}phase-process-{process_number}-starter.sh'

    # return the PHASE starter path
    return phase_process_starter

#-------------------------------------------------------------------------------

def get_log_file(process_number, output_dir):
    '''
    Get the log file path corresponding to the process number.
    '''

    # assign the log file path
    log_file = f'{output_dir}{os.sep}phase-process-{process_number}-log.txt'

    # return the log file path
    return log_file

#-------------------------------------------------------------------------------

if __name__ == '__main__':

    main()
    sys.exit(0)

#-------------------------------------------------------------------------------


from emotion.model.vgg19 import vgg19
import torch
import matplotlib.pyplot as plt
from facenet_pytorch import MTCNN
import numpy as np

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

LABELS = {
    0 : 'Angry',
    1 : 'Disgust',
    2 : 'Fear',
    3 : 'Happy',
    4 : 'Sad',
    5 : 'Surprise',
    6 : 'Neutral'
}

import os

model_dir = os.path.join(os.getcwd(),'emotion', 'data', 'saved', 'emotion.pth')
net = vgg19(1,7)
net.load_state_dict(torch.load(model_dir))
net = net.to(device)
net.eval()

# from emotion.data.dataLoader import *

# print('Loading Data', end = '\r')
# dataset = EmotionData()
# loader = EmotionDataloader(dataset.data_dict, 32 , 0)

# dataloaders = loader.loader_dict
# datasizes = loader.datasize_dict

# import matplotlib.pyplot as plt

def predict(img):
    #print(img.shape)
    img = cv2.resize(img, (48,48))
    img = torch.Tensor(img)
    img = img.view(-1,48,48)
    img = img.view(-1,1,48,48)
    img  = img.to(device)
    print(img.shape)
    o = net(img)
    pre = torch.max(o, 1)[1]
    return LABELS[pre.item()]

import cv2

# Load the cascade
mtcnn = MTCNN(thresholds = [0.7, 0.5, 0.5], device = 'cuda', margin=20)
# To capture video from webcam.
cap = cv2.VideoCapture(0)
# To use a video file as input
# cap = cv2.VideoCapture('filename.mp4')

def predict(img):
    #print(img.shape)
    img = cv2.resize(img, (48,48))
    img = torch.Tensor(img)
    img = img.view(-1,48,48)
    img = img.view(-1,1,48,48)
    img  = img.to(device)
    print(img.shape)
#     print(img.shape)
    o = net(img)
    print(o)
    pre = torch.max(o, 1)[1]
    print(f'predict {pre}')
    return LABELS[pre.item()]

def text(t, img, p):
    font                   = cv2.FONT_HERSHEY_SIMPLEX
    bottomLeftCornerOfText = p
    fontScale              = 1
    fontColor              = (0,0,255)
    lineType               = 2
    org                    = (0,100)

    cv2.putText(img,t,
        bottomLeftCornerOfText,
        font,
        fontScale,
        fontColor,
        lineType)

while True:
    # Read the frame
    _, img = cap.read()
    # Detect the faces

    faces = mtcnn.detect(img)
    print(faces)

    # Draw the rectangle around each face
    if (type(faces[0]) != type(None)):
        for (x, y, x1, y1) in faces[0]:
            x1 = int(x1)
            y1 = int(y1)
            x = int(x)
            y = int(y)

            print(x , y , x1 , y1 , sep = ' ')

            cv2.rectangle(img, (x, y), (x1, y1), (255, 0, 0), 2)
            face = img[x:x1, y:y1]
            gray = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY)
            t = predict(gray)
            text(t,img, (x,y))

    cv2.imshow('img', img)

    # Display
    # Stop if escape key is pressed
    k = cv2.waitKey(30) & 0xff
    if k==27:
        break
# Release the VideoCapture object
cap.release()


#!/usr/bin/env python
#-*- coding: utf-8 -*

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patheffects as path_effects
import seaborn as sns

x = [3.5, 9.2, 11.7, 24.1, 49.1]
y = [u"Nuestra\nImplementación", u"HomographyNet\n(Regresión)" , u"ORB\n+\nRANSAC", u"HomographyNet\n(Clasificación)", u"Homografía\nIdentidad"]
ax = sns.barplot(y, x, palette="Blues")
ax.set(ylabel="Mean Average Corner Error\n(pixels)")
for i, rect in enumerate(ax.patches):
	txt = ax.text(rect.get_x() + rect.get_width()/2.0 - len(str(x[i])) * 0.05, rect.get_height()- 2.75 - rect.get_height()*0.05, x[i], fontsize=20, color='white')
	txt.set_path_effects([path_effects.Stroke(linewidth=2, foreground="gray"), path_effects.Normal()])

plt.xticks(rotation=30)
plt.tight_layout()
plt.show()


from django.db import models
from .Resource import *

class PublicationManager(models.Manager):
    def addPublication(self, request):
        """ add new publication """
        R = Resource.objects.addResource(request)
        P = Publication(
            resource=R,
            title=request['title'],
            authors=request['authors'],
            publicationDate=request['publicationDate'],
            organization=request['organization'],
            link=request['link']
        )
        P.save()
        return P

    def editPublication(self, request):
        """ edit existing publication """
        R = Resource.objects.editResource(request)
        P = Publication.objects.get(resource=R)
        P.title = request['title']
        P.authors = request['authors']
        P.publicationDate = request['publicationDate']
        P.organization = request['organization']
        P.link = request['link']
        P.save()
        return P

    def getDocumentById(self, request):
        """ get publication details on the basis of resource ID """
        R = Resource.objects.getResourceById(request)
        P = Publication.objects.get(resource=R)
        return P

    def retrievePublications(self, request):
        """ retrieve details of all the publications depending on the request """
        """ note: courseId is compulsory field; title, authors, organization, link are optional fields """
        R = Resource.objects.retrieveResources(request)
        P = Publication.objects.filter(pk__in=R)
        if 'title' in request.keys():
            P = P.objects.filter(title=request['title'])
        if 'authors' in request.keys():
            P = P.objects.filter(authors=request['authors'])
        if 'organization' in request.keys():
            P = P.objects.filter(organization=request['organization'])
        if 'link' in request.keys():
            P = P.objects.filter(link=request['link'])

        return P

    def deletePublication(self, request):
        """ deletes existing publication """
        R = Resource.objects.getResourceById(request)
        P = Publication.objects.get(resource=R)
        P.delete()
        R.delete()
        return P

class Publication(models.Model):
    # Resource
    resource = models.OneToOneField(Resource, on_delete=models.CASCADE, primary_key=True)
    # Title
    title = models.CharField(max_length=500, blank=False, null=False)
    # Authors
    authors = models.CharField(max_length=250)
    # Publication date
    publicationDate = models.DateField(editable=True, auto_now=False, auto_now_add=False)
    # Organization
    organization = models.CharField(max_length=100)
    # Link
    link = models.URLField()

    objects = PublicationManager()

    def __str__(self):
        return self.title + " - " + self.authors + " - " + self.publicationDate


import fitz
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize, word_tokenize
import base64
import requests
import os
from dotenv import load_dotenv

# make sure to download before running
# nltk.download('punkt')
# nltk.download('stopwords')

# function to extract text from each page
def read(file_content):
    text = []
    images = []

    # Open the PDF using PyMuPDF
    document = fitz.open(stream=file_content, filetype="pdf")

    # Iterate through the PDF pages and extract text
    for page_num in range(len(document)):
        page = document[page_num]
        page_text = page.get_text()

        # Extract image from each page and convert to base64
        pixmap = page.get_pixmap()
        image_data = pixmap.tobytes()
        image_base64 = base64.b64encode(image_data).decode('utf-8')
        images.append(image_base64)

        text.append(page_text)

    document.close()

    page_summaries = summarize_pages(text, num_sentences=1)

    return text, page_summaries, images

# function to extract prompts for iage generation
def summarize_pages(text, num_sentences=1):

    summaries = []
    stop_words = set(stopwords.words("english"))

    for page_text in text:
        # Tokenize the page text into sentences
        sentences = sent_tokenize(page_text)

        # Tokenize each sentence into words and remove stop words
        words = [word for word in word_tokenize(page_text) if word.lower() not in stop_words]

        # Calculate word frequencies
        word_freq = nltk.FreqDist(words)

        # Sort sentences by the sum of their word frequencies
        ranked_sentences = sorted(sentences, key=lambda sentence: sum(word_freq[word] for word in word_tokenize(sentence)), reverse=True)

        # Select the top N sentences as the summary
        summary = " ".join(ranked_sentences[:num_sentences])
        summaries.append(summary)

    return summaries

# testing out using LLM to create better prompts

# if __name__ == "__main__":
#     # Load environment variables from the .env file
#     load_dotenv()
#     auth_token = os.getenv('hugging_face_api_token')

#     API_URL = "https://api-inference.huggingface.co/models/google/flan-t5-base"
#     headers = {"Authorization": f"Bearer {auth_token}"}

#     def prompt_extract(payload):
#         response = requests.post(API_URL, headers=headers, json=payload)
#         return response.json()

#     output = prompt_extract({
#         "inputs": "Generate a prompt for image generation using this text: The ferocious dragon roars great flames down the village",
#     })

#     print(output)


#!/usr/bin/env python
"""actionVerification.py:
Small script to check if a given host is reachable and/or pre defined services are available.
Services can be defined in the config.py file.

Current return codes:
'OK':           0
'ERROR':        1
'TARGET_ERROR': 50
'NOTSURE':      100

Author: Tomer Siani Nov. 2014

"""

import sys
import time
import nmap
import argparse
import socket

#Import configurations
from config import services as service_ref
from config import return_codes as return_codes

#define parser for arguments
parser = argparse.ArgumentParser(description='Checks activity for given host using nmap. (Currently only supporting IPv4)')
parser.add_argument('-t', default="10.20.4.115", type=str, dest='target', help='target IP/hostname')
parser.add_argument('-p', default='0', type=int, dest='port', help='Port to scan on target')
parser.add_argument('-s', default="", type=str, dest='service', help='Service to scan for on target')
parser.add_argument('-S', action='store_true', help='Scans all target services')
parser.add_argument('-A', action='store_true', help='Agressive scanning')
parser.add_argument('-v', action='store_true', help='verbose output')
parser.add_argument('--debug', action='store_true', help='Debug output')

global v,d
d=False
v=False

try:
    nm = nmap.PortScanner()         # instantiate nmap.PortScanner object
except nmap.PortScannerError:
    print('Nmap not found', sys.exc_info()[0])
    sys.exit(1)
except:
    print("Unexpected error:", sys.exc_info()[0])
    sys.exit(1)

def main(argv=sys.argv):

    args=parser.parse_args()
    global v,d
    v = args.v
    d = args.debug
    target=checkTarget(args.target)
    port = args.port
    service = args.service
    scanArgs=""
    if args.A:
        log("Agressive scan active")
        scanArgs="-A"
    return_value=0

    #If service scan is required print output
    if args.S:
        v = True
        for i in service_ref:
            checkService(target,service_ref[i],scanArgs)
    else:

        #If only the target is defined ping scan
        if port==0 and service=="":
            log("Checking if host is up")
            nm.scan(target,arguments='-sn')
            return_value=isUp(nm[target].state())

        #if port is defined
        if port>0 and service=="":
            return_value=checkPort(target,port,scanArgs)

        #Check if service is regitered in config file
        if service in service_ref:
            log("Checking service {} on port {}".format(service,service_ref[service]))
            return_value   = checkService(target,service_ref[service],scanArgs)

        elif service != "":
            log("Service not registered in config-file")
            return_value   = return_codes['ERROR']
    print("Return value = {}".format(return_value))
    sys.exit(int(return_value))

def log(string):
    if v:
        print(string)

def debugLog(string):
    if d:
        print("---DEBUG: {}".format(string))

def isUp(state):
    if state=="up":
        return return_codes['OK']
    else:
        return return_codes['ERROR']

def checkPort(target,port,scanArgs):
    nm.scan(target,arguments='{} -p {}'.format(scanArgs,port))
    debugLog("Issued nmap command: {}".format(nm.command_line()))
    if nm[target].has_tcp(port):
            #nm[target].tcp(int(port))
            state=nm[target]['tcp'][port]['state']
            log('port : %s\tstate : %s' % (port, state))
            debugLog("State    : {}".format(state))
            debugLog("Scan info: {}".format(nm.scaninfo()))
            debugLog("Protocols: {}".format(nm[target].all_protocols()))
            debugLog(nm.csv())
            if isOpen(nm[target]['tcp'][port]['state']):
                return return_codes['OK']
            else:
                return return_codes['ERROR']
    else:
        return None

def checkService(target,port,scanArgs):
    nm.scan(target,arguments='-sV {} -p {}'.format(scanArgs,port))
    debugLog("Issued nmap command: {}".format(nm.command_line()))
    if nm[target].has_tcp(port):
            state=nm[target]['tcp'][port]['state']
            service=nm[target]['tcp'][port]['product']
            version=nm[target]['tcp'][port]['version']
            debugLog("State    : {}".format(state))
            debugLog("Service  : {}".format(service))
            debugLog("Version  : {}".format(version))
            debugLog("Scan info: {}".format(nm.scaninfo()))
            debugLog("Protocols: {}".format(nm[target].all_protocols()))
            debugLog(nm.csv())
            log('port : %s\tstate : %s' % (port, nm[target]['tcp'][port]['state']))

            #Version detected: service most likely running
            if isOpen(state) and  not version=="":
                log("Service running: {}".format(service))
                log("Version info: {}\n".format(version))
                return return_codes['OK']

            #Version could not be detected
            if isOpen(state) and version=="":
                log("Failed to determine Verion. Port open but service not reachable")
                return return_codes['NOTSURE']
            else:
                return return_codes['ERROR']
    else:
        return return_codes['ERROR']

def isOpen(state):
    if state=="open":
        return 1
    else:
        return 0

#Check if target (hostname/ip)
def checkTarget(target):
    try:
        socket.inet_aton(target)
        return target
    except:
        try:
            log("Target given is not a valit IPv4 ip")
            log("Found host ip:{}".format(socket.gethostbyname_ex(target)))
            return str(socket.gethostbyname(target))
        except:
            print("Could not resolve hostname")
            sys.exit(return_codes['TARGET_ERROR'])

__name__="__main__"
main()


from django.db import models

class Transaction(models.Model):
    """
    Money moving (transactions)
    """
    customer_fk = models.ForeignKey(
        "user.Customer",
        on_delete=models.CASCADE,
        related_name="transactions",
        blank=True,
        null=True,
    )
    amount = models.PositiveIntegerField(default=0)
    TYPE_CHOICES = [
        ("income", "Income"),
        ("expense", "Expense"),
    ]
    type = models.CharField(
        default="income",
        max_length=25,
        blank=True,
        null=True,
        verbose_name="Type transaction",
        choices=TYPE_CHOICES,
    )
    created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    updated = models.DateTimeField(auto_now=True, blank=True, null=True)

    def __str__(self):
        return f"Transaction by {self.customer_fk}"


from tkinter import *
from tkinter.messagebox import *
from collections import defaultdict

class Polynome(defaultdict):
    def __init__(self, **kwargs):
        defaultdict.__init__(self, float, **kwargs)

    def fromstring(s):
        poly = Polynome()
        s = s.replace('+',' ')
        ls = s.split()  #розбиваємо на список одночленів
        for m in ls:
            c = m.split('*x**') #виділяємо степінь та коефіцієнт
            power = int(c[1])
            coeff = float(c[0])
            poly[power] = coeff
        return poly

    fromstring = staticmethod(fromstring)

    def add_monom(self, deg, coeff):
        if coeff != 0:
            self[deg] += coeff

    def get_degree(self):
        return max(self)

    def __str__(self):
        monomials = list(self.items())
        if not monomials:
            poly_str = "0.0*x**0"
        else:
            monomials.sort(reverse=True)
            ls = ["{}*x**{}".format(mono[1], mono[0]) for mono in monomials]
            poly_str = ' + '.join(ls)
        return poly_str

    def __call__(self, x):
        return sum([self[k]*x**k for k in self])

    def __add__(self, other):
        p = Polynome()
        keys = set(self.keys()) | set(other.keys())
        for k in keys:
            p[k] = self[k] + other[k]
        return self._delzeroes(p)

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        p = Polynome()
        keys = set(self.keys()) | set(other.keys())
        for k in keys:
            p[k] = self[k] - other[k]
        return self._delzeroes(p)

    def __rsub__(self, other):
        p = Polynome()
        keys = set(self.keys()) | set(other.keys())
        for k in keys:
            p[k] = other[k] - self[k]
        return self._delzeroes(p)

    def __mul__(self, other):
        p = Polynome()
        for k1 in self:
            for k2 in other:
                p[k1 + k2] += self[k1] * other[k2]
        return self._delzeroes(p)

    def __rmul__(self, other):
        return self.__rmul__(other)

    def deriv(self, n=1):
        p = self
        for i in range(n):
            p = self._deriv(p)
        return self._delzeroes(p)

    def _deriv(self, p):
        pp = Polynome()
        for k in p:
            if k != 0:
                pp[k - 1] = p[k] * k
        return pp

    def _delzeroes(self, p):
        pp = Polynome()
        for k in p:
            if p[k] != 0:
                pp[k] = p[k]
        return pp

    def makewidgets(self):
        self.frame = Frame(self.root)

# if __name__ == '__main__':
#     p1 = Polynome.fromstring('3.7*x**3 + 0.3*x**1 + -1.2*x**0')
#     print('р1 =', p1)
#     p2 = Polynome.fromstring('2.2*x**3 + -1.3*x**2 + 0.2*x**1')
#     print('р2 =', p2)
#     print('Значення p1 у точці x=2:', p1(2))
#     print('Сума p1+p2:', p1 + p2)
#     print('Різниця p1-p2:', p1 - p2)
#     print('Добуток p1*p2:', p1 * p2)
#     p = p1.deriv(2)
#     print('2 похідна р1:', p)

class Calculator:
    def __init__(self, master):
        self.root = master
        self.first = ""
        self.second = ""
        self.result = ""
        self.n = 0
        self._make_widgets()
        self._calculate()

    def _calculate(self):
        pass

    def _make_widgets(self):
        self._frame_top = Frame(self.root)

        self._lbl_n = Label(self._frame_top, text="Enter n:", font="Arial 16")
        self._lbl_n.pack(side = LEFT, padx = 5)
        self._entry_n = Entry(self._frame_top, width=7, justify='center', font="Arial 16", textvariable = self.n)
        self._entry_n.pack(side = RIGHT, padx = 5)
        self._frame_top.pack(side=TOP, fill=Y, expand=NO)
        self._btn_ok = Button(self.root, width=8, justify='center', text='Ok', command=self.ok_handler)
        self._btn_ok.pack(side=BOTTOM, padx=5, pady=5)

    def ok_handler(self, ev=None):
        self.n = int(self._entry_n.get())
        self._lbl_n.pack_forget()
        self._entry_n.pack_forget()
        self._btn_ok.pack_forget()
        if not self._entry_n.get():
            showwarning(message='Enter n!')
            return
        print("n: ", self.n)
        self._input_coefficients()

    def _input_coefficients(self):
        self.first = []
        for i in range(0, self.n + 1):
            self.first.append(self._input_one(i))
        self._frame_first_wrapper = Frame(self._frame_top)
        self._btn_f = Button(self._frame_first_wrapper, width=8, justify='center', text='Ok', command=self.ok_input())
        self._btn_f.pack(side=RIGHT, padx=5, pady=5)
        self._frame_first_wrapper.pack(side=TOP, fill=Y, expand=NO)

    def _input_one(self, i):
        self._frame_first = Frame(self._frame_top)
        self._lbl_first = Label(self._frame_first, text='*x**' + str(i), font="Arial 16")
        self._lbl_first.pack(side=RIGHT, padx=5)
        self._entry_first = Entry(self._frame_first, width=3, justify='center', font="Arial 16", textvariable="")
        self._entry_first.pack(side=LEFT, padx=5)
        self._frame_first.pack(side=LEFT, fill=Y, expand=NO)

    def ok_input(self):
        result = self._entry_first.get()
        if result:
            self._frame_first.pack_forget()
            self._lbl_first.pack_forget()
            self._entry_first.pack_forget()
            self._frame_top.pack_forget()
        return result

def main():
    top = Tk()
    d = Calculator(top)
    mainloop()
    # val = d.get()

if __name__ == '__main__':
    main()


from keras.layers import Dense
from keras.models import Sequential
from keras.callbacks import ProgbarLogger
import numpy as np
import matplotlib.pyplot as plt

n_samples = 500

def powerTwo(x):
 return x*x
np.random.seed(10)
X = np.random.uniform(-2, 2, n_samples)
Y = powerTwo(X)
# tarin MLP
model = Sequential()
model.add(Dense(100, input_dim=1, activation='relu'))
model.add(Dense(1))
model.compile(loss='mae', optimizer='rmsprop', metrics=['accuracy'])
model.fit(X, Y, nb_epoch=20, batch_size=2, verbose=1, validation_split = 0.1, callbacks =[ProgbarLogger()])
#try new samples
new_samples = 300
new_X = np.random.uniform(-2, 2, new_samples)
new_Y = powerTwo(new_X)
pred_Y = model.predict(new_X)
plt.plot(new_X,new_Y,'go',label="X*X")
plt.plot(new_X,pred_Y,'yo',label="PredictedX*X")
plt.show()
print("green shows original X^2 and yellow shows predicted X^2")