#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Oct  4 07:33:11 2019

@author: vboas
"""

import numpy as np
from scipy.stats import multivariate_normal
import matplotlib.pyplot as plt
import itertools
import functools

class SigmoidalFeature(object):
    """
    Sigmoidal features

    1 / (1 + exp((m - x) @ c)
    """

    def __init__(self, mean, coef=1):
        """
        construct sigmoidal features

        Parameters
        ----------
        mean : (n_features, ndim) or (n_features,) ndarray
            center of sigmoid function
        coef : (ndim,) ndarray or int or float
            coefficient to be multplied with the distance
        """
        if mean.ndim == 1:
            mean = mean[:, None]
        else:
            assert mean.ndim == 2
        if isinstance(coef, int) or isinstance(coef, float):
            if np.size(mean, 1) == 1:
                coef = np.array([coef])
            else:
                raise ValueError("mismatch of dimension")
        else:
            assert coef.ndim == 1
            assert np.size(mean, 1) == len(coef)
        self.mean = mean
        self.coef = coef

    def _sigmoid(self, x, mean):
        return np.tanh((x - mean) @ self.coef * 0.5) * 0.5 + 0.5

    def transform(self, x):
        """
        transform input array with sigmoidal features

        Parameters
        ----------
        x : (sample_size, ndim) or (sample_size,) ndarray
            input array

        Returns
        -------
        output : (sample_size, n_features) ndarray
            sigmoidal features
        """
        if x.ndim == 1:
            x = x[:, None]
        else:
            assert x.ndim == 2
        assert np.size(x, 1) == np.size(self.mean, 1)
        basis = [np.ones(len(x))]
        for m in self.mean:
            basis.append(self._sigmoid(x, m))
        return np.asarray(basis).transpose()

class PolynomialFeature(object):
    """
    polynomial features

    transforms input array with polynomial features

    Example
    =======
    x =
    [[a, b],
    [c, d]]

    y = PolynomialFeatures(degree=2).transform(x)
    y =
    [[1, a, b, a^2, a * b, b^2],
    [1, c, d, c^2, c * d, d^2]]
    """

    def __init__(self, degree=2):
        """
        construct polynomial features

        Parameters
        ----------
        degree : int
            degree of polynomial
        """
        assert isinstance(degree, int)
        self.degree = degree

    def transform(self, x):
        """
        transforms input array with polynomial features

        Parameters
        ----------
        x : (sample_size, n) ndarray
            input array

        Returns
        -------
        output : (sample_size, 1 + nC1 + ... + nCd) ndarray
            polynomial features
        """
        if x.ndim == 1:
            x = x[:, None]
        x_t = x.transpose()
        features = [np.ones(len(x))]
        for degree in range(1, self.degree + 1):
            for items in itertools.combinations_with_replacement(x_t, degree):
                features.append(functools.reduce(lambda x, y: x * y, items))
        return np.asarray(features).transpose()

class GaussianFeature(object):
    """
    Gaussian feature

    gaussian function = exp(-0.5 * (x - m) / v)
    """

    def __init__(self, mean, var):
        """
        construct gaussian features

        Parameters
        ----------
        mean : (n_features, ndim) or (n_features,) ndarray
            places to locate gaussian function at
        var : float
            variance of the gaussian function
        """
        if mean.ndim == 1:
            mean = mean[:, None]
        else:
            assert mean.ndim == 2
        assert isinstance(var, float) or isinstance(var, int)
        self.mean = mean
        self.var = var

    def _gauss(self, x, mean):
        return np.exp(-0.5 * np.sum(np.square(x - mean), axis=-1) / self.var)

    def transform(self, x):
        """
        transform input array with gaussian features

        Parameters
        ----------
        x : (sample_size, ndim) or (sample_size,)
            input array

        Returns
        -------
        output : (sample_size, n_features)
            gaussian features
        """
        if x.ndim == 1:
            x = x[:, None]
        else:
            assert x.ndim == 2
        assert np.size(x, 1) == np.size(self.mean, 1)
        basis = [np.ones(len(x))]
        for m in self.mean:
            basis.append(self._gauss(x, m))
        return np.asarray(basis).transpose()

class Regression(object):
    """
    Base class for regressors
    """
    pass

class LinearRegression(Regression):
    """
    Linear regression model
    y = X @ w
    t ~ N(t|X @ w, var)
    """

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        perform least squares fitting

        Parameters
        ----------
        X : (N, D) np.ndarray
            training independent variable
        t : (N,) np.ndarray
            training dependent variable
        """
        self.w = np.linalg.pinv(X) @ t
        self.var = np.mean(np.square(X @ self.w - t))

    def predict(self, X:np.ndarray, return_std:bool=False):
        """
        make prediction given input

        Parameters
        ----------
        X : (N, D) np.ndarray
            samples to predict their output
        return_std : bool, optional
            returns standard deviation of each predition if True

        Returns
        -------
        y : (N,) np.ndarray
            prediction of each sample
        y_std : (N,) np.ndarray
            standard deviation of each predition
        """
        y = X @ self.w
        if return_std:
            y_std = np.sqrt(self.var) + np.zeros_like(y)
            return y, y_std
        return y

class RidgeRegression(Regression):
    """
    Ridge regression model

    w* = argmin |t - X @ w| + alpha * |w|_2^2
    """

    def __init__(self, alpha:float=1.):
        self.alpha = alpha

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        maximum a posteriori estimation of parameter

        Parameters
        ----------
        X : (N, D) np.ndarray
            training data independent variable
        t : (N,) np.ndarray
            training data dependent variable
        """

        eye = np.eye(np.size(X, 1))
        self.w = np.linalg.solve(self.alpha * eye + X.T @ X, X.T @ t)

    def predict(self, X:np.ndarray):
        """
        make prediction given input

        Parameters
        ----------
        X : (N, D) np.ndarray
            samples to predict their output

        Returns
        -------
        (N,) np.ndarray
            prediction of each input
        """
        return X @ self.w

class BayesianRegression(Regression):
    """
    Bayesian regression model

    w ~ N(w|0, alpha^(-1)I)
    y = X @ w
    t ~ N(t|X @ w, beta^(-1))
    """

    def __init__(self, alpha:float=1., beta:float=1.):
        self.alpha = alpha
        self.beta = beta
        self.w_mean = None
        self.w_precision = None

    def _is_prior_defined(self) -> bool:
        return self.w_mean is not None and self.w_precision is not None

    def _get_prior(self, ndim:int) -> tuple:
        if self._is_prior_defined():
            return self.w_mean, self.w_precision
        else:
            return np.zeros(ndim), self.alpha * np.eye(ndim)

    def fit(self, X:np.ndarray, t:np.ndarray):
        """
        bayesian update of parameters given training dataset

        Parameters
        ----------
        X : (N, n_features) np.ndarray
            training data independent variable
        t : (N,) np.ndarray
            training data dependent variable
        """

        mean_prev, precision_prev = self._get_prior(np.size(X, 1))

        w_precision = precision_prev + self.beta * X.T @ X
        w_mean = np.linalg.solve(
            w_precision,
            precision_prev @ mean_prev + self.beta * X.T @ t
        )
        self.w_mean = w_mean
        self.w_precision = w_precision
        self.w_cov = np.linalg.inv(self.w_precision)

    def predict(self, X:np.ndarray, return_std:bool=False, sample_size:int=None):
        """
        return mean (and standard deviation) of predictive distribution

        Parameters
        ----------
        X : (N, n_features) np.ndarray
            independent variable
        return_std : bool, optional
            flag to return standard deviation (the default is False)
        sample_size : int, optional
            number of samples to draw from the predictive distribution
            (the default is None, no sampling from the distribution)

        Returns
        -------
        y : (N,) np.ndarray
            mean of the predictive distribution
        y_std : (N,) np.ndarray
            standard deviation of the predictive distribution
        y_sample : (N, sample_size) np.ndarray
            samples from the predictive distribution
        """

        if sample_size is not None:
            w_sample = np.random.multivariate_normal(
                self.w_mean, self.w_cov, size=sample_size
            )
            y_sample = X @ w_sample.T
            return y_sample
        y = X @ self.w_mean
        if return_std:
            y_var = 1 / self.beta + np.sum(X @ self.w_cov * X, axis=1)
            y_std = np.sqrt(y_var)
            return y, y_std
        return y

class EmpiricalBayesRegression(BayesianRegression):
    """
    Empirical Bayes Regression model
    a.k.a.
    type 2 maximum likelihood,
    generalized maximum likelihood,
    evidence approximation

    w ~ N(w|0, alpha^(-1)I)
    y = X @ w
    t ~ N(t|X @ w, beta^(-1))
    evidence function p(t|X,alpha,beta) = S p(t|w;X,beta)p(w|0;alpha) dw
    """

    def __init__(self, alpha:float=1., beta:float=1.):
        super().__init__(alpha, beta)

    def fit(self, X:np.ndarray, t:np.ndarray, max_iter:int=100):
        """
        maximization of evidence function with respect to
        the hyperparameters alpha and beta given training dataset

        Parameters
        ----------
        X : (N, D) np.ndarray
            training independent variable
        t : (N,) np.ndarray
            training dependent variable
        max_iter : int
            maximum number of iteration
        """
        M = X.T @ X
        eigenvalues = np.linalg.eigvalsh(M)
        eye = np.eye(np.size(X, 1))
        N = len(t)
        for _ in range(max_iter):
            params = [self.alpha, self.beta]

            w_precision = self.alpha * eye + self.beta * X.T @ X
            w_mean = self.beta * np.linalg.solve(w_precision, X.T @ t)

            gamma = np.sum(eigenvalues / (self.alpha + eigenvalues))
            self.alpha = float(gamma / np.sum(w_mean ** 2).clip(min=1e-10))
            self.beta = float(
                (N - gamma) / np.sum(np.square(t - X @ w_mean))
            )
            if np.allclose(params, [self.alpha, self.beta]):
                break
        self.w_mean = w_mean
        self.w_precision = w_precision
        self.w_cov = np.linalg.inv(w_precision)

    def _log_prior(self, w):
        return -0.5 * self.alpha * np.sum(w ** 2)

    def _log_likelihood(self, X, t, w):
        return -0.5 * self.beta * np.square(t - X @ w).sum()

    def _log_posterior(self, X, t, w):
        return self._log_likelihood(X, t, w) + self._log_prior(w)

    def log_evidence(self, X:np.ndarray, t:np.ndarray):
        """
        logarithm or the evidence function

        Parameters
        ----------
        X : (N, D) np.ndarray
            indenpendent variable
        t : (N,) np.ndarray
            dependent variable
        Returns
        -------
        float
            log evidence
        """
        N = len(t)
        D = np.size(X, 1)
        return 0.5 * (
            D * np.log(self.alpha) + N * np.log(self.beta)
            - np.linalg.slogdet(self.w_precision)[1] - D * np.log(2 * np.pi)
        ) + self._log_posterior(X, t, self.w_mean)

# 3. Linear Models for Regression
np.random.seed(1234)

def create_toy_data(func, sample_size, std, domain=[0, 1]):
    x = np.linspace(domain[0], domain[1], sample_size)
    np.random.shuffle(x)
    t = func(x) + np.random.normal(scale=std, size=x.shape)
    return x, t

# 3.1 Linear Basis Function Models
x = np.linspace(-1, 1, 100)
X_polynomial = PolynomialFeature(11).transform(x[:, None])
X_gaussian = GaussianFeature(np.linspace(-1, 1, 11), 0.1).transform(x)
X_sigmoidal = SigmoidalFeature(np.linspace(-1, 1, 11), 10).transform(x)

plt.figure(figsize=(20, 5))
for i, X in enumerate([X_polynomial, X_gaussian, X_sigmoidal]):
    plt.subplot(1, 3, i + 1)
    for j in range(12):
        plt.plot(x, X[:, j])

# 3.1.1 Maximum likelihood and least squares
def sinusoidal(x):
    return np.sin(2 * np.pi * x)

x_train, y_train = create_toy_data(sinusoidal, 10, 0.25)
x_test = np.linspace(0, 1, 100)
y_test = sinusoidal(x_test)

# Pick one of the three features below
# feature = PolynomialFeature(8)
feature = GaussianFeature(np.linspace(0, 1, 8), 0.1)
# feature = SigmoidalFeature(np.linspace(0, 1, 8), 10)

X_train = feature.transform(x_train)
X_test = feature.transform(x_test)
model = LinearRegression()
model.fit(X_train, y_train)
y, y_std = model.predict(X_test, return_std=True)

plt.scatter(x_train, y_train, facecolor="none", edgecolor="b", s=50, label="training data")
plt.plot(x_test, y_test, label="$\sin(2\pi x)$")
plt.plot(x_test, y, label="prediction")
plt.fill_between(
    x_test, y - y_std, y + y_std,
    color="orange", alpha=0.5, label="std.")
plt.legend()
plt.show()

# 3.1.4 Regularized least squares
model = RidgeRegression(alpha=1e-3)
model.fit(X_train, y_train)
y = model.predict(X_test)

plt.scatter(x_train, y_train, facecolor="none", edgecolor="b", s=50, label="training data")
plt.plot(x_test, y_test, label="$\sin(2\pi x)$")
plt.plot(x_test, y, label="prediction")
plt.legend()
plt.show()

# 3.2 The Bias-Variance Decomposition
# feature = PolynomialFeature(24)
feature = GaussianFeature(np.linspace(0, 1, 24), 0.1)
# feature = SigmoidalFeature(np.linspace(0, 1, 24), 10)

for a in [1e2, 1., 1e-9]:
    y_list = []
    plt.figure(figsize=(20, 5))
    plt.subplot(1, 2, 1)
    for i in range(100):
        x_train, y_train = create_toy_data(sinusoidal, 25, 0.25)
        X_train = feature.transform(x_train)
        X_test = feature.transform(x_test)
        model = BayesianRegression(alpha=a, beta=1.)
        model.fit(X_train, y_train)
        y = model.predict(X_test)
        y_list.append(y)
        if i < 20:
            plt.plot(x_test, y, c="orange")
    plt.ylim(-1.5, 1.5)

    plt.subplot(1, 2, 2)
    plt.plot(x_test, y_test)
    plt.plot(x_test, np.asarray(y_list).mean(axis=0))
    plt.ylim(-1.5, 1.5)
    plt.show()


# coding=utf-8
import torch
from torch.nn import functional as F
from torch.nn.modules import Module

class PrototypicalLoss(Module):
    '''
    Loss class deriving from Module for the prototypical loss function defined below
    '''
    def __init__(self, n_support):
        super(PrototypicalLoss, self).__init__()
        self.n_support = n_support

    def forward(self, input, target):
        return prototypical_loss(input, target, self.n_support)

def euclidean_dist(x, y):
    '''
    Compute euclidean distance between two tensors
    '''
    # x: N x D
    # y: M x D
    n = x.size(0)
    m = y.size(0)
    d = x.size(1)
    if d != y.size(1):
        raise Exception

    x = x.unsqueeze(1).expand(n, m, d)
    y = y.unsqueeze(0).expand(n, m, d)

    return torch.pow(x - y, 2).sum(2)

def prototypical_eval(input, target, prototypes):
    target_cpu = target.to('cpu')
    input_cpu = input.to('cpu')
    dists = euclidean_dist(input_cpu, prototypes)
    #print(dists.size(), input_cpu.size(), prototypes.size())
    log_p_y = F.log_softmax(-dists, dim=1)
    #print(log_p_y.size())
    _, y_hat = log_p_y.max(1)
    #print(y_hat.size(), target_cpu.size())
    acc_val = y_hat.eq(target_cpu).float().mean()
    return acc_val, y_hat


# Analog PyGame clock

import pygame
import pygame_gui
from pygame_gui.elements.ui_image import UIImage

from math import pi, cos, sin
import datetime

DARK = 33, 41, 46
WHITE = 255, 255, 255
GRAY = 76, 80, 82
RED = 255, 0, 0

class SnakeAClock(pygame_gui.elements.UIWindow):
    DIMS = (300, 300)

    def __init__(self, pos, manager):
        super().__init__(
            pygame.Rect(pos, (self.DIMS[0] + 32, self.DIMS[1] + 60)),
            manager=manager,
            window_display_title="aclock",
            object_id="#aclock",
            resizable=True,
        )

        self.dsurf = UIImage(
            pygame.Rect((0, 0), self.DIMS),
            pygame.Surface(self.DIMS).convert(),
            manager=manager,
            container=self,
            parent_element=self,
        )
        self.draw_dial()
        self.clean_dial = self.dial.copy()
        self.manager = manager

    def process_event(self, event):
        super().process_event(event)
        r = super().get_abs_rect()
        if event.type == pygame.MOUSEBUTTONUP and (
            r.w != self.DIMS[0] + 32 or r.h != self.DIMS[1] + 60
        ):
            self.DIMS = r.w - 32, r.h - 60
            super().kill()
            self.__init__((r.left, r.top), self.manager)

    def update(self, delta):
        super().update(delta)
        self.dial = self.clean_dial.copy()
        self.draw_hands()
        self.dsurf.image.blit(self.dial, (0, 0))

    def clocksize(self):
        return int(0.95 * min(self.DIMS) / 2)

    def diam(self, x, r1, r2, r3, dx):
        x1, y1 = (
            r1 * self.clocksize() * sin(x * pi / 180),
            r1 * self.clocksize() * cos(x * pi / 180),
        )
        x2, y2 = (
            r2 * self.clocksize() * sin((x + dx) * pi / 180),
            r2 * self.clocksize() * cos((x + dx) * pi / 180),
        )
        x3, y3 = (
            r3 * self.clocksize() * sin(x * pi / 180),
            r3 * self.clocksize() * cos(x * pi / 180),
        )
        x4, y4 = (
            r2 * self.clocksize() * sin((x - dx) * pi / 180),
            r2 * self.clocksize() * cos((x - dx) * pi / 180),
        )
        p = [
            (int(x1 + self.DIMS[0] // 2), int(-y1 + self.DIMS[1] // 2)),
            (int(x2 + self.DIMS[0] // 2), int(-y2 + self.DIMS[1] // 2)),
            (int(x3 + self.DIMS[0] // 2), int(-y3 + self.DIMS[1] // 2)),
            (int(x4 + self.DIMS[0] // 2), int(-y4 + self.DIMS[1] // 2)),
        ]
        pygame.draw.polygon(self.dial, WHITE, p)

    def draw_dial(self):
        self.dial = pygame.Surface(self.DIMS)
        self.dial.fill(DARK)
        pygame.draw.circle(
            self.dial, WHITE, (self.DIMS[0] // 2, self.DIMS[1] // 2), self.clocksize()
        )
        pygame.draw.circle(
            self.dial,
            GRAY,
            (self.DIMS[0] // 2, self.DIMS[1] // 2),
            int(0.99 * self.clocksize()),
        )
        for x in range(60):
            if x % 5 == 0:
                continue
            x1, y1 = (
                0.95 * self.clocksize() * sin(6 * x * pi / 180),
                0.95 * self.clocksize() * cos(6 * x * pi / 180),
            )
            x2, y2 = (
                0.92 * self.clocksize() * sin(6 * x * pi / 180),
                0.92 * self.clocksize() * cos(6 * x * pi / 180),
            )
            pygame.draw.line(
                self.dial,
                WHITE,
                (int(x1 + self.DIMS[0] // 2), int(y1 + self.DIMS[1] // 2)),
                (int(x2 + self.DIMS[0] // 2), int(y2 + self.DIMS[1] // 2)),
                2,
            )
        for x in range(0, 360, 30):
            if x % 90 == 0:
                self.diam(x, 0.95, 0.88, 0.88, 2)
            else:
                self.diam(x, 0.95, 0.95, 0.87, 1)

    def draw_hands(self):
        # hour hand
        now = datetime.datetime.now()
        x = 30 * ((now.hour - 12) % 12) + now.minute / 2
        self.diam(x, 0.45, 0.08, -0.08, 30)

        # minute hand
        x = 6 * now.minute + now.second / 10
        self.diam(x, 0.75, 0.08, -0.08, 25)

        # second hand
        x = 6 * now.second
        x1, y1 = (
            0.8 * self.clocksize() * sin(x * pi / 180),
            0.8 * self.clocksize() * cos(x * pi / 180),
        )
        x2, y2 = 0, 0
        pygame.draw.line(
            self.dial,
            RED,
            (int(x1 + self.DIMS[0] // 2), int(-y1 + self.DIMS[1] // 2)),
            (int(x2 + self.DIMS[0] // 2), int(-y2 + self.DIMS[1] // 2)),
            3,
        )


from perfis import views
from django.urls import path
from django.contrib.auth import views as v
from usuarios.views import RegistrarUsuarioView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
	path('', views.index, name='index'),
	path('perfil/<int:perfil_id>', views.exibir_perfil, name='exibir'),
	path('perfil/<int:perfil_id>/convidar', views.convidar, name='convidar'),
	path('perfil/<int:perfil_id>/desfazer', views.desfazer, name='desfazer'),
	path('convite/<int:convite_id>/aceitar', views.aceitar, name='aceitar'),
	path('convite/<int:convite_id>/recusar', views.recusar, name='recusar'),
	path('login/', v.LoginView.as_view(template_name='usuarios/login.html'), name='login'),
	path('logout/', v.LogoutView.as_view(template_name='usuarios/login.html'), name="logout"),
	path('registrar/', RegistrarUsuarioView.as_view(), name='registrar'),
	path('password/', views.change_password, name='change_password'),
	path('feed/', views.feed, name='feed'),
	path('promover/<int:perfil_id>', views.promover, name='promover'),
	path('desativar/',views.desativar, name='desativar'),
	path('reativar/',views.reativar, name='reativar'),
	path('bloquear/<int:perfil_id>',views.bloquear,name='bloquear'),
	path('desbloquear/<int:perfil_id>',views.desbloquear, name='desbloquear'),
	path('search', views.search, name='search'),
	path('updatefoto',views.updatefoto, name='updatefoto'),
	path('perfil_list', views.perfil_list, name='perfil_list'),
]
if settings.DEBUG:
	urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


import numpy as np
import pandas as pd

import h5py
import json

from dev_link import *
from util import *

from icecream import ic

class VibExportIms:
    """ Handles reading IMS dataset feature extraction output in CSV (by previous project)
    and exporting to h5py data record,
    with the following properties: RMS_time, Range_time, Kurtosis, Skewness, Range_freq, Peak_freq, Mean_freq, Peak_amp

    .. note:: The 1st test has 2 dimension for each of the 4 bearings
    .. note:: The 4th test is defined test 3

    .. note:: The 1st row in the feature domain intentionally removed was included for export

    Split into 4 partitions with names: [test1/ch1/, test1/ch2/, test2/, test3/]
    """
    FEAT_CSV_NMS = dict(
        rms_time='RMS',
        range_time='p2p',
        kurtosis='kurtosis',
        skewness='skew',
        rms_freq='rmsFeq',
        mean_freq='meanFeq',
        peak_freq='peakFeq',
        rot_amp='peakAmp'
    )

    ENC_FEAT_STOR = dict(  # Dictionary on storage encoding of properties
        rms_time=0,
        range_time=1,
        kurtosis=2,
        skewness=3,
        rms_freq=4,
        mean_freq=5,
        peak_freq=6,
        rot_amp=7
    )

    def get_test_feature_series(self, idx_tst, feat='rms_time'):
        """ Feature across all channels available """
        fl_nm = f'{FEAT_PATH_IMS}test{idx_tst+1}_{self.FEAT_CSV_NMS[feat]}.csv'
        df = pd.read_csv(fl_nm, header=None)
        return df.to_numpy().T

    def get_feature_series(self, idx_tst, idx_brg, feat='rms_time', ch=None):
        """
        :param idx_tst: The test number index in [0, 2] for 3 tests
        :param idx_brg: The bearing index in [0, 3] for 4 bearings
        :param feat: Feature/Property
        :param ch: Which channel of bearing vibration, integer in [0, 1], only an option for test 1
        """
        idx = idx_brg if idx_tst != 0 else (idx_brg * 2 + ch)
        fl_nm = f'{FEAT_PATH_IMS}test{idx_tst+1}_{self.FEAT_CSV_NMS[feat]}.csv'
        df = pd.read_csv(fl_nm, header=None)
        return df[idx].to_numpy()

    def export(self, fl_nm='ims_features'):
        fl_nm = f'data/{fl_nm}.hdf5'
        open(fl_nm, 'a').close()  # Create file in OS
        fl = h5py.File(fl_nm, 'w')
        fl.attrs['feat_stor_idxs'] = json.dumps(self.ENC_FEAT_STOR)
        fl.attrs['nums_msr'] = json.dumps(config('ims.num_measurements'))
        tst_nms = []
        for (idx_tst, tst_nm) in [(0, '/ch1'), (1, '/ch2'), (2, ''), (3, '')]:
            i_tst = max(idx_tst - 1, 0)  # To be compatible with `get_feature_series`
            tst_nm = f'test{i_tst+1}{tst_nm}'
            tst_nms.append(tst_nm)
            group = fl.create_group(tst_nm)
            idxs_brg = list(range(config('ims.num_bearings')))
            # if idx_tst == 0:
            #     idxs_brg = [i * 2 for i in idxs_brg]
            # elif idx_tst == 1:
            #     idxs_brg = [i * 2 + 1 for i in idxs_brg]
            for idx_brg in idxs_brg:
                dset = np.stack([
                    self.get_feature_series(i_tst, idx_brg, feat=f, ch=idx_tst) for f in self.FEAT_CSV_NMS
                ])
                group.create_dataset(f'bearing{idx_brg+1}', data=dset)
        fl.attrs['tst_nms'] = json.dumps(tst_nms)  # 4 tests
        print(f'Metadata attributes created: {list(fl.attrs.keys())}')
        print(f'Features extracted: {[nm for nm in fl]}')


## variable gamma fiber...

## model creation of gamma fiber (111) // ND
# (hkl) // ND, random vector // RD

import numpy as np
import random
from euler import euler
gauss = random.gauss
expov = random.expovariate
logno = random.lognormvariate
norma = random.normalvariate
from sym import __mmm__ as mmm

def main(ngrains=100,sigma=5.,iopt=1,ifig=1):
    """
    arguments
    =========
    ngrains = 100
    sigma   = 5.
    iopt    = 1 (1: gauss (recommended); 2: expov; 3: logno; 4: norma)
    ifig    = 1
    """
    import upf
    import matplotlib.pyplot as plt
    h = mmm()
    gr = []
    for i in range(ngrains):
        dth = random.uniform(-180., 180.)
        g = gen_gamma_gr(dth, sigma, iopt=iopt)
        for j in range(len(h)):
            temp = np.dot(g,h[j].T)
            phi1,phi,phi2 = euler(a=temp, echo=False)
            gr.append([phi1,phi,phi2,1./ngrains])

    fn = 'gam_fib_ngr%s_sigma%s.cmb'%(str(len(gr)).zfill(5),str(sigma).zfill(3))
    f = open(fn,'w')
    f.writelines('Artificial gamma fibered polycrystal aggregate\n')
    f.writelines('var_gam_fiber.py python script\n')
    f.writelines('distribution: %s')
    if iopt==1: f.writelines(' gauss')
    if iopt==2: f.writelines(' expov')
    if iopt==3: f.writelines(' logno')
    if iopt==4: f.writelines(' norma')
    f.writelines('\n')
    f.writelines('B %i\n'%ngrains)
    for i in range(len(gr)):
        f.writelines('%7.3f %7.3f %7.3f %13.4e\n'%(
            gr[i][0], gr[i][1], gr[i][2], 1./len(gr)))

    upf.cubgr(gr=gr,ifig=ifig)
    plt.figure(ifig).savefig('%s.pdf'%(fn.split('.cmb')[0]))

    return np.array(gr)

def gen_gamma_gr(th=0.,sigma=5.,iopt=1):
    """
    grain generator for gamma fiber

    =========
    Arguments

    th       = 0.0
    sigma    = 5.0
    iopt     = 1
    """
    from text import miller2mat

    ## gamma fiber: axisymmetry about ND
    hkl, uvw = hkl_gamma()
    g_casa = miller2mat(hkl, uvw)
    g_sasa = nd_rot(th)
    ##

    g = np.dot(g_casa,g_sasa)
    if iopt==1: dth=gauss(mu=0., sigma=sigma)
    if iopt==2: dth=expov(sigma)
    if iopt==3: dth=logno(mu=0., sigma=sigma)
    if iopt==4: dth=norma(mu=0., sigma=sigma)

    return rot_vectang(th=dth, r=g)

def rd_rot(thet):
    return vector_ang(u=[1,0,0],th=thet)
def td_rot(thet):
    return vector_ang(u=[0,1,0],th=thet)
def nd_rot(thet):
    return vector_ang(u=[0,0,1],th=thet)

def rot_vectang(th,r):
    """ Rotate the given rotation matrix r
    [ca<-sa] by a random axis with th degree.
    """
    #import cs
    delta, phi = rot_rand_axis()
    v = polar2vect(delta,phi)
    #rot = cs.vector_ang(u=v, th=th)
    rot = vector_ang(u=v, th=th)
    newr = np.dot(rot,r)
    return newr

def rot_rand_axis():
    delta = random.uniform(-1.,1.)
    delta = np.arccos(delta)
    phi   = random.uniform(-np.pi, np.pi)
    return delta, phi

def polar2vect(delta, phi):
    """ Given delta and phi returns a vector"""
    x = np.cos(phi)
    y = np.sin(phi)
    z = np.sin(delta)
    vector = np.array([x,y,z])
    vector = vector / np.linalg.norm(vector)
    return vector

def vector_ang(u,th):
    """
    implementation of subroutine vector_ang in cs.f

    arguments
    =========
    u[3] = vector axis about whic the rotation occurs
    th   = radian angle (degree of the rotation)
    """
    u = np.array(u)
    u = u/np.sqrt((u**2).sum()) # normalize

    idx = np.identity(3)

    ct = np.cos(th*np.pi/180.)
    st = np.sin(th*np.pi/180.)
    cm = crossop(u) # cross product operator

    # print th
    # print ct, st
    # print cm
    # raw_input()

    r = np.zeros((3,3))

    for i in range(3):
        for j in range(3):
            r[i,j] = idx[i,j] * ct + st * cm[i,j] + \
                     (1. - ct ) * u[i] * u[j]

    return r

def crossop(u):
    """
    Cross operator can be used to obtain the cross
    product as a matrix-vector product

    a x b  = [a_x]_ij [b]_j
    """
    m=np.zeros((3,3))
    m[0][1] = -u[2]
    m[0][2] =  u[1]
    m[1][0] =  u[2]
    m[1][2] = -u[0]
    m[2][0] = -u[1]
    m[2][1] =  u[0]

    return m

# hkl // ND
# uvw // RD
# xyz // TD

"""
Only major diection is relevant
Any auxilary vector that is perpendicular to the
major will work it out.
 """
def hkl_gamma():
    hkl = [ 1, 1, 1] # major // ND
    uvw = [-1, 1, 0] # minor // RD
    return hkl, uvw

def hkl_alpha():
    uvw = [ 1, 1, 0] # major // RD
    hkl = [ 0, 0, 1] # minor // ND

def hkl_eta():
    uvw = [0,0,1] # major // RD
    hkl = [1,0,0] # minor // ND

def hkl_epsilon():
    xyz = [1,1,0] # major // TD
    uvw = [0,0,1] # minor // RD


from tkinter import *
from tkinter.ttk import *
import psutil
import time
from threading import Thread
import sys

import utils as Utils
import const.color as Colors
import const.dimensions as Dimensions
import const.config as Config

window = Tk()
window.title(Config.APP_NAME_SHORT)
window.geometry(f"{Dimensions.SCREEN_WIDTH}x{Dimensions.SCREEN_HEIGHT}")
window.resizable(False, False)

icon = PhotoImage(file="img/icon.gif")
window.iconphoto(False, icon)

window.grid_columnconfigure(0, weight=1)

# <-- ROW 0 - START -->

row_0 = Frame(window)
row_0.grid(row=0, column=0, sticky="nsew")
row_0.grid_columnconfigure(0, weight=1)
row_0.grid_columnconfigure(1, weight=3)

# row 0 col 0 (General)
sys_info_frame = LabelFrame(row_0, text="General", padding=Dimensions.PADDING_L)
sys_info_frame.grid(row=0, column=0, sticky="nsew")

sys_info_frame.battery_label = Label(sys_info_frame)
sys_info_frame.battery_label.grid(row=0, sticky=W)
sys_info_frame.uptime_label = Label(sys_info_frame)
sys_info_frame.uptime_label.grid(row=1, sticky=W)
sys_info_frame.cpu_cores_label = Label(sys_info_frame)
sys_info_frame.cpu_cores_label.grid(row=2,sticky=W)

# row 0 col 1 (Memory)
memory_info_frame = LabelFrame(row_0, text="Memory", padding=Dimensions.PADDING_L)
memory_info_frame.grid(row=0, column=1, sticky="nsew")
memory_info_frame.grid_columnconfigure(0, weight=1)
memory_info_frame.grid_columnconfigure(1, weight=1)

memory_info_frame.mem_total = Label(memory_info_frame, font='Arial 12', foreground=Colors.GRAY)
memory_info_frame.mem_total.grid(row=0, column=0, sticky=W)
memory_info_frame.mem_used = Label(memory_info_frame, font='Arial 12', foreground=Colors.BLUE)
memory_info_frame.mem_used.grid(row=0, column=1, sticky=W)
memory_info_frame.mem_free = Label(memory_info_frame, font='Arial 12', foreground=Colors.BLACK)
memory_info_frame.mem_free.grid(row=0, column=2, sticky=W)
memory_info_frame.status_bar = Progressbar(memory_info_frame, orient=HORIZONTAL, mode="determinate", length=100)
memory_info_frame.status_bar.grid(row=1, columnspan=3, sticky=W+E)

# <-- ROW 0 - END -->

# <-- ROW 1 - START -->

row_1 = Frame(window)
row_1.grid(row=1, column=0, sticky="nsew")
row_1.grid_columnconfigure(0, weight=1)
row_1.grid_columnconfigure(1, weight=1)

# row 1 col 0 (RAM Usage)
ram_usage_frame = LabelFrame(row_1, text="RAM Usage", padding=Dimensions.PADDING_L)
ram_usage_frame.grid(row=0, column=0, sticky="nsew")
ram_usage_frame.grid_columnconfigure(0, weight=1)

ram_usage_frame.status_bar = Progressbar(ram_usage_frame, orient=HORIZONTAL, mode="determinate", length=100)
ram_usage_frame.status_bar.grid(row=0, sticky=W+E)
ram_usage_frame.status = Label(ram_usage_frame, font="Arial 15")
ram_usage_frame.status.grid(row=1, sticky=W+E)

# row 1 col 1 (CPU Usage)
cpu_usage_frame = LabelFrame(row_1, text="CPU Usage", padding=Dimensions.PADDING_L)
cpu_usage_frame.grid(row=0, column=1, sticky="nsew")
cpu_usage_frame.grid_columnconfigure(0, weight=1)

cpu_usage_frame.status_bar = Progressbar(cpu_usage_frame, orient=HORIZONTAL, mode="determinate", length=100)
cpu_usage_frame.status_bar.grid(row=0, sticky=W+E)
cpu_usage_frame.status = Label(cpu_usage_frame, font="Arial 15")
cpu_usage_frame.status.grid(row=1, sticky=W+E)

# <-- ROW 1 - END -->

# <-- ROW 2 - START -->

row_2 = Frame(window)
row_2.grid(row=2, column=0, sticky="nswe")
row_2.grid_columnconfigure(0, weight=1)

# row 2 col 0 (Tasks)
tasks_count_frame = LabelFrame(row_2, text="Tasks")
tasks_count_frame.grid(sticky="nswe")
tasks_count_frame.grid_columnconfigure(0, weight=1)
tasks_count_frame.grid_columnconfigure(1, weight=1)
tasks_count_frame.grid_columnconfigure(2, weight=1)
tasks_count_frame.grid_columnconfigure(3, weight=1)
tasks_count_frame.grid_columnconfigure(4, weight=1)

tasks_count_frame.total = Label(tasks_count_frame, font="Arial 12", padding=Dimensions.PADDING_S)
tasks_count_frame.total.grid(row=0, column=0, sticky="nsew")
tasks_count_frame.running = Label(tasks_count_frame, font="Arial 12", padding=Dimensions.PADDING_S)
tasks_count_frame.running.grid(row=0, column=1, sticky="nsew")
tasks_count_frame.sleeping = Label(tasks_count_frame, font="Arial 12", padding=Dimensions.PADDING_S)
tasks_count_frame.sleeping.grid(row=0, column=2, sticky="nsew")
tasks_count_frame.stopped = Label(tasks_count_frame, font="Arial 12", padding=Dimensions.PADDING_S)
tasks_count_frame.stopped.grid(row=0, column=3, sticky="nsew")
tasks_count_frame.zombie = Label(tasks_count_frame, font="Arial 12", padding=Dimensions.PADDING_S)
tasks_count_frame.zombie.grid(row=0, column=4, sticky="nsew")

# <-- ROW 2 - END -->

# <-- ROW 3 - START -->

row_3 = Frame(window)
row_3.grid(row=3, column=0, sticky="nswe")
row_3.grid_columnconfigure(0, weight=1)
row_3.grid_columnconfigure(1, weight=1)

# row 3 col 0 (Network)
network_frame = LabelFrame(row_3, text="Network", padding=Dimensions.PADDING_L)
network_frame.grid(row=0, column=0, sticky="nswe")
network_frame.grid_columnconfigure(0, weight=1)
network_frame.grid_columnconfigure(1, weight=1)
network_frame.grid_rowconfigure(0, weight=1)
network_frame.grid_rowconfigure(1, weight=1)

c00 = Frame(network_frame)
c00.grid(row=0, column=0, sticky="nswe")
c00.title = Label(c00, text="Download")
c00.title.grid(row=0, sticky=W)
c00.val = Label(c00, font='Arial 18')
c00.val.grid(row=1, sticky=W)

c01 = Frame(network_frame)
c01.grid(row=0, column=1, sticky="nswe")
c01.title = Label(c01, text="Download Speed")
c01.title.grid(row=0, sticky=W)
c01.val = Label(c01, foreground=Colors.GREEN, font='Arial 18')
c01.val.grid(row=1, sticky=W)

c10 = Frame(network_frame)
c10.grid(row=1, column=0, sticky="nswe")
c10.title = Label(c10, text="Upload")
c10.title.grid(row=0, sticky=W)
c10.val = Label(c10, font='Arial 18')
c10.val.grid(row=1, sticky=W)

c11 = Frame(network_frame)
c11.grid(row=1, column=1, sticky="nswe")
c11.title = Label(c11, text="Upload Speed")
c11.title.grid(row=0, sticky=W)
c11.val = Label(c11, foreground=Colors.RED, font='Arial 18')
c11.val.grid(row=1, sticky=W)

# row 3 col 1 (Top Precess)
top_process_frame = LabelFrame(row_3, text="Top process")
top_process_frame.grid(row=0, column=1, sticky="nswe")
top_process_frame.grid_columnconfigure(0, weight=1)
top_process_frame.grid_columnconfigure(1, weight=1)
top_process_frame.grid_columnconfigure(2, weight=1)
top_process_frame.grid_columnconfigure(3, weight=1)
top_process_frame.grid_columnconfigure(4, weight=1)

# table header starts
top_process_frame.c00 = Label(top_process_frame, text="pid", padding=Dimensions.PADDING_S, font='bold')
top_process_frame.c00.grid(row=0, column=0, sticky="w")
top_process_frame.c01 = Label(top_process_frame, text="Name", padding=Dimensions.PADDING_S, font='bold')
top_process_frame.c01.grid(row=0, column=1, sticky="w")
top_process_frame.c02 = Label(top_process_frame, text="Usage", padding=Dimensions.PADDING_S, font='bold')
top_process_frame.c02.grid(row=0, column=2, sticky="w")
top_process_frame.c03 = Label(top_process_frame, text="Status", padding=Dimensions.PADDING_S, font='bold')
top_process_frame.c03.grid(row=0, column=3, sticky="w")
top_process_frame.c04 = Label(top_process_frame, text="Threads", padding=Dimensions.PADDING_S, font='bold')
top_process_frame.c04.grid(row=0, column=4, sticky="w")
# table header ends

# table row 1 starts
top_process_frame.c10 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c10.grid(row=1, column=0, sticky="w")
top_process_frame.c11 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c11.grid(row=1, column=1, sticky="w")
top_process_frame.c12 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c12.grid(row=1, column=2, sticky="w")
top_process_frame.c13 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c13.grid(row=1, column=3, sticky="w")
top_process_frame.c14 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c14.grid(row=1, column=4, sticky="w")
# table row 1 ends

# table row 2 starts
top_process_frame.c20 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c20.grid(row=2, column=0, sticky="w")
top_process_frame.c21 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c21.grid(row=2, column=1, sticky="w")
top_process_frame.c22 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c22.grid(row=2, column=2, sticky="w")
top_process_frame.c23 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c23.grid(row=2, column=3, sticky="w")
top_process_frame.c24 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c24.grid(row=2, column=4, sticky="w")
# table row 2 ends

# table row 3 starts
top_process_frame.c30 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c30.grid(row=3, column=0, sticky="w")
top_process_frame.c31 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c31.grid(row=3, column=1, sticky="w")
top_process_frame.c32 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c32.grid(row=3, column=2, sticky="w")
top_process_frame.c33 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c33.grid(row=3, column=3, sticky="w")
top_process_frame.c34 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c34.grid(row=3, column=4, sticky="w")
# table row 3 ends

# table row 4 starts
top_process_frame.c40 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c40.grid(row=4, column=0, sticky="w")
top_process_frame.c41 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c41.grid(row=4, column=1, sticky="w")
top_process_frame.c42 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c42.grid(row=4, column=2, sticky="w")
top_process_frame.c43 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c43.grid(row=4, column=3, sticky="w")
top_process_frame.c44 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c44.grid(row=4, column=4, sticky="w")
# table row 4 ends

# table row 5 starts
top_process_frame.c50 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c50.grid(row=5, column=0, sticky="w")
top_process_frame.c51 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c51.grid(row=5, column=1, sticky="w")
top_process_frame.c52 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c52.grid(row=5, column=2, sticky="w")
top_process_frame.c53 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c53.grid(row=5, column=3, sticky="w")
top_process_frame.c54 = Label(top_process_frame, padding=Dimensions.PADDING_S)
top_process_frame.c54.grid(row=5, column=4, sticky="w")
# table row 5 ends

# <-- ROW 3 - END -->

# <-- ROW 4 - START -->

info_frame = Frame(window, padding=Dimensions.PADDING_L, relief=SUNKEN)
info_frame.grid(row=4, sticky="nswe")
info_frame.grid_columnconfigure(0, weight=1)

info_frame.title = Label(info_frame, text=Config.APP_NAME_LONG)
info_frame.title.grid(row=0)
auth_list = f"{Config.AUTH_AS} | {Config.AUTH_DF} | {Config.AUTH_SB} | {Config.AUTH_TP}"
info_frame.creators = Label(info_frame, text=auth_list)
info_frame.creators.grid(row=1)

# <-- ROW 4 - END -->

# NETWORK INFO CALCULATION - START
net_info_up = ""
net_info_dl = ""
net_info_up_speed = ""
net_info_dl_speed = ""

def network_info_stats():
    UPDATE_DELAY = 1
    io = psutil.net_io_counters()
    bytes_sent, bytes_recv = io.bytes_sent, io.bytes_recv
    while True:
        time.sleep(UPDATE_DELAY)
        io_2 = psutil.net_io_counters()
        us, ds = io_2.bytes_sent - bytes_sent, io_2.bytes_recv - bytes_recv
        global net_info_up
        net_info_up = Utils.get_size(io_2.bytes_sent)
        global net_info_dl
        net_info_dl = Utils.get_size(io_2.bytes_recv)
        global net_info_up_speed
        net_info_up_speed = Utils.get_size(us / UPDATE_DELAY)
        global net_info_dl_speed
        net_info_dl_speed = Utils.get_size(ds / UPDATE_DELAY)
        bytes_sent, bytes_recv = io_2.bytes_sent, io_2.bytes_recv

# a thread to find the network information
network_info_thread = Thread(target=network_info_stats)
network_info_thread.start()
# NETWORK INFO CALCULATION - START

app_running = True

while app_running:

    battery_percentage = psutil.sensors_battery().percent
    sys_info_frame.battery_label.config(text=f"Battery: {battery_percentage:.2f}%")

    up_time = time.time() - psutil.boot_time()
    up_time_hrs = up_time / 60 / 60
    final_up_time = ''
    if up_time_hrs > 1:
        final_up_time = str(f"{up_time_hrs:.2f} hrs")
    else:
        final_up_time = str(f"{up_time/60:.2f} min")
    sys_info_frame.uptime_label.config(text=f"Up Time: {final_up_time}")

    sys_info_frame.cpu_cores_label.config(text=f"CPU cores: {psutil.cpu_count()}")

    disk_usage = psutil.disk_usage('/')
    percentage_used = round(disk_usage.percent)
    total_memory = str(round(disk_usage.total / (1024.0 ** 3))) + 'GB'
    free_memory = str(round(disk_usage.free / (1024.0 ** 3))) + 'GB'
    used_memory = str(round(disk_usage.used / (1024.0 ** 3))) + 'GB'

    memory_info_frame.mem_total.config(text=f"Total: {total_memory}")
    memory_info_frame.mem_used.config(text=f"Used: {used_memory}")
    memory_info_frame.mem_free.config(text=f"Free: {free_memory}")

    disk_usage = psutil.disk_usage('/')
    percentage_used = round(disk_usage.percent)
    memory_info_frame.status_bar.config(value=percentage_used)

    ram_percentage = psutil.virtual_memory().percent
    percentage_used = round(ram_percentage)
    ram_usage_frame.status_bar.config(value=percentage_used)
    ram_usage_frame.status.config(text=f"{ram_percentage}%")

    cpu_percentage = psutil.cpu_percent()
    percentage_used = round(cpu_percentage)
    cpu_usage_frame.status_bar.config(value=percentage_used)
    cpu_usage_frame.status.config(text=f"{cpu_percentage}%")

    total_proc_no = 0
    running_proc_no = 0
    sleeping_proc_no = 0
    zombie_proc_no = 0
    stopped_proc_no = 0
    process_list = []
    for proc in psutil.process_iter():
        mem_p = round(proc.memory_percent(),2)
        process_list.append([
            proc.pid,
            proc.name(),
            f"{mem_p}%",
            proc.status(),
            proc.num_threads()
        ])
        total_proc_no += 1
        if (proc.status() == psutil.STATUS_RUNNING):
            running_proc_no += 1
        elif (proc.status() == psutil.STATUS_SLEEPING):
            sleeping_proc_no += 1
        elif (proc.status() == psutil.STATUS_ZOMBIE):
            zombie_proc_no += 1
        elif proc.status() == psutil.STATUS_STOPPED:
            stopped_proc_no += 1

    process_list.sort(key=lambda x:x[2], reverse=True)

    tasks_count_frame.total.config(text=f"Total:{total_proc_no}")
    tasks_count_frame.running.config(text=f"Running:{running_proc_no}")
    tasks_count_frame.sleeping.config(text=f"Sleeping:{sleeping_proc_no}")
    tasks_count_frame.stopped.config(text=f"Stopped:{stopped_proc_no}")
    tasks_count_frame.zombie.config(text=f"Zombie:{zombie_proc_no}")

    c00.val.config(text=net_info_up)
    c01.val.config(text=f"{net_info_up_speed}/s")
    c10.val.config(text=net_info_dl)
    c11.val.config(text=f"{net_info_dl_speed}/s")

    top_process_frame.c10.config(text=process_list[0][0])
    top_process_frame.c11.config(text=process_list[0][1])
    top_process_frame.c12.config(text=process_list[0][2])
    top_process_frame.c13.config(text=process_list[0][3])
    top_process_frame.c14.config(text=process_list[0][4])

    top_process_frame.c20.config(text=process_list[1][0])
    top_process_frame.c21.config(text=process_list[1][1])
    top_process_frame.c22.config(text=process_list[1][2])
    top_process_frame.c23.config(text=process_list[1][3])
    top_process_frame.c24.config(text=process_list[1][4])

    top_process_frame.c30.config(text=process_list[2][0])
    top_process_frame.c31.config(text=process_list[2][1])
    top_process_frame.c32.config(text=process_list[2][2])
    top_process_frame.c33.config(text=process_list[2][3])
    top_process_frame.c34.config(text=process_list[2][4])

    top_process_frame.c40.config(text=process_list[3][0])
    top_process_frame.c41.config(text=process_list[3][1])
    top_process_frame.c42.config(text=process_list[3][2])
    top_process_frame.c43.config(text=process_list[3][3])
    top_process_frame.c44.config(text=process_list[3][4])

    top_process_frame.c50.config(text=process_list[4][0])
    top_process_frame.c51.config(text=process_list[4][1])
    top_process_frame.c52.config(text=process_list[4][2])
    top_process_frame.c53.config(text=process_list[4][3])
    top_process_frame.c54.config(text=process_list[4][4])

    time.sleep(0.1)
    window.update()

window.mainloop()

def disable_event():
    network_info_thread.join()
    window.quit()
    window.destroy()
    sys.exit()

window.protocol("WM_DELETE_WINDOW", disable_event)


# -*- coding: utf-8 -*-
"""
Created on Fri Nov 27 17:04:58 2020

@author: abhay
"""

import numpy as np
import pandas as pd
import numpy.random as rand
import shutil
import os
# COST Function we will use the given cst calculator
from Farm_Evaluator_Vec_copy import AEP, binWindResourceData, loadPowerCurve
import matplotlib.pyplot as plt

# MAIN CLASS PARTICLES
# Each particle is a wind farm layout of lenght 4000x4000 dimensions
# Each windmill in the particle is bounded between (50,3950)
# The distance between each windmill should be at a distance 400 m

class Particle:
    def __init__(self,n_turbines = 50):
        # ABout thte particle
        self.length = 4000
        self.boundary = 50
        self.separation = 400
        self.n_turbines = n_turbines

        # fitness of the particle
        self.fitness = 0

        # personal best
        self.p_best_x = np.zeros(50)
        self.p_best_y = np.zeros(50)

        self.best_aep = 0
        self.best_fitness = None

        #Initially we will assign random coordinates to the turbines
        #self.position_x = np.ones(n_turbines)*self.boundary + rand.uniform(size = n_turbines) * (self.length - 2* self.boundary)
        #self.position_y = np.ones(n_turbines)*self.boundary + rand.uniform(size = n_turbines) * (self.length - 2* self.boundary)
        self.position_x = np.random.uniform(50,3950,50)
        self.position_y = np.random.uniform(50,3950,50)
        self.position_x,self.position_y = self.calc_postion(np.zeros(self.n_turbines), np.zeros(self.n_turbines),
                                                            np.zeros(self.n_turbines), np.zeros(self.n_turbines))

    def calc_postion(self, v1,v2, g_best_x, g_best_y):
        new_pos_x = self.position_x + np.multiply(v1[0], (g_best_x - self.position_x)) + np.multiply(v2[0], (self.p_best_x - self.position_x))
        new_pos_y = self.position_y + np.multiply(v1[1], (g_best_y - self.position_y)) + np.multiply(v2[1], (self.p_best_y - self.position_y))
        for i in range(len(new_pos_x)):
            for j in range(len(new_pos_x)):
                if (i == j):
                    continue

                x_1, y_1 = new_pos_x[i],new_pos_y[i]
                x_2, y_2 = new_pos_x[j],new_pos_y[j]
                dist = np.sqrt((x_1 - x_2)** 2 + (y_1 - y_2)** 2)
                if (dist < self.separation):
                    radius = (self.separation - dist) / 2
                    angle = np.arctan((y_2 - y_1) / (x_2 - x_1 + 1e-3))
                    # turn = np.random.uniform(low = -1.57, high = 1.57)
                    turn = 0
                    c=(x_2 * y_1 - x_1 * y_2) / (x_2 - x_1 + 1e-3)

                    s_x_1 = x_1
                    s_y_1 = y_1 + c
                    s_x_2 = x_2
                    s_y_2 = y_2 + c

                    r_x_1 = s_x_1 * np.cos(angle) + s_y_1 * np.sin(angle) + radius*np.cos(turn)
                    r_y_1 = s_y_1 * np.cos(angle) - s_x_1 * np.sin(angle) + radius*np.sin(turn)
                    r_x_2 = s_x_2 * np.cos(angle) + s_y_2 * np.sin(angle) - radius*np.cos(turn)
                    r_y_2 = s_y_2 * np.cos(angle) - s_x_2 * np.sin(angle) - radius * np.sin(turn)

                    [new_pos_x[i],new_pos_y[i]] = [r_x_1 * np.cos(angle) - r_y_1 * np.sin(angle), r_x_1 * np.sin(angle) + r_y_1 * np.cos(angle) - c]
                    [new_pos_x[j],new_pos_y[j]] = [r_x_2 * np.cos(angle) - r_y_2 * np.sin(angle), r_x_2 * np.sin(angle) + r_y_2 * np.cos(angle) - c]

            new_pos_x[i] = min(new_pos_x[i], self.length - self.boundary)
            new_pos_y[i] = min(new_pos_y[i], self.length - self.boundary)
            new_pos_x[i] = max(self.boundary, new_pos_x[i])
            new_pos_y[i] = max(self.boundary, new_pos_y[i])

        return new_pos_x,new_pos_y

    def calc_violation(self,position_x,position_y):
        cost = 0
        for i in range(self.n_turbines) :
            x1, y1 = position_x[i],position_y[i]
            # Check boundary constraints
            if x1 < self.boundary :
                cost = cost + (self.boundary - x1)**2
            if y1 < self.boundary :
                cost = cost + (self.boundary - y1)**2
            if x1 > self.length - self.boundary :
                cost = cost + (self.length - self.boundary - x1)**2
            if y1 > self.length - self.boundary :
                cost = cost + (self.length - self.boundary - y1)**2

            for j in range(self.n_turbines) :
                if i == j :
                    continue
                x2 , y2 = position_x[j],position_y[j]
                dist = np.sqrt((x1 - x2)**2 + (y1 - y2)**2)
                if dist < self.separation:
                    cost =cost + self.separation - dist
        return cost

# THe SWARM CLASS

class PSO:
    def __init__(self, n_turbines = 50,n_particles = 100, iterations = 50):
        # Will will load the power curve of the turbine and the wind data
        self.power_curve = loadPowerCurve(r'Shell_Hackathon Dataset/power_curve.csv')
        self.wind_data = binWindResourceData(r'Shell_Hackathon Dataset/Wind Data/wind_data_2017.csv')

        self.total_iterations = iterations
        self.n_particles = n_particles
        self.n_turbines = n_turbines

        self.g_best_x = []
        self.g_best_y = []

        self.g_best_aep = 0
        self.best_aep = []# for logging the aeps to graph
        self.g_best_fitness = None
        self.counter = 0
        #Loading The particles to the swarm
        self.particles = [Particle() for i in range(n_particles)]

    def calc_AEP(self, position_x, position_y):
        return AEP(position_x, position_y, self.power_curve, self.wind_data)

    def calc_fitness(self, aep, violation_cost):
        if violation_cost != 0:
            return -violation_cost
        else:
            return aep

    def log_best_plots(self,g_best_x,g_best_y,count):
        if count < 1:
            shutil.rmtree("globalbest")
            os.mkdir("globalbest")
        data = pd.DataFrame()
        data['x'] = g_best_x
        data['y'] = g_best_y
        data.to_csv("globalbest/iteration_"+str(count) + ".csv",index = False)

    def iterate(self):
        for i in range(self.n_particles):
            v1 = np.random.uniform(low = 0, high = 1, size = [2,self.n_turbines])
            v2 = np.random.uniform(low = 0, high = 1, size = [2,self.n_turbines])
            new_pos_x,new_pos_y = self.particles[i].calc_postion(v1,v2,self.g_best_x, self.g_best_y)

            violation_cost = self.particles[i].calc_violation(
                self.particles[i].position_x, self.particles[i].position_y)

            new_aep = self.calc_AEP(new_pos_x, new_pos_y)
            new_fitness = self.calc_fitness(new_aep, violation_cost)
            # Update particle fitness
            if new_fitness > self.particles[i].best_fitness:
                self.particles[i].best_fitness = new_fitness
                self.particles[i].best_aep = new_aep
                self.particles[i].p_best_x = new_pos_x
                self.particles[i].p_best_y = new_pos_y
            # Update global fitness
            if (new_fitness > self.g_best_fitness) :
                self.g_best_fitness = new_fitness
                self.g_best_aep = new_aep
                self.g_best_x = new_pos_x
                self.g_best_y = new_pos_y

            self.particles[i].fitness = new_fitness

            #self.particles[i].pos_history.append(self.particles[i].pos) # check these and local bests also
            self.particles[i].position_x = new_pos_x
            self.particles[i].position_y = new_pos_y
        self.best_aep.append(new_aep)

    def run(self):
        #initializing the variables(iteration = 0)
        for particle in self.particles:
            violation_cost = particle.calc_violation(
                particle.position_x, particle.position_y)
            aep = self.calc_AEP(particle.position_x, particle.position_y)
            particle.fitness = self.calc_fitness(aep, violation_cost)
            # Updating the initial global best
            if self.g_best_fitness is None or particle.fitness > self.g_best_fitness:
                self.g_best_fitness = particle.fitness
                self.g_best_x = particle.position_x
                self.g_best_y = particle.position_y
                self.g_best_aep = aep
            particle.best_fitness = particle.fitness
            particle.best_aep = aep
            particle.p_best_x = particle.position_x
            particle.p_best_y = particle.position_y

        self.best_aep.append(aep)
        self.log_data()

        self.log_best_plots(self.g_best_x, self.g_best_y, self.counter)
        self.counter =self.counter + 1

        while self.counter < self.total_iterations:
            self.iterate()
            self.log_data()
            self.log_best_plots(self.g_best_x, self.g_best_y, self.counter)
            self.counter = self.counter + 1
        self.log_data()
        self.plotter(self.g_best_x, self.g_best_y, self.best_aep, self.total_iterations)

    def log_data(self):
        print("Iteration: ", self.counter, "Best Fitness: ", self.g_best_fitness, "Best AEP: ", self.g_best_aep)

    def plotter(self,x,y,aep,iterations):
        fig,ax = plt.subplots(1, 2, figsize=(10, 5))

        a = range(iterations)
        print(a,aep)
        ax[0].set_xlabel("X (m)")
        ax[0].set_ylabel("Y (m)")
        ax[0].axis(xmin=0,xmax=4000)
        ax[0].axis(ymin=0,ymax=4000)
        ax[0].axhline(y=3950, color='r', linestyle='-')
        ax[0].axhline(y=50, color='r', linestyle='-')
        ax[0].axvline(x=3950, color='r', linestyle='-')
        ax[0].axvline(x=50, color='r', linestyle='-')
        #ax[0].set_title('Iterations : ' + str(i))
        ax[0].scatter(x,y)

        ax[1].set_ylabel('No of iterations')
        ax[1].set_xlabel('Annual Energy Production')
        ax[1].plot(a,aep)

        fig.tight_layout()
        plt.show()


from app.transform_annotation import transform_annotation
from app.annotation_wrapper import Annotation
from pathlib import Path
from unittest import TestCase

original_path = Path(__file__).with_name("original.xml")
with original_path.open("r") as f:
    ORIGINAL_MOCK = f.read()

transformed_path = Path(__file__).with_name("transformed.xml")
with transformed_path.open("r") as f:
    TRANSFORMED_MOCK = f.read()

def test_transform_annotation():
    original_annotation = Annotation(raw_str=ORIGINAL_MOCK)
    transformed_annotation = transform_annotation(original_annotation)
    tc = TestCase()
    tc.maxDiff = None
    tc.assertDictEqual(
        Annotation(raw_str=TRANSFORMED_MOCK).dict_repr,
        transformed_annotation.dict_repr,
    )


import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
os.environ['CUDA_VISIBLE_DEVICES'] = ''

import numpy as np

import warnings
warnings.filterwarnings("ignore")

import config as cfg

# Import TFLite from runtrime or Tensorflow;
# import Keras if protobuf model;
# NOTE: we have to use TFLite if we want to use
# the metadata model or want to extract embeddings
try:
    import tflite_runtime.interpreter as tflite
except ModuleNotFoundError:
    from tensorflow import lite as tflite
if not cfg.MODEL_PATH.endswith('.tflite'):
   from tensorflow import keras

INTERPRETER = None
M_INTERPRETER = None
PBMODEL = None

def loadModel(class_output=True):

    global PBMODEL
    global INTERPRETER
    global INPUT_LAYER_INDEX
    global OUTPUT_LAYER_INDEX

    # Do we have to load the tflite or protobuf model?
    if cfg.MODEL_PATH.endswith('.tflite'):

        # Load TFLite model and allocate tensors.
        INTERPRETER = tflite.Interpreter(model_path=cfg.MODEL_PATH, num_threads=cfg.TFLITE_THREADS)
        INTERPRETER.allocate_tensors()

        # Get input and output tensors.
        input_details = INTERPRETER.get_input_details()
        output_details = INTERPRETER.get_output_details()

        # Get input tensor index
        INPUT_LAYER_INDEX = input_details[0]['index']

        # Get classification output or feature embeddings
        if class_output:
            OUTPUT_LAYER_INDEX = output_details[0]['index']
        else:
            OUTPUT_LAYER_INDEX = output_details[0]['index'] - 1

    else:

        # Load protobuf model
        # Note: This will throw a bunch of warnings about custom gradients
        # which we will ignore until TF lets us block them
        PBMODEL = keras.models.load_model(cfg.MODEL_PATH, compile=False)

def loadMetaModel():

    global M_INTERPRETER
    global M_INPUT_LAYER_INDEX
    global M_OUTPUT_LAYER_INDEX

    # Load TFLite model and allocate tensors.
    M_INTERPRETER = tflite.Interpreter(model_path=cfg.MDATA_MODEL_PATH, num_threads=cfg.TFLITE_THREADS)
    M_INTERPRETER.allocate_tensors()

    # Get input and output tensors.
    input_details = M_INTERPRETER.get_input_details()
    output_details = M_INTERPRETER.get_output_details()

    # Get input tensor index
    M_INPUT_LAYER_INDEX = input_details[0]['index']
    M_OUTPUT_LAYER_INDEX = output_details[0]['index']

def predictFilter(lat, lon, week):

    global M_INTERPRETER

    # Does interpreter exist?
    if M_INTERPRETER == None:
        loadMetaModel()

    # Prepare mdata as sample
    sample = np.expand_dims(np.array([lat, lon, week], dtype='float32'), 0)

    # Run inference
    M_INTERPRETER.set_tensor(M_INPUT_LAYER_INDEX, sample)
    M_INTERPRETER.invoke()

    return M_INTERPRETER.get_tensor(M_OUTPUT_LAYER_INDEX)[0]

def explore(lat, lon, week):

    # Make filter prediction
    l_filter = predictFilter(lat, lon, week)

    # Apply threshold
    l_filter = np.where(l_filter >= cfg.LOCATION_FILTER_THRESHOLD, l_filter, 0)

    # Zip with labels
    l_filter = list(zip(l_filter, cfg.LABELS))

    # Sort by filter value
    l_filter = sorted(l_filter, key=lambda x: x[0], reverse=True)

    return l_filter

def flat_sigmoid(x, sensitivity=-1):
    return 1 / (1.0 + np.exp(sensitivity * np.clip(x, -15, 15)))

def predict(sample):

    global INTERPRETER

    # Does interpreter or keras model exist?
    if INTERPRETER == None and PBMODEL == None:
        loadModel()

    if PBMODEL == None:

        # Reshape input tensor
        INTERPRETER.resize_tensor_input(INPUT_LAYER_INDEX, [len(sample), *sample[0].shape])
        INTERPRETER.allocate_tensors()

        # Make a prediction (Audio only for now)
        INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample, dtype='float32'))
        INTERPRETER.invoke()
        prediction = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)

        return prediction

    else:

        # Make a prediction (Audio only for now)
        prediction = PBMODEL.predict(sample)

        return prediction

def embeddings(sample):

    global INTERPRETER

    # Does interpreter exist?
    if INTERPRETER == None:
        loadModel(False)

    # Reshape input tensor
    INTERPRETER.resize_tensor_input(INPUT_LAYER_INDEX, [len(sample), *sample[0].shape])
    INTERPRETER.allocate_tensors()

    # Extract feature embeddings
    INTERPRETER.set_tensor(INPUT_LAYER_INDEX, np.array(sample, dtype='float32'))
    INTERPRETER.invoke()
    features = INTERPRETER.get_tensor(OUTPUT_LAYER_INDEX)

    return features


from __future__ import print_function, division

import datetime
import os

import matplotlib.pyplot as plt
import numpy as np
from data_loader import DataLoader
from tensorflow.keras.layers import Input, Concatenate
from tensorflow.keras.layers import LeakyReLU
from tensorflow.keras.layers import UpSampling2D, Conv2D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow_addons.layers.normalizations import InstanceNormalization

IMG_SIZE = 256

def build_generator(img: Input) -> Model:
    """
    U-Net Generator
    :param img: input image placeholder
    """

    def downsampling2d(layer_input, filters: int):
        """Layers used in the encoder"""
        d = Conv2D(filters=filters,
                   kernel_size=4,
                   strides=2,
                   padding='same')(layer_input)
        d = LeakyReLU(alpha=0.2)(d)
        d = InstanceNormalization()(d)
        return d

    def upsampling2d(layer_input, skip_input, filters: int):
        """
        Layers used in the decoder
        :param layer_input: input layer
        :param skip_input: another input from the corresponding encoder block
        :param filters: number of filter
        """
        u = UpSampling2D(size=2)(layer_input)
        u = Conv2D(filters=filters, kernel_size=4, strides=1, padding='same',
                   activation='relu')(u)
        u = InstanceNormalization()(u)
        u = Concatenate()([u, skip_input])
        return u

    # Encoder
    gf = 32
    d1 = downsampling2d(img, gf)
    d2 = downsampling2d(d1, gf * 2)
    d3 = downsampling2d(d2, gf * 4)
    d4 = downsampling2d(d3, gf * 8)

    # Decoder
    # Note that we concatenate each upsampling2d block with
    # its corresponding downsampling2d block, as per U-net
    u1 = upsampling2d(d4, d3, gf * 4)
    u2 = upsampling2d(u1, d2, gf * 2)
    u3 = upsampling2d(u2, d1, gf)

    u4 = UpSampling2D(size=2)(u3)
    output_img = Conv2D(3, kernel_size=4, strides=1, padding='same', activation='tanh')(u4)

    model = Model(img, output_img)

    model.summary()

    return model

def build_discriminator(img: Input) -> Model:
    """
    CNN discriminator
    :param img: input image placeholder
    """

    def d_layer(layer_input, filters, f_size=4, normalization=True):
        """Discriminator layer"""
        d = Conv2D(filters, kernel_size=f_size, strides=2, padding='same')(layer_input)
        d = LeakyReLU(alpha=0.2)(d)
        if normalization:
            d = InstanceNormalization()(d)
        return d

    df = 64

    d1 = d_layer(img, df, normalization=False)
    d2 = d_layer(d1, df * 2)
    d3 = d_layer(d2, df * 4)
    d4 = d_layer(d3, df * 8)

    validity = Conv2D(1, kernel_size=4, strides=1, padding='same')(d4)

    model = Model(img, validity)

    model.summary()

    return model

def train(epochs: int,
          data_loader: DataLoader,
          g_XY: Model,
          g_YX: Model,
          d_X: Model,
          d_Y: Model,
          combined: Model,
          batch_size=1,
          sample_interval=50):
    """
    :param epochs: number of steps to train
    :param data_loader: the data loader
    :param g_XY: generator G = X -> Y
    :param g_YX: generator F = Y -> X
    :param d_X: discriminator for X
    :param d_Y: discriminator for Y
    :param combined: the combined generator/discriminator model
    :param batch_size: mini batch size
    :param sample_interval: how often to sample images
    """
    start_time = datetime.datetime.now()

    # Calculate output shape of D (PatchGAN)
    patch = int(IMG_SIZE / 2 ** 4)
    disc_patch = (patch, patch, 1)

    # GAN loss ground truths
    valid = np.ones((batch_size,) + disc_patch)
    fake = np.zeros((batch_size,) + disc_patch)

    for epoch in range(epochs):
        for batch_i, (imgs_X, imgs_Y) in enumerate(data_loader.load_batch(batch_size)):
            # Train the discriminators

            # Translate images to opposite domain
            fake_Y = g_XY.predict(imgs_X)
            fake_X = g_YX.predict(imgs_Y)

            # Train the discriminators (original images = real / translated = Fake)
            dX_loss_real = d_X.train_on_batch(imgs_X, valid)
            dX_loss_fake = d_X.train_on_batch(fake_X, fake)
            dX_loss = 0.5 * np.add(dX_loss_real, dX_loss_fake)

            dY_loss_real = d_Y.train_on_batch(imgs_Y, valid)
            dY_loss_fake = d_Y.train_on_batch(fake_Y, fake)
            dY_loss = 0.5 * np.add(dY_loss_real, dY_loss_fake)

            # Total disciminator loss
            d_loss = 0.5 * np.add(dX_loss, dY_loss)

            # Train the generators
            g_loss = combined.train_on_batch([imgs_X, imgs_Y],
                                             [valid, valid,
                                              imgs_X, imgs_Y,
                                              imgs_X, imgs_Y])

            elapsed_time = datetime.datetime.now() - start_time

            # Plot the progress
            print("[Epoch %d/%d] [Batch %d/%d] [D loss: %f, acc: %3d%%] [G loss: %05f, adv: %05f, recon: %05f, id: %05f] time: %s " \
                  % (epoch, epochs, batch_i, data_loader.n_batches, d_loss[0], 100 * d_loss[1], g_loss[0], np.mean(g_loss[1:3]), np.mean(g_loss[3:5]), np.mean(g_loss[5:6]), elapsed_time))

            # If at save interval => save generated image samples
            if batch_i % sample_interval == 0:
                sample_images(epoch, batch_i, g_XY, g_YX, data_loader)

def sample_images(epoch: int,
                  current_batch: int,
                  g_XY: Model,
                  g_YX: Model,
                  data_loader: DataLoader):
    """
    Sample new generated images
    :param epoch: current epoch
    :param current_batch: current batch
    :param g_XY: generator G: X->Y
    :param g_YX: generator F: Y->X
    :param data_loader: data loader
    """
    os.makedirs('images/%s' % data_loader.dataset_name, exist_ok=True)
    r, c = 2, 3

    imgs_X = data_loader.load_data(domain="A", batch_size=1, is_testing=True)
    imgs_Y = data_loader.load_data(domain="B", batch_size=1, is_testing=True)

    # Translate images to the other domain
    fake_Y = g_XY.predict(imgs_X)
    fake_X = g_YX.predict(imgs_Y)

    # Translate back to original domain
    reconstr_X = g_YX.predict(fake_Y)
    reconstr_Y = g_XY.predict(fake_X)

    gen_imgs = np.concatenate([imgs_X, fake_Y, reconstr_X, imgs_Y, fake_X, reconstr_Y])

    # Rescale images 0 - 1
    gen_imgs = 0.5 * gen_imgs + 0.5

    titles = ['Original', 'Translated', 'Reconstructed']
    fig, axs = plt.subplots(r, c)
    cnt = 0
    for i in range(r):
        for j in range(c):
            axs[i, j].imshow(gen_imgs[cnt])
            axs[i, j].set_title(titles[j])
            axs[i, j].axis('off')
            cnt += 1
    fig.savefig("images/%s/%d_%d.png" % (data_loader.dataset_name, epoch, current_batch))
    plt.close()

if __name__ == '__main__':
    # Input shape
    img_shape = (IMG_SIZE, IMG_SIZE, 3)

    # Configure data loader
    data_loader = DataLoader(dataset_name='facades',
                             img_res=(IMG_SIZE, IMG_SIZE))

    # Loss weights
    lambda_cycle = 10.0  # Cycle-consistency loss
    lambda_id = 0.1 * lambda_cycle  # Identity loss

    optimizer = Adam(0.0002, 0.5)

    # Build and compile the discriminators
    d_X = build_discriminator(Input(shape=img_shape))
    d_Y = build_discriminator(Input(shape=img_shape))
    d_X.compile(loss='mse',
                optimizer=optimizer,
                metrics=['accuracy'])
    d_Y.compile(loss='mse',
                optimizer=optimizer,
                metrics=['accuracy'])

    # Build the generators
    img_X = Input(shape=img_shape)
    g_XY = build_generator(img_X)

    img_Y = Input(shape=img_shape)
    g_YX = build_generator(img_Y)

    # Translate images to the other domain
    fake_Y = g_XY(img_X)
    fake_X = g_YX(img_Y)

    # Translate images back to original domain
    reconstr_X = g_YX(fake_Y)
    reconstr_Y = g_XY(fake_X)

    # Identity mapping of images
    img_X_id = g_YX(img_X)
    img_Y_id = g_XY(img_Y)

    # For the combined model we will only train the generators
    d_X.trainable = False
    d_Y.trainable = False

    # Discriminators determines validity of translated images
    valid_X = d_X(fake_X)
    valid_Y = d_Y(fake_Y)

    # Combined model trains both generators to fool the two discriminators
    combined = Model(inputs=[img_X, img_Y],
                     outputs=[valid_X, valid_Y,
                              reconstr_X, reconstr_Y,
                              img_X_id, img_Y_id])
    combined.compile(loss=['mse', 'mse',
                           'mae', 'mae',
                           'mae', 'mae'],
                     loss_weights=[1, 1,
                                   lambda_cycle, lambda_cycle,
                                   lambda_id, lambda_id],
                     optimizer=optimizer)

    train(epochs=75,
          batch_size=1,
          data_loader=data_loader,
          g_XY=g_XY,
          g_YX=g_YX,
          d_X=d_X,
          d_Y=d_Y,
          combined=combined,
          sample_interval=200)


"""
selfplaying controller
"""
import logging
import os
import threading

import numpy as np
import torch
import torch.multiprocessing as mp

from utils import listener_process
from .selfplay_worker import SelfplayWorker

class Selfplay:

    def __init__(self, game, model, checkpointer, cfg):
        self.game               = game
        self.model              = model
        self.cfg                = cfg
        self.checkpointer       = checkpointer
        self.num_workers        = cfg.SELF_PLAY.NUM_WORKER
        self.game_count         = mp.Value('i', 0)
        self.exp_queue          = mp.Queue()
        self.logging_queue      = mp.Queue()
        self.barrier            = mp.Barrier(self.num_workers+1)
        self.self1_wins_count   = mp.Value("i", 0)
        self.self2_wins_count   = mp.Value("i", 0)

        exp_path = os.path.join(cfg.DIRS.EXPERIMENT, "training_data")
        os.makedirs(exp_path, exist_ok=True) ############### fix later
        self.exp_folder = exp_path

    def plays(self, idx):
        """
        init and run selfplay processes
        gather and save training examples
        terminate selfplay processes
        """
        self.model.eval()
        self.model.freeze_param()

        # init and run worker
        self._start_workers()

        # wait all workers
        self.barrier.wait()

        logging.info(
            "player1 vs player2: "
            f"{self.self1_wins_count.value:0>3} - "
            f"{self.self2_wins_count.value:0>3}")

        # collect sample
        self._collect_samples(idx)

        # terminate selfplay process and reset atributes
        self._reset_wokers()

    def _start_workers(self):
        """
        create and start logging thread and selfplay workers
        """

        # create and start logging thread
        self.logging_thread = threading.Thread(
            target=listener_process,
            args=(self.logging_queue,)
        )
        self.logging_thread.start()

        # create and start selfplay workers
        self.workers = [SelfplayWorker(
            pid=i+1,
            model=self.model,
            game=self.game,
            exp_queue=self.exp_queue,
            logging_queue=self.logging_queue,
            global_games_count=self.game_count,
            barrier=self.barrier,
            cfg=self.cfg,
            p1_wins=self.self1_wins_count,
            p2_wins=self.self2_wins_count,
        ) for i in range(self.num_workers)]

        for worker in self.workers:
            worker.start()

    def _collect_samples(self, idx):
        """
        collect and save samples generated by selfplaying
        format: {
            "states": torch tensor of shape (N, 1, H, W)
                        where H,W is board size
            "policies": torch tensor of shape (N, V)
                        where V is number of moves
            "values": torch tensor of shape (N,1)
        }
        """

        num_exp = self.exp_queue.qsize()
        logging.info(f"collecting {num_exp} samples")

        x,y = self.game.getBoardSize()
        num_moves = self.game.getActionSize()

        boards = np.zeros((num_exp, x, y))
        policies = np.zeros((num_exp, num_moves))
        values = np.zeros((num_exp,1))
        for i in range(num_exp):
            board, policy, value = self.exp_queue.get()
            boards[i] = board
            policies[i] = policy
            values[i,0] = value

        exp_file = os.path.join(
            self.exp_folder, f"iter_{idx:0>3}_{num_exp:0>6}_samples.npy")
        data = {
            "states": boards.astype(np.int8),
            "policies": policies,
            "values": values
        }

        self.checkpointer.save_data(exp_file, data, iter=idx, epoch=0)

        del boards
        del policies
        del values
        torch.cuda.empty_cache()

    def _reset_wokers(self):
        """
        terminate workers and reset attributes
        """

        # finish workers
        for worker in self.workers:
            worker.join()

        # finish logging thread
        self.logging_queue.put_nowait(None)
        self.logging_thread.join()

        # reset attributes
        self.game_count = mp.Value("i", 0)
        self.self1_wins_count = mp.Value("i", 0)
        self.self2_wins_count = mp.Value("i", 0)
        self.exp_queue = mp.Queue()

        self.barrier = mp.Barrier(self.num_workers + 1)
        self.logging_queue = mp.Queue()


from django.db import models
from accounts.models import User

# Create your models here.

class Timetable(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
    Name = models.CharField(max_length=50, default='courses')
    Date = models.DateField(blank=True, null=True)
    start_time = models.TimeField()
    end_time = models.TimeField()

    VENUE_CHOICES = [
            ('PY102', "PY102"),
            ('ZIBAMBWE',"ZIBAMBWE"),
            ('AJOSE', "AJOSE"),
            ('1000SLT',"1000SLT"),
            ('ADMIN EXT RM A',"ADMIN EXT RM A"),
            ('AUD1', "AUD1"),
            ('AUD2',"AUD2"),
            ('ODLT1',"ODLT1"),
            ('ODLT2',"ODLT2"),
            ('PY130',"PY130"),
            ('PY238', "PY238"),
            ('BOOA',"BOOA"),
            ('BOOB',"BOOB"),
            ('BOOC', "BOOC"),
        ]
    Venue = models.CharField(max_length=50, choices=VENUE_CHOICES)

    PURPOSE_CHOICES =[
        ('Lecture', "Lecture"),
        ('Defence',"Defence"),
        ('Meeting', "Meeting"),
        ('Seminar', "Seminar"),
        ('Test', "Test"),
        ('Exam', "Exam"),
    ]
    purpose = models.CharField(max_length=7, choices=PURPOSE_CHOICES, null=False)

    DAYS_CHOICES = [
        ('0',"Monday"),
        ('1', "Tuesday"),
        ('2',"Wednesday"),
        ('3', "Thursday"),
        ('4', "Friday"),
        ('5', "Saturday"),
    ]
    days = models.CharField(max_length=10, choices=DAYS_CHOICES, blank=True, null=True)

    STATUS_CHOICES = [
        ('TEMPORARY',"Temporary"),
        ('PERMANENT',"Permanent"),
    ]
    allocation_status = models.CharField(max_length=10, choices=STATUS_CHOICES, blank=True, null=True)

    def __str__(self):
        return self.Venue


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

'''
Interfaz de consola que recibe y muestra los datos que envía el brick al puerto serial
'''

import serial
import time
import sys

arduino = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.1)
arduino.flushInput()

while True:
    time.sleep(0.2)
    try:
        texto = arduino.readline().strip().replace("\n", "")
        if texto:
            print(texto)
    except KeyboardInterrupt:
        print("Cerrando el programa...")
        break
    except serial.SerialException:
        print('Conexión perdida.')
        break
    except IOError:
        print('Error de Entrada/Salida')
        break

arduino.close()
sys.exit()


import dash
from dash import html

app = dash.Dash(__name__)

app.layout = html.Div(children=[html.H1(children='Gaussian Mixtures'),
                                html.H2(children='Data Source: ECB')],
                      style={'textAlign':'center',
                             'color':'blue'})
if __name__ == '__main__':
    app.run_server(debug=True)


#!/usr/bin/env python
import codecs
import os.path
import re
import sys

from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))

def read(*parts):
    return codecs.open(os.path.join(here, *parts), 'r', encoding='gbk', errors='ignore').read()

def find_version(*file_paths):
    version_file = read(*file_paths)
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                              version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")

install_requires = [
    'tencentcloud-sdk-python',
    'fire',
]

setup_options = dict(
    name='wafcli',
    version=find_version("wafcli", "__init__.py"),
    description='腾讯T-Sec Web应用防火墙命令行工具',
    long_description="https://github.com/huangjacky/waf-cli",
    long_description_content_type="text/markdown",
    author='HuangJacky',
    maintainer_email="HuangJacky@163.com",
    url='https://cloud.tencent.com/product/waf',
    scripts=['bin/waf', 'bin/waf.cmd'],
    packages=find_packages(exclude=['tests*']),
    package_data={'wafcli': ['data/*.json', 'examples/*/*.rst',
                             'examples/*/*.txt', 'examples/*/*/*.txt',
                             'examples/*/*/*.rst', 'topics/*.rst',
                             'topics/*.json']},
    install_requires=install_requires,
    extras_require={},
    license="MIT",
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Intended Audience :: System Administrators',
        'Natural Language :: English',
        'License :: OSI Approved :: Apache Software License',
        'Programming Language :: Python',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
        'Programming Language :: Python :: 3.8',
    ],
)

if 'py2exe' in sys.argv:
    setup_options['options'] = {
        'py2exe': {
            'optimize': 0,
            'skip_archive': True,
            'dll_excludes': ['crypt32.dll'],
            'packages': ['docutils', 'urllib', 'httplib', 'HTMLParser',
                         'wafcli', 'ConfigParser', 'xml.etree', 'pipes'],
        }
    }
    setup_options['console'] = ['bin/waf']

setup(**setup_options)


# import os
# os.environ['CUDA_VISIBLE_DEVICES']='1'
import torch
import torch.nn as nn
import configs
import torch.nn.functional as nnf
from Moudules import *
from einops.layers.torch import Rearrange
from einops import rearrange
import torchvision

class Conv3dReLU(nn.Sequential):
    def __init__(
            self,
            in_channels,
            out_channels,
            kernel_size,
            padding=0,
            stride=1,
            use_batchnorm=True,
    ):
        conv = nn.Conv3d(
            in_channels,
            out_channels,
            kernel_size,
            stride=stride,
            padding=padding,
            bias=False,
        )
        relu = nn.LeakyReLU(inplace=True)
        if not use_batchnorm:
            nm = nn.InstanceNorm3d(out_channels)
        else:
            nm = nn.BatchNorm3d(out_channels)

        super(Conv3dReLU, self).__init__(conv, nm, relu)

class DecoderBlock(nn.Module):
    def __init__(
            self,
            in_channels,
            out_channels,
            skip_channels=0,
            use_batchnorm=True,
    ):
        super().__init__()
        self.conv1 = Conv3dReLU(
            in_channels + skip_channels,
            out_channels,
            kernel_size=3,
            padding=1,
            use_batchnorm=use_batchnorm,
        )
        self.conv2 = Conv3dReLU(
            out_channels,
            out_channels,
            kernel_size=3,
            padding=1,
            use_batchnorm=use_batchnorm,
        )
        self.up = nn.Upsample(scale_factor=2, mode='trilinear', align_corners=False)

    def forward(self, x, skip=None):
        x = self.up(x)
        if skip is not None:
            x = torch.cat([x, skip], dim=1)
        x = self.conv1(x)
        x = self.conv2(x)
        return x

class RegistrationHead(nn.Sequential):
    def __init__(self, in_channels, out_channels, kernel_size=3, upsampling=1):
        conv3d = nn.Conv3d(in_channels, out_channels, kernel_size=kernel_size, padding=kernel_size // 2)
        conv3d.weight = nn.Parameter(Normal(0, 1e-5).sample(conv3d.weight.shape))
        conv3d.bias = nn.Parameter(torch.zeros(conv3d.bias.shape))
        super().__init__(conv3d)

class SpatialTransformer(nn.Module):
    """
    N-D Spatial Transformer
    Obtained from https://github.com/voxelmorph/voxelmorph
    """

    def __init__(self, size, mode='bilinear'):
        super().__init__()

        self.mode = mode

        vectors = [torch.arange(0, s) for s in size]
        grids = torch.meshgrid(vectors)
        grid = torch.stack(grids)
        grid = torch.unsqueeze(grid, 0)
        grid = grid.type(torch.FloatTensor)

        self.register_buffer('grid', grid)

    def forward(self, src, flow):

        new_locs = self.grid + flow
        shape = flow.shape[2:]

        for i in range(len(shape)):
            new_locs[:, i, ...] = 2 * (new_locs[:, i, ...] / (shape[i] - 1) - 0.5)

        if len(shape) == 2:
            new_locs = new_locs.permute(0, 2, 3, 1)
            new_locs = new_locs[..., [1, 0]]
        elif len(shape) == 3:
            new_locs = new_locs.permute(0, 2, 3, 4, 1)
            new_locs = new_locs[..., [2, 1, 0]]

        return nnf.grid_sample(src, new_locs, align_corners=True, mode=self.mode)

class PatchEmbed(nn.Module):
    """ Image to Patch Embedding
    Args:
        patch_size (int): Patch token size. Default: 4.
        in_chans (int): Number of input image channels. Default: 3.
        embed_dim (int): Number of linear projection output channels. Default: 96.
        norm_layer (nn.Module, optional): Normalization layer. Default: None
    """

    def __init__(self, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
        super().__init__()
        patch_size = to_3tuple(patch_size)
        self.patch_size = patch_size

        self.in_chans = in_chans
        self.embed_dim = embed_dim

        self.proj = nn.Conv3d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)
        if norm_layer is not None:
            self.norm = norm_layer(embed_dim)
        else:
            self.norm = None

    def forward(self, x):
        """Forward function."""

        _, _, H, W, T = x.size()
        if W % self.patch_size[1] != 0:
            x = nnf.pad(x, (0, self.patch_size[1] - W % self.patch_size[1]))
        if H % self.patch_size[0] != 0:
            x = nnf.pad(x, (0, 0, 0, self.patch_size[0] - H % self.patch_size[0]))
        if T % self.patch_size[0] != 0:
            x = nnf.pad(x, (0, 0, 0, 0, 0, self.patch_size[0] - T % self.patch_size[0]))

        x = self.proj(x)
        if self.norm is not None:
            Wh, Ww, Wt = x.size(2), x.size(3), x.size(4)
            x = x.flatten(2).transpose(1, 2)
            x = self.norm(x)
            x = x.transpose(1, 2).view(-1, self.embed_dim, Wh, Ww, Wt)

        return x

#
# class AttnWindowAttn(nn.Module):
#     def __init__(self, dim, factor=0.25):
#         """
#         """
#         super(AttnWindowAttn, self).__init__()
#         self.factor=factor
#         self.mlp = nn.Sequential(
#             nn.Linear(dim, dim * self.factor),
#             nn.ReLU(),
#             nn.Linear(dim * self.factor, dim)
#         )
#         self.sigmoid = nn.Sigmoid()
#
#     def forward(self, x):
#         """
#
#         :param x: [B L C]
#         :return:
#         """
#
#         y = torch.mean(x, dim=1, keepdim=True)
#         y = self.mlp(y)
#         y = self.sigmoid(y)
#         y = y.expand_as(x)
#         attn_window = y * x
#
#         return attn_window

class HeadTrans(nn.Sequential):
    def __init__(self, shape):
        super(HeadTrans, self).__init__()
        self.shape = shape
        self.patch_emb = nn.Sequential(
            nn.Conv3d(2, 16, 3, 1, 1),
            nn.LeakyReLU(0.2),
            nn.Conv3d(16, 32, 3, 2, 1),
            nn.LeakyReLU(0.2),
            nn.Conv3d(32, 96, 3, 2, 1),
            nn.LeakyReLU(0.2),
            Rearrange('B C D H W -> B (D H W) C'),
            nn.LayerNorm(96),
            Rearrange('B (D H W) C -> B C D H W', D=shape[0] // 4, H=shape[1] // 4, W=shape[2] // 4)
        )

    def forward(self, x):
        y = self.patch_emb(x)
        return y

class SwinNet(nn.Module):
    def __init__(self, config):
        '''
        TransMorph Model
        '''
        super(SwinNet, self).__init__()

        if_convskip = config.if_convskip
        self.if_convskip = if_convskip
        if_transskip = config.if_transskip
        self.if_transskip = if_transskip
        embed_dim = config.embed_dim

        self.transformer = SwinTransformerHigh(patch_size=config.patch_size,
                                               in_chans=config.in_chans,
                                               embed_dim=config.embed_dim,
                                               depths=config.depths,
                                               num_heads=config.num_heads,
                                               window_size=config.window_size,
                                               mlp_ratio=config.mlp_ratio,
                                               qkv_bias=config.qkv_bias,
                                               drop_rate=config.drop_rate,
                                               drop_path_rate=config.drop_path_rate,
                                               ape=config.ape,
                                               spe=config.spe,
                                               patch_norm=config.patch_norm,
                                               use_checkpoint=config.use_checkpoint,
                                               out_indices=config.out_indices,
                                               pat_merg_rf=config.pat_merg_rf,
                                               )

        self.transformer.patch_embed = nn.Sequential()

        self.transformer.patch_embed.add_module('new_patch_emb', HeadTrans(config.img_size))

        self.up0 = DecoderBlock(embed_dim * 8, embed_dim * 4, skip_channels=embed_dim * 4 if if_transskip else 0,
                                use_batchnorm=False)
        self.up1 = DecoderBlock(embed_dim * 4, embed_dim * 2, skip_channels=embed_dim * 2 if if_transskip else 0,
                                use_batchnorm=False)
        self.up2 = DecoderBlock(embed_dim * 2, embed_dim, skip_channels=embed_dim if if_transskip else 0,
                                use_batchnorm=False)
        self.up3 = DecoderBlock(embed_dim, embed_dim // 2, skip_channels=embed_dim // 2 if if_convskip else 0,
                                use_batchnorm=False)
        self.up4 = DecoderBlock(embed_dim // 2, config.reg_head_chan,
                                skip_channels=config.reg_head_chan if if_convskip else 0,
                                use_batchnorm=False)
        self.c1 = Conv3dReLU(2, embed_dim // 2, 3, 1, use_batchnorm=False)
        self.c2 = Conv3dReLU(2, config.reg_head_chan, 3, 1, use_batchnorm=False)
        self.reg_head = RegistrationHead(
            in_channels=config.reg_head_chan,
            out_channels=3,
            kernel_size=3,
        )

        self.spatial_trans = SpatialTransformer(config.img_size)

    def forward(self, x):
        source = x[:, 0:1, :, :]

        out_feats = self.transformer(x)

        f1 = out_feats[-2]
        f2 = out_feats[-3]
        f3 = out_feats[-4]
        f4 = out_feats[-5]
        f5 = out_feats[-6]

        x = self.up0(out_feats[-1], f1)
        x = self.up1(x, f2)
        x = self.up2(x, f3)
        x = self.up3(x, f4)
        x = self.up4(x, f5)
        flow = self.reg_head(x)
        out = self.spatial_trans(source, flow)
        return out, flow

class PatchExpanding(nn.Module):
    def __init__(self, dim, scale_factor=8, bias=False):
        """
        Expand operation in decoder.
        :param dim: input token channels for expanding.
        :param scale_factor: the expanding scale for token channels.
        """
        super(PatchExpanding, self).__init__()
        self.dim = dim

        self.expander = nn.Sequential(
            Rearrange('B C D H W -> B D H W C'),
            nn.Linear(self.dim, scale_factor * self.dim, bias=bias),
            Rearrange('b D H W (h d w c) -> b (D d) (H h) (W w) c', d=2, h=2, w=2, c=self.dim // 2),

        )
        self.norm = nn.Sequential(
            nn.LayerNorm(self.dim // 2, eps=1e-6),
            Rearrange('B D H W C -> B C D H W')
        )

    def forward(self, x):
        """
        Run forward pass.
        :param x: torch.Tensor
            Input tokens.
        :return: x: torch.Tensor
            Output expanded tokens.
        """
        y = self.norm(self.expander(x))

        return y

CONFIGS = {
    'RFRANet': configs.RFRANet()}