"""Test fixtures for kernels."""

from typing import Dict

import numpy as np
import pytest

from probnum.quad.integration_measures import (
    GaussianMeasure,
    IntegrationMeasure,
    LebesgueMeasure,
)
from probnum.quad.kernel_embeddings import KernelEmbedding
from probnum.randprocs import kernels

# pylint: disable=unnecessary-lambda

@pytest.fixture(
    params=[pytest.param(seed, id=f"seed{seed}") for seed in range(1)],
    name="rng",
)
def fixture_rng(request):
    """Random state(s) used for test parameterization."""
    return np.random.default_rng(seed=request.param)

@pytest.fixture(
    params=[pytest.param(num_data, id=f"ndata{num_data}") for num_data in [1, 2, 20]],
    name="num_data",
)
def fixture_num_data(request) -> int:
    """Size of the dataset."""
    return request.param

@pytest.fixture(
    params=[
        pytest.param(input_dim, id=f"dim{input_dim}") for input_dim in [1, 2, 3, 5]
    ],
    name="input_dim",
)
def fixture_input_dim(request) -> int:
    """Input dimension of the covariance function."""
    return request.param

# Datasets
@pytest.fixture(name="x")
def fixture_x(input_dim: int, num_data: int, rng: np.random.Generator) -> np.ndarray:
    """Random data from a standard normal distribution."""
    return rng.normal(0, 1, size=(num_data, input_dim))

# Measures
@pytest.fixture(
    params=[
        pytest.param(diagonal, id="covdiag" if diagonal else "covfull")
        for diagonal in [True, False]
    ],
    name="cov_diagonal",
)
def fixture_diagonal(request) -> str:
    """Possible forms of the covariance matrix."""
    return request.param

@pytest.fixture(
    params=[pytest.param(name, id=name) for name in ["gauss", "lebesgue"]],
    name="measure_name",
)
def fixture_measure_names(request) -> str:
    """Pedestrian way to deal with integration measures."""
    return request.param

@pytest.fixture(name="measure_params")
def fixture_measure_params(
    measure_name: str,
    input_dim: int,
    cov_diagonal: bool,
    rng: np.random.Generator,
) -> Dict:
    params = {"name": measure_name}

    if measure_name == "gauss":
        # set up mean and covariance
        if input_dim == 1:
            mean = rng.normal(0, 1)
            cov = rng.uniform(0.5, 1.5)
        else:
            mean = rng.normal(0, 1, size=(input_dim, 1))
            if cov_diagonal:
                cov = np.diag(rng.uniform(0.5, 1.5, size=(input_dim,)))
            else:
                mat = rng.normal(0, 1, size=(input_dim, input_dim))
                cov = mat @ mat.T

        params["mean"] = mean
        params["cov"] = cov

    elif measure_name == "lebesgue":
        # set up bounds
        rv = rng.uniform(0, 1, size=(input_dim, 2))
        domain = (rv[:, 0] - 1.0, rv[:, 1] + 1.0)

        params["domain"] = domain
        params["normalized"] = True

    return params

@pytest.fixture(name="measure")
def fixture_measure(measure_params) -> IntegrationMeasure:
    """Measure."""
    name = measure_params.pop("name")

    if name == "gauss":
        return GaussianMeasure(**measure_params)
    elif name == "lebesgue":
        return LebesgueMeasure(**measure_params)
    raise NotImplementedError

# Kernels
@pytest.fixture(
    params=[
        pytest.param(kerndef, id=kerndef[0].__name__)
        for kerndef in [
            (kernels.ExpQuad, {"lengthscales": 1.25}),
        ]
    ],
    name="kernel",
)
def fixture_kernel(request, input_dim: int) -> kernels.Kernel:
    """Kernel / covariance function."""
    return request.param[0](**request.param[1], input_shape=(input_dim,))

# Kernel Embeddings
@pytest.fixture(name="kernel_embedding")
def fixture_kernel_embedding(
    request, kernel: kernels.Kernel, measure: IntegrationMeasure
) -> KernelEmbedding:
    """Set up kernel embedding."""
    return KernelEmbedding(kernel, measure)

# Test functions
@pytest.fixture(
    params=[
        pytest.param(fun, id=f"f={key}")
        for key, fun in {
            "x": lambda x: x,
            "x**2": lambda x: x**2,
            "sin(x)": lambda x: np.sin(x),
        }.items()
    ],
    name="f1d",
)
def fixture_f1d(request):
    """1D test function for BQ."""
    return request.param

# Matern kernels
@pytest.fixture(
    params=[
        pytest.param(matern_nu, id=f"nu={matern_nu}")
        for matern_nu in [0.5, 1.5, 2.5, 3.5]
    ],
    name="matern_nu",
)
def fixture_matern_nu(request) -> int:
    """Input dimension of the covariance function."""
    return request.param

@pytest.fixture(
    params=[
        pytest.param(matern_lengthscale, id=f"lengthscales={matern_lengthscale}")
        for matern_lengthscale in [0.8, 1.0, 1.25]
    ],
    name="matern_lengthscale",
)
def fixture_matern_lengthscale(request) -> int:
    """Input dimension of the covariance function."""
    return request.param

@pytest.fixture(name="matern_kernel")
def fixture_matern_kernel(
    request, input_dim: int, matern_nu: float, matern_lengthscale: float
) -> kernels.Kernel:
    """Set up Matern kernel."""
    return kernels.ProductMatern(
        input_shape=(input_dim,), nus=matern_nu, lengthscales=matern_lengthscale
    )


import time
from datetime import datetime, timedelta, timezone
import logging
import sys
import math

if (len(sys.argv) < 2):
	exit()
now = datetime.now()
zone_cn = timezone(timedelta(hours=8))
now_cn = now.astimezone(zone_cn)
logging.warning(f'服务器时间：{now}, 北京时间：{now_cn}')
logging.warning(now_cn.hour)
target_hour = -1
hour = now_cn.hour
if (len(sys.argv) == 2 and "-" in sys.argv[1]):
	hs = sys.argv[1].split("-")
	if hour+1 >= int(hs[0]) and hour+1 <= int(hs[1]):
		target_hour = hour+1
else :
	for i in range(1, len(sys.argv)):
		if (hour < int(sys.argv[i])):
			target_hour = int(sys.argv[i])
			break

if target_hour == -1:
	logging.error(f'木有匹配到对应的参数: {sys.argv[1:]}')
	exit()
logging.warning(f'匹配到的参数为: {target_hour}')

if target_hour == 24:
	target_hour = 0
target_time = now_cn.replace(hour=target_hour,minute=0, second=0, microsecond=0)
if target_hour == 0:
	target_time = target_time + timedelta(days=1)
logging.warning(f'当前时间: {now_cn}, 目标时间: {target_time}')

td = target_time - now_cn
if td.seconds > 3600:
	logging.error('时间差大于1小时，退出')
	exit()
logging.warning(f'需要沉睡：{td.seconds}秒')
wait = td.seconds+math.floor(td.microseconds/1000)/1000
time.sleep(wait)
logging.warning(f'当前北京时间：{datetime.now().astimezone(zone_cn)}')


import sys, random, time, os
import random
import pygame
import tkinter as tk
from tkinter import messagebox

#CONSTANTS SCREEN WIDTH AND HEIGHT
WIDTH = 500
HEIGHT = 500
ROWS = 20
WHITE = (255,255,255)
RED = (255,0,0)
BLACK = (0,0,0)
YELLOW = (255,255,0)
GREEN = (0,255,0)
FPS = 20 # FPS for the game
CLOCK = pygame.time.Clock()
FRUIT_WIDTH = 50
FRUIT_HEIGHT = 50
SNAKE_SIZE = 10

#FRUIT
BANANA = pygame.transform.scale(pygame.image.load(os.path.join('assets','banana.jpg')),(30,30))

# INITIATE PYGAME
pygame.init()
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Snake Game')

def draw_window():
    global snake, fruit
    WIN.fill(BLACK)
    draw_grid(WIDTH,ROWS)
    snake.draw_snake()
    fruit.draw(WIN)
    pygame.display.update()

def draw_grid(width, row):
    size_between = WIDTH//ROWS
    x = 0
    y=0
    for i in range(ROWS):
        x = x + size_between
        y = y + size_between
        pygame.draw.line(WIN,(255,255,255), (x,0),(x,WIDTH))
        pygame.draw.line(WIN,(255,255,255), (0,y),(WIDTH, y))

def randomize_fruit(rows, snake):
    # print(positions)
    positions = snake.body

    while True:
        x = random.randrange(rows)
        y = random.randrange(rows)
        if len(list(filter(lambda z: z.pos==(x,y),positions))) > 0:
            continue
        else:
            break
    return (x,y)

def message_box(subject,content):
    root = tk.Tk()
    root.attributes("-topmost",True)
    root.withdraw()
    messagebox.showinfo(subject,content)
    try:
        root.destroy()
    except:
        pass

class Cube: # use to represent the snake
    rows = 20
    w = 500
    def __init__(self, start, _dirnx=1, _dirny=0, color=RED):
        self.pos = start
        self._dirnx = _dirnx
        self._dirny = _dirny
        self.color = color

    def move(self, _dirnx, _dirny):
        self._dirnx = _dirnx
        self._dirny = _dirny
        self.pos = (self.pos[0]+ self._dirnx, self.pos[1]+self._dirny)

    def draw(self, surface=WIN, eyes= False):
        dis = self.w // self.rows
        i = self.pos[0]
        j = self.pos[1]

        pygame.draw.rect(surface, self.color,(i*dis+1, j*dis+1,dis-2,dis-2) )
        if eyes:
            centre = dis//2
            radius = 3
            circleMiddle = (i*dis+centre-radius,j*dis+8)
            circleMiddle2 = (i*dis + dis -radius*2, j*dis+8)
            pygame.draw.circle(WIN, (0,0,0), circleMiddle, radius)
            pygame.draw.circle(WIN, (0,0,0), circleMiddle2, radius)

class Snake:
    body = []
    turns = {} #REMEMBER THE POSITION WHERE THE SNAKE TURNS
    def __init__(self,color,pos):
        self.color = color
        self.head = Cube(pos)
        self.body.append(self.head)
        #SETTING THE DIRECTION OF THE SNAKE
        self._dirnx = 0
        self._dirny = 0
    def move(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()

            key_pressed = pygame.key.get_pressed()
            for key in key_pressed:
                if key_pressed[pygame.K_a]:
                    self._dirnx = -1
                    self._dirny = 0
                    self.turns[self.head.pos[:]] = [self._dirnx, self._dirny]
                elif key_pressed[pygame.K_s]:
                    self._dirnx = 0
                    self._dirny = 1
                    self.turns[self.head.pos[:]] = [self._dirnx, self._dirny]
                elif key_pressed[pygame.K_d]:
                    self._dirnx = 1
                    self._dirny = 0
                    self.turns[self.head.pos[:]] = [self._dirnx, self._dirny]
                elif key_pressed[pygame.K_w]:
                    self._dirnx = 0
                    self._dirny = -1
                    self.turns[self.head.pos[:]] = [self._dirnx, self._dirny]

        #MAKE OTHER PART OF THE SNAKE TURN AT THE INDICATED POSITION
        for i, c in enumerate(self.body):
            p = c.pos[:]
            if p in self.turns:
                turn = self.turns[p]
                c.move(turn[0],turn[1])
                if i == len(self.body)-1:
                    self.turns.pop(p)
            else:
                if c._dirnx == -1 and c.pos[0]<=0 : c.pos = (c.rows-1, c.pos[1])
                elif c._dirnx == 1 and c.pos[0]>=c.rows-1:c.pos=(0,c.pos[1])
                elif c._dirny == 1 and c.pos[1]>=c.rows-1:c.pos=(c.pos[0],0)
                elif c._dirny == -1 and c.pos[1] <= 0: c.pos=(c.pos[0],c.rows-1)
                else:
                    c.move(c._dirnx,c._dirny )
    def draw_snake(self):
        for i,c in enumerate(self.body):
            if i == 0:
                c.draw(WIN,eyes=True)
            else:
                c.draw(WIN)
    def addCube(self):
        tail = self.body[-1]
        dx,dy = tail._dirnx, tail._dirny
        if dx ==1 and dy ==0:
            self.body.append(Cube((tail.pos[0]-1,tail.pos[1])))
        elif dx==-1 and dy==0:
            self.body.append(Cube((tail.pos[0]+1,tail.pos[1])))
        elif dx==0 and dy==1:
            self.body.append(Cube((tail.pos[0],tail.pos[1]-1)))
        elif dx==0 and dy==-1:
            self.body.append(Cube((tail.pos[0],tail.pos[1]+1)))

        self.body[-1]._dirnx = dx
        self.body[-1]._dirny = dy
    def reset(self,pos):
        self.head = Cube(pos)
        self.body=[]
        self.body.append(self.head)
        self.turns = {}
        self._dirnx = 1
        self._dirny = 0

def main():

    global snake, fruit
    game = True
    fruit_rec = pygame.Rect(50,50, FRUIT_WIDTH, FRUIT_WIDTH)
    snake = Snake((255,0,0),(10,10))
    fruit = Cube(randomize_fruit(ROWS,snake), color=GREEN)
    direction = "right"
    while game:
        pygame.time.delay(80)
        CLOCK.tick(FPS)
        snake.move()
        if snake.body[0].pos == fruit.pos:
            snake.addCube()
            fruit = Cube(randomize_fruit(ROWS,snake),color=(0,255,0))
        for x in range(len(snake.body)):
            if snake.body[x].pos in list(map(lambda z: z.pos,snake.body[x+1:])):
                print("Score: ",len(snake.body))
                message_box('You Lost!', 'Play Again')
                snake.reset((10,10))
                break

        draw_window()

if __name__ == "__main__":
    main()


#!/usr/bin/env python3

#####################################################################
# This script presents how to play a deathmatch game with built-in bots.
#####################################################################

import itertools as it
import os
import random
from collections import deque
from time import sleep, time

import numpy as np
import skimage.transform
import torch
import torch.nn as nn
import torch.optim as optim
import vizdoom as vzd
from tqdm import trange

from Agents.DQN import DQNAgent
import rewards

# Q-learning settings
learning_rate = 0.00025
discount_factor = 0.99
train_epochs = 1
learning_steps_per_epoch = 2000
replay_memory_size = 10000

# NN learning settings
batch_size = 64

# Training regime
test_episodes_per_epoch = 100

# Other parameters
frame_repeat = 4
resolution = (30, 45)
episodes_to_watch = 10

model_savefile = "./model-doom.pth"
save_model = True
load_model = False
skip_learning = False

if torch.cuda.is_available():
    DEVICE = torch.device("cuda")
    torch.backends.cudnn.benchmark = True
else:
    DEVICE = torch.device("cpu")

def preprocess(img):
    """Down samples image to resolution"""
    img = skimage.transform.resize(img, resolution)
    img = img.astype(np.float32)
    img = np.expand_dims(img, axis=0)
    return img

# class DuelQNet(nn.Module):
#     """
#     This is Duel DQN architecture.
#     see https://arxiv.org/abs/1511.06581 for more information.
#     """

#     def __init__(self, available_actions_count):
#         super().__init__()
#         self.conv1 = nn.Sequential(
#             nn.Conv2d(1, 8, kernel_size=3, stride=2, bias=False),
#             nn.BatchNorm2d(8),
#             nn.ReLU(),
#         )

#         self.conv2 = nn.Sequential(
#             nn.Conv2d(8, 8, kernel_size=3, stride=2, bias=False),
#             nn.BatchNorm2d(8),
#             nn.ReLU(),
#         )

#         self.conv3 = nn.Sequential(
#             nn.Conv2d(8, 8, kernel_size=3, stride=1, bias=False),
#             nn.BatchNorm2d(8),
#             nn.ReLU(),
#         )

#         self.conv4 = nn.Sequential(
#             nn.Conv2d(8, 16, kernel_size=3, stride=1, bias=False),
#             nn.BatchNorm2d(16),
#             nn.ReLU(),
#         )

#         self.state_fc = nn.Sequential(nn.Linear(96, 64), nn.ReLU(), nn.Linear(64, 1))

#         self.advantage_fc = nn.Sequential(
#             nn.Linear(96, 64), nn.ReLU(), nn.Linear(64, available_actions_count)
#         )

#     def forward(self, x):
#         x = self.conv1(x)
#         x = self.conv2(x)
#         x = self.conv3(x)
#         x = self.conv4(x)
#         x = x.view(-1, 192)
#         x1 = x[:, :96]  # input for the net to calculate the state value
#         x2 = x[:, 96:]  # relative advantage of actions in the state
#         state_value = self.state_fc(x1).reshape(-1, 1)
#         advantage_values = self.advantage_fc(x2)
#         x = state_value + (
#             advantage_values - advantage_values.mean(dim=1).reshape(-1, 1)
#         )

#         return x

# class DQNAgent:
#     def __init__(
#         self,
#         action_size,
#         memory_size,
#         batch_size,
#         discount_factor,
#         lr,
#         load_model,
#         epsilon=1,
#         epsilon_decay=0.9996,
#         epsilon_min=0.1,
#     ):
#         self.action_size = action_size
#         self.epsilon = epsilon
#         self.epsilon_decay = epsilon_decay
#         self.epsilon_min = epsilon_min
#         self.batch_size = batch_size
#         self.discount = discount_factor
#         self.lr = lr
#         self.memory = deque(maxlen=memory_size)
#         self.criterion = nn.MSELoss()

#         if load_model:
#             print("Loading model from: ", model_savefile)
#             self.q_net = torch.load(model_savefile)
#             self.target_net = torch.load(model_savefile)
#             self.epsilon = self.epsilon_min

#         else:
#             print("Initializing new model")
#             self.q_net = DuelQNet(action_size).to(DEVICE)
#             self.target_net = DuelQNet(action_size).to(DEVICE)

#         self.opt = optim.SGD(self.q_net.parameters(), lr=self.lr)

#     def get_action(self, state):
#         if np.random.uniform() < self.epsilon:
#             return random.choice(range(self.action_size))
#         else:
#             state = np.expand_dims(state, axis=0)
#             state = torch.from_numpy(state).float().to(DEVICE)
#             action = torch.argmax(self.q_net(state)).item()
#             return action

#     def update_target_net(self):
#         self.target_net.load_state_dict(self.q_net.state_dict())

#     def append_memory(self, state, action, reward, next_state, done):
#         self.memory.append((state, action, reward, next_state, done))

#     def train(self):
#         batch = random.sample(self.memory, self.batch_size)
#         batch = np.array(batch, dtype=object)

#         states = np.stack(batch[:, 0]).astype(float)
#         actions = batch[:, 1].astype(int)
#         rewards = batch[:, 2].astype(float)
#         next_states = np.stack(batch[:, 3]).astype(float)
#         dones = batch[:, 4].astype(bool)
#         not_dones = ~dones

#         row_idx = np.arange(self.batch_size)  # used for indexing the batch

#         # value of the next states with double q learning
#         # see https://arxiv.org/abs/1509.06461 for more information on double q learning
#         with torch.no_grad():
#             next_states = torch.from_numpy(next_states).float().to(DEVICE)
#             idx = row_idx, np.argmax(self.q_net(next_states).cpu().data.numpy(), 1)
#             next_state_values = self.target_net(next_states).cpu().data.numpy()[idx]
#             next_state_values = next_state_values[not_dones]

#         # this defines y = r + discount * max_a q(s', a)
#         q_targets = rewards.copy()
#         q_targets[not_dones] += self.discount * next_state_values
#         q_targets = torch.from_numpy(q_targets).float().to(DEVICE)

#         # this selects only the q values of the actions taken
#         idx = row_idx, actions
#         states = torch.from_numpy(states).float().to(DEVICE)
#         action_values = self.q_net(states)[idx].float().to(DEVICE)

#         self.opt.zero_grad()
#         td_error = self.criterion(q_targets, action_values)
#         td_error.backward()
#         self.opt.step()

#         if self.epsilon > self.epsilon_min:
#             self.epsilon *= self.epsilon_decay
#         else:
#             self.epsilon = self.epsilon_min

def run(game, agent, actions, episodes, bots, num_epochs, frame_repeat, steps_per_epoch):

    last_frags = 0
    prev_item = 0
    train_scores = []

    for i in range(episodes):

        print("Episode #" + str(i + 1))

        # Add specific number of bots
        # (file examples/bots.cfg must be placed in the same directory as the Doom executable file,
        # edit this file to adjust bots).
        game.send_game_command("removebots")
        for i in range(bots):
            game.send_game_command("addbot")

        # Play until the game (episode) is over.

        # Initialize new reward
        reward = 0
        while not game.is_episode_finished():

            # Get the state.
            state = game.get_state()

            # Analyze the state.

            # Make your action.
            #game.make_action(choice(actions))
            state = preprocess(game.get_state().screen_buffer)
            best_action_index = agent.get_action(state)

            reward = game.make_action(actions[best_action_index], frame_repeat)

            reward += rewards.frag_reward(game, 100, last_frags)
            prev_frag = game.get_game_variable(vzd.GameVariable.FRAGCOUNT)

            reward += rewards.item_reward(game, 20, prev_item)
            prev_item  = game.get_game_variable(vzd.GameVariable.ITEMCOUNT)

            next_state = preprocess(game.get_state().screen_buffer)
            # Update agent rewards
            agent.append_memory(state, actions, reward, next_state, game.is_episode_finished())

            frags = game.get_game_variable(vzd.GameVariable.FRAGCOUNT)
            if frags != last_frags:
                last_frags = frags
                print("Player has " + str(frags) + " frags.")

            items = game.get_game_variable(vzd.GameVariable.ITEMCOUNT)
            if items != prev_item:
                prev_item = items
                print("Player has " + str(items) + " items.")

            # Check if player is dead
            if game.is_player_dead():
                print("Player died.")
                # Use this to respawn immediately after death, new state will be available.
                game.respawn_player()

        print("Episode finished.")
        print("************************")

        print("Results:")
        server_state = game.get_server_state()
        for i in range(len(server_state.players_in_game)):
            if server_state.players_in_game[i]:
                print(
                    server_state.players_names[i]
                    + ": "
                    + str(server_state.players_frags[i])
                )
        print("************************")

        # Starts a new episode. All players have to call new_episode() in multiplayer mode.
        train_scores.append(game.get_total_reward() + reward)
        game.new_episode()

        agent.update_target_net()

        train_scores = np.array(train_scores)

        print(
            "Results: mean: {:.1f} +/- {:.1f},".format(
                train_scores.mean(), train_scores.std()
            ),
            "min: %.1f," % train_scores.min(),
            "max: %.1f," % train_scores.max(),
        )

    if save_model:
        print("Saving the network weights to:", model_savefile)
        torch.save(agent.q_net, model_savefile)

    return agent, game

if __name__ == "__main__":
    game = vzd.DoomGame()

    # Use CIG example config or your own.
    game.load_config(os.path.join(vzd.scenarios_path, "multiplayer_with_bots.cfg"))

    game.set_doom_map("map01")  # Limited deathmatch.
    #game.set_doom_map("map02")  # Full deathmatch.

    # Start multiplayer game only with your AI
    # (with options that will be used in the competition, details in cig_mutliplayer_host.py example).
    game.add_game_args(
        "-host 1 -deathmatch +timelimit 10.0 "
        "+sv_forcerespawn 1 +sv_noautoaim 1 +sv_respawnprotect 1 +sv_spawnfarthest 1 +sv_nocrouch 1 "
        "+viz_respawn_delay 10 +viz_nocheat 1"
    )

    # Bots are loaded from file, that by default is bots.cfg located in the same dir as ViZDoom exe
    # Other location of bots configuration can be specified by passing this argument
    game.add_game_args("+viz_bots_path ../../scenarios/perfect_bots.cfg")

    # Name your agent and select color
    # colors: 0 - green, 1 - gray, 2 - brown, 3 - red, 4 - light gray, 5 - light brown, 6 - light red, 7 - light blue
    game.add_game_args("+name AI +colorset 0")

    game.set_mode(vzd.Mode.PLAYER)
    game.set_console_enabled(True)

    # game.set_window_visible(False)

    game.init()

    # Three example sample actions
    actions = [
        [1, 0, 0, 0, 0, 0, 0, 0],
        [0, 1, 0, 0, 0, 0, 0, 0],
        [0, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 0, 0, 1, 0],
        [0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 1, 0, 0, 0, 0, 0],
        [1, 0, 0, 1, 0, 0, 0, 0]
    ]
    last_frags = 0

    # Play with this many bots
    bots = 7

    # Run this many episodes
    episodes = 10

    # Instantiate DQNAgent
    agent = DQNAgent(
        len(actions),
        lr=learning_rate,
        batch_size=batch_size,
        memory_size=replay_memory_size,
        discount_factor=discount_factor,
        load_model=load_model,
    )

    agent, game = run(
        game,
        agent,
        actions,
        episodes,
        bots,
        5,
        frame_repeat,
        25200
    )

    game.close()


import cv2
import numpy as np
import os

from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
import keras
from keras.models import Sequential, Model
from keras.layers import Dense, Activation, Input
import tensorflow as tf
from keras.utils import to_categorical
from keras.layers import Conv2D, MaxPool2D, Flatten

train_loc = "DataSet"
train_data = tf.keras.preprocessing.image.ImageDataGenerator(horizontal_flip=(True),rescale=(1/255.0),).flow_from_directory(train_loc,batch_size=25,subset=("training"),target_size=(128,128),shuffle=(False))
classes=list(train_data.class_indices.keys())

def detect_face(img):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (128, 128))
    return img
def print_progress(val, val_len, folder, bar_size=20):
    progr = "#"*round((val)*bar_size/val_len) + " "*round((val_len - (val))*bar_size/val_len)
    if val == 0:
        print("", end = "\n")
    else:
        print("[%s] (%d samples)\t label : %s \t\t" % (progr, val+1, folder), end="\r")

dataset_folder = "dataset/"

names = []
images = []
for folder in os.listdir(dataset_folder):
    files = os.listdir(os.path.join(dataset_folder, folder))[:250]
    if len(files) < 100 :
        continue
    for i, name in enumerate(files):
        if name.find(".jpg") > -1 :
            img = cv2.imread(os.path.join(dataset_folder + folder, name))
            img = detect_face(img) # detect face using mtcnn and crop to 100x100
            if img is not None :
                images.append(img)
                names.append(folder)

                print_progress(i, len(files), folder)
print("\nnumber of samples :", len(names))

def img_augmentation(img):
    h, w = img.shape
    center = (w // 2, h // 2)
    M_rot_5 = cv2.getRotationMatrix2D(center, 5, 1.0)
    M_rot_neg_5 = cv2.getRotationMatrix2D(center, -5, 1.0)
    M_rot_10 = cv2.getRotationMatrix2D(center, 10, 1.0)
    M_rot_neg_10 = cv2.getRotationMatrix2D(center, -10, 1.0)
    M_trans_3 = np.float32([[1, 0, 3], [0, 1, 0]])
    M_trans_neg_3 = np.float32([[1, 0, -3], [0, 1, 0]])
    M_trans_6 = np.float32([[1, 0, 6], [0, 1, 0]])
    M_trans_neg_6 = np.float32([[1, 0, -6], [0, 1, 0]])
    M_trans_y3 = np.float32([[1, 0, 0], [0, 1, 3]])
    M_trans_neg_y3 = np.float32([[1, 0, 0], [0, 1, -3]])
    M_trans_y6 = np.float32([[1, 0, 0], [0, 1, 6]])
    M_trans_neg_y6 = np.float32([[1, 0, 0], [0, 1, -6]])

    imgs = []
    imgs.append(cv2.warpAffine(img, M_rot_5, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_rot_neg_5, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_rot_10, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_rot_neg_10, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_3, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_neg_3, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_6, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_neg_6, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_y3, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_neg_y3, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_y6, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.warpAffine(img, M_trans_neg_y6, (w, h), borderValue=(255,255,255)))
    imgs.append(cv2.add(img, 10))
    imgs.append(cv2.add(img, 30))
    imgs.append(cv2.add(img, -10))
    imgs.append(cv2.add(img, -30))
    imgs.append(cv2.add(img, 15))
    imgs.append(cv2.add(img, 45))
    imgs.append(cv2.add(img, -15))
    imgs.append(cv2.add(img, -45))

    return imgs
augmented_images = []
augmented_names = []
for i, img in enumerate(images):
    try :
        augmented_images.extend(img_augmentation(img))
        augmented_names.extend([names[i]] * 20)
    except :
        print(i)
print(len(augmented_images), len(augmented_names))
images.extend(augmented_images)
names.extend(augmented_names)
print(len(images), len(names))

unique, counts = np.unique(names, return_counts = True)

for item in zip(unique, counts):
    print(item)

n = 1000

def randc(labels, l):
    return np.random.choice(np.where(np.array(labels) == l)[0], n, replace=False)

mask = np.hstack([randc(names, l) for l in np.unique(names)])
names = [names[m] for m in mask]
images = [images[m] for m in mask]

print(len(names))

le = LabelEncoder()

le.fit(names)

labels = le.classes_

name_vec = le.transform(names)

categorical_name_vec = to_categorical(name_vec)

print("number of class :", len(labels))
print(labels)
print(name_vec)
print(categorical_name_vec)

x_train, x_test, y_train, y_test = train_test_split(np.array(images, dtype=np.float32),   # input data
                                                    np.array(categorical_name_vec),       # target/output data
                                                    test_size=0.15,
                                                    random_state=42)
print(x_train.shape, y_train.shape, x_test.shape,  y_test.shape)

x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], 1)
x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1)
x_train.shape, x_test.shape

def cnn_model(input_shape):
    model = Sequential()

    model.add(Conv2D(64,
                    (3,3),
                    padding="valid",
                    activation="relu",
                    input_shape=input_shape))
    model.add(Conv2D(64,
                    (3,3),
                    padding="valid",
                    activation="relu",
                    input_shape=input_shape))

    model.add(MaxPool2D(pool_size=(2, 2)))

    model.add(Conv2D(128,
                    (3,3),
                    padding="valid",
                    activation="relu"))
    model.add(Conv2D(128,
                    (3,3),
                    padding="valid",
                    activation="relu"))
    model.add(MaxPool2D(pool_size=(2, 2)))

    model.add(Flatten())

    model.add(Dense(128, activation="relu"))
    model.add(Dense(64, activation="relu"))
    model.add(Dense(len(labels)))  # equal to number of classes
    model.add(Activation("softmax"))

    model.summary()

    model.compile(optimizer='adam',
                  loss='categorical_crossentropy',
                  metrics = ['accuracy'])

    return model

input_shape = x_train[0].shape

EPOCHS = 6
BATCH_SIZE = 32

model = cnn_model(input_shape)

history = model.fit(x_train,
                    y_train,
                    epochs=EPOCHS,
                    batch_size=BATCH_SIZE,
                    shuffle=True,
                    validation_split=0.25   # 15% of train dataset will be used as validation set
                    )
model.save("model-cnn-facerecognition.h5")

y_pred=model.predict(x_test)

print(classification_report(y_test.argmax(axis=1),
                            y_pred.argmax(axis=1),
                            target_names=labels))

from keras.models import load_model
def draw_ped(img, label, x0, y0, xt, yt, color=(255,127,0), text_color=(255,255,255)):

    (w, h), baseline = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
    cv2.rectangle(img,
                  (x0, y0 + baseline),
                  (max(xt, x0 + w), yt),
                  color,
                  2)
    cv2.rectangle(img,
                  (x0, y0 - h),
                  (x0 + w, y0 + baseline),
                  color,
                  -1)
    cv2.putText(img,
                label,
                (x0, y0),
                cv2.FONT_HERSHEY_SIMPLEX,
                0.5,
                text_color,
                1,
                cv2.LINE_AA)
    return img

# --------- load Haar Cascade model -------------
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# --------- load Keras CNN model -------------
model = load_model("model-cnn-facerecognition.h5")
print("[INFO] finish load model...")

cap = cv2.VideoCapture(0)
while cap.isOpened() :
    ret, frame = cap.read()
    if ret:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.1, 5)
        for (x, y, w, h) in faces:

            face_img = gray[y:y+h, x:x+w]
            face_img = cv2.resize(face_img, (128, 128))
            face_img = face_img.reshape(1, 128, 128, 1)

            result = model.predict(face_img)
            idx = result.argmax(axis=1)
            confidence = result.max(axis=1)*100
            if confidence > 80:
                label_text = "%s (%.2f %%)" % (labels[idx], confidence)
            else :
                label_text = "N/A"
            frame = draw_ped(frame, label_text, x, y, x + w, y + h, color=(0,255,255), text_color=(50,50,50))

        cv2.imshow('Detect Face', frame)
    else :
        break
    if cv2.waitKey(10) == ord('q'):
        break

cv2.destroyAllWindows()
cap.release()

Raspberry pi (python)/face recognition/cnnModule.py


import random
import copy
from abc import ABC, abstractmethod
from typing import Dict

class Solution(ABC):
    @abstractmethod
    def mutate(self):
        pass

    @abstractmethod
    def crossover(self, solution: 'Solution'):
        pass

    # @abstractmethod
    # def print_solution(self):
    #     pass

    @abstractmethod
    def fitness(self, constraints, seeded_solution):
        pass

    @abstractmethod
    def optimize(self, greater_constraints, seeded_solution):
        pass

    @abstractmethod
    def get_sol(self):
        pass

class MatrixSolution(Solution):
    def __init__(self, N):
        self.__N = N
        self.__solution = []
        base_permutation = list(range(1, N + 1))  # create list of [1,2,..,N]
        for i in range(N):
            base_permutation_copy = copy.deepcopy(base_permutation)
            random.shuffle(base_permutation_copy)
            self.__solution.append(base_permutation_copy)

    def optimize(self, greater_constraints, seeded_solution):
        """
         optimization -
         1. greater constraints in Row are met
         2. greater constraints in Col are met
         2. seeded solution constraints are met
         """
        sol_copy = copy.deepcopy(self)
        i = 0
        it = iter(greater_constraints)
        try:
            while i < sol_copy.__N:  # allowed up-to N optimization operations
                constraint = next(it)
                if not sol_copy.__greater_sign(constraint):
                    big, small = constraint
                    # make greater sign conform with row
                    if big[0] == small[0]:
                        temp = sol_copy.__solution[big[0] - 1][big[1] - 1]
                        sol_copy.__solution[big[0] - 1][big[1] - 1] = sol_copy.__solution[small[0] - 1][small[1] - 1]
                        sol_copy.__solution[small[0] - 1][small[1] - 1] = temp
                        i += 1
                    else:  # make greater sign conform with col  must swap 4 elements this time
                        swappable1 = sol_copy.__solution[big[0] - 1][big[1] - 1]
                        swappable2 = sol_copy.__solution[small[0] - 1][small[1] - 1]
                        # swap in the first row
                        swap2_idx = sol_copy.__solution[big[0] - 1].index(swappable2)
                        sol_copy.__solution[big[0] - 1][big[1] - 1] = swappable2
                        sol_copy.__solution[big[0] - 1][swap2_idx] = swappable1
                        # swap in the second row
                        swap1_idx = sol_copy.__solution[small[0] - 1].index(swappable1)
                        sol_copy.__solution[small[0] - 1][small[1] - 1] = swappable1
                        sol_copy.__solution[small[0] - 1][swap1_idx] = swappable2
                        i += 1

        except StopIteration:
            for k in range(sol_copy.__N):
                for j in range(sol_copy.__N):
                    if i >= sol_copy.__N:
                        break
                    seed = seeded_solution.__solution[k][j]
                    if seed != 0 and sol_copy.__solution[k][j] != seed:
                        # swap places with where seed is supposed to be
                        idx = sol_copy.__solution[k].index(seed)
                        temp = sol_copy.__solution[k][j]
                        sol_copy.__solution[k][j] = sol_copy.__solution[k][idx]
                        sol_copy.__solution[k][idx] = temp
                        i += 1
                if i >= sol_copy.__N:
                    break
        return sol_copy

    def mutate(self):
        """
        picks a random row to mutate and swap two random elements
        :return copy of current Solution after swapping
        """
        sol_copy = copy.deepcopy(self)
        N = len(self.__solution)
        row = random.choice(range(N))
        cols = random.sample(range(N), 2)  # pick two indexes from that row to be swapped
        temp = sol_copy.__solution[row][cols[0]]
        sol_copy.__solution[row][cols[0]] = sol_copy.__solution[row][cols[1]]
        sol_copy.__solution[row][cols[1]] = temp
        # sol_copy._conform_seed()
        return sol_copy

    def crossover(self, solution: 'MatrixSolution'):
        """
        picks a random row - R.
        Append to grid3 all rows from grid1 until R and all rows from grid2 from R until the end
        :return copy of current Solution after swapping
        """
        sol_copy = copy.deepcopy(self)
        N = len(self.__solution)
        row = random.randint(0, N - 1)
        new_sol = self.__solution[:row]
        new_sol += solution.__solution[row:]
        sol_copy.__solution = new_sol
        # sol_copy._conform_seed()
        return sol_copy

    def __consistent(self, solution):
        """ returns num of diff elements in each row. Best case is 0 when each row is a permutation """
        return sum(self.__N - len(set(row)) for row in solution)

    def __compare_to_seed(self, seeded_solution: 'MatrixSolution'):
        """ count number of mismatches between initial seeded solution with current solution """
        count = 0
        for seed_row, row in zip(seeded_solution.__solution, self.__solution):
            for x_sr, x_r in zip(seed_row, row):
                if x_sr:  # when x_sr == 0 -> no seed
                    if x_sr != x_r:  # mismatch
                        count += 1
        return count

    def fitness(self, greater_constraints, seeded_solution):
        """ our fitness func sums up all miss matches in a given solution """
        # calc diff elements in each ROW
        fit = self.__consistent(self.__solution)
        # calc diff elements in each COL
        fit += self.__consistent(zip(*self.__solution))
        # calc diff from seed (given digits)
        fit += self.__compare_to_seed(seeded_solution)
        # calc diff greater sign
        fit += self._eval_greater_constraints(greater_constraints)
        return fit

    def _eval_greater_constraints(self, constraints):
        """ returns number of satisfied constraints """
        count = 0
        for constraint in constraints:
            if not self.__greater_sign(constraint):
                count += 1
        return count

    def __greater_sign(self, constraint):
        big, small = constraint
        return self.__solution[big[0] - 1][big[1] - 1] > self.__solution[small[0] - 1][small[1] - 1]

    def get_sol(self):
        return self.__solution

    @classmethod
    def get_seeded_solution(cls, N, seeds):
        sol = cls(N)
        sol.__solution = [[0 for j in range(N)] for i in range(N)]
        for seed in seeds:
            i, j, num = seed
            sol.__solution[i - 1][j - 1] = num
        return sol

class SolutionFactory(ABC):
    @abstractmethod
    def generate_random_solution(self, N) -> Solution:
        pass
    @abstractmethod
    def generate_seeded_solution(self, N, seeds) -> Solution:
        pass

class MatrixSolutionFactory(SolutionFactory):

    def generate_random_solution(self, N) -> MatrixSolution:
        return MatrixSolution(N)

    def generate_seeded_solution(self, N, seeds) -> MatrixSolution:
        return MatrixSolution.get_seeded_solution(N, seeds)

class FutoshikiPuzzle:
    def __init__(self, N, greater_constraints, seed_constraints, factory: SolutionFactory):
        self.__board_size = N
        self.__greater_constraints = greater_constraints
        self.__seed_constraints = seed_constraints
        self.__factory = factory
        self.__seeded_solution = factory.generate_seeded_solution(self.__board_size, self.__seed_constraints)

    def get_max_constraints(self):
        """ :returns num of constraints to be met.
         i.e each row and column is a permutation + initial board values + greater signs """
        return self.__board_size * (self.__board_size - 1) * 2 \
               + len(self.__greater_constraints) + len(self.__seed_constraints)

    def fitness_func(self, solution: Solution):
        return solution.fitness(self.__greater_constraints, self.__seeded_solution)

    def optimization_func(self, solution: Solution):
        return solution.optimize(self.__greater_constraints, self.__seeded_solution)

    def is_terminal_state(self, score):
        return score == 0

    def get_random_solution(self) -> Solution:
        return self.__factory.generate_random_solution(self.__board_size)

    def get_best_worst_avg_score(self, population_to_score: Dict[Solution, int]):
        """ simple util func to save data for plotting """
        best_score = self.get_max_constraints()  # being best means close to 0
        worst_score = 0  # being worst means close to num constraints
        sum = 0
        for score in population_to_score.values():
            if score < best_score:
                best_score = score
            if score > worst_score:
                worst_score = score
            sum += score
        return best_score, worst_score, sum / len(population_to_score)

    def print_solution(self, solution: Solution):
        N = len(solution.get_sol())
        # create the extra rows for pretty printing
        new_rows = [['     ' for j in range(N)] for i in range(N-1)]
        for big, small in self.__greater_constraints:
            if big[1] == small[1]:  # same column
                if big[0] < small[0]:  # sign should be V
                    new_rows[big[0] - 1][big[1] - 1] = '  v  '
                else:
                    new_rows[small[0] - 1][small[1] - 1] = '  ˄  '

        solution_to_print = solution.get_sol()

        print(7 * N * "*" + "*")
        for i in range(N):
            print("|", end=' ')
            for j in range(N):
                if j == N - 1:
                    print(str(solution_to_print[i][j]) + " ", end='|\n')
                else:
                    if ((i+1,j+2),(i+1,j+1)) in self.__greater_constraints:
                        print(str(solution_to_print[i][j]) + " | < |", end=' ')
                    elif ((i+1,j+1),(i+1,j+2)) in self.__greater_constraints:
                        print(str(solution_to_print[i][j]) + " | > |", end=' ')
                    else:
                        print(str(solution_to_print[i][j]) + " |   |", end=' ')
            if not i == N-1:
                for k in range(N):
                    if k == N - 1:
                        print(new_rows[i][k], end='\n')
                    else:
                        print(new_rows[i][k], end='   ')

        print(7 * N * "*" + "*")


from aiogram import types
from loguru import logger

from bot import emojies
from bot.constants import LookingTripState
from bot.decorators import get_api
from services.atlas.atlas_api import AtlasAPI
from services.atlas.dto import LookingTripParams
from services.atlas.scheduler import scheduler

def start_searching_trip(message: types.Message, param: LookingTripParams):
    logger.log("BOT", f"The trip search {param.id} added to pool")

    scheduler.add_job(
        trip_searching,
        id=str(param.id),
        kwargs={"message": message, "params": param},
        trigger="interval",
        seconds=param.interval * 60,
        coalesce=True,
    )

    if not scheduler.state:
        scheduler.start()

def stop_trip_searching(param: LookingTripParams):
    if scheduler.get_job(str(param.id)):
        logger.log("BOT", f"The trip search {param.id} has stopped")
        scheduler.remove_job(str(param.id))

async def notify_job_users(jobs, msg: str):
    users = set()
    for job in jobs:
        message = job.kwargs.get('message')
        if not message or message and message.from_id in users:
            continue
        users.add(message.from_id)
        await message.answer(msg)

async def stop_all_tips_searching():
    await notify_job_users(
        scheduler.get_jobs(),
        f"{emojies.EXCLAMATION_MARK} Технические неполадки, все задачи были остановлены {emojies.EXCLAMATION_MARK}"
    )
    scheduler.remove_all_jobs()

# def is_job_running(param: LookingTripParams):
#     return LookingTripState.ON if scheduler.get_job(str(param.id)) else LookingTripState.OFF

def change_searching_trip_state(curr_state: LookingTripState) -> LookingTripState:
    return LookingTripState.ON if curr_state == LookingTripState.OFF else LookingTripState.OFF

@get_api
async def trip_searching(message: types.Message, api: AtlasAPI, params: LookingTripParams):
    logger.log("BOT", f"Getting trips to chat_id: {message.chat.id}, by params.id: {params.id}")
    res = await api.get_all_trips(params.departure_city, params.arrival_city, params.date)
    logger.info("BOT", f"Got a response to chat_id: {message.chat.id}, by params.id: {params.id}")
    await message.answer(f"Результат поиска: {res}")


import numpy as np
import xarray
import matplotlib.pyplot as plt
import pandas as pd
import os
import cartopy.crs as ccrs
import gsw as TEOS_10

file_name_stem = 'CO_DMQCGL01_'
data_type_dict = {'XBT': ['PR_XB','PR_BA','PR_TE','PR_OC','PR_SH','PR_GL'],
                  'CTD': ['PR_OC','PR_TE','PR_BA','PR_CT','PR_IC','PR_ME','PR_SD','PR_OS','PR_SH'],
                  'Seal': ['PR_OC','PR_TE','PR_BA','PR_CT','PR_IC','PR_ME','PR_SD','PR_OS'],
                  'Float': ['PR_PF','PR_TE'],
                  'All' : ['PR_PF','PR_XB','PR_BA','PR_TE','PR_OC','PR_SH','PR_GL','PR_CT','PR_IC','PR_ME','PR_SD','PR_OS','PR_SH']}

data_type_string  = ['PR_XB','PR_BA','PR_TE','PR_OC','PR_SH','PR_GL']

#data_type_string  = ['PR_OC','PR_TE','PR_BA','PR_CT','PR_IC','PR_ME','PR_SD','PR_OS','PR_GL']

WMO_code_dict = {'XBT'  : ['001','002','009','011','019','021','022','031','032','039','041','042','049',
                           '051','052','059','060','061','069','071','079','081','201','202','211','212',
                           '221','222','229','231','241','251','252','401','411','421','431','451','460',
                           '461','462','481','491','501','700','710','720','730','741','742','743','751'],
                 'CTD'  : ['800','810','820','830','1017'],
                 'Seal' : ['995'],
                 'Float': ['831','840','841','842','843','844','845','846','847','850','851','852','853','856',
                           '856','858','860','861'],
                 'All' : ['001','002','009','011','019','021','022','031','032','039','041','042','049',
                           '051','052','059','060','061','069','071','079','081','201','202','211','212',
                           '221','222','229','231','241','251','252','401','411','421','431','451','460',
                           '461','462','481','491','501','700','710','720','730','741','742','743','751',
                           '800','810','820','830','1017',
                           '831','840','841','842','843','844','845','846','847','850','851','852','853','856',
                           '856','858','860','861',
                           '995',
                           '999']}

#data_type_string  = ['PR_CT','PR_OC','PR_TE']
def get_duplicate_depth_index(depths):

    unique_vals, inverse, count = np.unique(depths, return_inverse=True,return_counts=True)
    idx_vals_repeated = np.where(count > 1)[0]
    if 0==len(idx_vals_repeated):

        return []

    else:
        vals_repeated = unique_vals[idx_vals_repeated]
        idx_repeated  = []
        for i_rep_val in vals_repeated:
            idx_repeated.append(np.nonzero(depths==i_rep_val)[0])
    return idx_repeated

def compound_logical(data,condition):
    data = data.tolist()
    n_conditions = len(condition)
    matching_indicies  = []
    found_data = False

    for i_cond in range(0,n_conditions):
        condition_indicies = [i for i,n in enumerate(data) if n.strip() == condition[i_cond]]
        if len(condition_indicies) != 0:
            for idx in condition_indicies:
               matching_indicies.append(idx)

    return sorted(matching_indicies)

if __name__ == '__main__':

    #base_file_path  = '/OSM/CBR/OA_DCFP/data3/observations/CORA/legacy/CORA_50/unpacked/home/cercache/users/mirror/home/oo9/oo/CORA4.3/Final_patched'
    base_file_path  = '/OSM/CBR/OA_DCFP/data2/observations/CORA/CORA_50/unpacked/home/cercache/users/mirror/home/oo9/oo/CORA4.3/Final_patched/'
#    base_file_path  = '/OSM/CBR/OA_DCFP/work/cha674/CORA_interrogation/test_files/'
    platform_type   = 'All'
    CORA_VERSION    = 50
    variable_to_get = 'salinity'

    MAX_DEPTH_TO_COMPUTE_STATS = 2000
    START_YEAR  = 2014
    END_YEAR    = 2016

    file_to_read = {str(START_YEAR) : []}
    total_num_profiles_for_year = {str(START_YEAR) : 0}
    for i_year in range(START_YEAR,END_YEAR):
        file_to_read[str(i_year)] = []
        total_num_profiles_for_year[str(i_year)] = 0

    total_num_profiles  = 0
    n_days_in_database  = 0
    n_files  = 0

    for i_year in range(START_YEAR,END_YEAR):
        data_path_for_current_year = os.path.join(base_file_path,str(i_year))
        dir_contents = os.listdir(data_path_for_current_year)
        dir_contents.sort()
        first_pass = True
        total_num_profiles_current_year = 0

        for entry in dir_contents:
            for i_file_type in data_type_dict[platform_type]:
                if os.path.isfile(os.path.join(data_path_for_current_year,entry)) and entry.endswith(i_file_type + ".nc"):
                    #print(entry)
                    file_handle  = xarray.open_dataset(os.path.join(data_path_for_current_year,entry), decode_times=True)
                    WMO_inst_type = file_handle['WMO_INST_TYPE'].values.astype('str')
                    WMO_type = WMO_inst_type.dtype
                    if platform_type == 'All':
                        idx_to_get = file_handle['N_PROF'].values

                    else:
                        idx_to_get = compound_logical(WMO_inst_type,WMO_code_dict[platform_type])
                    if first_pass:
                        dates  = pd.to_datetime(file_handle['JULD'][idx_to_get].values).date
                        first_pass=False
                    else:
                        dates = np.concatenate([dates,pd.to_datetime(file_handle['JULD'][idx_to_get].values).date])

                    variable_list = file_handle.data_vars

                    if ((variable_to_get.lower() == 'temperature') or (variable_to_get.lower() == 'temp')) and 'TEMP' in variable_list:

                        var     = file_handle['TEMP'][idx_to_get,:]
                        n_profiles_current_file = np.logical_not(np.all(np.isnan(var),axis=1)).values.sum()

                    elif ((variable_to_get == 'salinity') or (variable_to_get.lower() == 'salt')) and 'PSAL' in variable_list:

                        var     = file_handle['PSAL'][idx_to_get,:]
                        n_profiles_current_file = np.logical_not(np.all(np.isnan(var),axis=1)).values.sum()

                    else:
                        n_profiles_current_file = 0

                    total_num_profiles_current_year = total_num_profiles_current_year + n_profiles_current_file

                    #END if n_profiles !=0
                    file_handle.close()
                    if n_profiles_current_file !=0:
                        file_to_read[str(i_year)].append(os.path.join(data_path_for_current_year,entry))
                #END if os.path
            #END for i_file_type in data_type_string
        #END for entry in dir_contents
        file_to_read[str(i_year)].sort()

        if i_year == START_YEAR:
            unique_dates = {str(i_year) : np.sort(np.unique(dates))}
        else:
            unique_dates[str(i_year)] = np.sort(np.unique(dates))

        n_days_in_database = n_days_in_database + len(unique_dates[str(i_year)])

        n_files = n_files + len(file_to_read[str(i_year)])
        total_num_profiles_for_year[str(i_year)] = total_num_profiles_current_year
        total_num_profiles = total_num_profiles + total_num_profiles_current_year
    #END for i_year
    #print(file_to_read)
    print('==============================================================')
    print('Total number of files: ', n_files)
    print('Total number of profiles: ', total_num_profiles)
    print('Total number of unique dates in database:', n_days_in_database)
    print('==============================================================')
#    file_of_type_to_get.sort()
#    n_points_at_depth
#    for i_year in range(START_YEAR,END_YEAR):
#        print(total_num_profiles_for_year[str(i_year)])

    print(total_num_profiles_for_year)

    for i_year in range(START_YEAR,END_YEAR):

        #data_path_for_current_year = os.path.join(base_file_path,str(i_year))
        #dir_contents = os.listdir(data_path_for_current_year)
        first_pass = True
        total_num_profiles_current_year = 0

        print('============================')
        print('Year: ', i_year)
        print('Total number of profiles for year: ', total_num_profiles_for_year[str(i_year)])
        profile_counter = 0
        latitude  = np.nan * np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float32)
        longitude = np.nan * np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float32)
        time      = np.zeros(total_num_profiles_for_year[str(i_year)],dtype='datetime64[ns]')

        WMO_inst_code  = np.zeros(total_num_profiles_for_year[str(i_year)],dtype=WMO_type)
        max_depth      = np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float32)

        files_for_current_year = file_to_read[str(i_year)]
        for i_file in files_for_current_year:

            file_handle  = xarray.open_dataset(i_file, decode_times=True)
            n_levels            = file_handle['N_LEVELS'].size
            n_profiles_for_file = file_handle['N_PROF'].size
            WMO_inst_type = file_handle['WMO_INST_TYPE'].values.astype('str')

            if platform_type == 'All':
                idx_to_get = file_handle['N_PROF'].values
            else:
                idx_to_get = compound_logical(WMO_inst_type,WMO_code_dict[platform_type])

            WMO_inst_type = WMO_inst_type[idx_to_get]

            variable_list = file_handle.data_vars
            if ((variable_to_get.lower() == 'temperature') or (variable_to_get.lower() == 'temp')) and 'TEMP' in variable_list:
                var  = file_handle['TEMP'][idx_to_get,:]
            elif ((variable_to_get == 'salinity') or (variable_to_get.lower() == 'salt')) and 'PSAL' in variable_list:
                var  = file_handle['PSAL'][idx_to_get,:]

            good_profile_idx = np.nonzero(np.logical_not(np.all(np.isnan(var),axis=1)).values)[0]
            n_good_profiles = good_profile_idx.size

            current_latitudes = file_handle['LATITUDE'][idx_to_get][good_profile_idx].values
            current_longitudes = file_handle['LONGITUDE'][idx_to_get][good_profile_idx].values

            if 'DEPH' in variable_list:
                depth    = file_handle['DEPH'][idx_to_get,:][good_profile_idx,:].values
                vertical_coord_QC = file_handle['DEPH_QC'][idx_to_get,:][good_profile_idx,:].values

            if 'PRES' in variable_list:
                pressure          = file_handle['PRES'][idx_to_get,:][good_profile_idx,:].values
                vertical_coord_QC = file_handle['PRES_QC'][idx_to_get,:][good_profile_idx,:].values

                lat_broadcast = np.tile(current_latitudes,[1,n_levels]).reshape([n_good_profiles,n_levels])
                depth_from_pressure = -TEOS_10.z_from_p(pressure, lat_broadcast)

            if ('DEPH' in variable_list) and ('PRES' in variable_list):

                bad_profile_depth_idx = np.nonzero(np.all(np.isnan(depth),axis=1))[0]
                bad_profile_press_idx = np.nonzero(np.all(np.isnan(pressure),axis=1))[0]

                for i_bad_depth_profile in bad_profile_depth_idx:
                    if i_bad_depth_profile not in bad_profile_press_idx:
                        depth[i_bad_depth_profile,:] = depth_from_pressure[i_bad_depth_profile,:]
            if ('DEPH' not in variable_list) and ('PRES' in variable_list):
               depth = depth_from_pressure

            bad_profile_depth_idx = np.nonzero(np.all(np.isnan(depth),axis=1))[0]
            #print(np.nanmax(depth,axis=1))
            max_depth[profile_counter:profile_counter+n_good_profiles] = np.nanmax(depth,axis=1)

            current_latitudes[bad_profile_depth_idx] = np.nan
            current_longitudes[bad_profile_depth_idx] =np.nan
            latitude[profile_counter:profile_counter+n_good_profiles]  = current_latitudes
            longitude[profile_counter:profile_counter+n_good_profiles] = current_longitudes
            time[profile_counter:profile_counter+n_good_profiles]           =   file_handle['JULD'][good_profile_idx]
            WMO_inst_code[profile_counter:profile_counter+n_good_profiles]  = WMO_inst_type[good_profile_idx]

            profile_counter = profile_counter + n_good_profiles
        #END for entry in dir_contents

        output_file_path = '/OSM/CBR/OA_DCFP/work/cha674/CORA_interrogation/Stat_files_v' + str(CORA_VERSION) + '/V2_after_bug_fix/'
        output_file_name = 'CORA_v' + str(CORA_VERSION) + '_' + variable_to_get + '_' + str(i_year) + '_stats_' + platform_type + 'QC012.fix2.nc'

        print('Writing file: ', output_file_name, ' to ', output_file_path)

        output_dataset = xarray.DataArray(latitude,dims=('N_PROF'),coords={'N_PROF':np.arange(0,latitude.size)}).to_dataset(name='latitudes')
        output_dataset['longitudes'] = xarray.DataArray(longitude,dims=('N_PROF'),coords={'N_PROF':np.arange(0,latitude.size)})
        output_dataset['JULD']       = xarray.DataArray(time,dims=('N_PROF'),coords={'N_PROF':np.arange(0,latitude.size)})
        output_dataset['max_depth']  = xarray.DataArray(max_depth,dims=('N_PROF'),coords={'N_PROF':np.arange(0,latitude.size)})
        output_dataset['WMO_instrument_code']  = xarray.DataArray(WMO_inst_code,dims=('N_PROF'),coords={'N_PROF':np.arange(0,latitude.size)})

        output_dataset.to_netcdf(os.path.join(output_file_path,output_file_name))

    #END for i_year

    dsa
    for i_year in range(START_YEAR,END_YEAR):
        print('============================')
        print('Year: ', i_year)
        print('Total number of profiles for year: ', total_num_profiles_for_year[str(i_year)])
        profile_counter = 0
        latitude  = np.nan * np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float32)
        longitude = np.nan * np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float32)
        time      = np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float64)

        WMO_inst_code  = np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.int32)
        max_depth      = np.zeros(total_num_profiles_for_year[str(i_year)],dtype=np.float32)

        n_points_on_level = np.zeros([len(unique_dates[str(i_year)]),interp_levels.size],dtype=np.int32)

        n_files_for_year = len(file_of_type_to_get[str(i_year)])

        data_path_for_current_year = os.path.join(base_file_path,str(i_year))
        for i_file in range(0,n_files_for_year):

            print("Opening file: ", i_file, ' of ', n_files_for_year,': ', file_of_type_to_get[str(i_year)][i_file])

            file_handle  = xarray.open_dataset(os.path.join(data_path_for_current_year, file_of_type_to_get[str(i_year)][i_file]), decode_times=True)
            n_levels     = file_handle['N_LEVELS'].size
            WMO_inst_type = file_handle['WMO_INST_TYPE'].values.astype('str')

            idx_to_get = compound_logical(WMO_inst_type,WMO_code_dict[platform_type])
            n_profiles = len(idx_to_get)

            if n_profiles==0:
                continue

            current_latitude                                          = file_handle['LATITUDE'][idx_to_get].values
            current_longitude                                         = file_handle['LONGITUDE'][idx_to_get].values
            time_current_file                                         = file_handle['JULD'][idx_to_get].values
            time [profile_counter:profile_counter+n_profiles]         = time_current_file
            WMO_inst_code[profile_counter:profile_counter+n_profiles] = WMO_inst_type[idx_to_get].astype(int)

            latitude[profile_counter:profile_counter+n_profiles]      = file_handle['LATITUDE'][idx_to_get].values
            longitude[profile_counter:profile_counter+n_profiles]     = file_handle['LONGITUDE'][idx_to_get].values
            current_dates                                             = pd.to_datetime(time_current_file).date

            variable_list = file_handle.data_vars
            if 'DEPH' in variable_list:
                depth    = file_handle['DEPH'][idx_to_get,:].values
                vertical_coord_QC = file_handle['DEPH_QC'][idx_to_get,:]

            elif 'PRES' in variable_list:
                pressure          = file_handle['PRES'][idx_to_get,:].values
                vertical_coord_QC = file_handle['PRES_QC'][idx_to_get,:]

                lat_broadcast = np.tile(latitude[profile_counter:profile_counter+n_profiles],[1,n_levels]).reshape([n_profiles,n_levels])
                depth = -TEOS_10.z_from_p(pressure, lat_broadcast)
            #END if 'DEPH' in variable_list
            max_depth[profile_counter:profile_counter+n_profiles] = np.nanmax(depth,axis=1)

            if (variable_to_get.lower() == 'temperature') or (variable_to_get.lower() == 'temp'):
                if 'TEMP' in variable_list:

                    var     = file_handle['TEMP'][idx_to_get,:]
                    var_QC  = file_handle['TEMP_QC'][idx_to_get,:]
                else:
                    continue
            elif (variable_to_get == 'salinity') or (variable_to_get.lower() == 'salt'):
                if 'PSAL' in variable_list:
                    var     = file_handle['PSAL'][idx_to_get,:]
                    var_QC  = file_handle['PSAL_QC'][idx_to_get,:]
                else:
                    continue

            for i_profile in range(0,n_profiles):
#                print(i_profile)
                date_of_profile = current_dates[i_profile]
                idx_date = np.nonzero(unique_dates[str(i_year)]==date_of_profile)[0][0]

                profile_current = var[i_profile,:]
                QC_profile_current = var_QC[i_profile,:]
                vertical_coord_QC_profile_current = vertical_coord_QC[i_profile,:]

                profile_current = profile_current.where((QC_profile_current.astype(float)==0) | (QC_profile_current.astype(float)==1) | (QC_profile_current.astype(float)==2))
                profile_current = profile_current.where((vertical_coord_QC_profile_current.astype(float)==0) | (vertical_coord_QC_profile_current.astype(float)==1) | (vertical_coord_QC_profile_current.astype(float)==2))

                idx_duplicate_depths = get_duplicate_depth_index(depth[i_profile,:])
                if len(idx_duplicate_depths) != 0:
                    for i_duplicate_index in idx_duplicate_depths:
                        for i_index in range(1,len(i_duplicate_index)):

                            depth[i_profile,i_duplicate_index[i_index]]   = depth[i_profile,i_duplicate_index[i_index]] + 0.01*float(i_index)
                    #END for i_duplicate_index
                #END if len(idx_duplicate_depths) !=0

                n_good_points = (1*profile_current.notnull().values).sum()

                if n_good_points<5:
                    continue
                else:

                    profile_current['N_LEVELS'] = np.sort(depth[i_profile,:])
                    first_good_depth_var   = profile_current.to_series().first_valid_index()
                    last_good_depth_var    = profile_current.to_series().last_valid_index()
                    first_good_depth_depth = profile_current['N_LEVELS'].to_series().first_valid_index()
                    last_good_depth_depth  = profile_current['N_LEVELS'].to_series().last_valid_index()

                    first_good_depth = max(first_good_depth_var,first_good_depth_depth)
                    last_good_depth  = max(last_good_depth_var,last_good_depth_depth)

                    first_good_idx   = np.nonzero(profile_current['N_LEVELS'].values==first_good_depth)[0][0]
                    last_good_idx    = np.nonzero(profile_current['N_LEVELS'].values==last_good_depth )[0][0]

                    if np.any(profile_current['N_LEVELS'][first_good_idx:last_good_idx+1].isnull()):
#                        print('Hello')
                        depth_tmp = depth[i_profile,:]

                        depth_tmp[first_good_idx:last_good_idx] = pd.Series(depth_tmp[first_good_idx:last_good_idx+1]).interpolate().values
                        profile_current['N_LEVELS'] = depth_tmp
#                    print(last_good_depth)
#                    print(first_good_depth)
#                    print('======')
                    if first_good_depth>MAX_DEPTH_TO_COMPUTE_STATS:
                        first_standard_level =interp_levels.size
                    else:
                        first_standard_level = np.nonzero(interp_levels>=first_good_depth)[0][0]

                    if last_good_depth > MAX_DEPTH_TO_COMPUTE_STATS:
                        last_standard_level = interp_levels.size
                    else:
                        last_standard_level  = np.nonzero(interp_levels>=last_good_depth)[0][0]
                    good_levels = np.ones([last_standard_level-first_standard_level])
                    #print(first_good_depth)
                    #print(last_good_depth)
                    #print(first_standard_level)
                    #print(last_standard_level)
                    n_points_on_level[idx_date,first_standard_level:last_standard_level] = n_points_on_level[idx_date,first_standard_level:last_standard_level] + good_levels

                    #try:
                    #    profile_current = profile_current[first_good_idx:last_good_idx].interp(N_LEVELS=interp_levels,method='nearest')
                    #except:
                    #    profile_curren = np.nan * interp_levels

                    #n_points_on_level[idx_date,:] = n_points_on_level[idx_date,:] +  1*profile_current.notnull().values

                 #END if n_good_points<5:
            #END for i_profile
            profile_counter = profile_counter + n_profiles
            file_handle.close()
        #END for i_file

        n_points_on_level[:,0] = n_points_on_level[:,1]
        #output_file_path = '/OSM/CBR/OA_DCFP/work/cha674/CORA_interrogation/Stat_files_v51/'
        #output_file_name = 'CORA_v51_' + variable_to_get + '_' + str(i_year) + '_stats_' + platform_type + 'QC012.npz'

        output_file_path = '/OSM/CBR/OA_DCFP/work/cha674/CORA_interrogation/Stat_files_v' + str(CORA_VERSION) + '/Simple_Counts/'
        output_file_name = 'CORA_v' + str(CORA_VERSION) + '_' + variable_to_get + '_' + str(i_year) + '_stats_' + platform_type + 'QC012.simple_count_new.npz'

        print("Saving file: ", output_file_path + output_file_name)
        np.savez(output_file_path + output_file_name, n_points_on_level=n_points_on_level, time=time,longitude=longitude,latitude=latitude,unique_dates=unique_dates[str(i_year)],WMO_inst_code=WMO_inst_code,max_depth=max_depth)

    #END for i_year


from rest_framework import serializers
from rest_framework_recursive.fields import RecursiveField
from drf_writable_nested.serializers import WritableNestedModelSerializer
from manufacture.models import *

class StringSerializer(serializers.StringRelatedField):

    def to_internal_value(self, value):
        return value

class ProcessDetailSerializer(serializers.ModelSerializer):
    bill_of_materials = StringSerializer()
    process_equipment = StringSerializer()
    products = StringSerializer()
    rate = StringSerializer()
    type = serializers.SerializerMethodField()

    class Meta:
        model = Process
        fields = [
            "id",
            "parent_process",
            "process_equipment",
            'name',
            'description',
            'bill_of_materials',
            'type', # display this
            'duration',
            'rate',
            'products',
            'reference_number'

        ]

    def get_type(self, obj):
        return obj.get_type_display()

class ProcessListSerializer(serializers.ModelSerializer):
    type = serializers.SerializerMethodField()

    class Meta:
        model = Process
        fields = [
            'id',
            'name',
            'reference_number',
            'rate',
            'type',
        ]

    def get_type(self, obj):
        return obj.get_type_display()

class ProcessCreateUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Process
        fields = [
            "parent_process",
            "process_equipment",
            'name',
            'description',
            'bill_of_materials',
            'type',
            'duration',
            'rate',
            'products'
        ]

class ProcessRateCreateUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = ProcessRate
        fields = [
            "id",
            "unit",
            "unit_time",
            'quantity',
        ]

class ProcessRateSerializer(serializers.ModelSerializer):
    unit = StringSerializer()
    unit_time = serializers.SerializerMethodField()

    class Meta:
        model = ProcessRate
        fields = [
            "id",
            "unit",
            "unit_time",
            'quantity',
        ]

    def get_unit_time(self, obj):
        return obj.get_unit_time_display()


"""
SystemLab-Design Version 19.02
Functional block script: 90 Deg Optical Hybrid
Version 1.0 (19.02 23 Feb 2019)

Refs:
1) Integrated 90deg Hybrid Balanced Receiver Datasheet, Optoplex Corporation, Fremont, CA
Source: http://www.optoplex.com/download/Optoplex%20Integrated%2090deg%20Balanced
%20Receiver%20Brochure%20Rev3.3.pdf (Accessed 21 Feb 2019)
"""

import config

def run(input_signal_data, parameters_input, settings):

    '''==PROJECT SETTINGS==================================================='''
    module_name = '90 deg optical hybrid'
    n = settings['num_samples']
    n = int(round(n))
    iteration = settings['current_iteration']
    fs = settings['sampling_rate']

    # Status message
    if config.sim_status_win_enabled == True:
        config.sim_status_win.textEdit.append('Running ' + module_name +
                                          ' - Iteration #: ' + str(iteration))
    config.status.setText('Running ' + module_name +
                                          ' - Iteration #: ' + str(iteration))
    config.app.processEvents()

    if config.sim_data_activate == True:
        config.sim_data_view.dataEdit.append('Data output for ' + module_name +
                                          ' - Iteration #: ' + str(iteration))

    '''==INPUT PARAMETERS========================================================='''

    '''==INPUT SIGNALS======================================================'''
    signal_type = 'Optical'
    time_array = input_signal_data[0][3]

    optical_in_sig = input_signal_data[0][4]
    wave_key = optical_in_sig[0][0]
    wave_freq = optical_in_sig[0][1]
    e_field_input_sig = optical_in_sig[0][3]
    jones_vector_sig = optical_in_sig[0][2]
    noise_array_sig = optical_in_sig[0][4]
    psd_array_sig = optical_in_sig[0][5]

    optical_in_ref = input_signal_data[1][4]
    wave_key = optical_in_ref[0][0]
    wave_freq = optical_in_ref[0][1]
    e_field_input_ref = optical_in_ref[0][3]
#    jones_vector_ref = optical_in_ref[0][2]
    noise_array_ref = optical_in_ref[0][4]
#    psd_array_ref = optical_in_ref[0][5]

    '''==CALCULATIONS======================================================='''

    # Calculate fields exiting ports 3-6
    # Ref 1 - Port 3: S+L, Port 4: S-L, Port 5: S+jL, Port 6: S-jL
    e_field_output_P3 = 0.5*(e_field_input_sig + e_field_input_ref)
    e_field_output_P4 = 0.5*(e_field_input_sig - e_field_input_ref)
    e_field_output_P5 = 0.5*(e_field_input_sig + 1j*e_field_input_ref)
    e_field_output_P6 = 0.5*(e_field_input_sig - 1j*e_field_input_ref)

    e_field_noise_P3 = 0.5*(noise_array_sig + noise_array_ref)
    e_field_noise_P4 = 0.5*(noise_array_sig - noise_array_ref)
    e_field_noise_P5 = 0.5*(noise_array_sig + 1j*noise_array_ref)
    e_field_noise_P6 = 0.5*(noise_array_sig - 1j*noise_array_ref)

    '''==OUTPUT PARAMETERS LIST============================================='''
    ninety_deg_hybrid_parameters = []
    ninety_deg_hybrid_parameters = parameters_input #If no changes were made to parameters

    '''==RESULTS============================================================'''
    ninety_deg_hybrid_results = [] #No results

    '''==RETURN (Output Signals, Parameters, Results)=========================='''

    optical_P3 = [[wave_key, wave_freq, jones_vector_sig, e_field_output_P3, e_field_noise_P3, psd_array_sig]]
    optical_P4 = [[wave_key, wave_freq, jones_vector_sig, e_field_output_P4, e_field_noise_P4, psd_array_sig]]
    optical_P5 = [[wave_key, wave_freq, jones_vector_sig, e_field_output_P5, e_field_noise_P5, psd_array_sig]]
    optical_P6 = [[wave_key, wave_freq, jones_vector_sig, e_field_output_P6, e_field_noise_P6, psd_array_sig]]

    return ([[3, signal_type, fs, time_array, optical_P3],
             [4, signal_type, fs, time_array, optical_P4],
             [5, signal_type, fs, time_array, optical_P5],
             [6, signal_type, fs, time_array, optical_P6]],
             ninety_deg_hybrid_parameters, ninety_deg_hybrid_results)


import dlib
import cv2
import imutils
import QT_gui
import global_v as GV

# 開啟影片檔案
cap = cv2.VideoCapture(0)

# Dlib 的人臉偵測器
detector = dlib.get_frontal_face_detector()

# 以迴圈從影片檔案讀取影格，並顯示出來
while(cap.isOpened()):
  ret, frame = cap.read()

  # 偵測人臉
  face_rects, scores, idx = detector.run(frame, 0)
  rectarea=0
  # 取出所有偵測的結果
  for i, d in enumerate(face_rects):
    x1 = d.left()
    y1 = d.top()
    x2 = d.right()
    y2 = d.bottom()
    text = "%2.2f(%d)" % (scores[i], idx[i])

    # 以方框標示偵測的人臉
    cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 4, cv2.LINE_AA)
    rectarea=abs(x1-x2)*abs(y1-y2)
    # 標示分數
    #cv2.putText(frame, text, (x1, y1), cv2.FONT_HERSHEY_DUPLEX,
    #        0.7, (255, 255, 255), 1, cv2.LINE_AA)

  # 顯示結果
  cv2.imshow("Face Detection", frame)
  if rectarea>=180000:
    cv2.imwrite("face.jpg", frame[y1:y2,x1:x2])
    cap.release()
    cv2.destroyAllWindows()
    QT_gui.FirstUi()

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


#!/usr/bin/python3

# sudo systemctl start bluetooth
# echo "power on" | bluetoothctl

import collections
import struct
import sys
import argparse
import datetime
import time
import pickle
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.dates import DayLocator, HourLocator, DateFormatter, drange
from bluetooth import *
import csv

# Process socket data from USB meter and extract volts, amps etc.
def processdata(d):

    data = {}

    data["Volts"] = struct.unpack(">h", d[2 : 3 + 1])[0] / 1000.0  # volts
    data["Amps"] = struct.unpack(">h", d[4 : 5 + 1])[0] / 10000.0  # amps
    data["Watts"] = struct.unpack(">I", d[6 : 9 + 1])[0] / 1000.0  # watts
    data["temp_C"] = struct.unpack(">h", d[10 : 11 + 1])[0]  # temp in C
    data["temp_F"] = struct.unpack(">h", d[12 : 13 + 1])[0]  # temp in F

    utc_dt = datetime.datetime.now(datetime.timezone.utc)  # UTC time
    dt = utc_dt.astimezone()  # local time
    data["time"] = dt

    g = 0
    for i in range(16, 95, 8):
        ma, mw = struct.unpack(">II", d[i : i + 8])  # mAh,mWh respectively
        gs = str(g)
        data[gs + "_mAh"] = ma
        data[gs + "_mWh"] = mw
        g += 1

    data["data_line_pos_volt"] = struct.unpack(">h", d[96: 97 + 1])[0] / 100.0
    data["data_line_neg_volt"] = struct.unpack(">h", d[98: 99 + 1])[0] / 100.0
    data["resistance"] = struct.unpack(">I", d[122: 125 + 1])[0] / 10.0  # resistance
    return data

def main(target_pods: int, repetition: int, time_analysis: int):

    #Variables
    path_out = '/home/luongtrann/hanoi/code/data_ummeter'

    try:
        addr = '00:16:A5:00:0F:65'
        sock = BluetoothSocket(RFCOMM)
        res = sock.connect((addr, 1))
    except:
        print("Having some problems to connect to the UMMETER")
        # Automagically find USB meter
        nearby_devices = discover_devices(lookup_names=True)

        for v in nearby_devices:
            if "UM25C" in v[1]:
                print("Found", v[0])
                addr = v[0]
                break

        if addr is None:
            print("No address provided", file=sys.stderr)
            quit()

        service_matches = find_service(address=addr)

        if len(service_matches) == 0:
            print("No services found for address ", addr, file=sys.stderr)
            quit()

        first_match = service_matches[0]
        port = first_match["port"]
        name = first_match["name"]
        host = first_match["host"]

        if host is None or port is None:
            print("Host or port not specified", file=sys.stderr)
            quit()

        sock = BluetoothSocket(RFCOMM)
        print('connecting to "{}" on {}:{}'.format(name, host, port))
        res = sock.connect((host, port))

    with open('{}/data_ummeter_{}_{}.csv'.format(path_out, str(target_pods), str(repetition)), 'a+') as f:
        writer = csv.writer(f)
        writer.writerow(["time", "Volts", "Amps", "Watts"])
        leng = 20
        volts = collections.deque(maxlen=leng)
        currents = collections.deque(maxlen=leng)
        watts = collections.deque(maxlen=leng)
        times = collections.deque(maxlen=leng)

        d = b""

        endtime = time.time()+(60*int(time_analysis)+240) #[m]->[s] + 45s for cold and delete
        while endtime-time.time() > 0:
            # Send request to USB meter
            sock.send((0xF0).to_bytes(1, byteorder="big"))

            d += sock.recv(130)

            if len(d) != 130:
                continue

            data = processdata(d)
            volts.append(data["Volts"])
            currents.append(data["Amps"])
            watts.append(data["Watts"])
            times.append(data["time"])

            #print("%s: %fV %fA %fW" % (data["time"], data["Volts"], data["Amps"], data["Watts"]))

            writer.writerow([data["time"], data["Volts"], data["Amps"], data["Watts"]])

            d = b""
            time.sleep(0.1)

        print('Closed')
        sock.close()
    return True


import os
import errno
import urllib
from collections import OrderedDict
import sys
import cStringIO
import logging

from cfgm_common import vnc_cgitb

def cgitb_hook(info=None, **kwargs):
    vnc_cgitb.Hook(**kwargs).handle(info or sys.exc_info())
# end cgitb_hook

def detailed_traceback():
    buf = cStringIO.StringIO()
    cgitb_hook(format="text", file=buf)
    tb_txt = buf.getvalue()
    buf.close()
    return tb_txt
# end detailed_traceback

def encode_string(enc_str, encoding='utf-8'):
    """Encode the string using urllib.quote_plus

    Eg. @input:
            enc_str = 'neté
            type - 'unicode' or 'str'
        @retval
            enc_str = 'net%C3%A9%C3%B9'
            type - str
    """
    try:
        enc_str.encode()
    except (UnicodeDecodeError, UnicodeEncodeError):
        if type(enc_str) is unicode:
            enc_str = enc_str.encode(encoding)
        enc_str = urllib.quote_plus(enc_str)
    except Exception:
        pass
    return enc_str

def decode_string(dec_str, encoding='utf-8'):
    """Decode the string previously encoded using urllib.quote_plus.

    Eg. If dec_str = 'net%C3%A9%C3%B9'
           type - 'unicode' or 'str'
        @retval
            ret_dec_str = 'neté
            type - unicode
    """
    ret_dec_str = dec_str
    try:
        if type(ret_dec_str) is unicode:
            ret_dec_str = str(ret_dec_str)
        ret_dec_str = urllib.unquote_plus(ret_dec_str)
        return ret_dec_str.decode(encoding)
    except Exception:
        return dec_str

class CacheContainer(object):
    def __init__(self, size):
        self.container_size = size
        self.dictionary = OrderedDict()

    def __getitem__(self, key, default=None):
        value = self.dictionary[key]
        # item accessed - put it in the front
        del self.dictionary[key]
        self.dictionary[key] = value

        return value

    def __setitem__(self, key, value):
        self.dictionary[key] = value
        if len(self.dictionary.keys()) > self.container_size:
            # container is full, loose the least used item
            self.dictionary.popitem(last=False)

    def __contains__(self, key):
        return key in self.dictionary

    def __repr__(self):
        return str(self.dictionary)

def CamelCase(input):
    words = input.replace('_', '-').split('-')
    name = ''
    for w in words:
        name += w.capitalize()
    return name
# end CamelCase

def str_to_class(class_name, module_name):
    try:
        return reduce(getattr, class_name.split("."), sys.modules[module_name])
    except Exception as e:
        logger = logging.getLogger(module_name)
        logger.warn("Exception: %s", str(e))
        return None
# end str_to_class

def obj_type_to_vnc_class(obj_type, module_name):
    return str_to_class(CamelCase(obj_type), module_name)
# end obj_type_to_vnc_class

def getCertKeyCaBundle(bundle, certs):
    if os.path.isfile(bundle):
        # Check if bundle needs to be replaced if
        # constituent files were updated
        bundle_is_stale = False
        bundle_mod_time = os.path.getmtime(bundle)
        for cert in certs:
            if os.path.getmtime(cert) > bundle_mod_time:
                bundle_is_stale = True
                break
        if not bundle_is_stale:
            return bundle

    try:
        os.makedirs(os.path.dirname(bundle))
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise
    with open(bundle, 'w') as ofile:
        for cert in certs:
            with open(cert) as ifile:
                for line in ifile:
                    ofile.write(line)
    os.chmod(bundle,0o777)
    return bundle
# end CreateCertKeyCaBundle

# <uuid> | "tenant-"<uuid> | "domain-"<uuid>
def shareinfo_from_perms2_tenant(field):
    x = field.split(":")
    if len(x) == 1:
        x.insert(0, "tenant")
    return x
# end

def shareinfo_from_perms2(field):
    x = field.split(":")
    if len(x) == 2:
        x.insert(0, "tenant")
    return x
# end


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

import tensorflow as tf
import numpy as np

from vgg16_model import vgg16 as vgg16
import TensorflowUtils as utils
import read_voa_data as scene_parsing
import datetime
import BatchDatasetReader as dataset
from six.moves import xrange
from function import accuracy
from PIL import Image

FLAGS = tf.flags.FLAGS
tf.flags.DEFINE_integer("batch_size", "10", "batch size for training")
tf.flags.DEFINE_string("logs_dir", "logs/", "path to logs directory")
tf.flags.DEFINE_string("data_dir", "dataset/", "path to dataset")
tf.flags.DEFINE_float("learning_rate", "1e-4", "Learning rate for Momentum Optimizer")
tf.flags.DEFINE_bool('debug', "False", "Debug mode: True/ False")
tf.flags.DEFINE_string("model_dir", "Model_zoo/", "Path to vgg model mat")
tf.flags.DEFINE_string('mode', "train", "Mode train/ test/ visualize")
tf.flags.DEFINE_float("momentum", "0.9", "momentum for Momentum Optimizer")
tf.flags.DEFINE_float("weight_decay", "5e-4", "weight_decay for reg_loss")

MAX_ITERATION = int(1e5 + 1)
IMAGE_SIZE = 500

MODEL_URL = "http://www.vlfeat.org/matconvnet/models/beta16/imagenet-vgg-verydeep-16.mat"

def inference(image, keep_prob):
    """ fcn_8s """
    # load data
    vgg16_object = vgg16()
    print("setting up vgg initialized conv layers ...")
    model_data = utils.get_model_data(FLAGS.model_dir, MODEL_URL)
    mean = model_data['normalization'][0][0][0]
    mean_pixel = np.mean(mean, axis=(0, 1))
    weights = model_data['layers'][0]

    # preprocess
    processed_image = utils.process_image(image, mean_pixel)

    # deconvolution
    with tf.variable_scope("inference"):
        image_net = vgg16_object._vgg16_modified(processed_image, weights)

        pool4, pool3 = image_net["pool4"], image_net["pool3"]

        conv_final_layer = image_net["conv5_3"]

        """ pool5 """
        pool5 = vgg16_object._max_pool(conv_final_layer, 2, 2, 'pool5')

        """ fc6 """
        W6 = utils.weight_variable([7, 7, 512, 4096], name="W6")
        b6 = utils.bias_variable([4096], name="b6")
        fc6 = vgg16_object._conv(pool5, W6, b6, 'fc6')
        relu6 = vgg16_object._relu(fc6, 'relu6')
        fc6 = tf.nn.dropout(relu6, keep_prob)

        """ fc7 """
        W7 = utils.weight_variable([1, 1, 4096, 4096], name="W7")
        b7 = utils.bias_variable([4096], name="b7")
        fc7 = vgg16_object._conv(fc6, W7, b7, 'fc7')
        relu7 = vgg16_object._relu(fc7, 'relu7')
        fc7 = tf.nn.dropout(relu7, keep_prob)

        """ fc8 """
        W8 = utils.weight_variable([1, 1, 4096, 21], name="W8")
        b8 = utils.bias_variable([21], name="b8")
        fc8 = vgg16_object._conv(fc7, W8, b8, 'fc8')

        # upsample and add with pool4(pool4 should pass through a score layer)
        score_w1 = utils.weight_variable([1,1,512,21], name="score_w1")
        score_b1 = utils.weight_variable([21], name="score_b1")
        score1 = vgg16_object._conv(pool4, score_w1, score_b1, 'score1')
        W_t1 = tf.Variable(initial_value=bilinear_init(), name="W_t1")
        b_t1 = tf.Variable(initial_value=tf.constant(0.0, shape=[21]), name="b_t1")
        conv_t1 = vgg16_object.conv2d_transpose_strided(fc8, W_t1, b_t1, output_shape=tf.shape(score1))
        fuse_1 = tf.add(conv_t1, score1, name="fuse_1")

        # upsample and add with pool3(pool3 should pass through a score layer)
        score_w2 = utils.weight_variable([1,1,256,21], name="score_w2")
        score_b2 = utils.weight_variable([21], name="score_b2")
        score2 = vgg16_object._conv(pool3, score_w2, score_b2, 'score2')
        W_t2 = tf.Variable(initial_value=bilinear_init(), name="W_t2")
        b_t2 = tf.Variable(initial_value=tf.constant(0.0, shape=[21]), name="b_t2")
        conv_t2 = vgg16_object.conv2d_transpose_strided(fuse_1, W_t2, b_t2, output_shape=tf.shape(score2))
        fuse_2 = tf.add(conv_t2, score2, name="fuse_2")

        shape = tf.shape(processed_image)
        deconv_shape3 = tf.stack([shape[0], shape[1], shape[2], 21])
        W_t3 = tf.Variable(initial_value=bilinear_init(scale=8), name="W_t3")
        b_t3 = tf.Variable(initial_value=tf.constant(0.0, shape=[21]), name="b_t3")
        conv_t3 = vgg16_object.conv2d_transpose_strided(fuse_2, W_t3, b_t3, output_shape=deconv_shape3, stride=8)

        prediction = tf.argmax(conv_t3, dimension=3, name="prediction")
        return prediction, conv_t3, pool4

#Create bilinear weights in numpy array
def bilinear_init(scale=2, num_classes=21):
    filter_size = (2 * scale - scale % 2)
    bilinear_kernel = np.zeros([filter_size, filter_size], dtype=np.float32)
    scale_factor = (filter_size + 1) // 2
    if filter_size % 2 == 1:
        center = scale_factor - 1
    else:
        center = scale_factor - 0.5
    for x in range(filter_size):
        for y in range(filter_size):
            bilinear_kernel[x,y] = (1 - abs(x - center) / scale_factor) * \
                                   (1 - abs(y - center) / scale_factor)
    weights = np.zeros((filter_size, filter_size, num_classes, num_classes))
    for i in range(num_classes):
        weights[:, :, i, i] = bilinear_kernel

    #assign numpy array to tensor
    bilinear_initial = tf.convert_to_tensor(weights, dtype=tf.float32)
    return bilinear_initial

def train(loss_val, var_list):
    optimizer = tf.train.MomentumOptimizer(FLAGS.learning_rate, FLAGS.momentum)
    grads = optimizer.compute_gradients(loss_val, var_list=var_list)
    if FLAGS.debug:
        # print(len(var_list))
        for grad, var in grads:
            utils.add_gradient_summary(grad, var)
    return optimizer.apply_gradients(grads)

def main(argv=None):
    keep_probability = tf.placeholder(tf.float32, name="keep_probabilty")
    image = tf.placeholder(tf.float32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 3], name="input_image")
    annotation = tf.placeholder(tf.int32, shape=[None, IMAGE_SIZE, IMAGE_SIZE], name="annotation")

    # TODO
    pred_annotation, logits, c_l_l = inference(image, keep_probability)

    tf.summary.image("input_image", image, max_outputs=20)
    # tf.summary.image("ground_truth", tf.cast(annotation, tf.uint8), max_outputs=20)
    # tf.summary.image("pred_annotation", tf.cast(pred_annotation, tf.uint8), max_outputs=20)
    annotation_onehot = tf.one_hot(annotation, 21, 1.0, 0.0, -1)
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = annotation_onehot, logits = logits))
    # loss = tf.reduce_mean((tf.nn.sparse_softmax_cross_entropy_with_logits(logits=tf.clip_by_value(tf.cast(logits, dtype=tf.float32), 1e-10, 1), labels=tf.cast(annotation, dtype=tf.int32))))
    tf.summary.scalar("entropy", loss)

    trainable_var = tf.trainable_variables()
    if FLAGS.debug:
        for var in trainable_var:
            utils.add_to_regularization_and_summary(var)
        # reg_loss = tf.add_n(tf.get_collection("reg_loss"))
    reg_loss = tf.add_n([tf.nn.l2_loss(v) for v in tf.trainable_variables()])
    loss += FLAGS.weight_decay * reg_loss

    train_op = train(loss, trainable_var)

    print("Setting up summary op...")
    summary_op = tf.summary.merge_all()

    print("Setting up image reader...")
    train_records, valid_records = scene_parsing.read_dataset(FLAGS.data_dir)
    print(len(train_records))
    print(len(valid_records))

    print("Setting up dataset reader")
    image_options = {'resize': False, 'resize_size': IMAGE_SIZE}
    if FLAGS.mode == 'train':
        train_dataset_reader = dataset.BatchDatasetReader(train_records, image_options, FLAGS.data_dir)
        validation_dataset_reader = dataset.BatchDatasetReader(valid_records, image_options, FLAGS.data_dir)

    tf_config = tf.ConfigProto()
    tf_config.gpu_options.per_process_gpu_memory_fraction = 0.7
    sess = tf.Session(config=tf_config)

    print("Setting up Saver...")
    saver = tf.train.Saver()
    summary_writer = tf.summary.FileWriter(FLAGS.logs_dir, sess.graph)

    sess.run(tf.initialize_all_variables())
    # print(sess.run(tf.trainable_variables()))

    ckpt = tf.train.get_checkpoint_state(FLAGS.logs_dir)
    if ckpt and ckpt.model_checkpoint_path:
        saver.restore(sess, ckpt.model_checkpoint_path)
        print("Model restored...")

    if FLAGS.mode == "train":
        for itr in xrange(MAX_ITERATION):
            train_images, train_annotations = train_dataset_reader.read_next_batch(FLAGS.batch_size)
            feed_dict = {image: train_images, annotation: train_annotations, keep_probability: 0.85}

            sess.run(train_op, feed_dict=feed_dict)
            print(sess.run(c_l_l, feed_dict=feed_dict))
            if itr % 10 == 0:
                train_loss, summary_str = sess.run([loss, summary_op], feed_dict=feed_dict)
                print("Step: %d, Train_loss:%g" % (itr, train_loss))
                summary_writer.add_summary(summary_str, itr)

            if itr % 500 == 0:
                valid_images, valid_annotations = validation_dataset_reader.read_next_batch(FLAGS.batch_size)
                valid_loss = sess.run(loss, feed_dict={image: valid_images, annotation: valid_annotations,
                                                       keep_probability: 1.0})
                pred = sess.run(pred_annotation, feed_dict={image: valid_images, annotation: valid_annotations,
                                keep_probability: 1.0})
                valid_accu = accuracy.batch_calc_accuracy(pred, valid_annotations)
                print("%s ---> Validation_accu: %g" % (datetime.datetime.now(), valid_accu))
                print("%s ---> Validation_loss: %g" % (datetime.datetime.now(), valid_loss))
                saver.save(sess, FLAGS.logs_dir + "model.ckpt", itr)

    elif FLAGS.mode == "visualize":
        valid_images, valid_annotations = validation_dataset_reader.get_random_batch(FLAGS.batch_size)
        # pred = sess.run(pred_annotation, feed_dict={image: valid_images, annotation: valid_annotations,
        #                                             keep_probability: 1.0})
        # pred = np.squeeze(pred, axis=3)

        # save the prediction
        pass
        # for itr in range(FLAGS.batch_size):
        #     # save gt
        #     pal = (Image.open('/home/jingyang/Desktop/fcn/fcn_test/dataset/SegmentationClass_tranformed/2007_000032.png')).getpalette()
        #     new_img = Image.fromarray(valid_annotations[itr], mode="P")
        #     new_img.putpalette(pal)
        #     path = "logs/gt_"+ str(5 + itr)+".png"
        #     new_img.save(path)
        #     # save inp
        #     utils.save_image(valid_images[itr].astype(np.uint8), FLAGS.logs_dir, name="inp_" + str(5 + itr))
        #     #utils.save_image(valid_annotations[itr].astype(np.uint8), FLAGS.logs_dir, name="gt_" + str(5 + itr))
        #     # save pred
        #     new_img = Image.fromarray(pred[itr], mode="P")
        #     new_img.putpalette(pal)
        #     path = "logs/pred_"+ str(5 + itr)+".png"
        #     new_img.save(path)
        #     # utils.save_image(pred[itr].astype(np.uint8), FLAGS.logs_dir, name="pred_" + str(5 + itr))
        #     print("Saved image: %d" % itr)

if __name__ == "__main__":
    tf.app.run()