from datetime import datetime

from ueaglider.data.db_session import create_session
from ueaglider.data.db_classes import Pins, Audit, Missions, Targets, Gliders, Dives, ArgosTags
from ueaglider.services.argos_service import tag_info
from ueaglider.services.glider_service import glider_info
from ueaglider.services.user_service import find_user_by_id

def edit_waypoint_info(waypoint_id, info_txt):
    if not waypoint_id:
        return None
    session = create_session()
    waypoint = session.query(Pins).filter(Pins.WaypointsID == waypoint_id).first()
    waypoint.Info = info_txt
    session.commit()
    session.close()
    return

def create_waypoint(missionid, name, lat, lon, info):
    session = create_session()
    waypoint = Pins()
    waypoint.MissionID = missionid
    waypoint.Name = name
    waypoint.Latitude = lat
    waypoint.Longitude = lon
    waypoint.Info = info
    session.add(waypoint)
    session.commit()
    session.close()
    return waypoint

def delete_pin(pin_id):
    session = create_session()
    pin = session.query(Pins) \
        .filter(Pins.WaypointsID == pin_id) \
        .first()
    session.delete(pin)
    session.commit()
    session.close()
    return pin

def create_target(missionid, name, lat, lon, radius, goto):
    session = create_session()
    target = Targets()
    target.MissionID = missionid
    target.Name = name
    target.Latitude = lat
    target.Longitude = lon
    target.Radius = radius
    target.Goto = goto
    session.add(target)
    session.commit()
    session.close()
    return target

def delete_target(target_id):
    session = create_session()
    target = session.query(Targets) \
        .filter(Targets.TargetsID == target_id) \
        .first()
    session.delete(target)
    session.commit()
    session.close()
    return target

def delete_glider(glider_num):
    session = create_session()
    target = session.query(Gliders) \
        .filter(Gliders.Number == glider_num) \
        .first()
    session.delete(target)
    session.commit()
    session.close()
    return

def create_mission(number, name, start, end, info):

    mission = Missions()
    mission.Number = number
    mission.Name = name
    mission.StartDate = start
    mission.EndDate = end
    mission.Info = info
    session = create_session()
    session.add(mission)
    session.commit()
    session.close()
    return mission

def delete_mission(mission_id):
    session = create_session()
    mission = session.query(Missions) \
        .filter(Missions.Number == mission_id) \
        .first()
    session.delete(mission)
    session.commit()
    return mission

def delete_dive(dive_id):
    session = create_session()
    dive = session.query(Dives) \
        .filter(Dives.DiveInfoID == dive_id) \
        .first()
    session.delete(dive)
    session.commit()
    return dive

def delete_multiple_dives(glider_id):
    dive = None
    session = create_session()
    dives = session.query(Dives) \
        .filter(Dives.MissionID == 1)\
        .filter(Dives.GliderID == glider_id) \
        .all()
    for dive in dives:
        session.delete(dive)
    session.commit()
    return dive

def create_glider(number, name, info, mission_id, ueaglider):
    glider = Gliders()
    glider.Number = number
    glider.Name = name
    glider.Info = info
    glider.MissionID = mission_id
    glider.UEAGlider = ueaglider
    session = create_session()
    session.add(glider)
    session.commit()
    session.close()
    return glider

def assign_glider(number, mission_id):
    glider, __ = glider_info(number)
    glider.MissionID = mission_id
    session = create_session()
    session.add(glider)
    session.commit()
    session.close()
    return glider

def create_tag(number, mission_id, glider_id):
    tag = ArgosTags()
    tag.TagNumber = number
    tag.MissionID = mission_id
    tag.GliderID = glider_id
    session = create_session()
    session.add(tag)
    session.commit()
    session.close()
    return tag

def assign_tag(number, mission_id, glider_id):
    tag= tag_info(number)
    tag.MissionID = mission_id
    tag.GliderID = glider_id
    session = create_session()
    session.add(tag)
    session.commit()
    session.close()
    return tag

def delete_tag(tag_num):
    session = create_session()
    target = session.query(ArgosTags) \
        .filter(ArgosTags.TagNumber == tag_num) \
        .first()
    session.delete(target)
    session.commit()
    session.close()
    return

def audit_entry(user_id: int, message: str):
    user = find_user_by_id(user_id)
    if not user:
        return None
    audit = Audit()
    audit.UserID = user_id
    audit.Date = datetime.now()
    audit.Info = message

    session = create_session()
    session.add(audit)
    session.commit()
    session.close()
    return audit


import numpy as np
from numpy import linalg
from scipy import sparse
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator

def read_dataset(path: str):
    with open(path, 'r') as f:
        lines = f.readlines()
        x = np.zeros([len(lines), 123])
        y = np.zeros([len(lines)])
        for (i, line) in enumerate(lines):
            y[i] = 0.0 if line[0] == '-' else 1.0
            features = line.strip().split()[1:]
            for feature in features:
                index = int(feature.split(':')[0]) - 1
                assert 0 <= index < 123
                x[i, index] = 1.0
        return x.T, y

def predict(X, y, w):
    mu = 1.0 / (np.exp(-w.dot(X)) + 1.0) - 0.5
    labels = mu >= 0
    return np.sum(labels == y) / y.shape[0]

def IRLS(X, y, tX, ty, lam=0.001, threshold=0.00001, max_iter=20):
    train_acc, test_acc = [], []

    # X: [d, n], y: [n]
    d, n = X.shape

    # w: [d]
    w = np.ones(d)

    count = 0
    while True:
        # mu: [n], > 0
        mu = 1.0 / (np.exp(-w.dot(X)) + 1.0)

        # A, A_inv: [n, n]
        s = mu * (1 - mu) + 0.01
        A = sparse.diags(s)
        A_inv = sparse.diags(1 / s)

        # z:
        z = X.T.dot(w) - A_inv.dot(mu - y)

        # XAX^\intercal + \lambda I
        M = (A.dot(X.T)).T.dot(X.T) + lam * np.eye(d)
        M_inv = linalg.inv(M)

        # wt: [d]
        wt = A.dot(M_inv.dot(X).T).T.dot(z)

        # delta and update
        delta = np.sum(np.abs(w - wt)) / np.sum(np.abs(w))
        w = wt
        train_acc.append(predict(X, y, w))
        test_acc.append(predict(tX, ty, w))
        count += 1
        if delta < threshold or count == max_iter:
            break
    return w, train_acc, test_acc

# Read datasets
train_x, train_y = read_dataset('a9a/a9a')
test_x, test_y = read_dataset('a9a/a9a.t')

# Test different lambdas and draw
fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.set_xticks(range(1, 21))
ax2.set_xticks(range(1, 21))
for lam in [0, 0.1, 1, 10, 100, 1000]:
    print('Testing \\lambda={} ...'.format(lam))
    _, train_acc, test_acc = IRLS(train_x, train_y, test_x, test_y, lam=lam)
    print(train_acc, test_acc)
    int_axis = [i for i in range(1, len(train_acc) + 1)]
    ax1.plot(int_axis, train_acc, label='$\\lambda={}$'.format(lam))
    ax2.plot(int_axis, test_acc)
fig.legend()
fig.savefig('train.pdf')


import numpy as np
import tensorflow as tf
import datetime

n = 10

A = np.random.rand(10000, 10000).astype('float32')
B = np.random.rand(10000, 10000).astype('float32')

c1 = []
c2 = []

def matpow(M, n):
    if n == 1:
        return M
    else:
        return tf.matmul(M, matpow(M, n-1))

with tf.device('/gpu:0'):
    a = tf.placeholder(tf.float32, [10000, 10000])
    b = tf.placeholder(tf.float32, [10000, 10000])
    c1.append(matpow(a, n))
    c1.append(matpow(b, n))

with tf.device('/cpu:0'):
  sum = tf.add_n(c1) #Addition of all elements in c1, i.e. A^n + B^n

t1_1 = datetime.datetime.now()
#sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True))
"""
with tf.Session(config=tf.ConfigProto\
              (log_device_placement=log_device_placement)) as sess:
     sess.run(sum, {a:A, b:B})
"""
with tf.Session(config=tf.ConfigProto\
                (allow_soft_placement=True,\
                 log_device_placement=True)) as sess:
    sess.run(sum, {a:A, b:B})
t2_1 = datetime.datetime.now()
print("GPU computation time: " + str(t2_1-t1_1))


from collections import UserDict
from datetime import datetime
from datetime import timedelta

class CacheDict(UserDict):

    times = {}

    def __init__(self, dict={}, keytime=60, **kwargs):
        super().__init__(dict, **kwargs)

        self.keytime = keytime

    def __getitem__(self, key):

        if not self.times.get(key):
            raise KeyError(key)

        elapsed_time = datetime.now() - self.times.get(key)
        if elapsed_time.seconds <= 60:
            return super().__getitem__(key)
        else:
            self.data.pop(key)
            raise KeyError(key)

    def __setitem__(self, key, item):
        self.times[key] = datetime.now()

        return super().__setitem__(key, item)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

' hipnuc protocol module '

import threading
import struct
import datetime
import time

class HipnucFrame_Exception(Exception):
    def __init__(self,err='HI221GW Frame Error'):
        Exception.__init__(self,err)

class HipnucFrame_NoValid_Exception(HipnucFrame_Exception):
    def __init__(self,err='No valid frame received'):
        Exception.__init__(self,err)

class HipnucFrame_NotCompleted_Exception(HipnucFrame_Exception):
    def __init__(self,err='No full frame received'):
        Exception.__init__(self,err)

class HipnucFrame_ErrorFrame_Exception(HipnucFrame_Exception):
    def __init__(self,err='Error frame'):
        Exception.__init__(self,err)

def _parse_data_packet_0x90(data_section:list,node_num = None):
    module_id = {
        "id": data_section[0],
    }
    return module_id

def _parse_data_packet_0xD1(data_section:list,node_num = None):
    quaternion_list = []

    # for pos in range(node_num):
    pos = 0
    t_pos = pos * 16
    W = float(struct.unpack("<f", bytes(data_section[t_pos:t_pos + 4]))[0])
    t_pos += 4
    X = float(struct.unpack("<f", bytes(data_section[t_pos:t_pos + 4]))[0])
    t_pos += 4
    Y = float(struct.unpack("<f", bytes(data_section[t_pos:t_pos + 4]))[0])
    t_pos += 4
    Z = float(struct.unpack("<f", bytes(data_section[t_pos:t_pos + 4]))[0])

    temp_dic = {
        "W":round(W,3),
        "X":round(X,3),
        "Y":round(Y,3),
        "Z":round(Z,3)
    }
    quaternion_list.append(temp_dic)

    quaternion = {
        "quat":quaternion_list
    }

    return quaternion

def _parse_data_packet_0xA0(data_section:list,node_num = None):
    acc_list = []

    # for pos in range(node_num):
    pos = 0
    t_pos = pos * 6
    X = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])
    t_pos += 2
    Y = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])
    t_pos += 2
    Z = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])

    temp_dic = {
        "X":round(X,3),
        "Y":round(Y,3),
        "Z":round(Z,3)
    }
    acc_list.append(temp_dic)

    acc = {
        "acc":acc_list
    }

    return acc

def _parse_data_packet_0xB0(data_section:list,node_num = None):
    gyr_list = []

    # for pos in range(node_num):
    pos = 0
    t_pos = pos * 6
    X = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])
    t_pos += 2
    Y = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])
    t_pos += 2
    Z = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])

    temp_dic = {
        "X":round(X,3),
        "Y":round(Y,3),
        "Z":round(Z,3)
    }
    gyr_list.append(temp_dic)

    gyr = {
        "gyr":gyr_list
    }

    return gyr

def _parse_data_packet_0xC0(data_section:list,node_num = None):
    mag_list = []

    # for pos in range(node_num):
    pos = 0
    t_pos = pos * 6
    X = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])
    t_pos += 2
    Y = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])
    t_pos += 2
    Z = int(struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0])

    temp_dic = {
        "X":round(X,3),
        "Y":round(Y,3),
        "Z":round(Z,3)
    }
    mag_list.append(temp_dic)

    mag = {
        "mag":mag_list
    }

    return mag

def _parse_data_packet_0xD0(data_section:list,node_num = None):
    eul_list = []

    # for pos in range(node_num):
    pos = 0
    t_pos = pos * 6
    Pitch = struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0]
    Pitch = Pitch/100
    t_pos += 2
    Roll = struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0]
    Roll = Roll/100
    t_pos += 2
    Yaw = struct.unpack("<h", bytes(data_section[t_pos:t_pos + 2]))[0]
    Yaw = Yaw/10

    temp_dic = {
        "Pitch":round(Pitch,2),
        "Roll":round(Roll,2),
        "Yaw":round(Yaw,2)
    }
    eul_list.append(temp_dic)

    euler = {
        "euler":eul_list
    }

    return euler

def _parse_data_packet_0x91(data_section:list,node_num = None):
    pos = 0
    id_temp_list = []
    timestamp_temp_list = []
    acc_temp_list = []
    gyr_temp_list = []
    mag_temp_list = []
    eul_temp_list = []
    quat_temp_list = []

    # id
    id = data_section[pos]
    id_dic = {
        "":id
    }

    id_temp_list.append(id_dic)
    pos += 1
    #reserved
    pos += 6
    #timestamp
    timestamp = int(struct.unpack("<I", bytes(data_section[pos:pos + 4]))[0])
    timestamp_dic = {
        "(s)":round(timestamp/1000,3)
    }

    timestamp_temp_list.append(timestamp_dic)
    pos += 4
    #acc
    acc_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    acc_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    acc_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    acc_dic = {
        "X":round(acc_X,3),
        "Y":round(acc_Y,3),
        "Z":round(acc_Z,3)
    }
    acc_temp_list.append(acc_dic)
    #gyr
    gyr_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    gyr_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    gyr_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    gyr_dic = {
        "X": round(gyr_X,3),
        "Y": round(gyr_Y,3),
        "Z": round(gyr_Z,3)
    }
    gyr_temp_list.append(gyr_dic)
    #mag
    mag_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    mag_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    mag_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    mag_dic = {
        "X": round(mag_X),
        "Y": round(mag_Y),
        "Z": round(mag_Z)
    }
    mag_temp_list.append(mag_dic)
    #eul
    eul_Roll = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    eul_Pitch = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    eul_Yaw = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    eul_dic = {
        "Roll": round(eul_Roll, 2),
        "Pitch": round(eul_Pitch, 2),
        "Yaw": round(eul_Yaw, 2)
    }
    eul_temp_list.append(eul_dic)

    #quat
    quat_W = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    quat_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    quat_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    quat_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
    pos += 4
    quat_dic = {
        "W": round(quat_W,3),
        "X": round(quat_X,3),
        "Y": round(quat_Y,3),
        "Z": round(quat_Z,3),
    }
    quat_temp_list.append(quat_dic)

    temp_dic_list = {
        "id":id_temp_list,
        "timestamp":timestamp_temp_list,
        "acc":acc_temp_list,
        "gyr":gyr_temp_list,
        "mag":mag_temp_list,
        "euler":eul_temp_list,
        "quat":quat_temp_list
    }
    return temp_dic_list

def _parse_data_packet_0x93(data_section:list,node_num = None):
    pos = 0
    id_temp_list = []
    timestamp_temp_list = []
    acc_temp_list = []
    gyr_temp_list = []

    # id
    id = data_section[pos]
    id_temp_list.append(id)
    pos += 1
    #reserved
    pos += 6
    #timestamp
    timestamp = int(struct.unpack("<I", bytes(data_section[pos:pos + 4]))[0])
    timestamp_temp_list.append(timestamp)
    pos += 4
    #acc
    acc_X = int(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])
    pos += 2
    acc_Y = int(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])
    pos += 2
    acc_Z = int(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])
    pos += 2
    acc_dic = {
        "X":acc_X,
        "Y":acc_Y,
        "Z":acc_Z
    }
    acc_temp_list.append(acc_dic)
    #gyr
    gyr_X = int(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])
    pos += 2
    gyr_Y = int(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])
    pos += 2
    gyr_Z = int(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])
    pos += 2
    gyr_dic = {
        "X": gyr_X,
        "Y": gyr_Y,
        "Z": gyr_Z
    }
    gyr_temp_list.append(gyr_dic)

    temp_dic = {
        "id":id_temp_list,
        "timestamp":timestamp_temp_list,
        "acc":acc_temp_list,
        "gyr":gyr_temp_list,
    }
    return temp_dic

rel_node_num = 0
module_node_num = 0
def _parse_data_packet_0x62(data_section:list,node_num = None):
    global rel_node_num
    global module_node_num
    global data_packet_properties
    id_temp_list = []
    gwid_temp_list = []
    timestamp_temp_list = []
    acc_temp_list = []
    gyr_temp_list = []
    mag_temp_list = []
    eul_temp_list = []
    quat_temp_list = []
    pos = 0

    gwid = data_section[0]
    id_dic = {
            "":gwid
        }
    gwid_temp_list.append(id_dic)

    cnt = data_section[1]
    rel_node_num = cnt
    module_node_num = cnt
    data_packet_properties[0x62]["data_len"] = 5 + (76 * cnt)
    pos += 2
    #reserved
    pos += 5
    #0x91 packet
    for node in range(cnt):
        #packet id
        pos += 1

        # id
        id = data_section[pos]
        id_dic = {
            "":id
        }
        id_temp_list.append(id_dic)
        pos += 1
        #reserved
        pos += 6
        #timestamp
        timestamp = int(struct.unpack("<I", bytes(data_section[pos:pos + 4]))[0])
        timestamp_dic = {
            "(s)":round(timestamp/1000,3)
        }

        timestamp_temp_list.append(timestamp_dic)
        pos += 4

        #acc
        acc_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        acc_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        acc_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        acc_dic = {
            "X":round(acc_X,3),
            "Y":round(acc_Y,3),
            "Z":round(acc_Z,3)
        }
        acc_temp_list.append(acc_dic)
        #gyr
        gyr_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        gyr_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        gyr_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        gyr_dic = {
            "X": round(gyr_X,3),
            "Y": round(gyr_Y,3),
            "Z": round(gyr_Z,3)
        }
        gyr_temp_list.append(gyr_dic)
        #mag
        mag_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        mag_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        mag_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        mag_dic = {
            "X": round(mag_X),
            "Y": round(mag_Y),
            "Z": round(mag_Z)
        }
        mag_temp_list.append(mag_dic)
        #eul
        eul_Roll = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        eul_Pitch = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        eul_Yaw = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        eul_dic = {
            "Roll": round(eul_Roll, 2),
            "Pitch": round(eul_Pitch, 2),
            "Yaw": round(eul_Yaw, 2)
        }
        eul_temp_list.append(eul_dic)

        #quat
        quat_W = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        quat_X = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        quat_Y = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        quat_Z = float(struct.unpack("<f", bytes(data_section[pos:pos + 4]))[0])
        pos += 4
        quat_dic = {
            "W": round(quat_W,3),
            "X": round(quat_X,3),
            "Y": round(quat_Y,3),
            "Z": round(quat_Z,3),
        }
        quat_temp_list.append(quat_dic)

        temp_dic_list = {
            "id":id_temp_list,
            "timestamp":timestamp_temp_list,
            "acc":acc_temp_list,
            "gyr":gyr_temp_list,
            "mag":mag_temp_list,
            "euler":eul_temp_list,
            "quat":quat_temp_list
        }

    temp_dic = {
        "GWD":gwid_temp_list,
        "id":id_temp_list,
        "timestamp":timestamp_temp_list,
        "acc":acc_temp_list,
        "gyr":gyr_temp_list,
        "mag":mag_temp_list,
        "euler":eul_temp_list,
        "quat":quat_temp_list
    }
    return temp_dic

rel_node_num = 0
module_node_num = 0
#only for 400hz acc and gyro
def _parse_data_packet_0x63(data_section:list,node_num = None):
    global rel_node_num
    global module_node_num
    global data_packet_properties
    id_temp_list = []
    timestamp_temp_list = []
    acc_temp_list = []
    gyr_temp_list = []

    pos = 0
    gwid = data_section[0]
    cnt = data_section[1]
    rel_node_num = cnt
    module_node_num = cnt
    data_packet_properties[0x63]["data_len"] = 5 + (24 * cnt)
    pos += 2
    #reserved
    pos += 5
    #0x93 packet
    for node in range(cnt):
        #packet id
        pos += 1

        # id
        id = data_section[pos]
        id_dic = {
            "":id
        }
        id_temp_list.append(id_dic)
        pos += 1
        #reserved
        pos += 6
        #timestamp
        timestamp = int(struct.unpack("<I", bytes(data_section[pos:pos + 4]))[0])
        timestamp_dic = {
            "(s)":round(timestamp/1000,3)
        }

        timestamp_temp_list.append(timestamp_dic)
        pos += 4

        #acc
        acc_X = float(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])/1000
        pos += 2
        acc_Y = float(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])/1000
        pos += 2
        acc_Z = float(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])/1000
        pos += 2

        acc_dic = {
            "X":round(acc_X,3),
            "Y":round(acc_Y,3),
            "Z":round(acc_Z,3)
        }
        acc_temp_list.append(acc_dic)
        #gyr
        gyr_X = float(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])/10
        pos += 2
        gyr_Y = float(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])/10
        pos += 2
        gyr_Z = float(struct.unpack("<h", bytes(data_section[pos:pos + 2]))[0])/10
        pos += 2
        gyr_dic = {
            "X": round(gyr_X,3),
            "Y": round(gyr_Y,3),
            "Z": round(gyr_Z,3)
        }
        gyr_temp_list.append(gyr_dic)

    temp_dic = {
        "GWD":gwid_temp_list,
        "id":id_temp_list,
        "timestamp":timestamp_temp_list,
        "acc":acc_temp_list,
        "gyr":gyr_temp_list,
    }
    return temp_dic
data_packet_properties = {
    # id
    0x90: {
        "type": "id",
        "id_len": 1,
        "data_len": 1,
        "parse method": _parse_data_packet_0x90,
        "gw_data":False
    },

    # acc
    0xA0: {
        "type": "acc",
        "id_len": 1,
        "data_len": 6,
        "parse method": _parse_data_packet_0xA0,
        "gw_data": False
    },
    # gyr
    0xB0: {
        "type": "gyr",
        "id_len": 1,
        "data_len": 6,
        "parse method": _parse_data_packet_0xB0,
        "gw_data": False
    },
    # mag
    0xC0: {
        "type": "mag",
        "id_len": 1,
        "data_len": 6,
        "parse method": _parse_data_packet_0xC0,
        "gw_data": False
    },
    # float_eul
    0xD0: {
        "type": "euler",
        "id_len": 1,
        "data_len": 6,
        "parse method": _parse_data_packet_0xD0,
        "gw_data": False
    },
    # quat
    0xD1: {
        "type": "quat",
        "id_len": 1,
        "data_len": 16,
        "parse method": _parse_data_packet_0xD1,
        "gw_data":False
    },
    # imusol
    0x91: {
        "type": "imusol",
        "id_len": 1,
        "data_len": 76,
        "parse method": _parse_data_packet_0x91,
        "gw_data": False
    },
    # gwimusol
    0x62: {
        "type": "gwsol",
        "id_len": 1,
        "data_len": 76 * 1,
        "parse method": _parse_data_packet_0x62,
        "gw_data": True
    },

    # imusol only raw
    0x93: {
        "type": "imusol_raw",
        "id_len": 1,
        "data_len": 24,
        "parse method": _parse_data_packet_0x93,
        "gw_data": False
    },

    # gwsol only raw
    0x63: {
        "type": "gwsol_raw",
        "id_len": 1,
        "data_len": 24 * 1,
        "parse method": _parse_data_packet_0x63,
        "gw_data": True
    }
}

def crc16_update(buffer_list, cal_len, cal_pos, crc=0):
    for temp_j in range(cal_len):
        byte = buffer_list[temp_j + cal_pos]
        crc ^= byte << 8
        crc &= 0xffffffff
        for temp_i in range(8):
            temp = crc << 1
            temp &= 0xffffffff
            if (crc & 0x8000):
                temp ^= 0x1021
                temp &= 0xffffffff
            crc = temp

    return (crc & 0xffff)

SampleRate = 0
SamplesReceived = 0
prevSamplesReceived = 0
sample_rate_alive_flag = True

def sample_rate_timer_cb(sample_timer):
    global SampleRate,SamplesReceived,prevSamplesReceived,sample_rate_alive_flag

    SampleRate = SamplesReceived - prevSamplesReceived
    prevSamplesReceived = SamplesReceived
    print("每秒幀率：",SampleRate,datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))

    if sample_rate_alive_flag == True:
        sample_timer = threading.Timer(1.00, sample_rate_timer_cb,args=(sample_timer,))
        sample_timer.start()

def sample_rate_timer_close():
    global sample_rate_alive_flag
    sample_rate_alive_flag = False

# 找到幀頭
def find_frameheader(buffer_list:list):
    # 循環查找，直至拋出異常
    while True:
        # 查找幀頭的第一個標識符0x5a,若未找到，將會拋出ValueError異常
        try:
            header_ind = buffer_list.index(0x5a)
        except ValueError:
            raise HipnucFrame_NotCompleted_Exception

        if header_ind + 1 > len(buffer_list) - 1:
            raise HipnucFrame_NotCompleted_Exception

        if buffer_list[header_ind + 1] == 0xa5:
            # 找到幀頭標識符0x5aa5，返回幀頭位置
            return header_ind
        else:
            # 未找到幀頭標識符，切片繼續查找
            buffer_list = buffer_list[header_ind + 1:]

# 驗證獲取長度
def _get_frame_length(buffer_list, header_pos):
    return int(struct.unpack("<h", bytes(buffer_list[header_pos + 2:header_pos + 4]))[0])

# 驗證長度是否合法
def _verify_frame_length(buffer_list:list, header_pos):
    # 獲取到幀長度
    frame_len = int(struct.unpack("<h", bytes(buffer_list[header_pos + 2:header_pos + 4]))[0])
    # 判斷幀長度是否合法
    if frame_len >= 1024:
        raise HipnucFrame_ErrorFrame_Exception
    elif frame_len + header_pos + 6 > len(buffer_list) :
        raise  HipnucFrame_NotCompleted_Exception

# 驗證crc是否正確
def _verify_frame_crc(buffer_list, header_pos=0):
    # 獲取到幀長度
    frame_len = int(struct.unpack("<h", bytes(buffer_list[header_pos + 2:header_pos + 2 + 2]))[0])
    # 獲取幀內的crc
    f_crc = int(struct.unpack("<H", bytes(buffer_list[header_pos + 4:header_pos + 4 + 2]))[0])
    # 計算幀的crc
    cal_crc = crc16_update(buffer_list, 4, header_pos, 0)
    cal_crc = crc16_update(buffer_list, frame_len, header_pos + 6, cal_crc)

    if cal_crc != f_crc:
        raise HipnucFrame_ErrorFrame_Exception

# 截取一條完整且合法的幀，並將幀頭幀尾返回
def intercept_one_complete_frame(buffer_list):
    # 找幀頭
    header_pos = find_frameheader(buffer_list)
    try:
        frame_len = int(struct.unpack("<H", bytes(buffer_list[header_pos + 2:header_pos + 2 + 2]))[0])
    except struct.error:
        raise HipnucFrame_NotCompleted_Exception
    end_pos = header_pos + 5 + frame_len
    # 驗證幀長度
    _verify_frame_length(buffer_list, header_pos)
    # 驗證crc
    _verify_frame_crc(buffer_list, header_pos)

    return header_pos, end_pos

# 從完整幀中獲取資訊
def extraction_information_from_frame(frame_list:list, inf_fifo,report_datatype: dict = None):
    # 幀率統計
    global SamplesReceived
    global rel_node_num
    global module_node_num
    SamplesReceived = SamplesReceived + 1
    # 處理數據幀
    data_dic = {}
    pos = 0

    data_frame_list = frame_list[6:]

    #遍歷解析數據段內包含的數據
    while len(data_frame_list) > 0:
        if data_frame_list[0] in data_packet_properties:

            temp_dic = data_packet_properties[data_frame_list[0]]["parse method"](data_frame_list[1:],module_node_num)

            try:
                if report_datatype[data_packet_properties[data_frame_list[0]]["type"]] == True:
                    data_dic.update(temp_dic)
                else:
                    pass

            except KeyError:
                pass

            if data_packet_properties[data_frame_list[0]]["gw_data"] == True:
                rel_node_num = module_node_num
            else:
                rel_node_num = 1

            id_len = data_packet_properties[data_frame_list[0]]["id_len"]

            if data_frame_list[0] == 0x62:
                data_len = 76 * rel_node_num + 8
            elif data_frame_list[0] == 0x63:
                data_len = 24 * rel_node_num + 8

            else:
                data_len = data_packet_properties[data_frame_list[0]]["data_len"] * rel_node_num

            data_frame_list = data_frame_list[id_len + data_len:]
        else:
            # raise HipnucFrame_ErrorFrame_Exception
            data_frame_list = data_frame_list[1:]

    inf_fifo.put(data_dic)


from __future__ import absolute_import, division, print_function, unicode_literals

import argparse
import copy
import json
import os

SPLITS = ["train", "dev", "devtest", "teststd"]

def get_image_name(scene_ids, turn_ind):
    """Given scene ids and turn index, get the image name.
    """
    sorted_scene_ids = sorted(
        ((int(key), val) for key, val in scene_ids.items()),
        key=lambda x: x[0],
        reverse=True
    )
    # NOTE: Hardcoded to only two scenes.
    if turn_ind >= sorted_scene_ids[0][0]:
        scene_label = sorted_scene_ids[0][1]
    else:
        scene_label = sorted_scene_ids[1][1]
    image_label = scene_label
    if "m_" in scene_label:
        image_label = image_label.replace("m_", "")
    return f"{image_label}.png", scene_label

def get_object_mapping(scene_label, args):
    """Get the object mapping for a given scene.
    """
    scene_json_path = os.path.join(
        args["scene_json_folder"], f"{scene_label}_scene.json"
    )
    with open(scene_json_path, "r") as file_id:
        scene_objects = json.load(file_id)["scenes"][0]["objects"]
    object_map = [ii["index"] for ii in scene_objects]
    return object_map

def main(args):
    for split in SPLITS:
        read_path = args[f"simmc_{split}_json"]
        print(f"Reading: {read_path}")
        with open(read_path, "r") as file_id:
            dialogs = json.load(file_id)

        # Reformat into simple strings with positive and negative labels.
        # (dialog string, label)
        ambiguous_candidates_data = []
        for dialog_id, dialog_datum in enumerate(dialogs["dialogue_data"]):
            history = []
            for turn_ind, turn_datum in enumerate(dialog_datum["dialogue"]):
                history.append(turn_datum["transcript"])

                annotations = turn_datum["transcript_annotated"]
                if annotations.get("disambiguation_label", False):
                    label = annotations["disambiguation_candidates"]
                    image_name, scene_label = get_image_name(
                        dialog_datum["scene_ids"], turn_ind
                    )
                    # If dialog contains multiple scenes, map it accordingly.
                    object_map = get_object_mapping(scene_label, args)
                    new_datum = {
                        "dialog_id": dialog_datum["dialogue_idx"],
                        "turn_id": turn_ind,
                        "input_text": copy.deepcopy(history),
                        "ambiguous_candidates": label,
                        "image_name": image_name,
                        "object_map": object_map,
                    }
                    ambiguous_candidates_data.append(new_datum)
                # Ignore if system_transcript is not found (last round teststd).
                if turn_datum.get("system_transcript", None):
                    history.append(turn_datum["system_transcript"])

        print(f"# instances [{split}]: {len(ambiguous_candidates_data)}")
        save_path = os.path.join(
            args["ambiguous_candidates_save_path"],
            f"simmc2.1_ambiguous_candidates_dstc11_{split}.json"
        )
        print(f"Saving: {save_path}")
        with open(save_path, "w") as file_id:
            json.dump(
                {
                    "source_path": read_path,
                    "split": split,
                    "data": ambiguous_candidates_data,
                },
                file_id
            )

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--simmc_train_json", default=None, help="Path to SIMMC 2.1 train"
    )
    parser.add_argument(
        "--simmc_dev_json", default=None, help="Path to SIMMC 2.1 dev"
    )
    parser.add_argument(
        "--simmc_devtest_json", default=None, help="Path to SIMMC 2.1 devtest"
    )
    parser.add_argument(
        "--simmc_teststd_json", default=None, help="Path to SIMMC 2.1 teststd (public)"
    )
    parser.add_argument(
        "--scene_json_folder", default=None, help="Path to SIMMC scene jsons"
    )
    parser.add_argument(
        "--ambiguous_candidates_save_path",
        required=True,
        help="Path to save SIMMC disambiguate JSONs",
    )

    try:
        parsed_args = vars(parser.parse_args())
    except (IOError) as msg:
        parser.error(str(msg))
    main(parsed_args)


'''
Description:
Author: weihuang
Date: 2021-11-18 15:47:44
LastEditors: weihuang
LastEditTime: 2021-11-22 22:38:26
'''
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch.autograd import Variable

class CrossEntropy2d(nn.Module):
    def __init__(self, reduction="mean", ignore_label=255):
        super(CrossEntropy2d, self).__init__()
        self.reduction = reduction
        self.ignore_label = ignore_label

    def forward(self, predict, target, weight=None):
        """
            Args:
                predict:(n, c, h, w)
                target:(n, h, w)
                weight (Tensor, optional): a manual rescaling weight given to each class.
                                           If given, has to be a Tensor of size "nclasses"
        """
        assert not target.requires_grad
        assert predict.dim() == 4
        assert target.dim() == 3
        assert predict.size(0) == target.size(0), "{0} vs {1} ".format(predict.size(0), target.size(0))
        assert predict.size(2) == target.size(1), "{0} vs {1} ".format(predict.size(2), target.size(1))
        assert predict.size(3) == target.size(2), "{0} vs {1} ".format(predict.size(3), target.size(3))
        n, c, h, w = predict.size()
        target_mask = (target >= 0) * (target != self.ignore_label)
        target = target[target_mask]
        if not target.data.dim():
            return Variable(torch.zeros(1))
        predict = predict.transpose(1, 2).transpose(2, 3).contiguous()
        predict = predict[target_mask.view(n, h, w, 1).repeat(1, 1, 1, c)].view(-1, c)
        loss = F.cross_entropy(predict, target, weight=weight, reduction=self.reduction)
        return loss

class FocalLoss(nn.Module):
    def __init__(self, alpha=1, gamma=0, size_average=True):
        super(FocalLoss, self).__init__()
        self.alpha = alpha
        self.gamma = gamma
        self.size_average = size_average

    def forward(self, inputs, targets):
        ce_loss = F.cross_entropy(inputs, targets, reduction='none')
        pt = torch.exp(-ce_loss)
        focal_loss = self.alpha * (1-pt)**self.gamma * ce_loss
        if self.size_average:
            return focal_loss.mean()
        else:
            return focal_loss.sum()

class MSELoss(nn.Module):
    def forward(self,input,target):
        return torch.mean((input-target)**2)

class BCELoss(nn.Module):
    def forward(self, y_pred, y_label):
        y_truth_tensor = torch.FloatTensor(y_pred.size())
        y_truth_tensor.fill_(y_label)
        y_truth_tensor = y_truth_tensor.to(y_pred.get_device())
        return nn.BCEWithLogitsLoss()(y_pred, y_truth_tensor)

class WeightedBCELoss(nn.Module):
    def forward(self, input_y, target, weight):
        return F.binary_cross_entropy(input_y, target, weight)

class L1Loss_weighted(nn.Module):
    def forward(self, input, target, weights):
        loss = weights * torch.abs(input - target)
        loss = torch.mean(loss)
        return loss

def weighted_l1_loss(input, target, weights):
    loss = weights * torch.abs(input - target)
    loss = torch.mean(loss)
    return loss

def bce_loss(y_pred, y_label):
    y_truth_tensor = torch.FloatTensor(y_pred.size())
    y_truth_tensor.fill_(y_label)
    y_truth_tensor = y_truth_tensor.to(y_pred.get_device())
    return nn.BCEWithLogitsLoss()(y_pred, y_truth_tensor)


import os
import io
import re
import sys
import pandas as pd
import ujson as json
from argparse import ArgumentParser, FileType

from rasm import rasm

RULE_GROUPS = {
    'ASSIM-M': ['M1', 'M2'],
    'ASSIM-N': ['N2.1.1.A', 'N2.1.1.B', 'N2.1.1.C', 'N2.1.1.D', 'N2.1.2.A', 'N2.1.2.B', 'N2.1.2.C', 'N2.1.2.D', 'N2.2.A', 'N2.2.B', 'N2.2.C',
                  'N2.2.D', 'N3.A', 'N3.B', 'N3.C', 'N3.D', 'N4.A', 'N4.B', 'N4.C', 'N4.D'],
    'ASSIM': ['MITHL-bb', 'MITHL-dd', 'MITHL-kk', 'MITHL-ll', 'MITHL-yy', 'MITHL-hh', 'MITHL-ww', 'MITHL-tt', 'MITHL-rr', 'MITHL-ðð', 'MITHL-ff', 'MITHL-33',
              'MTJNS-dt', 'MTJNS-td', 'MTJNS-tT', 'MTJNS-ṯð', 'MTJNS-lr', 'MTJNS-ðṮ', 'MTJNS-qk', 'MTJNS-bm', 't-assim'],
    'MADDA': ['MADD-hmz', 'MADD-hmz-A-sil', 'MADD-hmz-sp-1', 'MADD-hmz-sp-2', 'MADD-hmz-sp-3', 'MADD-hmz-sp-4', 'MADD-lzm', 'MADD-shdd-skn', 'MADD-sp-1', 'MADD-sp-2',
              'MADD-sp-3', 'MADD-sp-4', 'MADD-sp-5', 'MADD-sp-6', 'MADD-sp-7', 'MADD-sp-8', 'MADD-sp-9', 'MADD-sp-A', 'MADD-sp-B', 'MADD-sp-C', 'MADD-sp-D'],
    'SHAMS': ['SHMS'],
    'CLIT-H': ['HU', 'HI'],
    'MIN-W': ['min-u-1', 'min-u-2', 'min-u-3', 'min-u-4', 'min-u-5', 'min-u-6', 'min-u-7', 'min-u-8'],
    'MIN-Y': ['min-y-1', 'min-y-2', 'min-y-3', 'min-y-4', 'min-y-5', 'min-y-6', 'min-y-7', 'min-y-8', 'min-y-9', 'min-y-A'],
    'P_SIL': ['P-sil-1', 'P-sil-2'],
    'SIL': ['Sil-1', 'Sil-2', 'Sil-3', 'Sil-4', 'Sil-5', 'Sil-6', 'Sil-7', 'Sil-8', 'Sil-9', 'Sil-A', 'Sil-B', 'Sil-C', 'Sil-D', 'Sil-E', 'Sil-F', 'Sil-G'],
    'SAKT': ['sakt-1', 'sakt-2', 'sakt-3'],
    'HAPAX': ['hapax-1', 'hapax-2', 'hapax-3'],
}

#FIXME add reference
# According to Nicolai Sinai the following list seems to be additions:
# Q. 52:21, 53:23, 53:26–32, 69:7, 73:20, 74:31, 74:56, 78:37–40, 81:29, 84:25, 85:7–11, 87:7, 89:15–16, 89:23–24, 89:27–30, 90:17–20, 95:6, 97:4, and 103:3
EXCLUDE = [(52,21), (53,23), (53,26), (53,27), (53,28), (53,29), (53,30), (53,31), (53,32),
           (69,7),
           (73,20), (74,31), (74,56),
           (78,37), (78,38), (78,39), (78,40),
           (81,29),
           (84,25), (85,7), (85,8), (85,9), (85,10), (85,11),
           (87,7),
           (89,15), (89,16), (89,23), (89,24), (89,27), (89,28), (89,29), (89,30), (90,17), (90,18), (90,19), (90,20),
           (95,6),
           (97,4),
           (103,3)]

if __name__ == '__main__':

    parser = ArgumentParser(description='add or remove tajweed phonetic layer to orthography in Quranic text')
    parser.add_argument('infile', nargs='?', type=FileType('r'), default=sys.stdin, help='counts json file')
    parser.add_argument('outfile', help='csv outfile') #DEBUG
    parser.add_argument('--groups', action='store_true', help='aggregate the rules in logical groups and sum the counts')
    parser.add_argument('--rm_hapax', action='store_true', help='do not include hapax rule')
    parser.add_argument('--exclude', action='store_true', help='exclude verses that have been identified as possible later additions')
    parser.add_argument('--restrict', action='store_true', help='include ONLY verses have been identified as possible later additions')
    parser.add_argument('--chunks', metavar='SIZE', type=int, help='aggregate counts in chunks of words instead of by verses')
    parser.add_argument('--debug', action='store_true', help='show debugging info')
    args = parser.parse_args()

    counts = json.load(args.infile)

    RULE_MAPPER = {rule:gr for gr,rule_li in RULE_GROUPS.items() for rule in rule_li}

    if args.groups:
        _cnt = dict(zip(RULE_GROUPS, [0]*len(RULE_GROUPS)))
    else:
        _cnt = dict(zip(RULE_MAPPER, [0]*len(RULE_MAPPER)))

    cnt_inner = dict(_cnt)
    cnt_bound = dict(_cnt)

    rows = []
    for qara, _, _, qpal, qind in rasm(((1,1,1,1), (114,6,3,4)), paleo=True):

        if args.restrict and (qind[0], qind[1]) not in EXCLUDE:
            continue

        if args.exclude and (qind[0], qind[1]) in EXCLUDE:
            continue

        for rule, tokens in counts.items():

            if args.rm_hapax and rule in RULE_GROUPS['HAPAX']:
                continue

            if args.groups:
                rule = RULE_MAPPER[rule]

            for token in tokens:
                if tuple(token['ind']) == qind:

                    if token['bound']:
                        cnt_bound[rule] += token['cnt']
                    else:
                        cnt_inner[rule] += token['cnt']

        rows.append({**{'qindex': ':'.join(map(str, qind))},
                     **{k+'_I':v for k,v in cnt_inner.items()},
                     **{k+'_B':v for k,v in cnt_bound.items()}})

        cnt_inner = dict(_cnt)
        cnt_bound = dict(_cnt)

    if args.chunks:
        aux = []
        for i in range(0, len(rows), args.chunks):
            row_group = rows[i:i+args.chunks]
            qindex = row_group[0]['qindex']
            for r in row_group:
                r.pop('qindex')
            new_row = dict(zip(row_group[0].keys(), [0]*len(row_group[0])))
            for row in row_group:
                for k in row:
                    new_row[k] += row[k]
            new_row['qindex'] = qindex
            aux.append(new_row)
        rows = aux

    df = pd.DataFrame([r.values() for r in rows])
    df.columns = rows[0].keys()

    # move qindex from last column position to first position
    cols = df.columns.tolist()
    df = df[cols[-1:]+cols[:-1]]

    # remove columns that only contain zeros
    df = df.loc[:, (df!=0).any(axis=0)]

    df.to_csv(args.outfile, index=False)


import numpy as np
from collections import namedtuple
from abc import ABCMeta, abstractmethod, abstractstaticmethod

# 决策树结点
# Parameters
# ----------
# feature : 特征，需要进行比对的特征名
# val : 特征值，当特征为离散值时，如果对应的特征值等于val，将其放入左子树，否则放入右子树
# left : 左子树
# right : 右子树
# label : 所属的类
TreeNode = namedtuple("TreeNode", 'feature val left right label')

class DecisionTreeClassifier(object):
    """
    决策树分类器，采用 CART 算法训练
    """

    def __init__(self, max_depth=10,min_num_leaf=2):
        self.max_depth = max_depth
        self.min_num_leaf=min_num_leaf

    @staticmethod
    def devide_X(X_, feature, val):
        """切分集合
        :param X_: 被切分的集合, shape=[ni_samples, ni_features + 1]
        :param feature: 切分变量
        :param val: 切分变量的值
        :return: 左集合，有集合
        """
        return X_[X_[:, feature] == val], X_[X_[:, feature] != val]

    @staticmethod
    def gini(D):
        """求基尼指数 Gini(D)
        :param D: shape = [ni_samples]
        :return: Gini(D)
        """
        # 目前版本的 numpy.unique 不支持 axis 参数
        _, cls_counts = np.unique(D, return_counts=True)
        probability = cls_counts / cls_counts.sum()
        return 1 - (probability ** 2).sum()

    @staticmethod
    def congini(D_, val):
        """求基尼指数 Gini(D, A)
        :param D_: 被计算的列. shape=[ni_samples, 2]
        :param val: 被计算的列对应的切分变量
        :return: Gini(D, A)
        """
        left, right = D_[D_[:, 0] == val], D_[D_[:, 0] != val]
        return DecisionTreeClassifier.gini(left[:, -1]) * left.shape[0] / D_.shape[0] + \
               DecisionTreeClassifier.gini(right[:, -1]) * right.shape[0] / D_.shape[0]

    @staticmethod
    def get_fea_best_val(D_):
        """寻找当前特征对应的最优切分变量
        :param D_: 被计算的列. shape=[ni_samples, 2]
        :return: 最优切分变量的值和基尼指数的最大值
        """
        vals = np.unique(D_[:, :-1])
        tmp = np.array([DecisionTreeClassifier.congini(D_, val) for val in vals])
        return vals[np.argmax(tmp)], tmp.max()

    @staticmethod
    def get_best_index(X_, features):
        """寻找最优切分特征
        :param X_: 候选集 shape=[ni_samples, n_features + 1]
        :param features: 特征的候选集合
        :return: 最优切分特征的编号和特征值
        """
        ginis = [
            DecisionTreeClassifier.get_fea_best_val(
                np.c_[X_[:, i], X_[:, -1]]) for i in features]
        ginis = np.array(ginis)
        i = np.argmax(ginis[:, 1])
        return features[i], ginis[i, 0]

    def build(self, X_, features, depth=None):
        """建树
        :param X_: 候选集 shape=[ni_samples, n_features + 1]
        :param features: 候选特征集
        :param depth: 当前深度
        :return: 结点
        """
        print(X_.shape,features,depth)
        if np.unique(X_[:, -1]).shape[0] == 1:
            return TreeNode(None, None, None, None, X_[0, -1])
        if features.shape[0] == 0 or X_.shape[0]<=self.min_num_leaf or depth and depth >= self.max_depth:
            classes, classes_count = np.unique(X_[:, -1], return_counts=True)
            return TreeNode(None, None, None, None, classes[np.argmax(classes_count)])
        feature_index, val = DecisionTreeClassifier.get_best_index(X_, features)
        new_features = features[features != feature_index]
        del features
        left, right = DecisionTreeClassifier.devide_X(X_, feature_index, val)
        left_branch = self.build(left, new_features, depth + 1 if depth else None)
        right_branch = self.build(right, new_features, depth + 1 if depth else None)
        return TreeNode(feature_index, val, left_branch, right_branch, None)

    def fit(self, X, y):
        """
        :param X_: shape = [n_samples, n_features]
        :param y: shape = [n_samples]
        :return: self
        """
        features = np.arange(X.shape[1])
        X_ = np.c_[X, y]
        self.root = self.build(X_, features)
        return self

    def predict_one(self, x):
        p = self.root
        while p.label is None:
            p = p.left if x[p.feature] == p.val else p.right
        return p.label

    def predict(self, X):
        """
        :param X: shape = [n_samples, n_features]
        :return: shape = [n_samples]
        """
        return np.array([self.predict_one(x) for x in X])

cluster=np.array([
        [1,2,3,0],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,3,0],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,2,0],
        [2,2,3,1],
        [1,2,3,0],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,3,0],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,2,0],
        [2,2,3,1],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,2,0],
        [2,2,3,1],
        [1,2,3,0],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,3,0],
        [1,2,2,0],
        [2,2,3,1],
        [2,2,3,1],
        [2,3,4,0],
        [1,2,2,0],
         ])
train_x = cluster[:, 0:-1]
train_y = cluster[:, -1]
iv_clf = DecisionTreeClassifier()
iv_clf.fit(train_x, train_y)
print(iv_clf.predict_one([2, 2, 4]))


import ast
import re
import tokenize
import unicodedata

from sympy.parsing import sympy_parser
from sympy.core.basic import Basic

#####
# Process Unicode characters into equivalent allowed characters:
#####

# Unicode number and fraction name information:
_NUMBERS = {"ZERO": 0, "ONE": 1, "TWO": 2, "THREE": 3, "FOUR": 4, "FIVE": 5, "SIX": 6, "SEVEN": 7, "EIGHT": 8, "NINE": 9}
_FRACTIONS = {"HALF": 2, "THIRD": 3, "QUARTER": 4, "FIFTH": 5, "SIXTH": 6, "SEVENTH": 7, "EIGHTH": 8, "NINTH": 9, "TENTH": 10}
_FRACTIONS.update({"{}S".format(key): value for key, value in _FRACTIONS.items() if key != "HALF"})
# Major uppercase and lowercase Greek letters, excluding 'GREEK SMALL LETTER FINAL SIGMA' (\u03C2):
_GREEK_LETTERS_REGEX = r"[\u0391-\u03A9\u03B1-\u03C1\u03C3-\u03C9]"

def process_unicode_chars(match_object):
    """Clean a string of Unicode characters into allowed characters if possible."""
    result = ""
    prev_name = None
    for char in match_object.group(0):
        name = unicodedata.name(char, None)

        if name is None:
            result += char
        elif name.startswith("SUPERSCRIPT") and name.split()[1] in _NUMBERS:
            number = name.split()[1]
            # Check if this is a continuation of a exponent, or a new one.
            if prev_name is not None and prev_name.startswith("SUPERSCRIPT"):
                result += "{0:d}".format(_NUMBERS[number])
            else:
                result += "**{0:d}".format(_NUMBERS[number])
        elif name.startswith("SUBSCRIPT") and name.split()[1] in _NUMBERS:
            number = name.split()[1]
            # Check if this is a continuation of a subscript, or a new one.
            if prev_name is not None and prev_name.startswith("SUBSCRIPT"):
                result += "{0:d}".format(_NUMBERS[number])
            else:
                result += "_{0:d}".format(_NUMBERS[number])
        elif name.startswith("VULGAR FRACTION"):
            numerator_name = name.split()[2]
            denominator_name = name.split()[3]
            if numerator_name in _NUMBERS and denominator_name in _FRACTIONS:
                result += "({0:d}/{1:d})".format(_NUMBERS[numerator_name], _FRACTIONS[denominator_name])
            else:
                result += char
        elif name in ["MULTIPLICATION SIGN", "ASTERISK OPERATOR"]:
            result += "*"
        elif name in ["DIVISION SIGN", "DIVISION SLASH"]:
            result += "/"
        elif name in ["LESS-THAN OR EQUAL TO", "LESS-THAN OR SLANTED EQUAL TO"]:
            result += "<="
        elif name in ["GREATER-THAN OR EQUAL TO", "GREATER-THAN OR SLANTED EQUAL TO"]:
            result += ">="
        elif name in ["LOGICAL AND", "N-ARY LOGICAL AND"]:
            result += "&"
        elif name in ["LOGICAL OR", "N-ARY LOGICAL OR"]:
            result += "|"
        elif name in ["XOR", "CIRCLED PLUS"]:
            result += "^"
        elif name == "NOT SIGN":
            result += "~"
        elif re.match(_GREEK_LETTERS_REGEX, char):
            # There are more Greek letters with names like the below than usually
            # supported by maths systems. The regex is a quick way to filter by Unicode
            # codepoint.
            if name.startswith("GREEK CAPITAL LETTER"):
                result += "({})".format(name.replace("GREEK CAPITAL LETTER ", "").title())
            elif name.startswith("GREEK SMALL LETTER"):
                result += "({})".format(name.replace("GREEK SMALL LETTER ", "").lower())
            else:
                # Something is wrong, skip character:
                result += char
        else:
            result += char

        prev_name = name
    return result

#####
# Customised SymPy Internals:
#####

# What constitutes a relation?
RELATIONS = {ast.Lt: "<", ast.LtE: "<=", ast.Gt: ">", ast.GtE: ">="}

def evaluateFalse(s):
    """Replaces operators with the SymPy equivalents and set evaluate=False.

       Unlike the built-in evaluateFalse(...), we want to use a slightly more
       sophisticated EvaluateFalseTransformer and make operators AND functions
       evaluate=False.
        - 's' should be a string of Python code for the maths abstract syntax tree.
    """
    node = ast.parse(s)
    node = _EvaluateFalseTransformer().visit(node)
    # node is a Module, we want an Expression
    node = ast.Expression(node.body[0].value)

    return ast.fix_missing_locations(node)

class _EvaluateFalseTransformer(sympy_parser.EvaluateFalseTransformer):
    """Extend default SymPy EvaluateFalseTransformer to affect functions too.

       The SymPy version does not force function calls to be 'evaluate=False',
       which means expressions like "log(x, 10)" get simplified to "log(x)/log(10)"
       or "cos(-x)" becomes "cos(x)". For our purposes, this is unhelpful and so
       we also prevent this from occuring.

       Currently there is a list of functions not to transform, because some do
       not support the "evaluate=False" argument. This isn't particularly nice or
       future proof!
    """

    _evaluate_false_keyword = ast.keyword(arg='evaluate', value=ast.NameConstant(value=False, ctx=ast.Load()))
    _one = ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()), args=[ast.Num(n=1)], keywords=[])
    _minus_one = ast.UnaryOp(op=ast.USub(), operand=_one)
    _bool_ops = {
        ast.And: "And",
        ast.Or: "Or"
    }
    _bool_values = {
        # CPython 3.8 and later no longer allow overridding of "True" and "False" as names,
        # so we must use "true" and "false" instead.
        # https://github.com/python/cpython/blob/3.8/Python/ast.c#L28-L39
        True: ast.Name(id="true", ctx=ast.Load()),
        False: ast.Name(id="false", ctx=ast.Load())
    }

    def visit_Call(self, node):
        """Ensure all function calls are 'evaluate=False'."""
        # Since we have overridden the visit method, we are now responsible for
        # ensuring all child nodes are visited too. This is done most simply by
        # calling generic_visit(...) on ourself:
        self.generic_visit(node)
        # FIXME: Some functions cannot accept "evaluate=False" as an argument
        # without their __new__() method raising a TypeError. There is probably
        # some underlying reason which we could take into account of.
        # For now, ignore those known to be problematic:
        _ignore_functions = ["Integer", "Float", "Symbol", "factorial"]
        if node.func.id in _ignore_functions:
            # print("\tIgnoring function: {}".format(node.func.id))
            pass
        else:
            # print("\tModifying function: {}".format(node.func.id))
            node.keywords.append(self._evaluate_false_keyword)
        # We must return the node, modified or not:
        return node

    def visit_Constant(self, node):
        """Ensure boolean constants can be sympy classes if needed."""
        # As above, must ensure child nodes are visited:
        self.generic_visit(node)
        # Replace the built-in True/False with names we can override if needed:
        if node.value in self._bool_values:
            return self._bool_values[node.value]
        else:
            return node

    def visit_Compare(self, node):
        """Ensure all comparisons use sympy classes with 'evaluate=False'."""
        # Can't cope with comparing multiple inequalities:
        if len(node.comparators) > 1:
            raise TypeError("Cannot parse nested inequalities!")
        # As above, must ensure child nodes are visited:
        self.generic_visit(node)
        # Use the custom Equals class if equality, otherwise swap with a known relation:
        operator_class = node.ops[0].__class__
        if isinstance(node.ops[0], ast.Eq):
            return ast.Call(func=ast.Name(id='Eq', ctx=ast.Load()), args=[node.left, node.comparators[0]], keywords=[self._evaluate_false_keyword])
        elif operator_class in RELATIONS:
            return ast.Call(func=ast.Name(id='Rel', ctx=ast.Load()), args=[node.left, node.comparators[0], ast.Str(RELATIONS[operator_class])], keywords=[self._evaluate_false_keyword])
        else:
            # An unknown type of relation. Leave alone:
            return node

    def sympy_visit_BinOp(self, node):
        """Convert some operators to SymPy equivalents.

           This method is mostly copied from SymPy directly, but there is a fix
           to the nesting of Mul not yet in the upstream!
        """
        if node.op.__class__ in self.operators:
            sympy_class = self.operators[node.op.__class__]
            right = self.visit(node.right)
            left = self.visit(node.left)
            if isinstance(node.left, ast.UnaryOp) and not isinstance(node.right, ast.UnaryOp) and sympy_class in ('Mul',):
                left, right = right, left
            if isinstance(node.op, ast.Sub):
                right = ast.Call(
                    func=ast.Name(id='Mul', ctx=ast.Load()),
                    # Ensure Mul objects don't end up nested:
                    args=self.flatten([self._minus_one, right], 'Mul'),
                    keywords=[self._evaluate_false_keyword]
                )
            if isinstance(node.op, ast.Div):
                if isinstance(node.left, ast.UnaryOp):
                    if isinstance(node.right, ast.UnaryOp):
                        left, right = right, left
                    left = ast.Call(
                        func=ast.Name(id='Pow', ctx=ast.Load()),
                        args=[left, self._minus_one],
                        keywords=[self._evaluate_false_keyword]
                    )
                else:
                    right = ast.Call(
                        func=ast.Name(id='Pow', ctx=ast.Load()),
                        args=[right, self._minus_one],
                        keywords=[self._evaluate_false_keyword]
                    )

            new_node = ast.Call(
                    func=ast.Name(id=sympy_class, ctx=ast.Load()),
                    args=[left, right],
                    keywords=[self._evaluate_false_keyword]
                )

            if sympy_class in ('Add', 'Mul'):
                # Denest Add or Mul as appropriate
                new_node.args = self.flatten(new_node.args, sympy_class)

            return new_node
        return node

    def visit_BinOp(self, node):
        """Ensure bitwise operations are modified into SymPy operations.

            This function also calls a SymPy function to convert Add, Sub, Mul
            and Div into SymPy classes.
        """
        node_class = node.op.__class__
        # "Implies", which overloads bit-shifting, mustn't get simplified:
        if node_class in [ast.LShift, ast.RShift]:
            # As above, must ensure child nodes are visited:
            right = self.generic_visit(node.right)
            left = self.generic_visit(node.left)
            if node_class is ast.LShift:
                left, right = right, left
            return ast.Call(func=ast.Name(id="Implies", ctx=ast.Load()), args=[left, right], keywords=[self._evaluate_false_keyword])
        # "Xor" must be transformed from Bitwise to Boolean, and not simplified either:
        elif node_class == ast.BitXor:
            right = self.generic_visit(node.right)
            left = self.generic_visit(node.left)
            return ast.Call(func=ast.Name(id="Xor", ctx=ast.Load()), args=[left, right], keywords=[self._evaluate_false_keyword])
        else:
            # Otherwise we want ensure the parent SymPy method runs on this node,
            # to save re-writing that code here:
            return self.sympy_visit_BinOp(node)

    def visit_BoolOp(self, node):
        """Ensure And and Or are not simplified."""
        # As above, must ensure child nodes are visited:
        self.generic_visit(node)
        # Fix the boolean operations to SymPy versions to ensure no simplification:
        node_class = node.op.__class__
        if node_class in self._bool_ops:
            return ast.Call(func=ast.Name(id=self._bool_ops[node_class], ctx=ast.Load()), args=node.values, keywords=[self._evaluate_false_keyword])
        else:
            # An unknown type of boolean operation. Leave alone:
            return node

    def visit_UnaryOp(self, node):
        """Ensure boolean Not is not simplified and unary minus is consistent."""
        node_class = node.op.__class__
        # As above, must ensure child nodes are visited:
        self.generic_visit(node)
        # Fix the boolean Not to the SymPy version to ensure no simplification:
        if node_class in [ast.Not, ast.Invert]:
            return ast.Call(func=ast.Name(id="Not", ctx=ast.Load()), args=[node.operand], keywords=[self._evaluate_false_keyword])
        # Replace all uses of unary minus with multiplication by minus one for
        # consistency reasons:
        elif node_class in [ast.USub]:
            return ast.Call(func=ast.Name(id='Mul', ctx=ast.Load()),
                            # Ensure Mul objects don't end up nested:
                            args=self.flatten([self._minus_one, node.operand], 'Mul'),
                            keywords=[self._evaluate_false_keyword])
        else:
            # Only interested these; leave everything else alone:
            return node

#    def visit(self, node):
#        """Visit every node in the tree."""
#        before = ast.dump(node)
#        # MUST call super method to ensure tree is iterated over correctly!
#        node = super().visit(node)
#        after = ast.dump(node)
#        print(node.__class__)
#        print("{}\n==>\n{}\n\n".format(before, after))
#        return node

#####
# Custom SymPy Parser Transformations:
#####

def auto_symbol(tokens, local_dict, global_dict):
    """Replace the sympy builtin auto_symbol with a much more aggressive version.

       We have to replace this, because SymPy attempts to be too accepting of
       what it considers to be valid input and allows Pythonic behaviour.
       We only really want pure mathematics notations where possible!
    """
    result = []
    # As with all tranformations, we have to iterate through the tokens and
    # return the modified list of tokens:
    for tok in tokens:
        tokNum, tokVal = tok
        if tokNum == tokenize.NAME:
            name = tokVal
            # Check if the token name is in the local/global dictionaries.
            # If it is, convert it correctly, otherwise leave untouched.
            if name in local_dict:
                result.append((tokenize.NAME, name))
                continue
            elif name in global_dict:
                obj = global_dict[name]
                if isinstance(obj, (Basic, type)) or callable(obj):
                    # If it's a function/basic class, don't convert it to a Symbol!
                    result.append((tokenize.NAME, name))
                    continue
            result.extend([
                (tokenize.NAME, 'Symbol'),
                (tokenize.OP, '('),
                (tokenize.NAME, repr(str(name))),
                (tokenize.OP, ')'),
            ])
        else:
            result.append(tok)

    return result

def fix_booleans(tokens, local_dict, global_dict):
    """
    Combines several fixes to the tokenising of boolean-like inputs, for efficiency.

     - Fix the precedence issues with "or", "and" and "not" being looser
         than equals, which led to problems such as
         "A == B or C" incorrectly becoming "Or(Eq(A, B), C)",
         by changing them into bitwise operators to be fixed post-parsing.
     - Add an xor keyword by tokenising it into a bitwise XOR to be treated
         in the same way as the above bitwise operators must be.
     - Convert 0 and 1 to be False and True respectively.
    """
    result = []
    _bool_to_bit_map = {
        "xor": "^",
        "or": "|",
        "and": "&",
        "not": "~"
    }
    _integer_map = {
        "0": "false",
        "1": "true"
    }

    for tok in tokens:
        tokNum, tokVal = tok
        tokVal = tokVal.lower()
        if tokNum == tokenize.NAME and tokVal and tokVal in _bool_to_bit_map:
            result.append((tokenize.OP, _bool_to_bit_map[tokVal]))
        elif tokNum == tokenize.NUMBER and tokVal in _integer_map:
            result.append((tokenize.NAME, _integer_map[tokVal]))
        else:
            result.append(tok)

    return result

# This transformation is left for reference, and excluded from coverage reports:
def split_symbols_implicit_precedence(tokens, local_dict, global_dict):  # pragma: no cover
    """Replace the sympy builtin split_symbols with a version respecting implicit multiplcation.

       By replacing this we can better cope with expressions like 1/xyz being
       equivalent to 1/(x*y*z) rather than (y*z)/x as is the default. However it
       cannot address issues like 1/2x becoming (1/2)*x rather than 1/(2*x), because
       Python's tokeniser does not respect whitespace and so cannot distinguish
       between '1/2 x' and '1/2x'.

       This transformation is unlikely to be used, but is provided as proof of concept.
    """
    result = []
    split = False
    split_previous = False
    for tok in tokens:
        if split_previous:
            # throw out closing parenthesis of Symbol that was split
            split_previous = False
            continue
        split_previous = False
        if tok[0] == tokenize.NAME and tok[1] == 'Symbol':
            split = True
        elif split and tok[0] == tokenize.NAME:
            symbol = tok[1][1:-1]
            if sympy_parser._token_splittable(symbol):
                # If we're splitting this symbol, wrap it in brackets by adding
                # them before the call to Symbol:
                result = result[:-2] + [(tokenize.OP, '(')] + result[-2:]
                for char in symbol:
                    if char in local_dict or char in global_dict:
                        # Get rid of the call to Symbol
                        del result[-2:]
                        result.extend([(tokenize.NAME, "{}".format(char)),
                                       (tokenize.NAME, 'Symbol'), (tokenize.OP, '(')])
                    else:
                        result.extend([(tokenize.NAME, "'{}'".format(char)), (tokenize.OP, ')'),
                                       (tokenize.NAME, 'Symbol'), (tokenize.OP, '(')])
                # Delete the last two tokens: get rid of the extraneous
                # Symbol( we just added
                # Also, set split_previous=True so will skip
                # the closing parenthesis of the original Symbol
                del result[-2:]
                split = False
                split_previous = True
                # Then close the extra brackets we added:
                result.append((tokenize.OP, ')'))
                continue
            else:
                split = False
        result.append(tok)
    return result


import os
import zipfile

def unzip(filename: str, extract_to: str) -> None:
    """
    This method run unzip a file to specified path
    :param filename:    Path/filename of zip file
    :param extract_to:  Path with name of output folder
    :return: None
    """

    this_folder = os.path.dirname(os.path.abspath(__file__))
    file = os.path.join(this_folder, filename)

    with zipfile.ZipFile(file, "r") as zip_ref:
        zip_ref.extractall(extract_to)


import numpy as np
import glog
import pandas as pd
import os
import gzip

def export_roi_gene(file_path: str, roi: list):
    """
    Args:
        file_path: path of gene file
        roi: [x0, y0, w, h]
    Returns: None
    """

    if file_path.endswith('.gz'):
        f = gzip.open(file_path, 'rb')
    else: f = open(file_path, 'rb')

    glog.info('Start parse head info of file <{}>'.format(file_path))
    header = ''
    num_of_header_lines = 0
    eoh = 0
    for i, l in enumerate(f):
        l = l.decode("utf-8")  # read in as binary, decode first
        if l.startswith('#'):  # header lines always start with '#'
            header += l
            num_of_header_lines += 1
            eoh = f.tell()  # get end-of-header position
        else: break
    # find start of expression matrix
    f.seek(eoh)

    x0, y0, w, h = roi
    typeColumn = {
                    "geneID": 'str',
                    "x": np.uint32,
                    "y": np.uint32,
                    "values": np.uint32,
                    "UMICount": np.uint32,
                    "MIDCount": np.uint32,
                    "MIDCounts": np.uint32
                    }

    glog.info("Loading matrix data...")
    df = pd.read_csv(file_path, header=num_of_header_lines, sep='\t', dtype=typeColumn)

    if "UMICount" in df.columns: df = df.rename(columns={'UMICount':'MIDCount'})
    if "MIDCounts" in df.columns: df = df.rename(columns={'MIDCounts':'MIDCount'})

    df = df.drop(df[(df['x'] < x0) | (df['x'] > (x0 + w))].index)
    df = df.drop(df[(df['y'] < y0) | (df['y'] > (y0 + h))].index)
    df['x'] -= df['x'].min()
    df['y'] -= df['y'].min()
    output = os.path.join(os.path.dirname(file_path), 'SS2000.gem')
    glog.info('Write ROI gene file to {}'.format(output))
    # df.to_pickle(output, compression='gzip')

    df.to_csv(output, sep='\t', index=False)
    # with gzip.open(output.replace('.gem', '.gem.gz'), 'wb') as fd:
    #     fd.write(df)

def main():
    file_path = r'D:\code\mine\github\SS200000213BR_C5.gem.gz'
    roi = [12030, 16167, 5820, 4380]
    export_roi_gene(file_path, roi)

if __name__ == '__main__': main()


from django.template import Library
from hx_lti_initializer.models import LTIProfile

register = Library()

@register.filter_function
def list_of_possible_admins(already_in_course):
    list_of_usernames_already_in_course = []
    list_of_unique_names = []
    result = []

    for profile in LTIProfile.objects.all():
        if profile.id in already_in_course:
            list_of_usernames_already_in_course.append(profile.user.username)
        if (
            profile.user.username not in list_of_unique_names
            and "preview:" not in profile.user.username
        ):
            list_of_unique_names.append(profile.user.username)

    for name in list_of_unique_names:
        result.append((name in list_of_usernames_already_in_course, name))

    return result


import numpy as np
from scipy.special import factorial

ident = 'dick6D'
d = 6
title_plot = r'$f_6(u)=\left(\prod_{i=2}^6 u_i^{i-1} \right) \exp\left\{\prod_{i=1}^6 u_i\right\}$'
mat_folder = 'simuDick/d6'
true_val = np.exp(1.) - np.sum(1. / factorial(np.arange(6)))
orders = [1, 2, 4, 6, 8]
min_neval = 100
max_neval = 2 * 10**7
nks = 20
nreps = 50

def phi(u):
    pu = 1.
    for i in range(1, d):
        pu = pu * u[:, i]**i
    return pu * np.exp(np.prod(u, axis=-1))


'''
Created on 08.02.2016.

@author: Lazar
'''
from concepts.row import Row
from textx.exceptions import TextXSemanticError

class View(object):
    basic_type_names = ['text', 'number', 'checkbox', 'link',
                        'email', 'password', 'menuitem', 'menu',
                        'button', 'radio', 'form', 'label', 'image',
                        'date', 'combobox', 'list', 'table',
                        'thumbnail', 'row', 'multilist']

    def __init__(self, parent, name, views, object=None, query=None):
        self.name = name
        self.views = views
        self.parent = parent
        self.object = object
        self.query = query
        self.rows = []
        self.path = {}
        self.subviews = []

        seen = set()

        row = Row(self, 1)
        last_row_number = 1
        for view_selector in views:
            if view_selector.__class__.__name__ == 'RowSeparator':
                if view_selector.number < 0:
                    row_number = last_row_number
                    last_row_number += 1
                else:
                    if view_selector.number and view_selector.number not in seen:
                        seen.add(view_selector.number)
                    else:
                        line, col = self._tx_metamodel.parser.pos_to_linecol(self._tx_position)
                        raise TextXSemanticError("ERROR: (at %d, %d) More than one row at position %d." %
                                                 (line, col, view_selector.number))
                    last_row_number = view_selector.number
                    row_number = view_selector.number
                self.rows.append(row)
                row = Row(self, row_number)
            else:
                row.selectors.append(view_selector)
                if view_selector.__class__.__name__ == 'ViewInView':
                    self.subviews.append(view_selector.selector)
        if row not in self.rows:
            self.rows.append(row)

    def __str__(self):
        return self.name

    def accept(self, visitor):
        return visitor.visit_view(self)


import sys
from collections import deque
input = sys.stdin.readline

def check(a, b, size):
    return 0 == psa[a + size - 1][b + size - 1] - psa[a - 1][b + size - 1] - psa[a + size - 1][b - 1] + psa[a - 1][b - 1]

moves = ((1, 0), (0, 1), (-1, 0), (0, -1))
n, m = [int(x) for x in input().split()]
psa = [[0] * (m + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
    line = input()[:-1]
    for j in range(1, m + 1):
        v = line[j - 1] == "X"
        psa[i][j] = psa[i - 1][j] + psa[i][j - 1] - psa[i - 1][j - 1] + v

low, high = 1, 0
while high < min(n, m) and check(1, 1, high + 1):
    high += 1

while low <= high:
    size = (low + high) // 2
    queue = deque([[1, 1]])
    visited = [0] * ((n + 1) * (m + 1))
    visited[m + 2] = 1
    bottom, right = n - size + 1, m - size + 1
    while queue:
        a, b = queue.popleft()
        if a == bottom and b == right:
            low = size + 1
            break
        for x, y in moves:
            x = x + a
            y = y + b
            if 1 <= x <= bottom and 1 <= y <= right and not visited[x * (m + 1) + y] and check(x, y, size):
                visited[x * (m + 1) + y] = 1
                queue.append([x, y])
    else:
        high = size - 1
print(high)


# django imports
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import permission_required
from django.core.urlresolvers import reverse
from django.db import IntegrityError
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template import RequestContext
from django.template.loader import render_to_string

# lfs imports
from lfs.catalog.models import Product
from lfs.catalog.models import ProductPropertyValue
from lfs.catalog.models import Property
from lfs.catalog.models import PropertyGroup
from lfs.core.signals import product_removed_property_group

@permission_required("manage_shop", login_url="/login/")
def manage_properties(request, product_id, template_name="manage/product/properties.html"):
    """
    """
    product = get_object_or_404(Product, pk=product_id)

    # Generate list of product property groups; used for enter value
    product_property_groups = []
    for property_group in product.property_groups.all():
        properties = []
        for property in property_group.properties.order_by("groupspropertiesrelation"):
            # Try to get the value, if it already exists.
            try:
                ppv = ProductPropertyValue.objects.get(property = property, product=product)
            except ProductPropertyValue.DoesNotExist:
                value = ""
            else:
                value = ppv.value

            # mark selected options "selected"
            options = []
            for option in property.options.all():
                options.append({
                    "id"       : option.id,
                    "name"     : option.name,
                    "selected" : str(option.id) == value
                })

            properties.append({
                "id"      : property.id,
                "name"    : property.name,
                "type"    : property.type,
                "options" : options,
                "value"   : value,
            })

        product_property_groups.append({
            "id"   : property_group.id,
            "name" : property_group.name,
            "properties" : properties,
        })

    # Generate list of all property groups; used for group selection
    product_property_group_ids = [p["id"] for p in product_property_groups]
    shop_property_groups = []
    for property_group in PropertyGroup.objects.all():

        shop_property_groups.append({
            "id" : property_group.id,
            "name" : property_group.name,
            "selected" : property_group.id in product_property_group_ids,
        })

    return render_to_string(template_name, RequestContext(request, {
        "product" : product,
        "product_property_groups" : product_property_groups,
        "shop_property_groups" : shop_property_groups,
    }))

@permission_required("manage_shop", login_url="/login/")
def update_property_groups(request, product_id):
    """Updates property groups for the product with passed id.
    """
    selected_group_ids = request.POST.getlist("selected-property-groups")

    for property_group in PropertyGroup.objects.all():
        # if the group is within selected groups we try to add it to the product
        # otherwise we try do delete it
        if str(property_group.id) in selected_group_ids:
            try:
                property_group.products.get(pk=product_id)
            except ObjectDoesNotExist:
                property_group.products.add(product_id)
        else:
            property_group.products.remove(product_id)
            product = Product.objects.get(pk=product_id)
            product_removed_property_group.send([property_group, product])

    url = reverse("lfs_manage_product", kwargs={"product_id" : product_id})
    return HttpResponseRedirect(url)

@permission_required("manage_shop", login_url="/login/")
def update_properties(request, product_id):
    """Updates properties for product with passed id.
    """
    # Update properties' values
    for key, value in request.POST.items():
        if key.startswith("property") == False:
            continue

        property_id = key.split("-")[1]
        property = get_object_or_404(Property, pk=property_id)
        product = get_object_or_404(Product, pk=product_id)

        try:
            ppv = ProductPropertyValue.objects.get(product = product_id, property = property_id)
        except ProductPropertyValue.DoesNotExist:
            if not property.is_valid_value(value):
                value = 0
            ProductPropertyValue.objects.create(product=product, property = property, value=value)
        else:
            if not property.is_valid_value(value):
                value = 0

            ppv.value = value
            ppv.save()

    url = reverse("lfs_manage_product", kwargs={"product_id" : product_id})
    return HttpResponseRedirect(url)


from selenium import webdriver

from amazon_pages.home_page import HomePage

def test__amazon():
    """ Go to book_page categorie, add first item to cart, change quantity to 2"""
    driver = webdriver.Chrome()
    home = HomePage(driver)
    cart_page = home.accept_cookie()\
        .open_all_book()\
        .select_first_book_nouveautes()\
        .add_to_cart().open_cart()\
        .set_quantity(2)
    assert cart_page.get_quantity() == "2"


from matplotlib import pyplot as plt

def visualize(flight):
    altitude = [t.position.y for t in flight]
    velocity = [t.velocity.y for t in flight]
    time = list(range(len(flight)))
    plt.figure()
    plt.subplot(211)
    plt.xlabel("Time (secs)")
    plt.ylabel("Altitude(m)")
    plt.plot(time, altitude)
    plt.subplot(212)
    plt.xlabel("Time (secs)")
    plt.ylabel("Velocity(m/s)")
    plt.plot(time,velocity)
    plt.show()


"""
Class for acting as a server inside of a simpy simulation. This server is nothing
more than a resource with some additional patches.

@author Tycho Atsma <tycho.atsma@gmail.com>
@file   lib/Server.py
"""

# dependencies
from simpy import PreemptiveResource
from numpy.random import exponential, uniform

class Server(PreemptiveResource):

    def __init__(self, *args, **kwargs):
        """
        Constructor.

        Parameters
        ----------
        @see simpy.Resource

        Keyworded arguments
        -------------------
        uuid: string
            UUID as identifier for this server.
        kind: string
            Kind of the server (e.g. balance, regular, database).

        Optiomal Keyworded arguments
        memmax: integer:
            Set scalar how many times the max capacity fits in memory
            Default = 10
        """
        # call the parent constructor
        super().__init__(*args)

        # reference to the environment and capacity
        self._env = args[0]

        # Set memory max capacity
        if 'memmax' in kwargs:
            self.memmax = kwargs['memmax']
        else:
            # Default is 10 times the capacity
            self.memmax = 10

        # Set latencyscaler capacity
        if 'latencyscaler' in kwargs:
            self.latencyscaler = kwargs['latencyscaler']
        else:
            # Default is 1 times the capacity
            self.latencyscaler = 1

        # setup the initial state of this server
        self._state = {
            'name':  "%s#%s" % (kwargs['kind'], kwargs['uuid']),
            'kind':  kwargs['kind'],
            'queue': len(self.queue),
            'users': self.count,
            'cpu': 0,
            'memory': 0,
            'latency': 0,
        }

    def environment(self):
        """
        Getter to expose the environment.

        Returns
        -------
        Environment
        """
        return self._env

    def get_capacity(self):
        """
        Getter to expose the server capacity.

        Returns
        -------
        int
        """
        return self.capacity

    def request(self, *args, **kwargs):
        """
        Method override to request a context in which this resource can be accessed.
        @see https://simpy.readthedocs.io/en/latest/api_reference/simpy.resources.html#simpy.resources.resource.Request

        Keyworded parameters
        ----------
        priority: int
            See simpy.PreemptiveResource.request.
        """

        # parse parameters for the super class method
        priority = kwargs['priority'] if 'priority' in kwargs else 1

        # call the parent class for the original method
        return super().request(priority=priority)

    def state(self):
        """
        Method to expose the current state of a server.

        Returns
        -------
        dict
        """

        self._state.update(queue=len(self.queue),
                           users=self.count,
                           cpu=self.cpu(),
                           memory=self.memory(),
                           latency=self.latency()
                           )

        return self._state

    def latency(self):
        """
        Method to expose the server latency.

        Returns
        -------
        float
        """
        # state = self.state()

        # Temporalily update the amount of users by adding one to reflect the
        # incoming transaction

        # expose a random value based on an exponential distribution, scaled
        # with the cpu usage
        # return exponential(self.cpu())

        latency = exponential(self.cpu()) * self.latencyscaler

        return latency

    def memory(self):
        """
        Method to expose the server's memory usage.

        Returns
        -------
        float
        """
        # # get the current state
        # state = self.state()

        # expose the calculated memory usage based on the queue, users, and
        # scaled capacity
        return (self.count + len(self.queue)) / (self.capacity * self.memmax)

    def cpu(self):
        """
        Method to expose the server's cpu usage.

        Optional parameters:
        addition (defaul = 0), possibility to add user to keep values non-zero

        Returns
        -------
        float
        """
        # # get the current state
        # state = self.state()

        # expose the cpu load
        return self.count / self.capacity

    def faulty_patch(self, state):
        # error function to increase the latency scaler tenfold when true
        if state:
            self.latencyscaler = 10
        if not state:
            self.latencyscaler = 1


from pathlib import Path

import pytest

from helpers.regression import verify_output

RINOH_PATH = Path(__file__).parent / 'rinoh'
OUTPUT_PATH = Path(__file__).parent / 'output'

def test_version(script_runner):
    ret = script_runner.run('rinoh', '--version')
    assert ret.success
    assert ret.stderr == ''

def collect_tests():
    for rst_path in sorted(RINOH_PATH.glob('*.rst')):
        yield rst_path.stem

@pytest.mark.parametrize('test_name', collect_tests())
def test_rinoh(script_runner, test_name):
    rst_path = Path(test_name + '.rst')
    args = []
    templconf_path = rst_path.with_suffix('.rtt')
    if (RINOH_PATH / templconf_path).exists():
        args += ['--template', str(templconf_path)]
    stylesheet_path = rst_path.with_suffix('.rts')
    if (RINOH_PATH / stylesheet_path).exists():
        args += ['--stylesheet', str(stylesheet_path)]
    output_dir = OUTPUT_PATH / ('rinoh_' + test_name)
    output_dir.mkdir(parents=True, exist_ok=True)
    ret = script_runner.run('rinoh', *args, str(rst_path),
                            '--output', str(output_dir), cwd=RINOH_PATH)
    assert ret.success
    verify_output(test_name, output_dir, RINOH_PATH)


""""
MeGaNeKo 2022 - https://github.com/MeGaNeKoS/Discord-Bot-Template
Description:
This is a template to create your own discord bot in python.
Version: 1.0
"""
import logging

class STDERRLogger:
    def __init__(self):
        self.logger = logging.getLogger("STDERR")
        formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')

        file_handler = logging.FileHandler('stderr.log')
        file_handler.setFormatter(formatter)

        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(formatter)

        self.logger.addHandler(file_handler)
        self.logger.addHandler(stream_handler)

        self.buf = []

    def write(self, msg):

        if msg.endswith('\n'):
            self.buf.append(msg.removesuffix('\n'))
            self.logger.error(''.join(self.buf))
            self.buf = []
        else:
            self.buf.append(msg)

    def flush(self):
        pass


from collections import defaultdict

f = open('/Users/moishe/src/aoc-21/day-10/input/input.txt')

xlat_closer = {
  '>': '<',
  ']': '[',
  '}': '{',
  ')': '('
}

score_lookup = {
  ')': 3,
  ']': 57,
  '}': 1197,
  '>': 25137
}

counters = defaultdict(int)
score = 0
for l in f:
  l = l.rstrip()
  current_open = []
  for (idx, c) in enumerate(l):
    if c in ['(', '[', '<', '{']:
      current_open.append(c)
    else:
      last_open = current_open.pop()
      if last_open != xlat_closer[c]:
        score += score_lookup[c]
        print("corrupt closer: expected %c to be closed but found %c instead" % (last_open, c))

print(score)


import falcon
from math import sqrt
from wsgiref.simple_server import make_server

class Calc():
    def on_get(self, req, resp):
        qs = req.params
        resp.body = "Waiting for input\n"
        resp.status = falcon.HTTP_200

    def on_post(self, req, resp):
        chunk = req.stream.read(4096)
        values = chunk.split(b'&')
        a = int(values[0].split(b'=')[1])
        b = int(values[1].split(b'=')[1])
        c = int(values[2].split(b'=')[1])
        resp.body = self.calc_x(a,b,c)
        resp.status = falcon.HTTP_200

    def calc_determinant(self,a, b, c):
        return b*b - 4*a*c

    def calc_x(self,a,b,c):
        determinant = self.calc_determinant(a,b,c)
        if determinant > 0:
            x1 = (-b + sqrt(determinant)) / (2*a)
            x2 = (-b - sqrt(determinant)) / (2*a)
            return "Roots are real and different.\nx1 = {}\nx2 = {}".format(x1,x2)
        elif determinant == 0:
            x1 = (-b + sqrt(determinant)) / (2*a)
            return "Roots are real and same.\nx1 = x2 = {}".format(x1)
        else:
            realPart = -b/(2*a)
            imaginaryPart =sqrt(-determinant)/(2*a)
            return "Roots are complex and different.\nx1 = {0}+{1}i\nx2 = {0}-{1}i\n".format(realPart,imaginaryPart)

api = falcon.API()
r = Calc()
api.add_route('/',r)

ser = make_server('', 8080, api)
ser.serve_forever()


from multiprocessing import Pool
from argparse import ArgumentParser
from tbselenium.tbdriver import TorBrowserDriver
from tbselenium.utils import launch_tbb_tor_with_stem
from tbselenium.common import STEM_SOCKS_PORT, USE_RUNNING_TOR,\
    STEM_CONTROL_PORT

JOBS_IN_PARALLEL = 3

def run_in_parallel(inputs, worker, no_of_processes=JOBS_IN_PARALLEL):
    p = Pool(no_of_processes)
    p.map(worker, inputs)

def visit_check_tpo_with_stem(tbb_dir):
    url = "https://check.torproject.org"
    with TorBrowserDriver(tbb_dir,
                          socks_port=STEM_SOCKS_PORT,
                          control_port=STEM_CONTROL_PORT,
                          tor_cfg=USE_RUNNING_TOR) as driver:
        driver.load_url(url, wait_on_page=3)
        print(driver.find_element_by("h1.on").text)
        print(driver.find_element_by(".content > p").text)

def launch_browsers_in_parallel(tbb_path):
    tor_process = launch_tbb_tor_with_stem(tbb_path=tbb_path)
    run_in_parallel(JOBS_IN_PARALLEL * [tbb_path],
                    visit_check_tpo_with_stem)
    tor_process.kill()

def main():
    desc = "Visit check.torproject.org website running 3 browsers in parallel"
    parser = ArgumentParser(description=desc)
    parser.add_argument('tbb_path')
    args = parser.parse_args()
    launch_browsers_in_parallel(args.tbb_path)

if __name__ == '__main__':
    main()


from collections import deque

def neighbors(position: tuple[int, int, int]) -> list[tuple[int, int, int]]:
    x, y, step = position
    return [
        (x + 1, y, step + 1),
        (x - 1, y, step + 1),
        (x, y + 1, step + 1),
        (x, y - 1, step + 1),
    ]

class Solution:
    def nearestExit(self, maze: list[list[str]], entrance: list[int]) -> int:
        assert maze

        height = len(maze) - 1
        width = len(maze[0]) - 1

        def in_maze(x: int, y: int) -> bool:
            return 0 <= x <= height and 0 <= y <= width

        def is_exit(x: int, y: int) -> bool:
            return x == 0 or y == 0 or x == height or y == width

        seen = set()
        positions: deque[tuple[int, int, int]] = deque()

        start_x, start_y = entrance

        seen.add((start_x, start_y))
        positions.append((start_x, start_y, 0))

        while positions:
            position = positions.popleft()
            for neighbor in neighbors(position):
                x, y, step = neighbor

                if (x, y) in seen or not in_maze(x, y):
                    continue

                seen.add((x, y))

                if maze[x][y] == ".":
                    if is_exit(x, y):
                        return step
                    positions.append(neighbor)

        return -1


import sys,os

import gmsh
import numpy as np

from mpi4py import MPI

import dolfinx

dir = os.path.dirname(__file__)

gmsh.initialize()

lc = 0.2
num_airfoil_refinement = 100

L = 4
H = 1
gdim = 2

"""
    Defining the shape of the airfoil using Bézier Curves
    Geometrical parameters of the airfoil according to Xiaoqiang et al
"""
c_1, c_2 = 0.5, 0.5                                     # Coefficients of camber-line-abscissa parameter equation
c_3, c_4 = 0.1, 0.05                                    # Coefficients of camber-line.ordinate parameter equation
coeff_thick = [0.2969,-0.126,-0.3516,0.2843,-0.1036]    # Coefficients of the thickness equation taken from the NACA 2412 Airfoil

# Bézier curves with control parameter k \in [0,1]
x_c = lambda k: 3 * c_1 * k * (1 - k)**2 + 3 * c_2 * (1-k) * k**2 + k**3    # Camber-line-abscissa
y_c = lambda k: 3 * c_3 * k * (1 - k)**2 + 3 * c_4 * (1-k) * k**2           # Camber-line-abscissa

# Thickness equation for a 6% thick airfoil
thickness = lambda x: 0.06 / 0.1 * (coeff_thick[0] * np.sqrt(x) + coeff_thick[1] * x + coeff_thick[2] * x**2 + coeff_thick[3] * x**3 + coeff_thick[4] * x**4)

# Position of the airfoil in the computational domain defined by the coordinates of the leading edge
leading_edge_x = np.min([L/8,0.5])
leading_edge_y = H/2

# Upper and lower surface of the airfoil
x_u = x_l = lambda k: leading_edge_x + x_c(k)
y_u = lambda k: leading_edge_y + y_c(k) + thickness(x_c(k))
y_l = lambda k: leading_edge_y + y_c(k) - thickness(x_c(k))

# Calculate maximal thickness of the airfoil
thickness_max = np.max([thickness(x) for x in np.linspace(0,1,num_airfoil_refinement)])

"""
    Meshing the airfoil using gmsh
"""

rectangle = gmsh.model.occ.addRectangle(0,0,0, L, H, tag=3)
# Define lower curve of the airfoil using the BSplines and given points
points_lower_curve=[]
for k in np.linspace(0,1,num_airfoil_refinement):
    points_lower_curve.append(gmsh.model.occ.addPoint(x_l(k), y_l(k), 0.0, lc))

# Define upper curve of the airfoil using the BSplines and given points
points_upper_curve=[points_lower_curve[0]]
for k in np.linspace(0,1,num_airfoil_refinement)[1:-1]:
    points_upper_curve.append(gmsh.model.occ.addPoint(x_u(k), y_u(k), 0.0, lc))
points_upper_curve.append(points_lower_curve[-1])

C1 = gmsh.model.occ.addBSpline(points_lower_curve, degree=3)
C2 = gmsh.model.occ.addBSpline(points_upper_curve, degree=3)

# Create airfoil and cut out of computational domain
W = gmsh.model.occ.addWire([C1,C2])
obstacle=gmsh.model.occ.addPlaneSurface([W])

# Remove points of the airfoil
for i in list(dict.fromkeys(points_lower_curve + points_upper_curve)):
    gmsh.model.occ.remove([(0, i)])

# Cut out airfoil from computational domain
fluid = gmsh.model.occ.cut([(gdim, rectangle)], [(gdim, obstacle)])
gmsh.model.occ.synchronize()

# Create a distance field to the airfoil
distance_field = gmsh.model.mesh.field.add("Distance")
gmsh.model.mesh.field.setNumbers(distance_field, "CurvesList", [C1, C2])
gmsh.model.mesh.field.setNumbers(distance_field,"PointsList", [points_lower_curve[0],points_lower_curve[-1]])
gmsh.model.mesh.field.setNumber(distance_field,"Sampling", num_airfoil_refinement*2)
# Create refined mesh using a threshold field
refinement= gmsh.model.mesh.field.add("Threshold")
gmsh.model.mesh.field.setNumber(refinement, "IField", distance_field)
# Set the refinement levels (LcMin for the mesh size in the refined region, LcMax for the mesh size far from the refined region)
gmsh.model.mesh.field.setNumber(refinement, "LcMin", lc/5)
gmsh.model.mesh.field.setNumber(refinement, "LcMax", lc*2)
# Set the threshold value where which refinement should be applied
gmsh.model.mesh.field.setNumber(refinement, "DistMin", thickness_max/2)
gmsh.model.mesh.field.setNumber(refinement, "DistMax", thickness_max)

# Set the field as background mesh
gmsh.model.mesh.field.setAsBackgroundMesh(refinement)

# 8=Frontal-Delaunay for Quads
gmsh.option.setNumber("Mesh.Algorithm", 8)
# 2=simple full-quad
gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
# Apply recombination algorithm
gmsh.option.setNumber("Mesh.RecombineAll", 1)
# Mesh subdivision algorithm
gmsh.option.setNumber("Mesh.SubdivisionAlgorithm", 1)
# Mesh generation
gmsh.model.mesh.generate(gdim)
# Mesh order
gmsh.model.mesh.setOrder(1)
# Mesh optimisation
gmsh.model.mesh.optimize("Netgen")

"""
    Defining boundary markers for the mesh
"""

fluid_marker, wall_marker, obstacle_marker = 1, 1, 2
wall, obstacle = [], []

surfaces = gmsh.model.getEntities(dim=gdim)
boundaries = gmsh.model.getBoundary(surfaces, oriented=False)

gmsh.model.addPhysicalGroup(surfaces[0][0], [surfaces[0][1]], fluid_marker)
gmsh.model.setPhysicalName(surfaces[0][0], fluid_marker, "Fluid")

for boundary in boundaries:
    center_of_mass = gmsh.model.occ.getCenterOfMass(boundary[0], boundary[1])
    if np.allclose(center_of_mass, [0, H/2, 0]):
        wall.append(boundary[1])
    elif np.allclose(center_of_mass, [L, H/2, 0]):
        wall.append(boundary[1])
    elif np.allclose(center_of_mass, [L/2, H, 0]):
        wall.append(boundary[1])
    elif np.allclose(center_of_mass, [L/2, 0, 0]):
        wall.append(boundary[1])
    else:
        obstacle.append(boundary[1])

# Set physical markers for the boundaries
gmsh.model.addPhysicalGroup(gdim-1, wall, wall_marker)
gmsh.model.setPhysicalName(gdim-1, wall_marker, "wall")
gmsh.model.addPhysicalGroup(gdim-1, obstacle, obstacle_marker)
gmsh.model.setPhysicalName(gdim-1, obstacle_marker, "obstacle")

gmsh.model.occ.remove(gmsh.model.getEntities(dim=gdim-1))
gmsh.model.occ.remove(gmsh.model.getEntities(dim=gdim))
gmsh.model.occ.remove(gmsh.model.getEntities(dim=0))

gmsh.write(os.path.join(dir,"mesh.msh"))

gmsh.fltk.run()

# Import mesh in dolfinx
gmsh_model_rank = 0
mesh_comm = MPI.COMM_WORLD

mesh, cell_tags, facet_tags = dolfinx.io.gmshio.read_from_msh(os.path.join(dir,"mesh.msh"), mesh_comm, gmsh_model_rank, gdim=gdim)

with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "mesh.xdmf","w") as mesh_file_xdmf:
    mesh_file_xdmf.write_mesh(mesh)
    mesh_file_xdmf.write_meshtags(cell_tags, mesh.geometry)
    mesh_file_xdmf.write_meshtags(facet_tags, mesh.geometry)