import json
import logging
import uuid

import aiohttp.web

from .jsonencoder import JSONEncoder

logger = logging.getLogger(__name__)

class WebSocketRPCProtocol:

    def __init__(self):
        self.service_container = {}
        self.service_allowed_methods = {}
        self.disconnect_handlers = {}
        self.clients_by_id = {}

    async def connect(self, request):
        socket = aiohttp.web.WebSocketResponse()
        await socket.prepare(request)

        client_id, client_data = await self.handshake(socket)
        self.clients_by_id[client_id] = socket

        session_data = {
            **request.cookies,
            **client_data
        }

        for service_name, service in self.service_container.items():
            await service.on_connected(client_id, session_data)

        await self.receive_messages(socket, client_id)

        return socket

    async def handshake(self, socket):
        async for msg in socket:
            if msg.type == aiohttp.WSMsgType.text:
                rpc_body = json.loads(msg.data)
                logger.debug("rpc body: %s", rpc_body)

                if rpc_body["type"] != "hello":
                    raise Exception("invalid hello message")

                client_id = rpc_body.get("client_id", str(uuid.uuid1()))
                hello_message = {
                    "type": "hello",
                    "client_id": client_id
                }

                await socket.send_str(json.dumps(hello_message))
                return client_id, {k: v for k, v in rpc_body.items() if k not in ("type", "client_id")}

            elif msg.type == aiohttp.WSMsgType.close:
                raise Exception("connection closed without explanation")

        raise Exception("no handshake received")

    async def receive_messages(self, socket, client_id):
        async for msg in socket:
            if msg.type == aiohttp.WSMsgType.text:
                try:
                    message_body = json.loads(msg.data)
                    if message_body["type"] != "rpc":
                        raise Exception("unhandled message of type %s" % message_body["type"])

                    rpc_body = message_body["rpc"]
                    service_name = rpc_body["service"]
                    method_name = rpc_body["method"]
                    service = self.service_container[service_name]

                    if method_name in self.service_allowed_methods[service_name]:
                        await getattr(service, method_name)(client_id, **rpc_body.get("params", {}))
                    else:
                        logger.warning("method %s is not allowed for service %s", method_name, service_name)
                except Exception as e:
                    logger.exception(str(e))
            elif msg.type == aiohttp.WSMsgType.close:
                pass

        for service_name, service in self.service_container.items():
            await service.on_disconnected(client_id)

    def register_service(self, service_instance, allowed_methods):
        service_name = service_instance.__class__.__name__
        self.service_container[service_name] = service_instance
        self.service_allowed_methods[service_name] = allowed_methods

    async def send_event(self, client_id, event_data):
        socket = self.clients_by_id[client_id]

        message = {
            "type": "event",
            "event": event_data }

        await socket.send_str(json.dumps(message, cls = JSONEncoder))


# Weichao Qiu @ 2018
# Visualize arm dataset

import unreal.virtual_db as vdb
import imageio as io
import matplotlib.pyplot as plt
import numpy as np

joint_name = vdb.meta.arm_skel

def fov2f(fov, width):
    # fov = 2 * arctan(w / 2f)
    fov = fov * np.pi / 180
    return width / (2 * np.tan(fov / 2))

def f2fov(f, width):
    # fov = 2 * arctan(w / 2f)
    fov = 2 * np.arctan(width / (2 * f))
    fov = fov * 180 / np.pi
    return fov

def get_vertex_2d_raw(dataset, ids, cam, actor_name):
    vertexs = dataset.get_d3_vertex(ids)
    #actor_name = "OWI-arm-baked-pivot_2";
    if isinstance(vertexs[0], dict): #fit to the new data generation tool
        vertex = vertexs[0][actor_name]
    else:
        vertex = vertexs[0]
    points3d = np.array([[v['X'], v['Y'], v['Z']] for v in vertex])
    points2d = cam.project_to_2d(points3d)
    return points2d

def get_vertex_2d(dataset, frame_id, cam_name, actor_name):
    cams = [cam_name]
    ids = [frame_id]

    images = dataset.get_image(cams, ids); image_dir = images[0]
    cams_info = dataset.get_cam_info(cams, ids); cam_info = cams_info[0]

    loc = cam_info['Location']
    rot = cam_info['Rotation']
    cam = vdb.d3.CameraPose(loc['X'], loc['Y'], loc['Z'],
        rot['Pitch'], rot['Yaw'], rot['Roll'],
        cam_info['FilmWidth'], cam_info['FilmHeight'], cam_info['FilmWidth']/2)

    points2d = get_vertex_2d_raw(dataset, ids, cam, actor_name)
    return points2d, image_dir

def get_joint_2d_raw(dataset, ids, cam, actor_name):
    #joint_name = vdb.meta.arm_skel
    joints = dataset.get_d3_skeleton(ids)
    #actor_name = "OWI-arm-baked-pivot_2";
    joint = joints[0][actor_name]['WorldJoints'] # This usage might change
    # joint = dict({k.lower(): v for (k, v) in joint.items()}) # Convert key to lower case
    # Convert to np array
    points3d = np.array([[joint[v]['X'], joint[v]['Y'], joint[v]['Z']] for v in joint_name])
    points2d = cam.project_to_2d(points3d)
    return points2d

def get_joint_2d(dataset, frame_id, cam_name, actor_name):
    ids = [frame_id]
    cams = [cam_name]

    images = dataset.get_image(cams, ids); image_dir = images[0]

    # Project to 2D joint
    # ---------------------------------------------------------------------
    cams_info = dataset.get_cam_info(cams, ids); cam_info = cams_info[0]

    loc = cam_info['Location']
    rot = cam_info['Rotation']
    cam = vdb.d3.CameraPose(loc['X'], loc['Y'], loc['Z'],
        rot['Pitch'], rot['Yaw'], rot['Roll'],
        cam_info['FilmWidth'], cam_info['FilmHeight'], cam_info['FilmWidth']/2)

    #print(points3d)
    points2d = get_joint_2d_raw(dataset, ids, cam, actor_name)

    return points2d, image_dir

def get_joint_vertex_2d(dataset, frame_id, cam_name, actor_name):
    ids = [frame_id]
    cams = [cam_name]

    images = dataset.get_image(cams, ids); image_dir = images[0]

    # Project to 2D joint
    # ---------------------------------------------------------------------
    cams_info = dataset.get_cam_info(cams, ids); cam_info = cams_info[0]

    if cam_info.__contains__('Fov'):
        f = fov2f(cam_info['Fov'], cam_info['FilmWidth'])
    else:
        f = fov2f(90, cam_info['FilmWidth'])

    loc = cam_info['Location']
    rot = cam_info['Rotation']
    cam = vdb.d3.CameraPose(loc['X'], loc['Y'], loc['Z'],
        rot['Pitch'], rot['Yaw'], rot['Roll'],
        cam_info['FilmWidth'], cam_info['FilmHeight'], f)

    joint_2d = get_joint_2d_raw(dataset, ids, cam, actor_name)
    vertex_2d = get_vertex_2d_raw(dataset, ids, cam, actor_name)
    return joint_2d, vertex_2d, image_dir

def show_frame(dataset, frame_id, cam_name, actor_name):
    ids = [frame_id]
    cams = [cam_name]

    points2d, _ = get_joint_2d(dataset, frame_id, cam_name, actor_name)

    # Visualize 2D joint
    # ---------------------------------------------------------------------
    images = dataset.get_image(cams, ids); image = images[0]

    plt.subplot(121)
    plt.imshow(io.imread(image))
    plt.plot(points2d[:,0], points2d[:,1], '*')
    for edge in vdb.meta.arm_skel_edge:
        plt.plot(points2d[edge,0], points2d[edge,1], 'r-')

    # Load 3D vertex data and project to 2d
    # ---------------------------------------------------------------------
    points2d = get_vertex_2d(dataset, frame_id, cam_name, actor_name)

    plt.subplot(122)
    plt.imshow(io.imread(image))
    plt.plot(points2d[:,0], points2d[:,1], '*')

    # Show plot
    plt.show()

def main():
    db_root_dir = '/mnt/c/qiuwch/ue4_project/CarAct/OWIMap'

    cams = ['FusionCameraActor_1', 'FusionCameraActor2',
        'FusionCameraActor3', 'FusionCameraActor4']

    dataset = vdb.Dataset(db_root_dir)
    ids = dataset.get_ids() # The frame ids we have.
    print('Number of images %d' % len(ids))

    show_frame(dataset, ids[0], cams[3])

if __name__ == '__main__':
    main()


# !/usr/bin python3
# encoding: utf-8 -*-
# @author: 沙陌 微信：Matongxue_2
# @Time: 2022-01-16 14:42
# @Copyright：北京码同学

# 几个高阶函数，了解下，主要是做面试题的时候可能会用到

# 计算给定序列中各个数字的2次方,生成一个新的列表
from functools import reduce

list1 = [2,4,6,7,2,6] # 新的是[4,16,36,49,4,36]

def ercifang(i):
    return i**2
# map(ercifang, list1) 含义是，将list1中的每个数据传递给函数ercifang进行计算，得到新结果
print(list(map(ercifang, list1)))
# 使用匿名函数
print(list(map(lambda i:i**2, list1)))
list2 = ['20cm','10mm','30mm','50cm','70cm']
# 提出list2这个列表中以cm结尾数据，形成新的列表
def jduge_cm(i:str): #i:str  注意这是声明入参的类型是字符串
    if i.endswith('cm'):
        return i
print(list(map(jduge_cm, list2)))

# 计算一个列表的所有项的乘几
list3 = [2,4,6,7,2,6]
# 需要导入from functools import reduce
print(reduce(lambda x, y: x * y, list3))

# 得到一个列表中所有的偶数
list4 = [1,2,3,4,5,6,7,8,9,10]
print(list(filter(lambda x: x % 2 == 0, list4)))

list5 = ['20cm','10mm','30mm','50cm','70cm']
# 提出list2这个列表中以cm结尾数据，形成新的列表
def jduge_cm(i:str): #i:str  注意这是声明入参的类型是字符串
    return i.endswith('cm')
print(list(filter(lambda i: i.endswith('cm'), list5)))
print(list(filter(jduge_cm, list5)))
#filter 的第一个参数是函数，这个函数的返回值是布尔值，表示是否满足条件


import fnmatch
import click
import collections
import mlflow
import json
import time
import os.path

from ast import literal_eval
from tempfile import TemporaryDirectory
from tqdm import tqdm

from aim import Run, Image, Text, Audio

IMAGE_EXTENSIONS = ('jpg', 'bmp', 'jpeg', 'png', 'gif', 'svg')
HTML_EXTENSIONS = ('html',)
TEXT_EXTENSIONS = (
    'txt',
    'log',
    'py',
    'js',
    'yaml',
    'yml',
    'json',
    'csv',
    'tsv',
    'md',
    'rst',
    'jsonnet',
)

# Audio is not handled in mlflow but including here just in case
AUDIO_EXTENSIONS = (
    'flac',
    'mp3',
    'wav',
)

class RunHashCache:
    def __init__(self, repo_path, no_cache=False):
        self._cache_path = os.path.join(repo_path, 'mlflow_logs_cache')
        self._needs_refresh = False

        if no_cache and os.path.exists(self._cache_path):
            os.remove(self._cache_path)

        try:
            with open(self._cache_path) as FS:
                self._cache = json.load(FS)
        except Exception:
            self._cache = {}

    def get(self, run_id):
        return self._cache.get(run_id)

    def __setitem__(self, key: str, val: str):
        if not self._cache.get(key) == val:
            self._cache[key] = val
            self._needs_refresh = True

    def __getitem__(self, key: str):
        return self._cache[key]

    def refresh(self):
        if self._needs_refresh:
            with open(self._cache_path, 'w') as FS:
                json.dump(self._cache, FS)

def get_mlflow_experiments(client, experiment):
    if experiment is None:
        # process all experiments
        experiments = client.search_experiments()
    else:
        try:
            ex = client.get_experiment(experiment)
        except mlflow.exceptions.MlflowException:
            ex = client.get_experiment_by_name(experiment)
        if not ex:
            raise RuntimeError(f'Could not find experiment with id or name "{experiment}"')
        experiments = (ex,)

    return experiments

def get_aim_run(repo_inst, run_id, run_name, experiment_name, run_cache):
    if run_cache.get(run_id):
        aim_run = Run(
            run_hash=run_cache[run_id],
            repo=repo_inst,
            system_tracking_interval=None,
            capture_terminal_logs=False,
            experiment=experiment_name,
        )
    else:
        aim_run = Run(
            repo=repo_inst,
            system_tracking_interval=None,
            capture_terminal_logs=False,
            experiment=experiment_name,
        )
        run_cache[run_id] = aim_run.hash
    aim_run.name = run_name
    return aim_run

def collect_run_params(aim_run, mlflow_run):
    aim_run['mlflow_run_id'] = mlflow_run.info.run_id
    aim_run['mlflow_experiment_id'] = mlflow_run.info.experiment_id
    aim_run.description = mlflow_run.data.tags.get("mlflow.note.content")

    # Collect params & tags
    # MLflow provides "string-ified" params values and we try to revert that
    aim_run['params'] = _map_nested_dicts(_try_parse_str, mlflow_run.data.params)
    aim_run['tags'] = {
        k: v for k, v in mlflow_run.data.tags.items() if not k.startswith('mlflow')
    }

def collect_artifacts(aim_run, mlflow_run, mlflow_client, exclude_artifacts):
    if '*' in exclude_artifacts:
        return

    run_id = mlflow_run.info.run_id

    artifacts_cache_key = '_mlflow_artifacts_cache'
    artifacts_cache = aim_run.meta_run_tree.get(artifacts_cache_key) or []

    __html_warning_issued = False
    with TemporaryDirectory(prefix=f'mlflow_{run_id}_') as temp_path:
        artifact_loc_stack = [None]
        while artifact_loc_stack:
            loc = artifact_loc_stack.pop()
            artifacts = mlflow_client.list_artifacts(run_id, path=loc)

            for file_info in artifacts:
                if file_info.is_dir:
                    artifact_loc_stack.append(file_info.path)
                    continue

                if file_info.path in artifacts_cache:
                    continue
                else:
                    artifacts_cache.append(file_info.path)

                if exclude_artifacts:
                    exclude = False
                    for expr in exclude_artifacts:
                        if fnmatch.fnmatch(file_info.path, expr):
                            exclude = True
                            break
                    if exclude:
                        continue

                downloaded_path = mlflow_client.download_artifacts(run_id, file_info.path, dst_path=temp_path)
                if file_info.path.endswith(HTML_EXTENSIONS):
                    if not __html_warning_issued:
                        click.secho(
                            'Handler for html file types is not yet implemented.', fg='yellow'
                        )
                        __html_warning_issued = True
                    continue
                elif file_info.path.endswith(IMAGE_EXTENSIONS):
                    aim_object = Image
                    kwargs = dict(
                        image=downloaded_path,
                        caption=file_info.path
                    )
                    content_type = 'image'
                elif file_info.path.endswith(TEXT_EXTENSIONS):
                    with open(downloaded_path) as fh:
                        content = fh.read()
                    aim_object = Text
                    kwargs = dict(
                        text=content
                    )
                    content_type = 'text'
                elif file_info.path.endswith(AUDIO_EXTENSIONS):
                    audio_format = os.path.splitext(file_info.path)[1].lstrip('.')
                    aim_object = Audio
                    kwargs = dict(
                        data=downloaded_path,
                        caption=file_info.path,
                        format=audio_format
                    )
                    content_type = 'audio'
                else:
                    click.secho(
                        f'Unresolved or unsupported type for artifact {file_info.path}', fg='yellow'
                    )
                    continue

                try:
                    item = aim_object(**kwargs)
                except Exception as exc:
                    click.echo(
                        f'Could not convert artifact {file_info.path} into aim object - {exc}', err=True
                    )
                    continue
                aim_run.track(item, name=loc or 'root', context={'type': content_type})

            aim_run.meta_run_tree[artifacts_cache_key] = artifacts_cache

def collect_metrics(aim_run, mlflow_run, mlflow_client, timestamp=None):
    for key in mlflow_run.data.metrics.keys():
        metric_history = mlflow_client.get_metric_history(mlflow_run.info.run_id, key)
        if timestamp:
            metric_history = list(filter(lambda m: m.timestamp >= timestamp, metric_history))

        for m in metric_history:
            aim_run.track(m.value, step=m.step, name=m.key)

def convert_existing_logs(repo_inst, tracking_uri, experiment=None, excluded_artifacts=None, no_cache=False):
    client = mlflow.tracking.client.MlflowClient(tracking_uri=tracking_uri)

    experiments = get_mlflow_experiments(client, experiment)
    run_cache = RunHashCache(repo_inst.path, no_cache)
    for ex in tqdm(experiments, desc=f'Parsing mlflow experiments in {tracking_uri}', total=len(experiments)):
        runs = client.search_runs(ex.experiment_id)

        for run in tqdm(runs, desc=f'Parsing mlflow runs for experiment `{ex.name}`', total=len(runs)):
            # get corresponding `aim.Run` object for mlflow run
            aim_run = get_aim_run(repo_inst, run.info.run_id, run.info.run_name, ex.name, run_cache)
            # Collect params and tags
            collect_run_params(aim_run, run)

            # Collect metrics
            collect_metrics(aim_run, run, client)

            # Collect artifacts
            collect_artifacts(aim_run, run, client, excluded_artifacts)

    run_cache.refresh()

def _wait_forever(watcher):
    try:
        while True:
            time.sleep(24 * 60 * 60)  # sleep for a day
    except KeyboardInterrupt:
        watcher.stop()

def _map_nested_dicts(fun, tree):
    if isinstance(tree, collections.abc.Mapping):
        return {k: _map_nested_dicts(fun, subtree) for k, subtree in tree.items()}
    else:
        return fun(tree)

def _try_parse_str(s):
    assert isinstance(s, str), f'Expected a string, got {s} of type {type(s)}'
    try:
        return literal_eval(s.strip())
    except:  # noqa: E722
        return s


import atexit
import os
import csv
import time
import numpy as np
import torch
import pandas as pd
import pyesapi as api
import json
from ax.modelbridge.random import RandomModelBridge
from ax import Experiment
from typing import Dict, cast
from ax.core.data import Data
from ax.core.arm import Arm
from ax.core.types import TTrialEvaluation
from ax.core.generator_run import GeneratorRun
from ax.core.objective import Objective
from ax.core.optimization_config import OptimizationConfig
from ax.modelbridge.registry import Models
from bo_planner.opt_backend import OptSimulator, OptRunner
from bo_planner.metric import PlanQualityMetric
import bo_planner.opt_space as opt_space
from bo_planner.data_storage import DataStorage
import bo_planner.utils as utils

def main(n_batch, patient_id=None,
         course_id="C1", plan_id="sobol",
         model_select='FULLYBAYESIAN',
         goal_fn="./config/PQM/Rectum/PQM.csv",
         obj_fn="./config/prescriptions/Rectum/34D.csv",
         const_fn = "./config/prescriptions/Rectum/rectum_constraint.txt",
         n_init=1,
         batch_size=3,
         opt_dir=None,
         dvh_dir=None,
         **kwargs
         ):
    """Main routine for the automated planning.
    The total number of queried samples are `n_init + n_batch * batch_size`
    Args:
        n_batch: total number of trial batches
        patient_id: patient ID
        course_id: course ID
        plan_id: Plan ID
        model_select: BO model to use
        goal_fn: filename defining the clinical goals for PQM
        obj_fn: filename defining the objective space for TPS
        n_init: initial trial numbers, currently using Sobol sequences
        batch_size: size of each trial batch
    Return:
        None
    """
    config_fn = kwargs.pop("env_fn", "./config/env_config.json")
    with open(config_fn, "r") as buf:
         config = json.load(buf)
    tkwargs = {
        "dtype": torch.double,
        "device": torch.device("cuda" if torch.cuda.is_available() else "cpu")}
    goal_df = pd.read_csv(goal_fn)
    f_df, p_dict, f_dict = opt_space.parse_obj(obj_fn)
    c_str = opt_space.load_constraints(const_fn)
    struct_roi = {i.split("_")[0] for i in goal_df["Structure"]}
    # add BODY for further extractions of total dvh
    struct_roi.add("BODY")
    app = api.CustomScriptExecutable.CreateApplication("BayOpt")
    atexit.register(app.Dispose)
    # initialize simulator
    patient = app.OpenPatientById(patient_id)
    patient.BeginModifications()
    plan = patient.CoursesLot(course_id).PlanSetupsLot(plan_id)
    plan.SetCalculationModel(api.CalculationType.PhotonVolumeDose, config["DCA"])
    plan.SetCalculationModel(api.CalculationType.PhotonIMRTOptimization, config["OA"])
    plan.SetCalculationModel(api.CalculationType.PhotonVMATOptimization, config["OA"])
    plan.SetCalculationModel(api.CalculationType.PhotonLeafMotions, config["LMC"])
    plan.SetCalculationOption(config["DCA"], "UseGPU", "Yes")
    plan.SetCalculationOption(config["OA"], "UseGPU", "Yes")
    opt_simulator = OptSimulator(plan, struct_roi, fixed_objectives=f_dict)
    opt_runner = OptRunner(opt_simulator)
    opt_prefix = "./opt_res/{}".format(patient_id) + opt_dir
    dvh_prefix = "./opt_res/{}".format(patient_id) + dvh_dir
    if not os.path.exists(opt_prefix):
        os.makedirs(opt_prefix)
    if not os.path.exists(dvh_prefix):
        os.makedirs(dvh_prefix)
    save_data = DataStorage(opt_prefix, dvh_prefix, p_dict)  # data storage
    pars_random = []

    # initialize search space
    search_space = opt_space.form_space(p_dict, c_strs=c_str)
    plan_quality = PlanQualityMetric("PQM", goal_df, noise_sd=0)
    optimization_config = OptimizationConfig(objective=Objective(metric=plan_quality))
    print(f"doing {n_init + n_batch * batch_size} evaluations")
    experiment = Experiment(name="saasbo_planning",
                            search_space=search_space,
                            optimization_config=optimization_config,
                            runner=opt_runner)
    sobol = Models.SOBOL(search_space=experiment.search_space)
    experiment = opt_space.init_data(patient_id, experiment, n_init, mode="sobol", file='', generator=sobol)
    for trial_name, trial in experiment.trials.items():  # extract data from initial experiment
        pars_random.append(list(trial.arms[0].parameters.values()))
        save_data.save_dvh(trial.arms)   # Store the DVHs generated by SOBOL during initialization
    data = experiment.fetch_data()
    save_data.save_init_data(data, pars_random)   # save init data

    for i in range(n_batch):
        if model_select == 'FULLYBAYESIAN':
            model = Models.FULLYBAYESIAN(
               experiment=experiment,
               data=data,
               num_samples=256,
               warmup_steps=512,
               gp_kernel="matern",
               torch_device=tkwargs["device"],
               torch_dtype=tkwargs["dtype"],
               verbose=False,
               disable_progbar=True)
        elif model_select == 'GPEI':
            model = Models.GPEI(
                experiment=experiment,
                data=data,
            )
        elif model_select == 'SOBOL':
            model = Models.SOBOL(
                experiment=experiment,
                data=data,
            )
        generator_run = model.gen(batch_size)
        trial = experiment.new_batch_trial(generator_run=generator_run)
        trial.run()
        trial.complete()
        data = Data.from_multiple_data([data, trial.fetch_data()])
        new_value = trial.fetch_data().df["mean"].max()
        if model_select == 'FULLYBAYESIAN':
            save_data.save_lenscal_saas(model)
        elif model_select == 'GPEI':
            save_data.save_lenscale_gpei(model)
        save_data.save_opt_data(data, trial, batch_size, n_init, i)
        save_data.save_dvh(trial.arms)
        print(f"Iteration: {i}, Best in iteration {new_value:.3f}, Best so far: {data.df['mean'].max():.3f}")
    save_data.close_lenscale_file()

    best_params, arm_name = utils.extract_best_params(data, experiment)
    # last step: dose calculation and re-optimization with the best params
    data, trial = utils.calculate_plan(experiment, arm_name, best_params, data)
    save_data.save_cal_data(data, best_params)
    save_data.save_dvh(trial.arms, 'reopt-cal1')

    # reopt with calculated dose
    data, trial = utils.reopt_calculated_plan(experiment, best_params, data)
    save_data.save_cal_data(data, best_params)
    save_data.close_pars_file()
    save_data.save_dvh(trial.arms, 'reopt-cal2')
    app.SaveModifications()
    app.ClosePatient()
    app.Dispose()
    print("optimization completed")

if __name__ == "__main__":
    with open("./config/pat_names.txt", "r") as buf:
         pat_list = list(buf.readline().strip().split(" "))
    for pa in pat_list:
        main(n_batch=2, patient_id=pa, plan_id="test", model_select='SOBOL', opt_dir="/util_random/", dvh_dir="/dvh_random/")
        print(pa + ' sobol is ok !')
        main(n_batch=2, patient_id=pa, plan_id="test", model_select='GPEI', opt_dir="/util_gpei/", dvh_dir="/dvh_gpei/")
        print(pa + ' gpei is ok !')
        main(n_batch=2, patient_id=pa, plan_id="test", model_select='FULLYBAYESIAN', opt_dir="/util_saas/", dvh_dir="/dvh_saas/")
        print(pa + " saasbo is ok !")


import sys
import pathlib
sys.path.append(pathlib.Path().resolve().__str__())
from util import parseAOC, parseAOC_test
from collections import deque,defaultdict

data = parseAOC("./day18.txt")

PT =  set()
sides = 0

for line in data:
    x,y,z = line.split(",")
    x,y,z = int(x),int(y),int(z)
    PT.add((x,y,z))

    # add 6 sides per point
    sides += 6

for x,y,z in PT:
    for dx,dy,dz in [(1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1)]:
        if (x+dx,y+dy,z+dz) in PT:
            sides -= 1

print(sides)

maxx = max([x for x,y,z in PT])
maxy = max([y for x,y,z in PT])
maxz = max([z for x,y,z in PT])
MAX = max(maxx,maxy,maxz)+1

OUT = set()
def isOnEdge(x,y,z):
    if x < 0 or y < 0 or z < 0:
        return True

    if x >= MAX or y >= MAX or z >= MAX:
        return True

    if (x,y,z) in PT:
        return False

    if (x,y,z) in OUT:
        return True
    VISITED = set()
    Q = deque([(x,y,z)])
    while Q:
        x,y,z = Q.popleft()
        if (x,y,z) in PT:
            continue
        if (x,y,z) in VISITED:
            continue
        VISITED.add((x,y,z))
        if len(VISITED) > 6000:
            for pt in VISITED:
                OUT.add(pt)
            return True

        for dx,dy,dz in [(1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1)]:
            Q.append((x+dx,y+dy,z+dz))
    return False

sides = 0
for (x,y,z) in PT:
    for dx,dy,dz in [(1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1)]:
        if isOnEdge(x+dx,y+dy,z+dz):
            sides += 1

print(sides)


from pyexpat import features
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.parameter import Parameter

import math
import numpy as np

from timm import create_model

def init_weights(model):
    classname = model.__class__.__name__
    if classname.find("Conv2d") != -1:
        nn.init.xavier_uniform_(model.weight, gain=np.sqrt(2))
        model.bias.data.fill_(0)
    elif classname.find("BatchNorm") != -1:
        model.weight.data.normal_(1.0, 0.02)
        model.bias.data.fill_(0)
    elif classname.find("GRU") != -1:
        for weight in model.parameters():
            if len(weight.size()) > 1:
                nn.init.orghogonal_(weight.data)
    elif classname.find("Linear") != -1:
        model.weight.data.normal_(0, 0.01)
        model.bias.data.zero_()

def split(x,num_splits = 6):
    b,c,h,w = x.size()
    cutoff = w // num_splits * num_splits

    x = x[:,:,:,:cutoff]
    #print(x.shape)
    b,c,h,w = x.size()

    ksize = stride = (h,w // num_splits)

    patches = x.unfold(2, ksize[0], stride[0]).unfold(3, ksize[1], stride[1]).squeeze(2).permute(0,2,1,3,4)

    patches = patches.contiguous().view(b * num_splits,*patches.shape[2:])

    return patches

def merge(patches,num_splits = 6):
    b,c,h,w = patches.size()

    stitched = patches.contiguous().view(b // num_splits, c, -1, h*w).permute(0, 1, 3, 2)
    stitched = stitched.contiguous().view(b // num_splits, c*h*w, -1)
    stitched = F.fold(stitched, output_size=(h, w*num_splits), kernel_size=(h,w), stride=(h,w))

    return stitched

class ArgMax(nn.Module):

    def __init__(self, dim=None):
        super().__init__()
        self.dim = dim

    def forward(self, x):
        return torch.argmax(x, dim=self.dim)

class Clamped_Sigmoid(nn.Module):
    def __init__(self,min=1e-2,max=1.0-1e-2):
        super().__init__()
        self._min = min
        self._max = max
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(x)
        x = torch.clamp(x,min=self._min,max=self._max)
        return x

class Activation(nn.Module):

    def __init__(self, name, **params):
        super().__init__()
        if name is None or name == 'identity':
            self.activation = nn.Identity(**params)
        elif name == 'sigmoid':
            self.activation = nn.Sigmoid()
        elif name == 'clamped_sigmoid':
            self.activation = Clamped_Sigmoid(**params)
        elif name == 'softmax2d':
            self.activation = nn.Softmax(dim=1, **params)
        elif name == 'softmax':
            self.activation = nn.Softmax(**params)
        elif name == 'logsoftmax':
            self.activation = nn.LogSoftmax(**params)
        elif name == 'argmax':
            self.activation = ArgMax(**params)
        elif name == 'argmax2d':
            self.activation = ArgMax(dim=1, **params)
        elif callable(name):
            self.activation = name(**params)
        else:
            raise ValueError('Activation should be callable/sigmoid/softmax/logsoftmax/None; got {}'.format(name))

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

def gem(x, p=3, eps=1e-6):
    return F.avg_pool2d(x.clamp(min=eps).pow(p), (x.size(-2), x.size(-1))).pow(1.0 / p)

class GeM(nn.Module):
    def __init__(self, p=3, eps=1e-6):
        super(GeM, self).__init__()
        self.p = Parameter(torch.ones(1) * p)
        self.eps = eps

    def forward(self, x):
        ret = gem(x, p=self.p, eps=self.eps)
        return ret

    def __repr__(self):
        return (
            self.__class__.__name__
            + "("
            + "p="
            + "{:.4f}".format(self.p.data.tolist()[0])
            + ", "
            + "eps="
            + str(self.eps)
            + ")"
        )

class Backbone(nn.Module):
    def __init__(self,name = 'resnet18',in_channels=1,pretrained=True,depth=5):
        super().__init__()
        kwargs = dict(
            in_chans=in_channels,
            features_only=True,
            pretrained=pretrained,
            out_indices=tuple(range(depth)),
        )
        self.backbone = create_model(name, **kwargs)
        self.in_channels = in_channels
        self.features_channels = self.backbone.feature_info.channels()
        self.depth = depth

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

class Conv3x3(nn.Sequential):
    def __init__(self,in_channels,out_channels,kernel):
        conv = nn.Conv2d(in_channels=in_channels,out_channels=out_channels,kernel_size=kernel,padding='same',padding_mode='zeros')
        bn = nn.BatchNorm2d(out_channels)
        relu = nn.ReLU()
        super().__init__(conv,bn,relu)

class Classification_Head(nn.Sequential):
    def __init__(self, in_channels, classes, dropout=0.2, activation=None):

        dropout = nn.Dropout(p=dropout, inplace=False) if dropout else nn.Identity()
        linear = nn.Linear(in_channels, classes, bias=True)
        activation = Activation(activation)
        super().__init__(dropout, linear, activation)

class Classification_HeadV4(nn.Sequential):
    def __init__(self, in_channels,classes, dropout=0.2, activation=None,groups=8,groups_out=1):
        out_channels = in_channels // groups * groups_out
        if out_channels % groups != 0:
            out_channels = int(math.ceil(out_channels / groups) * groups)

        print(f'Classification Head: in_channels : {in_channels}, out_channels : {out_channels}, groups : {groups}')

        conv0 = nn.Conv1d(in_channels,out_channels,kernel_size=2,stride=1,padding=0,bias=False,groups=groups)
        bn0 = nn.BatchNorm1d(out_channels)
        relu = nn.ReLU()
        dropout = nn.Dropout(p=dropout, inplace=False)
        conv1 = nn.Conv1d(out_channels,classes,kernel_size=1,stride=1,padding=0,bias=True)
        activation = Activation(activation)
        super().__init__(conv0,bn0,relu,dropout,conv1,activation)

class Attention_FT(nn.Module):

    def __init__(self,in_channels):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size=1,bias=False)
        self.softmax = nn.Softmax(dim=-1)
        self.relu = nn.ReLU()

    def forward(self,x):
        b,c,h,w = x.shape
        x = self.conv1(x)

        f_avg = x.mean(dim=-1).unsqueeze(-1)
        t_avg = x.mean(dim=-2).unsqueeze(-2)

        att_map = torch.matmul(f_avg,t_avg)
        att_map = self.softmax(att_map.view(b,c,-1)).view(b,c,h,w)
        x_att = x * att_map

        x = x + x_att
        x = self.relu(x)
        return x

class CoW(nn.Module):
    def __init__(self,in_channels,coeffs_channels):
        super().__init__()
        mods = []
        ins_chs = [in_channels,*coeffs_channels]
        for i,coeff_channels in enumerate(coeffs_channels):
            mods.append(
                nn.Sequential(
                    nn.Conv1d(in_channels=ins_chs[i],out_channels=coeff_channels,kernel_size=1,bias=False,padding=0),
                    nn.BatchNorm1d(coeff_channels),
                    nn.PReLU(),
                )
            )

        mods.append(
            nn.Sequential(
                    nn.Conv1d(in_channels=coeffs_channels[-1],out_channels=1,kernel_size=1,bias=False,padding=0),
                    nn.Softmax(dim=-1)
                )

        )

        self.mods = nn.ModuleList(mods)

    def forward(self,x):
        for mod in self.mods:
            x = mod(x)
        x = x.permute(0,2,1)
        #x = torch.clamp(x,min=0.1)
        #s = x.sum(dim=1).unsqueeze(1)
        #x = x / s
        return x

class SED_V5(nn.Module):

    def __init__(
        self,
        backbone = 'resnet18',
        in_channels=1,
        pretrained_backbone =True,
        backbone_depth = 5,
        num_classes=152,
        dropout=0.2,
        activation=None,
        k=8,
        k2=1,
        use_attention = True
        ):
        super().__init__()

        self.k = k
        self.use_attention = use_attention

        self.backbone = Backbone(name=backbone,in_channels=in_channels,pretrained=pretrained_backbone,depth=backbone_depth)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
        self.flatten = nn.Flatten()

        feature_channels = self.backbone.features_channels[-1]
        print(f'Backbone {backbone} with {feature_channels} feature channels...')

        if feature_channels > 512:
            self.bot = Conv3x3(feature_channels,512,1)
            feature_channels = 512
            print(f'Adjusted N# Features to 512....')
        else:
            self.bot = None

        self.fc = Classification_HeadV4(feature_channels * k,num_classes,dropout=dropout,activation=activation,groups=k,groups_out=k2)

        if use_attention:
            self.att = Attention_FT(feature_channels)

    def forward(self,x,num_splits=None):

        b,c,h,w = x.size()
        if num_splits is not None:
            x = split(x,num_splits)

        features = self.backbone(x)[-1]
        if self.bot is not None:
            features = self.bot(features)

        if self.use_attention:
            features = self.att(features)

        oc = features.shape[1]
        features = features.reshape(b,num_splits,oc,-1)
        features = features.permute(0,2,1,3).reshape(b,oc,-1)
        features,indices = torch.topk(features,k=self.k,dim=-1)

        indices = torch.div(indices % (h*w), w, rounding_mode='trunc').float()  / h
        features = features.reshape(b,-1,1)
        indices = indices.reshape(b,-1,1)

        samples = torch.cat([features,indices],dim=-1)

        y_out = self.fc(samples)
        y_out = y_out[:,:,0]
        return y_out

class SED_V7(nn.Module):

    def __init__(
        self,
        backbone = 'resnet34',
        in_channels=1,
        pretrained_backbone =True,
        backbone_depth = 5,
        num_classes=152,
        dropout=0.2,
        activation=None,
        coeff_channels = [128,64],
        num_splits=6
        ):
        super().__init__()

        self.num_splits = num_splits
        self.backbone = Backbone(name=backbone,in_channels=in_channels,pretrained=pretrained_backbone,depth=backbone_depth)
        self.pool = GeM()

        feature_channels = self.backbone.features_channels[-1]
        print(f'Backbone {backbone} with {feature_channels} feature channels...')

        self.cow = CoW(feature_channels,coeff_channels)
        self.fc = Classification_Head(feature_channels,num_classes,dropout,activation)

    def forward(self,x):

        b,c,h,w = x.size()

        x = split(x,self.num_splits)

        features = self.backbone(x)[-1]
        features = self.pool(features)
        features = features[:,:,0,0]

        _,ch = features.size()
        features = features.view(-1,self.num_splits,ch)

        weights = self.cow(features.permute(0,2,1))
        w_features = (features * weights).sum(dim=1)
        y_out = self.fc(w_features)

        return y_out,weights.squeeze(-1)

    def forward_5s(self,x):

        b,c,h,w = x.size()

        #x = split(x,self.num_splits)

        features = self.backbone(x)[-1]
        features = self.pool(features)
        features = features[:,:,0,0]

        y_out = self.fc(features)
        return y_out

    def forward_debug(self,x):

        b,c,h,w = x.size()

        x = split(x,self.num_splits)

        features = self.backbone(x)[-1]
        features = self.pool(features)
        features = features[:,:,0,0]

        _,ch = features.size()
        features = features.view(-1,self.num_splits,ch)

        weights = self.cow(features.permute(0,2,1))
        print(weights)
        w_features = (features * weights).sum(dim=1)
        y_out = self.fc(w_features)
        return y_out

def create_sed_model(name='sed_v1',**kwargs):

    if name == 'sed_v5':
        return SED_V5(**kwargs)
    elif name == 'sed_v7':
        return SED_V7(**kwargs)

    else:
        raise NotImplementedError(f'SED model {name} is not implemented')

if __name__ == '__main__':

    """
    x = torch.rand([6, 1, 224, 1350])
    kwargs = dict(
        backbone = 'regnety_008',
        in_channels=1,
        pretrained_backbone =False,
        backbone_depth = 5,
        num_classes=152,
        dropout=0.2,
        activation=None,
        coeff_channels = [128,64],
        num_splits=6
    )
    net = create_sed_model(name='sed_v7',**kwargs)

    with torch.no_grad():
        y,cow_weights = net(x)
    print(y.shape)
    print(cow_weights.shape)
    """


from aiogram import types

from data.db_models import Chat
from filters import GroupFilter
from loader import Game, dp, db

@dp.message_handler(GroupFilter(),
                    content_types=[types.ContentType.NEW_CHAT_MEMBERS])
async def new_member(message: types.Message):
    members_list = message.new_chat_members
    for user in members_list:
        if user.id == (await dp.bot.get_me()).id:
            await message.answer('Привет🤘! Я бот-ведущий игры мафия🤵🏻 с элементами Brawl Stars!\n'
                                 '⚠ Для адекватной работы мне остро необходимы права администратора!\n'
                                 'Дополнительную информацию можно найти по команде /help в личных сообщениях со мной!')
        else:
            chat_data: Chat = await db.get_chat(message.chat.id)
            if not chat_data.is_show_hello_msg:
                return
            chat_obj = Game.get_chat(message.chat.id)
            if chat_obj:
                if chat_obj.phase in ['day', 'night']:
                    await message.answer(f"💬 {user.get_mention()}, добро пожаловать!"
                                         f"\nВ данный момент идет игра, вам нужно подождать 🕗, "
                                         f"пока она закончится! "
                                         f"А пока вы можете ознакомиться с ℹ правилами игры: /help")
                elif chat_obj.phase == 'starting':
                    await message.answer(f"💬 {user.get_mention()}, добро пожаловать!\n"
                                         f"В данный момент идет подбор игроков, вы можете 🎭 присоединиться!")
            else:
                await message.answer(f"💬 {user.get_mention()}, добро пожаловать!\n"
                                     f"В данный момент не идет игры, "
                                     f"вы можете ознакомиться с ℹ правилами игры: /help.")

@dp.message_handler(content_types=[types.ContentType.GROUP_CHAT_CREATED])
async def group_created(message: types.Message):
    await message.answer('Привет🤘! Я бот-ведущий игры мафия🤵🏻 с элементами Brawl Stars!\n'
                         '⚠ Для адекватной работы мне остро необходимы права администратора!\n'
                         'Дополнительную информацию можно найти по команде /help в личных сообщениях со мной!')


import time
import grovepi
import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-p", "--pin", required=True,
                                help="GrovePi Pin")
args = vars(ap.parse_args())

pin = int(args['pin'])

while True:
    try:
        value = grovepi.analogRead(pin)
        print("value = {}".format(value))
        time.sleep(.5)

    except IOError:
        print ("Error")


from src.data_preparation.pipeline.pipeline import Pipeline
from functools import wraps
from src.data_preparation.pipeline.stock_data.summary import SummaryStockData

class PipelineStockData(Pipeline):

    def __init__(self):
        self.summary = SummaryStockData()
        self._scalers = None
        self._data = None

    @classmethod
    def process(cls, function):

        @wraps(function)
        def process_data(self, *args, show_summary=True, dict_summary=True, **kwargs):

            data, additional_summary_information = function(self, *args, **kwargs)

            if len(data) == 3:
                self._scalers, self._data, initial_index = data
                final_index = initial_index
            else:
                self._scalers, self._data, initial_index, final_index = data

            if not additional_summary_information:
                additional_summary_information = {}

            return self._summary_management(show_summary, dict_summary)\
                (show_summary, dict_summary,
                 priority = self.priority,
                 initial_index=initial_index,
                 final_index=final_index,
                 scaler=self._scalers,
                 transform_functions=function.__doc__,
                 **additional_summary_information)

        return process_data

    @property
    def data(self):
        return self._data

    @property
    def scalers(self):
        return self._scalers

    def _write_summary(self, **kwargs):
        self.summary.enter_params(**kwargs)
        self.summary.build()

    def _summary_management(self, show_summary, dict_summary):

        if show_summary or dict_summary:
            return self._summary_actions
        return lambda *args, **kwargs: None

    def _summary_actions(self, show_summary, dict_summary, **kwargs):

        self._write_summary(**kwargs)
        if show_summary:
            print(self.summary.str_summary)
        if dict_summary:
            return self.summary.registry
        return None


from dataclasses import dataclass
from enum import Enum
from pathlib import Path

class TargetTypes(Enum):
    DIRECTORY = 1
    FILE = 2

@dataclass
class BaseTarget:
    path: Path
    type: TargetTypes

    def __init__(self, path: Path):
        if not hasattr(self, "type"):
            raise NotImplementedError(
                "You need to set the type for BaseTarget subclass"
            )

        self.path = path


from ursina import *
from ursina.shaders import lit_with_shadows_shader
from ursina.lights import DirectionalLight

from simulators.ursina.ursina_mesh import create_sphere

shader = lit_with_shadows_shader
shader.default_input = {
    'texture_scale': Vec2(1, 1),
    'texture_offset': Vec2(0, 0),
    'shadow_color': Vec4(0.1, 0.1, 0.1, .5),
}

Entity.default_shader = shader

app = Ursina()

moon = Entity(model=create_sphere(0.5, 32), texture="../textures/moon.png", y=1, color=color.light_gray)
earth = Entity(model=create_sphere(0.5, 32), texture='../textures/earth.png', y=1, x=1, z=3)
e_pos = earth.position

sun = DirectionalLight(shadow_map_resolution=(1024, 1024), position=[e_pos[0], e_pos[1] + 1, e_pos[2] + 1])
sun.look_at(moon)
sun._light.show_frustum()

# light = PointLight(parent=earth, intensity=10, range=10, color=color.white)

def update():
    moon.x += (held_keys['d'] - held_keys['a']) * time.dt
    moon.y += (held_keys['e'] - held_keys['q']) * time.dt
    moon.z += (held_keys['w'] - held_keys['s']) * time.dt
    sun.update_bounds()

# scene.fog_density = (100, 500)
# scene.fog_color = color.orange
# scene.fog_density = (10, 50)
Sky(color=color.light_gray, texture="../textures/cosmic1.png")
EditorCamera()

app.run()


from django.db import models

# Create your models here.

class Subscription(models.Model):
    customer = models.ForeignKey('customer.Customer')
    package = models.ForeignKey('package.Package')
    created_at = models.DateTimeField(auto_now_add=True, null=False)
    updated_at = models.DateTimeField(auto_now=True, null=False)
    startdate = models.DateField(max_length=255, null=False)
    enddate = models.DateField(max_length=255, null=False)
    sessionsleft = models.IntegerField()
    flexiflag = models.BooleanField()
    expiryflag = models.BooleanField()


import datetime

from commercetools.importapi import models

def test_serialization_optional_values():
    item = models.LineItemImportDraft(
        name={"nl-NL": "foobar"},
        variant=models.LineItemProductVariantImportDraft(sku="foobar"),
        price=models.LineItemPrice(
            value=models.Money(cent_amount=1000, currency_code="EUR"),
        ),
        quantity=3,
    )

    data = item.serialize()
    item_cycle = models.LineItemImportDraft.deserialize(data)
    data_cycle = item_cycle.serialize()

    expected = {
        "name": {"nl-NL": "foobar"},
        "price": {
            "value": {
                "centAmount": 1000,
                "currencyCode": "EUR",
                "type": "centPrecision",
            }
        },
        "quantity": 3.0,
        "variant": {"sku": "foobar"},
    }
    assert expected == data
    assert expected == data_cycle

def test_serialization_optional_values():
    now = datetime.datetime(2021, 1, 30, 11, 21, 8)
    custom = models.Custom(
        type=models.TypeKeyReference(key="my-custom-type"),
        fields=models.FieldContainer(
            {
                "foo": models.NumberField(value=1234),
                "itemDate": models.DateTimeField(value=now),
            }
        ),
    )
    data = custom.serialize()
    expected = {
        "fields": {
            "foo": {
                "type": "Number",
                "value": 1234,
            },
            "itemDate": {
                "type": "DateTime",
                "value": "2021-01-30T11:21:08",
            },
        },
        "type": {"typeId": "type", "key": "my-custom-type"},
    }
    assert data == expected


from ase import units
from ase.md.langevin import Langevin
from pyiron_base import GenericParameters
from pyiron.gpaw.pyiron_ase import AseAdapter
from pyiron.atomistics.job.interactivewrapper import InteractiveWrapper

__author__ = "Jan Janssen"
__copyright__ = (
    "Copyright 2020, Max-Planck-Institut für Eisenforschung GmbH - "
    "Computational Materials Design (CM) Department"
)
__version__ = "1.0"
__maintainer__ = "Jan Janssen"
__email__ = "janssen@mpie.de"
__status__ = "development"
__date__ = "Sep 1, 2018"

class LangevinAse(InteractiveWrapper):
    """
    Reference implementation of a thermostat implemented in ASE. While we have multiple implementations of the
    Langevin thermostat already, this one is using the ASE interface and the Langevin thermostat implemented in ASE.
    It is therefore a perfect example how other thermostats implemented in ASE can be used inside pyiron.

    Args:
        project (ProjectHDFio): points to the HDF5 file the job is stored in
        job_name (str): name of the job, which has to be unique within the project

    Attributes:
        input (pyiron.objects.hamilton.md.lammps.Input): handle the input
    """

    def __init__(self, project, job_name):
        super(LangevinAse, self).__init__(project, job_name)
        self.__name__ = "LangevinAse"
        self.input = Input()
        self._fast_mode = False

    def set_input_to_read_only(self):
        """
        This function enforces read-only mode for the input classes, but it has to be implement in the individual
        classes.
        """
        super(LangevinAse, self).set_input_to_read_only()
        self.input.read_only = True

    def write_input(self):
        """
        No input is written when using the ASE interface
        """
        pass

    def _write_run_wrapper(self, debug=False):
        """
        No wrapper is written for the ASE interface

        Args:
            debug (bool): the debug flag is ignored
        """
        pass

    def run_static(self):
        """
        Static run function, which uses the ASEAdapter to connect the pyiron interactive reference job with the
        Langevin thermostat implemented in ASE, by setting the ASEAdapter as a replacement of the ASE atoms object.
        """
        self.status.running = True
        self.ref_job_initialize()
        aseadapter = AseAdapter(self.ref_job, self._fast_mode)
        langevin = Langevin(
            atoms=aseadapter,
            timestep=self.input["time_step"] * units.fs,
            temperature=self.input["temperature"] * units.kB,
            friction=self.input["friction"],
            fixcm=True,
        )
        langevin.run(self.input["ionic_steps"])
        self.status.collect = True
        aseadapter.interactive_close()
        self._finish_job()

class Input(GenericParameters):
    """
    class to control the generic input for a Sphinx calculation.

    Args:
        input_file_name (str): name of the input file
        table_name (str): name of the GenericParameters table
    """

    def __init__(self, input_file_name=None, table_name="input"):
        super(Input, self).__init__(
            input_file_name=input_file_name,
            table_name=table_name,
            comment_char="#",
            separator_char="=",
            end_value_char=";",
        )

    def load_default(self):
        """
        Loads the default file content
        """
        file_content = (
            "ionic_steps = 100\n"
            "temperature = 1500\n"
            "time_step = 1\n"
            "friction = 0.002\n"
            "fix_center_of_mass = True\n"
        )
        self.load_string(file_content)


"""
Polarion:
    casecomponent: WebConsole
    linkedWorkItems: MTA_Web_Console
"""
import pytest

from mta.base.application.implementations.web_ui import navigate_to
from mta.entities.analysis_results import AnalysisResults
from mta.entities.analysis_results import AnalysisResultsView
from mta.entities.global_config.rules_configuration import CustomRulesConfiguration
from mta.entities.global_config.rules_configuration import CustomRulesView
from mta.entities.global_config.rules_configuration import SystemRulesConfiguration
from mta.entities.report import AllApplicationsView
from mta.entities.report import Issues

@pytest.fixture(scope="function")
def add_global_custom_rule(mta_app):
    """This fixture with upload global custom rule file"""
    file_name = "custom.Test1rules.rhamt.xml"
    rules_configurations = CustomRulesConfiguration(mta_app, file_name)
    rules_configurations.upload_custom_rule_file()
    view = rules_configurations.create_view(CustomRulesView)
    view.wait_displayed("20s")
    yield file_name, view, rules_configurations
    rules_configurations.delete_custom_rule()
    view.logout()

def test_crud_global_custom_rule(mta_app, add_global_custom_rule):
    """Test to upload global custom rules file

    Polarion:
        assignee: ghubale
        initialEstimate: 1/12h
        caseimportance: medium
        testSteps:
            1. Login to MTA web console
            2. Navigate to Global > Rules configuration > Custom rules
            3. Click on Add rule button and browse rules file
            4. Click on Close button
        expectedResults:
            1. Custom rules file should be listed in table
    """
    file_name, view, rules_configurations = add_global_custom_rule
    assert file_name in [rules["Short path"] for rules in view.table.read()]

def test_search_global_custom_rule(mta_app, add_global_custom_rule):
    """Test to search global custom rules file from table

    Polarion:
        assignee: ghubale
        initialEstimate: 1/12h
        caseimportance: medium
        testSteps:
            1. Login to MTA web console
            2. Navigate to Global > Rules configuration > Custom rules
            3. Click on Add rule button and browse rules files
            4. Click on Close button
            5. Add value in 'Filter by short path' input box and hit enter
        expectedResults:
            1. Custom rules file should searched by substring
    """
    file_name, view, rules_configurations = add_global_custom_rule
    view.wait_displayed("20s")

    view.search.fill("rhamt")
    view.wait_displayed("20s")
    view.search.fill("rhamt-invalid")
    try:
        assert file_name not in [rules["Short path"] for rules in view.table.read()]
        view.search.fill("")
    except IndexError:
        view.search.fill("")
        pass

def test_analysis_global_custom_rule(
    mta_app, add_global_custom_rule, create_minimal_project, request
):
    """Test to upload global custom rules file

    Polarion:
        assignee: ghubale
        initialEstimate: 1/12h
        caseimportance: medium
        testSteps:
            1. Upload global custom rule file
            2. Create project and run analysis
            3. Go to analysis details page and check if custom rules contains global scope custom
               rule file
        expectedResults:
            1. Analysis should be completed successfully
            2. Global custom rule should be applied/fired in the analysis report
    """
    file_name, view, rules_configurations = add_global_custom_rule
    project, project_collection = create_minimal_project
    analysis_results = AnalysisResults(mta_app, project.name)
    view = navigate_to(analysis_results, "AnalysisDetailsPage")
    view.custom_rules.wait_displayed("20s")
    card_info = view.custom_rules.read()
    assert file_name in card_info["body"].split("Global")[1]
    view.execution_link.click()
    view = analysis_results.create_view(AnalysisResultsView)
    view.wait_displayed("30s")
    view.analysis_results.show_report(request)
    view = analysis_results.create_view(AllApplicationsView)
    view.application_table.application_details("acmeair-webapp-1.0-SNAPSHOT.war")
    view.tabs.issues.click()
    view = analysis_results.create_view(Issues)
    # TODO(ghubale): Update test case with reading Migration potential table
    assert view.wait_displayed("20s")

def test_invalid_rule_file_type(mta_app, request):
    """Test to upload global custom rules file

    Polarion:
        assignee: ghubale
        initialEstimate: 1/12h
        caseimportance: medium
        testSteps:
            1. Upload invalid global custom rule file
            2. Check number of rules in it
        expectedResults:
            1. Invalid global custom rule file should have 0 rules
    """
    file_names = ["customWebLogic.windup.label.xml", "empty_rule_file.xml"]

    @request.addfinalizer
    def _finalize():
        for file in file_names:
            rules = CustomRulesConfiguration(mta_app, file)
            rules.delete_custom_rule()
        view.logout()

    for file_name in file_names:
        rules_configurations = CustomRulesConfiguration(mta_app, file_name)
        rules_configurations.upload_custom_rule_file()
        view = rules_configurations.create_view(CustomRulesView)
        view.wait_displayed("5s")

        all_rules = view.table.read()
        for rule in all_rules:
            if rule["Short path"] == file_name:
                assert int(rule["Number of rules"]) == 0

def test_total_global_system_rule(mta_app, request):
    """Test to upload global custom rules file

    Polarion:
        assignee: ghubale
        initialEstimate: 1/12h
        caseimportance: medium
        testSteps:
            1. Navigate to Global > Rules configuration > System rules
            2. Check show all rules
        expectedResults:
            1. Total system rules count should be 331
    """

    @request.addfinalizer
    def _finalize():
        # Reset view else the URL does not change
        view.logout()

    global_configurations = SystemRulesConfiguration(mta_app)
    view = navigate_to(global_configurations, "SystemRule")
    view.show_all_rules.wait_displayed("30s")
    no_of_rules_before = view.paginator.total_items
    view.show_all_rules.click()
    assert view.paginator.total_items >= no_of_rules_before

def test_filter_global_system_rule(mta_app, request):
    """Test to upload global custom rules file

    Polarion:
        assignee: ghubale
        initialEstimate: 1/12h
        caseimportance: medium
        testSteps:
            1. Navigate to Global > Rules configuration > System rules
            2. Check show all rules
        expectedResults:
            1. Total system rules count should be 331
    """
    filters = {
        "Source": ["agroal", "amazon", "avro"],
        # "Target": ["camel", "cloud-readiness", "quarkus"],
        # TODO(ghubale): Uncomment it once fixed drop down selection for option - Target
    }

    @request.addfinalizer
    def _finalize():
        # Reset view else the URL does not change
        view.logout()

    global_configurations = SystemRulesConfiguration(mta_app)
    view = navigate_to(global_configurations, "SystemRule")
    view.show_all_rules.wait_displayed("30s")
    view.show_all_rules.click()
    for filter_type in filters:
        for filter_value in filters[filter_type]:
            global_configurations.search_system_rules(
                search_value=filter_value, filter_type=filter_type, clear_filters=True
            )
            filtered_rules = view.table.read()
            for rule in filtered_rules:
                assert filter_value in rule[filter_type]


from rest_framework.permissions import BasePermission

from .models import Ticket

class TicketOwnerOrAssignee(BasePermission):
    def has_permission(self, request, view):
        user_id = request.user.id
        ticket_id = view.kwargs.get("pk")
        ticket = Ticket.objects.get(id=ticket_id)
        return ticket.member.user.id == user_id or ticket.assignee.user.id == user_id


from heapq import heappop, heappush
from utils import get_file_content, parse_as_csv_content
from string import ascii_lowercase

WAITING_ON_STATION = 5
TRAIN_SOURCE = "_"
EVENT_ARRIVE = 1
EVENT_LEAVE = 2
EVENT_STATION_STATE_CHANGE = 3

def transform_time_to_minutes(time_value: str):
    hour, minutes = map(int, time_value.split(":"))
    return hour * 60 + minutes

def transposition(source):
    result = None
    for row in source:
        if result == None:
            result = [[] for _ in row if _ != "a"]

        tmp = enumerate(row)
        next(tmp)
        for index, column in tmp:
            result[index - 1].append(column)

    yield from result

def transform_to_trains_table(content: str):
    for row in transposition(parse_as_csv_content(content)):
        x = [None if t == "" else transform_time_to_minutes(t) for t in row]

        result = {}
        previous_station = TRAIN_SOURCE
        previous_time = 0
        for index, station_time in enumerate(x):
            if station_time == None:
                continue

            station = ascii_lowercase[index]
            result[previous_station] = (station, station_time - previous_time)
            previous_station = station
            previous_time = station_time

        yield result

def solution(content: str) -> int:
    stations_names = set()
    trains = []

    for s in transform_to_trains_table(content):
        trains.append(s)
        stations_names.update(s.keys())
        stations_names.update(x[0] for x in s.values())

    stations_names.remove(TRAIN_SOURCE)
    events = []
    starts_times = {}
    ends_times = {}

    stations_queues = {s: [] for s in stations_names}
    stations = {s: None for s in stations_names}

    for train_index, train in enumerate(trains):
        starts_times[train_index] = train[TRAIN_SOURCE][1]
        heappush(
            events,
            (
                train[TRAIN_SOURCE][1],
                EVENT_ARRIVE,
                train_index,
                train[TRAIN_SOURCE][0],
                TRAIN_SOURCE,
            ),
        )

    while events:
        time, event_type, train_index, current_station, from_station = heappop(events)

        if event_type == EVENT_ARRIVE:
            stations_queues[current_station].append((from_station, time, train_index))
            heappush(
                events,
                (
                    time,
                    EVENT_STATION_STATE_CHANGE,
                    None,
                    current_station,
                    None,
                ),
            )

        elif event_type == EVENT_LEAVE:
            stations[current_station] = None
            heappush(
                events,
                (
                    time,
                    EVENT_STATION_STATE_CHANGE,
                    None,
                    current_station,
                    None,
                ),
            )

            if current_station not in trains[train_index]:
                ends_times[train_index] = time
            else:
                to_state, time_difference = trains[train_index][current_station]
                heappush(
                    events,
                    (
                        time + time_difference,
                        EVENT_ARRIVE,
                        train_index,
                        to_state,
                        current_station,
                    ),
                )

        elif event_type == EVENT_STATION_STATE_CHANGE:
            if stations[current_station] == None and stations_queues[current_station]:
                stations_queues[current_station].sort(reverse=True)
                train_id = stations_queues[current_station].pop()[2]
                stations[current_station] = train_id
                heappush(
                    events,
                    (
                        time + WAITING_ON_STATION,
                        EVENT_LEAVE,
                        train_id,
                        current_station,
                        current_station,
                    ),
                )

    return max(
        ends_times[train_index] - _from for train_index, _from in starts_times.items()
    )

assert (
    solution(
        """station,r1,r2,r3
a,00:01,,00:02
b,00:16,,00:17
c,,00:21,
d,00:46,00:51,00:47"""
    )
    == 64
)

print("Solution", solution(get_file_content("input34.csv")))


from mysql.connector import connect
import settings
from flask import g

def get_db():
    if 'db' not in g:
        g.db = connect(option_files=settings.INFO_FiLE_PATH)
    return g.db

def insert_site(conn, name, url):
    query = """
        INSERT INTO Site(name, address) VALUES (%s, %s);
    """
    cursor = conn.cursor()
    value = (name, url)
    cursor.execute(query, value)
    cursor.close()

def insert_company(conn, site_id, name):
    query = """
            INSERT INTO Company(site_id, name)
            VALUES(%s,%s);
    """
    cursor = conn.cursor()
    value = (site_id, name)
    cursor.execute(query, value)
    cursor.close()

def insert_model(conn, company_id, name):
    query = """
            INSERT INTO Model(company_id, name)
            VALUES(%s,%s);
    """
    cursor = conn.cursor()
    value = (company_id, name)
    cursor.execute(query, value)
    cursor.close()

def insert_product(conn, idb, model_id, name, number, price):
    query = """
            INSERT INTO Product(id, model_id, name, number, price)
            VALUES(%s,%s,%s,%s,%s);
    """
    cursor = conn.cursor()
    value = (idb, model_id, name, number, price)
    cursor.execute(query, value)
    cursor.close()

def update_site(conn, idb, name, url):
    query = """
            UPDATE Site SET name = %s, address = %s
            WHERE id = %s;
    """
    cursor = conn.cursor()
    value = (name, url, idb)
    cursor.execute(query, value)
    cursor.close()

def update_company(conn, idb, name):
    query = """
            UPDATE Company SET name = %s
            WHERE id = %s;
    """
    cursor = conn.cursor()
    value = (name, idb)
    cursor.execute(query, value)
    cursor.close()

def update_model(conn, idb, name):
    query = """
            UPDATE Model SET name = %s
            WHERE id = %s;
    """
    cursor = conn.cursor()
    value = (name, idb)
    cursor.execute(query, value)
    cursor.close()

def update_product(conn, code, price):
    query = """
            UPDATE Product SET price = %s
            WHERE id = %s;
    """
    cursor = conn.cursor()
    value = (price, code)
    cursor.execute(query, value)
    cursor.close()

def get_company_id(conn, name):
    query = "SELECT id FROM Company WHERE name = %s"
    cursor = conn.cursor()
    value = (name,)
    cursor.execute(query, value)
    com_id = cursor.fetchone()[0]
    cursor.close()
    return com_id

def get_model_id(conn, name):
    query = "SELECT id FROM Model WHERE name = %s"
    cursor = conn.cursor()
    value = (name,)
    cursor.execute(query, value)
    mod_id = cursor.fetchone()[0]
    cursor.close()
    return mod_id


import math
import torch
import torch.nn as nn
import torch.nn.functional as F

class GCNLayer(nn.Module):
    """
        GCN layer, similar to https://arxiv.org/abs/1609.02907
        Implementation inspired by https://github.com/tkipf/pygcn
    """

    def __init__(self, in_features, out_features, bias=True, device='cpu'):
        """
        :param in_features:     size of the input per node
        :param out_features:    size of the output per node
        :param bias:            whether to add a learnable bias before the activation
        :param device:          device used for computation
        """
        super(GCNLayer, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.device = device
        self.W = nn.Parameter(torch.zeros(size=(in_features, out_features), device=device))
        if bias:
            self.b = nn.Parameter(torch.zeros(out_features, device=device))
        else:
            self.register_parameter('b', None)
        self.reset_parameters()

    def reset_parameters(self):
        stdv = 1. / math.sqrt(self.W.size(1))
        self.W.data.uniform_(-stdv, stdv)
        if self.b is not None:
            self.b.data.uniform_(-stdv, stdv)

    def forward(self, X, adj):
        (B, N, _) = adj.shape

        # linear transformation
        XW = torch.matmul(X, self.W)

        # normalised mean aggregation
        adj = adj + torch.eye(N, device=self.device).unsqueeze(0)
        rD = torch.mul(torch.pow(torch.sum(adj, -1, keepdim=True), -0.5),
                       torch.eye(N, device=self.device).unsqueeze(0))  # D^{-1/2]
        adj = torch.matmul(torch.matmul(rD, adj), rD)  # D^{-1/2] A' D^{-1/2]
        y = torch.bmm(adj, XW)

        if self.b is not None:
            y = y + self.b
        return F.leaky_relu(y)

    def __repr__(self):
        return self.__class__.__name__ + ' (' \
               + str(self.in_features) + ' -> ' \
               + str(self.out_features) + ')'


import random
import sqlite3

# ============= create account ===========

is_exit = False

def create_pin():
    return str(int(random.random() * 1e4)).zfill(4)

def create_checksum(string):
    accum = 0
    for i in reversed(range(len(string))):
        val = int(string[i]) * (1 if i % 2 else 2)
        accum += val if val <= 9 else val - 9
    return (10 - accum % 10) if accum % 10 > 0 else 0

def create_account():
    bank_id_st = '400000'
    act_st = str(int(random.random() * 1e6)).zfill(9)
    checksum_st = str(create_checksum(bank_id_st + act_st))
    return bank_id_st + act_st + checksum_st

def enter_acct():
    acct = input('Enter your card number:\n')
    if len(acct) != 16 or not acct.isnumeric():
        print('Invalid card number')
        return False
    lpin = input('Enter your PIN:\n')
    if len(lpin) != 4 or not lpin.isnumeric():
        print('Invalid PIN')
        return False
    query = "SELECT pin FROM card WHERE  number = '{}'".format(acct)
    cursor.execute(query)
    results = cursor.fetchone()
    if results is None:
        print('Wrong card number or PIN')
        return False
    if lpin != results[0]:
        print('Wrong card number or PIN')
        return False
    print('You have successfully logged in!')
    return acct

def get_balance(card_number):
    query = "SELECT balance FROM card WHERE  number = '{}'".format(card_number)
    cursor.execute(query)
    return int(cursor.fetchone()[0])

def add_income(card_number, addition):
    query = "UPDATE card SET balance = balance + {} WHERE number = {}".format(addition, card_number)
    cursor.execute(query)
    connection.commit()

def close_account(card_number):
    query = "DELETE FROM card WHERE number = {}".format(card_number)
    cursor.execute(query)
    connection.commit()

def has_enough_money(card_number, transfer_amount):
    if get_balance(card_number) < transfer_amount:
        return False
    return True

def is_card_exists(card_number):
    query = "SELECT * FROM card WHERE  number = '{}'".format(card_number)
    cursor.execute(query)
    return not cursor.fetchone() is None

def execute_transaction(from_card, to_card, amount):
    add_income(from_card, -1 * amount)
    add_income(to_card, amount)

def luhn_checksum(card_number):
    def digits_of(n):
        return [int(d) for d in str(n)]

    digits = digits_of(card_number)
    odd_digits = digits[-1::-2]
    even_digits = digits[-2::-2]
    checksum = 0
    checksum += sum(odd_digits)
    for d in even_digits:
        checksum += sum(digits_of(d * 2))
    return checksum % 10

def is_luhn_valid(card_number):
    return luhn_checksum(card_number) == 0

# ============= MAIN ============
connection = sqlite3.connect('card.s3db')
cursor = connection.cursor()
command1 = '''CREATE TABLE IF NOT EXISTS card
(id INTEGER, number TEXT, pin TEXT, balance INTEGER DEFAULT 0)'''
cursor.execute(command1)

while True:
    # ============= User input ============
    choice = int(input('1. Create an account\n'
                       '2. Log into account\n'
                       '0. Exit'))
    if choice == 0:
        print('Bye!')
        connection.commit()
        break

    if choice == 1:
        try:
            card_num = create_account()
            print('Your card has been created')
            print('Your card number:\n{}'.format(card_num))
            pin = create_pin()
            print('Your card PIN:\n{}'.format(pin))
            cmd = "INSERT INTO card (number, pin) VALUES('{}', '{}')".format(card_num, pin)
            cursor.execute(cmd)
            connection.commit()
        except sqlite3.OperationalError:
            print('invalid attempt to append to database ----------')
            print('attempting to add {} with pin {} to\n'.format(card_num, pin))
            cursor.execute('SELECT * FROM card')
            results = cursor.fetchall()
            print(len(results))
            print(results)

    elif choice == 2:
        c_num = enter_acct()
        while True:
            if c_num:
                print('1. Balance\n'
                      '2. Add income\n'
                      '3. Do transfer\n'
                      '4. Close account\n'
                      '5. Log out\n'
                      '0. Exit')
            else:
                break
            choice2 = int(input())

            if choice2 == 1:
                print("Balance:", get_balance(c_num))
            elif choice2 == 2:
                income = int(input("Enter income:\n"))
                add_income(c_num, income)
                print("Income was added!\n")
            elif choice2 == 3:
                print("Transfer")
                t_card_number = input("Enter card number:\n")
                if t_card_number != c_num:
                    if is_luhn_valid(t_card_number):
                        if is_card_exists(t_card_number):
                            t_amount = int(input("Enter how much money you want to transfer:"))
                            if has_enough_money(c_num, t_amount):
                                execute_transaction(c_num, t_card_number, t_amount)
                            else:
                                print("Not enough money!")
                        else:
                            print("Such a card does not exist.")
                    else:
                        print("Probably you made mistake in the card number. Please try again!")
                else:
                    print("You can't transfer money to the same account!")
            elif choice2 == 4:
                close_account(c_num)
                print("\nThe account has been closed!\n")
                break
            elif choice2 == 5:
                print('You have successfully logged out!')
                break
            elif choice2 == 0:
                is_exit = True
                break
    if is_exit:
        break


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):

    dependencies = [
        ('localore_admin', '0005_auto_20160331_1015'),
        ('blog', '0030_auto_20160404_1610'),
    ]

    operations = [
        migrations.AddField(
            model_name='blogpage',
            name='tile_image',
            field=models.ForeignKey(blank=True, related_name='+', help_text='Optional: The image to use on the connections index page. Will use poster image if not set.', on_delete=django.db.models.deletion.SET_NULL, null=True, to='localore_admin.LocaloreImage'),
        ),
    ]


from OpenGL.GL import glBegin, glColor3f, glEnd, glEndList, glLineWidth, glNewList, glNormal3f, glVertex3f, \
                      GL_COMPILE, GL_LINES, GL_QUADS
from OpenGL.GLU import gluDeleteQuadric, gluNewQuadric, gluSphere

G_OBJ_SPHERE = 2
def make_sphere():
	glNewList(G_OBJ_SPHERE,GL_COMPILE)
	quad = gluNewQuadric()
	gluSphere(quad,0.5,30,30)
	gluDeleteQuadric(quad)
	glEndList()

def init_primitives():
	make_sphere()

OpenGL/3D Modelling Tool via OpenGL/primitive.py


#!/usr/bin/python3

import serial
import rrdtool
import os.path

def createrrd():
    # 600 samples of 5 minutes  (2 days and 2 hours)
    # 700 samples of 30 minutes (2 days and 2 hours, plus 12.5 days)
    # 775 samples of 2 hours    (above + 50 days)
    # 797 samples of 1 day      (above + 732 days, rounded up to 797)
    if os.path.exists("rads.rrd"):
        print("Using existing RRD...")
    else:
        rrdtool.create("rads.rrd",
                "--start", "now",
                "--step", "300",
                "DS:cps:GAUGE:600:U:U",
                "DS:cpm:GAUGE:600:U:U",
                "RRA:AVERAGE:0.5:1:600",
                "RRA:AVERAGE:0.5:6:700",
                "RRA:AVERAGE:0.5:24:775",
                "RRA:AVERAGE:0.5:288:797",
                "RRA:MAX:0.5:1:600",
                "RRA:MAX:0.5:6:700",
                "RRA:MAX:0.5:24:775",
                "RRA:MAX:0.5:288:797")

ser = serial.Serial('/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0KPLG7-if00-port0',baudrate=9600, bytesize=8,parity='N',stopbits=1, timeout=3, xonxoff=0, rtscts=0)

print(ser.baudrate)
print(ser.name)

createrrd()

while (1):
    # b'CPS, 0, CPM, 13, uSv/hr, 0.07, SLOW\r\n'
    line = ser.readline()
    string = line.decode()
    chunks = string.split(',')
    if (len(chunks) == 7):
        cps = chunks[1]
        cpm = chunks[3]
        print("Logging N:"+cps+":"+cpm)
        rrdtool.update("rads.rrd","N:"+cps+":"+cpm)
    else:
        print("Bad read:", line)


from __future__ import print_function
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import SGD
from keras.utils import np_utils
import numpy as np
import matplotlib.pyplot as plt
import random

Epoch = 30
Number_Hidden = 128
Speed_Learning = 0.01
Opt = SGD(lr=Speed_Learning)
Proportion_Validation = 0.2
Size_Batch = 1024
Verbose = 1
Number_Classes = 10
Length_Unit = 784
np.random.seed(461)

(input_X_train, output_Y_train), (input_X_test, output_Y_test) = mnist.load_data()
print("Training data input shape: ", input_X_train.shape)
print("Training data output shape: ", output_Y_train.shape)
print("Test data input shape: ", input_X_test.shape)
print("Test data output shape: ", output_Y_test.shape)

image = input_X_train[10]
print("A sample image is as an array: ")
print(str(image))
# plt.imshow(image, cmap='gray')
# plt.show()

input_X_train = input_X_train.reshape(60000, Length_Unit)
input_X_test = input_X_test.reshape(10000, Length_Unit)
input_X_train = input_X_train.astype('float32')
input_X_test = input_X_test.astype('float32')

input_X_train /= 255
input_X_test /= 255
output_Y_train = np_utils.to_categorical(output_Y_train, Number_Classes)
output_Y_test = np_utils.to_categorical(output_Y_test, Number_Classes)

model = Sequential()

model.add(Dense(Number_Hidden, input_shape=(Length_Unit,)))
model.add(Activation('relu'))

model.add(Dense(Number_Hidden))
model.add(Activation('relu'))

model.add(Dense(Number_Hidden))
model.add(Activation('relu'))

model.add(Dense(Number_Hidden))
model.add(Activation('relu'))

model.add(Dense(Number_Hidden))
model.add(Activation('relu'))

# model.add(Dense(Number_Hidden))
# model.add(Activation('relu'))

# model.add(Dense(Number_Classes))
# model.add(Activation('relu'))

# model.add(Dense(Number_Classes))
# model.add(Activation('relu'))

# model.add(Dense(Number_Classes))
# model.add(Activation('relu'))

# model.add(Dense(Number_Classes))
# model.add(Activation('relu'))

model.add(Dense(Number_Classes))
model.add(Activation('softmax'))

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

fitted_model = model.fit(input_X_train, output_Y_train, batch_size=Size_Batch, epochs=Epoch, verbose=Verbose, validation_split=Proportion_Validation)

score = model.evaluate(input_X_test, output_Y_test, verbose=Verbose)
print("Test score/loss:", score[0])
print("Test accuracy:", score[1])

plt.plot(fitted_model.history['acc'])
plt.plot(fitted_model.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()

plt.plot(fitted_model.history['loss'])
plt.plot(fitted_model.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

result = model.predict(input_X_test, batch_size=Size_Batch, verbose=Verbose)
new = []
for i in range(0, len(result)):
    if output_Y_test[i][0] == 1:
        new.append(result[i][0])
plt.boxplot(new)
plt.show()


import unittest
import tempfile
import os
import shutil

from utils.vasp import (find_vasp_directories)

class TestFindVaspDirectories(unittest.TestCase):
    def setUp(self):
        self.temp_dir = tempfile.mkdtemp()
        self.create_test_files()

    def tearDown(self):
        shutil.rmtree(self.temp_dir)

    def create_test_files(self):
        dir1_path = os.path.join(self.temp_dir, "dir1")
        os.makedirs(dir1_path)

        vasp_log_path = os.path.join(dir1_path, "asdf.jpg")
        with open(vasp_log_path, "w") as file:
            file.write("This is a jpg file")

        incar_path = os.path.join(dir1_path, "pasdf.txt")
        with open(incar_path, "w") as file:
            file.write("This is random text file")

        dir2_path = os.path.join(self.temp_dir, "dir2")
        os.makedirs(dir2_path)

        vasp_log_path = os.path.join(dir2_path, "vasp.log")
        with open(vasp_log_path, "w") as file:
            file.write("This is vasp.log")

        potcar_path = os.path.join(dir2_path, "POTCAR")
        with open(potcar_path, "w") as file:
            file.write("This is POTCAR")

        dir3_path = os.path.join(self.temp_dir, "dir3")
        os.makedirs(dir3_path)

        incar_path = os.path.join(dir3_path, "INCAR")
        with open(incar_path, "w") as file:
            file.write("This is INCAR")

        kpoints_path = os.path.join(dir3_path, "KPOINTS")
        with open(kpoints_path, "w") as file:
            file.write("This is KPOINTS")

        outcar_path = os.path.join(dir3_path, "OUTCAR")
        with open(outcar_path, "w") as file:
            file.write("This is OUTCAR")

    def test_find_vasp_directories(self):
        parent_dir = self.temp_dir
        filenames = ["vasp.log", "INCAR", "POTCAR", "CONTCAR", "KPOINTS", "OUTCAR"]
        all_present = False
        extract_tarballs = True

        directories = find_vasp_directories(parent_dir, filenames, all_present, extract_tarballs)

        self.assertEqual(len(directories), 2)

        expected_dirs = ["dir2", "dir3"]
        for dir_name in expected_dirs:
            self.assertIn(dir_name, [os.path.basename(dir) for dir in directories])

    def test_find_vasp_directories_negative(self):
        # Create a temporary empty directory to test the negative case
        empty_dir = tempfile.mkdtemp()

        # Call the function with empty directory and all_present=True
        parent_dir = empty_dir
        filenames = ["vasp.log", "INCAR", "POTCAR", "CONTCAR", "KPOINTS", "OUTCAR"]
        all_present = True
        extract_tarballs = True

        directories = find_vasp_directories(parent_dir, filenames, all_present, extract_tarballs)

        # Assert that the function returns an empty list as there are no directories that meet the criteria
        self.assertEqual(len(directories), 0)

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