import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from random import sample, randrange
from collections import deque
from numpy.random import default_rng, randint
from numpy import expand_dims, ndarray, stack, arange, argmax, array, repeat, tile
from models.legacy.network import DQNv2, model_savepath

class DQN_agent:
    def __init__(self, device: torch.device, action_num: int, mem_size: int,
                 batch_size: int, discount: float, lr: float, wd: float,
                 replay_mem_runs: int=10, model=DQNv2,
                 eps: float=1, eps_decay: float=0.99, eps_min: float=0.1):

        # store model hyper parameters
        self.device = device
        self.action_num = action_num
        self.batch_size = batch_size
        self.discount = discount
        self.lr = lr
        self.wd = wd
        self.eps = eps
        self.eps_decay = eps_decay
        self.eps_min = eps_min
        self.replay_mem_runs = replay_mem_runs
        self.rand_num = batch_size // replay_mem_runs
        self.mem_size = mem_size

        # initialize new model(s)
        self.q_net = model(action_num, batch_size, device).to(device)

        # initialize loss measurer, optimiser and replay memory queue
        self.criterion = nn.MSELoss()
        self.optimiser = optim.Adam(self.q_net.parameters(), lr=lr, weight_decay=wd)
        self.memory = deque(maxlen=mem_size)

        self.rng = default_rng()
        self.batch_row_idx = arange(batch_size)

    def decide_move(self, state: list[ndarray, ndarray]) -> torch.tensor:
        if self.rng.uniform() < self.eps:
            return self.rng.integers(0, self.action_num)
        else:
            state = torch.from_numpy(
                expand_dims(state, axis=0)
                ).float().to(self.device)
            return torch.argmax(self.q_net.inference(state)).item()

    def add_mem(self, state: list[ndarray, ndarray], action: int, reward: float,
                next_state: list[ndarray, ndarray], terminated: bool):
        self.memory.append((state, action, reward, next_state, terminated))

    def save_q_net(self, epoch: int):
        current = dict()
        current["stat_dict"] = self.q_net.state_dict()
        current["hyper_param"] = (self.action_num, self.mem_size, self.batch_size,
                                  self.discount, self.lr, self.wd, self.replay_mem_runs,
                                  self.eps, self.eps_decay, self.eps_min)
        torch.save(current, model_savepath %(epoch))
        del current

    def load_q_net(self, epoch: int, inference: bool=True):
        current = torch.load(model_savepath %(epoch))
        self.q_net.load_state_dict(current["stat_dict"])
        self.action_num, self.mem_size, self.batch_size, self.discount, self.lr, self.wd, \
            self.replay_mem_runs, self.eps, self.eps_decay, self.eps_min = current["hyper_param"]

        if not inference:
            self.rand_num = self.batch_size // self.replay_mem_runs
            self.optimiser = optim.Adam(self.q_net.parameters(), lr=self.lr, weight_decay=self.wd)
            self.memory = deque(maxlen=self.mem_size)
            self.rng = default_rng()
            self.batch_row_idx = arange(self.batch_size)
        else:
            self.q_net.eval()

        del current
        torch.cuda.empty_cache()

    def train(self):
        #batch = sample_mem(self.memory, self.replay_mem_runs, self.rand_num)
        batch = sample(self.memory, self.batch_size)
        batch = array(batch, dtype=object)

        device = self.device
        states = stack(batch[:, 0], dtype=float)
        actions = batch[:, 1].astype(int)
        rewards = batch[:, 2].astype(float)
        next_states = stack(batch[:, 3], dtype=float)
        terminated = batch[:, 4].astype(bool)
        on_going = ~terminated

        row_idx = self.batch_row_idx

        with torch.no_grad():
            next_states = torch.from_numpy(next_states).float().to(device)
            net1_result = self.q_net(next_states).cpu().data.numpy()
            idx = (row_idx, argmax(net1_result, 1))
            next_state_values = self.q_net(next_states).cpu().data.numpy()[idx][on_going]

        q_targets = rewards.copy() # don't modify in-place and change memory
        q_targets[on_going] += self.discount * next_state_values
        q_targets = torch.from_numpy(q_targets).float().to(device)

        idx = (row_idx, actions)
        states = torch.from_numpy(states).float().to(device)
        action_values = self.q_net(states)[idx].float().to(device)

        self.optimiser.zero_grad()
        temporal_err = self.criterion(q_targets, action_values)
        temporal_err.backward()
        self.optimiser.step()

        self.eps = self.eps * self.eps_decay if self.eps > self.eps_min else self.eps_min

def sample_mem(memory, run_len, run_num):
    mem_max = len(memory)
    element_selected = randint(0, mem_max, run_num)
    element_selected.sort()
    element_selected = repeat(element_selected, run_len) + tile(arange(run_len), run_num)
    element_selected[element_selected >= mem_max] = mem_max - 1
    return [memory[i] for i in element_selected]


from typing import Callable, Optional, List, Dict, Iterable, Tuple
from agglomerate.agglomerate_3d import Agglomerate3D, TREE_SCORE_OPTIONS
from itertools import product
from data.data_loader import DataLoader
import multiprocessing as mp
import pandas as pd
import numpy as np
from tqdm import tqdm

class BatchAgglomerate3D:
    def __init__(self,
                 linkage_cell: List[str],
                 linkage_region: List[str],
                 cell_type_affinity: List[Callable],
                 region_affinity: Optional[List[Callable]] = None,
                 max_region_diff: Optional[List[int]] = None,
                 region_dist_scale: Optional[Iterable[float]] = None,
                 verbose: Optional[bool] = False,
                 integrity_check: Optional[bool] = True):
        # Can't have mutable types as default :(
        if region_affinity is None:
            region_affinity = [None]
        if region_dist_scale is None:
            region_dist_scale = [1]
        if max_region_diff is None:
            max_region_diff = [0]
        self.linkage_cell = linkage_cell
        self.linkage_region = linkage_region
        self.cell_type_affinity = cell_type_affinity
        self.region_affinity = region_affinity
        self.max_region_diff = max_region_diff
        self.region_dist_scale = region_dist_scale
        self.verbose = verbose
        self.integrity_check = integrity_check
        self.agglomerators: List[Agglomerate3D] = []
        self.augmented_tree_scores: List[Dict[str, float]] = []
        self.tree_scores: Dict[str, List[float]] = {metric: [] for metric in TREE_SCORE_OPTIONS}
        self.pbar = \
            tqdm(total=np.product(list(map(len, [
                linkage_cell, linkage_region, cell_type_affinity, region_affinity, max_region_diff, region_dist_scale
            ]))))

    @staticmethod
    def _agglomerate_func(lc, lr, cta, ra, mrd, rds, ic, data):
        agglomerate = Agglomerate3D(linkage_cell=lc,
                                    linkage_region=lr,
                                    cell_type_affinity=cta,
                                    region_affinity=ra,
                                    max_region_diff=mrd,
                                    region_dist_scale=rds,
                                    verbose=False,
                                    pbar=False,
                                    integrity_check=ic
                                    )
        agglomerate.agglomerate(data)
        return agglomerate

    def _collect_agglomerators(self, result):
        self.agglomerators.append(result)
        self.pbar.update(1)

    def agglomerate(self, data_ct: DataLoader):
        pool = mp.Pool(mp.cpu_count())
        for lc, lr, cta, ra, mrd, rds in product(self.linkage_cell,
                                                 self.linkage_region,
                                                 self.cell_type_affinity,
                                                 self.region_affinity,
                                                 self.max_region_diff,
                                                 self.region_dist_scale):
            if self.verbose:
                print(f'Starting agglomeration with {lc, lr, cta, ra, mrd, rds, self.integrity_check}')
            pool.apply_async(self._agglomerate_func,
                             args=(lc, lr, cta, ra, mrd, rds, self.integrity_check, data_ct),
                             callback=self._collect_agglomerators)
        pool.close()
        pool.join()
        self.pbar.close()

    def _collect_augmented_scores(self, result):
        lc, lr, mrd, rds, scores = result
        for metric, score in zip(TREE_SCORE_OPTIONS, scores):
            self.augmented_tree_scores.append(
                {'linkage_cell': lc, 'linkage_region': lr, 'max_region_diff': mrd, 'region_dist_scale': rds,
                 'score metric': metric, 'score': score})
        self.pbar.update(1)

    @staticmethod
    def _augmented_score_func(a: Agglomerate3D) -> Tuple[str, str, int, float, List[float]]:
        return a.linkage_cell,   \
               a.linkage_region,  \
               a.max_region_diff,  \
               a.region_dist_scale, \
               [a.compute_tree_score(m) for m in TREE_SCORE_OPTIONS]

    def get_all_scores(self) -> pd.DataFrame:
        self._compute_tree_scores(func=self._augmented_score_func, callback=self._collect_augmented_scores)
        return pd.DataFrame(self.augmented_tree_scores)

    def _compute_tree_scores(self, func: Callable, callback: Callable):
        self.pbar = tqdm(total=len(self.agglomerators))
        pool = mp.Pool(mp.cpu_count())
        for a in self.agglomerators:
            pool.apply_async(func=func,
                             args=(a,),
                             callback=callback
                             )
        pool.close()
        pool.join()
        self.pbar.close()

    def _collect_basic_scores(self, scores: List[float]):
        for metric, score in zip(TREE_SCORE_OPTIONS, scores):
            self.tree_scores[metric].append(score)
        self.pbar.update(1)

    @staticmethod
    def _basic_score_func(a: Agglomerate3D) -> List[float]:
        return [a.compute_tree_score(m) for m in TREE_SCORE_OPTIONS]

    def get_best_agglomerators(self) -> Dict[str, Tuple[float, np.array]]:
        self._compute_tree_scores(func=self._basic_score_func, callback=self._collect_basic_scores)

        # best_agglomerators: Dict[str, Tuple[float, Agglomerate3D]] = {
        #     metric: (np.min(self.tree_scores[metric]), self.agglomerators[int(np.argmin(self.tree_scores[metric]))])
        #     for metric in TREE_SCORE_OPTIONS
        # }
        best_agglomerators: Dict[str, Tuple[float, Agglomerate3D]] = {
            metric: (
                np.min(self.tree_scores[metric]),
                np.unique(
                    np.array(self.agglomerators)[np.where(self.tree_scores[metric] == np.min(self.tree_scores[metric]))]
                )
            )
            for metric in TREE_SCORE_OPTIONS
        }

        return best_agglomerators


from flask import Flask, request, jsonify, Response

app = Flask(__name__)
app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False

class HTTPError(Exception):
    def __init__(self, status_code, message):
        Exception.__init__(self)
        self.message = message
        self.status_code = status_code

def something_fishy(reason):
    ip = request.remote_addr
    cropped_body = request.get_data(as_text=True)[:200]
    app.logger.warn('A fishy request came from %s at %s %s: %s' %
                    (ip, request.method, request.path, reason))
    if cropped_body:
        app.logger.warn('Request content: %s' % cropped_body)
    raise HTTPError(400, 'Bad request')

@app.errorhandler(HTTPError)
def handle_http_error(error):
    """
    :type error: HTTPError
    """
    response = jsonify({
        'message': error.message,
        'status_code': error.status_code,
    })
    """:type: Response"""
    response.status_code = error.status_code
    return response


import timm
import torch.nn as nn
from torchinfo import summary

import config

class SETIModel(nn.Module):
    def __init__(self, model_name: str, pretrained: bool = True) -> None:
        super(SETIModel, self).__init__()
        self.model_name = model_name
        self.model = timm.create_model(
            model_name=self.model_name, pretrained=pretrained, in_chans=1
        )
        if config.MODEL_NAME.startswith("rexnet"):
            self.input_fc = self.model.head.fc.in_features
            self.model.head.fc = nn.Linear(
                in_features=self.input_fc, out_features=1, bias=True
            )
        elif config.MODEL_NAME.startswith("efficientnet"):
            self.input_fc = self.model.classifier.in_features
            self.model.classifier = nn.Linear(
                in_features=self.input_fc, out_features=1, bias=True
            )
        elif config.MODEL_NAME.startswith("resnet"):
            self.input_fc = self.model.fc.in_features
            self.model.fc = nn.Linear(
                in_features=self.input_fc, out_features=1, bias=True
            )
        else:
            raise NotImplementedError("Model head has not been modified.")

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

def model_details(model, x):
    print("Model summary:")
    summary(
        model,
        input_size=(config.BATCH_SIZE, 1, config.SIZE, config.SIZE),
        verbose=1,
    )
    print(f"Output size: {model(x).shape}")

if __name__ == "__main__":
    import torch

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = SETIModel(model_name=config.MODEL_NAME)
    model = model.to(device)
    x = torch.rand(16, 1, config.SIZE, config.SIZE)
    x = x.to(device)
    model_details(model, x)


import logging

logging.basicConfig(filename="constructor.log", level=logging.INFO, format='%(levelname)s %(asctime)s %(name)s %(message)s')
class ineuron:
    logging.info("ineuron class conrtructor")
    try:
        def __int__(self,sunny,sudhanshu):
            self.sunny=sunny
            self.sudhanshu=sudhanshu
    except Exception as e:
        logging.info(e)

class student:
    logging.info("student class conrtructor")
    try:
        def __int__(self,vipin,ankit):
            self.vipin=vipin
            self.ankit=ankit
    except Exception as e:
        logging.info(e)

class internship:
    logging.info("internship class conrtructor")
    try:
        def __int__(self,data_science,python,big_data):
            self.data_science=data_science
            self.python=python
            self.big_data=big_data
    except Exception as e:
        logging.info(e)

class job:
    logging.info("job class constructor")
    try:
        def __int__(self,data_scientist,ml_engineer,python_developer):
            self.data_scientist=data_scientist
            self.ml_engineer=ml_engineer
            self.python_developer=python_developer

    except Exception as e:
        logging.info(e)

class blog:
    logging.info("blog class constructor")
    try:
        def __int__(self,python,ml,dl):
            self.python=python
            self.ml=ml
            self.dl=dl
    except Exception as e:
        logging.info(e)


# -----------------------------------------------------------------------------
# xml.py
#
# Author: Francesco Racciatti (racciatti.francesco@gmail.com)
#
# This module contains the interpreting services for AML.
# -----------------------------------------------------------------------------

import abc
import enum

import model.types as types
import model.statements as statements

class Interpreter(metaclass=abc.ABCMeta):
    """
    Abstract base class for interpreters.
    """

    @abc.abstractclassmethod
    def interpret(cls, aml, type):
        """
        Interprets the given AML source string.
        """
        pass

class Xml(Interpreter):
    """
    Provides an XML interpreter for AML.
    """

    @classmethod
    def interpret(cls, aml, type):
        xml = ''
        xml += '<?xml version="1.0"?>'
        xml += cls.codeblock(aml, type)
        return xml

    @classmethod
    def codeblock(cls, codeblock, indent):
        """
        Provides the XML representation of the AML codeblocks.
        """
        xml = ''
        # Gets the name of the codeblock's base class
        codeblock_namebaseclass = codeblock.__class__.__bases__[0].__name__.lower()
        xml += '\t' * indent + '<' + codeblock_namebaseclass + '>\n'
        # Gets the name of the codeblock's class
        codeblock_nameclass = codeblock.__class__.__name__.lower()
        xml += '\t' * (indent + 1) + '<' + codeblock_nameclass + '>\n'
        # Gets the codeblock's attributes
        for attribute in codeblock.__dict__.keys():
            value = codeblock.__dict__[attribute]
            # Handles the symbol-table
            if isinstance(value, types.SymbolTable):
                xml += cls.symboltable(value, indent + 2)
            # Handles the codeblock-table
            elif isinstance(value, statements.CodeblockTable):
                xml += cls.codeblocktable(value, indent + 2)
            # Handles a simple attribute
            else:
                attribute_name = attribute.lower()
                xml += '\t' * (indent + 2) + '<' + attribute_name + '>'
                xml += str(value)
                xml += '</' + attribute_name + '>\n'
        xml += '\t' * (indent + 1) + '</' + codeblock_nameclass + '>\n'
        xml += '\t' * indent + '</' + codeblock_namebaseclass + '>\n'
        return xml

    @classmethod
    def codeblocktable(cls, codeblocktable, indent):
        """
        Provides the XML representation of the AML codeblock-tables.
        """
        xml = ''
        # Gets the name of the codeblocktable's class
        codeblocktable_nameclass = codeblocktable.__class__.__name__.lower()
        xml += '\t' * indent + '<' + codeblocktable_nameclass + '>\n'
        # Scans the codeblock-table codeblock by codeblock
        for codeblock in codeblocktable.codeblocks:
            # Calls recursively the method Xml.codeblock()
            xml += Xml.codeblock(codeblock, indent + 1)
        xml += '\t' * indent + '</' + codeblocktable_nameclass + '>\n'
        return xml

    @classmethod
    def symboltable(cls, symboltable, indent):
        """
        Provides the XML representation of the AML symbol-tables.
        """
        xml = ''
        # Gets the name of the symboltable's class
        symboltable_nameclass = symboltable.__class__.__name__.lower()
        xml += '\t' * indent + '<' + symboltable_nameclass + '>\n'
        # Scans the symbol-table symbol by symbol
        for symbol in symboltable.identifier_object_dict.values():
            # Gets the name of the symbol's base class
            symbol_namebaseclass = symbol.__class__.__bases__[0].__name__.lower()
            xml += '\t' * (indent + 1) + '<' + symbol_namebaseclass + '>\n'
            # Gets the name of the symbol's class
            symbol_nameclass = symbol.__class__.__name__.lower()
            xml += '\t' * (indent + 2) + '<' + symbol_nameclass + '>\n'
            # Gets the attributes
            for attribute in symbol.__dict__.keys():
                attribute_name = attribute.lower()
                xml += '\t' * (indent + 3) + '<' + attribute_name + '>'
                xml += str(symbol.__dict__[attribute])
                xml += '</' + attribute_name + '>\n'
            xml += '\t' * (indent + 2) + '</' + symbol_nameclass + '>\n'
            xml += '\t' * (indent + 1) + '</' + symbol_namebaseclass + '>\n'
        xml += '\t' * indent + '</' + symboltable_nameclass + '>\n'
        return xml

class InterpreterService(object):
    """
    Provides the XML interpreting service.
    """

    @enum.unique
    class Type(enum.Enum):
        """
        Interpreting services.
        """
        XML = 'xml'
        JSON = 'json'
        YAML = 'yaml'

    @classmethod
    def interpret(cls, aml, type):
        """
        Interprets the given AML source string.
        """
        if type == Type.XML:
            return xml.Xml.intepret(aml, 0)
        elif type == Type.YAML:
            raise NotImplementedError("not implemented yet")
        elif type == Type.JSON:
            raise NotImplementedError("not implemented yet")
        else:
            raise ValueError("type not supported")


# This Python 3 environment comes with many helpful analytics libraries installed

# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python

# For example, here's several helpful packages to load in

import numpy as np # linear algebra

import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the "../input/" directory.

# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os

for dirname, _, filenames in os.walk('/kaggle/input'):

    for filename in filenames:

        print(os.path.join(dirname, filename))

# Any results you write to the current directory are saved as output.

import warnings

warnings.filterwarnings('ignore')

from sklearn.linear_model import LinearRegression

from sklearn.metrics import mean_squared_log_error

from sklearn.preprocessing import LabelEncoder

from sklearn.model_selection import KFold, GridSearchCV

import lightgbm as lgb

import xgboost as xgb

from tqdm import tqdm

train = pd.read_csv('../input/covid19-global-forecasting-week-3/train.csv')

test = pd.read_csv('../input/covid19-global-forecasting-week-3/test.csv')

submission = pd.read_csv('../input/covid19-global-forecasting-week-3/submission.csv')
train['Date'] = pd.to_datetime(train['Date']).dt.strftime("%m%d").astype(int)

test['Date'] = pd.to_datetime(test['Date']).dt.strftime("%m%d").astype(int)
train['Province_State'] = train['Province_State'].fillna('unknown')

test['Province_State'] = test['Province_State'].fillna('unknown')
train['Province_State'] = train['Province_State'].astype('category')

train['Country_Region'] = train['Country_Region'].astype('category')

test['Province_State'] = test['Province_State'].astype('category')

test['Country_Region'] = test['Country_Region'].astype('category')
FEATURES = ['Date']

submission = pd.DataFrame(columns=['ForecastId', 'ConfirmedCases', 'Fatalities'])

for i in tqdm(train.Country_Region.unique()):

    z_train = train[train['Country_Region'] == i]

    z_test = test[test['Country_Region'] == i]

    for k in z_train.Province_State.unique():

        p_train = z_train[z_train['Province_State'] == k]

        p_test = z_test[z_test['Province_State'] == k]

        x_train = p_train[FEATURES]

        y1 = p_train['ConfirmedCases']

        y2 = p_train['Fatalities']

        model = xgb.XGBRegressor(n_estimators=1300)

        model.fit(x_train, y1)

        ConfirmedCasesPreds = model.predict(p_test[FEATURES])

        model.fit(x_train, y2)

        FatalitiesPreds = model.predict(p_test[FEATURES])

        p_test['ConfirmedCases'] = ConfirmedCasesPreds

        p_test['Fatalities'] = FatalitiesPreds

        submission = pd.concat([submission, p_test[['ForecastId', 'ConfirmedCases', 'Fatalities']]], axis=0)
train_df = pd.read_csv('../input/covid19-global-forecasting-week-3/train.csv', index_col="Id")

test_df = pd.read_csv('../input/covid19-global-forecasting-week-3/test.csv', index_col="ForecastId")
y_train_cc = np.array(train_df['ConfirmedCases'].astype(int))

y_train_ft = np.array(train_df['Fatalities'].astype(int))

cols = ['ConfirmedCases', 'Fatalities']

full_df = pd.concat([train_df.drop(cols, axis=1), test_df])

index_split = train_df.shape[0]

full_df = pd.get_dummies(full_df, columns=full_df.columns)

x_train = full_df[:index_split]

x_test= full_df[index_split:]
from sklearn.tree import DecisionTreeRegressor

dt = DecisionTreeRegressor(random_state=1)

dt.fit(x_train,y_train_cc)

y_pred_cc = dt.predict(x_test)

y_pred_cc = y_pred_cc.astype(int)

y_pred_cc[y_pred_cc <0]=0
dt_f = DecisionTreeRegressor()

dt_f.fit(x_train,y_train_ft)
y_pred_ft = dt_f.predict(x_test)

y_pred_ft = y_pred_ft.astype(int)

y_pred_ft[y_pred_ft <0]=0

predicted_df_dt = pd.DataFrame([y_pred_cc, y_pred_ft], index = ['ConfirmedCases','Fatalities'], columns= np.arange(1, y_pred_cc.shape[0] + 1)).T
from sklearn.tree import DecisionTreeClassifier

dtcla = DecisionTreeClassifier()

# We train model

dtcla.fit(x_train, y_train_cc)

predictions = dtcla.predict(x_test)

dtcla.fit(x_train,y_train_ft)

predictions1 = dtcla.predict(x_test)
submission1 = pd.DataFrame({'ForecastId': test_df.index,'ConfirmedCases':predictions,'Fatalities':predictions1})
submission['ConfirmedCases']=np.round((submission['ConfirmedCases']+submission1['ConfirmedCases'])/2)

submission['Fatalities']=np.round((submission['Fatalities']+submission1['Fatalities'])/2)
submission.to_csv('submission.csv',index=False)


import fintech.accounts as accounts
import pymysql

def write_account_transaction_to_db(filename, account):
    print('Starting write of DB example')

    # Open database connection
    connection = pymysql.connect('localhost', 'user', 'password', 'accounts')

    # prepare a cursor object using cursor() method
    cursor = connection.cursor()

    try:
        # Execute INSERT command
        account_number = account.account_number
        name = account.account_holder
        cursor.execute(
            "INSERT INTO acc_info (idacc_info, name) " +
            "VALUES (" + account_number + ", '" + name + "')")
        # Commit the changes to the database

        # Write out the transactions
        for transaction in account.history:
            id = transaction.id
            action = transaction.action
            amount = transaction.amount
            statement = "INSERT into transactions (idtransactions, type, amount, account) VALUES (" + str(id) + ", '" + action + "', " + str(amount) + ", " + str(account_number) + ")"
            print(statement)
            cursor.execute(statement)
        connection.commit()
    except Exception as exp:
        # Something went wrong
        # rollback the changes
        print(exp)
        connection.rollback()

    # Close the database connection
    connection.close()

    print('Done Write DB Example')

print('Starting')
acc = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
acc.deposit(23.45)
acc.withdraw(12.33)

print('Writing Account Transactions')
write_account_transaction_to_db('accounts.xlsx', acc)

print('Done')


import pandas as pd
import wget
import multiprocessing

def run_process(url, output_path):
    wget.download(url, out=output_path)

if __name__ == '__main__':
    cpus = multiprocessing.cpu_count()
    max_pool_size = 4
    pool = multiprocessing.Pool(cpus if cpus < max_pool_size else max_pool_size)

    df = pd.read_json("set_10000.json")

    train_images = df[['image_url','token_id']]
    print(f"Please wait, downloading {train_images.index.size} images.")
    for ind in train_images.index:
        image_url = df['image_url'][ind]
        filename = df['token_id'][ind]

        pool.apply_async(run_process, args=(f"{image_url}=s128", f"out/{filename}.png", ))

    pool.close()
    pool.join()
    print("Finished")


import datetime
from yahooquery import Ticker
import matplotlib.pyplot as plt
import pandas as pd

today = datetime.datetime.strptime(str(datetime.date.today()),'%Y-%m-%d').date()

from_date = datetime.datetime.strptime("2021-01-06", "%Y-%m-%d").date()

print(f'Collecting data from {from_date} - {today}')
#end_date = date_1 + datetime.timedelta(days=10)
to_date = from_date
spy = Ticker('spy')
li = []
while to_date < today:
    to_date = from_date + datetime.timedelta(days=7)
    print(f'{from_date} - {to_date}')
    temp_df = spy.history(start=from_date, end=to_date, interval="5m")

    li.append(temp_df)
    from_date = to_date

spy_data = pd.concat(li)
outfile = open("spy_data.csv", 'wb')
spy_data.to_csv(outfile, sep='\t', encoding='utf-8')
outfile.close()


# !/usr/bin/python
# -*- coding: utf-8 -*-
"""Run the main body of this code to execute experiments."""
from __future__ import absolute_import
from __future__ import print_function
import os
import os.path
import autograd.numpy as np
import autograd.numpy.random as npr
import pickle
from autograd import grad
from autograd.misc.flatten import flatten
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF
from code.plotting import create_figure_and_axs, setup_ax_and_save, full_extent
from code.optimizers import adam, opt_params
from code.data_loader import load_mnist
from code.neural_network import init_random_params, identity, nn_predict, pred_loss

def log_gaussian(weights, var):
    """Find the log probability of the weights given some centered, spherical Gaussian prior.

    :param weights: The parameters ([[float]]) of the neural network.
    :param var: The variance (positive float) of the Gaussian distribution.
    :return: The log probability (float) of the weights of the neural network.
    """
    norm_sum = 0.0
    for i in range(10):
        norm_sum += np.linalg.norm(weights[0][0][:, i] * np.exp(var[i]), 2)
    return -norm_sum / 10.0

def experiment(train_data, valid_data, init_scale, num_iters_hypernet, step_size_hypernet, step_size, num_iters,
               batch_size_data, global_seed=0):
    """Run the second experiment, which consists of fitting a hypernetwork, which outputs neural network parameters.
    These neural network parameters try to fit the training data with some additional loss for the hyperparameters.
    We try to optimize the hyperparameters given the learned neural network response through the hypernetwork.
    We observe how the hypernetwork performs on the training and testing, by graphing it against the true loss.
    The true loss is found by training a neural network to convergence at a discrete number of points.

    :param train_data: The training data.
    :param valid_data: The testing data.
    :param init_scale: The scale (positive float) for the hypernetwork initialization.
    :param num_iters_hypernet: The number of iterations (integer) to run the hypernetwork optimizer for.
    :param step_size_hypernet: The step size (positive float) for the hypernetwork optimizer.
    :param step_size: The step size (positive float) for the loss approximation optimizer.
    :param num_iters: The number of iterations (integer) to run the optimization for.
    :param batch_size_data: The number of data points (integer) for a batch.
    :param global_seed: The seed (integer) to use when choosing a constant seed.
    :return: None, but saves pictures.
    """
    assert init_scale > 0
    assert step_size_hypernet > 0, step_size > 0
    assert num_iters > 0, num_iters_hypernet > 0

    def hyper_loss(weights, hyper):
        """Find the loss for neural network that is dependant on the hyperparameter.

        :param weights: The weights ([[float]]) of the neural network.
        :param hyper: The hyperparameter (float) input to the hypernetwork.
        :return: The loss (float) of network dependant on the hyperparameter.
        """
        return -log_gaussian(weights, hyper)

    train_inputs, train_targets = train_data
    valid_inputs, valid_target = valid_data
    batch_ind, feature_ind = 0, 1
    elementary_input_size = np.shape(train_inputs)[feature_ind]
    elementary_output_size = np.shape(train_targets)[feature_ind]
    elementary_layer_sizes = [elementary_input_size, elementary_output_size]
    num_hypers = 10  # The dimensionality of the hyperparameter space (integer).
    batch_size_elementary = 100  # The number of elementary data points to sample (i.e not hyperparameters).

    # Define neural network and function to turn a vector into its weight structure.
    example_elementary_params = init_random_params(init_scale, elementary_layer_sizes, npr.RandomState(global_seed))
    flat_elementary_params, unflatten_vector_to_network_weights = flatten(example_elementary_params)
    num_elementary_params = len(flat_elementary_params)

    rs_train = npr.RandomState(global_seed)

    def train_objective(weights, hyper, seed):
        """The objective for training a neural network.

        :param weights: The weights ([[float]]) of the neural network.
        :param hyper: The hyperparameter (float) input to the hypernetwork.
        :param seed: The seed (integer) for sampling.
        :return: The training loss (float).
        """
        idx = rs_train.randint(len(train_inputs) - batch_size_elementary)
        return -pred_loss(weights, train_inputs[idx:idx+batch_size_elementary],
                          train_targets[idx:idx+batch_size_elementary]) + hyper_loss(weights, hyper)

    def valid_objective(weights, hyper, seed):
        """The objective for validating a neural network.

        :param weights: The weights ([[float]]) of the neural network.
        :param hyper: The hyperparameter (float) input to the hypernetwork.
        :param seed: The seed (integer) for sampling a hyperparameter.
        :return: The validation loss (float).
        """
        return -pred_loss(weights, valid_inputs, valid_target)

    # TODO: Rename valid_objective to prediction loss, and move train objective into data generator block

    pickle_name = 'learn_vs_true_loss_scatter.pickle'
    if not os.path.isfile(pickle_name):  # Train a neural network from scratch with different hyperparameter values.
        real_step_size = 0.0001  # The step size to use to find the real loss (float).
        real_num_iters = 1000  # The number of iterations to use to find the real loss (integer).
        num_data = 2 ** 10 * 10
        data_inputs, data_target_params, data_target_loss = [], [], []
        for i in range(num_data):
            hyper_train = rs_train.rand(num_hypers) * 6.0 - 3.0
            print("Optimizing network parameters: ", i)
            init_params = init_random_params(init_scale, elementary_layer_sizes, npr.RandomState(global_seed))

            def cur_obj(w, seed):
                """The current objective function of the neural network.

                :param w: The weights ([float]) of the neural network.
                :param seed: The seed (integer) for sampling a hyperparameter.
                :return: The current objective value (float).
                """
                return train_objective(w, hyper_train, seed)

            optimized_params, _, _, _ = adam(grad(cur_obj), init_params, step_size=real_step_size, num_iters=real_num_iters)
            loss = valid_objective(optimized_params, hyper_train, global_seed)
            data_inputs += [hyper_train]
            flatten_opt_param, unflatten_vector_to_network_weights = flatten(optimized_params)
            data_target_params += [flatten_opt_param]
            data_target_loss += [loss]
        data_inputs = np.array(data_inputs)
        data_target_params = np.array(data_target_params)
        data_target_loss = np.array(data_target_loss)

        with open(pickle_name, 'wb') as handle:
            pickle.dump({'inputs': data_inputs, 'target_params': data_target_params, 'target_loss': data_target_loss},
                        handle, protocol=pickle.HIGHEST_PROTOCOL)

    with open(pickle_name, 'rb') as handle:
        pickle_data = pickle.load(handle)
        data_inputs = pickle_data['inputs']
        data_target_params = pickle_data['target_params']
        data_target_loss = pickle_data['target_loss']

    batch_size_sample = batch_size_data
    train_ind, valid_ind = batch_size_data, batch_size_data
    data_inputs_train, data_inputs_valid = data_inputs[:train_ind], data_inputs[valid_ind:]
    data_target_params_train, _ = data_target_params[:train_ind], data_target_params[valid_ind:]
    data_target_loss_train, data_target_loss_valid = data_target_loss[:train_ind], data_target_loss[valid_ind:]

    # New training for lambda, W, and lambda, Loss
    weight_layer_sizes = [num_hypers, num_elementary_params]
    init_weight_params = init_random_params(init_scale, weight_layer_sizes, npr.RandomState(global_seed))

    def train_weight_objective_loss(weights, seed):
        """The objective for training a neural network.

        :param weights: The weights ([[float]]) of the neural network.
        :param seed: The seed (integer) for sampling.
        :return: The training loss (float).
        """
        local_data_inputs = [rs_train.rand(num_hypers) * 6.0 - 3.0 for _ in range(batch_size_sample)]
        losses = [train_objective(unflatten_vector_to_network_weights(nn_predict(weights, np.array([local_data_input]),
                                                                                identity)[0]),
                                  local_data_input, global_seed)
                  for local_data_input in local_data_inputs]
        return np.mean(np.array(losses))

    def callback_weights_loss(weights, opt_iteration, g):
        """A callback for optimization.

        :param weights: The hypernetwork weights
        :param opt_iteration: The optimization iteration
        :param g: The gradient.
        :return: None
        """
        if opt_iteration % 10 == 0:
            print("Sampled Valid Loss Target: ", opt_iteration, ", Loss: ", train_weight_objective_loss(weights, 0))

    weight_params_loss, _, _, _ = adam(grad(train_weight_objective_loss), init_weight_params,
                                       step_size=step_size_hypernet, num_iters=num_iters_hypernet + 100,
                                       callback=callback_weights_loss)

    init_weight_params = init_random_params(init_scale, weight_layer_sizes, npr.RandomState(global_seed))

    def train_weight_objective_loss_target(weights, seed):
        """The objective for training a neural network.

        :param weights: The weights ([[float]]) of the neural network.
        :param seed: The seed (integer) for sampling.
        :return: The training loss (float).
        """
        idx = rs_train.randint(np.maximum(len(data_inputs_train) - batch_size_data, 1))
        local_data_inputs = data_inputs_train[idx:idx + batch_size_data]
        losses = [train_objective(unflatten_vector_to_network_weights(nn_predict(weights, np.array([local_data_input]),
                                                                                identity)[0]),
                                  local_data_input, global_seed)
                  for local_data_input in local_data_inputs]
        return np.mean(np.array(losses))

    def callback_weights_loss_target(weights, opt_iteration, g):
        """A callback for optimization.

        :param weights: The hypernetwork weights
        :param opt_iteration: The optimization iteration
        :param g: The gradient.
        :return: None
        """
        if opt_iteration % 10 == 0:
            print("Fixed Valid Loss Target: ", opt_iteration, ", Loss: ",
                  train_weight_objective_loss_target(weights, 0))

    weight_params_loss_target, _, _, _ = adam(grad(train_weight_objective_loss_target), init_weight_params,
                                              step_size=step_size_hypernet, num_iters=num_iters_hypernet,
                                              callback=callback_weights_loss_target)

    print("Preparing the data for plotting...")
    kernel = RBF()
    gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=1)
    gp.fit(data_inputs_train, data_target_loss_train)
    gp_loss_predictions, sigma = gp.predict(data_inputs_valid, return_std=True)

    def hypernet_loss(weights, local_data_input):
        """Find the loss for the hypernetwork.

        :param weights: The hypernet weights
        :param local_data_input: A hyperparameter.
        :return: None
        """
        weight_predictions_valid = nn_predict(weights, [local_data_input], identity)
        weight_predictions_valid = unflatten_vector_to_network_weights(weight_predictions_valid[0])
        return valid_objective(weight_predictions_valid, None, global_seed)

    loss_weight_predictions_loss = [hypernet_loss(weight_params_loss, data_input)
                                    for data_input in data_inputs_valid]
    loss_weight_predictions_loss_target = [hypernet_loss(weight_params_loss_target, data_input)
                                           for data_input in data_inputs_valid]

    fig, axs = create_figure_and_axs(fig_width=21, fig_height=7, num_cols=3, ms_size=34)

    print("Drawing the scatter plot...")
    min_v, max_v = 0.6, 1.1
    axs[0].hexbin(data_target_loss_valid, gp_loss_predictions, extent=[min_v, max_v, min_v, max_v], cmap='Reds',
                  mincnt=1)
    axs[1].hexbin(data_target_loss_valid, loss_weight_predictions_loss_target, extent=[min_v, max_v, min_v, max_v],
                  cmap='Greens', mincnt=1)
    axs[2].hexbin(data_target_loss_valid, loss_weight_predictions_loss, extent=[min_v, max_v, min_v, max_v],
                  cmap='Blues', mincnt=1)

    print("____________________________________________________________________________")
    print("Number of train data points: ", batch_size_data)
    print("GP Predicted Best: ", np.min(gp_loss_predictions), ", Actual Result: ",
          data_target_loss_valid[np.argmin(gp_loss_predictions)])
    print("Fixed Hypernet Predicted Best: ", np.min(loss_weight_predictions_loss_target),
          ", Actual Result: ", data_target_loss_valid[np.argmin(loss_weight_predictions_loss_target)])
    print("Stochastic Hypernet Predicted Best: ", np.min(loss_weight_predictions_loss),
          ", Actual Result: ", data_target_loss_valid[np.argmin(loss_weight_predictions_loss)])
    print("Actual Best: ", np.min(data_target_loss_valid))
    print("____________________________________________________________________________")

    orient_line = np.linspace(min_v, max_v, 100)
    for ax in axs:
        ax.plot(orient_line, orient_line, color='k')
        ax.set_xlim([min_v, max_v])
        ax.set_ylim([min_v, max_v])

    # axs[0].set_title('GP Mean')
    # axs[1].set_title('Hyper-train fixed')
    # axs[2].set_title('Hyper-train')

    axs[0].set_ylabel('Inferred Loss')

    #axs[1].set_xlabel('True loss')

    axs[1].set_yticks([])
    axs[2].set_yticks([])

    axs[0].set_xticks([.7, .8, .9, 1.0])
    axs[1].set_xticks([.7, .8, .9, 1.0])
    axs[2].set_xticks([.7, .8, .9, 1.0])
    axs[0].set_yticks([.7, .8, .9, 1.0])
    setup_ax_and_save(axs, fig, 'learn_vs_true_loss_scatter', do_xticks=False, do_yticks=False, y_mod=750.0, dpi=300)
    for key, ax in enumerate(axs):
        #if key is 0:
        extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
        fig.savefig('figures/ax' + str(key) + '_scatter.png', bbox_inches=extent.expanded(1.32, 1.15))
        fig.savefig('figures/ax' + str(key) + '_scatter.pdf', bbox_inches=extent.expanded(1.32, 1.15))
        #else:
        #extent = full_extent(ax, do_yticks=False).transformed(fig.dpi_scale_trans.inverted())
        #fig.savefig('figures/ax' + str(key) + '_scatter.png', bbox_inches=extent.expanded(1.0, 1.15))

    print("Drawing the histograms...")
    [ax.cla() for ax in axs]

    bins = 50
    axs[0].hist(gp_loss_predictions - data_target_loss_valid, bins=bins, color='r', normed=True, edgecolor='r')
    axs[1].hist(loss_weight_predictions_loss_target - data_target_loss_valid, bins=bins, color='g', normed=True,
                edgecolor='g')
    axs[2].hist(loss_weight_predictions_loss - data_target_loss_valid, bins=bins, color='b', normed=True, edgecolor='b')

    axs[0].set_ylabel('Frequency')
    axs[1].set_xlabel('Inferred - true loss')

    y_min, y_max = 10e32, -10e32
    for ax in axs:
        ylim = ax.get_ylim()
        y_min, y_max = np.minimum(y_min, ylim[0]), np.maximum(y_max, ylim[1])
    x_min, x_max = -0.35, 0.6
    for ax in axs:
        ax.set_xlim([x_min, x_max]), ax.set_ylim([y_min, y_max])
        ax.axvline(0, ymax=1.0, linestyle='--', color='Black')

    setup_ax_and_save(axs, fig, 'learn_vs_true_loss_hist', do_xticks=False)
    for key, ax in enumerate(axs):
        extent = full_extent(ax).transformed(fig.dpi_scale_trans.inverted())
        if key is 0:
            fig.savefig('figures/ax' + str(key) + '_hist.png', bbox_inches=extent) #.expand(1.32, 1.15))
            fig.savefig('figures/ax' + str(key) + '_hist.pdf', bbox_inches=extent)
        else:
            fig.savefig('figures/ax' + str(key) + '_hist.png', bbox_inches=extent)
            fig.savefig('figures/ax' + str(key) + '_hist.pdf', bbox_inches=extent)

if __name__ == '__main__':
    params = opt_params(None)

    n_data, n_data_val, n_data_test = 50000, params['n_data_val'], params['n_data_test']
    _, train_images, train_labels, test_images, test_labels = load_mnist()
    train_data = (train_images[:n_data], train_labels[:n_data])
    valid_data = (train_images[n_data:n_data + n_data_val], train_labels[n_data:n_data + n_data_val])
    test_data = (test_images[:n_data_test], test_labels[:n_data_test])

    # Define information about the optimization procedure and networks.
    init_scale = 0.00001  # The scale (positive float) for the hypernetwork initialization.
    num_iters = 5000  # The number of iterations to do the optimization for (integer).
    step_size = 0.0001  # The step size for the hyperparameter optimizer (positive float).
    num_iters_hypernet = 500  # The number of iterations to optimize the hypernetwork for (integer).

    batch_size_data = 25  # [10, 25, 100, 250, 1000, 25]
    experiment(train_data, valid_data, init_scale, num_iters_hypernet, params['step_size_hypernet'], step_size,
               num_iters, batch_size_data, params['global_seed'])


from flask import Flask, jsonify, render_template
import pandas as pd

belly_data = pd.read_excel("belly_data.xlsx", index=None)
samples = pd.read_csv("belly_button_biodiversity_samples.csv")
meta = pd.read_csv("Belly_Button_Biodiversity_Metadata.csv")

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html")

@app.route("/names")
def sample_id():
    samples_ids = list(samples.columns)
    samples_ids = samples_ids[1:]
    return jsonify(samples_ids)

@app.route("/otu")
def description():

    descriptions = list(belly_data["Lowest Taxonomic Level of Bacteria/Archaea Found"])
    return jsonify(descriptions)

@app.route("/metadata/<sample_id>")
def metadata(sample_id):
    sample_id = int(sample_id.replace("BB_", ""))
    match = meta[meta['SAMPLEID'] == sample_id][['SAMPLEID', 'ETHNICITY', 'GENDER', 'AGE', 'LOCATION','BBTYPE']].to_dict(orient='records')[0]
    return jsonify(match)

@app.route("/sample/<sample_id>")
def choosen_sample(sample_id):
    df = samples[['otu_id', sample_id]].sort_values(sample_id, ascending=False).dropna().rename(
        columns={sample_id: "sample_values"}).to_dict(orient='list')
    return jsonify(df)

if __name__ == '__main__':
    app.run(debug=True)


# File:         test_cc.py
# Purpose:      test the central controller backend
# Based on:     ../test_hybrid.py, ../test_uniform_sched.py

import openql as ql
import os
import unittest

from config import json_dir, output_dir
from typing import List, Tuple

config_fn = os.path.join(json_dir, 'test_cfg_cc.json')
platform_name = 's-17'
default_num_qubits = 17
default_num_cregs = 32
default_num_bregs = 32
all_qubits = range(0, default_num_qubits)

class TestCentralController(unittest.TestCase):
    @classmethod
    def setUp(cls):
        ql.initialize()
        ql.set_option('output_dir', output_dir)
        ql.set_option('scheduler', 'ALAP')
        ql.set_option('log_level', 'LOG_WARNING')

    # NB: based on PycQED::openql_helpers.py
    @staticmethod
    def _configure_compiler(
            platform: ql.Platform,
            cqasm_src_filename: str = "",
            extra_pass_options: List[Tuple[str, str]] = None
    ) -> ql.Compiler:
        # NB: for alternative ways to configure the compiler, see
        # https://openql.readthedocs.io/en/latest/gen/reference_configuration.html#compiler-configuration

        c = platform.get_compiler()

        # remove default pass list (this also removes support for most *global* options as defined in
        # https://openql.readthedocs.io/en/latest/gen/reference_options.html, except for 'log_level')
        # NB: this defeats automatic backend selection by OpenQL based on key "eqasm_compiler"
        c.clear_passes()

        # add the passes we need
        compiling_cqasm = cqasm_src_filename != ""
        if compiling_cqasm:
            # cQASM reader as very first step
            c.append_pass(
                'io.cqasm.Read',
                'reader',
                {
                    'cqasm_file': cqasm_src_filename
                }
            )

            # decomposer for legacy decompositions (those defined in the "gate_decomposition" section)
            # FIXME: comment incorrect, also decomposes new-style definitions
            # see https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
            c.append_pass(
                'dec.Instructions',
                # NB: don't change the name 'legacy', see:
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#predicate-key
                'legacy',
            )
        else:  # FIXME: experimental. Also decompose API input to allow use of new style decompositions
            c.append_pass(
                'dec.Instructions',
                # NB: don't change the name 'legacy', see:
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#predicate-key
                'legacy',
            )

        # report the initial qasm
        c.append_pass(
            'io.cqasm.Report',
            'initial',
            {
                'output_suffix': '.cq',
                'with_timing': 'no'
            }
        )

        # schedule
        c.append_pass(
            'sch.ListSchedule',
            'scheduler',
            {
                'resource_constraints': 'yes'
            }
        )

        # report scheduled qasm
        c.append_pass(
            'io.cqasm.Report',
            'scheduled',
            {
                'output_suffix': '.cq',
            }
        )

        # generate code using CC backend
        # NB: OpenQL >= 0.10 no longer has a CC-light backend
        c.append_pass(
            'arch.cc.gen.VQ1Asm',
            'cc_backend'
        )

        # set compiler pass options
        # c.set_option('*.output_prefix', f'{OqlProgram.output_dir}/%N.%P')
        # if self._arch == 'CC':
        #     c.set_option('cc_backend.output_prefix', f'{OqlProgram.output_dir}/%N')
        c.set_option('scheduler.scheduler_target', 'alap')
        if compiling_cqasm:
            c.set_option('cc_backend.run_once', 'yes')  # if you want to loop, write a cqasm loop

        # finally, set user pass options
        if extra_pass_options is not None:
            for opt, val in extra_pass_options:
                c.set_option(opt, val)

        # log.debug("\n" + c.dump_strategy())
        return c

    def test_gate_decomposition_cz(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_gate_decomposition_cz', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("cz", [8, 10])
        k.gate("cz", [10, 8])
        k.gate("cz", [8, 11])
        k.gate("cz", [11, 9])
        k.gate("cz", [11, 14])
        k.gate("cz", [14, 11])
        k.gate("cz", [10, 14])
        k.gate("cz", [14, 10])
        k.gate("cz", [9, 11])
        k.gate("cz", [11, 9])
        k.gate("cz", [9, 12])
        k.gate("cz", [12, 9])
        # k.gate("cz", [11, 15])
        # k.gate("cz", [15, 11])
        k.gate("cz", [12, 15])
        k.gate("cz", [15, 12])

        p.add_kernel(k)

        # compile, with new style gate decompositions
        c = self._configure_compiler(platform)
        c.compile(p)

    def test_native_instructions(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_native_instructions', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("prepz", [0])
        k.gate("i", [0])
        k.gate("rx180", [0])
        k.gate("ry180", [0])
        k.gate("rx90", [0])
        k.gate("ry90", [0])
        k.gate("rxm90", [0])
        k.gate("rym90", [0])

        k.gate("measure", [0])

        p.add_kernel(k)
        p.compile()

    def test_special_instructions(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_special_instructions', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("spec", [0])
        k.gate("rx12", [0])
        k.gate("square", [0])
        k.gate("rx45", [0])

        k.gate("rx2theta", [0])
        k.gate("rxm2theta", [0])
        k.gate("rx2thetaalpha", [0])
        k.gate("rphi180", [0])
        k.gate("rphi180beta", [0])
        k.gate("rx180beta", [0])
        k.gate("rphi180beta2", [0])
        k.gate("ry90beta", [0])
        k.gate("rym90alpha", [0])
        k.gate("ry90betapi", [0])
        k.gate("rphi180alpha", [0])
        k.gate("rx90alpha", [0])
        k.gate("rx180alpha2", [0])
        k.gate("rphim2theta", [0])

        p.add_kernel(k)
        p.compile()

    def test_gate_decompositions_alias(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_gate_decompositions_alias', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.gate("x", [0])
        k.gate("y", [0])
        k.gate("roty90", [0])
        k.gate("x180", [0])
        k.gate("y180", [0])
        k.gate("y90", [0])
        k.gate("x90", [0])
        k.gate("my90", [0])
        k.gate("mx90", [0])

        p.add_kernel(k)
        p.compile()

    # Quantum Error Correction cycle
    def test_qec(self):
        platform = ql.Platform(platform_name, config_fn)

        p = ql.Program('test_qec', platform, default_num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, default_num_qubits, default_num_cregs, default_num_bregs)

        # pipelined QEC: [
        # see: R. Versluis et al., Phys. Rev. A 8, 034021 (2017)
        # - nw, ne, sw, se] -> [n, e, w, s] because we rotate grid
        # - H -> rym90, ry90, see Fig 2 of reference
        #
        # class SurfaceCode, qubits, tiles, width, getNeighbourN, getNeighbourE, getNeighbourW, getNeighbourS,
        # getX, getZ, getData

        # define qubit aliases:
        # FIXME: neighbours make no sense anymore
        x = 7
        x_n = x - 5
        x_e = x + 1
        x_s = x + 5
        x_w = x - 1

        z = 11
        z_n = z - 5
        z_e = z + 1
        z_s = z + 5
        z_w = z - 1

        # create classical registers
        # FIXME: deprecated by branch condex
        # if 0:
        #     rdx = ql.CReg(1)
        #     rdz = ql.CReg(2)

        # X stabilizers
        k.gate("rym90", [x])
        k.gate("rym90", [x_n])
        k.gate("rym90", [x_e])
        k.gate("rym90", [x_w])
        k.gate("rym90", [x_s])
        k.barrier([])

        k.gate("cz", [x, x_e])
        k.gate("cz", [x, x_n])
        k.gate("cz", [x, x_s])
        k.gate("cz", [x, x_w])
        k.barrier([])

        k.gate("ry90", [x])
        k.gate("ry90", [x_n])
        k.gate("ry90", [x_e])
        k.gate("ry90", [x_w])
        k.gate("ry90", [x_s])
        k.barrier([])

        # k.gate("measure", [x], rdX)
        k.gate('measure', [x], 0, 0.0, [0])
        k.barrier([])

        # Z stabilizers
        k.gate("rym90", [z])
        k.barrier([])

        k.gate("cz", [z, z_e])
        k.gate("cz", [z, z_s])
        k.gate("cz", [z, z_n])
        k.gate("cz", [z, z_w])
        k.barrier([])

        k.gate("ry90", [z])
        # k.gate("measure", [z], rdZ)
        k.gate('measure', [z], 0, 0.0, [1])

        p.add_kernel(k)
        p.compile()

    def test_angle(self):
        platform = ql.Platform(platform_name, config_fn)

        p = ql.Program('test_angle', platform, default_num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, default_num_qubits, default_num_cregs, default_num_bregs)

        k.gate("rx180", [6], 0, 1.2345)     # NB: Python interface lacks classical parameter

        p.add_kernel(k)
        p.compile()

    def test_qi_example(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))

        p = ql.Program('test_qi_example', platform, 17, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 17, default_num_cregs, default_num_bregs)

        k.barrier([])
        for q in [0, 1, 2, 3, 4]:
            k.gate("prepz", [q])
        k.barrier([])

        k.gate("ry180", [0, 2])     # FIXME: "y" does not work, but gate decomposition should handle?
        # k.gate("cz", [0, 2])
        k.gate("cz", [8, 10])
        k.gate("y90", [2])
        k.barrier([])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.barrier([])

        p.add_kernel(k)

        # compile, with new style gate decompositions
        c = self._configure_compiler(platform)
        c.compile(p)

    # based on ../test_cqasm_reader.py::test_conditions
    # FIXME: uses old cqasm_reader
    def test_cqasm_conditions(self):
        cqasm_config_fn = os.path.join(json_dir, 'config_cc.json')
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))
        number_qubits = platform.get_qubit_number()
        name = 'test_cqasm_conditions'
        program = ql.Program(name, platform, number_qubits)
        qasm_rdr = ql.cQasmReader(platform, program, cqasm_config_fn)
        qasm_str = """
            version 1.1

            var qa, qb: qubit
            var ca, cb: bool

            { measure_fb qa, ca | measure_fb qb, cb }
            # .barrier  # use subcircuit to force new kernel, and thus scheduling realm
            # barrier [qa,qb]
            # { barrier qa | barrier qb }
            barrier

            # # Old hack for feedback
            # { measure qa, ca | measure qb, cb }
            #
            # .wait_uhfqa # use subcircuit to force new kernel, and thus scheduling realm
            # { _wait_uhfqa qa | _wait_uhfqa qb }
            # .dist_dsm
            # { _dist_dsm qa, ca | _dist_dsm qb, cb }
            # .wait_dsm
            # { _wait_dsm qa | _wait_dsm qb }
            # .test
            #
            cond(true) x qa
            cond(false) y qa
            cond(ca) z qa
            cond(!true) x qa
            cond(!false) y qa
            cond(!ca) z qa
            cond(!!true) x qa
            cond(!!false) y qa
            cond(!!ca) z qa
            cond(ca && cb) x qa
            cond(ca && true) y qa
            cond(ca && false) z qa
            cond(true && cb) x qa
            cond(false && cb) y qa
            cond(ca || cb) z qa
            cond(ca || true) x qa
            cond(ca || false) y qa
            cond(true || cb) z qa
            cond(false || cb) x qa
            cond(ca ^^ cb) y qa
            cond(ca ^^ true) z qa
            cond(ca ^^ false) x qa
            cond(true ^^ cb) y qa
            cond(false ^^ cb) z qa
            cond(!(ca && cb)) x qa
            cond(!(ca && true)) y qa
            cond(!(ca && false)) z qa
            cond(!(true && cb)) x qa
            cond(!(false && cb)) y qa
            cond(!(ca || cb)) z qa
            cond(!(ca || true)) x qa
            cond(!(ca || false)) y qa
            cond(!(true || cb)) z qa
            cond(!(false || cb)) x qa
            cond(!(ca ^^ cb)) y qa
            cond(!(ca ^^ true)) z qa
            cond(!(ca ^^ false)) x qa
            cond(!(true ^^ cb)) y qa
            cond(!(false ^^ cb)) z qa
            """
        qasm_rdr.string2circuit(qasm_str)
        ql.set_option('log_level', 'LOG_INFO')
        program.compile()
        # self.assertTrue(file_compare(os.path.join(output_dir, name + '.qasm'),
        #                              os.path.join(qasm_golden_dir, name + '.qasm')))

    def test_cqasm_gate_decomposition(self):
        cqasm_config_fn = os.path.join(json_dir, 'config_cc.json')
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))
        number_qubits = platform.get_qubit_number()
        name = 'test_cqasm_gate_decomposition'
        program = ql.Program(name, platform, number_qubits)
        qasm_rdr = ql.cQasmReader(platform, program, cqasm_config_fn)
        qasm_str = """
            version 1.1

            var qa, qb: qubit
            var ca, cb: bool

            { measure_fb qa, ca | measure_fb qb, cb }
            """
        qasm_rdr.string2circuit(qasm_str)
        ql.set_option('log_level', 'LOG_INFO')
        program.compile()

    # based on test_hybrid.py::test_do_while_nested_for()
    # FIXME: now fails with "in repeat-until loop body: expected creg reference, but got something else"
    @unittest.skip("fails on sf_cz_sw")
    # additionally, we don't support if_?_break anymore
    def test_nested_rus(self):
        num_qubits = 5
        q_idx = 0

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq_openql_0_10.json'))
        p = ql.Program('test_nested_rus', platform, num_qubits, default_num_cregs, default_num_bregs)

        outer_program = ql.Program('outer_program', platform, num_qubits, default_num_cregs, default_num_bregs)
        outer_kernel = ql.Kernel('outer_kernel', platform, num_qubits, default_num_cregs)
        outer_kernel.gate("measure_fb", [q_idx])
        outer_kernel.gate("if_1_break", [q_idx])  # FIXME: uses incorrect label
        outer_program.add_kernel(outer_kernel)

        inner_program = ql.Program('inner_program', platform, num_qubits, default_num_cregs, default_num_bregs)
        inner_kernel = ql.Kernel('inner_kernel', platform, num_qubits, default_num_cregs)
        inner_kernel.gate("measure_fb", [q_idx])
        inner_kernel.gate("if_0_break", [q_idx])
        inner_kernel.gate("rx180", [q_idx])
        inner_program.add_for(inner_kernel, 1000000)  # NB: loops *kernel*

        outer_program.add_program(inner_program)

        # NB: loops *program*, CC backend interprets all conditions as true
        foo = ql.CReg(0)
        p.add_do_while(outer_program, ql.Operation(foo, '==', foo))

        ql.set_option('log_level', 'LOG_INFO')  # override log level
        p.compile()

    # based on DCL test program
    @unittest.skip("fails on sf_cz_sw")
    # FIXME: additionally, we don't support if_?_break anymore
    def test_nested_rus_angle_0(self):
        num_qubits = 17

        ancilla1idx = 10
        ancilla2idx = 8
        data_idx = 11

        angle = 0
        echo_delay_inner_rus = 1
        echo_delay_inner_rus_data = 1
        echo_delay_outer_rus = 1

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq.json'))
        p = ql.Program('test_nested_rus_angle_0', platform, num_qubits, default_num_cregs, default_num_bregs)

        init_kernel = ql.Kernel('initKernel', platform, num_qubits, default_num_cregs)
        init_kernel.prepz(ancilla1idx)
        init_kernel.prepz(ancilla2idx)
        init_kernel.prepz(data_idx)
        init_kernel.gate('cw_{:02}'.format(int(angle) // 20 + 9), [data_idx])
        init_kernel.gate("wait", [], 0)
        p.add_kernel(init_kernel)

        outer_program = ql.Program('outerProgram', platform, num_qubits, default_num_cregs, default_num_bregs)
        rus_program_1 = ql.Program('rusProgram1', platform, num_qubits, default_num_cregs, default_num_bregs)
        rus_kernel_1 = ql.Kernel('rusKernel1', platform, num_qubits, default_num_cregs)
        rus_kernel_1.gate("rx2theta", [ancilla1idx])
        rus_kernel_1.gate("rYm90", [ancilla2idx])
        rus_kernel_1.gate("cz", [ancilla1idx, ancilla2idx])
        rus_kernel_1.gate("rXm2theta", [ancilla1idx])
        rus_kernel_1.gate("ry90beta", [ancilla2idx])
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx], 0)
        rus_kernel_1.gate("rphi180", [data_idx])
        rus_kernel_1.gate("measure_fb", [ancilla1idx])
        rus_kernel_1.gate("wait", [ancilla2idx], echo_delay_inner_rus)
        rus_kernel_1.gate("rphi180", [ancilla2idx])
        rus_kernel_1.gate("wait", [ancilla2idx], 1860-echo_delay_inner_rus)
        rus_kernel_1.gate("wait", [data_idx], echo_delay_inner_rus_data)
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_1.gate("if_0_break", [ancilla1idx])
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_1.gate("rx180", [ancilla1idx])
        rus_kernel_1.gate("rxm90", [ancilla2idx])
        rus_kernel_1.gate("rx180", [data_idx])
        rus_kernel_1.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_program_1.add_for(rus_kernel_1, 1000000)
        outer_program.add_program(rus_program_1)

        interm_program = ql.Program('intermProgram', platform, num_qubits, default_num_cregs, default_num_bregs)
        interm_kernel = ql.Kernel('intermKernel', platform, num_qubits, default_num_cregs)
        interm_kernel.gate("rx180", [ancilla2idx])
        interm_kernel.gate("rx180", [data_idx])
        interm_kernel.gate("rYm90", [data_idx])
        interm_kernel.gate("cz", [ancilla2idx, data_idx])
        interm_kernel.gate("rY90", [data_idx])
        interm_program.add_kernel(interm_kernel)
        outer_program.add_program(interm_program)

        rus_program_2 = ql.Program('rusProgram2', platform, num_qubits, default_num_cregs, default_num_bregs)
        rus_kernel_2 = ql.Kernel('rusKernel2', platform, num_qubits, default_num_cregs)
        rus_kernel_2.gate("rX2theta", [ancilla1idx])
        rus_kernel_2.gate("rYm90alpha", [ancilla2idx])
        rus_kernel_2.gate("cz", [ancilla1idx, ancilla2idx])
        rus_kernel_2.gate("rX2thetaalpha", [ancilla1idx])
        rus_kernel_2.gate("rY90betapi", [ancilla2idx])
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx], 0)
        rus_kernel_2.gate("rphi180beta", [data_idx])
        rus_kernel_2.gate("measure_fb", [ancilla1idx])
        rus_kernel_2.gate("wait", [ancilla2idx], echo_delay_inner_rus)
        rus_kernel_2.gate("rphi180alpha", [ancilla2idx])
        rus_kernel_2.gate("wait", [ancilla2idx], 1860-echo_delay_inner_rus)
        rus_kernel_2.gate("wait", [data_idx], echo_delay_inner_rus_data)
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_2.gate("if_0_break", [ancilla1idx])
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_kernel_2.gate("rx180", [ancilla1idx])
        rus_kernel_2.gate("rx90alpha", [ancilla2idx])
        rus_kernel_2.gate("rx180beta", [data_idx])
        rus_kernel_2.gate("wait", [ancilla1idx, ancilla2idx, data_idx], 0)
        rus_program_2.add_for(rus_kernel_2, 1000000)
        outer_program.add_program(rus_program_2)

        end_kernel = ql.Kernel('outerKernel', platform, num_qubits, default_num_cregs)
        end_kernel.gate("wait", [ancilla2idx, data_idx], 0)
        end_kernel.gate("rx180alpha2", [ancilla2idx])
        end_kernel.gate("measure_fb", [ancilla2idx])
        end_kernel.gate("wait", [data_idx], echo_delay_outer_rus)
        end_kernel.gate("rphi180beta2", [data_idx])
        end_kernel.gate("wait", [data_idx], 1880-echo_delay_outer_rus)
        end_kernel.gate("wait", [ancilla2idx, data_idx], 0)
        end_kernel.gate("if_0_break", [ancilla2idx])
        outer_program.add_kernel(end_kernel)

        foo = ql.CReg(0)
        p.add_do_while(outer_program, ql.Operation(foo, '==', foo))

        measure_kernel = ql.Kernel('measureKernel', platform, num_qubits, default_num_cregs)
        measure_kernel.gate("measure_fb", [data_idx])
        p.add_kernel(measure_kernel)

        ql.set_option('log_level', 'LOG_INFO')  # override log level
        p.compile()

    def test_rc_sched_measure(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))

        p = ql.Program('test_rc_sched_measure', platform, 5, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 5, default_num_cregs, default_num_bregs)

        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [0])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [1])

        p.add_kernel(k)
        p.compile()

    # FIXME: solve for real
    @unittest.skip("fails: 'Inconsistency detected in bundle contents: time travel not yet possible in this version'")
    def test_rc_sched_measure_asap(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))

        p = ql.Program('test_rc_sched_measure_asap', platform, 5, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 5, default_num_cregs, default_num_bregs)

        k.gate('x', [2])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [0])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.gate('x', [1])

        p.add_kernel(k)
        ql.set_option('scheduler', 'ASAP')
        p.compile()

    def test_rc_sched_measure_barrier(self):
        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s5_direct_iq.json'))

        p = ql.Program('test_rc_sched_measure_barrier', platform, 5, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, 5, default_num_cregs, default_num_bregs)

        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.barrier([])
        k.gate('x', [0])
        k.barrier([])
        for q in [0, 1, 2, 3, 4]:
            k.gate("measure", [q])
        k.barrier([])
        k.gate('x', [1])

        p.add_kernel(k)
        p.compile()

    # FIXME: solve for real
    @unittest.skip("fails with new IR")
    def test_rc_sched_cz(self):
        num_qubits = 17

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq.json'))

        p = ql.Program('test_rc_sched_cz', platform, num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, num_qubits, default_num_cregs, default_num_bregs)

        # NB: requires resource to manage fluxing
        k.gate("cz", [10, 14])  # no associated park
        k.gate("cz", [9, 11])   # parks 12
        k.gate('x', [10])
        p.add_kernel(k)

        ql.set_option('log_level', 'LOG_DEBUG')  # override log level
        p.compile()

    def test_rc_sched_prepz(self):
        num_qubits = 17

        platform = ql.Platform(platform_name,  os.path.join(json_dir, 'config_cc_s17_direct_iq.json'))

        p = ql.Program('test_rc_sched_prepz', platform, num_qubits, default_num_cregs, default_num_bregs)
        k = ql.Kernel('kernel_0', platform, num_qubits, default_num_cregs, default_num_bregs)

        k.gate('x', [2])
        k.gate('prepz', [1, 2])
        k.gate('x', [1])
        p.add_kernel(k)

        ql.set_option('log_level', 'LOG_DEBUG')  # override log level
        p.compile()

    # FIXME: add:
    # - qec_pipelined
    # - long program (RB)

if __name__ == '__main__':
    unittest.main()


from datetime import datetime

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect

from virtualbarcamp.accounts.forms import AcceptCodeOfConductForm
from virtualbarcamp.accounts.models import Account

def login(request):
    return render(request, "registration/login.html", {"include_bundle": "accounts"})

@login_required
def accept_code_of_conduct(request):
    if (
        hasattr(request.user, "account")
        and request.user.account.has_accepted_code_of_conduct is not None
    ):
        return redirect("home")

    if request.method == "POST":
        form = AcceptCodeOfConductForm(request.POST)
        if form.is_valid():
            Account.objects.get_or_create(
                user=request.user, has_accepted_code_of_conduct=datetime.now()
            )
            return redirect("home")
    else:
        form = AcceptCodeOfConductForm()

    return render(
        request,
        "registration/accept_code_of_conduct.html",
        {"form": form, "include_bundle": "accounts"},
    )


from datetime import datetime as dt
from threading import Lock, Thread
from ..customtypes import PowermeterMonitorDict
from ..hardware import S0interface, ZeroW

def _calcPower(_time: dt) -> float:
    global currentTime
    delta_t_sec: float = (_time - currentTime).total_seconds()
    currentTime = _time
    return 3.6 / delta_t_sec

def _fillMonitorDict(_time: dt, monitor: PowermeterMonitorDict, lock: Lock) -> None:
    """calculates electric power and fills PowermeterMonitorDict"""

    # calculate power before filling monitor-dict
    power: float = _calcPower(_time)

    # if power is too big (rarely happens under heavy load -> "Sensorprellung")
    # limit: 3 Phasen à 63A à 240V == 45.36kW
    if power > 46:
        # Werte darüber sind unmöglich
        return

    with lock:
        # start filling
        monitor["datetime"].append(_time)
        monitor["power_kW"].append(power)

# initialize time to get clean intervals for calculating consumed electric power
currentTime: dt = dt.now()

def _powermeterFunc(device: ZeroW, monitor: PowermeterMonitorDict, lock: Lock) -> None:
    """
    Main loop waiting for S0-interface to receive a signal, and then storing its
    state in a globally shared python-Dictionary.
    """

    # initialisiere S0-Schnittstelle
    s0interface: S0interface = device.powermeter
    s0interface.wasteSignal()

    while True:
        s0interface.waitForSignal()
        _fillMonitorDict(dt.now(), monitor, lock)

def powermeterThread(device: ZeroW, monitor: PowermeterMonitorDict, lock: Lock) -> None:
    """starts the powermeter-Thread"""
    powermeterThread: Thread = Thread(
        target=_powermeterFunc,
        name="powermeterThread",
        args=([device, monitor, lock])
    )
    powermeterThread.start()


from PyQt5.QtWidgets import (
  QPushButton, QDialog, QLabel,
  QFileDialog, QLineEdit, QDialogButtonBox,
  QFormLayout, QVBoxLayout, QWidget, QSpinBox
)
from .common_gui import accept_and_finish
from logic.train_network import train

class TrainWindow(QDialog):
  def __init__(self, parent):
    super().__init__(parent)
    self.setWindowTitle("Train neural network")
    self.layout = QFormLayout()
    self.setup_form()
    self.setup_end_buttons()
    self.setLayout(self.layout)
    self.exec()

  def setup_form(self):
    form = QWidget(self)
    form_layout = QFormLayout()
    label_processed_midi = QLabel('Select processed midi')
    self.processed_midi_input = QLineEdit()
    self.processed_midi_input.setReadOnly(True)
    form_layout.addRow(label_processed_midi, self.processed_midi_input)

    browser_button_midi = QPushButton('Browser...')
    browser_button_midi.setObjectName('BrowserButton')
    browser_button_midi.pressed.connect(self.set_processed_midi)
    form_layout.addWidget(browser_button_midi)

    label_weights_folder = QLabel('Select neural network weights folder')
    self.weights_folder_input = QLineEdit()
    self.weights_folder_input.setReadOnly(True)
    form_layout.addRow(label_weights_folder, self.weights_folder_input)

    browser_button_wights = QPushButton('Browser...')
    browser_button_wights.setObjectName('BrowserButton')
    browser_button_wights.pressed.connect(self.set_weights_folder)
    form_layout.addWidget(browser_button_wights)

    label_output_midi = QLabel('Number of epochs')
    label_output_midi.setObjectName('QLabelRow')
    self.epochs = QSpinBox()
    self.epochs.setObjectName('QSpinBox')
    self.epochs.setRange(1, 999999)
    self.epochs.setValue(8)
    form_layout.addRow(label_output_midi, self.epochs)

    form.setLayout(form_layout)
    self.layout.addWidget(form)

  def setup_end_buttons(self):
    buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
    buttonBox.accepted.connect(self.end_dialog)
    buttonBox.rejected.connect(self.reject)
    self.layout.addWidget(buttonBox)

  def end_dialog(self):
    accept_and_finish([
      self.processed_midi_input.text(),
      self.weights_folder_input.text(),
      self.epochs.value()
    ], train, self)

  def set_processed_midi(self):
    self.processed_midi_input.setText(
      QFileDialog.getOpenFileName (None, 'Select processed midi file')[0]
    )

  def set_weights_folder(self):
    directory_list = QFileDialog.getExistingDirectory(None, "Select weights Directory")
    print(directory_list)
    if directory_list:
      self.weights_folder_input.setText(directory_list)


import os
import json
import sys

import findspark
from IPython.core.display import display
import pyspark.sql.functions as psf
from pyspark.sql.functions import get_json_object
from pyspark.sql.types import ArrayType, StructType, StructField, StringType, IntegerType, DecimalType, DateType, \
    DoubleType, LongType

findspark.init('/Users/pradeepipol/Movies/BigData/spark-3.0.0-bin-hadoop2.7/')
import pyspark

from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession
from pyspark.streaming import StreamingContext, DStream

#from pyspark.streaming.dstream import d

f_count = 0;

def country_count_update(newValue, existingCount):
    if existingCount is None:
        existingCount = 0

    return sum(newValue) + existingCount
if __name__ == "__main__":
    os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages com.datastax.spark:spark-cassandra-connector_2.12:3.0.0-alpha2 pyspark-shell'

    data_spark_schema =StructType([
    StructField("venue", StructType([
        StructField("venue_name", StringType(), True),
        StructField("lon", DoubleType(), True),
        StructField("lat", DoubleType(), True),
        StructField("venue_id", DoubleType(), True),

    ]), True),
    StructField("visibility", StringType(), True),
    StructField("response", StringType(), True),
    StructField("guests", LongType(), True),
    StructField("member", StructType([
        StructField("member_id", LongType(), True),
        StructField("photo", StringType(), True),
        StructField("member_name", StringType(), True),
    ]), True),
    StructField("rsvp_id", LongType(), True),
    StructField("mtime", DateType(), True),
    StructField("event", StructType([
        StructField("event_name", StringType(), True),
        StructField("event_id", StringType(), True),
        StructField("time", DateType(), True),
        StructField("event_url", StringType(), True),
    ]), True),
    StructField("group", StructType([
        StructField("group_topics", ArrayType(StructType([
            StructField("urlkey", StringType(), True),
            StructField("topic_name", StringType(), True),
        ])), True),
        StructField("group_city", StringType(), True),
        StructField("group_country", StringType(), True),
        StructField("group_id", LongType(), True),
        StructField("group_name", StringType(), True),
        StructField("group_lon", DoubleType(), True),
        StructField("group_lat", DoubleType(), True),
        StructField("group_urlname", StringType(), True),
        StructField("group_state", StringType(), True),
    ]), True),
])

    spark = SparkSession \
       .builder \
       .config("spark.jars","spark-streaming-kafka-0-10_2.12-3.0.0.jar,spark-sql-kafka-0-10_2.12-3.0.0.jar,kafka-clients-2.5.0.jar,commons-pool2-2.8.0.jar,spark-token-provider-kafka-0-10_2.12-3.0.0.jar") \
        .config("spark.cassandra.connection.host", "127.0.0.1") \
        .config('spark.cassandra.output.consistency.level', 'ONE') \
        .appName("Q1") \
       .getOrCreate()

    streamingInputDF = spark \
        .readStream \
        .format("kafka") \
        .option("kafka.bootstrap.servers", "192.168.1.173:9092") \
        .option("subscribe", "meetup") \
        .load()

    stream_records = streamingInputDF.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING) as meetup_data") \
        .select(psf.from_json("meetup_data", data_spark_schema).alias("meetup_data"))
    stream_records.printSchema()
    sites_flat = stream_records.select("meetup_data.*").alias("one").select("member.*","event.*","venue.*","group.*","one.*").drop("group_topics")
    sites_flat1=sites_flat.filter(sites_flat["group_state"]=="CA").select(psf.array_join('group.group_topics.topic_name',delimiter=',').alias("group_topics"),"*").drop("member","event","venue","group")

    sites_flat1.printSchema()

    query =sites_flat1.writeStream\
      .outputMode("append")\
      .format("org.apache.spark.sql.cassandra")\
      .option("checkpointLocation", "Local\Temp")\
      .option("keyspace", "meetup")\
      .option("table", "meet")\
      .start()

    query.awaitTermination()

    #streamingOutPut=streamingInputDF.writeStream.start()

   # print(streamingInputDF.)
   # print(streamingInputDF.status)
    #streamingSelectDF = streamingInputDF.select(get_json_object(($'value').cast("string"),"group_state").alias("state")).groupBy("state")

                                                #(($"value")).cast("string"),"$.group_state")).alias())
    #df.isStreaming()  # Returns True for DataFrames that have streaming sources

  #  print(streamingSelectDF.status)
    #df=pyspark.streaming("kafka").option("kafka.bootstrap.servers", "192.168.56.1:9092").option(
       # "subscribe", "meetup").load()

    #sc = SparkContext(appName="PythonStreamingDirectKafkaWordCount",conf=conf)
    #

   # ssc.checkpoint("checkpoint")

   # kvs = KafkaUtils.createDirectStream(ssc, ["meetup"], {"bootstrap.servers": '192.168.56.1:9092'})

    # , kafkaParams = {"metadata.broker.list":"localhost:9092"}
    #kvs = KafkaUtils.createDirectStream(ssc, topic, kafkaParams)
'''

    kvs = KafkaUtils.createStream(ssc, '192.168.56.1:9092', "1", {'topic': 1})
    rsvps = kvs.map(lambda x: x[1])
    rsvps_json = rsvps.map(lambda x: json.loads(x.encode('ascii', 'ignore')))
    rsvps_us = rsvps_json.filter(lambda x: x['group']['group_country'] == 'us')
    rsvps_city_pair = rsvps_us.map(lambda x: (x['group']['group_city'], 1))
    rsvps_city_statefulCount = rsvps_city_pair.updateStateByKey(country_count_update)

    rsvps_city_statefulCount.pprint()

    ssc.start()
ssc.awaitTermination()
'''


from datetime import datetime

end_time = datetime(2021, 2, 12, 20)

sites_to_block = ['www.facebook.com', 'facebook.com']

hosts_path = "/etc/hosts"

redirect = "127.0.0.1"

def block_sites():
    if datetime.now() < end_time:
        print("block sites")
        # write all web-sites from our list to hostsfile
        with open(hosts_path, 'r+') as hostsfile:
            hosts_content = hostsfile.read()
            for site in sites_to_block:
                if site not in hosts_content:
                    hostsfile.write(redirect + " " + site + "\n")

    else:
        print("unblock sites")
        with open(hosts_path, 'r+') as hostsfile:
            lines = hostsfile.readline()
            hostsfile.seek(0)
            for line in lines:
                if not any(site in line for site in sites_to_block):
                    hostsfile.write(line)
                hostsfile.truncate()

if __name__ == "__main__":
    # 1. run manually
    block_sites()


from types import SimpleNamespace
import torch
from torch import nn
from datasets import SentenceClassificationDataset
from multitask_classifier import MultitaskBERT, process_batch
from optimizer import AdamW
from tokenizer import BertTokenizer
from torch.utils.data import DataLoader
from tqdm import tqdm

import torch.nn.functional as F

class CrossEncoder(nn.Module):

    def __init__(
            self,
            option='finetune', device='cuda',
            hidden_dropout_prob=0.2,
            optimizer_params = {'lr': 2e-5},
            optimizer_class = torch.optim.AdamW,
                 ):

        super().__init__()
        # Init model
        config = {
            'hidden_dropout_prob': 0.001,
            'num_labels': {3: 0, 2: 1, 4: 2, 0: 3, 1: 4},
            'hidden_size': 768,
            'data_dir': '.',
            'option': 'pretrain',
            'local_files_only': False
            }

        config = SimpleNamespace(**config)

        self.device = device
        self.model = MultitaskBERT(config)
        self.model.to(self.device)
        self.optimizer = AdamW(self.model.parameters(), lr=1e-3, weight_decay=0.05, betas=[0.9, 0.999], eps=1e-06)

    def fit(self, train_dataloader: DataLoader):
            for sentence_pairs in tqdm(train_dataloader, desc="Iteration", smoothing=0.05):
                self.model.zero_grad()
                self.model.train()
                sst_ids, sst_mask, sst_labels = process_batch(sentence_pairs, self.device, "sst")
                sst_outputs = self.model.predict_sentiment(sst_ids, sst_mask)
                sst_loss = F.cross_entropy(sst_outputs, sst_labels.view(-1), reduction='mean')
                print(sst_loss)
                self.optimizer.zero_grad()
                sst_loss.backward()
                self.optimizer.step()

if __name__ == '__main__':
    sentence_pairs = [
        ["The sun is shining. [SEP] It's a beautiful day.", 0.85, 1],
        ["Cats are independent animals. [SEP] Dogs are loyal companions.", 0.65, 2],
        ["Learning a new language can be challenging. [SEP] Practice is key to language acquisition.", 0.75, 3],
        ["Books are a source of knowledge. [SEP] Reading enhances intellectual growth.", 0.90, 4]
    ]
    tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', local_files_only=False)
    sentence_pairs = SentenceClassificationDataset(sentence_pairs, None, tokenizer)
    sentence_pairs_dataloader = DataLoader(sentence_pairs, shuffle=True, batch_size=4,
                                        collate_fn=sentence_pairs.collate_fn, num_workers=4)
    cross_encoder = CrossEncoder(device = 'cpu')
    cross_encoder.fit(train_dataloader=sentence_pairs_dataloader)


import cx_Freeze

executables = [cx_Freeze.Executable("main.py",
                                    targetName="Floppy.exe",
                                    icon="icon.ico")]
                                  #base = "Win32GUI",
                                  #icon = "assets/bobi_icon.png")]

build_exe_options = {"packages": ["pygame"],
                     "include_files":["src", "assets"]}

cx_Freeze.setup(
    name = "Floppy: Ad aeternum",
    version = "1.0b",
    description = "Juego Floppy: Ad aeternum",
    options={"build_exe": build_exe_options},
    executables = executables
    )


import pickle
from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from fastsklearnfeature.candidates.CandidateFeature import CandidateFeature
from fastsklearnfeature.candidates.RawFeature import RawFeature
from fastsklearnfeature.transformations.OneHotTransformation import OneHotTransformation
from typing import List

def create_min_curve(losses, test):
	min_losses = [losses[0]]
	test_equi = [test[0]]
	for l in np.arange(1, len(losses)):
		if min_losses[-1] > losses[l]:
			min_losses.append(losses[l])
			test_equi.append(test[l])
		else:
			min_losses.append(min_losses[-1])
			test_equi.append(test_equi[-1])
	return min_losses, test_equi

#all_features_200: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_new2.p", "rb"))

#all_features_200: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_step.p", "rb"))

all_features_200: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_new.p", "rb"))

#raw_first: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_new.p", "rb"))

numeric_representations: List[CandidateFeature] = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/features.p", "rb"))

name2feature = {}
name2id = {}
feature_names = []
for f in range(len(numeric_representations)):
	name2feature[str(numeric_representations[f])] = numeric_representations[f]
	name2id[str(numeric_representations[f])] = f
	feature_names.append(str(numeric_representations[f]))

losses = np.array([r['loss'] for r in all_features_200.results])
#losses_raw = [r['loss'] for r in raw_first.results]

complexities = np.zeros(len(losses))
feature_count = np.zeros(len(numeric_representations))

feature_scores = []

for t in range(len(numeric_representations)):
	feature_scores.append([])

for k,v in all_features_200.vals.items():
	for i in range(len(losses)):
		if v[i]:
			if k in name2feature:
				complexities[i] += name2feature[k].get_complexity()
				feature_count[name2id[k]] += 1
				feature_scores[name2id[k]].append(all_features_200.results[i]['loss'])

'''
test = [r['test'] for r in all_features_200.results]
test_raw = [r['test'] for r in raw_first.results]
'''

feature_score_average = []
feature_score_stddev = []
for trial_losses in feature_scores:
	feature_score_average.append(np.average(trial_losses))
	feature_score_stddev.append(np.std(trial_losses))

feature_score_average = np.array(feature_score_average)
feature_score_stddev = np.array(feature_score_stddev)

ids = np.argsort(feature_score_average)

fig, ax = plt.subplots()
barlist= plt.bar(range(len(numeric_representations)), feature_score_average[ids], yerr=feature_score_stddev[ids])

for f_id in ids:
	fname = feature_names[f_id]
	if fname in all_features_200.best_trial['misc']['vals'] and all_features_200.best_trial['misc']['vals'][fname][0]:
		barlist[f_id].set_color('red')
	else:
		barlist[f_id].set_color('blue')

plt.xticks(range(len(numeric_representations)), np.array(feature_names)[ids], rotation='vertical')
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.5)
plt.show()

ids = np.argsort(feature_count*-1)

fig, ax = plt.subplots()
barlist= plt.bar(range(len(numeric_representations)), feature_count[ids])

for f_id in ids:
	fname = feature_names[f_id]
	if fname in all_features_200.best_trial['misc']['vals'] and all_features_200.best_trial['misc']['vals'][fname][0]:
		barlist[f_id].set_color('red')
	else:
		barlist[f_id].set_color('blue')

plt.xticks(range(len(numeric_representations)), np.array(feature_names)[ids], rotation='vertical')
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.5)
plt.show()

test = 1.0 - np.array([r['test'] for r in all_features_200.results])

ids = np.argsort(complexities)

plt.plot(complexities[ids], losses[ids], color='red', label='cv error')
plt.plot(complexities[ids], test[ids], color='blue', label='test error')
plt.xlabel('Complexity')
plt.ylabel('Loss (1.0 - AUC)')

leg = plt.legend(loc='best', ncol=1, mode="expand", shadow=True, fancybox=True)
leg.get_frame().set_alpha(0.5)

plt.show()

plt.plot(range(len(complexities)), complexities, color='red')
plt.xlabel('Trials')
plt.ylabel('Complexity')

leg = plt.legend(loc='best', ncol=1, mode="expand", shadow=True, fancybox=True)
leg.get_frame().set_alpha(0.5)

plt.show()