# ---------------------------------------------------
#   Name : Chengxuan Li
#   ID: 1631060
#   CMPUT 274, Fall 2020
#
#   Weekly Exercise 6 : Object-Oriented Minimax
# ---------------------------------------------------
from math import inf
from random import choice
from random import seed

class Interface(object):

    def __init__(self):
        self.type = str(self.__class__)

    def __new__(cls, *args, **kwargs):
        """
        Singleton, class Board and Event only have one instance each time
        the game run
        :param args:
        :param kwargs:
        """
        if not hasattr(cls, "_instance"):
            cls._instance = object.__new__(cls)
        return cls._instance

    def __str__(self):
        return self.type

    def __repr__(self):
        s = "<%d> %s" % (id(self), self.type)
        return s

class Board(Interface):

    def __init__(self, size=(3,3)):
        super().__init__()

        self.board = size

    def empty_cells(self):
        """
        Each empty cell will be added into cells' list
        :return: a list of empty cells
        """
        empty_cells = []

        for row in self.board:
            for cell in row:
                if cell.state == State.EMPTY:
                    empty_cells.append(cell)

        return empty_cells

    def evaluate(self):
        """
        Function to heuristic evaluation of state.
        :return: +1 if the computer wins; -1 if the human wins; 0 draw
        """
        if self.wins(State.COMP):
            score = +1
        elif self.wins(State.HUMAN):
            score = -1
        else:
            score = 0

        return score

    def set_move(self, x, y, player):
        """
        Set the move on board, if the coordinates are valid
        :param x: X coordinate
        :param y: Y coordinate
        :param player: the current player
        """
        if self.valid_move(x, y):
            self.board[x][y].state = player
            return True
        else:
            return False

    def valid_move(self, x, y):
        """
        A move is valid if the chosen cell is empty
        :param x: X coordinate
        :param y: Y coordinate
        :return: True if the board[x][y] is empty
        """
        if self.board[x][y] in self.empty_cells():
            return True
        else:
            return False

    def wins(self, player):
        """
        This function tests if a specific player wins. Possibilities:
        * Three rows    [X X X] or [O O O]
        * Three cols    [X X X] or [O O O]
        * Two diagonals [X X X] or [O O O]
        :param player: a human or a computer
        :return: True if the player wins
        """
        win_state = [
            [self.board[0][0].state, self.board[0][1].state,
             self.board[0][2].state],
            [self.board[1][0].state, self.board[1][1].state,
             self.board[1][2].state],
            [self.board[2][0].state, self.board[2][1].state,
             self.board[2][2].state],
            [self.board[0][0].state, self.board[1][0].state,
             self.board[2][0].state],
            [self.board[0][1].state, self.board[1][1].state,
             self.board[2][1].state],
            [self.board[0][2].state, self.board[1][2].state,
             self.board[2][2].state],
            [self.board[0][0].state, self.board[1][1].state,
             self.board[2][2].state],
            [self.board[2][0].state, self.board[1][1].state,
             self.board[0][2].state],
        ]

        if [player, player, player] in win_state:
            return True
        else:
            return False

    @property
    def board(self):
        return self.__board

    @board.setter
    def board(self, size):
        r, c = size
        self.__board = []
        for x in range(r):
            row = []
            for y in range(c):
                row.append(State(x, y, State.EMPTY))
            self.__board.append(row)

class Event(Interface):

    def __init__(self):
        super().__init__()

        self.__h_choice = ""
        self.__c_choice = ""
        self.__first = ""

    @property
    def c_choice(self):
        return self.__c_choice

    @c_choice.setter
    def c_choice(self, choice):
        self.__c_choice = choice

    @property
    def first(self):
        return self.__first

    @first.setter
    def first(self, pos):
        self.__first = pos

    @property
    def h_choice(self):
        return self.__h_choice

    @h_choice.setter
    def h_choice(self, choice):
        self.__h_choice = choice

    def ai_turn(self):
        """
        The Human plays choosing a valid move.
        :return:
        """
        depth = len(self.board.empty_cells())
        if depth == 0 or self.game_over():
            return

        print()
        print(f'Computer turn [{self.c_choice}]')
        self.render()

        if depth == 9:
            x = choice([0, 1, 2])
            y = choice([0, 1, 2])
        else:
            move = self.minimax(depth, State.COMP)
            x, y = move[0], move[1]

        self.board.set_move(x, y, State.COMP)

    def game_over(self):
        """
        This function test if the human or computer wins
        :return: True if the human or computer wins
        """
        return self.board.wins(State.HUMAN) or self.board.wins(State.COMP)

    def game_over_msg(self):
        """
        Game over message
        :return:
        """
        if self.board.wins(State.HUMAN):
            print()
            print(f'Human turn [{self.h_choice}]')
            self.render()
            print('YOU WIN!')
        elif self.board.wins(State.COMP):
            print()
            print(f'Computer turn [{self.c_choice}]')
            self.render()
            print('YOU LOSE!')
        else:
            print()
            self.render()
            print('DRAW!')

    def handle(self):
        """
        Main loop of this game
        :return:
        """
        while len(self.board.empty_cells()) > 0 and not self.game_over():
            if self.first == 'N':
                self.ai_turn()
                self.first = ''

            self.human_turn()
            self.ai_turn()

    def human_turn(self):
        """
        The Human plays choosing a valid move.
        :return:
        """
        depth = len(self.board.empty_cells())
        if depth == 0 or self.game_over():
            return

        # Dictionary of valid moves
        move = -1
        moves = {
            1: [0, 0], 2: [0, 1], 3: [0, 2],
            4: [1, 0], 5: [1, 1], 6: [1, 2],
            7: [2, 0], 8: [2, 1], 9: [2, 2],
        }

        print()
        print(f'Human turn [{self.h_choice}]')
        self.render()

        while move < 1 or move > 9:
            try:
                move = int(input('Use numpad (1..9): '))
                coord = moves[move]
                can_move = self.board.set_move(coord[0], coord[1], State.HUMAN)

                if not can_move:
                    print('Bad move')
                    move = -1
            except (EOFError, KeyboardInterrupt):
                print('Bye')
                exit()
            except (KeyError, ValueError):
                print('Bad choice')

    def minimax(self, depth, player):
        """
        AI function that choice the best move
        :param depth: node index in the tree (0 <= depth <= 9),
        but never nine in this case (see iaturn() function)
        :param player: an human or a computer
        :return: a list with [the best row, best col, best score]
        """
        if player == State.COMP:
            best = [-1, -1, -inf]
        else:
            best = [-1, -1, +inf]

        if depth == 0 or self.game_over():
            score = self.board.evaluate()
            return [-1, -1, score]

        for cell in self.board.empty_cells():
            x, y = cell.coordinate
            self.board.board[x][y].state = player
            score = self.minimax(depth - 1, -player)
            self.board.board[x][y].state = 0
            score[0], score[1] = x, y

            if player == State.COMP:
                if score[2] > best[2]:
                    best = score  # max value
            else:
                if score[2] < best[2]:
                    best = score  # min value

        return best

    def pick_choice(self):
        """
        Loop of picking choice
        :return:
        """
        while self.h_choice != "O" and self.h_choice != "X":
            try:
                print("")
                self.h_choice = input("Choose X or O\nChosen: ").upper()
            except (EOFError, KeyboardInterrupt):
                print("Bye")
                exit()
            except (KeyError, ValueError):
                print("Bad choice")
        if self.h_choice == "X":
            self.c_choice = "O"
        else:
            self.c_choice = "X"
        print()

    def pick_first(self):
        """
        Loop of picking first to start
        :return:
        """
        while self.first != 'Y' and self.first != 'N':
            try:
                self.first = input('First to start?[y/n]: ').upper()
            except (EOFError, KeyboardInterrupt):
                print('Bye')
                exit()
            except (KeyError, ValueError):
                print('Bad choice')

    def render(self):
        """
        Print the board on console
        """
        str_line = '---------------'

        print('\n' + str_line)
        for row in self.board.board:
            for cell in row:
                symbol = self.chars[cell.state]
                print(f'| {symbol} |', end='')
            print('\n' + str_line)

    def run(self):
        """
        Main process of the game
        :return:
        """
        seed(274 + 2020)
        print()

        self.pick_choice()
        self.pick_first()

        self.chars = {
            State.HUMAN: self.h_choice,
            State.COMP: self.c_choice,
            State.EMPTY: " "
        }
        self.board = Board()

        self.handle()
        self.game_over_msg()

class State(Interface):
    HUMAN = -1
    COMP = +1
    EMPTY = 0

    def __init__(self, x, y, state):
        super().__init__()

        self.coordinate = (x, y)
        self.state = state

    def __new__(cls, *args, **kwargs):
        """
        Override the __new__ method from class Interface since the board can
        have multiple instances of class State
        :param args:
        :param kwargs:
        """
        return super(Interface, cls).__new__(cls)

    @property
    def coordinate(self):
        return self.__coordinate

    @coordinate.setter
    def coordinate(self, coord):
        self.__coordinate = coord

    @property
    def state(self):
        return self.__state

    @state.setter
    def state(self, cstate):
        self.__state = cstate

def main():
    """
    main function that calls all functions
    """
    event = Event()
    event.run()
    exit()

if __name__ == "__main__":
    main()


import os
import torch
from CLIP import clip
from PIL import Image
import csv
import matplotlib.pyplot as plt

device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = clip.load("ViT-B/32", device=device)

def read_class_text_from_csv(csv_file, encoding='utf-8', line=0):
    with open(csv_file, 'r', encoding=encoding, errors='replace') as file:
        reader = csv.reader(file)
        class_text = [row[line] for row in reader]  # 读取每一行第二个元素
    return class_text

def extract_subseries_from_csv(csv_file, brand_name, encoding='utf-8'):
    with open(csv_file, 'r', encoding=encoding, errors='replace') as file:
        reader = csv.reader(file)
        next(reader)  # 跳过CSV文件的标题行
        subseries = [row[2].strip() for row in reader if row[1].strip() == brand_name]
    return subseries

def extract_category_from_csv(csv_file, brand_name, subseries, sa = 0, encoding='utf-8'):
    with open(csv_file, 'r', encoding=encoding, errors='replace') as file:
        reader = csv.reader(file)
        next(reader)  # 跳过CSV文件的标题行
        shoes_price = [row[sa].strip() for row in reader if row[1].strip() == brand_name and row[2].strip() == subseries]
    return shoes_price

def predict(image_file, class_text):
    image = preprocess(Image.open(image_file)).unsqueeze(0).to(device)
    text = clip.tokenize(class_text).to(device)

    with torch.no_grad():
        image_features = model.encode_image(image)
        text_features = model.encode_text(text)

        logits_per_image, logits_per_text = model(image, text)
        brand_probs = logits_per_image.softmax(dim=-1).cpu().numpy()

    return brand_probs

def predict_brand(image_file, class_text):
    brand_probs = predict(image_file, class_text)

    max_brand_prob = 0.0
    max_brand_index = -1
    for i, prob in enumerate(brand_probs[0]):
        if prob > max_brand_prob:
            max_brand_prob = prob
            max_brand_index = i

    if max_brand_index != -1:
        max_brand = class_text[max_brand_index]
        # print(f"Brand Prediction: {max_brand}: {max_brand_prob}")
        return max_brand, max_brand_prob

def predict_series(image_file, class_text, count):
    brand_probs = predict(image_file, class_text)

    max_brand_prob = 0.0
    max_brand_index = -1
    for i, prob in enumerate(brand_probs[0]):
        if prob > max_brand_prob:
            max_brand_prob = prob
            max_brand_index = i

    if max_brand_index != -1:
        max_brand = class_text[max_brand_index]
        # print(f"Brand Prediction{count}: {max_brand}: {max_brand_prob}")
        return max_brand, max_brand_prob


import os, shutil

DATAPATH = '/home/dxx/Backup/STUDY/DM/data/test/0/'
OUTPUTPATH = '/home/dxx/Backup/STUDY/DM/output/test_result/'
num_class = 6

filenames = sorted(os.listdir(DATAPATH))
with open('result.txt') as f:
    results = [ line.strip()[-1] for line in f.readlines() ]

for category in range(num_class):
    os.makedirs(os.path.join(OUTPUTPATH, str(category)))

for filename, rst in zip(filenames, results):
    src = os.path.join(DATAPATH, filename)
    dst = os.path.join(OUTPUTPATH, str(rst), filename)
    shutil.copy(src, dst)


import threading
import inspect
import ctypes
from PyQt4 import QtCore

def async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""

    if not inspect.isclass(exctype):
        raise TypeError("Only types can be raised (not instances)")
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        tid,
        ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
        raise SystemError("PyThreadState_SetAsyncExc failed")

class Thread(threading.Thread):

    def _get_my_tid(self):
        """determines this (self's) thread id"""
        if not self.isAlive():
            return -1

        # do we have it cached?
        if hasattr(self, "_thread_id"):
            return self._thread_id

        # no, look for it in the _active dict
        for tid, tobj in threading._active.items():
            if tobj is self:
                self._thread_id = tid
                return tid

        raise AssertionError("could not determine the thread's id")

    def raise_exc(self, exctype):
        """raises the given exception type in the context of this thread"""

        tid = self._get_my_tid()
        if tid != -1:
            async_raise(tid, exctype)

    def terminate(self):
        """raises SystemExit in the context of the given thread, which should
        cause the thread to exit silently (unless caught)"""

        self.raise_exc(SystemExit)

class WatcherThread(QtCore.QThread):

    def __init__(self, cmd_thread):
        QtCore.QThread.__init__(self)
        self.cmd_thread = cmd_thread

    def run(self):
        self.cmd_thread.join()

class CmdThread(Thread):

    def __init__(self, editor, text):
        '''set up a separate thread to run the code given in txt in the
        InteractiveInterpreter editor.'''

        Thread.__init__(self)
        self.editor = editor
        self.text = text

    def run(self):
        lines = self.text.split('\n')
        if len(lines) > 1:
            self.editor.interpreter.runcode(self.text)
        else:
            self.editor.needmore = self.editor.interpreter.push(self.text)


#! /usr/bin/env python3
import os
import cv2
import math
import numpy as np
import pyrender
import trimesh

from tools.bop_toolkit_lib import view_sampler
from tools import io_interface

def kp_to_dict(kp):
    kp_dict = []
    for kpi in kp:
        kp_dict.append({'angle': kpi.angle,
                        'class_id': kpi.class_id,
                        'octave': kpi.octave,
                        'pt': [kpi.pt[0], kpi.pt[1]],
                        'response': kpi.response,
                        'size': kpi.size})
    return kp_dict

class ModelRenderer:
    def __init__(self, camera_info, view_radius):
        self.flip_yz_rotation = np.array([[1., 0., 0.],
                                          [0., -1., 0.],
                                          [0., 0., -1.]])

        # Set up the camera, z-axis away from the scene, x-axis right, y-axis up
        self.camera = pyrender.IntrinsicsCamera(fx=camera_info['K'][0],
                                                fy=camera_info['K'][4],
                                                cx=camera_info['K'][2],
                                                cy=camera_info['K'][5])
        self.renderer = pyrender.OffscreenRenderer(camera_info['image_width'],
                                                   camera_info['image_height'])
        # Set up the light, a single spot light in the same spot as the camera
        self.light = pyrender.SpotLight(
            color=np.ones(3),
            intensity=view_radius * view_radius * 20,
            innerConeAngle=np.pi / 16.0)

        self.views, views_level = view_sampler.sample_views(
            min_n_views=15,
            radius=view_radius, # 0.4
            azimuth_range=(0, 2 * math.pi),
            elev_range=(-0.5 * math.pi, 0.5 * math.pi),
            mode='hinterstoisser')

        self.num_views = len(self.views)
        for view_id in range(self.num_views):
            view = self.views[view_id]
            view['id'] = '{:0>6d}'.format(view_id)
            view['R'] = view['R'].tolist()
            view['t'] = view['t'].tolist()

        # sift = cv2.xfeatures2d.SURF_create()
        self.sift = cv2.xfeatures2d_SIFT.create() #cv2.SIFT_create()
        self.view_radius = view_radius

    def reset_light(self, intensity):
        self.light = pyrender.SpotLight(
            color=np.ones(3),
            intensity=intensity,
            innerConeAngle=np.pi / 16.0)

    def render_model_images(self, model_path, images_path, cal_features):
        # Load the FUZE bottle trimesh and put it in a scene
        fuze_trimesh = trimesh.load(model_path)
        mesh = pyrender.Mesh.from_trimesh(fuze_trimesh)

        for view_id in range(self.num_views):
            camera_pose = np.eye(4, dtype=np.float32)
            # cv to gl
            camera_pose[0:3, 0:3] = np.dot(self.flip_yz_rotation,
                                           np.array(self.views[view_id]['R']))
            camera_pose[0:3, 3] = \
                np.dot(self.flip_yz_rotation,
                       np.array(self.views[view_id]['t']).reshape([3]))

            # gl in object
            camera_pose[0:3, 0:3] = np.linalg.inv(camera_pose[0:3, 0:3])
            camera_pose[0:3, 3] = np.dot(camera_pose[0:3, 0:3],
                                         -camera_pose[0:3, 3])

            scene = pyrender.Scene()
            scene.add(mesh)
            scene.add(self.camera, pose=camera_pose)
            scene.add(self.light, pose=camera_pose)
            # Render the scene
            color, depth = self.renderer.render(scene)

            if not os.path.exists(images_path):
                os.makedirs(images_path)
            if cal_features:
                # Find keypoints and descriptors directly
                kp, des = self.sift.detectAndCompute(
                    cv2.cvtColor(color, cv2.COLOR_RGB2GRAY), None)

                io_interface.dump_pickle(
                    [kp_to_dict(kp), des],
                    images_path + '/{:0>6d}'.format(view_id) + '.pickle')

            cv2.imwrite(images_path + '/{:0>6d}'.format(view_id) + '.png',
                        cv2.cvtColor(color, cv2.COLOR_RGB2BGR))

    def render_snapshot(self, input_camera_pose, model_path, save_path):
        # Load the FUZE bottle trimesh and put it in a scene
        fuze_trimesh = trimesh.load(model_path)
        mesh = pyrender.Mesh.from_trimesh(fuze_trimesh)

        # gl in object
        camera_pose = np.eye(4, dtype=np.float32)
        camera_pose[0:3, 0:3] = np.dot(self.flip_yz_rotation, input_camera_pose)
        camera_pose[0:3, 3] = \
            np.dot(self.flip_yz_rotation,
                    np.array([[0], [0], [self.view_radius]]).reshape([3]))
        camera_pose[0:3, 0:3] = np.linalg.inv(camera_pose[0:3, 0:3])
        camera_pose[0:3, 3] = np.dot(camera_pose[0:3, 0:3],
                                     -camera_pose[0:3, 3])

        scene = pyrender.Scene()
        scene.add(mesh)
        scene.add(self.camera, pose=camera_pose)
        scene.add(self.light, pose=camera_pose)
        # Render the scene
        color, depth = self.renderer.render(scene)
        # Save png
        cv2.imwrite(save_path, cv2.cvtColor(color, cv2.COLOR_RGB2BGR))

    def render_models_projection(self,
                                 meshes, transformation, color_image):
        scene = pyrender.Scene()
        for mesh in meshes:
            scene.add(pyrender.Mesh.from_trimesh(mesh))

        camera_pose = np.eye(4, dtype=np.float32)
        # cv to gl
        camera_pose[0:3, 0:3] = np.dot(self.flip_yz_rotation,
                                       transformation[0:3, 0:3])
        camera_pose[0:3, 3] = np.dot(self.flip_yz_rotation,
                                     transformation[0:3, 3].reshape([3]))

        # gl in object
        camera_pose[0:3, 0:3] = np.linalg.inv(camera_pose[0:3, 0:3])
        camera_pose[0:3, 3] = np.dot(camera_pose[0:3, 0:3],
                                     -camera_pose[0:3, 3])

        scene.add(self.camera, pose=camera_pose)
        scene.add(self.light, pose=camera_pose)

        # Render the scene
        color, depth = self.renderer.render(scene)

        result_img = cv2.addWeighted(color, 0.7, color_image, 0.3, 0)
        return result_img

def render_models(model_renderer, images_path, models_path, models, over_write, suffix=''):
    io_interface.dump_yaml(model_renderer.views,
                           os.path.join(images_path, 'views.yaml'))

    for model_id, model in enumerate(models):
        model = str(model)
        print('rendering ' + model)

        #model_path = os.path.join(models_path, model, 'visual.ply')
        model_path = os.path.join(models_path, model, 'textured.obj')
        model_image_path = os.path.join(images_path, model+suffix)
        if over_write or not os.path.exists(model_image_path):
            model_renderer.render_model_images(
                model_path, os.path.join(images_path, model+suffix), True)

def show_intersection(mesh, ray_origins, ray_directions, locations):
    # stack rays into line segments for visualization as Path3D
    ray_visualize = trimesh.load_path(np.hstack((
        ray_origins,
        ray_origins + ray_directions)).reshape(-1, 2, 3))

    # make mesh transparent- ish
    mesh.visual.face_colors = [100, 100, 100, 100]

    # create a visualization scene with rays, hits, and mesh
    scene = trimesh.Scene([
        mesh,
        ray_visualize,
        trimesh.points.PointCloud(locations)])

    # display the scene
    scene.show()

def kp_mesh_intersection(kpoints, mesh, camera_matrix_inv):
    ray_origins = []
    ray_directions = []
    for p in kpoints:
        uv = np.array([p['pt'][0], p['pt'][1], 1])
        direction = camera_matrix_inv.dot(uv)

        # create some rays
        ray_origins.append([0, 0, 0])
        ray_directions.append(direction)

    ray_origins = np.array(ray_origins)
    ray_directions = np.array(ray_directions)
    # run the mesh-ray test
    locations, index_ray, index_tri = mesh.ray.intersects_location(
        ray_origins=ray_origins,
        ray_directions=ray_directions,
        multiple_hits=False)

    if locations.shape[0] < 4:
        return False, locations, index_ray

    show_intersection = False
    if show_intersection:
        show_intersection(mesh, ray_origins, ray_directions, locations)

    return True, locations, index_ray


import random
import pprint
import re
import numpy as np
import math

fichier = open('iris.txt')
lignes = fichier.readlines()

output = []
n = 5

for uneLigne in lignes:
    output.append([float(x) for x in uneLigne.split()])
    # tab = uneLigne.split()
    # n = 5
    # output=[tab[i:i + n] for i in range(0, len(tab), n)]

# for item in output :
#     # print(item, "\n")
#     print(item)

random.shuffle(output)

for item in output :
    print(item)

print(len(output))
print(list(map(lambda x:int(x[n - 1]), output)).count(1))
print(list(map(lambda x:int(x[n - 1]), output)).count(2))
print(list(map(lambda x:int(x[n - 1]), output)).count(3))

size = len(output)
A = []
T = []

for item in output:
    if item[n - 1] == 1 and list(map(lambda x:int(x[n - 1]), A)).count(1) < 33:
        A.append(item)
        output.remove(item)

for item in output:
    if item[n - 1] == 2 and list(map(lambda x:int(x[n - 1]), A)).count(2) < 33:
        A.append(item)
        output.remove(item)

for item in output:
    if item[n - 1] == 3 and list(map(lambda x:int(x[n - 1]), A)).count(3) < 33:
        A.append(item)
        output.remove(item)

T = output

print(len(A))
print(len(T))
#print(list(map(lambda x:int(x[n - 1]), A)).count(1))
#print(list(map(lambda x:int(x[n - 1]), A)).count(2))
#print(list(map(lambda x:int(x[n - 1]), A)).count(3))

def apprentissage(A, nbVariables, nbClasse):
    poids = []
    n = 1000
    e = 0.5
    for _ in range(nbClasse):
        tmp = []
        for __ in range(nbVariables):
            tmp.append(random.random())
        poids.append(tmp)
    pprint.pprint(poids)

    for _ in range(n):
        for x in A:
            classValue = x[-1]#oracle
            results = []
            for c in range(nbClasse):
                dotProduct = 0
                for v in range(nbVariables):
                    dotProduct += x[v] * poids[c][v]
                results.append(dotProduct)
            ci = np.argmax(results) + 1 #for class index
            if ci != classValue:
                for i in range(nbVariables):
                    poids[int(classValue)-1][i] += e * x[i]
                    poids[ci-1][i] -= e * x[i]

    return poids

def evaluate(P, x, nbVariables, nbClasse):
    results = []
    for c in range(nbClasse):
        dotProduct = 0
        for v in range(nbVariables):
            dotProduct += x[v] * P[c][v]
        results.append(dotProduct)
    return np.argmax(results) + 1 #for class index

def test(P, T, nbVariables, nbClasse):
    compteur = 0

    for t in T:
        v = evaluate(P, t, nbVariables, nbClasse)
        if v == int(t[-1]):
            compteur += 1
    print("Accuracy", compteur / len(T))

def normalize(O, nbVariables):
    for i in range(nbVariables):
        avg = 0
        for c in range(len(O)):
            avg += O[c][i]
        avg /= len(O)
        sigma = 0

        for c in range(len(O)):
            sigma += (O[c][i] - avg)**2
        sigma /= len(O)
        sigma = math.sqrt(sigma)

        for c in range(len(O)):
            O[c][i] = (O[c][i] - avg) / sigma

nbVariable = len(A[0]) - 1
nbClasse = 3

P = apprentissage(A, nbVariable, nbClasse)
test(P, T, nbVariable, nbClasse)

normalize(A, nbVariable)
normalize(T, nbVariable)

P = apprentissage(A, nbVariable, nbClasse)
test(P, T, nbVariable, nbClasse)


from config import *
from homework import *
import openpyxl
import matplotlib.pyplot as plt
from matplotlib.offsetbox import (OffsetImage, AnnotationBbox)

def get_img(datte, clas: str):
  wookbook = openpyxl.load_workbook(f"./outputs/{datte} schedule.xlsx")
  ws = wookbook.active
  dict_classes = {
    '5': ['C 2', 'E 2'],
    '6': ['G 2', 'I 2'],
    '7': ['K 2', 'M 2'],
    '8': ['C 12', 'E 12'],
    '9': ['G 12', 'I 12'],
    '10': ['K 12'],
    '11': ['M 12']
  }
  time_classes = 'B 2'.split(' ')

  if clas != '10' and clas != '11':
    a_class = dict_classes[clas][0].split(' ')
    b_class = dict_classes[clas][1].split(' ')

    times = []
    a = []
    b = []

    for i in range(int(a_class[1]), int(a_class[1])+9):
      a.append(ws[f'{a_class[0]}{i}'].value)
      b.append(ws[f'{b_class[0]}{i}'].value)
      times.append(ws[f'{time_classes[0]}{i}'].value)

    #define figure and axes
    fig, ax = plt.subplots()
    im = plt.imread('./assets/bb.png')
    imagebox = OffsetImage(im, zoom = 0.05)
    ab = AnnotationBbox(imagebox, (0.05, 1), frameon = False)
    ax.add_artist(ab)
    #create values for table
    table_data=[]
    for g in zip(a,b, times):
      table_data.append(tuple([g[2], g[0], g[1]]))

    #create table
    plt.rcParams['font.family'] = 'Helvetica'
    table = ax.table(cellText=table_data, loc='center')
    csfont = {'fontname':'Helvetica'}
    # plt.title('f.png')
    ax.set_title(f"{clas} класс на {datte}", x=0.25, y=0.96, fontsize=10, fontweight='bold', **csfont, color='#048B7B')

    table[(0, 0)].set_facecolor("#048B7B")
    table[(0, 1)].set_facecolor("#048B7B")
    table[(0, 2)].set_facecolor("#048B7B")
    table[(0,0)].set_text_props(weight='bold', color='w')
    table[(0,1)].set_text_props(weight='bold', color='w')
    table[(0,2)].set_text_props(weight='bold', color="w")
    ax.axis('off')
    table.scale(1,2)
    #display table
    plt.savefig(f'./outputs/{datte} {clas}.png', dpi=800)
  else:
    time_classes = 'B 2'.split(' ')
    sep = dict_classes[clas][0].split(' ')

    times = []
    res = []

    for i in range(int(sep[1]), int(sep[1])+9):
      res.append(ws[f'{sep[0]}{i}'].value)
      times.append(ws[f'{time_classes[0]}{i}'].value)
    #define figure and axes
    fig, ax = plt.subplots()
    im = plt.imread('./assets/bb.png')
    imagebox = OffsetImage(im, zoom = 0.05)
    ab = AnnotationBbox(imagebox, (0.04, 1), frameon = False)
    ax.add_artist(ab)
    #create values for table
    table_data=[]
    for g in zip(res, times):
      table_data.append(tuple([g[1], g[0]]))

    #create table
    plt.rcParams['font.family'] = 'Helvetica'
    csfont = {'fontname':'Helvetica'}
    table = ax.table(cellText=table_data, loc='center')
    ax.set_title(f"{clas} класс на {datte}", x=0.26, y=0.96, fontsize=10, fontweight='bold', **csfont, color='#048B7B')
    #modify table
    table[(0, 0)].set_facecolor("#048B7B")
    table[(0, 1)].set_facecolor("#048B7B")
    table[(0,0)].set_text_props(weight='bold', color='w')
    table[(0,1)].set_text_props(weight='bold', color='w')
    table.scale(1,2)
    ax.axis('off')

    #display table
    plt.savefig(f'./outputs/{datte} {clas}.png', dpi=800)

def get_hw():
  ls = parsingHomework(get_data(0))[0]
  hws = parsingHomework(get_data(0))[1]
  ls.insert(0, str('Предметы'))
  hws.insert(0, str('Домашнее задание'))

  log = []
  for n in zip(hws, ls):
    if len(n[0]) > 100:
      log.append(n)
      # s = n.split(' ')
      # print(s)
      # s[int(len(s)/2)] = '\n'
      # s[int(len(s)/2/2)] = '\n'
      hws.insert(hws.index(n[0]), "".join(n[0].split(' ')[:4]))
      hws.remove(n[0])
  res = []
  for l in log:
    res.append(f"*{l[1]}*: {l[0]}\n")
  fig, ax = plt.subplots()
  im = plt.imread('./assets/bb.png')
  imagebox = OffsetImage(im, zoom = 0.06)
  ab = AnnotationBbox(imagebox, (0.5, 1), frameon = False)
  ax.add_artist(ab)
  table_data=[]
  for g in zip(ls, hws):
    table_data.append(tuple([g[0], str(g[1])]))
  plt.rcParams['font.family'] = 'Helvetica'
  table = ax.table(cellText=table_data, loc='center')

  table[(0, 0)].set_facecolor("#048B7B")
  table[(0, 1)].set_facecolor("#048B7B")
  table[(0,0)].set_text_props(weight='bold', color='w')
  table[(0,1)].set_text_props(weight='bold', color='w')
  table.scale(1, 4)

  ax.axis('off')
  plt.savefig(f'./outputs/hw {tomorrow()}.png', dpi=800)
  return res

def FoodgetUploadFolderr(date, timeToFood: str):
  foodXlsx = openpyxl.load_workbook(f"./outputs/{date} food.xlsx")
  excelCursor = foodXlsx.active
  resultForDiner = 0
  for find in range(3, 15):
    resultForDiner += 1
    if excelCursor[f'B{find}'].value == "Итог по набору":
      break

  elementsPosition = {
    'breakfast': ['B 3', 'D 3'],
    'dinner': [f'B {3+resultForDiner}', f'D {3+resultForDiner}']
  }
  typeOfFoodResults = []
  foodResults = []

  if timeToFood == "Завтрак":

    breakfastType = elementsPosition['breakfast'][0].split(' ')
    breakfastFood = elementsPosition['breakfast'][1].split(' ')

    for i in range(int(breakfastType[1]), int(breakfastType[1])+10):
      if excelCursor[f'{breakfastType[0]}{i}'].value == "Итог по набору":
        break
      typeOfFoodResults.append(excelCursor[f'{breakfastType[0]}{i}'].value)
      foodResults.append(excelCursor[f'{breakfastFood[0]}{i}'].value)
    fig, ax = plt.subplots()
    im = plt.imread('./bb.png')
    imagebox = OffsetImage(im, zoom = 0.05)
    ab = AnnotationBbox(imagebox, (0.05, 0.9), frameon = False)
    ax.add_artist(ab)
    #create values for table
    table_data=[]
    for g in zip(typeOfFoodResults, foodResults):
      table_data.append(tuple([g[0], g[1]]))

    plt.rcParams['font.family'] = 'Helvetica'
    table = ax.table(cellText=table_data, loc='center')
    csfont = {'fontname':'Helvetica'}
    # plt.title('f.png')
    ax.set_title(f"Что будем хавать {date}", x=0.32, y=0.86, fontsize=10, fontweight='bold', **csfont, color='#048B7B')

    table[(0, 0)].set_facecolor("#048B7B")
    table[(0, 1)].set_facecolor("#048B7B")
    table[(0,0)].set_text_props(weight='bold', color='w')
    table[(0,1)].set_text_props(weight='bold', color='w')
    ax.axis('off')
    table.scale(1,2)
    #display table
    plt.savefig(f'./outputs/{date} food.png', dpi=800)

  else:
    dinnerType = elementsPosition['dinner'][0].split(' ')
    dinnerFood = elementsPosition['dinner'][1].split(' ')
    for i in range(int(dinnerType[1]), int(dinnerType[1])+10):

      if excelCursor[f'{dinnerType[0]}{i}'].value == "Итог по набору":
        break
      typeOfFoodResults.append(excelCursor[f'{dinnerType[0]}{i}'].value)
      foodResults.append(excelCursor[f'{dinnerFood[0]}{i}'].value)

    fig, ax = plt.subplots()
    im = plt.imread('./assets/bb.png')
    imagebox = OffsetImage(im, zoom = 0.05)
    ab = AnnotationBbox(imagebox, (0.05, 0.9), frameon = False)
    ax.add_artist(ab)
    #create values for table
    table_data=[]
    table_data.append(tuple(["Раздел", "Блюдо"]))
    for g in zip(typeOfFoodResults, foodResults):
      table_data.append(tuple([g[0], g[1]]))

    plt.rcParams['font.family'] = 'Helvetica'
    table = ax.table(cellText=table_data, loc='center')
    csfont = {'fontname':'Helvetica'}
    # plt.title('f.png')
    ax.set_title(f"Что будем хавать {date}", x=0.32, y=0.86, fontsize=10, fontweight='bold', **csfont, color='#048B7B')

    table[(0, 0)].set_facecolor("#048B7B")
    table[(0, 1)].set_facecolor("#048B7B")
    table[(0,0)].set_text_props(weight='bold', color='w')
    table[(0,1)].set_text_props(weight='bold', color='w')
    ax.axis('off')
    table.scale(1,2)
    #display table
    plt.savefig(f'./outputs/{date} food.png', dpi=800)


lanche = ['Hámburguer', 'Suco', 'Pizza', 'Pudim'] # Lista
lanche[3] = 'Picole' # Substitui o valor da posição 3
#Listas são mutáveis
lanche.append('Cookie') # Adiciona um valor no final da lista elemento 4
lanche.insert(0, 'Cachorro Quente') # Adiciona um valor na posição 0
#Refaz a numeração das chaves posteriores ao usar o insert
del lanche[3] # Deleta o valor da posição 3, a pizza
lanche.pop(2) # Deleta o valor da posição 2, o suco, sem índice é o último
print(lanche)
lanche.remove('Cookie') # Deleta o valor 'Cookie'
if 'Pizza' in lanche:
    lanche.remove('Pizza') #Verifica se está antes de remover, pois retorna erro se não estiver

valores = list(range(4, 11)) # Cria uma lista com os valores de 4 a 10, com ao todo 6 índices
valores = [8, 2, 5, 4, 9, 3, 0]
valores.sort() # Ordena os valores em ordem crescente
valores.sort(reverse=True) # Ordena os valores em ordem decrescente
len(valores) # Mostra o tamanho da lista, no caso 7

#Prática
#num = (2, 5, 9, 1)
#num[2] = 3 # Erro, tuplas são imutáveis
num = [2, 5, 9, 1]
print(num)
num[2] = 3 # Substitui o valor da posição 2, o 9, pelo 3
print(num)
num.append(7) # Adiciona o valor 7 no final da lista
num.sort()
print(num)
num.insert(3, 0) # Adiciona o valor 0 na posição 3
print(num)
print(f'Essa lista tem {len(num)} elementos')
num.pop(0)
print(num)
num.append(2)
num.remove(2) # Remove o primeiro valor 2 da lista
print(num)
valores = []
valores.append(5)
valores.append(9)
valores.append(4)

for v in valores:
    print(f'{v}...', end='')
for c, v in enumerate(valores):
    print(f'Na posição {c} encontrei o valor {v}!')

for cont in range(0, 5):
    valores.append(int(input('Digite um valor: ')))

a = [2, 3, 4, 7]
b = a # Cria uma ligação entre as listas
b[2] = 8 # Altera o valor da posição 2 de ambas as listas
c = a[:] # Cria uma cópia da lista a
c[2] = 4 # Altera o valor da posição 2 apenas da lista c
print(f'Lista A: {a}')
print(f'Lista B: {b}')
print(f'Lista C: {c}')

##Listas compostas

dados = list()
dados.append('Joao')
dados.append(17)
print(dados[0])
print(dados[1])
dados.append('Maria')
dados.append(10)
dados.append('Pedro')
dados.append(12)
pessoas = list()
pessoas.append(dados[:]) # Cria uma cópia da lista dados
print('-='*10)
print(dados)
print(pessoas)
print('-='*10)
print(pessoas[0])
print(pessoas[0][0]) # Mostra o primeiro valor da primeira lista

print('~'*30)
pessoas = [['Joao', 17], ['Maria', 10], ['Pedro', 12]]
print(pessoas[0])
print(pessoas[0][0])
print(pessoas[1][1])
print(pessoas[2][0])

teste = list()
teste.append('Joao')
teste.append(17)
galera = list()
galera.append(teste[:]) # Cria uma cópia da lista teste
teste[0] = 'Maria'
teste[1] = 22
galera.append(teste[:]) #Sem [:] cria uma ligação entre as listas
print(teste)
print(galera)

galera = [['Joao', 19], ['Ana', 33], ['Joaquim', 13], ['Maria', 45]]
print(galera[0])
print(galera[0][0])
print(galera[2][1])

#Sequência de Fibonnaci
fib = [0, 1]
for c in range(0, 8):
    fib.append(fib[c] + fib[c+1])
print(fib)

for p in galera:
    print(p)
    print(p[0])
    print(p[1])
    print(f'{p[0]} tem {p[1]} anos')

galera = list()
dado = list()
for c in range(3):
    dado.append(input('Nome: '))
    dado.append(int(input('Idade: ')))
    galera.append(dado[:])
    dado.clear() # Limpa a lista dado
print(galera)

totmai = totmen = 0
for p in galera:
    if p[1] >= 21:
        print(f'{p[0]} é maior de idade')
        totmai += 1
    else:
        print(f'{p[0]} é menor de idade')
        totmen += 1
print(f'Temos {totmai} maiores e {totmen} menores de idade')


"""
mappyTestingCIGARWalking.py
Marcus Viscardi,    October 13, 2021

I want to check that the CIGAR walking I have been doing with the
heatmap scripts is actually getting to the same "end" that minimap2
would have called with the original mapping!
"""

from geneHeatmaps2 import _flip_neg_strand_genes, load_reads_parquet
from nanoporePipelineCommon import find_newest_matching_file
import mappy

def mappy_aligner(path_to_genome):
    mp_aligner = mappy.Aligner(path_to_genome,
                               preset="splice", k=14,
                               extra_flags=0x100000,  # From: https://github.com/lh3/minimap2/blob/master/minimap.h
                               n_threads=10,
                               )
    if not mp_aligner:
        raise Exception("ERROR: failed to load/build index")

    print(mp_aligner.seq_names)  # Prints the contigs which in this case are the adapters in the fastq
    return mp_aligner

def _loop_align_seq(aligner, name, seq, print_per_seq=False):
    if print_per_seq:
        print(f"\n\nAligning read: {name}")
    # For each sequence, create empty dict to store info about mapping hits
    hit_objs = {}

    # Loop through each of the mapping hits generated:
    for hit in aligner.map(seq):
        hit_objs[hit.ctg] = hit

    # If1: there are any mapping hits:
    if hit_objs:
        print("\n", name)
        for chr, hit in hit_objs.items():
            if hit.trans_strand == 1:
                strand = "+"
            else:
                strand = "-"
            calced_other_end = _flip_neg_strand_genes(hit.r_st, hit.cigar_str, strand)
            if strand == "+":
                print(strand, hit.r_st, hit.r_en, calced_other_end, hit.r_st == calced_other_end, sep="\t")
            else:  # strand == "-"
                print(strand, hit.r_st, hit.r_en, calced_other_end, hit.r_en == calced_other_end, sep="\t")
    #         seq_assignment = {"read_id": name,
    #                           "adapter": max_match_keys[0],
    #                           "mapping_obj": hit_objs[max_match_keys[0]]}
    # return seq_assignment

if __name__ == '__main__':

    working_dir = "/data16/marcus/working/210905_nanoporeRun_totalRNA_5108_xrn-1-KD"
    df = load_reads_parquet(find_newest_matching_file(f"{working_dir}/output_dir/"
                                                  f"merge_files/*_mergedOnReads.tsv"), head=100)

    genome_path = "/data16/marcus/genomes/elegansRelease100/200430_allChrs.fa"
    aligner = mappy_aligner(genome_path)

    seq_assignments = []
    for name, seq in zip(df["read_id"].to_list(), df["sequence"].to_list()):
        seq_assignment = _loop_align_seq(aligner, name, seq, print_per_seq=False)
    #     seq_assignments.append(seq_assignment)
    # pprint(seq_assignments)


import sys
from transformers import GPT2Tokenizer, GPT2LMHeadModel
import torch
tokenizer = GPT2Tokenizer.from_pretrained("af1tang/personaGPT")
model = GPT2LMHeadModel.from_pretrained("af1tang/personaGPT")
if torch.cuda.is_available():
    model = model.cuda()

def flatten(l): return [item for sublist in l for item in sublist]

def to_data(x):
    if torch.cuda.is_available():
        x = x.cpu()
    return x.data.numpy()

def to_var(x):
    if not torch.is_tensor(x):
        x = torch.Tensor(x)
    if torch.cuda.is_available():
        x = x.cuda()
    return x

def display_dialog_history(dialog_hx):
    for j, line in enumerate(dialog_hx):
        msg = tokenizer.decode(line)
        if j % 2 == 0:
            print(">> User: " + msg)
        else:
            print("Bot: "+msg)
            print()

def generate_next(bot_input_ids, do_sample=True, top_k=10, top_p=.92,
                  max_length=1000, pad_token=tokenizer.eos_token_id):
    full_msg = model.generate(bot_input_ids, do_sample=True,
                              top_k=top_k, top_p=top_p,
                              max_length=max_length, pad_token_id=tokenizer.eos_token_id)
    msg = to_data(full_msg.detach()[0])[bot_input_ids.shape[-1]:]
    return msg

personas = [
    "I am a mature person.",
    "I am caring but get angry at injustices.",
    "I enjoy playing video games and birdwatching.",
]
personas = tokenizer.encode(
    ''.join(['<|p2|>'] + personas + ['<|sep|>'] + ['<|start|>']))

dialog = sys.argv[1:]

dialog_hx = []
for text in dialog:
    dialog_hx.append(tokenizer.encode(text + tokenizer.eos_token))

bot_input_ids = to_var([personas + flatten(dialog_hx)]).long()
encoded_msg = generate_next(bot_input_ids)
dialog_hx.append(encoded_msg)

msg = tokenizer.decode(encoded_msg, skip_special_tokens=True)
print(msg)
sys.stdout.flush()


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

import logging
from datetime import datetime, timedelta

from odoo import models, fields, api

_logger = logging.getLogger(__name__)

class LoanRecordAutovacuum(models.TransientModel):
    _name = 'loan.autovacuum'
    _description = "Loan - Delete old records"

    @api.model
    def autovacuum(self, days):
        """Delete all records older than ``days`` not in ['approved',]. This includes:

        Called from a cron.
        """
        days = (days > 0) and int(days) or 0
        deadline = datetime.now() - timedelta(days=days)
        data_models = (
            'loan.apply',
            'loan.loan',
            'loan.credit',
        )
        for data_model in data_models:
            records = self.env[data_model].search(
                [('create_date', '<=', fields.Datetime.to_string(deadline)),
                 ('state', 'not in', ['approved', 'refused'])])
            nb_records = len(records)
            # records.unlink()
            records.write({'active': False})
            _logger.info(
                u"AUTOVACUUM - %s '%s' records deactived",
                nb_records, data_model)
        return True

    @api.model
    def autovacuum_credit(self, days):
        """Delete all credit older than ``days`` in ['approved',]. This includes:

        Called from a cron.
        """
        days = (days > 0) and int(days) or 0
        deadline = datetime.now() - timedelta(days=days)
        data_models = (
            'loan.credit',
        )
        for data_model in data_models:
            records = self.env[data_model].search(
                [('create_date', '<=', fields.Datetime.to_string(deadline)),
                 ('state', 'in', ['approved', ]),
                 ('tag_ids.name', 'not in', ['本人', ])])
            nb_records = len(records)
            # records.unlink()
            records.write({'active': False})
            _logger.info(
                u"AUTOVACUUM - %s '%s' credits deactived",
                nb_records, data_model)
        return True


# 3. у нас есть шахматная доска. по горизонтали нумерована цифрами,
# по вертикали буквами. написать программу,
# которая определяет цвет клетки по ее координатам (например B7 = Белая),
# если точно знаем, что клетка А1 - черная

cell_position = input('Какая клетка интересует: ')
horizontal_letter = {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'H': 8}
# ниже проверяем ввод: должно быть два знака в строке, первый - буква, второй - цифра
if len(cell_position) == 2 and cell_position[0].isalpha() and cell_position[1].isdigit():
    if (cell_position[0]).upper() in horizontal_letter.keys() and (1 < int(cell_position[1]) < 9):
        if (horizontal_letter.get((cell_position[0]).upper()) + int(cell_position[1])) % 2 == 0:
            print('ЧЕРНАЯ')
        else:
            print('БЕЛАЯ')
    else:
        print('На шахматной доске нет такой клетки')
else:
    print('Ошибка формата ввода')


#!/usr/bin/env python
# coding:utf-8
"""
Name : socket_client.py
Author  : anne
Time    : 2019-08-05 14:50
Desc:
"""
import socket
client = socket.socket()
client.connect(('127.0.0.1',9999))
while True:
    msg = input('>>:').strip()
    if len(msg) == 0:continue
    client.send(msg.encode('utf-8'))
    data = client.recv(1024)
    print('recv:',data.decode())

client.close()


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.model_zoo as model_zoo
from torch.nn.parameter import Parameter
from torch.distributions.normal import Normal
import pdb

__all__ = ['Inception3', 'inception_v3', 'inception_v3_sparse']

model_urls = {
    # Inception v3 ported from TensorFlow
    'inception_v3_google': 'https://download.pytorch.org/models/inception_v3_google-1a9a5a14.pth',
}

norm_mean, norm_var = 0.0, 1.0

class Inception3(nn.Module):

    def __init__(self, is_sparse=False, num_classes=1000, aux_logits=False, transform_input=True, has_mask=None, filters=None):
        super(Inception3, self).__init__()

        # [inchanel, branch1x1, branch5x5, branch3x3, branch_pool]
        if filters is None:
            filters = [
                [64, 64, 96, 32], # A
                [64, 64, 96, 64], # A
                [64, 64, 96, 64], # A
                [384, 96, 288, 0], # B
                [192, 192, 192, 192], # C
                [192, 192, 192, 192], # C
                [192, 192, 192, 192], # C
                [192, 192, 192, 192], # C
                [320, 192, 768, 0], # D
                [320, 768, 768, 192], # E
                [320, 768, 768, 192], # E
            ]

        if has_mask is None:
            has_mask = [1]*40

        if is_sparse:
            inceptionA = SparseInceptionA
            inceptionB = SparseInceptionB
            inceptionC = SparseInceptionC
            inceptionD = SparseInceptionD
            inceptionE = SparseInceptionE
        else:
            inceptionA = InceptionA
            inceptionB = InceptionB
            inceptionC = InceptionC
            inceptionD = InceptionD
            inceptionE = InceptionE

        self.aux_logits = aux_logits
        self.transform_input = transform_input
        self.Conv2d_1a_3x3 = BasicConv2d(3, 32, kernel_size=3, stride=2)
        self.Conv2d_2a_3x3 = BasicConv2d(32, 32, kernel_size=3)
        self.Conv2d_2b_3x3 = BasicConv2d(32, 64, kernel_size=3, padding=1)
        self.Conv2d_3b_1x1 = BasicConv2d(64, 80, kernel_size=1)
        self.Conv2d_4a_3x3 = BasicConv2d(80, 192, kernel_size=3)

        self.Mixed_5b = inceptionA(192, pool_features=32, has_mask=has_mask[0:4])
        self.Mixed_5c = inceptionA(sum(filters[0]), pool_features=64, has_mask=has_mask[4:8])
        self.Mixed_5d = inceptionA(sum(filters[1]), pool_features=64, has_mask=has_mask[8:12])
        self.Mixed_6a = inceptionB(sum(filters[2]), has_mask=has_mask[12:14])
        self.Mixed_6b = inceptionC(sum(filters[3]), channels_7x7=128, has_mask=has_mask[14:18])
        self.Mixed_6c = inceptionC(sum(filters[4]), channels_7x7=160, has_mask=has_mask[18:22])
        self.Mixed_6d = inceptionC(sum(filters[5]), channels_7x7=160, has_mask=has_mask[22:26])
        self.Mixed_6e = inceptionC(sum(filters[6]), channels_7x7=192, has_mask=has_mask[26:30])
        if aux_logits:
            self.AuxLogits = InceptionAux(sum(filters[6]), num_classes)
        self.Mixed_7a = inceptionD(sum(filters[7]), has_mask=has_mask[30:32])
        self.Mixed_7b = inceptionE(sum(filters[8]), has_mask=has_mask[32:36])
        self.Mixed_7c = inceptionE(sum(filters[9]), has_mask=has_mask[36:40])
        self.fc = nn.Linear(sum(filters[10]), num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
                import scipy.stats as stats
                stddev = m.stddev if hasattr(m, 'stddev') else 0.1
                X = stats.truncnorm(-2, 2, scale=stddev)
                values = torch.Tensor(X.rvs(m.weight.numel()))
                values = values.view(m.weight.size())
                m.weight.data.copy_(values)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        if self.transform_input:
            x = x.clone()
            x[:, 0] = x[:, 0] * (0.229 / 0.5) + (0.485 - 0.5) / 0.5
            x[:, 1] = x[:, 1] * (0.224 / 0.5) + (0.456 - 0.5) / 0.5
            x[:, 2] = x[:, 2] * (0.225 / 0.5) + (0.406 - 0.5) / 0.5
        # 299 x 299 x 3
        x = self.Conv2d_1a_3x3(x)
        # 149 x 149 x 32
        x = self.Conv2d_2a_3x3(x)
        # 147 x 147 x 32
        x = self.Conv2d_2b_3x3(x)
        # 147 x 147 x 64
        x = F.max_pool2d(x, kernel_size=3, stride=2)
        # 73 x 73 x 64
        x = self.Conv2d_3b_1x1(x)
        # 73 x 73 x 80
        x = self.Conv2d_4a_3x3(x)
        # 71 x 71 x 192
        x = F.max_pool2d(x, kernel_size=3, stride=2)
        # 35 x 35 x 192
        x = self.Mixed_5b(x)
        # 35 x 35 x 256
        x = self.Mixed_5c(x)
        # 35 x 35 x 288
        x = self.Mixed_5d(x)
        # 35 x 35 x 288
        x = self.Mixed_6a(x)
        # print('after Mixed_6a', x.size())
        # 17 x 17 x 768
        x = self.Mixed_6b(x)
        # 17 x 17 x 768
        x = self.Mixed_6c(x)
        # 17 x 17 x 768
        x = self.Mixed_6d(x)
        # 17 x 17 x 768
        x = self.Mixed_6e(x)
        # 17 x 17 x 768
        if self.training and self.aux_logits:
            aux = self.AuxLogits(x)
        # 17 x 17 x 768
        x = self.Mixed_7a(x)
        # 8 x 8 x 1280
        x = self.Mixed_7b(x)
        # 8 x 8 x 2048
        x = self.Mixed_7c(x)
        # 8 x 8 x 2048
        x = F.avg_pool2d(x, kernel_size=8)
        # 1 x 1 x 2048
        x = F.dropout(x, training=self.training)
        # 1 x 1 x 2048
        x = x.view(x.size(0), -1)
        # 2048
        x = self.fc(x)
        # 1000 (num_classes)
        if self.training and self.aux_logits:
            return x, aux
        return x

class InceptionA(nn.Module):

    def __init__(self, in_channels, pool_features, has_mask):
        super(InceptionA, self).__init__()
        self.branch1x1 = BasicConv2d(in_channels, 64, kernel_size=1)

        self.branch5x5_1 = BasicConv2d(in_channels, 48, kernel_size=1)
        self.branch5x5_2 = BasicConv2d(48, 64, kernel_size=5, padding=2)

        self.branch3x3dbl_1 = BasicConv2d(in_channels, 64, kernel_size=1)
        self.branch3x3dbl_2 = BasicConv2d(64, 96, kernel_size=3, padding=1)
        self.branch3x3dbl_3 = BasicConv2d(96, 96, kernel_size=3, padding=1)

        self.branch_pool = BasicConv2d(in_channels, pool_features, kernel_size=1)

    def forward(self, x):
        branch1x1 = self.branch1x1(x)
        # print("A: branch1x1", branch1x1.shape[1])
        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)
        # print("A: branch5x5", branch5x5.shape[1])
        branch3x3dbl = self.branch3x3dbl_1(x)
        branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
        branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)
        # print("A: branch3x3dbl", branch3x3dbl.shape[1])
        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
        branch_pool = self.branch_pool(branch_pool)
        # print("A: branch_pool", branch_pool.shape[1])
        outputs = [branch1x1, branch5x5, branch3x3dbl, branch_pool]
        return torch.cat(outputs, 1)

class SparseInceptionA(InceptionA):
    def __init__(self, in_channels, pool_features, has_mask):
        super(SparseInceptionA, self).__init__(in_channels, pool_features, has_mask)
        m1 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m2 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m3 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m4 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        self.mask1 = Mask(m1)
        self.mask2 = Mask(m2)
        self.mask3 = Mask(m3)
        self.mask4 = Mask(m4)
        self.has_mask = has_mask

    def forward(self, x):
        out = []

        if self.has_mask[0] > 0:
            branch1x1 = self.branch1x1(x)
            branch1x1 = self.mask1(branch1x1)
            out.append(branch1x1)

        if self.has_mask[1] > 0:
            branch5x5 = self.branch5x5_1(x)
            branch5x5 = self.branch5x5_2(branch5x5)
            branch5x5 = self.mask2(branch5x5)
            out.append(branch5x5)

        if self.has_mask[2] > 0:
            branch3x3dbl = self.branch3x3dbl_1(x)
            branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
            branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)
            branch3x3dbl = self.mask3(branch3x3dbl)
            out.append(branch3x3dbl)

        if self.has_mask[3] > 0:
            branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
            branch_pool = self.branch_pool(branch_pool)
            branch_pool = self.mask4(branch_pool)
            out.append(branch_pool)

        # pdb.set_trace()
        return torch.cat(out, 1)

class InceptionB(nn.Module):

    def __init__(self, in_channels, has_mask):
        super(InceptionB, self).__init__()
        self.branch3x3 = BasicConv2d(in_channels, 384, kernel_size=3, stride=2)

        self.branch3x3dbl_1 = BasicConv2d(in_channels, 64, kernel_size=1)
        self.branch3x3dbl_2 = BasicConv2d(64, 96, kernel_size=3, padding=1)
        self.branch3x3dbl_3 = BasicConv2d(96, 96, kernel_size=3, stride=2)

    def forward(self, x):
        branch3x3 = self.branch3x3(x)
        # print("B: branch3x3", branch3x3.shape[1])
        branch3x3dbl = self.branch3x3dbl_1(x)
        branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
        branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)
        # print("B: branch3x3dbl", branch3x3dbl.shape[1])
        branch_pool = F.max_pool2d(x, kernel_size=3, stride=2)
        # print("B: branch_pool", branch_pool.shape[1])
        outputs = [branch3x3, branch3x3dbl, branch_pool]
        return torch.cat(outputs, 1)

class SparseInceptionB(InceptionB):

    def __init__(self, in_channels, has_mask):
        super(SparseInceptionB, self).__init__(in_channels, has_mask)
        m1 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m2 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        self.mask1 = Mask(m1)
        self.mask2 = Mask(m2)
        self.has_mask = has_mask
        # print('SparseIncpetionB',self.has_mask)

    def forward(self, x):
        out = []
        if self.has_mask[0] > 0:
            branch3x3 = self.branch3x3(x)
            branch3x3 = self.mask1(branch3x3)
            # print("B: branch3x3", branch3x3.shape[1])
            out.append(branch3x3)

        if self.has_mask[1] > 0:
            branch3x3dbl = self.branch3x3dbl_1(x)
            branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
            branch3x3dbl = self.branch3x3dbl_3(branch3x3dbl)
            branch3x3dbl = self.mask2(branch3x3dbl)
            # print("B: branch3x3dbl", branch3x3dbl.shape[1])
            out.append(branch3x3dbl)

        # if self.has_mask[2] > 0:
        branch_pool = F.max_pool2d(x, kernel_size=3, stride=2)
        # branch_pool = self.mask3(branch_pool)
        # print("B: branch_pool", branch_pool.shape[1])
        out.append(branch_pool)

        # pdb.set_trace()
        return torch.cat(out, 1)

class InceptionC(nn.Module):
    def __init__(self, in_channels, channels_7x7, has_mask):
        super(InceptionC, self).__init__()
        self.branch1x1 = BasicConv2d(in_channels, 192, kernel_size=1)

        c7 = channels_7x7
        self.branch7x7_1 = BasicConv2d(in_channels, c7, kernel_size=1)
        self.branch7x7_2 = BasicConv2d(c7, c7, kernel_size=(1, 7), padding=(0, 3))
        self.branch7x7_3 = BasicConv2d(c7, 192, kernel_size=(7, 1), padding=(3, 0))

        self.branch7x7dbl_1 = BasicConv2d(in_channels, c7, kernel_size=1)
        self.branch7x7dbl_2 = BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0))
        self.branch7x7dbl_3 = BasicConv2d(c7, c7, kernel_size=(1, 7), padding=(0, 3))
        self.branch7x7dbl_4 = BasicConv2d(c7, c7, kernel_size=(7, 1), padding=(3, 0))
        self.branch7x7dbl_5 = BasicConv2d(c7, 192, kernel_size=(1, 7), padding=(0, 3))

        self.branch_pool = BasicConv2d(in_channels, 192, kernel_size=1)

    def forward(self, x):
        branch1x1 = self.branch1x1(x)
        # print("C: branch1x1", branch1x1.shape[1])
        branch7x7 = self.branch7x7_1(x)
        branch7x7 = self.branch7x7_2(branch7x7)
        branch7x7 = self.branch7x7_3(branch7x7)
        # print("C: branch7x7", branch7x7.shape[1])
        branch7x7dbl = self.branch7x7dbl_1(x)
        branch7x7dbl = self.branch7x7dbl_2(branch7x7dbl)
        branch7x7dbl = self.branch7x7dbl_3(branch7x7dbl)
        branch7x7dbl = self.branch7x7dbl_4(branch7x7dbl)
        branch7x7dbl = self.branch7x7dbl_5(branch7x7dbl)
        # print("C: branch7x7dbl", branch7x7dbl.shape[1])
        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
        branch_pool = self.branch_pool(branch_pool)
        # print("C: branch_pool", branch_pool.shape[1])
        outputs = [branch1x1, branch7x7, branch7x7dbl, branch_pool]
        return torch.cat(outputs, 1)

class SparseInceptionC(InceptionC):
    def __init__(self, in_channels, channels_7x7, has_mask):
        super(SparseInceptionC, self).__init__(in_channels, channels_7x7, has_mask)

        m1 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m2 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m3 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m4 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        self.mask1 = Mask(m1)
        self.mask2 = Mask(m2)
        self.mask3 = Mask(m3)
        self.mask4 = Mask(m4)

        self.has_mask = has_mask

    def forward(self, x):
        out = []
        if self.has_mask[0] > 0:
            branch1x1 = self.branch1x1(x)
            branch1x1 = self.mask1(branch1x1)
            out.append(branch1x1)

        if self.has_mask[1] > 0:
            branch7x7 = self.branch7x7_1(x)
            branch7x7 = self.branch7x7_2(branch7x7)
            branch7x7 = self.branch7x7_3(branch7x7)
            branch7x7 = self.mask2(branch7x7)
            out.append(branch7x7)

        if self.has_mask[2] > 0:
            branch7x7dbl = self.branch7x7dbl_1(x)
            branch7x7dbl = self.branch7x7dbl_2(branch7x7dbl)
            branch7x7dbl = self.branch7x7dbl_3(branch7x7dbl)
            branch7x7dbl = self.branch7x7dbl_4(branch7x7dbl)
            branch7x7dbl = self.branch7x7dbl_5(branch7x7dbl)
            branch7x7dbl = self.mask3(branch7x7dbl)
            out.append(branch7x7dbl)

        if self.has_mask[3] > 0:
            branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
            branch_pool = self.branch_pool(branch_pool)
            branch_pool = self.mask4(branch_pool)
            out.append(branch_pool)

        # pdb.set_trace()
        return torch.cat(out, 1)

class InceptionD(nn.Module):

    def __init__(self, in_channels, has_mask):
        super(InceptionD, self).__init__()
        self.branch3x3_1 = BasicConv2d(in_channels, 192, kernel_size=1)
        self.branch3x3_2 = BasicConv2d(192, 320, kernel_size=3, stride=2)

        self.branch7x7x3_1 = BasicConv2d(in_channels, 192, kernel_size=1)
        self.branch7x7x3_2 = BasicConv2d(192, 192, kernel_size=(1, 7), padding=(0, 3))
        self.branch7x7x3_3 = BasicConv2d(192, 192, kernel_size=(7, 1), padding=(3, 0))
        self.branch7x7x3_4 = BasicConv2d(192, 192, kernel_size=3, stride=2)

    def forward(self, x):
        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        # print("D: branch3x3", branch3x3.shape[1])
        branch7x7x3 = self.branch7x7x3_1(x)
        branch7x7x3 = self.branch7x7x3_2(branch7x7x3)
        branch7x7x3 = self.branch7x7x3_3(branch7x7x3)
        branch7x7x3 = self.branch7x7x3_4(branch7x7x3)
        # print("D: branch7x7x3", branch7x7x3.shape[1])
        branch_pool = F.max_pool2d(x, kernel_size=3, stride=2)
        # print("D: branch_pool", branch_pool.shape[1])
        outputs = [branch3x3, branch7x7x3, branch_pool]
        return torch.cat(outputs, 1)

class SparseInceptionD(InceptionD):

    def __init__(self, in_channels, has_mask):
        super(SparseInceptionD, self).__init__(in_channels, has_mask)
        m1 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m2 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        self.mask1 = Mask(m1)
        self.mask2 = Mask(m2)
        # self.mask3 = Mask()
        self.has_mask = has_mask

    def forward(self, x):
        out = []
        if self.has_mask[0] > 0:
            branch3x3 = self.branch3x3_1(x)
            branch3x3 = self.branch3x3_2(branch3x3)
            branch3x3 = self.mask1(branch3x3)
            out.append(branch3x3)

        if self.has_mask[1] > 0:
            branch7x7x3 = self.branch7x7x3_1(x)
            branch7x7x3 = self.branch7x7x3_2(branch7x7x3)
            branch7x7x3 = self.branch7x7x3_3(branch7x7x3)
            branch7x7x3 = self.branch7x7x3_4(branch7x7x3)
            branch7x7x3 = self.mask2(branch7x7x3)
            out.append(branch7x7x3)

        # if self.has_mask[2] > 0:
        branch_pool = F.max_pool2d(x, kernel_size=3, stride=2)
        out.append(branch_pool)

        # pdb.set_trace()
        return torch.cat(out, 1)

class InceptionE(nn.Module):

    def __init__(self, in_channels, has_mask):
        super(InceptionE, self).__init__()
        self.branch1x1 = BasicConv2d(in_channels, 320, kernel_size=1)

        self.branch3x3_1 = BasicConv2d(in_channels, 384, kernel_size=1)
        self.branch3x3_2a = BasicConv2d(384, 384, kernel_size=(1, 3), padding=(0, 1))
        self.branch3x3_2b = BasicConv2d(384, 384, kernel_size=(3, 1), padding=(1, 0))

        self.branch3x3dbl_1 = BasicConv2d(in_channels, 448, kernel_size=1)
        self.branch3x3dbl_2 = BasicConv2d(448, 384, kernel_size=3, padding=1)
        self.branch3x3dbl_3a = BasicConv2d(384, 384, kernel_size=(1, 3), padding=(0, 1))
        self.branch3x3dbl_3b = BasicConv2d(384, 384, kernel_size=(3, 1), padding=(1, 0))

        self.branch_pool = BasicConv2d(in_channels, 192, kernel_size=1)

    def forward(self, x):
        branch1x1 = self.branch1x1(x)
        # print("E: branch1x1", branch1x1.shape[1])
        branch3x3 = self.branch3x3_1(x)
        branch3x3 = [
            self.branch3x3_2a(branch3x3),
            self.branch3x3_2b(branch3x3),
        ]
        branch3x3 = torch.cat(branch3x3, 1)
        # print("E: branch3x3", branch3x3.shape[1])
        branch3x3dbl = self.branch3x3dbl_1(x)
        branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
        branch3x3dbl = [
            self.branch3x3dbl_3a(branch3x3dbl),
            self.branch3x3dbl_3b(branch3x3dbl),
        ]
        branch3x3dbl = torch.cat(branch3x3dbl, 1)
        # print("E: branch3x3dbl", branch3x3dbl.shape[1])
        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
        branch_pool = self.branch_pool(branch_pool)
        # print("E: branch_pool", branch_pool.shape[1])
        outputs = [branch1x1, branch3x3, branch3x3dbl, branch_pool]
        return torch.cat(outputs, 1)

class SparseInceptionE(InceptionE):

    def __init__(self, in_channels, has_mask):
        super(SparseInceptionE, self).__init__(in_channels, has_mask)
        m1 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m2 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m3 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        m4 = Normal(torch.tensor([norm_mean]), torch.tensor([norm_var])).sample()
        self.mask1 = Mask(m1)
        self.mask2 = Mask(m2)
        self.mask3 = Mask(m3)
        self.mask4 = Mask(m4)

        self.has_mask = has_mask

    def forward(self, x):
        out = []
        if self.has_mask[0] > 0:
            branch1x1 = self.branch1x1(x)
            branch1x1 = self.mask1(branch1x1)
            out.append(branch1x1)

        if self.has_mask[1] > 0:
            branch3x3 = self.branch3x3_1(x)
            branch3x3 = [
                self.branch3x3_2a(branch3x3),
                self.branch3x3_2b(branch3x3),
            ]
            branch3x3 = torch.cat(branch3x3, 1)
            branch3x3 = self.mask2(branch3x3)
            out.append(branch3x3)

        if self.has_mask[2] > 0:
            branch3x3dbl = self.branch3x3dbl_1(x)
            branch3x3dbl = self.branch3x3dbl_2(branch3x3dbl)
            branch3x3dbl = [
                self.branch3x3dbl_3a(branch3x3dbl),
                self.branch3x3dbl_3b(branch3x3dbl),
            ]
            branch3x3dbl = torch.cat(branch3x3dbl, 1)
            branch3x3dbl = self.mask3(branch3x3dbl)
            out.append(branch3x3dbl)

        # pdb.set_trace()

        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)

        if self.has_mask[3] > 0:
            branch_pool = self.branch_pool(branch_pool)
            branch_pool = self.mask4(branch_pool)
            out.append(branch_pool)

        return torch.cat(out, 1)

class InceptionAux(nn.Module):

    def __init__(self, in_channels, num_classes):
        super(InceptionAux, self).__init__()
        self.conv0 = BasicConv2d(in_channels, 128, kernel_size=1)
        self.conv1 = BasicConv2d(128, 768, kernel_size=5)
        self.conv1.stddev = 0.01
        self.fc = nn.Linear(768, num_classes)
        self.fc.stddev = 0.001

    def forward(self, x):
        # 17 x 17 x 768
        x = F.avg_pool2d(x, kernel_size=5, stride=3)
        # 5 x 5 x 768
        x = self.conv0(x)
        # 5 x 5 x 128
        x = self.conv1(x)
        # 1 x 1 x 768
        x = x.view(x.size(0), -1)
        # 768
        x = self.fc(x)
        # 1000
        return x

class BasicConv2d(nn.Module):

    def __init__(self, in_channels, out_channels, **kwargs):
        super(BasicConv2d, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)
        self.bn = nn.BatchNorm2d(out_channels, eps=0.001)

    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        return F.relu(x, inplace=True)

class Mask(nn.Module):
    def __init__(self, init_value=[1]):
        super().__init__()
        self.weight = Parameter(torch.Tensor(init_value))

    def forward(self, input):
        return input * self.weight

def inception_v3(pretrained=False, **kwargs):
    if pretrained:
        if 'transform_input' not in kwargs:
            kwargs['transform_input'] = True
        model = Inception3(**kwargs)
        load_url = model_zoo.load_url(model_urls['inception_v3_google'])
        new_state_dict= {}
        for k, v in load_url.items():
            if 'AuxLogits' not in k:
                new_state_dict[k] = v
        model.load_state_dict(new_state_dict)
        return model, new_state_dict

    return Inception3(**kwargs)

def inception_v3_sparse(pretrained=False, **kwargs):
    return Inception3(is_sparse=True, **kwargs)

# def test():
#     index = [1, 3, 5, 10, 25]
#     mask = np.ones(42)
#     mask[index] = 0
#     net = inception_v3_sparse(has_mask=mask)
#     input = Variable(torch.randn(3,3,299,299))
#     logits = net(input)
#     print(logits.size())

# test()


import requests
import json
import time

rest_endpoint = "http://127.0.0.1:8080/motion/"
experiment_id = "NA"
sensorType = "NA"
inputDeviceId = "NA"
sensor_location = "NA"
exercise = "NA"
subject = "NA"

def make_post_call():
    data = {
        'xRoll': 0.1,
        'yPitch': 0.2,
        'zYaw': 0.3,
        'experimentId': experiment_id,
        'type': sensorType,
        'sensorLocation': sensor_location,
        'subject': subject,
        'isRaw': False,
        'timestamp': round(time.time() * 1000),
        'deviceId': inputDeviceId
    }
    requests.post(rest_endpoint, json=data)

while (True):
    make_post_call()
    time.sleep(.3)


import torch
from torch import nn
import numpy as np
import matplotlib
import matplotlib.pyplot as plt

import sklearn
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from helper_functions import accuracy_fn, plot_predictions, plot_decision_boundary

# Set hyperparams for datasets
NUM_CLASSES = 4
NUM_FEATURES = 2
RANDOM_SEED = 42
EPOCHS = 100
LEARNING_RATE = 0.1

# 1. CREATE MULTICLASS DATA: https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html
X_blob, y_blob = make_blobs(n_samples=1000,
                             n_features=NUM_FEATURES,
                            centers=NUM_CLASSES,
                            cluster_std=1.5,
                            random_state=RANDOM_SEED)

# 2. TURN DATA INTO TENSORS and split train test: https://pytorch.org/docs/stable/generated/torch.from_numpy.html
X_blob = torch.from_numpy(X_blob).type(torch.float32)
y_blob = torch.from_numpy(y_blob).type(torch.LongTensor) # need longTensor

X_blob_train, X_blob_test, y_blob_train, y_blob_test = train_test_split(X_blob, # will be shape of (batchsize, # features)
                                                                        y_blob, # will be shape of (batchsize), determining using argmax, which class it is likely to be
                                                                        test_size=0.2,
                                                                        random_state=RANDOM_SEED)

# 3. Visualize data
plt.figure(figsize=(10, 7))
plt.scatter(X_blob[:, 0], X_blob[:, 1], c=y_blob, cmap=plt.cm.RdYlBu)
plt.show()

# print(X_blob.shape, y_blob.shape) X has 2 features (input node features), and y is a scalar (means we have to squeeze later to match y_blob_preds)
# https://pytorch.org/docs/stable/generated/torch.unique.html
# print(torch.unique(y_blob_train)) shows that y has 4 unique values, 4 different classes
# plt.show()

# 4. Building multiclass classification model
class BlobModel(nn.Module):
    def __init__(self, input_features, output_features, hidden_units=8):
        super().__init__()
        # passes through sequentially
        self.linear_layer_stack = nn.Sequential(
            nn.Linear(in_features=input_features, out_features=hidden_units),
            nn.ReLU(),
            nn.Linear(in_features=hidden_units, out_features=hidden_units),
            nn.ReLU(),
            nn.Linear(in_features=hidden_units, out_features=output_features)
        )

    def forward(self, x):
        return self.linear_layer_stack(x)

torch.manual_seed(RANDOM_SEED)
model_4 = BlobModel(input_features=2, output_features=4)
print(model_4)

# 5. Create loss fn, optimizer, and training loop
loss_fn = nn.CrossEntropyLoss() # the params are not same shape here since its multiclass classification
optimizer = torch.optim.SGD(params=model_4.parameters(),
                            lr=LEARNING_RATE)

# y_logits = model_4(X_blob_train).squeeze()
# y_preds = torch.softmax(y_logits, dim=1).argmax(dim=1)

torch.manual_seed(RANDOM_SEED)
for epoch in range(EPOCHS):
    model_4.train()
    # need to convert logits(model) -> preds(softmax) -> labels(argmax)
    y_logits = model_4(X_blob_train)

    # https://pytorch.org/docs/stable/generated/torch.nn.Softmax.html
    # Softmax performs the operations on the given dimensions. Here, we want the rows to sum to 1, probability, and the rows here are dim=1. If dim=0, then the columns would sum since columns here are dim=0.
    y_preds = torch.softmax(y_logits, dim=1).argmax(dim=1)

    loss = loss_fn(y_logits, y_blob_train) #! internally applies softmax and does CE loss. shapes not the same since mutliclass classification
    acc = accuracy_fn(y_true=y_blob_train,
                      y_pred=y_preds)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    model_4.eval()
    with torch.inference_mode():
        test_logits = model_4(X_blob_test)
        test_preds = torch.softmax(test_logits, dim=1).argmax(dim=1)

        test_loss = loss_fn(test_logits, y_blob_test)
        test_acc = accuracy_fn(y_true=y_blob_test,
                               y_pred=test_preds)

    if epoch % (EPOCHS / 10) == 0:
        print(f"Epoch: {epoch} | Loss: {loss:.5f}, Acc: {acc:.2f}% | Test loss: {test_loss:.5f}, Test acc: {test_acc:.2f}%")


import sys
import time
import torch
from tqdm import tqdm
from torch import optim
from torch.utils.data import DataLoader
from dataset import Dataset
from ema import EMA
from leak_finder import LeakFinder
from utils import get_data
from vae import VariationalAutoEncoder, loss_function

# Configuration
if len(sys.argv) > 1 and sys.argv[1] is not None:
    DEVICE = sys.argv[1]
elif torch.backends.mps.is_available():
    DEVICE = torch.device("mps")
elif torch.cuda.is_available():
    DEVICE = torch.device("cuda")
else:
    DEVICE = torch.device("cpu")

# DEVICE = torch.device("mps") if  else  if  else "cpu")
WINDOW_LENGTH = 30  # h
BATCH_SIZE = 100  # h
LR_RATE = 10e-4  # h
NUM_EPOCHS = 3  # range: any
TEST_DATA = 0.3  # 30% range: 10-100%

RNN_H_DIM = 500
DENSE_DIM = 500
Z_DIM = 3  # h range: 3-10
X_DIM = 38
STD_DEVIATION_EPSILON = 10e-4  # h
NUM_PLANAR_TRANSOFORMS = 20  # h
TIME_AXIS = 1
DENSE_LAYERS = 2  # h

GRAD_REGULARIZATIONLIMIT = 10  # h
L2_REGULARIZATION = 10e-4  # h

TARGET_DECAY = 0.9999  # h range: 0-1
WAVEBOUND_ERROR_DEVIATION = 1e-4  # h range: idk

# Dataset Loading
(x_train, _), (x_test, y_test) = get_data(
    "machine-1-1", None, None, train_start=0, test_start=0
)
data = Dataset(x_train)
train_loader = DataLoader(dataset=data, batch_size=BATCH_SIZE)
# if torch.cuda.is_available() and torch.cuda.device_count() > 2:
#     DEVICE_SOURCE = torch.device("cuda:0")
#     DEVICE_TARGET = torch.device("cuda:1")
#     target_model = VariationalAutoEncoder(X_DIM, RNN_H_DIM, Z_DIM, device=DEVICE).to(
#         DEVICE_TARGET
#     )
#     source_model = VariationalAutoEncoder(X_DIM, RNN_H_DIM, Z_DIM, device=DEVICE).to(
#         DEVICE_SOURCE
#     )
# else:
target_model = VariationalAutoEncoder(X_DIM, RNN_H_DIM, Z_DIM, device=DEVICE).to(DEVICE)
ema = EMA(target_model, TARGET_DECAY)
ema.register()
source_model = VariationalAutoEncoder(X_DIM, RNN_H_DIM, Z_DIM, device=DEVICE).to(DEVICE)
target_optimizer = optim.Adam(target_model.parameters(), lr=LR_RATE)
source_optimizer = optim.Adam(source_model.parameters(), lr=LR_RATE)

epoch_times = []
avg_loss = 0
loss_stats = {"train": [], "val": []}  # for early stop

target_model.train()
source_model.train()

for epoch in range(1, NUM_EPOCHS + 1):
    loop = tqdm(enumerate(train_loader))
    start_time = time.process_time()
    for counter, data in loop:
        batch = torch.as_tensor(data, device=DEVICE)
        record_time = 0
        record_times = []
        for record in batch:  # BATCH_SIZE
            record_time = time.process_time()
            x_t, z, mu_z, logvar_z = target_model(record)
            s_x_t, s_z, s_mu_z, s_logvar_z = source_model(record)

            source_optimizer.zero_grad()
            source_loss = loss_function(
                record,
                s_x_t.squeeze(),
                s_mu_z.squeeze(),
                s_logvar_z.squeeze(),
                s_z.squeeze(),
                source_model,
                L2_REGULARIZATION,
            )
            source_loss.backward(inputs=list(source_model.parameters()))
            source_optimizer.step()

            target_optimizer.zero_grad()
            target_loss = loss_function(
                record,
                x_t.squeeze(),
                mu_z.squeeze(),
                logvar_z.squeeze(),
                z.squeeze(),
                target_model,
                L2_REGULARIZATION,
            )
            target_loss.backward(inputs=list(target_model.parameters()))
            target_optimizer.step()

            # Backprop
            with torch.no_grad():
                ema.update()
                ema.apply_shadow()
                # Move the in-place operation out of the `with torch.no_grad()` block
                for source_params, target_params in zip(
                    source_model.parameters(), target_model.parameters()
                ):
                    target_params.data = (
                        TARGET_DECAY * target_params.data
                        + (1 - TARGET_DECAY) * source_params.data
                    )

            # Delete to reduce memory consumption
            del record, source_params, target_params
            del x_t, z, mu_z, logvar_z
            del s_x_t, s_z, s_mu_z, s_logvar_z
            record_times.append(time.process_time() - record_time)

        loop.set_postfix(source_loss=source_loss.item())
        avg_loss += target_loss.item()
        print(
            "\nEpoch {} | Step: {}/{} | AvrgEpoch: {} | Batch: {} | {:.2f}s".format(
                epoch,
                (counter + 1),
                len(train_loader),
                avg_loss / (counter + 1),
                target_loss.item(),
                sum(record_times),
            )
        )

        del source_loss, target_loss, batch
        torch.cuda.empty_cache()  # try empty cache

    current_time = time.process_time()
    epoch_times.append(current_time - start_time)
    print(
        "Epoch {}/{} Done, Total Loss: {}, Done in {}s".format(
            epoch, NUM_EPOCHS, avg_loss / len(train_loader), current_time - start_time
        )
    )

print("Total Training Time: {} seconds".format(str(sum(epoch_times))))