import time
import numpy as np

from cysounddevice import PortAudio
from cysounddevice import types
from cysounddevice.types import SampleTime
from cysounddevice.utils import PortAudioError

from pd import PatchManager

N_TICKS = 1
SAMPLE_RATE = 44100
CHANNELS_IN = 0
CHANNELS_OUT = 2
BLOCKSIZE = 64

DURATION = 2

class Patch(PatchManager):
    def __init__(self, name='test2.pd', dir='.',
            sample_rate=44100, ticks=1,
            in_channels=0, out_channels=2):
        self.name = name.encode('UTF-8')
        self.dir = dir.encode('UTF-8')
        self.sample_rate = sample_rate
        self.ticks = ticks
        self.in_channels = in_channels
        self.out_channels = out_channels

    def config_stream(self, stream, play_duration):
        block_size = stream.frames_per_buffer
        start_time = SampleTime(0, 0, block_size, stream.stream_info.sample_rate)
        # self.center_freq = 1000.0

        self.stream = stream
        self.start_time = start_time
        self.current_time = start_time.copy()

        end_time = start_time.copy()
        while end_time.pa_time < play_duration:
            end_time.block += 1
        self.end_time = end_time
        self.play_duration = end_time.pa_time
        print('start_time={}, end_time={}'.format(start_time, end_time))

        stream.stream_info.input_channels = self.in_channels
        nchannels = stream.stream_info.output_channels
        nblocks = end_time.block + 1
        self.nchannels = nchannels
        self.nblocks = nblocks
        self.complete = False

    def run(self):
        # libpd part
        self.init()
        self.init_audio() #one channel in, one channel out

        # audio
        st_info = self.stream.stream_info
        assert not self.stream.active
        assert st_info.output_channels > 0
        assert self.stream.check() == 0

        r = False

        start_ts = time.time()
        end_ts = start_ts + self.play_duration + 2

        with self.stream:
            print('stream opened')
            while not self.complete:
                if not self.stream.active:
                    raise Exception('stream aborted')
                r = self.fill_buffer()
                if self.complete:
                    print('playback complete')
                    break
                if time.time() >= end_ts:
                    print('playback timeout')
                    break
                if not r:
                    time.sleep(.1)
            print('closing stream')
        print('stream closed')

    def fill_buffer(self):
        bfr = self.stream.output_buffer
        if not bfr.ready():
            return False
        data = self.generate()
        r = bfr.write_output_sf32(data)
        if not r:
            return False
        self.current_time.block += 1

        if self.current_time >= self.end_time:
            self.complete = True
            return False
        return True

    def generate(self):

        block_size = self.stream.frames_per_buffer
        fs = self.stream.sample_rate

        inbuf = np.zeros((self.in_channels, block_size), dtype='float32')
        outbuf = np.zeros((self.out_channels, block_size), dtype='float32')
        self.process_audio(self.ticks, inbuf, outbuf)

        sig = np.zeros((self.out_channels, block_size), dtype='float32')
        # dsp perform routine
        for i in range(block_size * self.out_channels):
            if (i % 2):
                sig[i] = outbuf[i]
            else:
                sig[i] = outbuf[i]

        # for i in range(self.out_channels):
        #     data[i,:] = sig
        return sig

def test_playback():
    p = Patch()
    port_audio = PortAudio()
    sample_rate = p.sample_rate
    sample_format = types.get_sample_formats()['sf_float32']
    block_size = p.blocksize()
    print(f'fs={sample_rate}, sample_format={sample_format} block_size={block_size}')
    port_audio.open() # have to open to enable get_host_api_by_name
    hostapi = port_audio.get_host_api_by_name('Core Audio')
    device = hostapi.devices[1]
    stream_kw = dict(
        sample_rate=sample_rate,
        block_size=block_size,
        sample_format=sample_format['name'].decode(),
        output_channels=p.out_channels,
    )
    stream = device.open_stream(**stream_kw)
    try:
        stream.check()
    except PortAudioError as exc:
        if exc.error_msg == 'Invalid sample rate':
            print(exc)
            return
    p.config_stream(stream, DURATION)
    p.run()
    assert p.complete
    # gen = Generator(stream, DURATION)
    # gen.run()
    # assert gen.complete

test_playback()


import torch
import numpy
from PIL import Image, ImageDraw

RESO_H = 768
RESO_W = RESO_H // 2
GRID_H = 16
GRID_W = RESO_W // 5

def transform_pred(pred, ratio, conf_thresh):
    conf = pred[0]
    mask = conf > conf_thresh

    center_x = torch.stack(
        [torch.arange(GRID_W // 2, RESO_W, GRID_W).float().to(pred.device)] * (RESO_H // GRID_H),
        dim=0,
    )
    center_y = torch.stack(
        [torch.arange(GRID_H // 2, RESO_H, GRID_H).float().to(pred.device)] * (RESO_W // GRID_W),
        dim=1,
    )

    center_x = (pred[1] * GRID_W + center_x)[mask]
    center_y = (pred[2] * GRID_H + center_y)[mask]

    w_half = pred[3][mask] * GRID_W / 2
    h_half = pred[4][mask] * GRID_H / 2

    conf = conf[mask]
    coor = torch.stack(
        (
            (center_x - w_half) / ratio[0],
            (center_y - h_half) / ratio[1],
            (center_x + w_half) / ratio[0],
            (center_y + h_half) / ratio[1],
        ),
        dim=1,
    )

    return conf, coor

def nms_filter(confidence, coordinate, iou_thresh):
    conf, indices = torch.sort(confidence, descending=True)
    coor = coordinate[indices]

    count = 1
    coor_nms = torch.zeros_like(coor)
    coor_nms[0] = coor[0]
    for i in range(1, len(coor)):
        if (calc_ious(coor_nms[0:count], coor[i]) < iou_thresh).all():
            coor_nms[count] = coor[i]
            count += 1

    return coor_nms[0:count]

def calc_f1(pred, truth, iou_thresh=0.5):
    """
    arguments:
        pred    prediction boxes as an N x 4 tensor, each row is (x0, y0, x1, y1) of a box.
                prediction boxes are assumed to be in descending confidence, i.e. the first box has
                the highest confidence
        truth   truth boxes as an M x 4 tensor, each row is (x0, y0, x1, y1) of a box. the order of
                truth boxes does not matter
        iou_thresh  optional. the IOU required for a prediction box to be considered as 'correct'

    return:
        f1-score, average-precision, average-recall

    note:
        this does NOT on CUDA, put things on CPU
    """
    ious = torch.zeros(len(pred), len(truth))
    for i, pred_box in enumerate(pred):
        ious[i] = calc_ious(truth, pred_box)
    ious_max, _ = torch.max(ious, dim=1)

    hit = (ious_max > iou_thresh).long().numpy()
    for i in range(len(hit)):
        hit[i] = hit[0:i].sum()

    precision = hit / numpy.arange(1, len(hit) + 1)
    for i in range(len(precision)):
        precision[i] = precision[i:].max()

    recall = hit / len(truth)

    # Average precision
    ap = numpy.interp(numpy.linspace(min(recall), max(recall), 101), recall, precision).mean()
    # Average recall
    ar = numpy.interp(numpy.linspace(min(precision), max(precision), 101), precision, recall).mean()
    # Average F1
    f1 = 2 * ap * ar / (ap + ar)

    return f1, ap, ar

def calc_ious(boxes, box0):
    m = torch.max(boxes, box0).t()
    n = torch.min(boxes, box0).t()
    ious = ((n[2] - m[0]).clamp(0) * (n[3] - m[1]).clamp(0)) / (
        (m[2] - n[0]).clamp(0) * (m[3] - n[1]).clamp(0)
    )

    return ious

if __name__ == "__main__":
    torch.set_printoptions(threshold=10, edgeitems=2)
    # torch.manual_seed(1)
    image = Image.new("RGB", (RESO_W, RESO_H))
    pred = torch.stack(
        (
            torch.rand(RESO_H // GRID_H, RESO_W // GRID_W),
            torch.rand(RESO_H // GRID_H, RESO_W // GRID_W) - 0.5,
            torch.rand(RESO_H // GRID_H, RESO_W // GRID_W) - 0.5,
            torch.rand(RESO_H // GRID_H, RESO_W // GRID_W) + 0.5,
            torch.rand(RESO_H // GRID_H, RESO_W // GRID_W) + 0.5,
        )
    )
    conf, coor = transform_pred(pred, (1, 1), conf_thresh=0.5)
    nms_coor = nms_filter(conf, coor, iou_thresh=0.1)

    conf, indices = torch.sort(conf, descending=True)
    coor = coor[indices]

    draw = ImageDraw.Draw(image)
    for c in nms_coor:
        draw.rectangle(tuple(c), fill="white")
    for i, c in enumerate(coor):
        draw.rectangle(tuple(c), outline="red", width=1)
        draw.text(tuple(c[0:2]), f"{i}", fill="red")
    image.save("tmp.png")


import pathlib as pl
from datetime import datetime

import MatDBForge.core.clusters as mdb_clust
import MatDBForge.core.utils as mdb_utils
from MatDBForge.core import initial_db as indb

MAX_SIZE = 5
NUM_STRUCT = 4
NUM_REPEAT = 10

# Gathering current time for filenames
now = datetime.now()
date_time = now.strftime("%Y-%m-%dT%H%M%S")

# Logger preparation
mdb_utils.init_logger(source=pl.Path(__file__).stem)

# Logging generation parameters
mdb_utils.custom_print(
    (
        f"Current run params: MAX_SIZE = {MAX_SIZE},"
        f" NUM_STRUCT = {NUM_STRUCT}, NUM_REPEAT = {NUM_REPEAT}"
    ),
    "debug",
)

# Creating a InitialDatabase object.
indb = indb.CuZnInitialDatabase(
    f"clusters_{date_time}_final",
    max_num_atoms=128,
)
mdb_utils.custom_print(indb, "done")

# Selecting phases to use
selected_phases = [
    phase
    for phase in indb.DB_PHASE_DIAGRAM.phases
    if phase.name not in ["m1", "m2", "m3", "m4"]
]

mdb_utils.custom_print("Adding base clusters...", "info")

# Generating cluster structures for different sizes
# using current phase, and applying
# replacements and perturbations to each generated structure.
# Structures are then stored into the database.
cluster_list = indb.generate_clusters(
    size_range=range(3, MAX_SIZE + 1),
    num_struct=NUM_STRUCT,
    num_repeat=NUM_REPEAT,
    add_dimer=True,
    save_in_db=True,
)

mdb_utils.custom_print(indb, "done")
print()

# For every phase, iterate over all structures and
# generate N_STRUCT*N_REPEAT random replacements.
mdb_utils.custom_print("Applying replacements...", "info")
for phase in selected_phases:
    mdb_utils.custom_print(f"Working with '{phase.name}' phase...", "debug")
    replaced_clusters = mdb_clust.apply_replacement_cluster_db(
        db_obj=indb,
        phase=phase,
        num_struct=NUM_STRUCT,
        num_repeat=NUM_REPEAT,
        similarity_check=True,
        save_in_db=False,
    )
    mdb_utils.custom_print(f"Phase '{phase.name}' done!", "done")

# Checking for similarity after replacement
unique_repl_clusters = mdb_utils.similarity_check_list(
    db_obj=indb,
    replaced_structures=replaced_clusters,
    save_in_db=True,
)

mdb_utils.clear_previous_print()
print()

# Getting all generated structures (base and perturb)
# and applying a perturbation.
mdb_utils.custom_print("Applying perturbations...", "info")
perturbed_clusters = mdb_clust.apply_gauss_perturb_db(
    db_obj=indb,
    center=0.04,
    repeat=NUM_REPEAT,
)

mdb_utils.custom_print(indb, "done")

indb.save_database(
    path="/home/psanz/teklahome/projects/p2-CuZn/relaxed_structures_initialdb/cluster_database",
    suffix="database",
)


from flask import Flask, request, jsonify, render_template, json
from flask_cors import CORS
from movie_recommendation import *
import pandas as pd

app = Flask(__name__)
CORS(app)

@app.route("/")
def getModel():
    return render_template('base.html')

@app.route('/', methods=['GET','POST'])
def recommend_movies():
    if request.method == 'POST':
        movie_name = request.form['movie']
        result = results(movie_name)
        # recommendations = jsonify(result)
        recommendations = get_name(result)
    return render_template('show.html', movies = recommendations)

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


import pandas as pd
import pickle
import numpy as np
from sklearn import metrics
# import matplotlib.pylab as plt
from src.functions import f_point_5

class BaseLinePredictor:
    """
    A baseline prediction class
    """
    def __init__(self, method='Jaccard', type='Unnormalized'):
        """
        The constructor of the baseline predictor
        :param method: only Jaccard method is supported
        :param type: one of the two options ('Unnormalized', 'Normalized')
        """
        self.method = method
        self.type = type
        self.h_train = None
        self.bsk_label_train = None
        self.__union_train = None
        self.ratio = None
        self.step = 1

    def fit(self, h_train, r_train, bsk_label_train,
            multi_item_bsk = None, ratio = None, step = 2):
        """
        The train method of class
        :param h_train: a csr_matrix
        :param bsk_label_train: a single column data frame
        :return: None
        """
        multi_item_bsk = (h_train>1).nonzero()[0]
        multi_idx = np.zeros(h_train.shape[0], dtype=bool)
        multi_idx[multi_item_bsk] = True

        h_train = h_train.sign()
        self.h_train = h_train
        self.r_train = r_train
        self.bsk_label_train = bsk_label_train.values
        self.__union_train = h_train.sum(1)

        if self.type == "Normalized":
            if ratio is None:
                self.ratio = bsk_label_train[multi_idx].sum()[0]/multi_idx.sum() /\
                    (bsk_label_train[np.logical_not(multi_idx)].sum()[0]/np.logical_not(multi_idx).sum())
            else:
                self.ratio = ratio
            self.bsk_label_train = self.bsk_label_train.astype(np.float)
            self.bsk_label_train[multi_idx, :] = self.bsk_label_train[multi_idx, :] / self.ratio
        else:
            self.ratio = 1

        self.step = step

    def predict(self, h_test, r_test):
        """
        Predict the result based on given h_test
        :param h_test: a csr_matrix
        :return: a list of prediction (continuous score)
        """
        multi_item_bsk = (h_test>1).nonzero()[0]
        h_test_sign = h_test.sign()
        wgt = np.ones((h_test_sign.shape[0]))
        if self.type == "Normalized":
            #assert test_bsk_name is not None, "test_bsk_name must be supplied for normalization"
            wgt[multi_item_bsk] = self.ratio
        h_mat = self.h_train.sign()
        intersect = h_mat * h_test_sign.T

        union2 = h_test_sign.sum(1)
        r_mat = self.r_train.sign()
        pred = []
        total_return_rate = (r_mat.sum(0)/h_mat.sum(0)).A1
        for i in range(len(union2)):
            ja = intersect[:, i] / (self.__union_train + union2[i] - intersect[:, i])  # Jaccard Index
            pred_bsk = (ja.T * self.bsk_label_train/ja.sum())[0,0] * wgt[i]
            if self.step == 1:
                pred_bsk = 1
            idx = self.bsk_label_train[:,0] > 0
            with np.errstate(divide='ignore',invalid='ignore'):
                pred_prod = ja[idx].T * r_mat[idx, :]/ \
                            (ja[idx].T * h_mat[idx, :]) * pred_bsk

            idx_purchase = (h_test_sign[i, :].todense().A1 > 0)
            pred_prod = pred_prod[:, idx_purchase].A1
            nan_prd = np.isnan(pred_prod)
            pred_prod[nan_prd] = total_return_rate[idx_purchase][nan_prd]

            if self.type == "Normalized":
                wgt_prod = (h_test[i, idx_purchase] > 1).todense().A1.astype(np.float) + 1
                pred_prod = pred_prod * wgt_prod

            pred.append((pred_bsk, pred_prod, r_test[i, idx_purchase].todense().A1 > 0))

        pred_rst = pd.DataFrame(pred, columns=['pred_prob', 'pred_prob_prod', 'obs_prod'])
        return pred_rst

    def pred_test_based_on_valid(self, h_validate, bsk_label_valid, h_test, bsk_label_test):
        """

        :param h_validate:
        :param bsk_label_valid:
        :param h_test:
        :return: optimal prec, recall, f_0.5, auc, fpr, tpr
        """
        pred_val = self.predict(h_validate, bsk_label_valid.index.values)

        prec, rec, thr = metrics.precision_recall_curve(bsk_label_valid, pred_val)
        f = f_point_5(prec, rec)
        thr_opt = thr[np.argmax(f)]

        pred_test = self.predict(h_test, bsk_label_test.index.values)
        prec, rec, thr = metrics.precision_recall_curve(bsk_label_test, pred_test)
        f = f_point_5(prec, rec)
        idx = np.where(thr <= thr_opt)[0][-1]

        fpr, tpr, _ = metrics.roc_curve(bsk_label_test, pred_test)
        auc = metrics.auc(fpr, tpr)

        return prec[idx], rec[idx], f[idx], auc, fpr, tpr, thr[idx]

    def pred_test_based_on_valid_prod(self, h_validate, bsk_label_valid, r_validate,
                                 h_test, bsk_label_test, r_test):
        """

        :param h_validate:
        :param bsk_label_valid:
        :param order_no_validate:
        :param r_validate:
        :param h_test:
        :param bsk_label_test:
        :param order_no_test:
        :param r_test:
        :param bs:
        :param phis:
        :return:
        """
        pred_val = self.predict(h_validate, r_validate)

        obs_prod = np.array([item for l in pred_val['obs_prod'] for item in l])
        pred_prod = np.array([item for l in pred_val['pred_prob_prod'] for item in l])

        prec, rec, thr = metrics.precision_recall_curve(obs_prod, pred_prod, pos_label=True)
        f = f_point_5(prec, rec)
        thr_opt = thr[np.argmax(f)]

        pred_test = self.predict(h_test, r_test)
        obs_prod = np.array([item for l in pred_test['obs_prod'] for item in l])
        pred_prod = np.array([item for l in pred_test['pred_prob_prod'] for item in l])

        prec, rec, thr = metrics.precision_recall_curve(obs_prod, pred_prod, pos_label=True)
        f = f_point_5(prec, rec)
        idx = np.where(thr <= thr_opt)[0][-1]

        fpr, tpr, _ = metrics.roc_curve(obs_prod, pred_prod)
        auc = metrics.auc(fpr, tpr)

        return prec[idx], rec[idx], f[idx], auc, fpr, tpr, thr[idx]

if __name__ == "__main__":
    import matplotlib.pylab as plt
    # load data
    with open("../data/h_train.pkl", 'rb') as f:
        h_train = pickle.load(f)
    with open("../data/r_train.pkl", 'rb') as f:
        r_train = pickle.load(f)

    with open("../data/h_validate.pkl", 'rb') as f:
        h_validate = pickle.load(f)
    with open("../data/h_test.pkl", 'rb') as f:
        h_test = pickle.load(f)

    with open("../data/r_validate.pkl", 'rb') as f:
        r_validate = pickle.load(f)
    with open("../data/r_test.pkl", 'rb') as f:
        r_test = pickle.load(f)

    bsk_label_train = pd.read_pickle("../data/bsk_label_train.pkl")
    bsk_label_valid = pd.read_pickle("../data/bsk_label_validate.pkl")
    bsk_label_test = pd.read_pickle("../data/bsk_label_test.pkl")

    # unnormalized

    p = BaseLinePredictor()
    p.fit(h_train, r_train, bsk_label_train)

    prec, rec, f, auc, fpr, tpr, thr = \
        p.pred_test_based_on_valid_prod(h_validate, bsk_label_valid, r_validate,
                                        h_test, bsk_label_test, r_test)

    plt.plot(fpr, tpr)
    plt.plot([0, 1], [0, 1], 'b--')

    print("auc, prec, rec, f1, thr:")
    print("%f, %f, %f, %f, %f" % (auc, prec, rec, f, thr))

    # normalized
    p_1 = BaseLinePredictor(type="Normalized")
    p_1.fit(h_train, r_train, bsk_label_train, 2)

    prec_1, rec_1, f_1, auc_1, fpr_1, tpr_1, thr =\
        p_1.pred_test_based_on_valid_prod(h_validate, bsk_label_valid, r_validate,
                                        h_test, bsk_label_test, r_test)

    # plt.plot(fpr_1, tpr_1)
    # plt.plot([0, 1], [0, 1], 'b--')

    print("auc, prec, rec, f1, thr:")
    print("%f, %f, %f, %f, %f" % (auc_1, prec_1, rec_1, f_1, thr))


from PyQt5.QtWidgets import (QWidget, QPushButton, QLabel, QComboBox, QDesktopWidget)
from PyQt5.QtGui import (QPainter, QPen, QFont)
from PyQt5.QtCore import Qt

class LearningUI(QWidget):
    def __init__(self):
        super(LearningUI, self).__init__()

        self.__init_ui()

        self.setMouseTracking(False)
        #保存所有绘画的点（要想将按住鼠标后移动的轨迹保留在窗体上，需要一个列表来保存所有移动过的点）
        self.pos_xy = []
        #设置pos_x、pos_y专门存放x、y轴坐标，方便计算
        self.pos_x = []
        self.pos_y = []

        #设置关联事件（学习、识别、清屏），连接到槽函数
        self.btn_learn.clicked.connect(self.btn_learn_on_clicked)
        self.btn_recognize.clicked.connect(self.btn_recognize_on_clicked)
        self.btn_clear.clicked.connect(self.btn_clear_on_clicked)

        #连接到自定义槽函数btn_add_on_clicked（192行）
        self.btn_add.clicked.connect(self.btn_add_on_clicked)
        self.btn_minus.clicked.connect(self.btn_minus_on_clicked)
        self.btn_mulitiplication.clicked.connect(self.btn_mulitiplication_on_clicked)
        self.btn_division.clicked.connect(self.btn_division_on_clicked)

    def __init_ui(self):

        #添加三个按钮，分别是学习、识别、清屏
        self.btn_learn = QPushButton("学习", self)
        '''
        setGeometry()方法做两个事。它定位了窗口在屏幕的位置并且设定窗口大小。前两个参数是窗口的x,y坐标。第三个参数是窗口宽度，第四个是窗口高度。
        '''
        self.btn_learn.setGeometry(50, 400, 70, 40)
        self.btn_recognize = QPushButton("识别", self)
        self.btn_recognize.setGeometry(320, 400, 70, 40)
        self.btn_clear = QPushButton("清屏", self)
        self.btn_clear.setGeometry(420, 400, 70, 40)

        '''
            添加+、-、*、/四个运算符按钮
        '''
        self.btn_add= QPushButton("+", self)
        self.btn_add.setGeometry(0, 100, 70, 40)

        self.btn_minus = QPushButton("-", self)
        self.btn_minus.setGeometry(0, 180, 70, 40)

        self.btn_mulitiplication = QPushButton("x", self)
        self.btn_mulitiplication.setGeometry(0, 260, 70, 40)

        self.btn_division = QPushButton("÷", self)
        self.btn_division.setGeometry(0, 340, 70, 40)

        #添加一个组合框，选择0-9
        self.combo_table = QComboBox(self)
        for i in range(10):
            self.combo_table.addItem("%d" % i)
        #设定窗口大小（x坐标，y坐标，宽度，高度）
        self.combo_table.setGeometry(150, 400, 70, 40)

        #添加一条标签
        self.label_end = QLabel('by 憨憨小分队', self)
        self.label_end.move(375, 470)

        #添加一条输出识别结果的标签
        self.label_output = QLabel('', self)
        #设定窗口大小（x坐标，y坐标，宽度，高度）
        self.label_output.setGeometry(0, 50,550 , 50)
        #设置边框大小、颜色
        self.label_output.setStyleSheet("QLabel{border:5px solid black;}")
        #设置字体类型、大小、加粗
        self.label_output.setFont(QFont("Roman times", 10, QFont.Bold))
        #设置文本居中
        self.label_output.setAlignment(Qt.AlignCenter)

        '''
        设置窗体样式
        '''
        #固定了窗体的宽度与高度
        self.setFixedSize(550, 500)
        #将窗体居中显示
        self.center()
        #设置窗体的标题
        self.setWindowTitle('0-9手写体识别(机器学习中的"HelloWorld!")')

    #窗口居中显示函数
    def center(self):
        #在主窗口内得到一个指定的长方形几何体
        qt_center = self.frameGeometry()
        '''
            QDesktopWidget类提供了关于用户桌面的信息，包括屏幕尺寸
        '''
        #得到显示器的中心点
        desktop_center = QDesktopWidget().availableGeometry().center()
        #把长方形窗口设定用户桌面的屏幕中心。
        qt_center.moveCenter(desktop_center)
        #把左上角的窗口移动到中央
        self.move(qt_center.topLeft())

    def paintEvent(self, event):
        '''
        相邻两个点之间画线，留下鼠标移动轨迹

        首先判断pos_xy列表中是不是至少有两个点了
        然后将pos_xy中第一个点赋值给point_start
        利用中间变量pos_tmp遍历整个pos_xy列表
        point_end = pos_tmp

        判断point_end是否是断点，如果是
        point_start赋值为断点
        continue
        判断point_start是否是断点，如果是
        point_start赋值为point_end
        continue

        画point_start到point_end之间的线
        point_start = point_end
        这样，不断地将相邻两个点之间画线，就能留下鼠标移动轨迹了
        '''
        #构造一个钢笔类
        painter = QPainter()
        painter.begin(self)
        #设置笔为黑色、大小为2、实线
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        painter.setPen(pen)

        #至少有两个点
        if len(self.pos_xy) > 1:
            #起点
            point_start = self.pos_xy[0]
            #遍历鼠标经过的点，找到终点
            for pos_tmp in self.pos_xy:
                point_end = pos_tmp

                #判断断点
                if point_end == (-1, -1):
                    point_start = point_end
                    continue

                if point_start == (-1, -1):
                    point_start = point_end
                    continue

                #绘制一条制定了断点坐标的线，绘制从(start[0],start[1])到(end[0],end[1])的直线并且设置当前画笔的位置为end那里
                painter.drawLine(point_start[0], point_start[1], point_end[0], point_end[1])
                point_start = point_end
        painter.end()

    def mouseReleaseEvent(self, event):
        '''
        重写鼠标按住后松开的事件
        在每次松开后向pos_xy列表中添加一个断点(-1, -1)
        然后在绘画时判断一下是不是断点就行了
        是断点的话就跳过去，不与之前的连续
        '''

        pos_test = (-1, -1)
        self.pos_xy.append(pos_test)

        self.update()

    #获取鼠标移动轨迹的点的坐标，存入数组
    def mouseMoveEvent(self, event):

        self.pos_x.append(event.pos().x())
        self.pos_y.append(event.pos().y())

        #中间变量pos_tmp提取当前点
        pos_tmp = (event.pos().x(), event.pos().y())
        #pos_tmp添加到self.pos_xy中
        self.pos_xy.append(pos_tmp)

        self.update()

    def btn_learn_on_clicked(self):
        '''
        需要用到数据库，因此在在子类中实现
        '''
        '''pass 是空语句，是为了保持程序结构的完整性。
           pass 不做任何事情，一般用做占位语句。
        '''

    pass

    def btn_recognize_on_clicked(self):
        '''
        需要用到数据库，因此在在子类中实现
        '''

    pass

    #清屏函数
    def btn_clear_on_clicked(self):
        '''
        按下清屏按钮：
        将列表赋值为空
        将输出识别结果的标签赋值为空
        然后刷新界面，重新绘画即可清屏
        '''

        self.pos_xy = []
        self.pos_x = []
        self.pos_y = []
        #self.label_output.setText('')
        self.update()

    #自定义槽函数
    def btn_add_on_clicked(self):
        content=self.label_output.text()
        self.label_output.setText("%s+"%content)

    #自定义槽函数
    def btn_minus_on_clicked(self):
        content=self.label_output.text()
        self.label_output.setText("%s-"%content)

    #自定义槽函数
    def btn_mulitiplication_on_clicked(self):
        content=self.label_output.text()
        self.label_output.setText("%s×"%content)

    #自定义槽函数
    def btn_division_on_clicked(self):
        content=self.label_output.text()
        self.label_output.setText("%s÷"%content)

    def get_pos_xy(self):
        min_y,min2_y,max2_y,max_y
        '''
        将手写体在平面上分为9个格子
        计算每个格子里点的数量
        然后点的数量转化为占总点数的百分比
        接着返回一个数组dim[9]
        横轴依次是min_x、min2_x、max2_x、max_x
        纵轴依次是min_y、min2_y、max2_y、max_y
        '''

        if not self.pos_xy:
            return None

        pos_count = len(self.pos_x)
        max_x = max(self.pos_x)
        max_y = max(self.pos_y)
        min_x = min(self.pos_x)
        min_y = min(self.pos_y)
        dim = [0, 0, 0, 0, 0, 0, 0, 0, 0]

        dis_x = (max_x - min_x) // 3
        dis_y = (max_y - min_y) // 3

        min2_x = min_x + dis_x
        min2_y = min_y + dis_y
        max2_x = max_x - dis_x
        max2_y = max_y - dis_y

        for i in range(len(self.pos_x)):
            if self.pos_y[i] >= min_y and self.pos_y[i] < min2_y:
                if self.pos_x[i] >= min_x and self.pos_x[i] < min2_x:
                    dim[0] += 1
                    continue
            if self.pos_x[i] >= min2_x and self.pos_x[i] < max2_x:
                dim[1] += 1
                continue
            if self.pos_x[i] >= max2_x and self.pos_x[i] <= max_x:
                dim[2] += 1
                continue
            elif self.pos_y[i] >= min2_y and self.pos_y[i] < max2_y:
                if self.pos_x[i] >= min_x and self.pos_x[i] < min2_x:
                    dim[3] += 1
                    continue
            if self.pos_x[i] >= min2_x and self.pos_x[i] < max2_x:
                dim[4] += 1
                continue
            if self.pos_x[i] >= max2_x and self.pos_x[i] <= max_x:
                dim[5] += 1
                continue
            elif self.pos_y[i] >= max2_y and self.pos_y[i] <= max_y:
                if self.pos_x[i] >= min_x and self.pos_x[i] < min2_x:
                    dim[6] += 1
                    continue
            if self.pos_x[i] >= min2_x and self.pos_x[i] < max2_x:
                dim[7] += 1
                continue
            if self.pos_x[i] >= max2_x and self.pos_x[i] <= max_x:
                dim[8] += 1
                continue
            else:
                pos_count -= 1
            continue

        for num in dim:
            num = num * 100 // pos_count

        return dim


from django.core.management.base import BaseCommand, CommandError
from articles.queries import *
from articles.models import *

from articles.getdata import *

class Command(BaseCommand):
    """
    """
    def handle(self, *args, **options):
        experiment_id = 'E-GEOD-10588'

        exp = Experiment.objects.get(data__contains={'accession':experiment_id})
        health_range = list(range(225470,225481)) + list(range(225483,225498))
        pre_eclampsia_range = list(range(225481,225482))+list(range(225498,225514))
        health_samples = ['GSM'+str(item) for item in health_range]
        pre_eclampsia_samples = ['GSM'+str(item) for item in pre_eclampsia_range]

        diagnosis = StandardName.objects.get(name='Diagnosis')
        pre_eclampsia = StandardValue.objects.get(value='severe preeclampsia')
        health = StandardValue.objects.get(value='Health')

        samples_in_experiment= Sample.objects.filter(experiment=exp)

        for sample in samples_in_experiment:
            sample_name = SampleAttribute.objects.get(
                            sample=sample,
                            old_name='name').old_value
            sample_name = str(sample_name)[:-2] # delete " 1" in the end
            print(sample_name)
            if sample_name in health_samples:
                SampleAttribute.objects.create(sample=sample,
                                               unificated_name=diagnosis,
                                               unificated_value=health)

            elif sample_name in pre_eclampsia_samples:
                SampleAttribute.objects.create(sample=sample,
                                               unificated_name=diagnosis,
                                               unificated_value=pre_eclampsia)
                # for item in d:
                #     item.delete()

            else:
                print("something went wrong")


import pytest

import nengo
from nengo.base import NengoObjectParam

def test_nengoobjectparam():
    """NengoObjectParam must be a Nengo object and is readonly by default."""
    class Test(object):
        nop = NengoObjectParam()

    inst = Test()
    assert inst.nop is None
    # Must be a Nengo object
    with pytest.raises(ValueError):
        inst.nop = 'a'
    a = nengo.Ensemble(10, dimensions=2, add_to_container=False)
    inst.nop = a.neurons
    assert inst.nop is a.neurons
    # Can't set it twice
    with pytest.raises(ValueError):
        inst.nop = a

def test_nengoobjectparam_nonzero():
    """Can check that objects have nonzero size in/out."""
    class Test(object):
        nin = NengoObjectParam(nonzero_size_in=True)
        nout = NengoObjectParam(nonzero_size_out=True)

    inst = Test()
    with nengo.Network():
        nin = nengo.Node(output=lambda t: t)
        nout = nengo.Node(output=lambda t, x: None, size_in=1)
        probe = nengo.Probe(nin)

        with pytest.raises(ValueError):
            inst.nin = nin
        with pytest.raises(ValueError):
            inst.nout = nout
        with pytest.raises(ValueError):
            inst.nout = probe

        inst.nin = nout
        inst.nout = nin

if __name__ == "__main__":
    nengo.log(debug=True)
    pytest.main([__file__, '-v'])


from typing import Optional

from pydantic import BaseModel, root_validator

__author__ = "Bruno Lange"
__email__ = "blangeram@gmail.com"
__license__ = "MIT"

class Model(BaseModel):
    name: str

class Node(BaseModel):
    label: str
    value: int

class NodePatch(BaseModel):
    label: Optional[str]
    value: Optional[int]

    @root_validator
    def at_least_one(cls, values):
        if not values["value"] and not values["label"]:
            raise ValueError("must provide either label or value (or both)")
        return values


from flask import Flask, render_template
from data import get_data

app = Flask(__name__)

Tutors = get_data()

@app.route('/')
def index():
    return render_template('index.html', tutors = Tutors)

@app.route('/about/')
def about():
    return render_template('about.html')

@app.route('/category/<string:category>/')
def category(category):
    mastered_tutors = []
    cap_cat = category.capitalize()
    if (category == "languages"):
        print("Yay")
        cap_cat = "Foreign Language"
    if (category == "standardized"):
        cap_cat = "Standardized Testing"
    if (category == "cs"):
        cap_cat = "Computer Science"
    for tutor in Tutors:
        if (tutor.subject.find(cap_cat) >= 0):
            mastered_tutors.append(tutor)
    return render_template('category.html', tutors = mastered_tutors, category = cap_cat)

@app.route('/tutors/<string:id>/')
def tutor(id):
    index = int(id) - 1
    return render_template('tutor.html', id = id, tutor = Tutors[index])

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


from torchvision.models import resnet50, ResNet50_Weights,resnet34, ResNet34_Weights
import models
import torchvision.transforms as transforms
import torch

class AddGaussianNoise(object):
    # Custom class to add gaussian noise to input images as data augmentation
    def __init__(self, mean=0., std=1.):
        self.std = std
        self.mean = mean

    def __call__(self, tensor):
        return tensor + torch.randn(tensor.size()) * self.std + self.mean

    def __repr__(self):
        return self.__class__.__name__ + '(mean={0}, std={1})'.format(self.mean, self.std)

#Self defined functions must be defined for adjust contrast and sharpness because they are functional pytorch augmentations that cannot be chained via compose normally
def adjust_contrast_compose_transform(cf):
    def _func(img):
        return transforms.functional.adjust_contrast(img,contrast_factor=cf) # 1 for original image, 2 for increasing constrast by factor of 2, will have to be tuned to our data
    return _func

class ModelManager():
    def __init__(self,input_size=512,contrast_factor = 1.2, gaussian_std = 0.1, affine_rotation=30, affine_translate_ratio=0.2):
        """
        This class should manage all the models we want to experiment with,
        either from direct import from pytorch or from the models folder
        """
        self.pretraining_source = ["imagenet",'random']
        # NOTE IF adding noise, MUST add noise AFTER normalize, or else image will become all noise
        # Current hyperparams are determined to be best after empirical tests
        # Standard transformation stack should be contrast -> normalize -> gaussianNoise.
        # Resizing can be done before or after contrast
        self.transform_string_key_base = {'gaussiannoise':AddGaussianNoise(0.,gaussian_std), #MUST set std to a value between 0 - 0.2 or else image becomes TOO much noise since tensor pixels are autoscaled to 0-1
                                        'normalize':transforms.Normalize((0.1875,),(0.198,)),
                                        'resize':transforms.Resize((input_size, input_size)),
                                        'adjust_contrast':adjust_contrast_compose_transform(contrast_factor),
                                        'random_affine':transforms.RandomAffine(degrees=affine_rotation,translate=(affine_translate_ratio,affine_translate_ratio))} #random image rotation by arg degree and translate by arg.decimal% of input_image size

    def get_model(self, model_name="resnet34", pretrain_source="imagenet", **kwargs):
        if model_name == "resnet34":
            return self.pretrained_resnet34(pretrain_source)
        elif model_name == "resnet50":
            return self.pretrained_resnet50(pretrain_source)
        elif model_name == "simpleconv":
            return models.Simpleconv(), None
        elif model_name == "inceptionv3":
            return models.InceptionV3(), None
        elif model_name == "bilbily":
            return models.Bilbily(**kwargs), None
        elif model_name == "vgg16":
            return models.Vgg16(), None
        else:
            raise ValueError("Wrong model name")

    def pretrained_resnet50(self,pretrain_source="imagenet"):

        if pretrain_source not in self.pretraining_source:
            raise NotImplementedError(f"The specified pretrain_source argument {pretrain_source} is not supported, please use one of the following options: {' '.join(self.pretraining_source)}")

        if pretrain_source == "imagenet":

            resnet50_model = resnet50(weights=ResNet50_Weights.DEFAULT)
            # Some pretrained models have packaged preprocessing transforms that should be applied/wrapped to input to ensure performance
            return resnet50_model, ResNet50_Weights.DEFAULT.transforms()

        elif pretrain_source == "random":

            resnet50_model = resnet50(weights=None)
            return resnet50_model, None

    def pretrained_resnet34(self,pretrain_source="imagenet"):

            if pretrain_source not in self.pretraining_source:
                raise NotImplementedError(f"The specified pretrain_source argument {pretrain_source} is not supported, please use one of the following options: {' '.join(self.pretraining_source)}")

            if pretrain_source == "imagenet":

                resnet34_model = resnet34(weights=ResNet34_Weights.DEFAULT)
                # Some pretrained models have packaged preprocessing transforms that should be applied/wrapped to input to ensure performance
                return resnet34_model, ResNet34_Weights.DEFAULT.transforms()

            elif pretrain_source == "random":

                resnet34_model = resnet34(weights=None)
                return resnet34_model, None

    def get_data_transform(self,transform_string_keys):
        compose_list = []
        for t in transform_string_keys:
            if t.lower() not in self.transform_string_key_base.keys():
                raise NotImplementedError(f"The specified data transform  {t} is not supported, please use one of the following options: {' '.join(self.transform_string_key_base.keys())}")
            compose_list.append(self.transform_string_key_base[t])

        composed_transforms = transforms.Compose(compose_list)
        return composed_transforms


'''
Hendra Soewarno (0119067305)
Honeypot TFTP ini tidak disertai pembatasan jumlah thread, sehingga perlu dilakukan
pembatasan pada level firewall.
/sbin/iptables  -A INPUT -p udp --syn --dport 6969 -m connlimit --connlimit-above 50 -j REJECT
TFtpSvr mensimulasikan server ftp untuk sebagai honeypot yang menarik penyerang
untuk melakukan bruteforce password. Honeypot akan merekam semua userid dan password
yang dicoba penyerang, sehingga menjadi early warning bagi administrator terkait dengan
userid/password yang compromis.
nohup python /path/to/tftpsvr.py &
'''
#!/usr/bin/env python3
import time
import datetime
import socket
import os
import logging
from logging.handlers import TimedRotatingFileHandler
from _thread import *
from pathlib import Path

class Client:
    def __init__(self, opcode, filename, mode):
        self.opcode = opcode
        self.time = time.time()
        self.mode = mode
        self.currentBlock = 0
        self.ackBlock = -1
        self.closed = False
        self.errorCode = -1
        now = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%d%H%M%S") + "."
        fn=Path(filename.decode("utf-8").replace(".",now,1))
        try:
            if opcode==1: #Read request RRQ
                self.ackBlock = 0
                self.currentBlock = 0
                self.file0=open(filename, "rb")
            else:
                self.file0=open(fn, "xb")
                self.file1=open(filename, "wb")

        except IOError:
            self.errorCode = 1
            self.closed = True

    def isClosed(self):
        return self.closed

    def isTimeOut(self):
        timeout = False
        if time.time() - self.time > 10: #second
            self.file0.close()
            if self.getOpcode() > 1:
                self.file1.close()
            timeout = True
        return timeout

    def getOpcode(self):
        return self.opcode

    def getErrorCode(self):
        return self.errorCode

class RRQClient(Client):

    def getNextBlock(self):
        return self.ackBlock+1

    def getNextData(self):
        if self.currentBlock == self.ackBlock:
            self.currentBlock = self.ackBlock + 1 #step next
            self.lastData = self.file0.read(512)
            if len(self.lastData) < 512: #EOF
                self.closed = True
                self.file0.close();
        return self.lastData

    def ackReceived(self, block):
        print("ACK Recieve")
        print(block)
        self.ackBlock=block

    def isNextDataReady(self):
        print("IsNExtDataReady")
        print(self.currentBlock)
        print(self.ackBlock)
        return (self.currentBlock == self.ackBlock) #RRQ

class WRQClient(Client):

    def putDataPacket(self, block, data):
        if block > self.ackBlock:
            self.file0.write(data)
            self.file1.write(data)
            self.currentBlock = block
        else:
            self.closed = True
            self.file0.close()
            self.file1.close()

    def isMustAck(self):
        return (self.ackBlock < self.currentBlock) #WRQ

    def getNextAckBlock(self):
        self.ackBlock=self.currentBlock
        return self.ackBlock

def craftAckPacket(block):
    return b'\0\4' + block.to_bytes(2, byteorder='big')

def craftDataPacket(block, data):
    return b'\0\3' + block.to_bytes(2, byteorder='big') + data

def craftErrorPacket(errorCode):
    error = [b'Not defined, see error message (if any).',
        b'File not found.',
        b'Access violation.',
        b'Disk full or allocation exceeded.',
        b'Unknown transfer ID.',
        b'File already exists.',
        b'No such user.'
    ]
    return b'\0\5' + errorCode.to_bytes(2, byteorder='big') + error[errorCode]

def parsePacketAndUpdate(client, address, packet):
    #https://tools.ietf.org/html/rfc1350
    opcode = int.from_bytes(packet[0:2],byteorder='big')
    '''
            pcode operation
            1     Read request (RRQ)
            2     Write request (WRQ)
            3     Data (DATA)
            4     Acknowledgment (ACK)
            5     Error (ERROR)
    '''
    if opcode == 1 or opcode == 2: #RRQ or WRQ
        print(packet)
        logger.info(packet)
        firstZPos = packet[2:].find(b'\0')
        filename =  packet[2:][0:firstZPos]
        secondZPos = packet[2:][0:firstZPos].find(b'\0')
        mode = packet[2+firstZPos+1:secondZPos]
        secondZPos = packet[2+firstZPos:].find(b'\0')
        if opcode==1:
            client[address] = RRQClient(opcode, filename, mode)
        else:
            client[address] = WRQClient(opcode, filename, mode)

    elif opcode == 3: #DATA only posible for WRQ
        block = int.from_bytes(packet[2:4],byteorder='big')
        data = packet[4:]
        client[address].putDataPacket(block,data)

    elif opcode == 4: #ACK only posible for RRQ
        print(packet)
        block = int.from_bytes(packet[2:],byteorder='big')
        client[address].ackReceived(block)

    else: #ERROR
        print(packet)
        logger.info(packet)
        errorCode=int.from_bytes(packet[2:4],byteorder='big')
        '''
            Value     Meaning
            0         Not defined, see error message (if any).
            1         File not found.
            2         Access violation.
            3         Disk full or allocation exceeded.
            4         Illegal TFTP operation.
            5         Unknown transfer ID.
            6         File already exists.
            7         No such user.
        '''
        errMsg=packet[4:-1]

#entry point
VERSION = "0.1a"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
host = "0.0.0.0"
port = 6969
ThreadCount = 0

#create logger object
logger = logging.getLogger()
logger.setLevel(logging.INFO)

#create logrotate daily, keep 30 days
handler = TimedRotatingFileHandler('HPOTtftp.log',
    when='midnight',
    interval=1,
    backupCount=30)

log_format="%(asctime)s %(levelname)s %(threadName)s %(message)s"
handler.setFormatter(logging.Formatter(log_format))
logger.addHandler(handler)

try:
    sock.bind((host, port))
except Exception as e:
    print(str(e))

logger.info("TFTP HoneyPot " + VERSION + " ready at port " + str(port))
print("TFTP HoneyPot " + VERSION + " ready at port " + str(port))

client = dict() #maintain each client session

while True:
    ## Get the data and the address
    packet, address = sock.recvfrom(4096)
    print(address)
    logger.info(address)
    parsePacketAndUpdate(client, address, packet)

    try:

        if address in client:
            currentClient=client[address]
            if currentClient.getErrorCode() > -1:
                sock.sendto(craftErrorPacket(currentClient.getErrorCode()), address)

        for scanAddr in list(client):
            if client[scanAddr].isClosed():
                print("Closed")
                logger.info("Closed")
                client.pop(scanAddr) #remove from client session
            elif client[scanAddr].isTimeOut():
                print("Timeout")
                logger.info("Timeout")
                client.pop(scanAddr) #remove from client session

        if address in client:
            currentClient=client[address]
            if currentClient.getOpcode()==1:
                if currentClient.isNextDataReady():
                    sock.sendto(craftDataPacket(currentClient.getNextBlock(), currentClient.getNextData()), address)
            elif client[address].getOpcode()==2:
                if currentClient.isMustAck():
                    sock.sendto(craftAckPacket(currentClient.getNextAckBlock()), address)

    except Exception as e:
        print(str(e))


from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render, redirect
from tablib import Dataset

from .models import Internal, Exportal,UpdateInfo
from django.views.generic import ListView
from .forms import UploadForm
from .resource import InternalResource,ExportalResource

# Create your views here.
class InternalListView(ListView):
    model = Internal
    template_name = "product/internal_list.html"

class UpdateInfoListView(ListView):
    model = UpdateInfo
    template_name = "product/update_info.html"

class LineListView(ListView):
    queryset = Internal.objects.filter(line=True)
    template_name = "product/line_list.html"

class ExportalListView(ListView):
    model = Exportal
    template_name = "product/exportal_list.html"

def internal_upload(request):
    if request.method == 'POST':
        new_internal = InternalResource()
        dataset = Dataset()
        new_internal = request.FILES['file']
        imported_data = dataset.load(new_internal.read(), format='xlsx')
        for data in imported_data:
            print(data[1])
            value = Internal(
                data[0],
                data[1],
                data[2],
                data[3],
                data[4],
                data[5],
                data[6],
                data[7],
                data[8],
                data[9],
                data[10],
                data[11],
                data[12],
                data[13],
            )
            value.save()
            UpdateInfo.objects.create(user=request.user,file_name="file")
    return render(request, 'product/add_internal.html')

def exportal_upload(request):
    if request.method == 'POST':
        exportal_rescource = ExportalResource()
        dataset = Dataset()
        new_persons = request.FILES['file']
        imported_data = dataset.load(new_persons.read(), format='xlsx')
        for data in imported_data:
            print(data[1])
            value = Exportal(
                data[0],
                data[1],
                data[2],
                data[3],
                data[4],
                data[5],
                data[6],
                data[7],
                data[8],
                data[9],
                data[10],
                data[11],
                data[12],
                data[13],
                data[14],
                data[15],
                data[16],
                data[17],
                data[18],
                data[19],
                data[20],

            )
            value.save()
            UpdateInfo.objects.create(user=request.user, file_name="file")
            # result = person_resource.import_data(dataset, dry_run=True)  # Test the data import

        # if not result.has_errors():
        #    person_resource.import_data(dataset, dry_run=False)  # Actually import now

    return render(request, 'product/add_exportal.html')


import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import matplotlib.pyplot as plt
import torch.nn.functional as F
import tensorflow as tf

device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
# device = 'cpu'

class regression_data(Dataset):
    def __init__(self, x, y, normalise=True):
        super(regression_data, self).__init__()
        self.update_data(x, y, normalise)

    def __len__(self):
        return self.x.shape[0]

    def __getitem__(self, index):
        x = torch.tensor(self.x[index]).float()
        y = torch.tensor(self.y[index]).float()
        return x, y

    def update_data(self, x, y, normalise=True, update_stats=True):
        assert x.shape[0] == y.shape[0]
        self.x = x
        self.y = y
        # normalise data
        self.normalise = normalise
        if update_stats:
            self.x_mean = self.x.mean(0) if normalise else 0.0
            self.x_std = self.x.std(0) if normalise else 1.0
            self.y_mean = self.y.mean(0) if normalise else 0.0
            self.y_std = self.y.std(0) if normalise else 1.0
        if self.normalise:
            self.x = normalise_data(self.x, self.x_mean, self.x_std)
            self.y = normalise_data(self.y, self.y_mean, self.y_std)

def to_numpy(x):
    if torch.is_tensor(x):
        return x.detach().cpu().numpy()
    else:
        return x

def normalise_data(x, mean, std):
    return (x - mean) / std

def unnormalise_data(x, mean, std):
    return x * std + mean

def import_dataset(fname):
    data = np.genfromtxt(fname, delimiter=',')
    return data

def import_train_test():
    noise_std = 0.1
    train = import_dataset(f'bayes_approx/datasets/gp_reg_dataset/training_sample_points{noise_std}.csv')
    test = import_dataset(f'bayes_approx/datasets/gp_reg_dataset/sample_function{noise_std}.csv')
    return train, test, noise_std

def create_regression_dataset():
    train, test, noise_std = import_train_test()
    train_x = train[:,0].reshape(-1,1); train_y = train[:,1].reshape(-1,1)
    test_x = test[:,0].reshape(-1,1); test_y = test[:,1].reshape(-1,1)
    normalised_train = regression_data(train_x, train_y)
    test = regression_data(test_x, test_y, normalise=False)

    # plt.plot(train_x, train_y, 'ro', label='data')
    # plt.plot(test_x, test_y, 'k-', label='ground-truth')
    # plt.legend()
    # plt.title('ground-truth function')
    # plt.show()

    train_loader = DataLoader(normalised_train, batch_size=50, shuffle=True)
    test_loader = DataLoader(test, batch_size=1000, shuffle=True)
    return train_loader, test_loader, normalised_train, test, noise_std

def create_regression_dataset_kf(kf):
    train, test, noise_std = import_train_test()
    train_x = train[:,0].reshape(-1,1); train_y = train[:,1].reshape(-1,1)
    test_x = test[:,0].reshape(-1,1); test_y = test[:,1].reshape(-1,1)

    # kf split
    normalised_train_list = []
    val_list = []
    train_loader_list = []
    val_loader_list = []
    for train_index, val_index in kf.split(train_x):
        kf_train_x = train_x[train_index]
        kf_train_y = train_y[train_index]
        kf_val_x = train_x[val_index]
        kf_val_y = train_y[val_index]

        # plt.scatter(kf_train_x, kf_train_y)
        # plt.scatter(kf_val_x, kf_val_y)

        normalised_train_list.append(regression_data(kf_train_x, kf_train_y))
        val_list.append(regression_data(kf_val_x, kf_val_y, normalise=False))

        train_loader_list.append(DataLoader(normalised_train_list[-1], batch_size=50, shuffle=True))
        val_loader_list.append(DataLoader(val_list[-1], batch_size=50, shuffle=True))

    test = regression_data(test_x, test_y, normalise=False)

    # plt.plot(test_x, test_y, '-k', label='ground-truth')
    # plt.legend()
    # plt.title('ground-truth function')
    # plt.show()

    test_loader = DataLoader(test, batch_size=1000, shuffle=True)
    return train_loader_list, val_loader_list, test_loader, normalised_train_list, val_list, test, noise_std

def get_regression_results(model, x, predict, dataset, K=50, log_lik_var=None):
    y_pred_mean, y_pred_std = predict(model, x, K=K)  # shape (K, N_test, y_dim)
    if log_lik_var is not None:
        # total uncertainty: here the preditive std needs to count for output noise variance
        y_pred_std = (y_pred_std**2 + torch.exp(log_lik_var)).sqrt()
    # unnormalise
    y_pred_mean = unnormalise_data(to_numpy(y_pred_mean), dataset.y_mean, dataset.y_std)
    # y_pred_mean = unnormalise_data(y_pred_mean, dataset.y_mean, dataset.y_std)
    y_pred_std = unnormalise_data(to_numpy(y_pred_std), 0.0, dataset.y_std)
    # y_pred_std = unnormalise_data(y_pred_std, 0.0, dataset.y_std)
    return y_pred_mean, y_pred_std

def get_unnormal_regression_results(model, x, predict, K=50, log_lik_var=None):
    y_pred_mean, y_pred_std = predict(model, x, K=K)  # shape (K, N_test, y_dim)
    if log_lik_var is not None:
        # total uncertainty: here the preditive std needs to count for output noise variance
        y_pred_std = (y_pred_std**2 + torch.exp(log_lik_var)).sqrt()
    return to_numpy(y_pred_mean), to_numpy(y_pred_std)

def plot_regression(normal_train, test, y_pred_mean, y_pred_std_noiseless,
                    y_pred_std, y_pred_mean_samples, title='', exp_name=None):
    x_train = unnormalise_data(normal_train.x, normal_train.x_mean, normal_train.x_std)
    y_train = unnormalise_data(normal_train.y, normal_train.y_mean, normal_train.y_std)

    # first for the total uncertainty (model/epistemic + data/aleatoric)
    plt.figure(figsize=(12, 6))
    plt.plot(x_train, y_train, "kx", mew=2, label='noisy sample points')
    plt.plot(test.x, y_pred_mean, "C0", lw=2, label='prediction mean')
    plt.fill_between(
        test.x[:,0],
        y_pred_mean[:,0] - 1.96 * y_pred_std[:,0],  # 95% confidence interval
        y_pred_mean[:,0] + 1.96 * y_pred_std[:,0],
        # y_pred_mean - 1.96 * y_pred_std,  # 95% confidence interval
        # y_pred_mean + 1.96 * y_pred_std,
        color="C0",
        alpha=0.2,
        label='total uncertainity'
    )
    plt.fill_between(
        test.x[:,0],
        y_pred_mean[:,0] - 1.96 * y_pred_std_noiseless[:,0],  # 95% confidence interval
        y_pred_mean[:,0] + 1.96 * y_pred_std_noiseless[:,0],
        # y_pred_mean - 1.96 * y_pred_std_noiseless,  # 95% confidence interval
        # y_pred_mean + 1.96 * y_pred_std_noiseless,
        color="b",
        alpha=0.2,
        label='model uncertainity'
    )

    plt.plot(test.x, np.array(y_pred_mean_samples)[:,:,0].T, "C0", linewidth=0.5)

    plt.plot(test.x, test.y, color='orange', label='sample function')
    plt.legend()
    plt.title(title)
    if exp_name is not None:
        plt.savefig(f'./figures/{exp_name}_out.png', bbox_inches='tight')
    plt.show()

def plot_bnn_pred_post(model, predict, normal_train, test, log_lik_var,
                       title=None, exp_name=None, device=device):
    if title is None:
        title = 'BNN approximate posterior (MFVI)'
    # plot the BNN prior in function space
    x_test_norm = normalise_data(test.x, normal_train.x_mean, normal_train.x_std)
    x_test_norm = torch.tensor(x_test_norm,).float().to(device)

    y_pred_mean, y_pred_std_noiseless = get_regression_results(
        model, x_test_norm, predict, normal_train
    )
    y_pred_mean_samples = [
        get_regression_results(model, x_test_norm, predict, normal_train, K=1)[0]
        for _ in range(10)
    ]
    model_noise_std = unnormalise_data(to_numpy(torch.exp(0.5*log_lik_var)), 0.0, normal_train.y_std)
    y_pred_std = np.sqrt(y_pred_std_noiseless**2 + model_noise_std**2)
    plot_regression(
        normal_train, test, y_pred_mean, y_pred_std_noiseless, y_pred_std, y_pred_mean_samples, title, exp_name
    )
    print(f'model_std: {model_noise_std}, pred_std: {y_pred_std_noiseless.mean()}')

# def plot_training_loss(logs):
#     _, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
#     ax1.plot(np.arange(logs.shape[0]), logs[:, 0], 'r-')
#     ax2.plot(np.arange(logs.shape[0]), logs[:, 1], 'r-')
#     ax1.set_xlabel('epoch')
#     ax2.set_xlabel('epoch')
#     ax1.set_title('nll')
#     ax2.set_title('kl')
#     plt.show()

def mse_test_step(model, dataloader, normal_train, predict, log_lik_var=None):
    """
    Calculate mean squared error on test set (normalising to train).
    """
    # model.eval()
    tloss = 0
    with torch.no_grad():
        for x_test, y_test in dataloader:
            x_test_norm = normalise_data(x_test, normal_train.x_mean, normal_train.x_std).float()
            y_pred_mean, _ = get_regression_results(
                model, x_test_norm, predict, normal_train, 50, log_lik_var
            )
            tloss += F.mse_loss(torch.from_numpy(y_pred_mean), y_test)
    print('\nTest set: MSE: {}'.format(tloss))
    return tloss/len(dataloader)

def gnll_test_step(model, dataloader, normal_train, predict, log_lik_var=None):
    """
    Calculate mean gaussian negative log likelihood on test set (normalising to train).
    """
    # model.eval()
    tloss = 0
    with torch.no_grad():
        for x_test, y_test in dataloader:
            x_test_norm = normalise_data(x_test, normal_train.x_mean, normal_train.x_std).float()
            y_pred_mean, y_pred_std = get_regression_results(
                model, x_test_norm, predict, normal_train, 50, log_lik_var
            )
            tloss += F.gaussian_nll_loss(
                torch.from_numpy(y_pred_mean), y_test, torch.from_numpy(y_pred_std), full=True
            )/len(dataloader)
    print('\nTest set: GNLL: {}'.format(tloss))
    return tloss/len(dataloader)

def mse_train(model, dataloader, predict, log_lik_var=None):
    """
    Calculate mean squared error on train set (without normalising to train).
    """
    # model.eval()
    tloss = 0
    with torch.no_grad():
        for x, y in dataloader:
            y_pred_mean, _ = get_unnormal_regression_results(
                model, x, predict, 50, log_lik_var
            )
            tloss += F.mse_loss(torch.from_numpy(y_pred_mean), y)
    print('\nTrain set: MSE: {}'.format(tloss))
    return tloss/len(dataloader)

def gnll_train(model, dataloader, predict, log_lik_var):
    """
    Calculate mean gaussian negative log likelihood on train set (without normalising to train).
    """
    # model.eval()
    tloss = 0
    with torch.no_grad():
        for x, y in dataloader:
            y_pred_mean, y_pred_std = get_unnormal_regression_results(
                model, x, predict, 50, log_lik_var
            )
            tloss += F.gaussian_nll_loss(
                torch.from_numpy(y_pred_mean), y, torch.from_numpy(y_pred_std), full=True
            )/len(dataloader)
    print('\nTrain set: GNLL: {}'.format(tloss))
    return tloss

def gpflow_get_regression_results(m, x, train, lik_var=None, unnormalise=True):
    y_pred_mean, y_pred_var = m.predict_f(x)
    y_pred_std = y_pred_var**0.5
    if lik_var is not None:
        # total uncertainty: here the preditive std needs to count for output noise variance
        y_pred_std = (y_pred_std**2 + lik_var)**0.5
    if unnormalise:
        y_pred_mean = unnormalise_data(y_pred_mean, train.y_mean, train.y_std)
        y_pred_std = unnormalise_data(y_pred_std, 0.0, train.y_std)
    return y_pred_mean, y_pred_std

def gpflow_plot_bnn_pred_post(m, train, test, lik_var, title=None, exp_name=None):
    if title is None:
        title = 'BNN approximate posterior (MFVI)'
    # predict mean and variance of latent GP at test points
    x_test_norm = normalise_data(test.x, train.x_mean, train.x_std)
    y_pred_mean_norm, y_pred_var_noiseless_norm = m.predict_f(x_test_norm)
    y_pred_mean = unnormalise_data(y_pred_mean_norm, train.y_mean, train.y_std)
    y_pred_std_noiseless = unnormalise_data(np.sqrt(y_pred_var_noiseless_norm), 0.0, train.y_std)

    # generate 10 samples from posterior
    y_pred_mean_samples_norm = m.predict_f_samples(x_test_norm, 10)  # shape (10, 100, 1)
    y_pred_mean_samples = unnormalise_data(y_pred_mean_samples_norm, train.y_mean, train.y_std)

    model_noise_std = unnormalise_data(lik_var**0.5, 0.0, train.y_std)
    y_pred_std = np.sqrt(y_pred_std_noiseless**2 + model_noise_std**2)

    plot_regression(
        train, test, y_pred_mean, y_pred_std_noiseless, y_pred_std, y_pred_mean_samples, title, exp_name
    )
    print(f'model_std: {model_noise_std}, pred_std: {y_pred_std_noiseless.mean()}')

def gpflow_test_step(m, test, train, loss_func='mse', lik_var=None):
    x_test_norm = normalise_data(test.x, train.x_mean, train.x_std)
    y_pred_mean, y_pred_std = gpflow_get_regression_results(
        m, x_test_norm, train, lik_var
    )
    if loss_func == 'mse':
        mse = tf.keras.losses.MeanSquaredError()
        loss = mse(y_pred_mean, test.y).numpy()
        print('\nTest set: MSE: {}'.format(loss))
    elif loss_func == 'gnll':
        loss = np.mean(0.5 * (2*np.log(y_pred_std) + (y_pred_mean - test.y)**2 / y_pred_std**2))
        print('\nTest set: GNLL: {}'.format(loss))
    return loss

def gpflow_mse_train(m, train, lik_var=None):
    y_pred_mean, _ = gpflow_get_regression_results(
        m, train.x, None, lik_var, False
    )
    mse = tf.keras.losses.MeanSquaredError()
    loss = mse(y_pred_mean, train.y).numpy()
    print('\nTrain set: MSE: {}'.format(loss))
    return loss

if __name__ == '__main__':
    train_loader, test_loader, train, test, noise_std = create_regression_dataset()

    x_train = unnormalise_data(train.x, train.x_mean, train.x_std)
    y_train = unnormalise_data(train.y, train.y_mean, train.y_std)
    # first for the total uncertainty (model/epistemic + data/aleatoric)
    plt.figure(figsize=(12, 6))
    plt.plot(test.x, test.y)
    plt.plot(x_train, y_train, "kx", mew=2, label='noisy sample points')
    plt.fill_between(
        test.x[:,0],
        # y_pred_mean[:,0] - 1.96 * y_pred_std[:,0],  # 95% confidence interval
        # y_pred_mean[:,0] + 1.96 * y_pred_std[:,0],
        test.y[:,0] - 1.96 * 0.1,  # 95% confidence interval
        test.y[:,0] + 1.96 * 0.1,
        color="C0",
        alpha=0.2,
        label='noise uncertainity (95% ci)'
    )
    plt.plot(test.x, test.y, color='orange', label='sample function')
    plt.legend()
    plt.title('GP Sample Function Regression Dataset')
    plt.show()


import requests
import hashlib
import base58
import codecs
import ecdsa
private_key = "18e14a7b6aaaaaaaaaa4f8114701e7c8e774e7f9a47e2c2035db29a206321725"
print(private_key)

#randomizing the startpoint at every program launch, so you dont scroll the same wallets again and again
a =int(input("Enter a big random number(1-9999999999999999999999): "))
if a % 2 == 0:
	private_key_decimal = int(private_key, base=16)
	private_key_decimal += a
	private_key=str(hex(private_key_decimal))
	#print(private_key,"\n",type(private_key))
	private_key = private_key[2:]
else:
	private_key_decimal = int(private_key, base=16)
	private_key_decimal -= a
	private_key=str(hex(private_key_decimal))
	#print(private_key,"\n",type(private_key))
	private_key = private_key[2:]

def gen_public_key(private_key):

	private_key_bytes = codecs.decode(private_key, 'hex')
	public_key_raw = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1).verifying_key
	public_key_bytes = public_key_raw.to_string()
	public_key_hex = codecs.encode(public_key_bytes, 'hex')
	public_key = (b'04' + public_key_hex).decode("utf-8")

	if (ord(bytearray.fromhex(public_key[-2:])) % 2 == 0):
	    public_key_compressed = '02'
	else:
	    public_key_compressed = '03'

	public_key_compressed += public_key[2:66]

	hex_str = bytearray.fromhex(public_key_compressed)
	sha = hashlib.sha256()
	sha.update(hex_str)

	rip = hashlib.new('ripemd160')
	rip.update(sha.digest())
	key_hash = rip.hexdigest()

	modified_key_hash = "00" + key_hash

	sha = hashlib.sha256()
	hex_str = bytearray.fromhex(modified_key_hash)
	sha.update(hex_str)

	sha_2 = hashlib.sha256()
	sha_2.update(sha.digest())

	checksum = sha_2.hexdigest()[:8]

	byte_25_address = modified_key_hash + checksum

	address = base58.b58encode(bytes(bytearray.fromhex(byte_25_address))).decode('utf-8')
	print(f"Privatekey: {private_key}")
	print(f"Publickey: {address}")
	print("-----------------------------------------------------------------------------------------------")
	return address

while True:
	private_key_decimal = int(private_key, base=16)
	private_key_decimal += 1
	private_key=str(hex(private_key_decimal))
	private_key = private_key[2:]
	pub_key = gen_public_key(private_key)
	data = requests.get(f"https://blockstream.info/api/address/{pub_key}").json()
	eingehend = data["chain_stats"]["funded_txo_count"]
	print(f'Balance: {data["chain_stats"]["funded_txo_sum"]-data["chain_stats"]["spent_txo_sum"]}')
	if eingehend >= 1:
		with open("yay.txt","a") as f:
			f.write(f"{private_key}\n")


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import cv2
import numpy as np
import os
import six

default_config = {
    "shuffle": True,
    "min_resize": 0.5,
    "max_resize": 4,
    "crop_size": 769,
}

def slice_with_pad(a, s, value=0):
    pads = []
    slices = []
    for i in range(len(a.shape)):
        if i >= len(s):
            pads.append([0, 0])
            slices.append([0, a.shape[i]])
        else:
            l, r = s[i]
            if l < 0:
                pl = -l
                l = 0
            else:
                pl = 0
            if r > a.shape[i]:
                pr = r - a.shape[i]
                r = a.shape[i]
            else:
                pr = 0
            pads.append([pl, pr])
            slices.append([l, r])
    slices = list(map(lambda x: slice(x[0], x[1], 1), slices))
    a = a[slices]
    a = np.pad(a, pad_width=pads, mode='constant', constant_values=value)
    return a

class CityscapeDataset:
    def __init__(self, dataset_dir, subset='train', config=default_config):
        label_dirname = os.path.join(dataset_dir, 'gtFine/' + subset)
        if six.PY2:
            import commands
            label_files = commands.getoutput(
                "find %s -type f | grep labelTrainIds | sort" %
                label_dirname).splitlines()
        else:
            import subprocess
            label_files = subprocess.getstatusoutput(
                "find %s -type f | grep labelTrainIds | sort" %
                label_dirname)[-1].splitlines()
        self.label_files = label_files
        self.label_dirname = label_dirname
        self.index = 0
        self.subset = subset
        self.dataset_dir = dataset_dir
        self.config = config
        self.reset()
        print("total number", len(label_files))

    def reset(self, shuffle=False):
        self.index = 0
        if self.config["shuffle"]:
            np.random.shuffle(self.label_files)

    def next_img(self):
        self.index += 1
        if self.index >= len(self.label_files):
            self.reset()

    def get_img(self):
        shape = self.config["crop_size"]
        while True:
            ln = self.label_files[self.index]
            img_name = os.path.join(
                self.dataset_dir,
                'leftImg8bit/' + self.subset + ln[len(self.label_dirname):])
            img_name = img_name.replace('gtFine_labelTrainIds', 'leftImg8bit')
            label = cv2.imread(ln)
            img = cv2.imread(img_name)
            if img is None:
                print("load img failed:", img_name)
                self.next_img()
            else:
                break
        if shape == -1:
            return img, label, ln

        if np.random.rand() > 0.5:
            range_l = 1
            range_r = self.config['max_resize']
        else:
            range_l = self.config['min_resize']
            range_r = 1

        if np.random.rand() > 0.5:
            assert len(img.shape) == 3 and len(
                label.shape) == 3, "{} {}".format(img.shape, label.shape)
            img = img[:, :, ::-1]
            label = label[:, :, ::-1]

        random_scale = np.random.rand(1) * (range_r - range_l) + range_l
        crop_size = int(shape / random_scale)
        bb = crop_size // 2

        def _randint(low, high):
            return int(np.random.rand(1) * (high - low) + low)

        offset_x = np.random.randint(bb, max(bb + 1, img.shape[0] -
                                             bb)) - crop_size // 2
        offset_y = np.random.randint(bb, max(bb + 1, img.shape[1] -
                                             bb)) - crop_size // 2
        img_crop = slice_with_pad(img, [[offset_x, offset_x + crop_size],
                                        [offset_y, offset_y + crop_size]], 128)
        img = cv2.resize(img_crop, (shape, shape))
        label_crop = slice_with_pad(label, [[offset_x, offset_x + crop_size],
                                            [offset_y, offset_y + crop_size]],
                                    255)
        label = cv2.resize(
            label_crop, (shape, shape), interpolation=cv2.INTER_NEAREST)
        return img, label, ln + str(
            (offset_x, offset_y, crop_size, random_scale))

    def get_batch(self, batch_size=1):
        imgs = []
        labels = []
        names = []
        while len(imgs) < batch_size:
            img, label, ln = self.get_img()
            imgs.append(img)
            labels.append(label)
            names.append(ln)
            self.next_img()
        return np.array(imgs), np.array(labels), names

    def get_batch_generator(self, batch_size, total_step):
        def do_get_batch():
            for i in range(total_step):
                imgs, labels, names = self.get_batch(batch_size)
                labels = labels.astype(np.int32)[:, :, :, 0]
                imgs = imgs[:, :, :, ::-1].transpose(
                    0, 3, 1, 2).astype(np.float32) / (255.0 / 2) - 1
                yield i, imgs, labels, names

        batches = do_get_batch()
        try:
            from prefetch_generator import BackgroundGenerator
            batches = BackgroundGenerator(batches, 100)
        except:
            print(
                "You can install 'prefetch_generator' for acceleration of data reading."
            )
        return batches


#!/usr/bin/env python
# encoding: utf-8
import wx, os, shutil, weakref, copy
import wx.grid as gridlib
from pyo import sndinfo
from constants import *
import QLiveLib

class SoundFileObject:
    def __init__(self, id, filename, loopmode=0, transpo=1, gain=0,
                 playing=0, directout=True, startpoint=0,
                 endpoint=-1, crossfade=5, channel=0):
        self.id = id
        self.filename = filename
        sndfolder = os.path.join(QLiveLib.getVar("projectFolder"), "sounds")
        info = sndinfo(os.path.join(sndfolder, self.filename))
        if info is None:
            self.valid = False
            self.duration = -1
        else:
            self.valid = True
            self.duration = info[1]
        self.loopmode = loopmode
        self.transpo = transpo
        self.gain = gain
        self.playing = playing
        self.directout = directout
        self.startpoint = startpoint
        self.endpoint = self.duration
        self.crossfade = crossfade
        self.channel = channel

        self.playerRef = None

        self.currentCue = 0
        self.cues = {}
        self.saveCue()

    def setPlayerRef(self, obj):
        if obj is None:
            self.playerRef = None
        else:
            self.playerRef = weakref.ref(obj)

    def getAttributes(self):
        return {
                ID_COL_FILENAME: self.filename,
                ID_COL_LOOPMODE: self.loopmode,
                ID_COL_TRANSPO: self.transpo,
                ID_COL_GAIN: self.gain,
                ID_COL_PLAYING: self.playing,
                ID_COL_DIRECTOUT: self.directout,
                ID_COL_STARTPOINT: self.startpoint,
                ID_COL_ENDPOINT: self.endpoint,
                ID_COL_CROSSFADE: self.crossfade,
                ID_COL_CHANNEL: self.channel
                }

    def setAttributes(self, dict):
        self.filename = dict[ID_COL_FILENAME]
        self.loopmode = dict[ID_COL_LOOPMODE]
        self.transpo = dict[ID_COL_TRANSPO]
        self.gain = dict[ID_COL_GAIN]
        self.playing = dict[ID_COL_PLAYING]
        self.directout = dict[ID_COL_DIRECTOUT]
        self.startpoint = dict[ID_COL_STARTPOINT]
        self.endpoint = dict[ID_COL_ENDPOINT]
        self.crossfade = dict[ID_COL_CROSSFADE]
        self.channel = dict[ID_COL_CHANNEL]

    def copy(self, obj):
        self.setAttributes(copy.deepcopy(obj.getAttributes()))
        self.currentCue = obj.getCurrentCue()
        self.setCues(copy.deepcopy(obj.getCues()))

    def setCurrentCue(self, x):
        self.currentCue = x

    def getCurrentCue(self):
        return self.currentCue

    def loadCue(self, x):
        if x in self.cues:
            self.setAttributes(self.cues[x])
        else:
            c = x
            while (c >= 0):
                if c in self.cues:
                    self.setAttributes(self.cues[c])
                    break
                c -= 1
        self.currentCue = x
        if self.playerRef is not None:
            player = self.playerRef()
            player.setAttributes(self.getAttributes())

    def delCue(self, x):
        del self.cues[x]
        for i in range(x+1, len(self.cues)):
            if i in self.cues:
                self.cues[i-1] = self.cues[i]
                del self.cues[i]

    def saveCue(self):
        self.cues[self.currentCue] = self.getAttributes()

    def addCue(self, x):
        self.currentCue = x
        self.saveCue()

    def getCues(self):
        return self.cues

    def setCues(self, cues):
        self.cues = cues

    def isValid(self):
        return self.valid

    def getId(self):
        return self.id

    def setId(self, x):
        self.id = x

    def setPlayerAttribute(self, id, value):
        if self.playerRef is not None:
            player = self.playerRef()
            player.setAttribute(id, value)

    def getFilename(self):
        return self.filename

    def setLoopMode(self, x):
        self.loopmode = x
        self.setPlayerAttribute(ID_COL_LOOPMODE, x)

    def getTranspo(self):
        return self.transpo

    def setTranspo(self, x):
        self.transpo = x
        self.setPlayerAttribute(ID_COL_TRANSPO, x)

    def getGain(self):
        return self.gain

    def setGain(self, x):
        self.gain = x
        self.setPlayerAttribute(ID_COL_GAIN, x)

    def getPlaying(self):
        return self.playing

    def setPlaying(self, x):
        self.playing = x
        self.setPlayerAttribute(ID_COL_PLAYING, x)

    def getDirectOut(self):
        return self.directout

    def setDirectOut(self, x):
        self.directout = x
        self.setPlayerAttribute(ID_COL_DIRECTOUT, x)

    def getStartPoint(self):
        return self.startpoint

    def setStartPoint(self, x):
        self.startpoint = x
        self.setPlayerAttribute(ID_COL_STARTPOINT, x)

    def getEndPoint(self):
        return self.endpoint

    def setEndPoint(self, x):
        self.endpoint = x
        self.setPlayerAttribute(ID_COL_ENDPOINT, x)

    def getCrossfade(self):
        return self.crossfade

    def setCrossfade(self, x):
        self.crossfade = x
        self.setPlayerAttribute(ID_COL_CROSSFADE, x)

    def getDuration(self):
        return self.duration

    def setChannel(self, x):
        self.channel = x
        self.setPlayerAttribute(ID_COL_CHANNEL, x)

    def getChannel(self):
        return self.channel

class GridFileDropTarget(wx.FileDropTarget):
    def __init__(self, grid):
        wx.FileDropTarget.__init__(self)
        self.grid = grid

    def OnDropFiles(self, x, y, filenames):
        x, y = self.grid.CalcUnscrolledPosition(x, y)
        col = self.grid.XToCol(x)
        row = self.grid.YToRow(y)
        if row > -1 and col == ID_COL_FILENAME:
            filename = filenames[0]
            if sndinfo(filename) is not None:
                self.grid.copyToSoundsFolder(filename)
                self.grid.setSelRow(row)
                self.grid.loadSound(os.path.basename(filename))

class SoundFileGrid(gridlib.Grid):
    def __init__(self, parent):
        super(SoundFileGrid, self).__init__(parent, style=wx.SUNKEN_BORDER)

        self.selRow = self.selCol = -1
        self.objects = []

        self.setInitialValuesToNone()

        self.textColour = self.GetDefaultCellTextColour()
        self.SetColLabelAlignment(wx.CENTER, wx.CENTER)
        self.SetCellHighlightColour("#CCCCCC")
        self.SetCellHighlightPenWidth(0)
        self.SetCellHighlightROPenWidth(0)
        self.SetSelectionBackground("#FFFFFF")
        self.SetSelectionForeground("#000000")
        self.font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL,
                            wx.FONTWEIGHT_NORMAL, face="Monospace")
        self.SetRowLabelSize(50)

        dropTarget = GridFileDropTarget(self)
        self.SetDropTarget(dropTarget)

        self.CreateGrid(0, 10)

        for i, label in enumerate(LABELS):
            self.SetColMinimalWidth(i, COLSIZES[i])
            self.SetColSize(i, COLSIZES[i])
            self.SetColLabelValue(i, label)

        self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.OnCellChange)
        self.Bind(gridlib.EVT_GRID_EDITOR_HIDDEN, self.OnCellEditorHidden)
        self.Bind(gridlib.EVT_GRID_EDITOR_SHOWN, self.OnCellEditorShown)
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClick)
        self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK, self.OnCellRightClick)
        self.Bind(gridlib.EVT_GRID_LABEL_RIGHT_CLICK, self.OnLabelRightClick)
        self.GetGridWindow().Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.GetGridWindow().Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.GetGridWindow().Bind(wx.EVT_MOTION, self.OnMotion)
        self.GetGridWindow().Bind(wx.EVT_SIZE, self.OnSize)

        self.addRow()

    def setSelRow(self, row):
        self.selRow = row

    def copyToSoundsFolder(self, path):
        sndfolder = os.path.join(QLiveLib.getVar("projectFolder"), "sounds")
        shutil.copy(path, sndfolder)

    def OnSize(self, evt):
        w, _ = self.GetGridWindow().GetClientSize()
        sz = w - (sum(COLSIZES) - COLSIZES[0])
        if sz >= COLSIZES[0]:
            self.SetColSize(0, sz)
        evt.Skip()

    def setInitialValuesToNone(self):
        self.clickPosition = self.initialTranspo = self.initialGain = None
        self.initialStart = self.initialEnd = self.initialFade = None
        self.initialChannel = None

    def addRow(self, index=None):
        if index == None:
            self.AppendRows(1, True)
            row = self.GetNumberRows() - 1
        else:
            self.InsertRows(index, 1, True)
            row = index
        # Filename
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_FILENAME, attr)
        renderer = gridlib.GridCellAutoWrapStringRenderer()
        self.SetCellRenderer(row, ID_COL_FILENAME, renderer)
        self.SetCellValue(row, ID_COL_FILENAME, "Click to choose a sound")
        self.SetCellTextColour(row, ID_COL_FILENAME, "#888888")
        # Loop Mode
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_LOOPMODE, attr)
        # Transpo
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_TRANSPO, attr)
        rd = gridlib.GridCellFloatRenderer()
        rd.SetPrecision(4)
        self.SetCellRenderer(row, ID_COL_TRANSPO, rd)
        # Gain
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_GAIN, attr)
        rd = gridlib.GridCellFloatRenderer()
        rd.SetPrecision(2)
        self.SetCellRenderer(row, ID_COL_GAIN, rd)
        # Playing
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_PLAYING, attr)
        # Direct Out
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_DIRECTOUT, attr)
        # Start Point
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_STARTPOINT, attr)
        rd = gridlib.GridCellFloatRenderer()
        rd.SetPrecision(4)
        self.SetCellRenderer(row, ID_COL_STARTPOINT, rd)
        # End Point
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_ENDPOINT, attr)
        rd = gridlib.GridCellFloatRenderer()
        rd.SetPrecision(4)
        self.SetCellRenderer(row, ID_COL_ENDPOINT, rd)
        # Crossfade
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_CROSSFADE, attr)
        rd = gridlib.GridCellFloatRenderer()
        rd.SetPrecision(1)
        self.SetCellRenderer(row, ID_COL_CROSSFADE, rd)
        # Channel
        attr = gridlib.GridCellAttr()
        attr.SetReadOnly(True)
        self.SetAttr(row, ID_COL_CHANNEL, attr)
        rd = gridlib.GridCellNumberRenderer()
        self.SetCellRenderer(row, ID_COL_CROSSFADE, rd)

        self.SetCellAlignment(row, 0, wx.ALIGN_LEFT, wx.ALIGN_CENTER)
        for i in range(1, len(LABELS)):
            self.SetCellAlignment(row, i, wx.ALIGN_CENTER, wx.ALIGN_CENTER)

    def putObjectAttrOnCells(self, obj, row):
        attrs = obj.getAttributes()
        for key in sorted(attrs):
            if key == ID_COL_FILENAME:
                self.SetCellValue(row, key, attrs[key])
            elif key == ID_COL_LOOPMODE:
                self.SetCellValue(row, key, LOOPMODES[attrs[key]])
            elif key == ID_COL_PLAYING:
                self.SetCellValue(row, key, PLAYING[attrs[key]])
            else:
                self.SetCellValue(row, key, str(attrs[key]))
        self.SetCellTextColour(row, ID_COL_FILENAME, self.textColour)

    def OnCellChange(self, evt):
        self.selRow, self.selCol = evt.GetRow(), evt.GetCol()
        val = self.GetCellValue(self.selRow, self.selCol)
        if self.selCol == ID_COL_TRANSPO:
            self.objects[self.selRow].setTranspo(float(val))
        elif self.selCol == ID_COL_GAIN:
            self.objects[self.selRow].setGain(float(val))
        elif self.selCol == ID_COL_STARTPOINT:
            self.objects[self.selRow].setStartPoint(float(val))
        elif self.selCol == ID_COL_ENDPOINT:
            self.objects[self.selRow].setEndPoint(float(val))
        elif self.selCol == ID_COL_CROSSFADE:
            self.objects[self.selRow].setCrossfade(float(val))
        elif self.selCol == ID_COL_CHANNEL:
            self.objects[self.selRow].setChannel(int(val))
        evt.Skip()

    def OnLeftDown(self, evt):
        upos = self.CalcUnscrolledPosition(evt.GetPosition())
        self.selRow, self.selCol = self.XYToCell(*upos)
        if self.selRow < (self.GetNumberRows() - 1) and \
           self.selCol in [ID_COL_TRANSPO, ID_COL_GAIN, ID_COL_STARTPOINT,
                           ID_COL_ENDPOINT, ID_COL_CROSSFADE, ID_COL_CHANNEL]:
            self.clickPosition = evt.GetPosition()[1]
            self.GetGridWindow().CaptureMouse()
            if self.selCol == ID_COL_TRANSPO:
                self.initialTranspo = self.objects[self.selRow].getTranspo()
            elif self.selCol == ID_COL_GAIN:
                self.initialGain = self.objects[self.selRow].getGain()
            elif self.selCol == ID_COL_STARTPOINT:
                self.initialStart = self.objects[self.selRow].getStartPoint()
            elif self.selCol == ID_COL_ENDPOINT:
                self.initialEnd = self.objects[self.selRow].getEndPoint()
            elif self.selCol == ID_COL_CROSSFADE:
                self.initialFade = self.objects[self.selRow].getCrossfade()
            elif self.selCol == ID_COL_CHANNEL:
                self.initialChannel = self.objects[self.selRow].getChannel()
        evt.Skip()

    def OnLeftUp(self, evt):
        if self.GetGridWindow().HasCapture():
            self.setInitialValuesToNone()
            self.GetGridWindow().ReleaseMouse()
        evt.Skip()

    def clip(self, x, mi, ma):
        if x < mi:
            return mi
        elif x > ma:
            return ma
        else:
            return x

    def OnMotion(self, evt):
        if self.clickPosition is not None:
            inc = {ID_COL_TRANSPO: [.0001, .01], ID_COL_GAIN: [.01, .1],
                   ID_COL_STARTPOINT: [.0001, .01], ID_COL_ENDPOINT: [.0001, .01],
                   ID_COL_CROSSFADE: [.1, 1], ID_COL_CHANNEL: [1, 1]}[self.selCol]
            diff = self.clickPosition - evt.GetPosition()[1]
            dur = self.objects[self.selRow].getDuration()
            if evt.ShiftDown():
                fdiff = diff * inc[0]
            else:
                fdiff = diff * inc[1]
            if self.selCol == ID_COL_TRANSPO:
                val = self.clip(self.initialTranspo + fdiff, 0.0, 4.0)
                self.objects[self.selRow].setTranspo(val)
            elif self.selCol == ID_COL_GAIN:
                val = self.clip(self.initialGain + fdiff, -120.0, 24.0)
                self.objects[self.selRow].setGain(val)
            elif self.selCol == ID_COL_STARTPOINT:
                val = self.clip(self.initialStart + fdiff, 0.0, dur)
                self.objects[self.selRow].setStartPoint(val)
            elif self.selCol == ID_COL_ENDPOINT:
                val = self.clip(self.initialEnd + fdiff, 0.0, dur)
                self.objects[self.selRow].setEndPoint(val)
            elif self.selCol == ID_COL_CROSSFADE:
                val = self.clip(self.initialFade + fdiff, 0.0, 50.0)
                self.objects[self.selRow].setCrossfade(val)
            elif self.selCol == ID_COL_CHANNEL:
                val = self.clip(self.initialChannel + fdiff, 0, 32)
                self.objects[self.selRow].setChannel(val)
            self.SetCellValue(self.selRow, self.selCol, str(val))
        evt.Skip()

    def OnCellEditorHidden(self, evt):
        QLiveLib.setVar("CanProcessCueKeys", True)

    def OnCellEditorShown(self, evt):
        QLiveLib.setVar("CanProcessCueKeys", False)

    def OnCellLeftClick(self, evt):
        # TODO: check and warning here...
        sndfolder = os.path.join(QLiveLib.getVar("projectFolder"), "sounds")
        self.snds = sorted([f for f in os.listdir(sndfolder)])
        if self.snds == []:
            self.OnCellRightClick(evt)
        self.selRow, self.selCol = evt.GetRow(), evt.GetCol()
        if self.selCol == ID_COL_FILENAME:
            menu = wx.Menu("Soundfiles")
            self.snds = sorted([f for f in os.listdir(sndfolder)])
            for i, snd in enumerate(self.snds):
                menu.Append(i+1, snd)
            menu.Bind(wx.EVT_MENU, self.selectSound, id=1, id2=i+1)
            self.PopupMenu(menu, evt.GetPosition())
            menu.Destroy()
        if self.selRow != self.GetNumberRows() - 1:
            if self.selCol == ID_COL_LOOPMODE:
                menu = wx.Menu("Loop Modes")
                for i, md in enumerate(LOOPMODES):
                    menu.Append(i+1, md)
                menu.Bind(wx.EVT_MENU, self.selectLoopMode, id=1, id2=i+1)
                self.PopupMenu(menu, evt.GetPosition())
                menu.Destroy()
            elif self.selCol == ID_COL_PLAYING:
                menu = wx.Menu("Playing Modes")
                for i, md in enumerate(PLAYING):
                    menu.Append(i+1, md)
                menu.Bind(wx.EVT_MENU, self.selectPlayingMode, id=1, id2=i+1)
                self.PopupMenu(menu, evt.GetPosition())
                menu.Destroy()
            elif self.selCol == ID_COL_DIRECTOUT:
                val = self.objects[self.selRow].getDirectOut()
                val = not val
                self.objects[self.selRow].setDirectOut(val)
                self.SetCellValue(self.selRow, self.selCol, str(val))
        evt.Skip()

    def OnCellRightClick(self, evt):
        self.selRow, self.selCol = evt.GetRow(), evt.GetCol()
        if self.selCol == ID_COL_FILENAME:
            dlg = wx.FileDialog(self,
                                "Open Soundfile...", os.path.expanduser("~"),
                                "", AUDIO_FILE_WILDCARD, style=wx.OPEN)
            if dlg.ShowModal() == wx.ID_OK:
                path = dlg.GetPath()
                self.copyToSoundsFolder(path)
                self.loadSound(os.path.basename(path))
            dlg.Destroy()
        evt.Skip()

    def OnLabelRightClick(self, evt):
        row = evt.GetRow()
        if row != -1:
            self.selRow = row
            menu = wx.Menu()
            for i, act in enumerate(["Duplicate", "Delete"]):
                menu.Append(i+1, act)
            menu.Bind(wx.EVT_MENU, self.doLabelAction, id=1, id2=i+1)
            self.PopupMenu(menu, evt.GetPosition())
            menu.Destroy()
        evt.Skip()

    def doLabelAction(self, evt):
        if evt.GetId() == 1: # Duplicate
            obj = self.objects[self.selRow]
            id = obj.getId()
            filename = obj.getFilename()
            new = SoundFileObject(id, filename)
            new.copy(obj)
            self.selRow += 1
            self.objects.insert(self.selRow, new)
            self.addRow(index=self.selRow)
            self.putObjectAttrOnCells(new, self.selRow)
            for id in [ID_COL_TRANSPO, ID_COL_GAIN, ID_COL_STARTPOINT,
                       ID_COL_ENDPOINT, ID_COL_CROSSFADE, ID_COL_CHANNEL]:
                attr = self.GetOrCreateCellAttr(self.selRow, id)
                attr.SetReadOnly(False)
        elif evt.GetId() == 2: # Delete
            del self.objects[self.selRow]
            self.DeleteRows(self.selRow, 1, True)
        for i, obj in enumerate(self.objects):
            obj.setId(i)

    def selectSound(self, evt):
        sel = self.snds[evt.GetId() - 1]
        if sel is not None:
            self.loadSound(sel)
        evt.Skip()

    def loadSound(self, sel):
        obj = SoundFileObject(self.selRow, sel)
        obj.setCurrentCue(QLiveLib.getVar("CuesPanel").getCurrentCue())
        if obj.isValid():
            if self.selRow < len(self.objects):
                self.objects[self.selRow] = obj
            else:
                self.objects.append(obj)
                self.addRow()
            self.putObjectAttrOnCells(obj, self.selRow)
            for id in [ID_COL_TRANSPO, ID_COL_GAIN, ID_COL_STARTPOINT,
                       ID_COL_ENDPOINT, ID_COL_CROSSFADE, ID_COL_CHANNEL]:
                attr = self.GetOrCreateCellAttr(self.selRow, id)
                attr.SetReadOnly(False)

    def addObject(self, id ,filename):
        self.selRow = id
        self.loadSound(filename)

    def setObjectCues(self, id, cues):
        obj = self.objects[id]
        obj.setCues(cues)
        obj.loadCue(0)

    def selectLoopMode(self, evt):
        sel = LOOPMODES[evt.GetId() - 1]
        if sel is not None:
            self.objects[self.selRow].setLoopMode(evt.GetId() - 1)
            self.SetCellValue(self.selRow, self.selCol, sel)

    def selectPlayingMode(self, evt):
        sel = PLAYING[evt.GetId() - 1]
        if sel is not None:
            self.objects[self.selRow].setPlaying(evt.GetId() - 1)
            self.SetCellValue(self.selRow, self.selCol, sel)

    def getSoundFileObjects(self):
        return self.objects

class SoundFilePanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.grid = SoundFileGrid(self)
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.grid, 1, wx.EXPAND)
        self.SetSizer(self.sizer)

    def loadCue(self, x):
        self.saveCue()
        for obj in self.getSoundFileObjects():
            obj.loadCue(x)
            self.grid.putObjectAttrOnCells(obj, obj.getId())

    def saveCue(self):
        for obj in self.getSoundFileObjects():
            obj.saveCue()

    def addCue(self, x):
        self.saveCue()
        for obj in self.getSoundFileObjects():
            obj.addCue(x)

    def delCue(self, x, cur):
        for obj in self.getSoundFileObjects():
            obj.delCue(x)
            self.loadCue(cur)

    def cueEvent(self, evt):
        tp = evt.getType()
        if tp == CUE_TYPE_DELETE:
            self.delCue(evt.getOld(), evt.getCurrent())
        elif tp == CUE_TYPE_SELECT:
            self.loadCue(evt.getCurrent())
        elif tp == CUE_TYPE_NEW:
            self.addCue(evt.getCurrent())
        elif tp == CUE_TYPE_SAVE:
            self.saveCue()

    def setSaveState(self, lst):
        for dict in lst:
            id = dict["id"]
            filename = dict["filename"]
            self.grid.addObject(id, filename)
            self.grid.setObjectCues(id, dict["cues"])

    def getSaveState(self):
        self.saveCue()
        l = []
        for obj in self.getSoundFileObjects():
            dict = {"id": obj.getId(),
                    "filename": obj.getFilename(),
                    "cues": obj.getCues()}
            l.append(dict)
        return l

    def getSoundFileObjects(self):
        return self.grid.getSoundFileObjects()


from utils import Point,Line
from logicBlock import Sweeper
from tkinter import *
import sys
import time
import config
from optparse import OptionParser
import random

# 0 if all points are paired
# 1 if there is an un-paired point
points_modulo = 0
px = 0
py = 0
num = 0
epsi = 0.01

INP_FILE = "data_files/input_data.txt"

fh = open(INP_FILE,"w+")

def draw_point(x,y):
   c = 'deep pink'
   size = 3
   x1, y1 = ( x - size ), ( y - size )
   x2, y2 = ( x + size ), ( y + size )
   config.drawing_board.create_oval( x1, y1, x2, y2, fill = c )

def empty_event(event):
   pass

def input_lines(event):
   python_green = "#476042"
   global points_modulo,px,py

   print("Mouse position:",event.x,event.y)
   x1, y1 = ( event.x - 1 ), ( event.y - 1 )
   x2, y2 = ( event.x + 1 ), ( event.y + 1 )
   config.drawing_board.create_oval( x1, y1, x2, y2, fill = python_green )

   if points_modulo == 0:
      px,py = event.x,event.y
      points_modulo = 1
   else:
      points_modulo = 0
      dir = []
      for i in range(4):
         dir.append(random.choice([-1,1]))
      config.drawing_board.create_line(px,py,event.x,event.y)
      if py == event.y: #it's a line parallel to the x axis
         dir[1] = 1
         dir[3] = -1
      fh.write(str(px+(dir[0] * epsi)) + " " + str(py+(dir[1] * epsi)) + " " + str(event.x+(dir[2] * epsi)) + " " + str(event.y+(dir[3] * epsi)) + "\n")
      print("Saving line: " + str(px+(dir[0] * epsi)) + " " + str(py+(dir[1] * epsi)) + " " + str(event.x+(dir[2] * epsi)) + " " + str(event.y+(dir[3] * epsi)) + "\n")
      # write the line correcting for x and y

def draw_sweep_line(p):
   config.drawing_board.create_line(0,p.y,config.canvas_width-1,p.y,fill="green")
   draw_point(p.x,p.y)

def run_eval(delay_param=200):
   print("Evaluation running")
   fh.close()

   # sweep_obj = Sweeper("temp_testing.txt")
   sweep_obj = Sweeper(INP_FILE)
   sweep_obj.run()
   print("Eval complete. Running animation")
   for p in config.sweep_y:
      print(p)

   delay = 0
   delay_amount =delay_param
   num_artifacts = 2#drawing two things and the first one is the line
   n = config.drawing_board.create_oval(0,0,1,1)
   points_drawn = dict()
   for p in config.sweep_y:
      print(p)
      if p not in points_drawn:
         config.drawing_board.after(delay,draw_sweep_line,p)
         n += num_artifacts
         points_drawn[p] = True # since the point isn't hashable
         delay += delay_amount
         config.drawing_board.after(delay,config.drawing_board.delete,n - (num_artifacts - 1))
         delay += delay_amount
   config.sweep_y = []
   print("Animation complete")

def clear_canvas():
   global fh
   fh.close()
   global INP_FILE
   INP_FILE = "data_files/input_data.txt"
   fh = open(INP_FILE,"w")

   global points_modulo
   points_modulo = 0

   config.drawing_board.delete("all")

   config.sweep_y = []

def save_input():
   global num

   print("num = ",num)

   with open("data_files/input_data.txt") as f:
      with open("data_files/examples/tc_"+str(num)+".txt","w") as f1:
         for l in f:
            print(l)
            f1.write(l)

   clear_canvas()
   num += 1

if __name__ == "__main__":

   parser = OptionParser()

   parser.add_option('--inp',dest='inp_file',type=str,help='File from which input is to be loaded')
   parser.add_option('-n',dest='test_case_num',type=int,help='The number to be assigned to the testcase file where the input will be saved')
   parser.add_option('--disp_delay',dest='disp_delay',type=int,help='The delay between two positions of the sweep line on the GUI')

   options, otherjunk = parser.parse_args(sys.argv[1:])
   if len(otherjunk) != 0:
       raise Exception('Command line input not understood: ' + str(otherjunk))
   print(options.inp_file,type(options.inp_file))

   if options.disp_delay is None:
      options.disp_delay = 200

   if options.test_case_num is None:
      num = 0
   else:
      num = options.test_case_num

   # Draw board
   config.master.title("Line Segment Intersection")
   config.drawing_board.bind("<Button-1>",input_lines)
   # config.drawing_board.bind("<Button-1>",temp_testing)

   start_button = Button(config.master,text = "Start Evaluation",command = lambda: run_eval(delay_param=options.disp_delay))
   start_button.pack(side = LEFT)

   clear_all_button = Button(config.master,text = "Clear Screen",command = clear_canvas)
   clear_all_button.pack(side = LEFT)

   print(options.test_case_num)

   save_button = Button(config.master,text = "Save Input",command = save_input)
   save_button.pack(side = LEFT)

   if options.inp_file is None:
      print("loading from gui")
      mainloop()
   else:
      print("loading from file")
      # load_file = "data_files/bad_cases/" + options.inp_file
      load_file = "data_files/examples/" + options.inp_file
      fh_temp = open(load_file ,"r")
      t = fh_temp.readlines()
      for row in t:
         x1,y1,x2,y2 = map(float,row.split(' '))
         config.drawing_board.create_line(x1,y1,x2,y2)
         print("drawing line:",x1,y1,x2,y2)
      fh_temp.close()
      # global INP_FILE
      INP_FILE = load_file
      # run_eval()
      mainloop()