# -*- coding: utf-8 -*-
import torch.nn as nn
from network import Decomposition,MultiscaleDiscriminator,downsample
from utils import gradient
from ssim import SSIM
import torch
import torch.optim as optim
import torchvision
import os
import torch.nn.functional as F
from contiguous_params import ContiguousParams

class Model(nn.Module):
    def __init__(self,args):
        super(Model, self).__init__()
        self.fusion = Decomposition()
        self.D = MultiscaleDiscriminator(input_nc=1)
        self.MSE_fun = nn.MSELoss()
        self.L1_loss = nn.L1Loss()
        self.SSIM_fun = SSIM()

        if args.contiguousparams==True:
            print("ContiguousParams---")
            parametersF = ContiguousParams(self.fusion.parameters())
            parametersD = ContiguousParams(self.D.parameters())
            self.optimizer_G = optim.Adam(parametersF.contiguous(), lr=args.lr)
            self.optimizer_D = optim.Adam(parametersD.contiguous(), lr=args.lr)
        else:
            self.optimizer_G = optim.Adam(self.fusion.parameters(), lr=args.lr)
            self.optimizer_D = optim.Adam(self.D.parameters(), lr=args.lr)

        self.g1 = self.g2 = self.g3 = self.s = self.img_re = None
        self.loss = torch.zeros(1)
        self.scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(self.optimizer_G , mode='min', factor=0.5, patience=2,
                                                               verbose=False, threshold=0.0001, threshold_mode='rel',
                                                               cooldown=0, min_lr=0, eps=1e-10)
        self.min_loss = 1000
        self.args = args
        self.downsample = downsample()
        self.criterionGAN = torch.nn.MSELoss()

        if args.multiGPU:
            self.mulgpus()
        self.load()
        self.load_D()

    def load_D(self,):
        if self.args.load_pt:
            print("=========LOAD WEIGHTS D=========")
            path = self.args.weights_path.replace("fusion","D")
            print(path)
            checkpoint = torch.load(path)

            if self.args.multiGPU:
                print("load D")
                self.D.load_state_dict(checkpoint['weight'])
            else:
                print("load D single")
                # 单卡模型读取多卡模型
                state_dict = checkpoint['weight']
                # create new OrderedDict that does not contain `module.`
                from collections import OrderedDict
                new_state_dict = OrderedDict()
                for k, v in state_dict.items():
                    name = k.replace('module.', '')  # remove `module.`
                    new_state_dict[name] = v
                # load params
                self.D.load_state_dict(new_state_dict)

            print("=========END LOAD WEIGHTS D=========")

    def load(self,):
        start_epoch = 0
        if self.args.load_pt:
            print("=========LOAD WEIGHTS=========")
            checkpoint = torch.load(self.args.weights_path)
            start_epoch = checkpoint['epoch'] + 1
            try:
                if self.args.multiGPU:
                    print("load G")
                    self.fusion.load_state_dict(checkpoint['weight'])
                else:
                    print("load G single")
                    # 单卡模型读取多卡模型
                    state_dict = checkpoint['weight']
                    # create new OrderedDict that does not contain `module.`
                    from collections import OrderedDict
                    new_state_dict = OrderedDict()
                    for k, v in state_dict.items():
                        name = k.replace('module.', '')  # remove `module.`
                        new_state_dict[name] = v
                    # load params
                    self.fusion.load_state_dict(new_state_dict)
            except:
                model = self.fusion
                print("weights not same ,try to load part of them")
                model_dict = model.state_dict()
                pretrained = torch.load(self.args.weights_path)['weight']
                # 1. filter out unnecessary keys
                pretrained_dict = {k: v for k, v in model_dict.items() if k in pretrained}
                left_dict = {k for k, v in model_dict.items() if k  not in pretrained}
                print(left_dict)
                # 2. overwrite entries in the existing state dict
                model_dict.update(pretrained_dict)
                # 3. load the new state dict
                model.load_state_dict(model_dict)
                print(len(model_dict),len(pretrained_dict))
                # model_dict = self.fusion.state_dict()
                # pretrained_dict = {k: v for k, v in model_dict.items() if k in checkpoint['weight'] }
                # print(len(checkpoint['weight'].items()), len(pretrained_dict), len(model_dict))
                # model_dict.update(pretrained_dict)
                # self.fusion.load_state_dict(model_dict)
            print("start_epoch:", start_epoch)
            print("=========END LOAD WEIGHTS=========")
        print("========START EPOCH: %d========="%start_epoch)
        self.start_epoch = start_epoch

    def mulGANloss(self, input_, is_real):
        if is_real:
            label = 1
        else:
            label = 0

        if isinstance(input_[0], list):
            loss = 0.0
            for i in input_:
                pred = i[-1]
                target = torch.Tensor(pred.size()).fill_(label).to(pred.device)
                loss += self.criterionGAN(pred, target)
            return loss
        else:
            target = torch.Tensor(input_[-1].size()).fill_(label).to(input_[-1].device)
            return self.criterionGAN(input_[-1], target)

    def forward(self,isTest=False):
        self.g1, self.g2, self.g3, self.s, self.img_re = self.fusion(self.img,isTest)

    def set_requires_grad(self, net, requires_grad=False):
        for param in net.parameters():
            param.requires_grad = requires_grad

    def backward_G(self):
        img = self.img
        img_re = self.img_re
        img_g = gradient(img)
        self.img_down = self.downsample(img)
        self.img_g = img_g
        # print(self.g1.sum(),self.g2.sum(),self.g3.sum(),img_g.sum())
        # print(self.g1.mean(), self.g2.mean(), self.g3.mean(), img_g.mean())
        g1 = self.MSE_fun(self.g1, img_g)
        g2 = self.MSE_fun(self.g2, img_g)
        g3 = self.MSE_fun(self.g3, img_g)
        grd_loss = g1+g2+g3
        self.lossg1 ,self.lossg2,self.lossg3 = g1,g2,g3
        # grd_loss = self.MSE_fun(self.g1, img_g) + self.MSE_fun(self.g2, img_g) + self.MSE_fun(self.g3, img_g)
        ssim_loss = 1 - self.SSIM_fun(img_re, img)
        ssim_loss = ssim_loss * 10
        pixel_loss = self.MSE_fun(img_re, img)
        pixel_loss = pixel_loss * 100

        loss_G = self.mulGANloss(self.D(self.s), is_real=True)*0.1

        # 损失求和 回传
        loss = pixel_loss + ssim_loss + grd_loss + loss_G

        loss.backward()
        self.loss,self.pixel_loss,self.ssim_loss, self.grd_loss = loss,pixel_loss,ssim_loss, grd_loss
        self.loss_G = loss_G

    def backward_D(self):
        # RealReal
        # Real
        pred_real = self.D(self.img_down.detach())
        loss_D_real = self.mulGANloss(pred_real, is_real=True)
        # Fake
        pred_fake = self.D(self.s.detach())
        loss_D_fake = self.mulGANloss(pred_fake, is_real=False)
        # Combined loss and calculate gradients
        loss_D = (loss_D_real + loss_D_fake) * 0.5
        loss_D.backward()
        self.loss_D = loss_D
        self.loss_D_real,self.loss_D_fake = loss_D_real,loss_D_fake

    def mulgpus(self):
        self.fusion= nn.DataParallel(self.fusion.cuda(), device_ids=self.args.GPUs, output_device=self.args.GPUs[0])
        self.D = nn.DataParallel(self.D.cuda(), device_ids=self.args.GPUs, output_device=self.args.GPUs[0])

    def setdata(self,img):
        img = img.to(self.args.device)
        self.img = img

    def step(self):
        self.optimizer_G.zero_grad()  # set G gradients to zero
        self.forward()

        self.set_requires_grad(self.D, False)  # D require no gradients when optimizing G

        self.backward_G()  # calculate gradients for G
        self.optimizer_G.step()  # update G weights

        # if it % 10 == 0:
        self.set_requires_grad(self.D, True)
        self.optimizer_D.zero_grad()  # set D gradients to zero
        self.backward_D()  # calculate gradients for D
        self.optimizer_D.step()  # update D weights

        self.print = 'ALL[%.5lf] pixel[%.5lf] grd[%.5lf](%.5lf %.5lf %.5lf) ssim[%.5lf] G[%.5lf]  D[%.5lf][%.5lf %.5lf ]' %\
                     (self.loss.item(), self.pixel_loss.item(), self.grd_loss.item(),self.lossg1.item() ,self.lossg2.item(),self.lossg3.item(), self.ssim_loss.item(),
                      self.loss_G.item(),self.loss_D.item(),self.loss_D_real.item(),self.loss_D_fake.item(),)

    def saveimg(self,epoch,num=0):
        img = torchvision.utils.make_grid(
            [self.img[0].cpu(), self.img_re[0].cpu(), self.img_down[0].cpu(),self.img_g[0].cpu(), self.s[0].cpu(), self.g1[0].cpu(), self.g2[0].cpu(),
             self.g3[0].cpu(), (self.g1+self.g2+self.g3)[0].cpu()], nrow=5)
        torchvision.utils.save_image(img, fp=(os.path.join('output/result_' + str(epoch) + '.jpg')))
        # torchvision.utils.save_image(img, fp=(os.path.join('output/epoch/'+str(num)+'.jpg')))

    def saveimgdemo(self):
        self.img_down = self.downsample(self.img)
        self.img_g = gradient(self.img)

        img = torchvision.utils.make_grid(
            [self.img[0].cpu(), self.img_re[0].cpu(), self.img_down[0].cpu(),self.img_g[0].cpu(), self.s[0].cpu(), self.g1[0].cpu(), self.g2[0].cpu(),
             self.g3[0].cpu(), (self.g1+self.g2+self.g3)[0].cpu()], nrow=5)
        torchvision.utils.save_image(img, fp=(os.path.join('demo_result.jpg')))
        # torchvision.utils.save_image(img, fp=(os.path.join('output/epoch/'+str(num)+'.jpg')))

    def saveimgfuse(self,name=''):
        self.img_down = self.downsample(self.img)
        self.img_g = gradient(self.img)

        img = torchvision.utils.make_grid(
            [self.img[0].cpu(), self.img_g[0].cpu(), ((self.g1+self.g2+self.g3)*1.5)[0].cpu()], nrow=3)
        torchvision.utils.save_image(img, fp=(os.path.join(name.replace('Test','demo'))))
        # torchvision.utils.save_image(img, fp=(os.path.join('output/epoch/'+str(num)+'.jpg')))

    def save(self, epoch):
        ## 保存模型和最佳模型
        if self.min_loss > self.loss.item():
            self.min_loss = self.loss.item()
            torch.save({'weight': self.fusion.state_dict(), 'epoch': epoch, },os.path.join('weights/best_fusion.pt'))
            torch.save({'weight': self.D.state_dict(), 'epoch': epoch, }, os.path.join('weights/best_D.pt'))
            print('[%d] - Best model is saved -' % (epoch))

        if epoch % 1 == 0:
            torch.save({'weight': self.fusion.state_dict(), 'epoch': epoch, },os.path.join('weights/epoch' + str(epoch) + '_fusion.pt'))
            torch.save({'weight': self.D.state_dict(), 'epoch': epoch, },os.path.join('weights/epoch' + str(epoch) + '_D.pt'))

    def getimg(self):
        return self.g1, self.g2,self.g3,self.s


import numpy as np
import librosa
from typing import List
import matplotlib.pyplot as plt
from scipy import signal
from scipy.fft import rfft, rfftfreq
import os

TECHNIQUES = ['High', 'Tasto', 'Bend', 'Harm', 'Strum', 'Pont', 'Ord', 'Chord', 'Smack', 'Palm', 'TEST', 'SILENCE']
#TECHNIQUES =  os.listdir("samples/manual") + ["SILENCE"]
# ['Bend', 'Chord', 'Harm', 'High', 'Ord', 'Palm', 'Pont', 'Smack', 'Strum', 'Tasto', 'TEST', 'SILENCE']
#   high    tasto  bend     harm    strum  pont     ord     chord    smack    palm

def find_onsets(y: np.ndarray, sr: int) -> np.ndarray:
    """Takes a numpy array and returns an array of onsets, currenly using librosa"""
    #return librosa.onset.onset_detect(y, sr=sr, backtrack=True, units="samples")
    o_env = librosa.onset.onset_strength(y=y, sr=sr, max_size=8)
    samps = librosa.samples_like(o_env)
    return librosa.onset.onset_detect(onset_envelope=o_env, sr=sr, backtrack=True, units="samples",
                                          delta=4.3, hop_length=512, normalize=False,
                                          pre_max = 1.0, post_max = 1.0, pre_avg = 4.0, post_avg = 5.0, wait = 1.0)

def get_waveform_from_ndarray(audio: np.ndarray, tf):
    audio = tf.convert_to_tensor(audio)

    tf.cast(audio, tf.float32)
    return audio

def get_waveform_from_bin(wfbin, tf):
    """Returns a tf tensor float32 waveform from a binary file"""
    audio, _ = tf.audio.decode_wav(wfbin)  # somewhere here it breaks.......
    tf.cast(audio, tf.float32)
    return tf.squeeze(audio, axis=-1)

def get_waveform_from_path(path: str, tf):
    """Returns a tf tensor float32 waveform from a path"""
    wfbin = tf.io.read_file(path)
    return get_waveform_from_bin(wfbin, tf)

def get_spectrogram(waveform, tf):
    """Takes a tf.float32 waveform and returns a spectrogram.  Max size = 16000 samples"""
    if tf.shape(waveform) > 16000:
        waveform = waveform[:16000]
    zero_padding = tf.zeros([16000] - tf.shape(waveform), dtype=tf.float32) #fix this so the padding isn't huge

    waveform = tf.cast(waveform, tf.float32)
    equal_length = tf.concat([waveform, zero_padding], 0)
    spectrogram = tf.signal.stft(
        equal_length, frame_length=255, frame_step=128)

    spectrogram = tf.abs(spectrogram)
    spectrogram = tf.expand_dims(spectrogram, -1)

    return spectrogram

def numpy_to_tfdata(note: np.ndarray, tf):
    """Turn a numpy buffer note into a tensorflow dataset of the spectrogram"""
    waveform = get_waveform_from_ndarray(note, tf)
    spec = get_spectrogram(waveform, tf)
    ds = tf.data.Dataset.from_tensors([spec])
    return ds

def int_to_string_results(int_results: List[int], techniques: List[str]) -> List[str]:
    return list(map(lambda i: techniques[i], int_results))

def prediction_to_int_ranks(prediction, tf):
    sftmax = tf.nn.softmax(prediction[0])
    sorted = np.sort(sftmax)[::-1]
    index_of = lambda x: np.where(sftmax == x)[0][0]
    prediction_ranks = list(map(index_of, sorted))
    return prediction_ranks

def plot_prediction(techniques, prediction, tf):
    """view a matplotlib graph of the prediction"""
    plt.bar(techniques, tf.nn.softmax(prediction[0]))
    plt.title(f'Predictions for new note:')
    plt.show()

def note_above_threshold(note: np.ndarray) -> bool:
    """Checks if the peak of a note is above a set threshold"""
    if np.max(np.abs(note)) > 0.09:
        return True
    else:
        return False

def get_partials(waveform: np.ndarray, sr: int) -> List[float]:
    normalized_wf = np.int16((waveform / waveform.max()) * 32767)
    N = len(normalized_wf)
    yf = rfft(normalized_wf)
    xf = rfftfreq(N, 1 / sr)
    half = len(xf) // 2
    peak_sig = np.abs(yf[:half])
    peaks, d = signal.find_peaks(peak_sig, height=100000, distance=250)  # This can be tweaked for better results
    peaks_amps = np.array(list(map(lambda p: [p, peak_sig[p]], peaks)))
    sorted_peaks = peaks_amps[peaks_amps[:, 1].argsort()][::-1]
    sorted_freqs = list(map(lambda i: xf[int(i)], sorted_peaks[:, 0]))
    sorted_freqs = filter(lambda freq: freq > 80, sorted_freqs)
    return list(sorted_freqs)

if __name__ == "__main__":
    print(TECHNIQUES)


import requests
import csv
from bs4 import BeautifulSoup
import json
from collections import namedtuple
from typing import List, Dict

TOPICS_NUMBER = 6
LEVELS_NUMBER = 5
MIN_LEVEL_CONTEST_ID = "030813"
MAX_LEVEL_CONTEST_ID = "030817"
TABLE_URL = ("https://ejudge.lksh.ru/standings/dk/stand.php"
             "?from={}&to={}".format(MIN_LEVEL_CONTEST_ID,
                                     MAX_LEVEL_CONTEST_ID))

Student = namedtuple('Student', 'group, last_name, first_name, ejid')

def get_table(table_url) -> BeautifulSoup:
    """Fetches results table from ejudge, returns soup"""
    response = requests.get(table_url)
    soup = BeautifulSoup(response.text, "lxml")
    table = soup.select_one("table")
    return table

def parse_results(table_soup: BeautifulSoup) -> Dict[Student, List[int]]:
    """Returns dict like {Student: [1 if problem is solved else 0]}"""
    result = {}
    rows = [row for row in table_soup.select("tr") if row.has_attr("ejid")]
    for row in rows:
        [group, last_name, first_name], ejid = row.select_one("nobr").contents[
            0].split(), int(row['ejid'])

        problem_tags = [td for td in row.findAll("td") if td.has_attr("title")]
        solved = [1 if tag["class"] == ["ac"] else 0 for tag in problem_tags]
        result[Student(group, last_name, first_name, ejid)] = solved

    return result

def last_occurrence(list_, elem):
    return len(list_) - 1 - list_[::-1].index(elem)

def calculate_mark(solved: List[int]) -> int:
    """Calculates mark from a list of solved"""
    levels = set()
    max_levels = []
    for topic in range(TOPICS_NUMBER):
        solved_from_topic = solved[topic::TOPICS_NUMBER]
        if any(solved_from_topic):
            max_level = last_occurrence(solved_from_topic, 1)
            max_levels.append(max_level)

    max_levels.sort(reverse=True)
    for level in max_levels:
        while level in levels and level != 0:
            level -= 1
        levels.add(level)

    return min(len(levels), len(max_levels))

def get_table_to_render(parsed_table: Dict[Student, List[int]]) -> list:
    return sorted([(*student, calculate_mark(solved))
                   for student, solved in parsed_table.items()])

def get_table_json(parsed_table: Dict[Student, List[int]]) -> str:
    return json.dumps([{
                           'first_name': student.first_name,
                           'last_name': student.last_name,
                           'group': student.group,
                           'score': calculate_mark(solved),
                           'ejid': student.ejid
                       } for student, solved in parsed_table.items()],
                      ensure_ascii=False)

def get_personal_json(parsed_table: Dict[Student, List[int]], ejid: int) -> str:
    filtered_student = [(student, solved)
                        for student, solved in parsed_table.items()
                        if student.ejid == ejid]

    if filtered_student:
        student, solved = filtered_student[0]
        return json.dumps({'first_ name': student.first_name,
                           'last_name': student.last_name,
                           'group': student.group,
                           'score': calculate_mark(solved),
                           'solved': solved,
                           'ejid': student.ejid},
                          ensure_ascii=False)
    else:
        return json.dumps({'error': 'ID не найден'}, ensure_ascii=False)

if __name__ == '__main__':
    results_table = get_table(TABLE_URL)
    parsed_table = parse_results(results_table)
    table = get_table_to_render(parsed_table)
    with open("results.csv", "w", encoding="utf-8") as file:
        csv_writer = csv.writer(file)
        csv_writer.writerows(table)


import json
import logging
import sys
from z3 import z3

from teether.constraints import check_model_and_resolve
from teether.evm.exceptions import IntractablePath
from teether.evm.state import LazySubstituteState, SymRead
from teether.project import Project
from teether.util.z3_extra_util import concrete

def set_balance(addr, bal, i_r):
    calldata = z3.Array('CALLDATA_%d' % i_r.xid, z3.BitVecSort(256), z3.BitVecSort(8))
    new_calldata = z3.Store(z3.Store(z3.Store(z3.Store(calldata, 0, 0x70), 1, 0xa0), 2, 0x82), 3, 0x31)
    for num, byte in enumerate(addr.to_bytes(32, 'big'), 4):
        new_calldata = z3.Store(new_calldata, num, byte)
    subst = [(calldata, new_calldata)]
    state = LazySubstituteState(i_r.state, subst)
    constraints = [z3.substitute(c, subst) for c in i_r.constraints]
    sha_constraints = {sha: z3.simplify(z3.substitute(sha_value, subst)) if not isinstance(sha_value, SymRead)
    else sha_value for sha, sha_value in i_r.sha_constraints.items()}
    mstart, msz = state.stack[-1], state.stack[-2]
    mm = i_r.state.memory.read(mstart, msz)
    if not isinstance(mm, SymRead):
        if all(concrete(m) for m in mm):
            return None
        mm = z3.simplify(z3.Concat([m if not concrete(m) else z3.BitVecVal(m, 8) for m in mm]))
    extra_constraints = [mm == bal]
    try:
        model = check_model_and_resolve(constraints + extra_constraints, sha_constraints)
        sloads = []
        storage = None
        for v in model:
            if v.name().startswith("SLOAD"):
                sloads.append(model.eval(model[v]).as_long())
            if v.name().startswith("STORAGE"):
                storage = z3.simplify(model[v])
        return {sl: model.eval(storage[sl]).as_long() for sl in sloads}
    except IntractablePath:
        return None

def main(code_path, output_file, target_addrs, target_bals):
    if code_path.endswith('.json'):
        with open(code_path, 'rb') as f:
            jd = json.load(f)
        p = Project.from_json(jd)
    else:
        with open(code_path) as infile:
            inbuffer = infile.read().rstrip()
    code = bytes.fromhex(inbuffer)
    p = Project(code)
    with open('%s.project.json' % code_path, 'w') as f:
        json.dump(p.to_json(), f)

    target_addrs = [int(addr, 16) for addr in target_addrs]
    target_bals = [int(bal) for bal in target_bals]
    storage_result = dict()

    addr, bal = target_addrs[0], target_bals[0]
    return_ins = p.cfg.filter_ins('RETURN')
    gen_constraints = p.get_constraints(return_ins)
    results = []
    for _, _, i_r in gen_constraints:
        stor = set_balance(addr, bal, i_r)
        if stor:
            storage_result.update(stor)
            results = [i_r] + results
            break
        results.append(i_r)
    else:
        logging.warning(f"Could not set balance of {hex(addr)} to {bal}")
    for addr,bal in zip(target_addrs[1:], target_bals[1:]):
        for i_r in results:
            stor = set_balance(addr, bal, i_r)
            if stor:
                storage_result.update(stor)
                break
        else:
            for _, _, i_r in gen_constraints:
                stor = set_balance(addr, bal, i_r)
                if stor:
                    storage_result.update(stor)
                    results = [i_r] + results
                    break
                results.append(i_r)
            else:
                logging.warning(f"Could not set balance of {hex(addr)} to {bal}")

    with open(output_file, 'w') as f:
        json.dump({"0x{0:0{1}X}".format(k, 64): "0x{0:0{1}x}".format(v, 64) for k, v in storage_result.items()}, f)

if __name__ == '__main__':

    if len(sys.argv) < 5 or len(sys.argv) % 2 != 1:
        print('Usage: %s <code> <output file> <target-address> <target-balance> [<target-address> <target-balance>] ...'
              % sys.argv[0], file=sys.stderr)
        exit(-1)

    code = sys.argv[1]
    output_file = sys.argv[2]
    target_addresses = sys.argv[3::2]
    target_balances = sys.argv[4::2]

    main(code, output_file, target_addresses, target_balances)


# -*- coding: utf-8 -*-
"""Translator module"""
from __future__ import division
from data import NUMBERS

class Translator(object):
    """Translator class"""

    @classmethod
    def translate(cls, data):
        """The method for converting a input data to number instance """
        if isinstance(data, str):
            str_result = "".join(char for char in data if char.isdigit())
            value = int(str_result) if str_result else 0
        elif isinstance(data, (int, float, long)):
            value = data
        else:
            raise TypeError("Expected {} or {} / {}. But taken {}".format(str, int, float, data))
        return value

    def __enter__(self):
        self.translate = self.context_translate
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return True

    @classmethod
    def context_translate(cls, data):
        """TRANSLATE methodf"""
        value = cls.translate(data)
        sign = "" if value >= 0 else NUMBERS["minus"]
        abs_value = abs(value)
        if value in NUMBERS and value < 100:
            str_value = NUMBERS[abs_value]
        else:
            str_value = " ".join(cls._get_power_thousand(abs_value))
        return " ".join((sign, str_value))

    @classmethod
    def _get_power_thousand(cls, value):
        """Sort out with thousand to the power"""
        while value >= 1:
            len_value = len(str(value))
            power_thousand = 10 ** ((len_value - 1) // 3 * 3)
            value_under_thousand = value // power_thousand

            str_value_under_thousand = " ".join(cls._get_under_thousand(value_under_thousand))

            str_power_thousand = NUMBERS[power_thousand] if power_thousand > 1 else ""
            str_value = " ".join((str_value_under_thousand, str_power_thousand))
            value -= value_under_thousand * power_thousand
            yield str_value

    @classmethod
    def _get_under_thousand(cls, value):
        """Sort out with values under thousand"""
        while value >= 1:
            if value >= 100:
                quantity_hundreds = value // 100
                value -= quantity_hundreds * 100
                str_and = NUMBERS["and"] if value > 0 else ""
                str_value = " ".join((NUMBERS[quantity_hundreds], NUMBERS[100], str_and))
            elif value in NUMBERS:
                str_value = NUMBERS[value]
                value = 0
            else:
                value_tens = value // 10 * 10
                str_value = NUMBERS[value_tens]
                value = value - value_tens
            yield str_value


#!/usr/bin/env python
"""
Download the given htmx version and the extensions we're using.
"""
import argparse
import subprocess
from typing import List, Optional

def main(argv: Optional[List[str]] = None) -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("version", help="e.g. 1.0.1")
    args = parser.parse_args(argv)
    version: str = args.version

    download_file(version, "htmx.js")
    download_file(version, "ext/debug.js")
    download_file(version, "ext/event-header.js")

    print("✅")
    return 0

def download_file(version: str, name: str) -> None:
    print(f"{name}...")
    subprocess.run(
        [
            "curl",
            "--silent",
            "--location",
            f"https://unpkg.com/htmx.org@{version}/dist/{name}",
            "-o",
            f"example/static/{name}",
        ],
        check=True,
    )
    # Fix lack of trailing newline in minified files as otherwise pre-commit
    # has to fix it.
    if name.endswith(".min.js"):
        with open(f"example/static/{name}", "a") as fp:
            fp.write("\n")

if __name__ == "__main__":
    raise SystemExit(main())


import sieve
from typing import Dict, List
import os
from dotenv import load_dotenv

load_dotenv()
api_key = os.environ.get('SIEVE_API_KEY')
sieve.SIEVE_API_KEY = os.getenv('SIEVE_API_KEY')
sieve.SIEVE_API_URL = os.getenv('SIEVE_API_URL')

@sieve.Model(
  name="deepface-emotion-detector",
  gpu = True,
  python_packages=[
    "opencv-python==4.6.0.66",
    "tensorflow==2.11.0",
    "pandas==1.5.3",
    "numpy==1.24.2",
    "deepface==0.0.79",
    'mediapipe==0.9.0'
  ],
  python_version="3.8",
)
class EmotionDetector:
    def __setup__(self):
        from deepface import DeepFace
        self.model = DeepFace.build_model('Emotion')
        # Load the weights from the saved H5 file
        self.emotion_labels = {0: 'angry', 1: 'disgust', 2: 'fear', 3: 'happy', 4: 'neutral', 5: 'sad', 6: 'surprise'}
        import mediapipe as mp
        self.mp_face_detection = mp.solutions.face_detection
        self.face_detection = self.mp_face_detection.FaceDetection(min_detection_confidence=0.7)

    def detect_faces(self, img: sieve.Image):
        import cv2
        import numpy as np
        results = self.face_detection.process(cv2.cvtColor(img.array, cv2.COLOR_BGR2RGB))
        faces = []
        if results.detections:
            for detection in results.detections:
                bounding_box = detection.location_data.relative_bounding_box
                x = int(bounding_box.xmin * img.width)
                w = int(bounding_box.width * img.width)
                y = int(bounding_box.ymin * img.height)
                h = int(bounding_box.height * img.height)

                detected_face = img.array[y : y + h, x : x + w]
                face_array = np.array(detected_face)
                bbox = [x, y, w, h]

                faces.append({
                    "array": face_array,
                    "box": bbox,
                    "class_name": "face",
                    "score": detection.score[0],
                    "frame_number": None if not hasattr(img, "frame_number") else img.frame_number
                })

        return faces

    def __predict__(self, img: sieve.Image) -> List:
        import tensorflow as tf
        import numpy as np
        from deepface import DeepFace
        import cv2
        outputs = []
        faces = self.detect_faces(img)
        for face in faces:
            face_img = face['array']
            #preprocess the face image
            if face_img is not None and np.any(face_img):

                gray_face = cv2.cvtColor(face_img, cv2.COLOR_RGB2GRAY)
                resized_face = cv2.resize(gray_face, (48, 48))
                preprocessed_face = tf.keras.applications.resnet50.preprocess_input(resized_face)
                preprocessed_face = np.expand_dims(preprocessed_face, axis=0)

                #predict the emotion of the face image
                emotions = self.model.predict(preprocessed_face)[0]
                labels = ['angry', 'disgust', 'fear', 'happy', 'neutral', 'sad', 'surprise']
                dominant_emotion = np.argmax(emotions)
                emotion_label = self.emotion_labels[dominant_emotion]
                confidence = emotions[dominant_emotion]

                outputs.append({
                    "frame_number": face['frame_number'],
                    "class_name": "face",
                    "box": face["box"],
                    "score": face["score"],
                    "emotion": emotion_label,
                    "confidence": confidence
                })

        return outputs


from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

from api.serializers import BookSerializer
from books.models import Book, PublicationLanguage, Author
from django.test import Client

client = Client()

class TestBookList(APITestCase):
    def setUp(self) -> None:
        self.publication_language_id = PublicationLanguage.objects.get_or_create(
            language="en")[0]
        self.author_id = Author.objects.get_or_create(name="test_author")[0]

    def test_empty_list_books(self):
        response = client.get(reverse("api:book_list"))
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)

        self.assertEqual(response.data, serializer.data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_all_books(self):
        book = Book.objects.create(
            isbn="1234567891234",
            title="test_title",
            publication_year=2008,
            page_count=1000,
            cover="https://google.pl",
            publication_language=self.publication_language_id)
        book.author.set([self.author_id])

        response = client.get(reverse("api:book_list"))
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)

        self.assertEqual(response.data, serializer.data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_filter_publication_date(self):
        book_first = Book.objects.create(
            isbn="1234567891234",
            title="test_title",
            publication_year=2008,
            page_count=2008,
            cover="https://google.pl",
            publication_language=self.publication_language_id)
        book_first.author.set([self.author_id])

        book_second = Book.objects.create(
            isbn="1234567891235",
            title="test_title123",
            publication_year=2018,
            page_count=2008,
            cover="https://google.pl",
            publication_language=self.publication_language_id)
        book_second.author.set([self.author_id])

        url = f"{reverse('api:book_list')}?publication_year__gte=&publication_year__lte=2013"
        response = client.get(url)
        books = Book.objects.filter(publication_year__lte=2013)
        serializer = BookSerializer(books, many=True)

        self.assertEqual(response.data, serializer.data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)


#imports the os package and inotify
import os
from inotify_simple import INotify, flags
#pulls in the package
inotify = INotify()
#runs the below command so this script will keep running once it's finished
os.system("while :; do python3 File-Changes.py; done")
#creates the watch flags
watch_flags = flags.CREATE | flags.DELETE | flags.MODIFY | flags.DELETE_SELF
#creates watches for the below directory
wdVarLog = inotify.add_watch("/var/log", watch_flags)
wdETC = inotify.add_watch("/etc", watch_flags)

#for event in inotify prints to directorylogs
for event in inotify.read():
    fOpen = open("directorylogs.txt","a")
    fOpen.write(event)
    fOpen.close()
    #for flag in event prints out to the same file as the events
    for flag in flags.from_mask(event.mask):
        fstring = (" " + str(flag))
        fOpen = open("directorylogs.txt","a")
        fOpen.write(fstring)
        fOpen.close()


import pytest
import torch

from renate.benchmark.models.transformer import HuggingFaceSequenceClassificationTransformer

@pytest.mark.parametrize("model_name", ["distilbert-base-uncased", "bert-base-uncased"])
def test_init(model_name):
    HuggingFaceSequenceClassificationTransformer(
        pretrained_model_name_or_path=model_name, num_outputs=10
    )

@pytest.mark.parametrize(
    "model_name,input_dim",
    [
        ["distilbert-base-uncased", (128,)],
        ["bert-base-uncased", (256,)],
    ],
)
def test_text_transformer_fwd(model_name, input_dim):
    transformer = HuggingFaceSequenceClassificationTransformer(
        pretrained_model_name_or_path=model_name
    )

    x = {"input_ids": torch.randint(0, 30000, (5, *input_dim))}
    y_hat = transformer(x)

    assert y_hat.shape[0] == 5
    assert y_hat.shape[1] == 10


import numpy as np
import torch
import copy
from pathlib import Path
from torch_scatter import scatter
from typing import Dict, Tuple

from pcdet.datasets.v2x_sim.v2x_sim_dataset_ego import V2XSimDataset_EGO, get_pseudo_sweeps_of_1lidar, get_nuscenes_sensor_pose_in_global, apply_se3_
from pcdet.datasets.v2x_sim.v2x_sim_utils import roiaware_pool3d_utils

class V2XSimDataset_EGO_LATE(V2XSimDataset_EGO):
    def __init__(self, dataset_cfg, class_names, training=True, root_path=None, logger=None):
        super().__init__(dataset_cfg, class_names, training, root_path, logger)
        assert self.mode == 'test', f"late fusion only support validation"

    def _get_prediction_ego(self, sample_token: str) -> np.ndarray:
        path_modar = self.exchange_database / f"{sample_token}_id1_modar.pth"
        modar = torch.load(path_modar, map_location=torch.device('cpu')).numpy() if path_modar.exists() else np.zeros(1, 9)
        return modar

    @torch.no_grad()
    def _get_prediction_agent(self, lidar_id: int, lidar_token: str, sample_token: str, exchange_setting: str) -> Tuple[np.ndarray]:
        """
        Predictions are in agent's frame
        """
        assert exchange_setting in ('now', 'prev')
        glob_se3_lidar = get_nuscenes_sensor_pose_in_global(self.nusc, lidar_token)  # (4, 4)

        path_modar = self.exchange_database / f"{sample_token}_id{lidar_id}_modar.pth"
        if path_modar.exists():
            modar = torch.load(path_modar)  # on gpu, (N_modar, 7 + 2) - box-7, score, label
            # ---
            # propagate modar forward
            path_foregr = self.exchange_database / f"{sample_token}_id{lidar_id}_foreground.pth"
            if path_foregr.exists() and exchange_setting == 'prev':
                foregr = torch.load(path_foregr)  # on gpu, (N_fore, 5 + 2 + 3 + 3) - point-5, sweep_idx, inst_idx, cls_prob-3, flow-3

                # pool
                box_idx_of_foregr = roiaware_pool3d_utils.points_in_boxes_gpu(
                    foregr[:, :3].unsqueeze(0), modar[:, :7].unsqueeze(0)
                ).squeeze(0).long()  # (N_foregr,) | == -1 mean not belong to any boxes
                mask_valid_foregr = box_idx_of_foregr > -1
                foregr = foregr[mask_valid_foregr]
                box_idx_of_foregr = box_idx_of_foregr[mask_valid_foregr]

                unq_box_idx, inv_unq_box_idx = torch.unique(box_idx_of_foregr, return_inverse=True)

                # weighted sum of foregrounds' offset; weights = foreground's prob dynamic
                boxes_offset = scatter(foregr[:, -3:], inv_unq_box_idx, dim=0, reduce='mean') * 2.  # (N_modar, 3)
                # offset modar; here, assume objects maintain the same speed
                modar[unq_box_idx, :3] += boxes_offset

            modar = modar.cpu().numpy()
        else:
            modar = np.zeros((0, 9))

        return modar, glob_se3_lidar

    def _get_lidar_token_of_present_agents(self, sample_token: str) -> Dict[int, str]:
        out = dict()
        if sample_token == '':
            return out

        sample = self.nusc.get('sample', sample_token)
        for sensor_name, sensor_token in sample['data'].items():
            if sensor_name not in self._lidars_name:
                continue
            lidar_id = int(sensor_name.split('_')[-1])
            out[lidar_id] = sensor_token

        return out

    def __getitem__(self, index):
        if self._merge_all_iters_to_one_epoch:
            index = index % len(self.infos)

        info = copy.deepcopy(self.infos[index])
        gt_boxes, gt_names = info['gt_boxes'], info['gt_names']
        # gt_boxes: (N_tot, 7)
        # gt_names: (N_tot,)

        ego_se3_glob = np.linalg.inv(get_nuscenes_sensor_pose_in_global(self.nusc, info['lidar_token']))  # (4, 4)

        sample_token = info['token']
        sample = self.nusc.get('sample', sample_token)

        # get prediction of the ego vehicle @ now
        exchange_boxes, exchange_metadata = dict(), dict()
        exchange_boxes[1] = self._get_prediction_ego(sample_token)
        exchange_metadata[1] = exchange_boxes[1].shape[0]

        if self.dataset_cfg.EXCHANGE_SETTING == 'now':
            dict_lidar_id_to_token = self._get_lidar_token_of_present_agents(sample_token)
            _token_of_sample_of_interest = sample_token
        elif self.dataset_cfg.EXCHANGE_SETTING == 'prev':
            dict_lidar_id_to_token = self._get_lidar_token_of_present_agents(sample['prev'])
            _token_of_sample_of_interest = sample['prev']
        else:
            raise NotImplementedError(f"EXCHANGE_SETTING := {self.dataset_cfg.EXCHANGE_SETTING} is unknown")

        if len(dict_lidar_id_to_token) > 0:
            for lidar_id, lidar_token in dict_lidar_id_to_token.items():
                if lidar_id == 1:
                    # ego vehicle is already handled above
                    continue

                modar, glob_se3_lidar = self._get_prediction_agent(lidar_id, lidar_token, _token_of_sample_of_interest, self.dataset_cfg.EXCHANGE_SETTING)

                # transform modar to ego frame
                ego_se3_lidar = ego_se3_glob @ glob_se3_lidar
                modar[:, :7] = apply_se3_(ego_se3_lidar, boxes_=modar[:, :7], return_transformed=True)

                # store agent's modar
                exchange_boxes[lidar_id] = modar
                exchange_metadata[lidar_id] = modar.shape[0]

        # -----------------
        # format output
        # assemble datadict
        input_dict = {
            'points': np.zeros((1, 7)),  # Dummy | (N_pts, 5 + 2) - point-5, sweep_idx, inst_idx
            'gt_boxes': gt_boxes,  # (N_inst, 7)
            'gt_names': gt_names,  # (N_inst,)
            'frame_id': Path(info['lidar_path']).stem,
            'metadata': {
                'lidar_token': info['lidar_token'],
                'num_sweeps_target': self.num_sweeps,
                'sample_token': info['token'],
                'lidar_id': 1,
                'num_original': 0,
                'exchange': exchange_metadata,
                'exchange_boxes': exchange_boxes,  # (N_boxes_tot, 7 + 2) - box-7, score, label
            }
        }

        # data augmentation & other stuff
        data_dict = self.prepare_data(data_dict=input_dict)

        return data_dict


import asyncio
import json
from datetime import datetime

import aiohttp

from pydantic import BaseModel, Field, NonNegativeFloat

from faststream import ContextRepo, FastStream, Logger
from faststream.kafka import KafkaBroker

broker = KafkaBroker("localhost:9092")
app = FastStream(broker)

class CryptoPrice(BaseModel):
    price: NonNegativeFloat = Field(
        ..., examples=[50000.0], description="Current price of cryptocurrency in USD"
    )
    crypto_currency: str = Field(
        ..., examples=["BTC"], description="The cryptocurrency"
    )

publisher = broker.publisher("new_crypto_price")

async def fetch_crypto_price(
    url: str, crypto_currency: str, logger: Logger, context: ContextRepo, time_interval: int = 2
) -> None:
    # Always use context: ContextRepo for storing app_is_running variable
    while context.get("app_is_running"):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                if response.status == 200:
                    data = await response.json()
                    price = data["data"]["amount"]
                    new_crypto_price = CryptoPrice(
                        price=price, crypto_currency=crypto_currency
                    )
                    await publisher.publish(
                        new_crypto_price,
                        key=crypto_currency.encode("utf-8"),
                    )
                else:
                    logger.warning(
                        f"Failed API request {url} at time {datetime.now()}"
                    )

        await asyncio.sleep(time_interval)

@app.on_startup
async def app_setup(context: ContextRepo):
    context.set_global("app_is_running", True)

@app.on_shutdown
async def shutdown(context: ContextRepo):
    context.set_global("app_is_running", False)

    # Get all the running tasks and wait them to finish
    fetch_tasks = context.get("fetch_tasks")
    await asyncio.gather(*fetch_tasks)

@app.after_startup
async def publish_crypto_price(logger: Logger, context: ContextRepo):
    logger.info("Starting publishing:")

    cryptocurrencies = [("Bitcoin", "BTC"), ("Ethereum", "ETH")]
    fetch_tasks = [
        asyncio.create_task(
            fetch_crypto_price(
                f"https://api.coinbase.com/v2/prices/{crypto_currency}-USD/spot",
                crypto_currency,
                logger,
                context,
            )
        )
        for _, crypto_currency in cryptocurrencies
    ]
    # you need to save asyncio tasks so you can wait them to finish at app shutdown (the function with @app.on_shutdown function)
    context.set_global("fetch_tasks", fetch_tasks)


from flask import Blueprint, g
from flask_graphql import GraphQLView
from flask_cors import CORS
from .schema import schema

api = Blueprint('api', __name__)
CORS(api, supports_credentials=True)  # Enables CORS with cross origin cookies

class CustomGraphQlView(GraphQLView):
    def dispatch_request(self):
        response = super().dispatch_request()
        for cookie in g.get("cookies", []):
            response.set_cookie(cookie.key, cookie.value, **cookie.settings)

        return response

api.add_url_rule(
    "/graphql",
    view_func=CustomGraphQlView.as_view(
        "graphql",
        schema=schema,
        graphiql=True,
        middleware=[]
    )
)


import csv
import json

# Save .csv file from dict List [{}]
def save_file(results, filename, format):

        if(format=='csv'):
            if(len(results) > 0):
                with open(f'{filename}.csv', 'w', encoding='utf8', newline='') as output_file:
                    output_file.write('sep=,\n')
                    fc = csv.DictWriter(output_file, fieldnames=results[0].keys())
                    fc.writeheader()
                    fc.writerows(results)
        elif(format=='json'):
            with open(f'{filename}.json', 'w') as f:
                json.dump(results, f)

        print(f'file saved to {filename}.{format}')


import os
import dataclasses
import unittest
import torch
import math
import copy

import numpy as np
import lpips

from dataset.co3d_dataset import Co3dDataset, FrameData
from dataset.dataset_zoo import DATASET_ROOT
from tools.utils import dataclass_to_cuda_
from evaluation.evaluate_new_view_synthesis import eval_batch
from tools.metric_utils import calc_psnr, eval_depth
from models.model_dbir import ModelDBIR

class TestEvaluation(unittest.TestCase):
    def setUp(self):
        # initialize evaluation dataset/dataloader
        torch.manual_seed(42)
        category = "skateboard"
        dataset_root = DATASET_ROOT
        frame_file = os.path.join(dataset_root, category, "frame_annotations.jgz")
        sequence_file = os.path.join(dataset_root, category, "sequence_annotations.jgz")
        self.image_size = 256
        self.dataset = Co3dDataset(
            frame_annotations_file=frame_file,
            sequence_annotations_file=sequence_file,
            dataset_root=dataset_root,
            image_height=self.image_size,
            image_width=self.image_size,
            box_crop=True,
            load_point_clouds=True,
        )
        self.bg_color = 0.0

        # init the lpips model for eval
        self.lpips_model = lpips.LPIPS(net="vgg")

    def test_eval_depth(self):
        """
        Check that eval_depth correctly masks errors and that, for get_best_scale=True,
        the error with scaled prediction equals the error without scaling the
        predicted depth. Finally, test that the error values are as expected
        for prediction and gt differing by a constant offset.
        """
        gt = (torch.randn(10, 1, 300, 400, device="cuda") * 5.0).clamp(0.0)
        mask = (torch.rand_like(gt) > 0.5).type_as(gt)

        for diff in 10 ** torch.linspace(-5, 0, 6):
            for crop in (0, 5):

                pred = gt + (torch.rand_like(gt) - 0.5) * 2 * diff

                # scaled prediction test
                mse_depth, abs_depth = eval_depth(
                    pred,
                    gt,
                    crop=crop,
                    mask=mask,
                    get_best_scale=True,
                )
                mse_depth_scale, abs_depth_scale = eval_depth(
                    pred * 10.0,
                    gt,
                    crop=crop,
                    mask=mask,
                    get_best_scale=True,
                )
                self.assertAlmostEqual(
                    float(mse_depth.sum()), float(mse_depth_scale.sum()), delta=1e-4
                )
                self.assertAlmostEqual(
                    float(abs_depth.sum()), float(abs_depth_scale.sum()), delta=1e-4
                )

                # error masking test
                pred_masked_err = gt + (torch.rand_like(gt) + diff) * (1 - mask)
                mse_depth_masked, abs_depth_masked = eval_depth(
                    pred_masked_err,
                    gt,
                    crop=crop,
                    mask=mask,
                    get_best_scale=True,
                )
                self.assertAlmostEqual(
                    float(mse_depth_masked.sum()), float(0.0), delta=1e-4
                )
                self.assertAlmostEqual(
                    float(abs_depth_masked.sum()), float(0.0), delta=1e-4
                )
                mse_depth_unmasked, abs_depth_unmasked = eval_depth(
                    pred_masked_err,
                    gt,
                    crop=crop,
                    mask=1 - mask,
                    get_best_scale=True,
                )
                self.assertGreater(
                    float(mse_depth_unmasked.sum()),
                    float(diff ** 2),
                )
                self.assertGreater(
                    float(abs_depth_unmasked.sum()),
                    float(diff),
                )

                # tests with constant error
                pred_fix_diff = gt + diff * mask
                for _mask_gt in (mask, None):
                    mse_depth_fix_diff, abs_depth_fix_diff = eval_depth(
                        pred_fix_diff,
                        gt,
                        crop=crop,
                        mask=_mask_gt,
                        get_best_scale=False,
                    )
                    if _mask_gt is not None:
                        expected_err_abs = diff
                        expected_err_mse = diff ** 2
                    else:
                        err_mask = (gt > 0.0).float() * mask
                        if crop > 0:
                            err_mask = err_mask[:, :, crop:-crop, crop:-crop]
                            gt_cropped = gt[:, :, crop:-crop, crop:-crop]
                        else:
                            gt_cropped = gt
                        gt_mass = (gt_cropped > 0.0).float().sum(dim=(1, 2, 3))
                        expected_err_abs = (
                            diff * err_mask.sum(dim=(1, 2, 3)) / (gt_mass)
                        )
                        expected_err_mse = diff * expected_err_abs
                    self.assertTrue(
                        torch.allclose(
                            abs_depth_fix_diff,
                            expected_err_abs * torch.ones_like(abs_depth_fix_diff),
                            atol=1e-4,
                        )
                    )
                    self.assertTrue(
                        torch.allclose(
                            mse_depth_fix_diff,
                            expected_err_mse * torch.ones_like(mse_depth_fix_diff),
                            atol=1e-4,
                        )
                    )

    def test_psnr(self):
        """
        Compare against opencv and check that the psnr is above
        the minimum possible value.
        """
        import cv2

        im1 = torch.rand(100, 3, 256, 256).cuda()
        for max_diff in 10 ** torch.linspace(-5, 0, 6):
            im2 = im1 + (torch.rand_like(im1) - 0.5) * 2 * max_diff
            im2 = im2.clamp(0.0, 1.0)
            # check that our psnr matches the output of opencv
            psnr = calc_psnr(im1, im2)
            psnr_cv2 = cv2.PSNR(
                im1.cpu().numpy().astype(np.float64),
                im2.cpu().numpy().astype(np.float64),
                1.0,
            )
            self.assertAlmostEqual(float(psnr), float(psnr_cv2), delta=1e-4)
            # check that all psnrs are bigger than the minimum possible psnr
            max_mse = max_diff ** 2
            min_psnr = 10 * math.log10(1.0 / max_mse)
            for _im1, _im2 in zip(im1, im2):
                _psnr = calc_psnr(_im1, _im2)
                self.assertTrue(float(_psnr) >= min_psnr)

    def _one_sequence_test(
        self,
        seq_dataset,
        n_batches=2,
        min_batch_size=5,
        max_batch_size=10,
    ):
        # form a list of random batches
        batch_indices = []
        for bi in range(n_batches):
            batch_size = torch.randint(
                low=min_batch_size, high=max_batch_size, size=(1,)
            )
            batch_indices.append(torch.randperm(len(seq_dataset))[:batch_size])

        loader = torch.utils.data.DataLoader(
            seq_dataset,
            # batch_size=1,
            shuffle=False,
            batch_sampler=batch_indices,
            collate_fn=FrameData.collate,
        )

        model = ModelDBIR(image_size=self.image_size, bg_color=self.bg_color)
        model.cuda()
        self.lpips_model.cuda()

        for frame_data in loader:
            self.assertIsNone(frame_data.frame_type)
            # override the frame_type
            frame_data.frame_type = [
                "train_unseen",
                *(["train_known"] * (len(frame_data.image_rgb) - 1)),
            ]

            # move frame_data to gpu
            frame_data = dataclass_to_cuda_(frame_data)
            preds = model(**dataclasses.asdict(frame_data))

            nvs_prediction = copy.deepcopy(preds["nvs_prediction"])
            eval_result = eval_batch(
                frame_data,
                nvs_prediction,
                bg_color=self.bg_color,
                lpips_model=self.lpips_model,
            )

            # Make a terribly bad NVS prediction and check that this is worse
            # than the DBIR prediction.
            nvs_prediction_bad = copy.deepcopy(preds["nvs_prediction"])
            nvs_prediction_bad.depth_render += (
                torch.randn_like(nvs_prediction.depth_render) * 100.0
            )
            nvs_prediction_bad.image_render += (
                torch.randn_like(nvs_prediction.image_render) * 100.0
            )
            nvs_prediction_bad.mask_render = (
                torch.randn_like(nvs_prediction.mask_render) > 0.0
            ).float()
            eval_result_bad = eval_batch(
                frame_data,
                nvs_prediction_bad,
                bg_color=self.bg_color,
                lpips_model=self.lpips_model,
            )

            lower_better = {
                "psnr": False,
                "psnr_fg": False,
                "depth_abs_fg": True,
                "iou": False,
                "rgb_l1": True,
                "rgb_l1_fg": True,
            }

            for metric in lower_better.keys():
                m_better = eval_result[metric]
                m_worse = eval_result_bad[metric]
                if m_better != m_better or m_worse != m_worse:
                    continue  # metric is missing, i.e. NaN
                _assert = (
                    self.assertLessEqual
                    if lower_better[metric]
                    else self.assertGreaterEqual
                )
                _assert(m_better, m_worse)

    def test_full_eval(self, n_sequences=5):
        """Test evaluation."""
        for seq, idx in list(self.dataset.seq_to_idx.items())[:n_sequences]:
            seq_dataset = torch.utils.data.Subset(self.dataset, idx)
            self._one_sequence_test(seq_dataset)


import torch
import torchaudio

from torchaudio.transforms import MelSpectrogram, Spectrogram

def load_wav_to_torch(full_path, hop_size=0, slice_train=False):
    wav, sampling_rate = torchaudio.load(full_path, normalize=True)
    if not slice_train:
        p = (wav.shape[-1] // hop_size + 1) * hop_size - wav.shape[-1]
        wav = torch.nn.functional.pad(wav, (0, p), mode="constant").data
    return wav.squeeze(0), sampling_rate

class SpectrogramFixed(torch.nn.Module):
    """In order to remove padding of torchaudio package + add log10 scale."""

    def __init__(self, **kwargs):
        super(SpectrogramFixed, self).__init__()
        self.torchaudio_backend = Spectrogram(**kwargs)

    def forward(self, x):
        outputs = self.torchaudio_backend(x)

        return outputs[..., :-1]

class MelSpectrogramFixed(torch.nn.Module):
    """In order to remove padding of torchaudio package + add log10 scale."""

    def __init__(self, **kwargs):
        super(MelSpectrogramFixed, self).__init__()
        self.torchaudio_backend = MelSpectrogram(**kwargs)

    def forward(self, x):
        outputs = torch.log(self.torchaudio_backend(x) + 0.001)

        return outputs[..., :-1]

def torch_wav2spec(wav_fn, fft_size, hop_size, win_length, num_mels, fmin, fmax, sample_rate):
    """ Waveform to linear-spectrogram and mel-sepctrogram. """
    # Read wavform
    wav, sr = load_wav_to_torch(wav_fn, hop_size, slice_train=False)
    if sr != sample_rate:
        raise ValueError(f"{sr} SR doesn't match target {sample_rate} SR")
    if torch.min(wav) < -1.:
        print('min value is ', torch.min(wav))
    if torch.max(wav) > 1.:
        print('max value is ', torch.max(wav))
    # Spectrogram process
    spec_fn = SpectrogramFixed(n_fft=fft_size, win_length=win_length, hop_length=hop_size,
                               window_fn=torch.hann_window).to(device=wav.device)
    spec = spec_fn(wav)
    # Mel-spectrogram
    mel_fn = MelSpectrogramFixed(sample_rate=sample_rate, n_fft=fft_size, win_length=win_length,
                                 hop_length=hop_size, f_min=fmin, f_max=fmax, n_mels=num_mels,
                                 window_fn=torch.hann_window).to(device=wav.device)
    mel = mel_fn(wav)
    # Wav-processing
    wav = wav.squeeze(0)[:mel.shape[-1]*hop_size]
    # Check wav and spectorgram
    assert wav.shape[-1] == mel.shape[-1] * hop_size, f"| wav: {wav.shape}, spec: {spec.shape}, mel: {mel.shape}"
    assert mel.shape[-1] == spec.shape[-1], f"| wav: {wav.shape}, spec: {spec.shape}, mel: {mel.shape}"
    return {"wav": wav.cpu().detach().numpy(), "linear": spec.squeeze(0).T.cpu().detach().numpy(),
            "mel": mel.squeeze(0).T.cpu().detach().numpy()}


from __future__ import absolute_import, division, print_function

# Local Imports
from modeling import ArgStrModel
from arguments import TrainingArguments
from training import ArgStrTrainer
from processors import get_datasets
from utils import Data_Collator, set_seed

# Standard Imports
import os
import random

# Third Party Imports
import json
import torch
import mlflow

from transformers import BertConfig

if __name__ == '__main__':
    # load the best trained model and config
    config_available = False
    os.environ["CUDA_VISIBLE_DEVICES"] = "3"
    # define the experiment parameters
    bert_arch = "bert-base-uncased"
    task_name = "STLAS_randomized_LOO_gretz_topic"
    exp_name = task_name + "_v1_bb"
    mlflow_exp_name = "ASL_randomized_v2"
    NUM_OF_SEEDS = 5

    # define the path from where the task data is loaded from.
    task_data_dir = "/mnt/data2/Sid/arg_quality/pytorch/task4_hpo/data/*.csv"

    if config_available:
        config_file = open("/mnt/data2/Sid/arg_quality/pytorch/task4_hpo/best_model_details_MTLAS_LOO_swanson_v2_bb"
                           ".json", )
        config_data = json.load(config_file)
    else:
        # define config
        config_data = {
            "bert_arch": bert_arch,
            "task_name": task_name,
            "exp_name": exp_name,
            "device": torch.device('cuda' if torch.cuda.is_available() else 'cpu'),
            "is_distributed": False,
            "resources_per_trial": {
                'cpu': 4,
                'gpu': 1
            },

            "data_dir": task_data_dir,
            "split_by_topic": True if "randomized" in task_name else False,
            "eval_batch_size": 128,
            "train_batch_size": 64,
            "max_seq_length": None,
            "max_seq_length_perc": 0.95,
            "data_collator": Data_Collator,

            "dropout_prob": 0.1,
            "bert_hidden_layers": 4,
            "nn_config": 1,
            "dataset_loss_method": "unweighted",

            "learning_rate": 4.8672041684500765e-06,
            "weight_decay": 0.1936871758204528,
            "num_epochs": 50,
            "max_steps": -1,  # We use num_epochs instead.

            "mlflow": {
                "experiment_name": mlflow_exp_name,
                "tracking_uri": "http://mlflow.dbs.ifi.lmu.de:5000"
            }
        }

    if mlflow.get_experiment_by_name(mlflow_exp_name) is None:
        mlflow.create_experiment(mlflow_exp_name)
    mlflow.set_experiment(experiment_name=mlflow_exp_name)
    mlflow.set_tracking_uri("http://mlflow.dbs.ifi.lmu.de:5000")

    # define 10 seeds to run for training
    seed_list = random.sample(range(0, 10000), NUM_OF_SEEDS)
    for seed_value in seed_list:
        set_seed(seed_value)
        with mlflow.start_run(run_name="asl_randomized_v1"):
            mlflow.log_param("seed", seed_value)
            mlflow.log_param("Task Name", task_name)
            print("Seed:", seed_value)
            train_dataset, eval_dataset, test_dataset, task_dict = get_datasets(config_data)
            # Load model setup.
            if not config_available:
                bert_config = BertConfig.from_pretrained(
                    config_data["bert_arch"],
                    finetuning_task=task_name,
                    output_hidden_states=True
                )

                model = ArgStrModel.from_pretrained(
                    config_data["bert_arch"],
                    config=bert_config,
                    dropout_prob=config_data["dropout_prob"],
                    bert_hidden_layers=config_data["bert_hidden_layers"],
                    mlp_config=config_data["nn_config"],
                    task_dict=task_dict,
                    device=config_data["device"]
                )
            else:
                bert_config = BertConfig.from_pretrained(
                    config_data["bert_arch"],
                    finetuning_task=task_name,
                    output_hidden_states=True
                )
                model = ArgStrModel(
                    config=bert_config,
                    dropout_prob=config_data["dropout_prob"],
                    bert_hidden_layers=config_data["bert_hidden_layers"],
                    mlp_config=config_data["nn_config"],
                    task_dict=task_dict,
                    device=config_data["device"])

                with open(os.path.join(config_data["best_checkpoint_path"], "best_model.pt"), 'rb') as checkpt:
                    model_state, optimizer_state = torch.load(checkpt)
                model.load_state_dict(model_state)

            training_args = TrainingArguments(
                learning_rate=config_data["learning_rate"],
                train_model=True,
                evaluate_during_training=True,
                save_steps=0,
                max_num_train_epochs=25,
                train_batch_size=config_data["train_batch_size"],
                eval_batch_size=config_data["eval_batch_size"],
                weight_decay=config_data["weight_decay"],
                weighted_dataset_loss=config_data["dataset_loss_method"]
            )

            retrain_runner = ArgStrTrainer(
                model=model,
                args=training_args,
                train_dataset=train_dataset,
                eval_dataset=eval_dataset,
                test_dataset=test_dataset,
                data_collator=Data_Collator,
                task_name=config_data["task_name"]
            )

            retrain_runner.train_model(device=config_data["device"],
                                       mlflow_logging=True,
                                       retraining=True,
                                       seed_value=seed_value)

            if "MTLAS" in task_name:
                retrain_runner.infer_model(
                    infer_dataset=test_dataset,
                    device=config_data["device"],
                    exp_name=config_data["exp_name"],
                    task_dict=task_dict,
                    exp_seed=seed_value,
                )


import time
import tensorflow.compat.v1 as tf
# tf.disable_eager_execution()
tf.config.run_functions_eagerly(True)
tf.enable_eager_execution()
from utils import *
from models import RGCN
import random
import pandas as pd
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF
from gcn.models import GCN
# Set random seed
seed = 123
np.random.seed(seed)
tf.set_random_seed(seed)
random.seed(seed)

# Settings
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('dataset', 'cora', 'Dataset string.')  # 'cora', 'citeseer', 'pubmed'
flags.DEFINE_float('learning_rate', 0.01, 'Initial learning rate.')
flags.DEFINE_integer('epochs', 200, 'Number of epochs to train.')
flags.DEFINE_integer('hidden1', 32, 'Number of units in hidden layer.')
flags.DEFINE_float('dropout', 0.6, 'Dropout rate (1 - keep probability).')
flags.DEFINE_float('weight_decay', 5e-4, 'Weight for L2 loss on embedding matrix.')
flags.DEFINE_float('para_var', 1, 'Parameter of variance-based attention')
flags.DEFINE_float('para_kl', 5e-4, 'Parameter of kl regularization')
flags.DEFINE_float('para_l2', 5e-4, 'Parameter for l2 loss.')
flags.DEFINE_integer('early_stopping', 20, 'Tolerance for early stopping (# of epochs).')
flags.DEFINE_integer('max_degree', 3, 'Maximum Chebyshev polynomial degree.')

# Load data
adj, features, y_train, y_val, y_test, train_mask, val_mask, test_mask, label = load_data(FLAGS.dataset)

# train_mask[641:700] = True

perturbed_features, y_train_gpc = perturb_features_gpc(features, 0.8)
gpc_idx, gpc_feature, gpc_y_train_gpc = get_gpc_train_data(perturbed_features, y_train_gpc, train_mask, test_mask, val_mask)

print(len(gpc_idx))

kernel = 1.0 * RBF(1.0)
gpc = GaussianProcessClassifier(kernel=kernel,
        random_state=0).fit(gpc_feature[:500], gpc_y_train_gpc[:500])
# gpc.score(perturbed_features, y_train_gpc)
gpc_res = gpc.predict(perturbed_features)
# print(type(gpc_res))
# gpc_res = np.asarray(y_train_gpc) # delete later, used for testing

# print(type(y_train_gpc))
gpc_predict_pert_idx = [i for i, x in enumerate(gpc_res==1) if x]

# print(all_idx_to_remove)

features = sp.csr_matrix(perturbed_features)
# features, y_train, train_mask, adj, label, y_val, val_mask = remove_pert(features, y_train, train_mask, adj, label, y_val, val_mask, gpc_predict_pert_idx)
features = modify_pert(features, gpc_predict_pert_idx) # for continuous features
# print(train_mask)

features = preprocess_features(features)

support = [preprocess_adj(adj, -0.5), preprocess_adj(adj, -1.0)]
placeholders = {
    'support': [tf.sparse_placeholder(tf.float32) for _ in range(2)],
    'features': tf.sparse_placeholder(tf.float32, shape=tf.constant(features[2], dtype=tf.int64)),
    'labels': tf.placeholder(tf.float32, shape=(None, y_train.shape[1])),
    'labels_mask': tf.placeholder(tf.int32),
    'dropout': tf.placeholder_with_default(0., shape=()),
    'num_features_nonzero': tf.placeholder(tf.int32),
}
model = GCN(placeholders, input_dim=features[2][1], logging=True)
sess = tf.Session()
def evaluate(features, support, labels, mask, placeholders, adj):
    t_test = time.time()
    feed_dict_val = construct_feed_dict(features, support, labels, mask, placeholders, adj)
    outs_val = sess.run([model.loss, model.accuracy], feed_dict=feed_dict_val)
    return outs_val[0], outs_val[1], (time.time() - t_test)

sess.run(tf.global_variables_initializer())
cost_val = []
var1 = []
for epoch in range(FLAGS.epochs):
    t = time.time()
    feed_dict = construct_feed_dict(features, support, y_train, train_mask, placeholders, adj)
    feed_dict.update({placeholders['dropout']: FLAGS.dropout})
    outs = sess.run([model.opt_op, model.loss, model.accuracy, model.vars], feed_dict=feed_dict)
    # print(outs[3].shape)
    # if epoch == (FLAGS.epochs-1):
    #     # print('%%%%%%%%%%%%%%%%%%%%%%%%%%%%')
    #     df = pd.DataFrame(data = outs[3])
    #     df.to_csv('/home/zihe-leon/Desktop/RobustGCN-master/src/var0.csv', index = False)
    cost, _, duration = evaluate(features, support, y_val, val_mask, placeholders, adj)
    cost_val.append(cost)
    # Print results
    print("Epoch:", '%04d' % (epoch + 1), "train_loss=", "{:.5f}".format(outs[1]),
          "train_acc=", "{:.5f}".format(outs[2]), "time=", "{:.5f}".format(time.time() - t))
    if epoch > FLAGS.early_stopping and cost_val[-1] > np.mean(cost_val[-(FLAGS.early_stopping+1):-1]):
        print("Early stopping...")
        break
print("Optimization Finished!")

adj, features, y_train, y_val, y_test, train_mask, val_mask, test_mask, label = load_data(FLAGS.dataset)
features = preprocess_features(features)
support = [preprocess_adj(adj, -0.5), preprocess_adj(adj, -1.0)]
test_cost, test_acc, test_duration = evaluate(features, support, y_test, test_mask, placeholders, adj)
print("Test set results:", "cost=", "{:.5f}".format(test_cost),
      "accuracy=", "{:.5f}".format(test_acc), "time=", "{:.5f}".format(test_duration))


# https://medium.com/analytics-vidhya/computer-vision-and-deep-learning-part-2-586b6a0d3220  --- main
# https://github.com/Esri/raster-deep-learning/blob/master/docs/writing_deep_learning_python_raster_functions.md
import cv2
import numpy as np

from matplotlib import pyplot as plt
cv_image= cv2.imread("/home/jameshung/Pictures/forest01.jpg",0)
one =cv2.adaptiveThreshold(cv_image,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11,2)
ret2, two = cv2.threshold(cv_image,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(cv_image,(5,5),0)
ret3,three = cv2.threshold(blur, 0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
images = [cv_image, 0, one,
          cv_image, 0, two,
          blur, 0, three]
titles = ['Original Image','Histogram','Adaptive Mean Thresholding',
          'Original Image','Histogram',"Otsu's Thresholding",
          'Gaussian filtered Image','Histogram',"Otsu's Thresholding of Gaussian Blur Image"]
for i in range(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()
cv2.waitKey(1000)


""" Provides the different Bounds that are used by the Table to determine
the Cells that are adjacent to the Table. """

from __future__ import annotations

from _operator import attrgetter
from itertools import cycle
from typing import Callable, cast, Iterable, NamedTuple, Protocol, TypeVar

from pdf2gtfs.config import Config
from pdf2gtfs.datastructures.pdftable.bbox import BBox
from pdf2gtfs.datastructures.table.direction import Direction, E, N, S, W
from pdf2gtfs.datastructures.table.cell import C, Cs

B = TypeVar("B", bound="Bounds")

class F(Protocol):
    """ Used as a type to typecheck min/max functions correctly. """
    def __call__(self, cells: Iterable[C] | Iterable[BBox],
                 key: Callable[[C | BBox], float]) -> C:
        pass

# Arguments used by the N-/S-/W-/EBounds.
#  — func: The function (min / max) used to determine the correct limit.
#  — direction: The Direction of the limit.
BoundArg = NamedTuple("BoundArg", [("func", F), ("direction", Direction)])

class Bounds:
    """ Basic Bounds, where not all limits necessarily exist. """
    d: Direction = None

    def __init__(self, n: float | None, w: float | None,
                 s: float | None, e: float | None) -> None:
        self._n = n
        self._w = w
        self._s = s
        self._e = e
        self._update_hbox()
        self._update_vbox()

    @classmethod
    def from_bboxes(cls, bboxes: list[BBox], *,
                    n: BoundArg | None = None, w: BoundArg | None = None,
                    s: BoundArg | None = None, e: BoundArg | None = None
                    ) -> B:
        """ Create a new Bounds from the BBoxes, based on which args are given.

        :param bboxes: The BBoxes used for construction.
        :param n: The northern BoundArg. None for NBounds.
        :param w: The western BoundArg. None for WBounds.
        :param s: The southern BoundArg. None for SBounds.
        :param e: The eastern BoundArg. None for EBounds.
        :return: A new Bounds created from the given BBoxes,
            based on which BoundArgs are provided.
        """
        return cls(n=get_limit_from_cells(bboxes, n),
                   w=get_limit_from_cells(bboxes, w),
                   s=get_limit_from_cells(bboxes, s),
                   e=get_limit_from_cells(bboxes, e))

    @classmethod
    def overlaps_any(cls, cells: Cs, c2: C) -> bool:
        """ Check if the given Cell overlaps with any of the given Cells.

        The overlap function is determined by cls.

        :param cells: Use these Cells to check overlap.
        :param c2: The Cell that is checked.
        :return: True if the Cell overlaps. False, otherwise.
        """
        func = getattr(c2.bbox, cls.d.o.overlap_func)
        for c1 in cells:
            if func(c1.bbox, 0.8):
                return True
        return False

    @classmethod
    def select_adjacent_cells(cls, border: list[BBox], cells: Cs) -> Cs:
        """ Select those Cells that are adjacent to the border BBoxes.

        :param border: The row/col of a Table that is used to determine
            if a Cell is adjacent to the Table.
        :param cells: The Cells that are checked for adjacency.
        :return: Those Cells, which are adjacent to the Table.
        """
        def get_all_adjacent_cells() -> Cs:
            """ Get Cells that fit only three bounds,
            but are overlapping with Cells that overlap all four.

            If we are extra_greedy, also get those cells that recursively
            overlap with cells that overlap with other cells.
            """
            # Need to shallow copy for overlap_cells to be different.
            all_cells = list(min_cells)
            overlap_cells = all_cells if Config.extra_greedy else min_cells
            while True:
                new_cells = [c for c in cells
                             if cls.overlaps_any(overlap_cells, c)
                             and c not in all_cells]
                if not new_cells:
                    break
                all_cells += new_cells
            return all_cells

        # Get the three basic bounds, which are created from the border.
        bounds = cls.from_bboxes(border)
        cells = list(filter(bounds.within_bounds, cells))
        if not cells:
            return []

        bounds.update_missing_bound(cells)

        # These are the Cells that fit all bounds.
        min_cells = list(filter(bounds.within_bounds, cells))

        adjacent_cells = get_all_adjacent_cells()

        # Sort columns by y0 and rows by x0.
        lower_coord = attrgetter(f"bbox.{cls.d.o.normal.lower.coordinate}")
        return list(sorted(adjacent_cells, key=lower_coord))

    @property
    def n(self) -> float | None:
        """ The northern bound, i.e., y0/the lowest y coordinate. """
        return self._n

    @n.setter
    def n(self, value: float | None) -> None:
        self._n = value
        self._update_vbox()

    @property
    def s(self) -> float | None:
        """ The southern bound, i.e., y1/the largest y coordinate. """
        return self._s

    @s.setter
    def s(self, value: float | None) -> None:
        self._s = value
        self._update_vbox()

    @property
    def w(self) -> float | None:
        """ The western bound, i.e., x0/the lowest x coordinate. """
        return self._w

    @w.setter
    def w(self, value: float | None) -> None:
        self._w = value
        self._update_hbox()

    @property
    def e(self) -> float | None:
        """ The eastern bound, i.e., x1/the largest y coordinate. """
        return self._e

    @e.setter
    def e(self, value: float | None) -> None:
        self._e = value
        self._update_hbox()

    @property
    def hbox(self) -> BBox | None:
        """ The horizontal BBox, using only w/e. """
        return self._hbox

    @property
    def vbox(self) -> BBox | None:
        """ The vertical BBox, using only n/s. """
        return self._vbox

    def _update_hbox(self) -> None:
        if self.w is None or self.e is None:
            hbox = None
        else:
            hbox = BBox(self.w, -1, self.e, -1)
        self._hbox = hbox

    def _update_vbox(self) -> None:
        if self.n is None or self.s is None:
            vbox = None
        else:
            vbox = BBox(-1, self.n, -1, self.s)
        self._vbox = vbox

    def within_h_bounds(self, bbox: BBox) -> bool:
        """ Check if the given BBox is within the current Bounds, horizontally.

        :param bbox: The BBox that is checked.
        :return: True if the BBox is within Bounds. False, otherwise.
        """
        if self.hbox and self.hbox.is_h_overlap(bbox, 0.5):
            return True
        if self.hbox:
            return False
        if self.w is not None and bbox.x1 <= self.w:
            return False
        if self.e is not None and bbox.x0 >= self.e:
            return False
        return True

    def within_v_bounds(self, bbox: BBox) -> bool:
        """ Check if the given BBox is within the current Bounds, vertically.

        :param bbox: The BBox that is checked.
        :return: True if the BBox is within Bounds. False, otherwise.
        """
        if self.vbox and self.vbox.is_v_overlap(bbox, 0.5):
            return True
        if self.vbox:
            return False
        if self.n is not None and bbox.y1 <= self.n:
            return False
        if self.s is not None and bbox.y0 >= self.s:
            return False
        return True

    def within_bounds(self, cell: C) -> bool:
        """ Check if the Cell is within the bounds.

        If the hbox/vbox is None, that is, if at least one of the w/e or n/s
        coordinates is None, the check will not fail immediately.
        Instead, in that case, only the existing (if any) coordinate will
        be checked.

        :param cell: The Cell that is checked.
        :return: True, if obj is within both the hbox and the vbox.
            False, otherwise.
        """
        bbox = cell.bbox
        return self.within_h_bounds(bbox) and self.within_v_bounds(bbox)

    def merge(self, bounds: B) -> None:
        """ Merge the Bounds, such that the resulting Bounds contain both.

        :param bounds: The Bounds that is merged into this one.
        """
        # n/w use min for lower bound, s/e use max for larger bound.
        for coordinate, func in zip("nswe", cycle((min, max))):
            getter = attrgetter(coordinate)
            value = func(map(getter, (self, bounds)), default=None)
            setattr(self, coordinate, value)

    def _update_single_limit(
            self, which: str, arg: BoundArg, cells: list[C]) -> None:
        """ Update a single bound using the BoundArg and the Cells.

        :param which: Can be one of "n", "w", "s", "e".
        :param arg: The BoundArg that is used to determine the limit.
        :param cells: The Cells used to calculate the limit.
        """
        setattr(self, which, get_limit_from_cells(cells, arg))

    def __repr__(self) -> str:
        cls_name = self.__class__.__name__
        fmt = "{: >7.2f}"
        n = fmt.format(self.n) if self.n is not None else "None"
        w = fmt.format(self.w) if self.w is not None else "None"
        s = fmt.format(self.s) if self.s is not None else "None"
        e = fmt.format(self.e) if self.e is not None else "None"
        return f"{cls_name}(n={n}, w={w}, s={s}, e={e})"

class WBounds(Bounds):
    """ The western outer bounds of a Table. Used when expanding a Table. """
    d = W

    @classmethod
    def from_bboxes(cls, bboxes: list[BBox], **_) -> WBounds:
        n = BoundArg(min, N)
        s = BoundArg(max, S)
        # We use the opposite Direction here, because we want the outer Bounds.
        e = BoundArg(min, E.opposite)
        return super().from_bboxes(bboxes, n=n, s=s, e=e)

    def update_missing_bound(self, cells: list[C]) -> None:
        """ Add the missing bound (western) based on the given Cells. """
        args: BoundArg = BoundArg(max, W)
        self._update_single_limit("w", args, cells)

class EBounds(Bounds):
    """ The eastern outer bounds of a Table. Used when expanding a Table. """
    d = E

    @classmethod
    def from_bboxes(cls, bboxes: list[BBox], **_) -> EBounds:
        n = BoundArg(min, N)
        s = BoundArg(max, S)
        # We use the opposite Direction here, because we want the outer Bounds.
        w = BoundArg(max, W.opposite)
        return super().from_bboxes(bboxes, n=n, w=w, s=s)

    def update_missing_bound(self, cells: list[C]) -> None:
        """ Add the missing bound (eastern) based on the given ells. """
        args: BoundArg = BoundArg(min, E)
        self._update_single_limit("e", args, cells)

class NBounds(Bounds):
    """ The northern outer bounds of a Table. Used when expanding a Table. """
    d = N

    @classmethod
    def from_bboxes(cls, bboxes: list[BBox], **_) -> NBounds:
        w = BoundArg(min, W)
        # We use the opposite Direction here, because we want the outer Bounds.
        s = BoundArg(min, S.opposite)
        e = BoundArg(max, E)
        return super().from_bboxes(bboxes, w=w, s=s, e=e)

    def update_missing_bound(self, cells: list[C]) -> None:
        """ Add the missing bound (northern) based on the given Cells. """
        args: BoundArg = BoundArg(max, N)
        self._update_single_limit("n", args, cells)

class SBounds(Bounds):
    """ The southern outer bounds of a Table. Used when expanding a Table. """
    d = S

    @classmethod
    def from_bboxes(cls, bboxes: list[BBox], **_) -> SBounds:
        # We use the opposite Direction here, because we want the outer Bounds.
        n = BoundArg(max, N.opposite)
        w = BoundArg(min, W)
        e = BoundArg(max, E)
        return super().from_bboxes(bboxes, n=n, w=w, e=e)

    def update_missing_bound(self, cells: list[C]) -> None:
        """ Add the missing bound (southern) based on the given Cells. """
        args: BoundArg = BoundArg(min, S)
        self._update_single_limit("s", args, cells)

def get_limit_from_cells(objects: list[C] | list[BBox], arg: BoundArg | None
                         ) -> float | None:
    """ Calculate a limit from the Cells using the provided func and attr.

    :param objects: The Cells/BBoxes used to calculate the limit.
    :param arg: The BoundArg used to determine the limit.
    :return: The limit of the Cells, based on the given func and d.
    """
    if not objects or not arg:
        return None

    prefix = "bbox." if hasattr(objects[0], "bbox") else ""
    getter = attrgetter(prefix + arg.direction.coordinate)

    # Get the Cell/BBox that has the highest/lowest value for c.
    limit = arg.func(objects, key=getter)
    # Get the actual value.
    return cast(float, getter(limit))

def select_adjacent_cells(d: Direction, bboxes: list[BBox], cells: Cs) -> Cs:
    """ Get all Cells adjacent in d to the given reference Cells.

    :param d: The Direction to check for adjacency in.
    :param bboxes: The BBoxes used to check for adjacency.
    :param cells: The Cells that are checked for adjacency.
    :return: The Cells that are adjacent to ref_cells.
    """
    bound_cls = {N: NBounds, W: WBounds, S: SBounds, E: EBounds}[d]

    adjacent_cells: Cs = bound_cls.select_adjacent_cells(bboxes, cells)

    normal = d.o.normal
    # Remove Cells that are not overlapping with any reference Cell.
    starter_id = 0
    for adj_cell in adjacent_cells:
        for i, bbox in enumerate(bboxes[starter_id:], starter_id):
            if adj_cell.bbox.is_overlap(normal.name, bbox):
                break
        else:
            adjacent_cells.remove(adj_cell)
            break
        starter_id = i
    return adjacent_cells


import pygame, humans, sys, menu
from random import randint

scan_delay = 300
coll_delay = 300
move_delay = 300

menu.valmynd()
skra = open("settings/exit.txt", "r")
for line in skra:
    if line == "True":
        sys.exit()
skra.close()
settings = (open("settings/settings.txt", "r").read()).split()

fps = int(settings[2])

pygame.init()
student_list = []
for stud_num in range(200):
    student_list.append(humans.student(randint(0,800), randint(0,800), randint(1,10), stud_num))

school = pygame.display.set_mode((800, 800))
school.fill((255,255,255))
while 1:#gameplay loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()
    target =randint(0,len(student_list) - 1)
    school.fill((255, 255, 255))
    for student in student_list:
        school.blit(student.image,student.rect)
        if scan_delay >= 10:
            student.scan_surroundings(student_list)
        if move_delay >= 10:
            student.move(student.moveto(student.find_friend()))
        else:
            student.move(student.move_angle)
        student.check_collide(student_list)
    if scan_delay >= 10:
        scan_delay = 0
    else:
        scan_delay += 1
    if move_delay >= 10:
        move_delay = 0
    else:
        move_delay += 1
    if coll_delay >= 1:
        coll_delay = 0
    else:
        coll_delay += 1
    pygame.display.flip()
    pygame.time.Clock().tick(fps)


import numpy as np
import pandas as pd
import logging

logging.getLogger(__name__).addHandler(logging.NullHandler())
logger = logging.getLogger(__name__)

try:
    from sklearn.base import TransformerMixin, BaseEstimator
except ImportError:
    msg = "scikit-learn not installed"
    logger.warning(msg)

try:
    from fancyimpute import IterativeImputer, SoftImpute
except ImportError:
    msg = "fancyimpute not installed"
    logger.warning(msg)

class MultipleImputer(BaseEstimator, TransformerMixin):
    """
    Multiple Imputation via fancyimpute.IterativeImputer.
    """

    def __init__(self, multiple=5, n_iter=10, groupby=None, *args, **kwargs):
        self.multiple = multiple
        self.n_iter = n_iter
        self.args = args
        self.kwargs = kwargs
        self.groupby = groupby

    def transform(self, X, *args, **kwargs):
        assert isinstance(X, pd.DataFrame)
        df = pd.DataFrame(columns=X.columns, index=X.index)
        if isinstance(self.imputers, dict):
            for c, d in self.imputers.items():
                mask = d["mask"]
                imputers = d["impute"]
                imputed_data = np.array([imp.transform(X[mask, :]) for imp in imputers])
                mean = np.mean(imputed_data, axis=0)
                df.loc[mask, ~pd.isnull(X[mask, :]).all(axis=0)] = mean
            return df
        else:
            imputed_data = np.array([imp.transform(X) for imp in self.imputers])
            mean = np.mean(imputed_data, axis=0)
            df.loc[:, ~pd.isnull(X).all(axis=0)] = mean
            return df

    """
    def inverse_transform(self, Y, *args, **kwargs):
        # For non-compositional data, take the mask and reverting to nan
        # for compositional data, renormalisation would be needed
        pass
    """

    def fit(self, X, y=None):
        assert isinstance(X, pd.DataFrame)
        start = X
        y_present = y is not None
        groupby_present = self.groupby is not None
        self.imputers = []
        if y_present or groupby_present:
            assert not (groupby_present and y_present)
            if y_present:
                classes = np.unique(y)
                gen_mask = lambda c: y == c
            if groupby_present:
                classes = X[self.groupby].unique()
                gen_mask = lambda c: X[self.groupby] == c
            self.imputers = {
                c: {
                    "impute": [
                        IterativeImputer(
                            n_iter=self.n_iter,
                            sample_posterior=True,
                            random_state=ix,
                            **self.kwargs
                        )
                        for ix in range(self.multiple)
                    ],
                    "mask": gen_mask(c),
                }
                for c in classes
            }

            msg = """Imputation transformer: {} imputers x {} classes""".format(
                self.multiple, len(classes)
            )
            logger.info(msg)

            for c, d in self.imputers.items():
                for imp in d["impute"]:
                    imp.fit(X[d["mask"], :])

        else:
            for ix in range(self.multiple):
                self.imputers.append(
                    IterativeImputer(
                        n_iter=self.n_iter,
                        sample_posterior=True,
                        random_state=ix,
                        **self.kwargs
                    )
                )
            msg = """Imputation transformer: {} imputers""".format(self.multiple)
            logger.info(msg)
            for ix in range(self.multiple):
                self.imputers[ix].fit(X)

        return self

class PdSoftImputer(BaseEstimator, TransformerMixin):
    """
    Multiple Imputation via fancyimpute.SoftImpute.
    """

    def __init__(self, max_iters=100, groupby=None, donotimpute=[], *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        self.max_iters = max_iters
        self.groupby = groupby
        self.donotimpute = donotimpute

    def transform(self, X, *args, **kwargs):
        """
        Impute Missing Values

        Todo
        ------
            * Need to use masks to avoid :class:`fancyimpute.SoftImpute` returning 0. where it cannot impute.
        """
        assert isinstance(X, pd.DataFrame)
        df = pd.DataFrame(columns=X.columns, index=X.index)  # df of nans
        df.loc[:, self.donotimpute] = X.loc[:, self.donotimpute]
        to_impute = [i for i in X.columns if not i in self.donotimpute]
        imputable = ~pd.isnull(X.loc[:, to_impute]).all(axis=1)
        if isinstance(self.imputer, dict):
            for c, d in self.imputer.items():
                mask = d["mask"]
                mask = mask & imputable
                imputer = d["impute"]
                imputed_data = imputer.fit_transform(X.loc[mask, to_impute])
                assert imputed_data.shape[0] == X.loc[mask, :].index.size
                df.loc[mask, to_impute] = imputed_data

            return df
        else:
            imputed_data = self.imputer.fit_transform(X.loc[imputable, to_impute])
            assert imputed_data.shape[0] == X.loc[imputable, :].index.size
            df.loc[imputable, to_impute] = imputed_data
            return df

    """
    def inverse_transform(self, Y, *args, **kwargs):
        # For non-compositional data, take the mask and reverting to nan
        # for compositional data, renormalisation would be needed
        pass
    """

    def fit(self, X, y=None):
        assert isinstance(X, pd.DataFrame)
        start = X
        y_present = y is not None
        groupby_present = self.groupby is not None
        self.imputer = []
        if y_present or groupby_present:
            assert not (groupby_present and y_present)
            if y_present:
                classes = np.unique(y)
                gen_mask = lambda c: y == c
            if groupby_present:
                classes = X[self.groupby].unique()
                gen_mask = lambda c: X[self.groupby] == c
            self.imputer = {
                c: {
                    "impute": SoftImpute(max_iters=self.max_iters, **self.kwargs),
                    "mask": gen_mask(c),
                }
                for c in classes
            }

            msg = """Building Soft Imputation Transformers for {} classes""".format(
                len(classes)
            )
            logger.info(msg)

        else:
            self.imputer = SoftImpute(max_iters=self.max_iters, **self.kwargs)
            msg = """Building Soft Imputation Transformer"""
            logger.info(msg)

        return self


"""
Signal characteristics animation
"""

import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib import gridspec
matplotlib.use('TkAgg')

class sigCharacterAnimation:
    '''
    Animation for signal characteristics
    '''
    # signal attributes
    am1, am2 = None, None           # signal amplitude, should <=1
    f1, f2 = None, None             # signal frequency, should >=1, multiple of 1
    phase1, phase2 = None, None     # signal phase, [0, 2pi)
    t = None
    sin1, cos1 = None, None         # signal 1
    sin2, cos2 = None, None         # signal 2
    # animation attributes
    fig, axes = None, None
    lines, point = None, None
    frames = None
    transFigure = None

    def __init__(self, signal1=None, signal2=None):
        if signal1 is None:
            signal1 = [1, 1, 0]
        if signal2 is None:
            signal2 = [1, 2, np.pi / 2]
        self.am1, self.am2 = signal1[0], signal2[0]
        self.f1, self.f2 = signal1[1], signal2[1]
        self.phase1, self.phase2 = signal1[2], signal2[2]
        # generate signal
        min_freq = min(self.f1, self.f2)
        fs = 64 * min_freq
        self.t = np.arange(0, 1 / min_freq, 1 / fs)
        self.sin1 = self.am1 * np.sin(2 * np.pi * self.f1 * self.t + self.phase1)
        self.cos1 = self.am1 * np.cos(2 * np.pi * self.f1 * self.t + self.phase1)
        self.sin2 = self.am2 * np.sin(2 * np.pi * self.f2 * self.t + self.phase2)
        self.cos2 = self.am2 * np.cos(2 * np.pi * self.f2 * self.t + self.phase2)
        self.frames = len(self.t)

    def start(self, save_gif=False, f_name='correlation'):
        '''start animation or save as gif'''
        self._init_animation()
        anim = FuncAnimation(self.fig, self._animate, frames=self.frames, blit=False,
                             interval=100, init_func=self._init_canvas)
        if save_gif:
            if not os.path.exists('vis'):
                os.makedirs('vis')
            anim.save(os.path.join('vis', f_name + '.gif'), codec='png', writer='imagemagick')
        else:
            plt.show()

    def _init_animation(self):
        ''' initialize animation'''

        self.fig = plt.figure(figsize=(8, 6))
        self.axes = [matplotlib.axes.Axes] * 4
        gs = gridspec.GridSpec(2, 2, width_ratios=[1, 2])
        self.axes[0] = plt.subplot(gs[0, 0], aspect='equal')
        self.axes[1] = plt.subplot(gs[0, 1])
        self.axes[2] = plt.subplot(gs[1, 0], aspect='equal')
        self.axes[3] = plt.subplot(gs[1, 1])

        self.lines = [matplotlib.axes.Axes.plot] * 4
        self.points = [matplotlib.axes.Axes.plot] * 4
        self.connect = [matplotlib.lines.Line2D] * 2
        circ1 = plt.Circle((0, 0), self.am1, fill=False, linewidth=2, color='orange')
        circ2 = plt.Circle((0, 0), self.am2, fill=False, linewidth=2, color='green')
        self.axes[0].add_artist(circ1)
        self.axes[0].set_xlim(-1.1, 1.1)
        self.axes[0].set_ylim(-1.1, 1.1)
        self.axes[0].axis('off')
        self.axes[1].set_xlim(-0.1, 1)
        self.axes[1].set_ylim(-1.1, 1.1)
        self.axes[1].axis('off')
        self.axes[2].add_artist(circ2)
        self.axes[2].set_xlim(-1.1, 1.1)
        self.axes[2].set_ylim(-1.1, 1.1)
        self.axes[2].axis('off')
        self.axes[3].set_xlim(-0.1, 1)
        self.axes[3].set_ylim(-1.1, 1.1)
        self.axes[3].axis('off')

        self.lines[0], = self.axes[0].plot([], [], linewidth=2)
        self.lines[1], = self.axes[1].plot([], [], linewidth=2, color='orange')
        self.lines[2], = self.axes[2].plot([], [], linewidth=2)
        self.lines[3], = self.axes[3].plot([], [], linewidth=2, color='green')
        self.points[0], = self.axes[0].plot([], [], 'ro', markersize=6)
        self.points[1], = self.axes[1].plot([], [], 'ro', markersize=6)
        self.points[2], = self.axes[2].plot([], [], 'ro', markersize=6)
        self.points[3], = self.axes[3].plot([], [], 'ro', markersize=6)
        self.connect[0] = matplotlib.lines.Line2D([], [], color='r', transform=self.fig.transFigure)
        self.connect[1] = matplotlib.lines.Line2D([], [], color='r', transform=self.fig.transFigure)
        self.fig.lines.extend(self.connect)
        self.transFigure = self.fig.transFigure.inverted()

    def _init_canvas(self):
        '''do nothing, return artists to be re-drawn'''
        return self.lines + self.points + self.connect

    def _animate(self, i):
        '''perform animation step'''
        # update artists
        self.lines[0].set_data([0, self.cos1[-i]], [0, self.sin1[-i]])
        self.lines[1].set_data(self.t, np.roll(self.sin1, i))
        self.lines[2].set_data([0, self.cos2[-i]], [0, self.sin2[-i]])
        self.lines[3].set_data(self.t, np.roll(self.sin2, i))
        self.points[0].set_data([self.cos1[-i]], [self.sin1[-i]])
        self.points[1].set_data([0], [self.sin1[-i]])
        self.points[2].set_data([self.cos2[-i]], [self.sin2[-i]])
        self.points[3].set_data([0], [self.sin2[-i]])

        coord1 = self.transFigure.transform(self.axes[0].transData.transform([self.cos1[-i], self.sin1[-i]]))
        coord2 = self.transFigure.transform(self.axes[1].transData.transform([0, self.sin1[-i]]))
        self.connect[0].set_data((coord1[0], coord2[0]), (coord1[1], coord2[1]))
        coord1 = self.transFigure.transform(self.axes[2].transData.transform([self.cos2[-i], self.sin2[-i]]))
        coord2 = self.transFigure.transform(self.axes[3].transData.transform([0, self.sin2[-i]]))
        self.connect[1].set_data((coord1[0], coord2[0]), (coord1[1], coord2[1]))
        return self.lines + self.points + self.connect

if __name__ == '__main__':

    save_fig = True
    # amplitude
    # anim = sigCharacterAnimation(signal1=[1, 1, 0], signal2=[0.5, 1, 0])
    # anim.start(save_gif=save_fig, f_name='sig_char_amplitude')

    # # frequency
    # anim = sigCharacterAnimation(signal1=[1, 1, 0], signal2=[1, 2, 0])
    # anim.start(save_gif=save_fig, f_name='sig_char_frequency')

    # phase
    anim = sigCharacterAnimation(signal1=[1, 1, 0], signal2=[1, 1, np.pi / 2])
    anim.start(save_gif=save_fig, f_name='sig_char_phase')