#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 17 12:50:49 2019

@author: louisrobinson
"""

import numpy as np

class TransportationTask:
	def __init__(self):
		'''
		origin is (0,0) in the bottom left
		(5, 0) is the top left, (0, 6) is the bottom right, (1,0) is up etc.
		grasping is 0,1,2 for each agent- indicating free, grasping-left, grasping-right
		state is the coords of the agent
		'''
		self.start_state = ((0,0), 0, (0,4), 0)
		self.r, self.c = 6, 7# rows, columns
		self.onBoard = lambda r, c: r >= 0 and r < self.r and c >= 0 and c < self.c
		self.walls = [(1, i) for i in [0,1,3,4,5,6]] + [(4,3),(0,6)]
		self.ind_actions = [(0,0),(0,1),(1,0),(0,-1),(-1,0)]
		self.all_actions = [(a, b) for a in self.ind_actions for b in self.ind_actions]

		# just because my other environment had this function
		self.valid_actions = lambda state: self.all_actions

		self.reset_state()

	def reset_state(self):
		self.state = self.start_state
		self.object = (3,3)
		return self.state

	def goal_check(self, state):
		return self.object in [(5,2),(5,3),(5,4)]

	def neighbourState(self, pos1, pos2):
		(r, c) = pos1
		neighbours1 = [(r+1, c), (r-1, c), (r, c+1), (r, c-1)]
		return pos2 in neighbours1

	# def oppositeActionRC(self, a1, a2, p1, p2):
	# 	(r1, c1), (r2, c2) = p1, p2
	# 	columnNeighbours = c1==c2+1 or c1==c2-1

	# 	(dr1, dc1), (dr2, dc2) = a1, a2

	# 	if columnNeighbours and

	# 	return (0,0)==(dr1+dr2, dc1+dc2)

	def graspable(self, pos):
		(r, c) = self.object
		r_l = {(r, c-1):1, (r, c+1):2}
		if pos in r_l:# left and right of object
			return r_l[pos]
		else:
			return 0

	def ind_step(self, pos, gr, action):
		''' ignores the other agent '''
		(r, c)   = pos
		(dr, dc) = action
		nr, nc = r+dr, c+dc
		if not self.onBoard(nr, nc):
			return pos, gr
		if (nr, nc) in self.walls or (nr, nc)==self.object:
			return pos, gr
		if gr==0:
			gr = self.graspable((nr, nc))
		return (nr, nc), gr

	def pushable(self, pos1, pos2, action):
		(ro, co) = self.object
		(r1, c1), (r2, c2) = pos1, pos2
		(dr, dc) = action
		nr1, nc1, nr2, nc2 = r1+dr, c1+dc, r2+dr, c2+dc
		nro, nco = ro+dr, co+dc
		if self.onBoard(nr1, nc1) and self.onBoard(nr2, nc2) and (nr1, nc1) not in self.walls and (nr2, nc2) not in self.walls and (nro, nco) not in self.walls:
			return True
		return False

	def ind_step_oneAgentConnected(self, pos, gr, act, otherPos):
		# BUT MUST ACCOUNT FOR THE OTHER AGENT AS AN OBSTACLE
		(r, c)   = pos
		(dr, dc) = act
		nr, nc = r+dr, c+dc
		if not self.onBoard(nr, nc) or (nr, nc)==otherPos:
			return pos, gr
		if (nr, nc) in self.walls or (nr, nc)==self.object:
			return pos, gr
		if gr==0:
			gr = self.graspable((nr, nc))
		return (nr, nc), gr

	def step(self, state, action, searchingPolicy=False):
		prevObj = self.object

		(pos1, gr1, pos2, gr2) = state
		(act1, act2) = action

		reward = 0
		if gr1 == 0 and gr2 == 0:# neither are holding on
			npos1, gr1 = self.ind_step(pos1, gr1, act1)
			npos2, gr2 = self.ind_step(pos2, gr2, act2)

			# print('----')
			# print((pos1, gr1, act1, npos1, gr1))
			# print((pos2, gr2, act2, npos2, gr2))
			# print('======')

			if gr1 in [1, 2] or gr2 in [1, 2]:
				if gr1 in [1, 2] and gr2 in [1, 2]:
					reward = 2
				else:
					reward = 1

			# agent 1 moves, then agent 2
			# neighbour, and agent1 is moving into agent2, and agent2 is not moving
			if self.neighbourState(pos1, pos2) and npos1==pos2 and npos2==pos2:# neither can move!
				npos1, npos2 = pos1, pos2
			elif npos1==npos2:# check they are not going into the same place
				npos1, npos2 = pos1, pos2

			# # agent 1 moves, then agent 2
			# if self.neighbourState(pos1, pos2):
			# 	if npos1==pos2:
			# 		if npos2==pos2:# neither can move!
			# 			npos1, npos2 = pos1, pos2
			# 	else:# both can move

			# 	if (act1==act2 or self.oppositeActionRC(act1, act2, pos1, pos2)):
			# 	print('=>')
			# 	if act1==act2:# same move
			# 		if npos1==pos1 or npos2==pos2:# obstacles for either
			# 			npos1, npos2 = pos1, pos2
			# 	else:# oppositeMove, can't move!
			# 		npos1, npos2 = pos1, pos2
			# else:
			# 	print('->')
			# 	if npos1 != pos2 and npos2 == npos1:
			# 		npos2 = pos2# move 1 valid, move 2 is invalid
			# 	if npos1 == pos2:
			# 		npos1 = pos1# move 1 is invalid
			# 		if npos2 == pos1:
			# 			npos2 = pos2# move 2 is also invalid

			# # agent 1 moves, then agent 2
			# if self.neighbourState(pos1, pos2) and (act1==act2 or self.oppositeActionRC(act1, act2, pos1, pos2)):
			# 	print('=>')
			# 	if act1==act2:# same move
			# 		if npos1==pos1 or npos2==pos2:# obstacles for either
			# 			npos1, npos2 = pos1, pos2
			# 	else:# oppositeMove, can't move!
			# 		npos1, npos2 = pos1, pos2
			# else:
			# 	print('->')
			# 	if npos1 != pos2 and npos2 == npos1:
			# 		npos2 = pos2# move 1 valid, move 2 is invalid
			# 	if npos1 == pos2:
			# 		npos1 = pos1# move 1 is invalid
			# 		if npos2 == pos1:
			# 			npos2 = pos2# move 2 is also invalid
		elif gr1 in [1, 2] and gr2 in [1, 2]:
			if act1==act2 and self.pushable(pos1, pos2, act1):
				# if nothing is in the way both agents, and the object can move
				(ro, co) = self.object
				(dr, dc) = act1
				self.object = (ro+dr, co+dc)

				(r1, c1), (r2, c2) = pos1, pos2
				npos1, npos2 = (r1+dr, c1+dc), (r2+dr, c2+dc)
			else:
				npos1, npos2 = pos1, pos2
		elif gr1 in [1, 2]:
			npos1 = pos1 # agent1 can't move
			# agent2 may be able to
			npos2, gr2 = self.ind_step_oneAgentConnected(pos2, gr2, act2, pos1)
			if gr2 in [1, 2]:
				reward = 1
		else:# gr2
			npos2 = pos2 # agent2 can't move
			# agent1 may be able to
			npos1, gr1 = self.ind_step_oneAgentConnected(pos1, gr1, act1, pos2)
			if gr1 in [1, 2]:
				reward = 1
		self.state = (npos1, gr1, npos2, gr2)

		if self.goal_check(self.state):
			if searchingPolicy:
			# if we don't want the hidden state (of the object) to change
				self.object = prevObj

			return self.state, 10, True

		if searchingPolicy:
			self.object = prevObj

		return self.state, reward, False

##################################
# gym/AC Wrapper

class TransportationEnv():
    def __init__(self):
        self.ev = TransportationTask()
        self.action_dim = len(self.ev.all_actions)# dr_i, dc_i, i in 1,2,3
        self.state_dim  = 6# r_i, c_i, i in 1,2,3
        self.state = self.reset()

        self.render_count = 0

    def reset(self):
        self.state = self.ev.reset_state()
        return self.convert_state(self.state)

    def render(self, dpi=80):
        record(self.render_count, 'Transportation task', 'x', self.state, self.ev.object, self.ev, dpi=dpi)
        self.render_count += 1

    def close(self):
        return

    def convert_state(self, s):
        ((r1, c1), gr1, (r2, c2), gr2) = s
        return np.array([r1, c1, gr1, r2, c2, gr2])

    def step(self, a):
        # convert action from np to tuple
        action = self.ev.all_actions[a]#((a[0],a[1]), (a[2],a[3]), (a[4],a[5]))
        next_state, reward, done = self.ev.step(self.state, action)
        self.state = next_state
        # convert state back from tuple to np
        next_state = self.convert_state(next_state)
        return next_state, reward, done, None

    def output_GIF(self):
        makeGIF('../plots/temp-plots/temp-plots1', '../plots/ActorCriticTransportationTaskGIF')

# env = TransportationTask()
# state = ((2, 2), 0, (1, 2), 0)
# print( (state, env.object) )
# (state, reward, ended) = env.step( state, ((0,-1), (1,0)) )
# print( (state, reward, ended, env.object) )
# (state, reward, ended) = env.step( state, ((-1,0), (1,0)) )
# print( (state, reward, ended, env.object) )
# (state, reward, ended) = env.step( state, ((1,0), (0,0)) )
# print( (state, reward, ended, env.object) )
# (state, reward, ended) = env.step( state, ((-1,0), (0,0)) )
# print( (state, reward, ended, env.object) )

import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator
from matplotlib.ticker import FixedLocator
from pylab import fill
import imageio
import os
import shutil

def makeGIF(plotroot, filename, interval=0.1, end_pause=12):
    # Set the directory you want to start from
    rootDir = './'+plotroot+'/'
    files={}
    for dirName, subdirList, fileList in os.walk(rootDir):
        for f in fileList:
            if f[0]=='V':
                iteration = f[1:-4]
                files[int(iteration)] = f
    keys = list(files.keys())
    keys.sort()

    for k in keys:
        path = rootDir+files[k]
        im = imageio.imread(path)
        (h, w, _) = im.shape

    images = []
    for k in keys:
        images.append(imageio.imread(rootDir+files[k]))
    for _ in range(end_pause):
        images.append(imageio.imread(rootDir+files[keys[-1]]))
    kargs = { 'duration': interval }
    imageio.mimsave(filename+'.gif', images, **kargs)

    # delete all of the png files
    shutil.rmtree(rootDir)
    os.mkdir(plotroot)

def printObjectTransportation(agents, obj, grasping, obstacles, goals, r, c, **kwargs):
    fig, ax1 = plt.subplots()

    if 'title' in kwargs: ax1.set_title(kwargs['title'], fontsize=18)
    if 'xax' in kwargs: ax1.set_xlabel(kwargs['xax'], fontsize=15)

    # Shade and label agents
    for i, (sy, sx) in zip([1,2], agents):
        ax1.text(sx+0.3, sy+0.3, '$A_'+str(i)+'$', color="b", fontsize=20)
        fill([sx,sx+1,sx+1,sx], [sy,sy,sy+1,sy+1], 'b', alpha=0.2, edgecolor='b')

    # Shade and label goal cells
    for (gy, gx) in goals:
    	fill([gx,gx+1,gx+1,gx], [gy,gy,gy+1,gy+1], 'g', alpha=0.2, edgecolor='g')
    ax1.text(goals[1][1]-0.3, goals[1][0]+0.4, 'Home base', color="g", fontsize=15)

    # Make obstacles:
    for (y, x) in obstacles:
        fill([x,x+1,x+1,x], [y,y,y+1,y+1], 'k', alpha=0.2, edgecolor='k')

    # make object
    [y, x] = obj
    ax1.text(x+0.05, y+0.37, 'Object', color="k", fontsize=14)
    fill([x,x+1,x+1,x], [y+0.3,y+0.3,y+0.7,y+0.7], 'r', alpha=0.5, edgecolor='k')

    # make grid lines on center
    plt.xticks([0.5+i for i in range(c)], [i for i in range(c)])
    plt.yticks([0.5+i for i in range(r)], [i for i in range(r)])
    plt.xlim(0,c)
    plt.ylim(0,r)

    # make grid
    minor_locator1 = AutoMinorLocator(2)
    minor_locator2 = FixedLocator([j for j in range(r)])
    plt.gca().xaxis.set_minor_locator(minor_locator1)
    plt.gca().yaxis.set_minor_locator(minor_locator2)
    plt.grid(which='minor')

    if 'filename' in kwargs:
        plt.savefig(kwargs['filename'], dpi=kwargs['dpi'])
    plt.close(fig)

def record(iteration, tt, xax, state, obj, env, up=True, dpi=80):
    agents, grasping = [state[0], state[2]], [state[1], state[3]]
    goals = [(5,2),(5,3),(5,4)]
    fn = "plots/temp-plots/temp-plots1/V"+str(iteration)+".png"
    if up: fn = "../"+fn
    printObjectTransportation(agents, obj, grasping, env.walls, goals, env.r, env.c,
    	show=False, filename=fn, title=tt+str(iteration), cbarlbl="Value", xax=xax, dpi=dpi)


from astropy.io import fits  # type: ignore
from dataclasses import dataclass, field
import matplotlib.pyplot as plt  # type: ignore
import numpy as np
from pathlib import Path
from pyuvdata import uvbeam  # type: ignore
from typing import Any, Optional
import warnings

from .coordinates import sph2cart, cart2sph

def mk_linspace(low: float, high: float, step: Any = 1) -> np.ndarray:
    """
    Make a linspace given low, high, step. This avoids the stability
    issues in np.arange(low, high, step) when low >> step (see numpy doc).
    If high is not a multiple of steps away from low, a warning will be raised.
    """
    if not np.isclose((high - low) // step, (high - low) / step, atol=1e-4):
        warnings.warn(
            "'high' is not a multiple of 'step' away from 'low',\
                'step' will be changed.",
            UserWarning,
        )
    num = int((high - low) // step + 1)
    return np.linspace(low, high, num=num)

def Efield_to_power(efield: np.ndarray, axis: int = 3) -> np.ndarray:
    """
    axis: the axis representing the x,yz-components. To be summed over.

    returns beam in V
    """

    return np.sqrt(np.sum(np.abs(efield) ** 2, axis=axis))

@dataclass
class Beam:
    fname: str
    beam_coords: str = "cartesian"
    E_field: np.ndarray = field(init=False)
    power: np.ndarray = field(init=False)
    frequencies: np.ndarray = field(init=False)
    theta: np.ndarray = field(init=False)
    phi: np.ndarray = field(init=False)

    def __post_init__(self):
        simfits = fits.open(self.fname)
        header = simfits[0].header
        self.E_field = simfits[0].data + 1j * simfits[1].data  # nu, th, ph
        simfits.close()
        self.E_field /= 1e3  # convert mV to V
        self.frequencies = mk_linspace(
            header["freq_start"], header["freq_end"], step=header["freq_step"]
        )  # in MHz
        self.theta = mk_linspace(
            header["theta_start"],
            header["theta_end"],
            step=header["theta_step"],
        )
        self.phi = mk_linspace(
            header["phi_start"], header["phi_end"], step=header["phi_step"]
        )
        if np.allclose(self.E_field[:, :, 0], self.E_field[:, :, -1]):
            assert np.isclose(self.phi[-1] - self.phi[0], 360)
            self.E_field = self.E_field[:, :, :-1]  # drop phi = 360 deg
            self.phi = self.phi[:-1]
        self.power = Efield_to_power(self.E_field, axis=3)

    def plot_power(self, freq: float):
        freq_idx = np.argmin(np.abs(self.frequencies - freq))
        plt.figure()
        plt.imshow(
            self.power[freq_idx],
            interpolation="none",
            aspect="auto",
            extent=[
                self.phi.min(),
                self.phi.max(),
                self.theta.max(),
                self.theta.min(),
            ],
        )
        plt.colorbar(label="Power [V]")
        plt.title(
            "Power at $\\nu={:.0f}$ MHz".format(self.frequencies[freq_idx])
        )
        plt.xlabel("$\\phi$ [deg]")
        plt.ylabel("$\\theta$ [deg]")
        plt.show()

    def plot_beamcuts(self, phi: float = 0):
        phi_idx = np.argmin(np.abs(self.phi - phi))
        plt.figure()
        plt.imshow(
            self.power[:, :, phi_idx],
            interpolation="none",
            aspect="auto",
            extent=[
                self.theta.min(),
                self.theta.max(),
                self.frequencies.max(),
                self.frequencies.min(),
            ],
        )
        plt.title("Power at $\\phi={:.0f}$ deg".format(self.phi[phi_idx]))
        plt.ylabel("$\\nu$ [MHz]")
        plt.xlabel("$\\theta$ [deg]")
        plt.colorbar(label="Power [V]")
        plt.show()

    def to_sphericals(self):
        if self.beam_coords == "sphericals":
            warnings.warn(
                "E-field is already in spherical coordinates.", UserWarning
            )
        else:  # cartesian coordinates
            E_sph = np.empty_like(self.E_field)
            for i, th in enumerate(np.radians(self.theta)):
                for j, ph in enumerate(np.radians(self.phi)):
                    rot_matrix = cart2sph(th, ph)
                    E_sph[:, i, j] = np.einsum(
                        "ij,fj->fi", rot_matrix, self.E_field[:, i, j]
                    )
            self.E_field = E_sph
            self.beam_coords = "sphericals"

    def to_cartesian(self):
        if self.beam_coords == "cartesian":
            warnings.warn(
                "E-field is already in cartesian coordinates.", UserWarning
            )
        else:  # spherical coordinates
            E_cart = np.empty_like(self.E_field)
            for i, th in enumerate(np.radians(self.theta)):
                for j, ph in enumerate(np.radians(self.phi)):
                    rot_matrix = sph2cart(th, ph)
                    E_cart[:, i, j] = np.einsum(
                        "ij,fj->fi", rot_matrix, self.E_field[:, i, j]
                    )
            self.E_field = E_cart
            self.beam_coords = "cartesian"

    def _flatten(
        self,
        beam_type: str = "power",
        arr: Optional[np.ndarray] = None,
        return_th_ph=True,
    ) -> np.ndarray:
        """
        Convert array with the shape (freq_size, th_size, ph_size) to a
        2d-array of shape (freq_size, th_size*ph_size) where theta increases
        faster than phi
        """
        if arr is None:
            if beam_type == "power":
                arr = np.copy(self.power)
            else:
                raise ValueError("No default array to flatten for E-field.")
        flat_beam = arr.reshape(
            self.frequencies.size, self.theta.size * self.phi.size, order="F"
        )
        flat_theta = np.tile(self.theta, self.phi.size)
        flat_phi = (
            np.tile(self.phi, self.theta.size)
            .reshape(self.phi.size, self.theta.size, order="F")
            .flatten(order="C")
        )
        if return_th_ph:
            return np.array([flat_beam, flat_theta, flat_phi])
        else:
            return flat_beam

    def _write_txt_power(self, path: str = ".", verbose: bool = False) -> str:
        beam2d, th2d, ph2d = self._flatten()
        savepath = path + "/tmp"
        Path(savepath).mkdir()
        if verbose:
            print(f"Saving {len(beam2d)} files to {savepath}")
        for i, freq in enumerate(self.frequencies):
            np.savetxt(
                savepath + f"/{freq}.txt",
                np.column_stack((th2d, ph2d, beam2d[i])),
                header="Theta [deg] Phi [deg] Abs(V) [V] \n\n",
                comments="",
            )
        return savepath

    def _write_txt_Efield(
        self, pol: str = "x", path: str = ".", verbose: bool = False
    ) -> str:
        """
        Save Efield beams in txt file format readable by UVBeam.
        """
        # get x-pol or y-pol. Easiest to convert to cartesian first:
        #  if self.beam_coords == "sphericals":
        #      self.to_cartesian()
        #  if pol == "x":  # XXX: not optimal, should be done on a copy
        #      self.E_field[:, :, :, 1:] = 0  # set Ey and Ez to 0 for x pol
        #  elif pol == "y":
        #      self.E_field[:, :, :, 0] = 0  # Ex = 0
        #      self.E_field[:, :, :, 2] = 0  # Ez = 0
        #  else:
        #      raise ValueError("pol must be 'x' or 'y'")
        self.to_sphericals()
        E_theta = self.E_field[:, :, :, 1]
        E_phi = self.E_field[:, :, :, 2]
        theta_mag = np.abs(E_theta)
        theta_phase = np.degrees(np.angle(E_theta))
        theta_phase = np.where(theta_phase < 0, theta_phase + 360, theta_phase)
        phi_mag = np.abs(E_phi)
        phi_phase = np.degrees(np.angle(E_phi))
        phi_phase = np.where(phi_phase < 0, phi_phase + 360, phi_phase)
        ax_ratio_sq = (
            theta_mag**2 + phi_mag**2 + np.abs(E_theta**2 + E_phi**2)
        )
        ax_ratio_sq /= (
            theta_mag**2 + phi_mag**2 - np.abs(E_theta**2 + E_phi**2)
        )
        ax_ratio = np.sqrt(ax_ratio_sq)
        theta_mag, theta, phi = self._flatten(
            beam_type="E_field", arr=theta_mag
        )
        theta_phase = self._flatten(
            beam_type="E_field", arr=theta_phase, return_th_ph=False
        )
        phi_mag = self._flatten(
            beam_type="E_field", arr=phi_mag, return_th_ph=False
        )
        phi_phase = self._flatten(
            beam_type="E_field", arr=phi_phase, return_th_ph=False
        )
        ax_ratio = self._flatten(
            beam_type="E_field", arr=ax_ratio, return_th_ph=False
        )
        delta = np.radians(theta_phase - phi_phase)
        E_mag = np.sqrt(
            theta_mag**2
            + phi_mag**2
            + 2 * theta_mag * phi_mag * np.cos(delta)
        )
        savepath = path + "/tmp"
        Path(savepath).mkdir()
        if verbose:
            print(f"Saving {len(self.frequencies)} files to {savepath}")
        for i, freq in enumerate(self.frequencies):
            np.savetxt(
                savepath + f"/{freq}.txt",
                np.column_stack(
                    (
                        theta,
                        phi,
                        E_mag[i],
                        theta_mag[i],
                        theta_phase[i],
                        phi_mag[i],
                        phi_phase[i],
                        ax_ratio[i],
                    )
                ),
                fmt="%.7f",
                header=(
                    "Theta [deg] Phi [deg] Abs(V) [V] Abs(Theta) [V]"
                    "Phase(Theta) [deg] Abs(Phi) [V] Phase(Phi) [deg]"
                    "Ax.Ratio []\n\n"
                ),
                comments="",
            )
        return savepath

    @staticmethod
    def _delete_txt(path: str, verbose: bool = False):
        for f in Path(path).iterdir():
            assert f.suffix == ".txt"  # safety
            f.unlink()  # delete file
        if verbose:
            print("Deleting files.")
        Path(path).rmdir()
        if verbose:
            print(f"Remove directory {path}.")

    def to_uvbeam(
        self, beam_type: str = "E_field", verbose: bool = False
    ) -> uvbeam.UVBeam:
        uvb = uvbeam.UVBeam()
        if beam_type == "power":
            if verbose:
                print("Making UVBeam object from power beam.")
            txtpath = self._write_txt_power(verbose=verbose)
            txtfiles = [str(child) for child in Path(txtpath).iterdir()]
            frequencies = [
                1e6 * float(Path(f).name[: -len(".txt")]) for f in txtfiles
            ]
            txtfiles = sorted(
                txtfiles, key=lambda x: frequencies[txtfiles.index(x)]
            )
            frequencies = sorted(frequencies)
            uvb.read_cst_beam(
                filename=txtfiles,
                beam_type="power",
                feed_pol="x",
                rotate_pol=False,
                frequency=frequencies,
                telescope_name="lusee-night",
                feed_name="lusee",
                feed_version="1.0",
                model_name="dipole_180",
                model_version="1.0",
                history="004",
                reference_impedance=50,
            )
            uvb.interpolation_function = "az_za_simple"
            self._delete_txt(txtpath, verbose=verbose)
        elif beam_type == "E_field":
            if verbose:
                print("Making UVBeam object from E-field beam.")
            txtpath = self._write_txt_Efield(pol="x", verbose=verbose)
            txtfiles = [str(child) for child in Path(txtpath).iterdir()]
            frequencies = [
                1e6 * float(Path(f).name[: -len(".txt")]) for f in txtfiles
            ]
            txtfiles = sorted(
                txtfiles, key=lambda x: frequencies[txtfiles.index(x)]
            )
            frequencies = sorted(frequencies)
            uvb.read_cst_beam(
                filename=txtfiles,
                beam_type="efield",
                feed_pol="x",
                rotate_pol=True,  # XXX
                frequency=frequencies,
                telescope_name="lusee-night",
                feed_name="lusee",
                feed_version="1.0",
                model_name="dipole_180",
                model_version="1.0",
                history="004",
                x_orientation="north",  # XXX
                reference_impedance=50,
            )
            uvb.interpolation_function = "az_za_simple"
            self._delete_txt(txtpath, verbose=verbose)
        else:
            raise ValueError("beam_type must be 'power' or 'E_field'")
        return uvb


from __future__ import annotations

import logging
from dataclasses import dataclass
from enum import Enum, unique
from typing import Any, Dict, Final, List, Optional

import av2.geometry.infinity_norm_utils as infinity_norm_utils
import av2.geometry.interpolate as interp_utils
import av2.geometry.polyline_utils as polyline_utils
from av2.map.map_primitives import Polyline
from av2.utils.typing import NDArrayFloat

WPT_INFINITY_NORM_INTERP_NUM: Final[int] = 50

logger = logging.getLogger(__name__)

@unique
class LaneType(str, Enum):
    """Describes the sorts of objects that may use the lane for travel."""

    VEHICLE: str = "VEHICLE"
    BIKE: str = "BIKE"
    BUS: str = "BUS"

@unique
class LaneMarkType(str, Enum):
    """Color and pattern of a painted lane marking, located on either the left or ride side of a lane segment.

    The `NONE` type indicates that lane boundary is not marked by any paint; its extent should be implicitly inferred.
    """

    DASH_SOLID_YELLOW: str = "DASH_SOLID_YELLOW"
    DASH_SOLID_WHITE: str = "DASH_SOLID_WHITE"
    DASHED_WHITE: str = "DASHED_WHITE"
    DASHED_YELLOW: str = "DASHED_YELLOW"
    DOUBLE_SOLID_YELLOW: str = "DOUBLE_SOLID_YELLOW"
    DOUBLE_SOLID_WHITE: str = "DOUBLE_SOLID_WHITE"
    DOUBLE_DASH_YELLOW: str = "DOUBLE_DASH_YELLOW"
    DOUBLE_DASH_WHITE: str = "DOUBLE_DASH_WHITE"
    SOLID_YELLOW: str = "SOLID_YELLOW"
    SOLID_WHITE: str = "SOLID_WHITE"
    SOLID_DASH_WHITE: str = "SOLID_DASH_WHITE"
    SOLID_DASH_YELLOW: str = "SOLID_DASH_YELLOW"
    SOLID_BLUE: str = "SOLID_BLUE"
    NONE: str = "NONE"
    UNKNOWN: str = "UNKNOWN"

@dataclass
class LocalLaneMarking:
    """Information about a lane marking, representing either the left or right boundary of a lane segment.

    Args:
        mark_type: type of marking that represents the lane boundary, e.g. "SOLID_WHITE" or "DASHED_YELLOW".
        src_lane_id: id of lane segment to which this lane marking belongs.
        bound_side: string representing which side of a lane segment this marking represents, i.e. "left" or "right".
        polyline: array of shape (N,3) representing the waypoints of the lane segment's marked boundary.
    """

    mark_type: LaneMarkType
    src_lane_id: int
    bound_side: str
    polyline: NDArrayFloat

@dataclass(frozen=False)
class LaneSegment:
    """Vector representation of a single lane segment within a log-specific Argoverse 2 map.

    Args:
        id: unique identifier for this lane segment (guaranteed to be unique only within this local map).
        is_intersection: boolean value representing whether or not this lane segment lies within an intersection.
        lane_type: designation of which vehicle types may legally utilize this lane for travel.
        right_lane_boundary: 3d polyline representing the right lane boundary.
        left_lane_boundary: 3d polyline representing the right lane boundary
        right_mark_type: type of painted marking found along the right lane boundary.
        left_mark_type: type of painted marking found along the left lane boundary.
        predecessors: unique identifiers of lane segments that are predecessors of this object.
        successors: unique identifiers of lane segments that represent successor of this object.
            Note: this list will be empty if no successors exist.
        right_neighbor_id: unique identifier of the lane segment representing this object's right neighbor.
        left_neighbor_id: unique identifier of the lane segment representing this object's left neighbor.
    """

    id: int
    is_intersection: bool
    lane_type: LaneType
    right_lane_boundary: Polyline
    left_lane_boundary: Polyline
    right_mark_type: LaneMarkType
    left_mark_type: LaneMarkType
    predecessors: List[int]
    successors: List[int]
    right_neighbor_id: Optional[int] = None
    left_neighbor_id: Optional[int] = None

    @classmethod
    def from_dict(cls, json_data: Dict[str, Any]) -> LaneSegment:
        """Convert JSON to a LaneSegment instance."""
        return cls(
            id=json_data["id"],
            lane_type=LaneType(json_data["lane_type"]),
            right_lane_boundary=Polyline.from_json_data(
                json_data["right_lane_boundary"]
            ),
            left_lane_boundary=Polyline.from_json_data(json_data["left_lane_boundary"]),
            right_mark_type=LaneMarkType(json_data["right_lane_mark_type"]),
            left_mark_type=LaneMarkType(json_data["left_lane_mark_type"]),
            right_neighbor_id=json_data["right_neighbor_id"],
            left_neighbor_id=json_data["left_neighbor_id"],
            predecessors=json_data["predecessors"],
            successors=json_data["successors"],
            is_intersection=json_data["is_intersection"],
        )

    @property
    def left_lane_marking(self) -> LocalLaneMarking:
        """Retrieve the left lane marking associated with this lane segment."""
        return LocalLaneMarking(
            mark_type=self.left_mark_type,
            src_lane_id=self.id,
            bound_side="left",
            polyline=self.left_lane_boundary.xyz,
        )

    @property
    def right_lane_marking(self) -> LocalLaneMarking:
        """Retrieve the right lane marking associated with this lane segment."""
        return LocalLaneMarking(
            mark_type=self.right_mark_type,
            src_lane_id=self.id,
            bound_side="right",
            polyline=self.right_lane_boundary.xyz,
        )

    @property
    def polygon_boundary(self) -> NDArrayFloat:
        """Extract coordinates of the polygon formed by the lane segment's left and right boundaries.

        Returns:
            array of shape (N,3).
        """
        return polyline_utils.convert_lane_boundaries_to_polygon(
            self.right_lane_boundary.xyz, self.left_lane_boundary.xyz
        )

    def is_within_l_infinity_norm_radius(
        self, query_center: NDArrayFloat, search_radius_m: float
    ) -> bool:
        """Whether any waypoint of lane boundaries falls within search_radius_m of query center, by l-infinity norm.

        Could have very long segment, with endpoints and all waypoints outside of radius, therefore cannot check just
        its endpoints.

        Args:
            query_center: array of shape (3,) representing 3d coordinates of query center.
            search_radius_m: distance threshold in meters (by infinity norm) to use for search.

        Returns:
            whether the lane segment has any waypoint within search_radius meters of the query center.
        """
        try:
            right_ln_bnd_interp = interp_utils.interp_arc(
                t=WPT_INFINITY_NORM_INTERP_NUM,
                points=self.right_lane_boundary.xyz[:, :2],
            )
            left_ln_bnd_interp = interp_utils.interp_arc(
                t=WPT_INFINITY_NORM_INTERP_NUM,
                points=self.left_lane_boundary.xyz[:, :2],
            )
        except Exception:
            logger.exception("Interpolation failed for lane segment %d", self.id)
            right_ln_bnd_interp = self.right_lane_boundary.xyz[:, :2]
            left_ln_bnd_interp = self.left_lane_boundary.xyz[:, :2]

        left_in_bounds = infinity_norm_utils.has_pts_in_infinity_norm_radius(
            right_ln_bnd_interp, query_center, search_radius_m
        )
        right_in_bounds = infinity_norm_utils.has_pts_in_infinity_norm_radius(
            left_ln_bnd_interp, query_center, search_radius_m
        )
        return left_in_bounds or right_in_bounds


import sys
import os
from typing import List, Any
from tempfile import NamedTemporaryFile
from contextlib import contextmanager

import mutagen.id3
from mutagen.id3 import ID3v1SaveOptions, ID3

from dimensions import dimensions

from .applier import Action, ActionGenerator, EasyID3Tags, prepare

__all__ = [
    'MyTags', 'AllId3TagsActionGenerator', 'DoNothing', 'DeleteTag',
    'DeleteUnacceptableTags', 'FixLyricsAttributes', 'action_list',
]

def recursive_delete_empty_folders(path: str) -> None:
    while len(os.listdir(path)) == 0:
        os.rmdir(path)
        path = os.path.dirname(path)

class MyTags(EasyID3Tags):
    def __init__(self, path) -> None:
        assert os.path.abspath(path) == path
        super().__init__(path)
        self.__original_path = path

    def path(self) -> str:
        return self.__original_path

    def _copy(self) -> Any:
        return self.filename, super()._copy()

    def _restore(self, value: Any) -> None:
        self.filename, id3_value = value
        super()._restore(id3_value)

    @classmethod
    def _diff2(cls, value1: Any, value2: Any) -> List[str]:
        filename1, id3_value1 = value1
        filename2, id3_value2 = value2

        result = []
        if filename1 != filename2:
            result.append("path. %s --> %s" % (prepare(filename1), prepare(filename1)))

        result.extend(super()._diff2(id3_value1, id3_value2))
        return result

    def write(self) -> None:
        assert os.path.abspath(self.filename) == self.filename
        if not os.path.isdir(os.path.dirname(self.filename)):
            os.makedirs(os.path.dirname(self.filename))
        os.rename(self.__original_path, self.filename)
        recursive_delete_empty_folders(os.path.dirname(self.__original_path))
        self.save(v1=ID3v1SaveOptions.CREATE, v2_version=3)

@contextmanager
def temp_input(data):
    temp = NamedTemporaryFile(delete=False)
    temp.write(data)
    temp.close()
    try:
        yield temp.name
    finally:
        os.unlink(temp.name)

def image_info(data: bytes):
    with temp_input(data) as image:
        return dimensions(image)[:3]

def lyrics_get(id3: ID3, key: str) -> List[str]:
    return [id3["USLT::eng"].text]

def lyrics_set(id3: ID3, key: str, value: List[str]) -> None:
    assert len(value) == 1
    id3.add(mutagen.id3.USLT(text=value[0], lang='eng'))

def lyrics_delete(id3: ID3, key: str) -> None:
    del id3["USLT::eng"]

def picture_get(id3: ID3, key: str) -> List[bytes]:
    return [id3["APIC:"].data]

def picture_set(id3: ID3, key: str, value: List[bytes]) -> None:
    assert len(value) == 1
    id3.add(mutagen.id3.APIC(data=value[0], mime=image_info(value[0])[2]))

def picture_delete(id3: ID3, key: str) -> None:
    del id3["APIC:"]

MyTags.RegisterKey("lyrics", lyrics_get, lyrics_set, lyrics_delete)
MyTags.RegisterKey("picture", picture_get, picture_set, picture_delete)

MyTags.RegisterTXXXKey('group', 'GROUP')
MyTags.RegisterTXXXKey('country', 'COUNTRY')
MyTags.RegisterTXXXKey('series', 'SERIES')
MyTags.RegisterTXXXKey('large_series', 'LARGESERIESINDICATOR')
MyTags.RegisterTXXXKey('artist_trans', 'ALBUMTRANSLATION')
MyTags.RegisterTXXXKey('album_trans', 'ALBUMTRANSLATION')
MyTags.RegisterTXXXKey('title_trans', 'TITLETRANSLATION')
MyTags.RegisterTXXXKey('artist_app', 'ALBUMAPPENDIX')
MyTags.RegisterTXXXKey('album_app', 'ALBUMAPPENDIX')
MyTags.RegisterTXXXKey('title_app', 'TITLEAPPENDIX')
MyTags.RegisterTXXXKey('ext_artist', 'EXTENDEDARTIST')
MyTags.RegisterTXXXKey('ext_album', 'EXTENDEDALBUM')
MyTags.RegisterTXXXKey('ext_title', 'EXTENDEDTITLE')
MyTags.RegisterTXXXKey('series_exc', 'SERIESEXCEPTION')
MyTags.RegisterTXXXKey('album_artist_exc', 'ALBUMEARTISTXCEPTION')
MyTags.RegisterTXXXKey('artist_exc', 'ALBUMEXCEPTION')
MyTags.RegisterTXXXKey('album_exc', 'ALBUMEXCEPTION')
MyTags.RegisterTXXXKey('title_exc', 'TITLEEXCEPTION')
MyTags.RegisterTXXXKey('rym_type', 'RYMTYPE')
MyTags.RegisterTXXXKey('rym_album', 'RYMALBUM')
MyTags.RegisterTXXXKey('rym_artist', 'RYMARTIST')
MyTags.RegisterTXXXKey('year_order', 'YEARORDER')
MyTags.RegisterTXXXKey('year_order_digits', 'YEARORDERDIGITS')
MyTags.RegisterTXXXKey('track_digits', 'TRACKDIGITS')
MyTags.RegisterTXXXKey('performer', 'PERFORMER')
MyTags.RegisterTXXXKey('super_genre', 'SUPERGENRE')
MyTags.RegisterTXXXKey('sub_genre', 'SUBGENRE')
MyTags.RegisterTXXXKey('genre_specifier', 'GENRESPECIFIER')
MyTags.RegisterTXXXKey('sec_genres', 'SECONDARYGENRES')

class AllId3TagsActionGenerator(ActionGenerator):
    def generate(self, tags: MyTags) -> List[Action]:
        return [self.of_tag(tag) for tag in tags.get_id3()]

    def of_tag(self, key: str) -> Action:
        raise NotImplementedError()

class DoNothing(Action):
    def apply(self, tags: MyTags) -> None:
        pass

    def key(self) -> str:
        return "DoNothing"

class DeleteTag(Action):
    def __init__(self, id3_tag_key: str) -> None:
        self.id3_tag_key = id3_tag_key

    def apply(self, tags: MyTags) -> None:
        del tags.get_id3()[self.id3_tag_key]

    def key(self) -> str:
        return "DeleteTag %s" % self.id3_tag_key

class CapitulateTXXXTag(Action):
    def __init__(self, txxx_desc: str) -> None:
        self.txxx_desc = txxx_desc

    def apply(self, tags: MyTags) -> None:
        tag_from = 'TXXX:' + self.txxx_desc
        tag_to = 'TXXX:' + self.txxx_desc.upper()
        if tag_from in tags.get_id3() and tag_from != tag_to:
            tags.get_id3()[tag_to] = tags.get_id3()[tag_from]
            tags.get_id3()[tag_to].desc = self.txxx_desc.upper()
            del tags.get_id3()[tag_from]

    def key(self) -> str:
        return "CapitulateTXXXTag %s" % self.txxx_desc

class DeleteUnacceptableTags(AllId3TagsActionGenerator):
    def __init__(self, acceptable_tags: List[str]) -> None:
        self.acceptable_tags = acceptable_tags

    def of_tag(self, key: str) -> Action:
        if key in self.acceptable_tags:
            return DoNothing()
        else:
            return DeleteTag(key)

class CapitulateTXXXTags(AllId3TagsActionGenerator):
    def of_tag(self, key: str) -> Action:
        if key.startswith('TXXX:'):
            return CapitulateTXXXTag(key[5:])
        else:
            return DoNothing()

class FixLyricsAttributes(Action):
    def apply(self, tags: MyTags) -> None:
        lyrics_list = tags.get_id3().getall('USLT')
        if len(lyrics_list) == 0:
            return
        lyrics = max(lyrics_list, key=lambda l: len(l.text)).text
        tags.get_id3().delall('USLT')
        tags['lyrics'] = lyrics

    def key(self) -> str:
        return "FixLyricsAttributes"

class CheckPicture(Action):
    def apply(self, tags: MyTags) -> None:
        if 'APIC:' not in tags.get_id3():
            print("%s has no picture" % prepare(tags.path()))
            return
        picture = tags.get_id3()['APIC:']
        width, height, mime = image_info(picture.data)
        side = min(width, height)
        if mime != 'image/jpeg':
            print("%s has bad picture mime: %s" % (prepare(tags.path()), mime))
        if side != 500:
            print("%s has bad picture size: (%d, %d)" % (prepare(tags.path()), width, height))
        tags.mime = mime

    def key(self) -> str:
        return "CheckPicture"

action_list = [
    CapitulateTXXXTags(),
    FixLyricsAttributes(),
    DeleteUnacceptableTags([
        'APIC:', 'TALB', 'TPE1', 'TPE2', 'TCON', 'TIT2', 'TCOM', 'TDRC', 'TRCK', 'USLT::eng',
        'TXXX:YEARORDER', 'TXXX:YEARORDERDIGITS', 'TXXX:TRACKDIGITS', 'TXXX:PERFORMER',
        'TXXX:GROUP', 'TXXX:LARGESERIESINDICATOR', 'TXXX:SERIES', 'TXXX:COUNTRY',
        'TXXX:SUPERGENRE', 'TXXX:SUBGENRE', 'TXXX:GENRESPECIFIER', 'TXXX:SECONDARYGENRES',
        'TXXX:ALBUMTRANSLATION', 'TXXX:ARTISTTRANSLATION', 'TXXX:TITLETRANSLATION',
        'TXXX:ARTISTAPPENDIX', 'TXXX:ALBUMAPPENDIX', 'TXXX:TITLEAPPENDIX',
        'TXXX:EXTENDEDARTIST', 'TXXX:EXTENDEDALBUM', 'TXXX:EXTENDEDTITLE',
        'TXXX:RYMARTIST', 'TXXX:RYMALBUM', 'TXXX:RYMTYPE',
        'TXXX:SERIESEXCEPTION', 'TXXX:ALBUMARTISTEXCEPTION',
        'TXXX:ALBUMEXCEPTION', 'TXXX:ARTISTEXCEPTION', 'TXXX:TITLEEXCEPTION',
        'TXXX:RYMARTISTEXCEPTION', 'TXXX:RYMALBUMEXCEPTION', 'TXXX:RYMTYPEEXCEPTION',
    ]),
    CheckPicture(),
]


from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import TemplateView
from django.views.generic import ListView
from django.views.generic import DetailView
from .models import Video
from .forms import VideoForm
import random
da1 = [["media/bounty.mp4", "Bounty", "Bucket", "Ballot", "Bleed", "Belief"], ["media/book.mp4", "Book", "Brook", "Block", "BLack", "Broom"], ["media/mice.mp4", "Mice", "Mark", "Meet", "Major", "Man"], ["media/boot.mp4", "Boot", "Beet", "Meet", "Heat", "Beak"], ["media/heat.mp4", "Hoot", "Heat", "Him", "Heat", "Heal"], ["media/pool.mp4",
                                                                                "pool", "pull", "poke", "pain", "peel"], ["media/soap.mp4", "soup", "soap", "soake", "sell", "seat"], ["media/see.mp4", "see", "seep", "sold", "sour", "seek"], ["media/jeep.mp4", "joke", "leap", "jake", "jam", "jeep"], ["media/soup.mp4", "soap", "soake", "sold", "sour", "seek"], ["media/leap.mp4", "jeep", "leap", "lake", "late", "look"]]
questions = random.sample(da1, 4)
questions_result = []
question_num = 0
score = 0

def index(request):
    global questions
    questions = random.sample(da1, 4)
    if request.method == 'GET':
        return render(request, 'index.html', {'data': 1})

def quiz(request):
    global question_num, score, questions_result

    if question_num == 0:
        questions_result = []
        score = 0

    questions_result.append(
        [questions[question_num][0], questions[question_num][0][len("media/"):-4]])

    if request.method == 'GET':
        return render(request, 'quiz.html', {'data': questions[question_num]+[score]})

    elif request.method == 'POST':
        # get variable from post request
        # save to database
        current_answer = questions[question_num][0][len("media/"):-4]
        question_num += 1
        selected_answer = request.POST.get('option').lower()
        if current_answer == selected_answer:
            score += 1

        if question_num == 4:
            question_num = 0
            return render(request, 'result.html', {'data': questions_result+[score]})

        return render(request, 'quiz.html', {'data': questions[question_num]+[score]})


import numpy as np
import os
import pickle
import torch

import slowfast.utils.checkpoint as cu
import slowfast.utils.distributed as du
import slowfast.utils.logging as logging
import slowfast.utils.misc as misc
import slowfast.visualization.tensorboard_vis as tb
from slowfast.datasets import loader
from slowfast.models import build_model
from slowfast.utils.env import pathmgr
from slowfast.utils.meters import AVAMeter, TestMeter, EPICTestMeter

from slowfast.utils.metrics import MT5R
from slowfast.utils.writejson import writetestjson
from slowfast.utils.savescores import savescores

import torch.nn.functional as F
from torchvision.transforms import Compose, Resize, CenterCrop, Normalize, ToTensor

from fvcore.nn import FlopCountAnalysis

from tqdm import tqdm

logger = logging.get_logger(__name__)

from collections import defaultdict
import json

import matplotlib.pyplot as plt

def show_img(img):
    img = np.asarray(img)
    plt.figure(figsize=(10, 10))
    plt.imshow(img)
    plt.axis('off')
    plt.savefig('img_resized.jpg')

def show_img2(img1, img2, alpha=0.8, savedir=None, savename=None):
    img1 = np.asarray(img1)
    img2 = np.asarray(img2)
    plt.figure(figsize=(10, 10))
    plt.imshow(img1)
    plt.imshow(img2, alpha=alpha)
    plt.axis('off')
    savedir = os.path.join('att_maps','mf', savedir)
    if not os.path.exists(savedir):
        os.mkdir(savedir)
    # print(os.path.join(savedir, savename+'.png'))
    plt.savefig(os.path.join(savedir, savename+'.png'), bbox_inches='tight', transparent=True, pad_inches=0)
    plt.close()

def my_forward_wrapper(attn_obj):
    def my_forward(x):
        (B, N, C) = x.shape

        qkv = attn_obj.qkv(x).reshape(B, N, 3, attn_obj.num_heads, C // attn_obj.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv.unbind(0)   # make torchscript happy (cannot use tensor as tuple)

        attn = (q @ k.transpose(-2, -1)) * attn_obj.scale
        attn = attn.softmax(dim=-1)
        attn = attn_obj.attn_drop(attn)
        attn_map = attn
        cls_attn_map = attn[:, :, 0, 1:]

        x = (attn @ v).transpose(1, 2).reshape(B, N, C)
        x = attn_obj.proj(x)
        x = attn_obj.proj_drop(x)
        return x, attn_map, cls_attn_map
    return my_forward

@torch.no_grad()
def perform_viz(test_loader, model, cfg, writer=None):
    """
    For classification:
    Perform mutli-view testing that uniformly samples N clips from a video along
    its temporal axis. For each clip, it takes 3 crops to cover the spatial
    dimension, followed by averaging the softmax scores across all Nx3 views to
    form a video-level prediction. All video predictions are compared to
    ground-truth labels and the final testing performance is logged.
    For detection:
    Perform fully-convolutional testing on the full frames without crop.
    Args:
        test_loader (loader): video testing loader.
        model (model): the pretrained video model to test.
        test_meter (TestMeter): testing meters to log and ensemble the testing
            results.
        cfg (CfgNode): configs. Details can be found in
            slowfast/config/defaults.py
        writer (TensorboardWriter object, optional): TensorboardWriter object
            to writer Tensorboard log.
    """
    # Enable eval mode.
    model.eval()

    for cur_iter, (inputs, labels, video_idx, meta) in tqdm(enumerate(test_loader)):
        if cfg.NUM_GPUS:
            # Transferthe data to the current GPU device.
            inputs, labels, video_idx, meta = misc.iter_to_cuda([inputs, labels, video_idx, meta])

        # Perform the forward pass.
        flops = FlopCountAnalysis(model, (inputs, meta))
        print('Total flops:',flops.total())
        # print(flops.by_module())
        # print(flops.by_module_and_operator())
        preds = model(inputs, meta)
        if isinstance(preds, tuple):
            preds, extra_preds = preds

        if isinstance(labels, (dict,)):
            metadata = meta
            verb_labels, video_idx = labels['verb'], video_idx
            noun_labels, video_idx = labels['noun'], video_idx
            verb_label = verb_labels[0].detach().cpu().item()
            noun_label = noun_labels[0].detach().cpu().item()
            # turn knob = 23,190
            # mix meat = 10,28
            # cut pizza = 7,91
            # dry pan = 14,5
            # remove onion = 12,16
            # remove cover = 12,89
            # crush spice = 49,85
            # take parsley = 0,169
            # close squash = 4,116
            # pour sugar = 9,102
            verb_noun = [(23,190), (10,28), (7,91), (14,5), (12,16), (12,89), (49,85), (0,169), (4,116), (9,102)]
            if  (verb_label, noun_label) in verb_noun:
                feat = model.forward_features(inputs, meta)

                viz_block = my_forward_wrapper(model.blocks[-1].attn)
                y, attn_map, cls_attn_map = viz_block(feat)

                attn_map = attn_map.mean(dim=1).squeeze(0).detach()
                cls_weight = cls_attn_map.mean(dim=1).view(8, 14, 14).detach().cpu()

                for i in range(cls_weight.shape[0]):
                    cls_resized = F.interpolate(cls_weight[i,:,:].view(1, 1, 14, 14), (224, 224), mode='bilinear').view(224, 224, 1)
                    img_resized = inputs[0][0,:,2*i+1,:,:].permute(1, 2, 0) * 0.5 + 0.5
                    show_img2(img_resized.cpu(), cls_resized, alpha=0.6, savedir=metadata['narration_id'][0]+'_'+str(verb_label)+'_'+str(noun_label),
                        savename=str(i))
def visualize(cfg):
    """
    Perform multi-view testing on the pretrained video model.
    Args:
        cfg (CfgNode): configs. Details can be found in
            slowfast/config/defaults.py
    """
    # Set random seed from configs.
    np.random.seed(cfg.RNG_SEED)
    torch.manual_seed(cfg.RNG_SEED)

    # Build the video model and print model statistics.
    model = build_model(cfg)

    cur_epoch = cu.load_test_checkpoint(cfg, model)

    # Create video testing loaders.
    test_loader = loader.construct_loader(cfg, "test")

    # # Perform single-view test on the entire dataset.
    perform_viz(test_loader, model, cfg)

import os
import sys
sys.path = [x for x  in sys.path if not (os.path.isdir(x) and 'slowfast' in os.listdir(x))]
sys.path.append(os.getcwd())

import slowfast
assert slowfast.__file__.startswith(os.getcwd()), f"sys.path: {sys.path}, slowfast.__file__: {slowfast.__file__}"

"""Wrapper to train and test a video classification model."""
from slowfast.config.defaults import assert_and_infer_cfg
from slowfast.utils.misc import launch_job
from slowfast.utils.parser import load_config, parse_args

def main():
    """
    Main function to spawn the train and test process.
    """
    args = parse_args()
    cfg = load_config(args)
    cfg = assert_and_infer_cfg(cfg)

    if cfg.CUDA_VISIBLE_DEVICES:
        os.environ["CUDA_VISIBLE_DEVICES"] = cfg.CUDA_VISIBLE_DEVICES

    visualize(cfg)

if __name__ == "__main__":
    main()


import numpy as np
import sympy as sm
import sys
import strToMatrix

def lagrange(table):
    try:
        table = strToMatrix.strToMatrix(table)
        x_vector = table[0].tolist()
        y_vector = table[1].tolist()
    except:
       print("Error: check type of input values")
       sys.exit(1)
    try:
        results = {}
        #we create the unknown of the equation
        x = sm.symbols('x')
        n = len(x_vector)
        final_equation = []
        polynomial = 0
        for i in range(0,n):
            #numerator of our expression
            num = 1
            #denominator of our expression
            den = 1
            for j in range(0,n):
                if j != i:
                    num = num*(x-x_vector[j])
                    den = den*(x_vector[i]-x_vector[j])
            # Lagrange interpolating polynomials
            try:
                interpolant = num/den
            except:
                print("Error: Division by zero in method execution")
                sys.exit(1)
            interpolant = interpolant.expand()
            results[i] = interpolant
            # here we put each equation
            try:
                equation = num*y_vector[i]/den
            except:
                print("Error: Division by zero in method execution")
                sys.exit(1)
            equation = equation.expand()
            # we add each equation to obtain the final polynomial
            polynomial += equation

        results['polynomial'] = polynomial
        print("Lagrange interpolation polynomials:")
        for i in range(len(results)-1):
            print(f"{results[i]}")
        print("\nPolynomial")
        print(results['polynomial'])
    except:
        print("Error: Initial data error, try again")
        sys.exit(1)

np.set_printoptions(precision=7)
#table = [[-1, 0, 3, 4],[15.5, 3, 8, 1]]
lagrange(sys.argv[1])


from google.cloud import speech_v1p1beta1
from google.cloud import storage
import io
import pandas as pd
import os

def set_env_variable(path):
    '''
    Sets the environment variable GOOGLE_APPLICATION_CREDENTIALS,
    which is required to make API calls to GCP.
    '''
    os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = path

def upload_blob(source_file_name, bucket_name="sample-audio-clips", destination_blob_name="audio/temp-audiofile.wav"):
    """Uploads a file to the bucket."""
    # bucket_name = "your-bucket-name"
    # source_file_name = "local/path/to/file"
    # destination_blob_name = "storage-object-name"

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(destination_blob_name)

    blob.upload_from_filename(source_file_name)

    print(
        "File {} uploaded to {}.".format(
            source_file_name, destination_blob_name
        )
    )
    return blob

def delete_from_gcs(blob):
    blob.delete()
    print("File audio/temp-audiofile.wav removed from Google Cloud Storage bucket.")

def sample_long_running_recognize(num_speakers, storage_uri="gs://sample-audio-clips/audio/temp-audiofile.wav"):
    """
    Print confidence level for individual words in a transcription of a short audio
    file
    Separating different speakers in an audio file recording

    Args:
      storage_uri URI for audio file in Cloud Storage, e.g. gs://[BUCKET]/[FILE]
    """

    client = speech_v1p1beta1.SpeechClient()

    # If enabled, each word in the first alternative of each result will be
    # tagged with a speaker tag to identify the speaker.
    enable_speaker_diarization = True

    # Optional. Specifies the estimated number of speakers in the conversation.
    diarization_speaker_count = num_speakers

    # When enabled, the first result returned by the API will include a list
    # of words and the start and end time offsets (timestamps) for those words.
    enable_word_time_offsets = True

    # The language of the supplied audio
    language_code = "en-US"  # Currently, "video" model is only available on en-US.

    config = {
        "enable_speaker_diarization": enable_speaker_diarization,
        "diarization_speaker_count": diarization_speaker_count,
        "language_code": language_code,
        "model": "video",
        "enable_word_time_offsets": enable_word_time_offsets
    }

    audio = {"uri": storage_uri}

    operation = client.long_running_recognize(config, audio)

    print(u"Waiting for operation to complete...")
    response = operation.result()

    return response

def create_dataframe(response):
    '''
    Processes the response from the Google Speech Cloud model.
    Output: A pandas dataframe.
    '''
    for result in response.results:
        # First alternative has words tagged with speakers
        alternative = result.alternatives[0]
        # print(u"Transcript: {}".format(alternative.transcript))

        # Capture data in pandas data frame
        d = []
        for w in alternative.words:
            d.append(
                {"Start (secs)": w.start_time.seconds,
                 "Start (ns)": w.start_time.nanos,
                 "End (secs)": w.end_time.seconds,
                 "End (ns)": w.end_time.nanos,
                 "Word": w.word,
                 "Speaker": w.speaker_tag})

        df = pd.DataFrame(d)  # Saves the last dataframe in response.results, is this desirable?
    return df


import openpyxl
from openpyxl import *

import googletrans
from googletrans import *

#---------------------------------------------------------

path       = None
excel_file = None
sheet      = None
translator = googletrans.Translator()

#---------------------------------------------------------

def limit_length(message):
    if len(message) == 0:
        return
    elif len(message) > 73:
        return message[0:73]
    else:
        return message

#---------------------------------------------------------

path = input()

excel_file = openpyxl.load_workbook( path )

sheet = excel_file[excel_file.sheetnames[0]]

#---------------------------------------------------------

for generator in sheet.iter_cols(min_col=4, max_col=4, min_row=2):
    for cell in generator:
            try:
                #translate old cell
                text = str(cell.value)
                translated = translator.translate(text, dest='sr', src='de')

                #add new cell
                new_cell = sheet.cell( row=cell.row, column=cell.column+1)
                new_cell.value = limit_length( str(translated.text) )
                print(new_cell.value)
            except:
                #add new cell (blank cell)
                new_cell = sheet.cell( row=cell.row, column=cell.column+1)
                new_cell.value = empty_string = ''

#---------------------------------------------------------

excel_file.save('t100_uebersetzt')


"""
    DSatur algorithm from: https://en.wikipedia.org/wiki/DSatur
"""

import collections

def max_dsat (neighbor_colors, graph):
    """
        Returns the vertex with the highest degree of saturation,
        using the highest degree to break ties.
        Parameters:
            neighbor_colors : dict - A dictionary with a vertex as a key and a set of its
                    neighbors colors
            graph : dict - A graph represented as an adjacency list

    """
    max_val = -1
    max_vertex = None
    for v in graph:
        if len (neighbor_colors[v]) > max_val or (len (neighbor_colors[v]) == max_val and len (graph[v]) > len (graph[max_vertex])):
            max_val = len (neighbor_colors[v])
            max_vertex = v
    return max_vertex

def dsatur (graph, neighbor_colors):
    """
        Implements the DSatur algorithm (greedy) for approximating the min coloring of a graph
        Parameters:
            graph : dict - An subgraph of the graph to be colored represented as an adjacency list,
                    each key is an uncolored vertex in the graph
            neighbor_colors : dict - A dictionary where the keys are vertices and the values
                    are the set of colors in the neighborhood
    """
    colorings = {}
    while (len (graph) > 0):
        u = max_dsat (neighbor_colors, graph)
        i = 0
        while u not in colorings:
            if i not in neighbor_colors[u]:
                colorings[u] = i
            i += 1
        neighbors = graph.pop (u)
        for v in neighbors:
            neighbor_colors[v].add (colorings[u])
    return colorings

def main ():
    n = int (input ())
    graph = {}
    uncolored_graph = {}
    neighbor_colors = {}
    for _ in range (n):
        u, v = input ().split ()
        if u not in graph:
            graph[u] = set ()
            uncolored_graph[u] = set ()
        if v not in graph:
            graph[v] = set ()
            uncolored_graph[v] = set ()
        graph[u].add (v)
        graph[v].add (u)
        uncolored_graph[u].add (v)
        uncolored_graph[v].add (u)
        neighbor_colors[u] = set ()
        neighbor_colors[v] = set ()

    colorings = dsatur (uncolored_graph, neighbor_colors)

    print (max (colorings.values ()))
    sorted_colorings = collections.OrderedDict (sorted (colorings.items ()))
    for v in sorted_colorings:
        print (v + " " + str (colorings[v]))

if __name__ == "__main__":
    main ()


# Licensed under a 3-clause BSD style license - see LICENSE.rst
# -*- coding: utf-8 -*-

import warnings
from distutils.version import LooseVersion

import pytest
import numpy as np

from astropy import __minimum_asdf_version__

asdf = pytest.importorskip('asdf', minversion=__minimum_asdf_version__)
from asdf import util
from asdf.tests import helpers
from asdf import AsdfFile
import asdf

import astropy.units as u
from astropy.modeling.core import fix_inputs
from astropy.modeling import models as astmodels

def custom_and_analytical_inverse():
    p1 = astmodels.Polynomial1D(1)
    p2 = astmodels.Polynomial1D(1)
    p3 = astmodels.Polynomial1D(1)
    p4 = astmodels.Polynomial1D(1)
    m1 = p1 & p2
    m2 = p3 & p4
    m1.inverse = m2
    return m1

test_models = [
    astmodels.Identity(2), astmodels.Polynomial1D(2, c0=1, c1=2, c2=3),
    astmodels.Polynomial2D(1, c0_0=1, c0_1=2, c1_0=3),
    astmodels.Shift(2.),
    astmodels.Hermite1D(2, c0=2, c1=3, c2=0.5),
    astmodels.Legendre1D(2, c0=2, c1=3, c2=0.5),
    astmodels.Chebyshev1D(2, c0=2, c1=3, c2=0.5),
    astmodels.Chebyshev2D(1, 1, c0_0=1, c0_1=2, c1_0=3),
    astmodels.Legendre2D(1, 1, c0_0=1, c0_1=2, c1_0=3),
    astmodels.Hermite2D(1, 1, c0_0=1, c0_1=2, c1_0=3),
    astmodels.Scale(3.4), astmodels.RotateNative2Celestial(5.63, -72.5, 180),
    astmodels.Multiply(3), astmodels.Multiply(10*u.m),
    astmodels.RotateCelestial2Native(5.63, -72.5, 180),
    astmodels.EulerAngleRotation(23, 14, 2.3, axes_order='xzx'),
    astmodels.Mapping((0, 1), n_inputs=3),
    astmodels.Shift(2.*u.deg),
    astmodels.Scale(3.4*u.deg),
    astmodels.RotateNative2Celestial(5.63*u.deg, -72.5*u.deg, 180*u.deg),
    astmodels.RotateCelestial2Native(5.63*u.deg, -72.5*u.deg, 180*u.deg),
    astmodels.RotationSequence3D([1.2, 2.3, 3.4, .3], 'xyzx'),
    astmodels.SphericalRotationSequence([1.2, 2.3, 3.4, .3], 'xyzy'),
    custom_and_analytical_inverse(),
]

math_models = []

for kl in astmodels.math.__all__:
    klass = getattr(astmodels.math, kl)
    math_models.append(klass())

test_models.extend(math_models)

def test_transforms_compound(tmpdir):
    tree = {
        'compound':
            astmodels.Shift(1) & astmodels.Shift(2) |
            astmodels.Sky2Pix_TAN() |
            astmodels.Rotation2D() |
            astmodels.AffineTransformation2D([[2, 0], [0, 2]], [42, 32]) +
            astmodels.Rotation2D(32)
    }

    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_inverse_transforms(tmpdir):
    rotation = astmodels.Rotation2D(32)
    rotation.inverse = astmodels.Rotation2D(45)

    real_rotation = astmodels.Rotation2D(32)

    tree = {
        'rotation': rotation,
        'real_rotation': real_rotation
    }

    def check(ff):
        assert ff.tree['rotation'].inverse.angle == 45

    helpers.assert_roundtrip_tree(tree, tmpdir, asdf_check_func=check)

@pytest.mark.parametrize(('model'), test_models)
def test_single_model(tmpdir, model):
    with warnings.catch_warnings():
        # Some schema files are missing from asdf<=2.4.2 which causes warnings
        if LooseVersion(asdf.__version__) <= '2.4.2':
            warnings.filterwarnings('ignore', 'Unable to locate schema file')
        tree = {'single_model': model}
        helpers.assert_roundtrip_tree(tree, tmpdir)

def test_name(tmpdir):
    def check(ff):
        assert ff.tree['rot'].name == 'foo'

    tree = {'rot': astmodels.Rotation2D(23, name='foo')}
    helpers.assert_roundtrip_tree(tree, tmpdir, asdf_check_func=check)

def test_zenithal_with_arguments(tmpdir):
    tree = {
        'azp': astmodels.Sky2Pix_AZP(0.5, 0.3)
    }

    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_naming_of_compound_model(tmpdir):
    """Issue #87"""
    def asdf_check(ff):
        assert ff.tree['model'].name == 'compound_model'

    offx = astmodels.Shift(1)
    scl = astmodels.Scale(2)
    model = (offx | scl).rename('compound_model')
    tree = {
        'model': model
    }
    helpers.assert_roundtrip_tree(tree, tmpdir, asdf_check_func=asdf_check)

def test_generic_projections(tmpdir):
    from astropy.io.misc.asdf.tags.transform import projections

    for tag_name, (name, params, version) in projections._generic_projections.items():
        tree = {
            'forward': util.resolve_name(
                f'astropy.modeling.projections.Sky2Pix_{name}')(),
            'backward': util.resolve_name(
                f'astropy.modeling.projections.Pix2Sky_{name}')()
        }

        helpers.assert_roundtrip_tree(tree, tmpdir)

def test_tabular_model(tmpdir):
    points = np.arange(0, 5)
    values = [1., 10, 2, 45, -3]
    model = astmodels.Tabular1D(points=points, lookup_table=values)
    tree = {'model': model}
    helpers.assert_roundtrip_tree(tree, tmpdir)
    table = np.array([[ 3.,  0.,  0.],
                      [ 0.,  2.,  0.],
                      [ 0.,  0.,  0.]])
    points = ([1, 2, 3], [1, 2, 3])
    model2 = astmodels.Tabular2D(points, lookup_table=table, bounds_error=False,
                                 fill_value=None, method='nearest')
    tree = {'model': model2}
    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_bounding_box(tmpdir):
    model = astmodels.Shift(1) & astmodels.Shift(2)
    model.bounding_box = ((1, 3), (2, 4))
    tree = {'model': model}
    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_linear1d(tmpdir):
    model = astmodels.Linear1D()
    tree = {'model': model}
    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_linear1d_quantity(tmpdir):
    model = astmodels.Linear1D(1*u.nm, 1*(u.nm/u.pixel))
    tree = {'model': model}
    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_tabular_model_units(tmpdir):
    points = np.arange(0, 5) * u.pix
    values = [1., 10, 2, 45, -3] * u.nm
    model = astmodels.Tabular1D(points=points, lookup_table=values)
    tree = {'model': model}
    helpers.assert_roundtrip_tree(tree, tmpdir)
    table = np.array([[3.,  0.,  0.],
                      [0.,  2.,  0.],
                      [0.,  0.,  0.]]) * u.nm
    points = ([1, 2, 3], [1, 2, 3]) * u.pix
    model2 = astmodels.Tabular2D(points, lookup_table=table,
                                 bounds_error=False, fill_value=None,
                                 method='nearest')
    tree = {'model': model2}
    helpers.assert_roundtrip_tree(tree, tmpdir)

def test_fix_inputs(tmpdir):

    with warnings.catch_warnings():
        # Some schema files are missing from asdf<=2.4.2 which causes warnings
        if LooseVersion(asdf.__version__) <= '2.4.2':
            warnings.filterwarnings('ignore', 'Unable to locate schema file')

        model = astmodels.Pix2Sky_TAN() | astmodels.Rotation2D()
        tree = {
            'compound': fix_inputs(model, {'x': 45}),
            'compound1': fix_inputs(model, {0: 45})
        }

        helpers.assert_roundtrip_tree(tree, tmpdir)

def test_fix_inputs_type():
    with pytest.raises(TypeError):
        tree = {
        'compound': fix_inputs(3, {'x': 45})
        }
        helpers.assert_roundtrip_tree(tree, tmpdir)

    with pytest.raises(AttributeError):
        tree = {
        'compound': astmodels.Pix2Sky_TAN() & {'x': 45}
        }
        helpers.assert_roundtrip_tree(tree, tmpdir)

comp_model = custom_and_analytical_inverse()

@pytest.mark.parametrize(('model'), [astmodels.Shift(1) & astmodels.Shift(2) | comp_model,
                                     comp_model | astmodels.Shift(1) & astmodels.Shift(2),
                                     astmodels.Shift(1) & comp_model,
                                     comp_model & astmodels.Shift(1)
                                     ])
def test_custom_and_analytical(model, tmpdir):
    fa = AsdfFile()
    fa.tree['model'] = model
    file_path = str(tmpdir.join('custom_and_analytical_inverse.asdf'))
    fa.write_to(file_path)
    with asdf.open(file_path) as f:
        assert f.tree['model'].inverse is not None


from unittest import mock

import pytest

from privx_api.base import format_path_components
from privx_api.enums import UrlEnum
from privx_api.exceptions import InternalAPIException
from privx_api.privx_api import PrivXAPI
from privx_api.utils import get_value

def test_urls():
    with pytest.raises(InternalAPIException):
        api = PrivXAPI("", "", "", "", "")
        api._get_url("not real")

    assert api._get_url(UrlEnum.AUTH.AUTHORIZE) != ""

@pytest.mark.parametrize(
    "base_url, args, expected",
    [
        ("/api/{id}/search", {"id": "a/b"}, "/api/a%2Fb/search"),
        ("/api/search?", {}, "/api/search?"),
    ],
)
def test_format_path_components(base_url, args, expected):
    assert format_path_components(base_url, **args) == expected

@pytest.mark.parametrize(
    "base_url, args",
    [
        ("/api/{id}/search", {"id": []}),
        ("/api/search/{ids}", {"ids": [1, 2, 3]}),
        ("/api/search/{ids}", {"ids": {"one": 1}}),
        ("/api/search/{ids}", {"ids": None}),
        ("/api/search/{ids}", {"ids": (1, 2, 3)}),
    ],
)
def test_format_path_components_negative(base_url, args):
    with pytest.raises(InternalAPIException):
        format_path_components(base_url, **args)

@pytest.mark.parametrize(
    "urlname, path_params, query_params, expected",
    [
        (
            UrlEnum.ROLE_STORE.MEMBERS,
            {"role_id": "123"},
            {"limit": 500},
            "/role-store/api/v1/roles/123/members?limit=500",
        ),
    ],
)
def test_build_url(urlname, path_params, query_params, expected):
    api = PrivXAPI("", "", "", "", "")
    assert api._build_url(urlname, path_params, query_params) == expected

@pytest.mark.parametrize(
    "url_name, expected_url",
    [
        ("AUTH.AUTHORIZE", "/auth/api/v1/oauth/authorize"),
        ("HOST_STORE.HOST", "/host-store/api/v1/hosts/{host_id}"),
        ("HOST_STORE.SEARCH", "/host-store/api/v1/hosts/search"),
        ("CONNECTION_MANAGER.SEARCH", "/connection-manager/api/v1/connections/search"),
    ],
)
def test_url_enum_get(url_name, expected_url):
    assert UrlEnum.get(url_name) == expected_url

@pytest.mark.parametrize(
    "url_name, expected_url",
    [
        ("TEST", "/asdasd/asd/test"),
        ("FAKE", None),
        ("", None),
        (None, None),
        (123, None),
    ],
)
def test_url_enum_get_exception_similar_url_name(url_name, expected_url):
    class TestEnumFirst:
        TEST = "TEST"
        urls = {TEST: "/asdasd/asd/test"}

    class TestEnumSecond:
        TEST = "TEST"
        urls = {TEST: "/asdasd/asd/test"}

    class FakeEnum(UrlEnum):
        CASE_1 = TestEnumFirst
        CASE_2 = TestEnumSecond

    with pytest.raises(InternalAPIException):
        FakeEnum.get(url_name)

@pytest.mark.parametrize(
    "value, expected_value",
    [
        ({"key": 123123}, '{"key": 123123}'),
        (
            "9293a478-0db1-4090-638d-22684820e230",
            "9293a478-0db1-4090-638d-22684820e230",
        ),
        ("{'key': 'value'}", "{'key': 'value'}"),
    ],
)
def test_make_body_params(value, expected_value):
    api = PrivXAPI("", "", "", "", "")
    assert api._make_body_params(value) == expected_value

@pytest.mark.parametrize(
    "params, exp_result",
    [
        (
            {
                "method": "GET",
                "url_name": UrlEnum.CONNECTION_MANAGER.CONNECTIONS,
                "query_params": {"offset": "111", "limit": "20"},
            },
            {
                "method": "GET",
                "url": "/connection-manager/api/v1/connections?offset=111&limit=20",
                "headers": {
                    "Content-type": "application/json",
                    "Authorization": "Bearer ",
                },
            },
        ),
        (
            {
                "method": "GET",
                "url_name": UrlEnum.CONNECTION_MANAGER.TRAIL_LOG_SESSION_ID,
                "query_params": {"format_param": "111", "filter_param": "20"},
                "path_params": {
                    "connection_id": "1",
                    "channel_id": "1",
                    "session_id": "1",
                },
            },
            {
                "method": "GET",
                "url": "/connection-manager/api/v1/connections/1/"
                "channel/1/log/1?format_param=111&filter_param=20",
                "headers": {
                    "Content-type": "application/json",
                    "Authorization": "Bearer ",
                },
            },
        ),
        (
            {
                "method": "GET",
                "url_name": UrlEnum.CONNECTION_MANAGER.TERMINATE_CONNECTION_ID,
                "query_params": {"format_param": "111", "filter_param": "20"},
                "path_params": {
                    "connection_id": "1",
                },
                "body": {"body_params": "just params"},
            },
            {
                "method": "GET",
                "url": "/connection-manager/api/v1/terminate"
                "/connection/1?format_param=111&filter_param=20",
                "headers": {
                    "Content-type": "application/json",
                    "Authorization": "Bearer ",
                },
                "body": '{"body_params": "just params"}',
            },
        ),
        (
            {
                "method": "POST",
                "url_name": UrlEnum.CONNECTION_MANAGER.TERMINATE_CONNECTION_ID,
                "path_params": {
                    "connection_id": "1",
                },
                "body": "body as a str",
            },
            {
                "method": "POST",
                "url": "/connection-manager/api/v1/terminate/connection/1",
                "headers": {
                    "Content-type": "application/json",
                    "Authorization": "Bearer ",
                },
                "body": "body as a str",
            },
        ),
    ],
)
def test_build_request(params, exp_result):
    api = PrivXAPI("", "", "", "", "")
    with mock.patch.object(PrivXAPI, "_authenticate"):
        assert sorted(api._build_request(**params)) == sorted(exp_result)

@pytest.mark.parametrize(
    "val, default_val, exp_val",
    [
        ("", "", ""),
        ("data", "", "data"),
        (0, 123, 0),
        ([], [1, 2, 3], []),
        (None, dict(), {}),
        (None, [], []),
        (None, None, None),
    ],
)
def test_get_value(val, default_val, exp_val):
    assert get_value(val, default_val) == exp_val


from django import forms
from .models import Book, BookReview

class BookForm(forms.ModelForm):
    """
    BookFrom model Form
    fields:
            -> title
            -> author
            -> description
            -> file
            -> cover
            -> link
            -> tags
    """

    class Meta:
        model = Book
        fields = ["title", "author", "description", "file", "cover", "link", "tags"]

    def __init__(self, *args, **kwargs):
        super(BookForm, self).__init__(*args, **kwargs)

        for field in self.fields:
            self.fields[field].widget.attrs["class"] = "form-control"
            if self.fields["tags"]:
                continue
            if self.fields["created_date"]:
                continue

        self.fields["tags"].widget.attrs["class"] = "form-select"
        self.fields["file"].widget.attrs["accept"] = ".pdf"
        self.fields["cover"].widget.attrs["accept"] = "image/*"

class BookReviewForm(forms.ModelForm):
    """
    BookReviewForm model Form
    fields:
            -> stars
            -> body
    """

    class Meta:
        model = BookReview
        fields = ["stars", "body"]

    def __init__(self, *args, **kwargs):
        super(BookReviewForm, self).__init__(*args, **kwargs)

        for field in self.fields:
            self.fields[field].widget.attrs["class"] = "form-control"


import numpy as np
from datasets import load_metric

root_dir = "/home/nl438/rds/hpc-work/PROJECT/custom_pipeline/"
def compute_metrics_acc(eval_pred):
    """Computes accuracy on a batch of predictions"""
    predictions = np.argmax(eval_pred.predictions, axis=1)
    metric = load_metric("accuracy")
    return metric.compute(predictions=predictions, references=eval_pred.label_ids)

def compute_metrics_regression(eval_pred):
    predictions = eval_pred.predictions
    references = eval_pred.label_ids
    metric1 = load_metric(f"{root_dir}ccc.py")
    metric2 = load_metric(f"{root_dir}rmse.py")

    return {"ccc": metric1.compute(predictions=predictions, references=references),
            "rmse": metric2.compute(predictions=predictions, references=references)}

def compute_metrics_multi(eval_pred):

    predictions_reg = eval_pred.predictions[0]
    predictions_cl = eval_pred.predictions[1]

    print(predictions_reg)
    print(predictions_cl)

    references_reg = eval_pred.label_ids[:, :3]
    references_cl = eval_pred.label_ids[:, 3]
    predictions_cl = np.argmax(predictions_cl, axis=1)

    metric1 = load_metric(f"{root_dir}ccc.py")
    metric2 = load_metric(f"{root_dir}rmse.py")
    metric3 = load_metric("accuracy")

    return {"ccc": metric1.compute(predictions=predictions_reg, references=references_reg),
            "rmse": metric2.compute(predictions=predictions_reg, references=references_reg),
            "accuracy": metric3.compute(predictions=predictions_cl, references=references_cl)}

# def compute_metrics_rmse(eval_pred):
#     predictions = eval_pred.predictions
#     references = eval_pred.label_ids
#     metric = load_metric("rmse.py")
#     return metric.compute(predictions=predictions, references=references)


import numpy as np
import cv2
import cv2.cv as cv
import time

cap = cv2.VideoCapture(0)
start_time = time.time()

palm_cascade = cv.Load('palm.xml')
fist_cascade = cv.Load('fist.xml')

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    if not ret:
        continue
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    gray_mat = cv.fromarray(gray)
    palms = cv.HaarDetectObjects(gray_mat, palm_cascade, cv.CreateMemStorage(0), 1.1, 8)
    fists = cv.HaarDetectObjects(gray_mat, fist_cascade, cv.CreateMemStorage(0), 1.1, 8)

    for (x, y, w, h), n in palms:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 255, 255))
    for (x, y, w, h), n in fists:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0))

    # Display the resulting frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()


import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go

######################## Part 1: Read combined data source ########################
# Read combined data
df = pd.read_csv('combined_data_source.csv')

######################## Part 2: Get data sub-sets needed for visualizations ########################

# Drop columns that are not needed for cluster collapsing
df_reduced = df.drop(['Property Name', 'Deal Id', 'NCE', 'NCE per Desk', 'NCE per USF'], axis=1)

# Function to get year filtered subset of df
def filter_year(input_df, year):
	return input_df[input_df['Open Year'] == year]

# Get separate df's for each year
df16_reduced = filter_year(df_reduced, 2016)
df17_reduced = filter_year(df_reduced, 2017)

# Function to callpse dfs by column=str
def collapse_df_cluster(input_df, column=str):
	return input_df.groupby([column]).sum()

# Collapse clusters
collapsed_df = collapse_df_cluster(df_reduced, 'Cluster')
collapsed_df16 = collapse_df_cluster(df16_reduced, 'Cluster')
collapsed_df17 = collapse_df_cluster(df17_reduced, 'Cluster')

# Calculate NCE, NCE per Desk, and NCE per USF
for i in [collapsed_df16, collapsed_df17, collapsed_df]:
	i['NCE'] = i['Capital Expenditure'] - i['TI Monies Received']
	i['NCE per Desk'] = i['NCE'] / i['Desk Count']
	i['NCE per USF'] = i['NCE'] / i['USF']

# Set up a dictionary to hold keys (cluster) and values (cluster filtered df collapsed by market)
cluster_dict ={}
for i in df_reduced['Cluster'].unique():
	cluster_dict[str(i)] = df_reduced[df_reduced['Cluster'] == i].sort_values(by='Market').set_index(['Market', 'Project Id']).groupby(level=[0]).sum()

# Calculate NCE, NCE per Desk, and NCE per USF
for key, value in cluster_dict.items():
	value['NCE'] = value['Capital Expenditure'] - value['TI Monies Received']
	value['NCE per Desk'] = value['NCE'] / value['Desk Count']
	value['NCE per USF'] = value['NCE'] / value['USF']

######################## Part 3: Build the Visualization ########################
app = dash.Dash()

app.layout = html.Div([

######################## Part 3A: Header ########################
dcc.Markdown('''
# Case Study Submission
*An analysis of Net Capital Expenditure by market and cluster during 2016 and 2017*

*By: Afaan Naqvi*
***
#### 1. Cluster vs Year Analysis
*2016 vs 2017 cluster comparison*
'''),
######################## Part 3B: Cluster vs year analysis ########################
html.Div([
	html.Div([
		dcc.Graph(
			id='nce-desk-year',
			figure={
			'data': [
			{'x': [i for i in collapsed_df16.index], 'y':[i for i in collapsed_df16['NCE per Desk']], 'type': 'bar', 'name': '2016'},
			{'x': [i for i in collapsed_df17.index], 'y':[i for i in collapsed_df17['NCE per Desk']], 'type': 'bar', 'name': '2017'},
			],
			'layout': {
			'title': 'NCE per Desk',
			'yaxis':{
			'title': 'US$/Desk'}

			}
			}
			)
		],
		style={'width': '48%', 'display': 'inline-block'}),

	html.Div([
		dcc.Graph(
			id='nce-usf-year',
			figure={
			'data': [
			{'x': [i for i in collapsed_df16.index], 'y':[i for i in collapsed_df16['NCE per USF']], 'type': 'bar', 'name': '2016'},
			{'x': [i for i in collapsed_df17.index], 'y':[i for i in collapsed_df17['NCE per USF']], 'type': 'bar', 'name': '2017'},
			],
			'layout': {
			'title': 'NCE per USF',
			'yaxis':{
			'title': 'US$/USF'}
			}
			}

			)
		],style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
	]),

html.Hr(),

######################## Part 3C: Cluster vs cluster analysis ########################
dcc.Markdown('''
#### 2. Cluster vs Cluster Analysis
*Year agnostic cluster comparison*
'''),
html.Div([
	html.Div([
		dcc.Graph(
			id='nce-desk-cluster',
			figure={
			'data': [
			{'x': [i for i in collapsed_df.index], 'y':[i for i in collapsed_df['NCE per Desk']], 'type': 'bar'},
			],
			'layout': {
			'title': 'NCE per Desk',
			'yaxis':{
			'title': 'US$/Desk'}

			}
			}
			)
		],
		style={'width': '48%', 'display': 'inline-block'}),

	html.Div([
		dcc.Graph(
			id='nce-usf-cluster',
			figure={
			'data': [
			{'x': [i for i in collapsed_df.index], 'y':[i for i in collapsed_df['NCE per USF']], 'type': 'bar'},
			],
			'layout': {
			'title': 'NCE per USF',
			'yaxis':{
			'title': 'US$/USF'}
			}
			}

			)
		],style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
	]),

html.Hr(),

######################## Part 3D: Market analysis ########################
dcc.Markdown('''
#### 3. Market Analysis
*Cheapest and most expensive markets to build in*
'''),
html.Div([
	html.Div([
		html.Label('Select Cluster'),
		dcc.Dropdown(
			id='cluster-input',
			options=[{'label': i, 'value': i} for i in sorted(list(cluster_dict.keys()))],
			value='Cluster 1'
			),

		],
		style={'width': '10%', 'display': 'inline-block'}),

	html.Div([

	html.Div([
		dcc.Graph(id='market-desk'),
		],
		style={'width': '48%', 'display': 'inline-block'}),

	html.Div([
		dcc.Graph(id='market-usf'),
		],style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
	]),
	]),

html.Hr(),

dcc.Markdown('''
#### 4. Outlier Analysis
*Identification of properties outside the expected NCE/Desk-to-NCE/USF correlation*
'''),
######################## Part 3E: Outlier analysis ########################
html.Div([
	dcc.Graph(
		id='nce-scatter',
		figure={
		'data': [
		go.Scatter(
			x=df[df['Cluster'] == i]['NCE per Desk'],
			y=df[df['Cluster'] == i]['NCE per USF'],
			text=df[df['Cluster'] == i]['Market'],
			mode='markers',
			opacity=0.7,
			marker={
			'size': 15,
			'line': {'width': 0.5, 'color': 'white'}
			},
			name=i
			) for i in df['Cluster'].unique()
		],
		'layout': go.Layout(
			xaxis={'title': 'US$/Desk'},
			yaxis={'title': 'US$/USF'},
			margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
			hovermode='closest',
			)
		}
		)
	]),

dcc.Markdown('''
	''')
])

######################## Part 4: Callbacks and functions ########################

@app.callback(
	dash.dependencies.Output('market-desk', 'figure'),
	[dash.dependencies.Input('cluster-input', 'value')])
def update_desk_graph(cluster_value):
	df = cluster_dict[cluster_value].sort_values(by='NCE per Desk', ascending=False)

	return {
	'data': [
	{'x': [i for i in df.index], 'y':[i for i in df['NCE per Desk']], 'type': 'bar', 'name': str(cluster_value)},
	],
	'layout': {
	'title': 'NCE per Desk',
	'yaxis':{
	'title': 'US$/Desk'}

	}
	}

@app.callback(
	dash.dependencies.Output('market-usf', 'figure'),
	[dash.dependencies.Input('cluster-input', 'value')])
def update_usf_graph(cluster_value):
	df = cluster_dict[cluster_value].sort_values(by='NCE per Desk', ascending=False)

	return {

	'data': [
	{'x': [i for i in df.index], 'y':[i for i in df['NCE per USF']], 'type': 'bar', 'name': str(cluster_value)},
	],
	'layout': {
	'title': 'NCE per USF',
	'yaxis':{
	'title': 'US$/USF'}

	}
	}

app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})

if __name__ == '__main__':
	app.run_server()


from urllib.parse import quote

try: import simplejson as json
except ImportError: import json

from .utils import build_where_clause, build_choose_clause
from .client import QuickBooks
from .exceptions import QuickbooksException

class ToJsonMixin(object):
    def to_json(self):
        return json.dumps(self, default=self.json_filter(), sort_keys=True, indent=4)

    def json_filter(self):
        """
        filter out properties that have names starting with _
        or properties that have a value of None
        """
        return lambda obj: dict((k, v) for k, v in obj.__dict__.items()
                                if not k.startswith('_') and getattr(obj, k) is not None)

class FromJsonMixin(object):
    class_dict = {}
    list_dict = {}

    @classmethod
    def from_json(cls, json_data):
        obj = cls()
        for key in json_data:
            if key in obj.class_dict:
                sub_obj = obj.class_dict[key]()
                sub_obj = sub_obj.from_json(json_data[key])
                setattr(obj, key, sub_obj)

            elif key in obj.list_dict:
                sub_list = []

                for data in json_data[key]:

                    if 'DetailType' in data and data['DetailType'] in obj.detail_dict:
                        sub_obj = obj.detail_dict[data['DetailType']]()
                    else:
                        sub_obj = obj.list_dict[key]()

                    sub_obj = sub_obj.from_json(data)
                    sub_list.append(sub_obj)

                setattr(obj, key, sub_list)
            else:
                setattr(obj, key, json_data[key])

        return obj

# Based on http://stackoverflow.com/a/1118038
def to_dict(obj, classkey=None):
    """
    Recursively converts Python object into a dictionary
    """
    if isinstance(obj, dict):
        data = {}
        for (k, v) in obj.items():
            data[k] = to_dict(v, classkey)
        return data
    elif hasattr(obj, "_ast"):
        return to_dict(obj._ast())
    elif hasattr(obj, "__iter__") and not isinstance(obj, str):
        return [to_dict(v, classkey) for v in obj]
    elif hasattr(obj, "__dict__"):
        data = dict([(key, to_dict(value, classkey))
                    for key, value in obj.__dict__.items()
                    if not callable(value) and not key.startswith('_')])

        if classkey is not None and hasattr(obj, "__class__"):
            data[classkey] = obj.__class__.__name__
        return data
    else:
        return obj

class ToDictMixin(object):
    def to_dict(self):
        return to_dict(self)

class ReadMixin(object):
    qbo_object_name = ""
    qbo_json_object_name = ""

    @classmethod
    def get(cls, id, qb=None):
        if not qb:
            qb = QuickBooks()

        json_data = qb.get_single_object(cls.qbo_object_name, pk=id)

        if cls.qbo_json_object_name != '':
            return cls.from_json(json_data[cls.qbo_json_object_name])
        else:
            return cls.from_json(json_data[cls.qbo_object_name])

class SendMixin(object):
    def send(self, qb=None, send_to=None):
        if not qb:
            qb = QuickBooks()

        end_point = "{0}/{1}/send".format(self.qbo_object_name.lower(), self.Id)

        if send_to:
            send_to = quote(send_to, safe='')
            end_point = "{0}?sendTo={1}".format(end_point, send_to)

        results = qb.misc_operation(end_point, None, 'application/octet-stream')

        return results

class VoidMixin(object):
    def void(self, qb=None):
        if not qb:
            qb = QuickBooks()

        if not self.Id:
            raise QuickbooksException('Cannot void unsaved object')

        data = {
            'Id': self.Id,
            'SyncToken': self.SyncToken,
        }

        endpoint = self.qbo_object_name.lower()
        url = "{0}/company/{1}/{2}".format(qb.api_url, qb.company_id, endpoint)
        results = qb.post(url, json.dumps(data), params={'operation': 'void'})

        return results

class UpdateMixin(object):
    qbo_object_name = ""
    qbo_json_object_name = ""

    def save(self, qb=None, request_id=None, params=None):
        if not qb:
            qb = QuickBooks()

        if self.Id and int(self.Id) > 0:
            json_data = qb.update_object(self.qbo_object_name, self.to_json(), request_id=request_id, params=params)
        else:
            json_data = qb.create_object(self.qbo_object_name, self.to_json(), request_id=request_id, params=params)

        if self.qbo_json_object_name != '':
            obj = type(self).from_json(json_data[self.qbo_json_object_name])
        else:
            obj = type(self).from_json(json_data[self.qbo_object_name])

        self.Id = obj.Id
        return obj

class UpdateNoIdMixin(object):
    qbo_object_name = ""
    qbo_json_object_name = ""

    def save(self, qb=None, request_id=None):
        if not qb:
            qb = QuickBooks()

        json_data = qb.update_object(self.qbo_object_name, self.to_json(), request_id=request_id)
        obj = type(self).from_json(json_data[self.qbo_object_name])
        return obj

class DeleteMixin(object):
    qbo_object_name = ""

    def delete(self, qb=None, request_id=None):
        if not qb:
            qb = QuickBooks()

        if not self.Id:
            raise QuickbooksException('Cannot delete unsaved object')

        data = {
            'Id': self.Id,
            'SyncToken': self.SyncToken,
        }
        return qb.delete_object(self.qbo_object_name, json.dumps(data), request_id=request_id)

class DeleteNoIdMixin(object):
    qbo_object_name = ""

    def delete(self, qb=None, request_id=None):
        if not qb:
            qb = QuickBooks()

        return qb.delete_object(self.qbo_object_name, self.to_json(), request_id=request_id)

class ListMixin(object):
    qbo_object_name = ""
    qbo_json_object_name = ""

    @classmethod
    def all(cls, order_by="", start_position="", max_results=100, qb=None):
        """
        :param start_position:
        :param max_results: The max number of entities that can be returned in a response is 1000.
        :param qb:
        :return: Returns list
        """
        return cls.where("", order_by=order_by, start_position=start_position,
                         max_results=max_results, qb=qb)

    @classmethod
    def filter(cls, order_by="", start_position="", max_results="", qb=None, **kwargs):
        """
        :param order_by:
        :param start_position:
        :param max_results:
        :param qb:
        :param kwargs: field names and values to filter the query
        :return: Filtered list
        """
        return cls.where(build_where_clause(**kwargs),
                         start_position=start_position, max_results=max_results, order_by=order_by,
                         qb=qb)

    @classmethod
    def choose(cls, choices, field="Id", qb=None):
        """
        :param choices:
        :param field:
        :param qb:
        :return: Filtered list
        """
        return cls.where(build_choose_clause(choices, field), qb=qb)

    @classmethod
    def where(cls, where_clause="", order_by="", start_position="", max_results="", qb=None):
        """
        :param where_clause: QBO SQL where clause (DO NOT include 'WHERE')
        :param order_by:
        :param start_position:
        :param max_results:
        :param qb:
        :return: Returns list filtered by input where_clause
        """
        if where_clause:
            where_clause = "WHERE " + where_clause

        if order_by:
            order_by = " ORDERBY " + order_by

        if start_position != "":
            start_position = " STARTPOSITION " + str(start_position)

        if max_results:
            max_results = " MAXRESULTS " + str(max_results)

        select = "SELECT * FROM {0} {1}{2}{3}{4}".format(
            cls.qbo_object_name, where_clause, order_by, start_position, max_results)

        return cls.query(select, qb=qb)

    @classmethod
    def query(cls, select, qb=None):
        """
        :param select: QBO SQL query select statement
        :param qb:
        :return: Returns list
        """
        if not qb:
            qb = QuickBooks()

        json_data = qb.query(select)

        obj_list = []

        if cls.qbo_json_object_name != '':
            object_name = cls.qbo_json_object_name
        else:
            object_name = cls.qbo_object_name

        if object_name in json_data["QueryResponse"]:
            for item_json in json_data["QueryResponse"][object_name]:
                obj_list.append(cls.from_json(item_json))

        return obj_list

    @classmethod
    def count(cls, where_clause="", qb=None):
        """
        :param where_clause: QBO SQL where clause (DO NOT include 'WHERE')
        :param qb:
        :return: Returns database record count
        """
        if not qb:
            qb = QuickBooks()

        if where_clause:
            where_clause = "WHERE " + where_clause

        select = "SELECT COUNT(*) FROM {0} {1}".format(
            cls.qbo_object_name, where_clause)

        json_data = qb.query(select)

        if "totalCount" in json_data["QueryResponse"]:
            return json_data["QueryResponse"]["totalCount"]
        else:
            return None

class QuickbooksPdfDownloadable(object):
    qbo_object_name = ""

    def download_pdf(self, qb=None):
        if self.Id and int(self.Id) > 0 and qb is not None:
            return qb.download_pdf(self.qbo_object_name, self.Id)
        else:
            raise QuickbooksException(
                "Cannot download {0} when no Id is assigned or if no quickbooks client is passed in".format(
                    self.qbo_object_name))

class ObjectListMixin(object):
    qbo_object_name = ""
    _object_list = []

    def __iter__(self):
        return self._object_list.__iter__()

    def __len__(self):
        return self._object_list.__len__()

    def __contains__(self, item):
        return self._object_list.__contains__(item)

    def __getitem__(self, key):
        # if key is of invalid type or value, the list values will raise the error
        return self._object_list.__getitem__(key)

    def __setitem__(self, key, value):
        self._object_list.__setitem__(key, value)

    def __delitem__(self, key):
        self._object_list.__delitem__(key)

    def __reversed__(self):
        return self._object_list.__reversed__()

    def append(self, value):
        self._object_list.append(value)

    def pop(self, *args, **kwargs):
        return self._object_list.pop(*args, **kwargs)

class PrefMixin(object):
    qbo_object_name = ""
    qbo_json_object_name = ""

    @classmethod
    def get(cls, qb=None):
        if not qb:
            qb = QuickBooks()

        end_point = "{0}/company/{1}/preferences".format(qb.api_url, qb.company_id)
        json_data = qb.get(end_point, {})
        return cls.from_json(json_data[cls.qbo_object_name])