import taichi as ti

ti.init(arch=ti.gpu)

use_mc = True
mc_clipping = False
pause = False

# Runge-Kutta order
rk = 3

n = 512
x = ti.var(ti.f32, shape=(n, n))
new_x = ti.var(ti.f32, shape=(n, n))
new_x_aux = ti.var(ti.f32, shape=(n, n))
dx = 1 / n
inv_dx = 1 / dx
dt = 0.05

stagger = ti.Vector([0.5, 0.5])

@ti.func
def Vector2(x, y):
    return ti.Vector([x, y])

@ti.func
def inside(p, c, r):
    return (p - c).norm_sqr() <= r * r

@ti.func
def inside_taichi(p):
    p = Vector2(0.5, 0.5) + (p - Vector2(0.5, 0.5)) * 1.2
    ret = -1
    if not inside(p, Vector2(0.50, 0.50), 0.55):
        if ret == -1:
            ret = 0
    if not inside(p, Vector2(0.50, 0.50), 0.50):
        if ret == -1:
            ret = 1
    if inside(p, Vector2(0.50, 0.25), 0.09):
        if ret == -1:
            ret = 1
    if inside(p, Vector2(0.50, 0.75), 0.09):
        if ret == -1:
            ret = 0
    if inside(p, Vector2(0.50, 0.25), 0.25):
        if ret == -1:
            ret = 0
    if inside(p, Vector2(0.50, 0.75), 0.25):
        if ret == -1:
            ret = 1
    if p[0] < 0.5:
        if ret == -1:
            ret = 1
    else:
        if ret == -1:
            ret = 0
    return ret

@ti.kernel
def paint():
    for i, j in ti.ndrange(n * 4, n * 4):
        ret = 1 - inside_taichi(Vector2(i / n / 4, j / n / 4))
        x[i // 4, j // 4] += ret / 16

@ti.func
def velocity(p):
    return ti.Vector([p[1] - 0.5, 0.5 - p[0]])

@ti.func
def vec(x, y):
    return ti.Vector([x, y])

@ti.func
def clamp(p):
    for d in ti.static(range(p.n)):
        p[d] = min(1 - 1e-4 - dx + stagger[d] * dx, max(p[d], stagger[d] * dx))
    return p

@ti.func
def sample_bilinear(x, p):
    p = clamp(p)

    p_grid = p * inv_dx - stagger

    I = ti.cast(ti.floor(p_grid), ti.i32)
    f = p_grid - I
    g = 1 - f

    return x[I] * (g[0] * g[1]) + x[I + vec(1, 0)] * (
        f[0] * g[1]) + x[I + vec(0, 1)] * (
            g[0] * f[1]) + x[I + vec(1, 1)] * (f[0] * f[1])

@ti.func
def sample_min(x, p):
    p = clamp(p)
    p_grid = p * inv_dx - stagger
    I = ti.cast(ti.floor(p_grid), ti.i32)

    return min(x[I],  x[I + vec(1, 0)], x[I + vec(0, 1)], x[I + vec(1, 1)])

@ti.func
def sample_max(x, p):
    p = clamp(p)
    p_grid = p * inv_dx - stagger
    I = ti.cast(ti.floor(p_grid), ti.i32)

    return max(x[I],  x[I + vec(1, 0)], x[I + vec(0, 1)], x[I + vec(1, 1)])

@ti.func
def backtrace(I, dt):
    p = (I + stagger) * dx
    if ti.static(rk == 1):
        p -= dt * velocity(p)
    elif ti.static(rk == 2):
        p_mid = p - 0.5 * dt * velocity(p)
        p -= dt * velocity(p_mid)
    elif ti.static(rk == 3):
        v1 = velocity(p)
        p1 = p - 0.5 * dt * v1
        v2 = velocity(p1)
        p2 = p - 0.75 * dt * v2
        v3 = velocity(p2)
        p -= dt * (2 / 9 * v1 + 1 / 3 * v2 + 4 / 9 * v3)
    else:
        ti.static_print(f"RK{rk} is not supported.")

    return p

@ti.func
def semi_lagrangian(x, new_x, dt):
    # Note: this loop is parallelized
    for I in ti.grouped(x):
        new_x[I] = sample_bilinear(x, backtrace(I, dt))

# Reference: https://github.com/ziyinq/Bimocq/blob/master/src/bimocq2D/BimocqSolver2D.cpp

@ti.func
def maccormack(x, dt):
    semi_lagrangian(x, new_x, dt)
    semi_lagrangian(new_x, new_x_aux, -dt)

    for I in ti.grouped(x):
        new_x[I] = new_x[I] + 0.5 * (x[I] - new_x_aux[I])

        if ti.static(mc_clipping):
            source_pos = backtrace(I, dt)
            min_val = sample_min(x, source_pos)
            max_val = sample_max(x, source_pos)

            if new_x[I] < min_val or new_x[I] > max_val:
                new_x[I] = sample_bilinear(x, source_pos)

@ti.kernel
def advect():
    if ti.static(use_mc):
        maccormack(x, dt)
    else:
        semi_lagrangian(x, new_x, dt)

    for I in ti.grouped(x):
        x[I] = new_x[I]

paint()

gui = ti.GUI('Advection schemes', (512, 512))

while True:
    while gui.get_event(ti.GUI.PRESS):
        if gui.event.key in [ti.GUI.ESCAPE, ti.GUI.EXIT]: exit(0)
        if gui.event.key == ti.GUI.SPACE:
            pause = not pause
    if not pause:
        for i in range(1):
            advect()
    gui.set_image(x.to_numpy())
    gui.show()


import numpy as np
from scipy.signal import spectrogram
from PyQt5.QtCore import QRectF
import pyqtgraph as pg

def decibel(power, ref_power=1.0, min_power=1e-20):
    """Transform power to decibel relative to ref_power.

    \\[ decibel = 10 \\cdot \\log_{10}(power/ref\\_power) \\]
    Power values smaller than `min_power` are set to `-np.inf`.

    Parameters
    ----------
    power: float or array
        Power values, for example from a power spectrum or spectrogram.
    ref_power: float or None or 'peak'
        Reference power for computing decibel.
        If set to `None` or 'peak', the maximum power is used.
    min_power: float
        Power values smaller than `min_power` are set to `-np.inf`.

    Returns
    -------
    decibel_psd: array
        Power values in decibel relative to `ref_power`.
    """
    if isinstance(power, (list, tuple, np.ndarray)):
        tmp_power = power
        decibel_psd = power.copy()
    else:
        tmp_power = np.array([power])
        decibel_psd = np.array([power])
    if ref_power is None or ref_power == 'peak':
        ref_power = np.max(decibel_psd)
    decibel_psd[tmp_power <= min_power] = float('-inf')
    decibel_psd[tmp_power > min_power] = 10.0 * np.log10(decibel_psd[tmp_power > min_power]/ref_power)
    if isinstance(power, (list, tuple, np.ndarray)):
        return decibel_psd
    else:
        return decibel_psd[0]

class SpecItem(pg.ImageItem):

    def __init__(self, data, rate, channel, nfft, *args, **kwargs):
        pg.ImageItem.__init__(self, **kwargs)
        self.setOpts(axisOrder='row-major')

        self.data = data
        self.rate = rate
        self.channel = channel
        self.offset = -1
        self.buffer_size = 0
        self.nfft = nfft
        self.tresolution = None
        self.fresolution = self.rate/self.nfft
        self.step_frac = 0.5
        self.current_nfft = 1
        self.current_step = 1
        self.fmax = 0.5/self.rate
        self.zmin, self.zmax = self.set_resolution(nfft, 0.5, True)
        self.f0 = 0.0
        self.f1 = self.fmax
        self.cbar = None
        #self.spectrum = None

    def set_resolution(self, nfft=None, step_frac=None, update=True):
        if not nfft is None:
            self.nfft = nfft
        self.fresolution = self.rate/self.nfft
        if not step_frac is None:
            self.step_frac = step_frac
            if self.step_frac > 1.0:
                self.step_frac = 1.0
        self.step = int(np.round(self.step_frac * self.nfft))
        if self.step < 1:
            self.step = 1
        if update:
            return self.update_spectrum()

    def setCBar(self, cbar):
        self.cbar = cbar

    def set_power(self, zmin, zmax):
        if not zmin is None:
            self.zmin = zmin
        if not zmax is None:
            self.zmax = zmax
        self.setLevels((self.zmin, self.zmax), update=True)
        if not self.cbar is None:
            self.cbar.setLevels((self.zmin, self.zmax))

    def viewRangeChanged(self):
        vb = self.getViewBox()
        if not isinstance(vb, pg.ViewBox):
            return

        trange = vb.viewRange()[0]
        start = max(0, int(trange[0]*self.rate))
        stop = min(len(self.data), int(trange[1]*self.rate+1))
        if start < self.data.offset or stop >= self.data.offset + len(self.data.buffer):
            self.data.update_buffer(start, stop)
        self.update_spectrum()

    def update_spectrum(self):
        if len(self.data.buffer) == 0:
            return 0, 1
        if self.offset == self.data.offset and \
           self.buffer_size == len(self.data.buffer) and \
           self.current_nfft == self.nfft and \
           self.current_step == self.step:
            return

        freq, time, Sxx = spectrogram(self.data.buffer[:, self.channel],
                                      self.rate, nperseg=self.nfft,
                                      noverlap=self.nfft-self.step)
        self.tresolution = time[1] - time[0]
        self.fresolution = freq[1] - freq[0]
        self.spectrum = decibel(Sxx)
        #print(np.max(self.spectrum))
        zmax = np.percentile(self.spectrum, 99.9) + 5.0
        #zmin = np.percentile(self.spectrum, 70.0)
        #zmax = -20
        zmin = zmax - 60
        self.fmax = freq[-1]
        self.setImage(self.spectrum, autoLevels=False)
        self.setRect(QRectF(self.data.offset/self.rate, 0, time[-1], freq[-1]))
        self.offset = self.data.offset
        self.buffer_size = len(self.data.buffer)
        self.current_nfft = self.nfft
        self.current_step = self.step
        return zmin, zmax

    def zoom_freq_in(self):
        df = self.f1 - self.f0
        if df > 0.1:
            df *= 0.5
            self.f1 = self.f0 + df

    def zoom_freq_out(self):
        if self.f1 - self.f0 < self.fmax:
            df = self.f1 - self.f0
            df *= 2.0
            if df > self.fmax:
                df = self.fmax
            self.f1 = self.f0 + df
            if self.f1 > self.fmax:
                self.f1 = self.fmax
                self.f0 = self.fmax - df
            if self.f0 < 0:
                self.f0 = 0
                self.f1 = df

    def freq_down(self):
        if self.f0 > 0.0:
            df = self.f1 - self.f0
            self.f0 -= 0.5*df
            self.f1 -= 0.5*df
            if self.f0 < 0.0:
                self.f0 = 0.0
                self.f1 = df

    def freq_up(self):
        if self.f1 < self.fmax:
            df = self.f1 - self.f0
            self.f0 += 0.5*df
            self.f1 += 0.5*df

    def freq_home(self):
        if self.f0 > 0.0:
            df = self.f1 - self.f0
            self.f0 = 0.0
            self.f1 = df

    def freq_end(self):
        if self.f1 < self.fmax:
            df = self.f1 - self.f0
            self.f1 = ceil(self.fmax/(0.5*df))*(0.5*df)
            self.f0 = self.f1 - df
            if self.f0 < 0.0:
                self.f0 = 0.0
                self.f1 = df

    def freq_resolution_down(self):
        if self.nfft > 16:
            self.set_resolution(nfft=self.nfft//2)

    def freq_resolution_up(self):
        if self.nfft*2 < len(self.data):
            self.set_resolution(nfft=self.nfft*2)

    def step_frac_down(self):
        if 0.5 * self.step_frac * self.nfft >= 1:
            self.set_resolution(step_frac=self.step_frac*0.5)

    def step_frac_up(self):
        if self.step_frac < 1.0:
            self.set_resolution(step_frac=self.step_frac*2.0)


import __future__
import os
import copy
import json
import logging
import pathlib

import vtk
import numpy as np
import pyvista as pv
import matplotlib.pyplot as plt
from easydict import EasyDict
import trimesh
from PIL import Image
import cv2
# import pygeodesic.geodesic as geodesic
import vtk.util.numpy_support as vtknp

from PyQt5 import QtWidgets

from ..path import LATLON_PATH

logger = logging.getLogger("vision6D")

def fread(fid, _len, _type):
    if _len == 0:
        return np.empty(0)
    if _type == "int16":
        _type = np.int16
    elif _type == "int32":
        _type = np.int32
    elif _type == "float32":
        _type = np.float32
    elif _type == "double":
        _type = np.double
    elif _type == "char":
        _type = np.byte
    elif _type == "uint8":
        _type = np.uint8
    else:
        raise NotImplementedError(f"Invalid _type: {_type}")

    return np.fromfile(fid, _type, _len)

def meshread(fid, linesread=False, meshread2=False):
    """Reads mesh from fid data stream

    Parameters
    ----------
    fid (io.BufferedStream)
        Input IO stream
    _type (str, optional):
        Specifying the data _type for the last fread
    linesread (bool, optional)
        Distinguishing different use cases,
            False => meshread (default)
            True  => linesread

    """

    # Creating mesh instance
    mesh = EasyDict()

    # Reading parameters for mesh
    mesh.id = fread(fid, 1, "int32")
    mesh.numverts = fread(fid, 1, "int32")[0]
    mesh.numtris = fread(fid, 1, "int32")[0]

    # Loading mesh data
    n = fread(fid, 1, "int32")
    if n == -1:
        mesh.orient = fread(fid, 3, "int32")
        mesh.dim = fread(fid, 3, "int32")
        mesh.sz = fread(fid, 3, "float32")
        mesh.color = fread(fid, 3, "int32")
    else:
        mesh.color = np.zeros(3)
        mesh.color[0] = n
        mesh.color[1:3] = fread(fid, 2, "int32")

    # Given input parameter `linesread`
    if linesread:
        mesh.vertices = fread(fid, 3 * mesh.numverts, "float32").reshape([3, mesh.numverts], order="F")
        mesh.triangles = fread(fid, 2 * mesh.numtris, "int32").reshape([2, mesh.numtris], order="F")
    # Given input parameter `meshread2`
    elif meshread2:
        mesh.vertices = fread(fid, 3 * mesh.numverts, "double").reshape([3, mesh.numverts], order="F")
        mesh.triangles = fread(fid, 3 * mesh.numtris, "int32").reshape([3, mesh.numtris], order="F")
    # Given input parameter `meshread`
    else:
        # Loading mesh vertices and triangles
        mesh.vertices = fread(fid, 3 * mesh.numverts, "float32").reshape([3, mesh.numverts], order="F")
        mesh.triangles = fread(fid, 3 * mesh.numtris, "int32").reshape([3, mesh.numtris], order="F")

    # Return data
    return mesh

def load_meshobj(meshpath):
    with open(meshpath, "rb") as fid:
        meshobj = meshread(fid)
    return meshobj

def load_trimesh(meshpath):
    meshobj = load_meshobj(meshpath)
    # load the original ossicles
    idx = np.where(meshobj.orient != np.array((1,2,3)))
    for i in idx: meshobj.vertices[i] = (meshobj.dim[i] - 1).reshape((-1,1)) - meshobj.vertices[i]
    # check the results
    # writemesh(meshpath, meshobj, mirror)

    # Reflection Relative to YZ Plane (x):
    # if mirror:
    #     meshobj.vertices[0] = (meshobj.dim[0] - 1) - meshobj.vertices[0].T
    #     writemesh(meshpath, meshobj, mirror=mirror)

    meshobj.vertices = meshobj.vertices * meshobj.sz.reshape((-1, 1))
    mesh = trimesh.Trimesh(vertices=meshobj.vertices.T, faces=meshobj.triangles.T, process=False) # mesh.vertices = meshobj.vertices.T.astype(np.float32) # mesh.faces = meshobj.triangles.T.astype(np.float32)
    assert mesh.vertices.shape == meshobj.vertices.T.shape
    assert mesh.faces.shape == meshobj.triangles.T.shape
    return mesh

def writemesh(meshpath, output_path, mesh, mirror=False, suffix=''):
    """
    write mesh object to improvise, and keep the original meshobj.sz
    """
    meshobj = load_meshobj(meshpath)
    # the shape has to be 3 x N
    meshobj.vertices = mesh.vertices.T / meshobj.sz.reshape((-1, 1)) if mesh.vertices.shape[1]==3 else mesh.vertices / meshobj.sz.reshape((-1, 1))
    meshobj.orient = np.array((1, 2, 3), dtype="int32")

    name = output_path.stem
    if "centered" in name:
        name = '_'.join(name.split("_")[:-1])
    name += suffix

    if mirror:
        if 'left' in name: side = "right"
        elif "right" in name: side = "left"
        name = name.split("_")[0] + "_" + side + "_" + '_'.join(name.split("_")[2:-1])

    with open(output_path.parent / (name + ".mesh"), "wb") as f:
        f.write(meshobj.id.astype('int32'))
        f.write(meshobj.numverts.astype('int32'))
        f.write(meshobj.numtris.astype('int32'))
        f.write(np.int32(-1))
        f.write(meshobj.orient.astype('int32'))
        f.write(meshobj.dim.astype('int32'))
        f.write(meshobj.sz.astype('float32'))
        f.write(meshobj.color.astype('int32'))
        # ndarray need to be continuous!
        f.write(np.array(meshobj.vertices).astype("float32").tobytes(order='F'))
        f.write(meshobj.triangles.astype("int32").tobytes(order='F'))
        """
        # if hasattr(mesh, "opacity"):
        #     f.write(mesh.opacity.T)
        #     if hasattr(mesh, "colormap"):
        #         f.write(mesh.colormap.numcols.T)
        #         f.write(mesh.colormap.numverts.T)
        #         f.write(mesh.colormap.cols.T)
        #         f.write(mesh.colormap.vertexindexes.T.tobytes(order='C'))
        """

def color2binary_mask(color_mask):
    binary_mask = np.zeros(color_mask[...,:1].shape, dtype=np.uint8)
    x, y, _ = np.where(color_mask != [0., 0., 0.])
    binary_mask[x, y] = 1
    return binary_mask

def create_2d_3d_pairs(color_mask:np.ndarray, vertices:pv.pyvista_ndarray, binary_mask:np.ndarray=None):

    if binary_mask is None:
        binary_mask = color2binary_mask(color_mask)
        assert (binary_mask == (0.3*color_mask[..., :1] + 0.59*color_mask[..., 1:2] + 0.11*color_mask[..., 2:]).astype("bool").astype('uint8')).all()

    idx = np.where(binary_mask == 1)

    # swap the points for opencv, maybe because they handle RGB image differently (RGB -> BGR in opencv)
    idx = idx[:2][::-1]

    pts = np.stack((idx[0], idx[1]), axis=1)

    # Obtain the 3D verticies (normaize rgb values)
    rgb = color_mask[pts[:,1], pts[:,0]]
    if np.max(rgb) > 1: rgb = rgb / 255

    # denormalize to get the rgb value for vertices respectively
    r = de_normalize(rgb[:, 0], vertices[..., 0])
    g = de_normalize(rgb[:, 1], vertices[..., 1])
    b = de_normalize(rgb[:, 2], vertices[..., 2])
    vtx = np.stack([r, g, b], axis=1)

    return vtx, pts

def solve_epnp_cv2(pts2d, pts3d, camera_intrinsics):
    pts2d = pts2d.astype('float32')
    pts3d = pts3d.astype('float32')
    camera_intrinsics = camera_intrinsics.astype('float32')

    predicted_pose = np.eye(4)
    if pts2d.shape[0] > 4:
        # Use EPNP, inliers are the indices of the inliers
        success, rotation_vector, translation_vector, inliers = cv2.solvePnPRansac(pts3d, pts2d, camera_intrinsics, distCoeffs=np.zeros((4, 1)), confidence=0.999, flags=cv2.SOLVEPNP_EPNP)
        if success:
            coordinate_change = np.array([[-1, 0, 0], [0, -1, 0], [0, 0, 1]])
            predicted_pose[:3, :3] = coordinate_change @ cv2.Rodrigues(rotation_vector)[0]
            predicted_pose[:3, 3] = coordinate_change @ np.squeeze(translation_vector)
    return predicted_pose

def transform_vertices(vertices, transformation_matrix=np.eye(4)):

    ones = np.ones((vertices.shape[0], 1))
    homogeneous_vertices = np.append(vertices, ones, axis=1)
    transformed_vertices = (transformation_matrix @ homogeneous_vertices.T)[:3].T

    return transformed_vertices

def normalize(x):
    return (x - min(x)) / (max(x) - min(x))

def de_normalize(rgb, vertices):
    return rgb * (np.max(vertices) - np.min(vertices)) + np.min(vertices)

def color_mesh(vertices, color=''):
    if color == 'nocs':
        assert vertices.shape[1] == 3, "the vertices is suppose to be transposed"
        colors = copy.deepcopy(vertices)
        # normalize vertices and center it to 0
        colors[..., 0] = normalize(vertices[..., 0])
        colors[..., 1] = normalize(vertices[..., 1])
        colors[..., 2] = normalize(vertices[..., 2])
    elif color == 'latlon': colors = load_latitude_longitude()
    return colors

def save_image(array, folder, name):
    img = Image.fromarray(array)
    img.save(folder / name)

def mesh2ply(meshpath, output_path):
    mesh = load_trimesh(meshpath)
    ply_file = trimesh.exchange.ply.export_ply(mesh)
    with open(output_path, "wb") as fid:
        fid.write(ply_file)

def rigid_transform_3D(A, B):

    assert A.shape == B.shape

    # find mean
    centroid_A = np.mean(A, axis=0)
    centroid_B = np.mean(B, axis=0)

    # # ensure centroids are 3x1
    # centroid_A = centroid_A.reshape(-1, 1)
    # centroid_B = centroid_B.reshape(-1, 1)

    # subtract mean
    Am = A - centroid_A
    Bm = B - centroid_B

    H = Am.T @ Bm

    # sanity check
    #if linalg.matrix_rank(H) < 3:
    #    raise ValueError("rank of H = {}, expecting 3".format(linalg.matrix_rank(H)))

    # find rotation
    U, S, Vt = np.linalg.svd(H)
    R = Vt.T @ U.T

    # special reflection case
    if np.linalg.det(R) < 0:
        print("det(R) < R, reflection detected!, correcting for it ...")
        Vt[2,:] *= -1
        R = Vt.T @ U.T

    t = -R @ centroid_A + centroid_B
    # convert the shape from (1, 3) to (3, 1)
    t = t.reshape((-1,1))

    rt = np.vstack((np.hstack((R, t)), np.array([0,0,0,1])))

    return rt

def load_latitude_longitude():
    # get the latitude and longitude
    # latlon_map_path = pkg_resources.resource_filename('vision6D', 'data/ossiclesCoordinateMapping.json')
    with open(LATLON_PATH, "r") as f: data = json.load(f)

    latitude = np.array(data['latitude']).reshape((len(data['latitude'])), 1)
    longitude = np.array(data['longitude']).reshape((len(data['longitude'])), 1)
    placeholder = np.zeros((len(data['longitude']), 1))

    # set the latlon attribute
    latlon = np.hstack((latitude, longitude, placeholder))
    return latlon

def latLon2xyzv1(m,lat,lon,gx,gy):
    vert = np.array([0, 0, 0])
    for f in m.faces:
        lonf = lon[f]
        if np.sum(lonf==0)>0 and np.sum(lonf>=0.9)>0:
            lonf[lonf==0] = 1
        V = [[lat[f[1]] - lat[f[0]], lat[f[2]] - lat[f[0]]], [lonf[1] - lonf[0], lonf[2] - lonf[0]]]
        ab = np.linalg.pinv(V) @ (np.array([gx,gy]) - np.array([lat[f[0]], lonf[0]]))
        a = ab[0]
        b = ab[1]
        if a>=0 and b>=0 and a+b<=1:
            vert = np.array(m.vertices[f[0]] + a*(m.vertices[f[1]]-m.vertices[f[0]]) + b*(m.vertices[f[2]]-m.vertices[f[0]]))
            break
    return vert

def latLon2xyz(m,lat,lonf,msk,gx,gy):
    xyz = []
    class xyznode:
        def __init__(self, pnt, d):
            self.pnt=pnt
            self.d=d
        def __le__(self, rhs):
            return self.d <= rhs.d

    indx = np.where(
        (np.sum(lat[m.faces]>=gx,axis=1)>0)&(np.sum(lat[m.faces]<=gx,axis=1)>0)&msk&
        (np.sum(lonf>=gy,axis=1)>0)&(np.sum(lonf<=gy,axis=1)>0))[0]
    if len(indx)==0:
        indx = [np.argmin(np.min((lat[m.faces]-gx)*(lat[m.faces]-gx) + (lonf-gy)*(lonf-gy), axis=1))]

    for ind in indx:
        f = m.faces[ind]
        V = np.array([[lat[f[1]] - lat[f[0]],lat[f[2]] - lat[f[0]]],
                        [lonf[ind,1] - lonf[ind,0],lonf[ind,2] - lonf[ind,0]]])##T?
        ab = np.linalg.pinv(V) @ (np.array([gx,gy]) - np.array([lat[f[0]],lonf[ind,0]]))
        a = ab[0]
        b = ab[1]
        if a>=0 and b>=0 and a + b<=1:
            xyz.append(xyznode(m.vertices[f[0]] + a * (m.vertices[f[1]] - m.vertices[f[0]]) + b * (m.vertices[f[2]] - m.vertices[f[0]]),
                        np.sum((np.array([lat[f[0]], lonf[ind,0]]) + V@ab - np.array([gx,gy]))**2)))
        else:
            c = V[:,0] @ (np.array([gx,gy]) - np.array([lat[f[0]],lonf[ind,0]]))/(np.linalg.norm(V[:,0])**2)
            d = V[:,1] @ (np.array([gx,gy]) - np.array([lat[f[0]],lonf[ind,0]])) / (np.linalg.norm(V[:,1])**2)
            v2 = np.array([lat[f[2]] - lat[f[1]], lonf[ind,2] - lonf[ind,1]])
            e = v2 @ (np.array([gx,gy]) - np.array([lat[f[1]],lonf[ind,1]])) / (np.linalg.norm(v2)**2)
            c = np.clip(c,0,1)
            d = np.clip(d,0,1)
            e = np.clip(e,0,1)
            p1 = c*V[:,0] + np.array([lat[f[0]],lonf[ind,0]])
            p2 = d*V[:,1] + np.array([lat[f[0]],lonf[ind,0]])
            p3 = e*v2     + np.array([lat[f[1]],lonf[ind,1]])
            d1 = np.sum((p1 - np.array([gx,gy]))**2)
            d2 = np.sum((p2 - np.array([gx,gy]))**2)
            d3 = np.sum((p3 - np.array([gx,gy]))**2)
            if d1 < d2 and d1<d3:
                xyz.append(xyznode(m.vertices[f[0]] + c * (m.vertices[f[1]] - m.vertices[f[0]]),d1))
            elif d2 < d3:
                xyz.append(xyznode(m.vertices[f[0]] + d * (m.vertices[f[2]] - m.vertices[f[0]]),d2))
            else:
                xyz.append(xyznode(m.vertices[f[1]] + e * (m.vertices[f[2]] - m.vertices[f[1]]),d3))
    return np.min(xyz).pnt

def get_image_actor_scalars(actor):
    input = actor.GetMapper().GetInput()
    shape = input.GetDimensions()[::-1]
    point_data = input.GetPointData().GetScalars()
    point_array = vtknp.vtk_to_numpy(point_data)
    if len(point_array.shape) == 1: point_array = point_array.reshape(*point_array.shape, 1)
    scalars = point_array.reshape(*shape[1:], point_array.shape[-1])
    # Due to the different coordinate system, we need to flip the image
    scalars = np.flipud(scalars)
    scalars = np.fliplr(scalars)
    return scalars

def get_mask_actor_points(actor):
    input = actor.GetMapper().GetInput()
    point_data = input.GetPoints().GetData()
    points_array = vtknp.vtk_to_numpy(point_data)
    vtk_matrix = actor.GetMatrix()
    matrix = np.array([[vtk_matrix.GetElement(i, j) for j in range(4)] for i in range(4)])
    # Calculate points not with homogeneous form
    points = (matrix[:3, :3] @ points_array.T).T + matrix[:3, 3:].T
    # Calculate points with homogeneous coordinates
    homogeneous_points = np.hstack((points_array, np.ones((points_array.shape[0], 1))))
    transformed_points = ((matrix @ homogeneous_points.T).T)[:, :3]
    assert np.isclose(transformed_points, points).all(), "points and transformed_points should be very very close!"
    return transformed_points

def get_bbox_actor_points(actor, image_center):
    input = actor.GetMapper().GetInput()
    point_data = input.GetPoints().GetData()
    points_array = vtknp.vtk_to_numpy(point_data)
    vtk_matrix = actor.GetMatrix()
    matrix = np.array([[vtk_matrix.GetElement(i, j) for j in range(4)] for i in range(4)])
    # Calculate points not with homogeneous form
    points = (matrix[:3, :3] @ points_array.T).T + matrix[:3, 3:].T
    # Calculate points with homogeneous coordinates
    homogeneous_points = np.hstack((points_array, np.ones((points_array.shape[0], 1))))
    transformed_points = ((matrix @ homogeneous_points.T).T)[:, :3]
    assert np.isclose(transformed_points, points).all(), "points and transformed_points should be very very close!"
    points = image_center - points
    return points

def get_mesh_actor_vertices_faces(actor):
    input = actor.GetMapper().GetInput()
    points = input.GetPoints().GetData()
    cells = input.GetPolys().GetData()
    vertices = vtknp.vtk_to_numpy(points)
    """
    # popular presentation
    Triangle 1: (0, 1, 2)
    Triangle 2: (3, 4, 5)
    Triangle 3: (6, 7, 8)
    Triangle 4: (9, 10, 11)

    # When PyVista converts this mesh into a vtkPolyData object, the faces are represented as a list of vertex indices and the number of vertices in each face:
    Face 1: (3, 0, 1, 2)
    Face 2: (3, 3, 4, 5)
    Face 3: (3, 6, 7, 8)
    Face 4: (3, 9, 10, 11)
    """
    faces = vtknp.vtk_to_numpy(cells).reshape((-1, 4))
    faces = faces[:, 1:] # trim the first element in each row
    return vertices, faces

def get_mesh_actor_scalars(actor):
    input = actor.GetMapper().GetInput()
    point_data = input.GetPointData()
    scalars = point_data.GetScalars()
    if scalars: scalars = vtknp.vtk_to_numpy(scalars)
    return scalars

def create_render(w, h):
    render = pv.Plotter(window_size=[w, h], lighting=None, off_screen=True)
    render.set_background('black')
    assert render.background_color == "black", "render's background need to be black"
    return render

# Calculate the rotation error
def angler_distance(R_a, R_b):
    R_diff = np.dot(R_a, R_b.T)
    angle_diff_rad = np.arccos(np.clip((np.trace(R_diff) - 1) / 2, -1, 1))
    angle_diff_deg = np.degrees(angle_diff_rad)
    return angle_diff_deg

def reset_vtk_lut(colormap):
    if isinstance(colormap, str):
        color_num = 256
        viridis_cm = plt.get_cmap(colormap, color_num)
        colors = viridis_cm(np.arange(color_num))
    else:
        colors = colormap
        color_num = len(colors)
    lut = vtk.vtkLookupTable()
    lut.SetNumberOfTableValues(color_num)
    lut.Build()
    for i, color in enumerate(colors): lut.SetTableValue(i, color[0], color[1], color[2], 1.0)  # Last value is alpha (opacity)
    return lut

def display_warning(message):
    QtWidgets.QMessageBox.warning(QtWidgets.QMainWindow(), "vision6D", message, QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
    return 0


from distutils.core import setup
from setuptools import find_packages

#  Get requirements from requirements.txt file
#  'pip freeze > requirements.txt' will create the requirements file.
with open('requirements.txt') as f:
    install_requires = f.read().splitlines()

setup(
    name='aipy',
    version='0.0.1',
    license='MIT',
    author='Sean MacPherson',
    description='A Python Artificial Intelligence library.',
    packages=find_packages(),
    install_requires=install_requires,
)


import requests
from urllib.parse import urlparse, urlunparse
from urllib3.exceptions import ConnectTimeoutError, ConnectionError, \
    InvalidHeader, MaxRetryError, NewConnectionError, TimeoutError, \
    ReadTimeoutError, InsecureRequestWarning
from urllib3 import disable_warnings
from socket import timeout as socketTimeout, gaierror
disable_warnings(InsecureRequestWarning)

class Service():
    """
    The Xcalar Api service object is a collection of utilities for detecting the state of
    Xcalar software services.

    To obtain a Service instance:
        >>> from xcalar.external.service import Service
        >>> service = Service("base_url"="https://cluster_node4.domain/")

    **Initializer Arguments**

    The Xcalar Api Service must be called with the following arguments:

    * **base_url** (:class:`str`) - Url for a cluster node where Xcalar is running

    **Atttributes**

    None.

    **Methods**

    These are the available methods:

    * :meth:`node_status`

    """

    def __init__(self, base_url=None):
        """
        Object to evaluate Xcalar service status

        :param base_url: Url to a Xcalar node, like "https://my-xalar-node"

        :raises ValueError: if no base_url is provided
        """
        self._base_url = base_url
        if (self._base_url is None):
            raise ValueError("A base node url must be provided!")

    def node_status(self, time_out=5):
        """
        This method returns a dictionary showing the list of Xcalar services that
        respond to requests on a cluster node and an overall status.

        Example:
            >>> from xcalar.external.service import Service
            >>> node = Service('https://my-node:8443')
            >>> status = node.node_status()
            >>> status
            { 'total_services': 5, 'services': { 'caddy': True, 'expServer': True,
            'usrnode': True, 'mgmtd': True, 'sqldf': True }, 'status': "up" }

        :param time_out: the number of seconds a REST http request will wait
                         before timing out

        :returns: a structure describing the state of cluster services
        :return_type: :obj:`dict`

        * :Response Stucture:
            * (*dict*)
                * **total_services** (*int*) - total number of Xcalar node services
                * **services** (*dict*) - A dictionary of node services and a boolean \
                                          describing their current availability: True is up \
                                          and False is down.  The number of keys should \
                                          equal total_services.
                * **status** (*str*) - One of three stings: 'up' means all services responded, \
                                       'down' means that no services responded, 'partial' means \
                                       that n services responded where 0 < n < total_services
        """

        def poll_service(parsed_url, service, service_paths, check_struct,
                         service_result):
            service_url = parsed_url
            service_url = service_url._replace(path=service_paths[service])
            is_running = 0

            try:
                service_resp = \
                    requests.get(urlunparse(service_url),
                                 verify=False, timeout=time_out)
            except (ConnectTimeoutError, ConnectionError, InvalidHeader,
                    MaxRetryError, NewConnectionError, TimeoutError,
                    ConnectionRefusedError, ConnectionResetError,
                    ConnectionAbortedError, socketTimeout, gaierror,
                    ReadTimeoutError, requests.ReadTimeout,
                    requests.ConnectionError) as e:
                return is_running

            if not check_struct and service_resp.status_code == 200:
                service_result['services'][service] = True
                is_running = 1

            if check_struct and service_resp.status_code == 200 and \
               service_resp.json()['status'] == "up":
                service_result['services'][service] = True
                is_running = 1

            return is_running

        result = {
            'services': {
                'caddy': False,
                'expServer': False,
                'usrnode': False,
                'mgmtd': False,
                'sqldf': False
            },
            'status': 'down'
        }

        paths_by_service = {
            'caddy': '/healthCheck',
            'expServer': '/app/service/healthCheck',
            'usrnode': '/app/service/healthCheckUsrnode',
            'mgmtd': '/app/service/healthCheckMgmtd',
            'sqldf': '/app/service/healthCheckSqldf'
        }

        self.parsed_url = urlparse(self._base_url)
        total_services = len(result['services'])
        running_services = 0

        running_services += \
            poll_service(self.parsed_url, 'caddy',
                         paths_by_service, False, result)

        if result['services']['caddy']:
            running_services += \
                    poll_service(self.parsed_url, 'expServer',
                                 paths_by_service, True, result)

        if result['services']['expServer']:
            for service in ['usrnode', 'mgmtd', 'sqldf']:
                running_services += \
                        poll_service(self.parsed_url, service,
                                     paths_by_service, True, result)

        if running_services == total_services:
            result['status'] = 'up'
        elif running_services > 0 and \
        running_services < total_services:
            result['status'] = 'partial'

        return result


import argparse

from Population import *
from Population_sandbox import *
from RotTable import *
from Traj3D import *

parser = argparse.ArgumentParser()
parser.add_argument("--filename", help="input filename of DNA sequence")
parser.parse_args()
args = parser.parse_args()

def main():

    rot_table = RotTable()
    traj = Traj3D()

    if args.filename:
        # Read file
        lineList = [line.rstrip('\n') for line in open("plasmid_8k.fasta")]
        # Formatting
        seq = ''.join(lineList[1:])
        traj.compute(seq, rot_table)
    else:
        traj.compute(
            "AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAAGGTTAAGTCAG",
            rot_table)
    print(traj.getTraj())

    if args.filename:
        traj.draw(args.filename + ".png")
    else:
        traj.draw("sample.png")

def main_2():
    iter_max = 30

    Pop = Population(
        "AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAAGGTTAAGTCAG")
    Pop.evolve(iter_max, "Tournoi")

def main_3():
    Pop = Population(
        "AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAAGGTTAAGTCAG")
    Pop.next_gen()

def draw_initial_seq(file_name):
    """ Permet de tracer le brin d'adn avec la table des angles originale à partir d'un fichier fasta."""
    rot_table = RotTable()
    traj = Traj3D()
    lineList = [line.rstrip('\n') for line in open(file_name)]
    seq = ''.join(lineList[1:])
    traj.compute(seq, rot_table)
    traj.draw("sample.png")

def draw_traited(
        file_name,
        scaling,
        methode_sele,
        nbiter,
        nbindiv,
        Luck,
        Puiss):
    """ Permet de tracer le brain d'adn avec la table des angles optimisée à partir d'un fichier fasta, mais également la convergence au fil des générations"""
    lineList = [line.rstrip('\n') for line in open(file_name)]
    traj = Traj3D()
    seq = ''.join(lineList[1:])
    Pop = Population(seq, n=nbindiv)
    Pop.evolve(
        nbiter,
        scaling=scaling,
        selection_method=methode_sele,
        luck_prob=Luck,
        puissance=Puiss)
    traj.compute(seq, Pop._Get_Current_Best()[0])
    traj.draw("sample.png")

def test_draw_traited_2(file_name, methode_sele, nbiter, nbindiv):
    lineList = [line.rstrip('\n') for line in open(file_name)]
    seq = ''.join(lineList[1:])
    Pop = Population(seq, n=nbindiv)
    Pop.evolve(nbiter, selection_method=methode_sele)
    traj = Traj3D()
    traj.compute(seq, Pop._Get_Current_Best()[0])
    return traj

def main_4():
    lineList = [line.rstrip('\n') for line in open("./Data/plasmid_8k.fasta")]
    seq = ''.join(lineList[1:])
    pop_size = 20
    nb_gen = 4

    pop = Population(seq, pop_size)
    pop.evolve(nb_gen, selection_method="Tournoi", alpha=0.593879313130056)
    #best = pop._Get_Current_Best()
    #print("Meilleur score obtenu de",best[1],"avec l'individu :\n")
    # print(best[0])

def main_5():
    lineList = [line.rstrip('\n') for line in open("./Data/plasmid_8k.fasta")]
    seq = ''.join(lineList[1:])
    pop = Population(seq)
    pop.eval_pop()
    print(pop._Get_pop())
    pop.eval_pop()
    print(pop._Get_pop())
    pop.eval_pop()
    print(pop._Get_pop())

def main_6():
    lineList = [line.rstrip('\n') for line in open("./Data/plasmid_8k.fasta")]
    seq = ''.join(lineList[1:])
    pop_size = 30
    nb_gen = 20

    pop = Population(
        "AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAAGGTTAAGTCAG",
        pop_size)
    pop.evolve_and_graph(
        nb_gen,
        scaling=False,
        alpha=0.593879313130056,
        selection_method="Tournoi")

def draw_seq():
    rot_table = {
        'AA': [
            35.60831497330928, 7.300914398651058, -154.0], 'AC': [
            35.02399069084545, 2.666893442212051, 143.0], 'AG': [
                26.2, 8.994736694729562, 2.0], 'AT': [
                    26.08456146107297, 7.648153845528422, 0.0], 'CC': [
                        33.70967753141159, 0.9148954541563099, -57.0], 'CG': [
                            30.820267576802113, 5.397768853723985, 0], 'GC': [
                                39.355615833563824, 4.617189422112741, 180.0], 'TA': [
                                    35.93130323359519, -0.23199257503017134, 0.0], 'TC': [
                                        37.6615370686879, 10.949138895925273, -120.0], 'TG': [
                                            34.817713024996905, 82.349600699326, 64.0]}
    lineList = [line.rstrip('\n') for line in open("./Data/plasmid_8k.fasta")]
    seq = ''.join(lineList[1:])
    traj = Traj3D()
    traj.compute(seq, RotTable(rot_dict=rot_table).Reconstitution())
    traj.draw("sample.png")

def main_sandbox():
    lineList = [line.rstrip('\n') for line in open("./Data/plasmid_8k.fasta")]
    seq = ''.join(lineList[1:])
    pop = Population_sandbox(seq,n=50)
    pop.evolve_double_graph(50, scaling=True)
    pop.dump_n_bests(20)

if __name__ == "__main__":
    # draw_seq()
    main_sandbox()


from os import system
from pathlib import Path

homeDirectory = Path.home()
mainAppsPath = '/Applications'
homeAppsPath = homeDirectory / 'Applications'

# get the files
listOfHomeApps = Path(homeAppsPath).rglob('*.app')
listOfMainApps = Path(mainAppsPath).glob('*.app')

# terminal colors
class TermColors:
    red = '\033[31m'
    green = '\033[32m'
    white = '\033[37m'

# add soft links from ~/Applications to /Applications
if listOfHomeApps:
    print('Linking any apps that do not exist in the main app directory...')
    for app in listOfHomeApps:
        # see if link exists
        link = Path(mainAppsPath) / app.name
        linkExist = Path(link).exists()

        if linkExist:
            print(TermColors.white + '\t"' + link.name + '" exists')
        else:
            print(TermColors.green + '\tlinking "' + app.name + '" to /Applications')
            # make soft link
            source = str(app.parent / app.name)
            destination = str(Path(mainAppsPath) / app.name)
            system('ln -s "' + source + '" "' + destination + '"')
    print(TermColors.white + 'Done!')

else:
    print("No apps were found in the home directory.")

# remove dead soft links from /Applications
print('Checking main Applications directory for dead links...')
for app in listOfMainApps:
    linkPath = Path(mainAppsPath) / app.name
    if linkPath.is_symlink():
        linkSource = Path(linkPath).readlink()
        sourceExist = Path(linkSource).exists()
        if sourceExist:
            print(TermColors.white + '\t"' + str(linkSource) + '" is alive!')
        else:
            print(TermColors.red + '\t"' + str(linkSource) + '" is dead...deleting...')
            system('rm -f "' + str(Path(mainAppsPath) / app.name) + '"')
print(TermColors.white + 'Done!')
print('Exiting...')


from websocket_server import WebsocketServer
import json
from multiprocessing import Manager
from threading import Thread

from judger import Judger, JudgeResult
from exceptions import JudgeServiceError

class JudgeServer(object):
    def __init__(self):
        self.server = WebsocketServer(host='0.0.0.0', port=8080)
        self.server.set_fn_new_client(self.new_client)
        self.server.set_fn_client_left(self.client_left)
        self.server.set_fn_message_received(self.task_received)

    def start(self):
        self.server.run_forever()

    @staticmethod
    def new_client(client, _server):
        print("New client connected and was given id %d" % client['id'])

    @staticmethod
    def client_left(client, _server):
        print("Client(%d) disconnected" % client['id'])

    def task_received(self, client, _server, message):
        try:
            task = json.loads(message)
        except json.decoder.JSONDecodeError:
            return
        result_queue = Manager().Queue()
        Thread(target=self.feedback, args=(client, result_queue)).start()
        try:
            Judger(task_id=task['task_id'],
                   case_id=task['case_id'],
                   case_conf=task['case_config'],
                   result_queue=result_queue
                   ).judge(task['code'],
                           task['lang'],
                           task['limit'])
        except JudgeServiceError as e:
            result_queue.put(Judger.make_report(
                status=JudgeResult.SYSTEM_ERROR,
                score=0,
                max_time=0,
                max_memory=0,
                log=str(e),
                detail=[]
            ))
        result_queue.put(None)

    def feedback(self, client, queue):
        while True:
            item = queue.get()
            if item is None:
                break
            data = json.dumps(item)
            self.server.send_message(client, data)

server = JudgeServer()
server.start()


from keras.preprocessing.image import img_to_array, list_pictures, load_img, array_to_img
import cv2
import random
import numpy as np
from PIL import Image
import os
import glob

sendsize = 700
sendimg = int(sendsize/3)
row = 256
col = 256
noise_amount = 0.12

min_table = 50
max_table = 205
diff_table = max_table - min_table

LUT_HC = np.arange(256, dtype='uint8')
LUT_LC = np.arange(256, dtype='uint8')

# ハイコントラストLUT作成
for i in range(0, min_table):
    LUT_HC[i] = 0
for i in range(min_table, max_table):
    LUT_HC[i] = 255 * (i - min_table) / diff_table
for i in range(max_table, 255):
    LUT_HC[i] = 255

# ローコントラストLUT作成
for i in range(256):
    LUT_LC[i] = min_table + i * (diff_table) / 255

def makeresize(file_name, extension):
    img = cv2.imread(file_name+extension)
    madeimg = cv2.resize(img, dsize=(row, col))

    cv2.imwrite(file_name+"_resize.bmp", madeimg)

def makenoise(file_name, extension):
    img = cv2.imread(file_name+extension)
    madeimg = cv2.resize(img, dsize=(row, col))

    ind = list(range(sendimg+1, row*col-sendimg*2, sendimg))
    randomindex = random.sample(range(0, len(ind)), int(len(ind)*noise_amount))
    ind = [ind[i] for i in randomindex]

    for i in ind:
        # print(i)
        for j in range(sendimg):
            madeimg[(i+j)//row][(i+j) % col] = [0, 0, 0]
    cv2.imwrite(file_name+"_noise.bmp", madeimg)

def makerotate(file_name, extension):
    img = cv2.imread(file_name+extension)
    madeimg = cv2.resize(img, dsize=(row, col))
    p90img = madeimg.transpose(1, 0, 2)[:, ::-1]  # +90度
    m90img = madeimg.transpose(1, 0, 2)[::-1]  # -90度

    cv2.imwrite(file_name+"_p90.bmp", p90img)
    cv2.imwrite(file_name+"_m90.bmp", m90img)

def makecontrast(file_name, extension):
    img = cv2.imread(file_name+extension)
    madeimg = cv2.resize(img, dsize=(row, col))

    high_cont_img = cv2.LUT(madeimg, LUT_HC)
    low_cont_img = cv2.LUT(madeimg, LUT_LC)
    cv2.imwrite(file_name+"_highcont.bmp", high_cont_img)
    cv2.imwrite(file_name+"_lowcont.bmp", low_cont_img)

if __name__ == '__main__':
    files = glob.glob('./exp/*/*/*/*.JPG')

    for f in files:
        print(f)
        ftitle, text = os.path.splitext(f)
        makeresize(ftitle, text)
        makenoise(ftitle, text)
        makerotate(ftitle, text)
        makecontrast(ftitle, text)
        os.remove(f)


import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

build_exe_options = {
    "packages": ["pkg_resources","os","sys", "lxml","xmlrpclib", "collections", "scrapy","zope.interface"],
    "excludes":['collections.abc'],
    "include_msvcr":True,
    "namespace_packages": ['zope'],
    "include_files": [
        ("C:\\Users\\ramdani\\scraptop\\scrapy.cfg","scrapy.cfg"),
        ("C:\\Users\\ramdani\\scraptop\\env\\Lib\\site-packages\\Scrapy\\VERSION","VERSION"),
        ("C:\\Users\\ramdani\\scraptop\\env\\Lib\\site-packages\\Scrapy\\mime.types","mime.types")
    ],
    "includes": ["pkg_resources", "os", "Flask", "twisted", "SQLAlchemy","scrapy", 'zope', 'zope.interface', 'pkgutil', 'lxml',
                         'lxml._elementpath', 'email.mime.multipart', 'email.mime.text',
                         ],
    }

executables = [
    Executable('main.py', base=base)
]

setup(name='Scraptop',
      version='0.1',
      description='Scraping Tokopedia',
      options = {"build_exe": build_exe_options},
      executables=executables
      )


from blueman.main.Config import Config
from blueman.Functions import *
from blueman.Constants import *

from gi.repository import Gtk

class GsmSettings(Gtk.Dialog):
    def __init__(self, bd_address):
        GObject.GObject.__init__(self)

        self.device = bd_address

        self.Builder = Gtk.Builder()
        self.Builder.set_translation_domain("blueman")
        self.Builder.add_from_file(UI_PATH + "/gsm-settings.ui")

        vbox = self.Builder.get_object("vbox1")

        self.config = Config("gsm_settings/" + bd_address)
        self.props.icon_name = "network-wireless"
        self.props.title = _("GSM Settings")

        self.props.resizable = False

        a = self.get_content_area()
        a.pack_start(vbox, True, True, 0)
        vbox.show()

        self.e_apn = self.Builder.get_object("e_apn")
        self.e_number = self.Builder.get_object("e_number")

        if self.config.props.apn == None:
            self.config.props.apn = ""

        if self.config.props.number == None:
            self.config.props.number = "*99#"

        self.e_apn.props.text = self.config.props.apn
        self.e_number.props.text = self.config.props.number

        self.e_apn.connect("changed", self.on_changed)
        self.e_number.connect("changed", self.on_changed)

        self.add_button("_Close", Gtk.ResponseType.CLOSE)

    def on_changed(self, e):
        if e == self.e_apn:
            self.config.props.apn = e.props.text
        elif e == self.e_number:
            self.config.props.number = e.props.text


import ply.lex as lex
import re

tokens = (
    "LEVANTAR",
    "POUSAR",
    "MOEDA",
    "NUMERO",
    "ABORTAR",
    )

t_LEVANTAR = r"LEVANTAR"
t_POUSAR = r"POUSAR"
t_ABORTAR = r"ABORTAR"

saldo = 0

estado = 0

def t_MOEDA(t):
    r"MOEDA\s((\d+[c|e][,|\.]\s?)+)"
    match = re.match(r"MOEDA\s((\d+[c|e][,|\.]\s?)+)",t.value)
    t.value = match.group(1)
    return t

def t_NUMERO(t):
    r"T=(00\d*|\d{9}\b)"
    match = re.match(r"T=(00\d*|\d{9}\b)",t.value)
    t.value = match.group(1)
    return t

def t_error(t):
    print("ERRO")
    t.lexer.skip(1)

def t_whitespace(t):
    r"\s+"
    pass

def calcSaldo():
    global saldo
    euros = str(int(saldo/100))
    centimos = str(saldo)[-2:]
    string = euros+"e"+centimos+"c"
    return string

def parseMoedas(moedas):
    global saldo
    validas = ['10c', '20c', '50c', '1e', '2e']

    valores = re.findall(r'\d+[c|e]',moedas)
    for valor in valores:
        if valor in validas:
            tipo = valor[-1:]
            valor = int(valor[:-1])
            if tipo == 'e':
                saldo += valor * 100
            elif tipo == 'c':
                saldo += valor
        else:
            print("maq: " + valor + " - moeda inválida")
    print("maq: saldo = " + calcSaldo())

def parseNumero(numero):
    global saldo

    if(numero[:3]=="601" or numero[:3]=="641"):
        print("maq: Esse número não é permitido neste telefone. Queira discar novo número!")

    elif(numero[:2]=="00"):
        if (saldo > 150):
            saldo -= 150
            print("maq: saldo = " + calcSaldo())
        else:
            print("maq: Saldo insuficiente para efetuar a chamada")

    elif(numero[:1]=="2"):
        if (saldo > 25):
            saldo -= 25
            print("maq: saldo = " + calcSaldo())
        else:
            print("maq: Saldo insuficiente para efetuar a chamada")

    elif(numero[:3]=="800"):
        print("maq: saldo = " + calcSaldo())

    elif(numero[:3]=="808"):
        if(saldo > 10):
            saldo -= 10
            print("maq: saldo = " + calcSaldo())
        else:
            print("maq: Saldo insuficiente para efetuar a chamada")
    else: print("maq: Contacto inválido")

def parse(token):
    global estado

    if (token.type == "LEVANTAR"):
        if(estado == 0):
            estado = 1
            print("maq: Introduza moedas.")
        else:
            print("maq: O telefone já se encontra levantado")

    elif (token.type == "POUSAR"):
        if(estado == 1):
            saldoTotal = calcSaldo()
            print("maq: Troco =" + saldoTotal + "; Volte sempre!")
        else: print("maq: O telefone já se encontra pousado.")

    elif(token.type == "MOEDA"):
        if(estado == 0):
            print("maq: O telefone está pousado.")
        else:
            parseMoedas(token.value)

    elif(token.type == "NUMERO"):
        if(estado == 0):
            print("maq: O telefone está pousado.")
        else: parseNumero(token.value)

    elif (token.type == "ABORTAR"):
        estado = 2
    else:
        print("Erro no input")

lexer = lex.lex()

while(True):
    line=input(">> ")
    lexer.input(line)
    for token in lexer:
        parse(token)
        if(estado==2):
            break


from typing import List

# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

# 比较暴力的方法，不会超时

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        def merge(list1, list2):
            """合并两个链表"""
            if list1.val is None:
                return list2
            elif list2.val is None:
                return list1
            head = list1
            pre_list1 = None
            # 比较两个数组
            while list1 and list2:
                if list1.val < list2.val:
                    pre_list1 = list1
                    list1 = list1.next
                else:
                    if pre_list1 is None:
                        head = list2
                        list2 = list2.next
                        head.next = list1
                        pre_list1 = head
                    else:
                        temp = list2
                        list2 = list2.next
                        pre_list1.next = temp
                        temp.next = list1
                        pre_list1 = temp
            if list2:
                pre_list1.next = list2
            return head

        # 去掉列表中的空链表
        index_none = []
        for i, list_ in enumerate(lists):
            if list_ is None:
                index_none.append(i)
        temp = 0
        for index in index_none:
            index -= temp
            lists.pop(index)
            temp += 1

        if len(lists) == 0:
            return
        list1 = lists[0]
        for list_ in lists[1:]:
            list1 = merge(list1, list_)
        return list1

if __name__ == '__main__':
    input = []
    head = ListNode(1)
    head.next = ListNode(4)
    head.next.next = ListNode(5)
    input.append(head)
    head = ListNode(1)
    head.next = ListNode(3)
    head.next.next = ListNode(4)
    input.append(head)
    Solution().mergeKLists(input)


# -*- coding: utf-8 -*-
"""
Created on Thu Aug 23 13:33:38 2018

@author: denisse.perez
"""
from werkzeug.utils import secure_filename

#from app import app
import pandas as pd
from flask import render_template, request, Flask
import os

import xlrd

app = Flask(__name__)

#@app.route('/')
@app.route('/', methods = ['GET', 'POST'])
def index():
    try:
        try:
            file = request.files['file']
            #filename = secure_filename(file.filename)
            #print(filename)
            file.save(os.path.join(app.root_path,"../files/Input.xlsx"))
        except Exception as e:
            print(e)
        base = pd.read_excel(os.path.join(app.root_path,"../files/Input.xlsx"), sheet_name="Base", index_col=False)
        activity_type = base['Activity Type']
        activity_name = base['Activity Name']
        portfolio = base['Portfolio']
        base['MEDIA COST'] = round(base['MEDIA COST'], 2)

        # Gold Activities (First Matrice's row)

        GC = base.loc[(activity_type == 'GOLD') & (portfolio == 'Core') & (activity_name != 'AON') & (
                    activity_name != 'E-Commerce')]
        gold_cores = pd.DataFrame
        gold_cores = {'Activity': GC['Key'], 'Media Cost': GC['MEDIA COST'], 'iTO': GC['iTO Euros']}
        gold_cores = (pd.DataFrame(gold_cores)).reset_index()
        gold_cores.index = gold_cores.index + 1
        gold_cores = gold_cores.drop(gold_cores.columns[0], axis=1)

        GFC = base.loc[(activity_type == 'GOLD') & (portfolio == 'Future Core')]
        gold_FutureCores = pd.DataFrame
        gold_FutureCores = {'Activity': GFC['Key'], 'Media Cost': GFC['MEDIA COST'],
                            'iTO': GFC['iTO Euros']}
        gold_FutureCores = (pd.DataFrame(gold_FutureCores)).reset_index()
        gold_FutureCores.index = gold_FutureCores.index + 1
        gold_FutureCores = gold_FutureCores.drop(gold_FutureCores.columns[0], axis=1)

        GS = base.loc[(activity_type == 'GOLD') & (portfolio == 'Supporters')]
        gold_supporter = pd.DataFrame
        gold_supporter = {'Activity': GS['Key'], 'Media Cost': GS['MEDIA COST'],
                          'iTO': GS['iTO Euros']}
        gold_supporter = (pd.DataFrame(gold_supporter)).reset_index()
        gold_supporter.index = gold_supporter.index + 1
        gold_supporter = gold_supporter.drop(gold_supporter.columns[0], axis=1)

        # Silver Activities (Second Matrice's row)

        SC = base.loc[(activity_type == 'SILVER') & (portfolio == 'Core') & (activity_name != 'AON') & (
                    activity_name != 'E-Commerce')]
        silver_cores = pd.DataFrame
        silver_cores = {'Activity': SC['Key'], 'Media Cost': SC['MEDIA COST'], 'iTO': SC['iTO Euros']}
        silver_cores = (pd.DataFrame(silver_cores)).reset_index()
        silver_cores.index = silver_cores.index + 1
        silver_cores = silver_cores.drop(silver_cores.columns[0], axis=1)

        SFC = base.loc[(activity_type == 'SILVER') & (portfolio == 'Future Core')]
        silver_FutureCores = pd.DataFrame
        silver_FutureCores = {'Activity': SFC['Key'], 'Media Cost': SFC['MEDIA COST'],
                              'iTO': SFC['iTO Euros']}
        silver_FutureCores = (pd.DataFrame(silver_FutureCores)).reset_index()
        silver_FutureCores.index = silver_FutureCores.index + 1
        silver_FutureCores = silver_FutureCores.drop(silver_FutureCores.columns[0], axis=1)

        SS = base.loc[(activity_type == 'SILVER') & (portfolio == 'Supporters')]
        silver_supporter = pd.DataFrame
        silver_supporter = {'Activity': SS['Key'], 'Media Cost': SS['MEDIA COST'],
                            'iTO': SS['iTO Euros']}
        silver_supporter = (pd.DataFrame(silver_supporter)).reset_index()
        silver_supporter.index = silver_supporter.index + 1
        silver_supporter = silver_supporter.drop(silver_supporter.columns[0], axis=1)

        # Bronze Activities (Third Matrice's row)

        BC = base.loc[(activity_type == 'BRONZE') & (portfolio == 'Core') & (activity_name != 'AON') & (
                    activity_name != 'E-Commerce')]
        bronze_cores = pd.DataFrame
        bronze_cores = {'Activity': BC['Key'], 'Media Cost': BC['MEDIA COST'], 'iTO': BC['iTO Euros']}
        bronze_cores = (pd.DataFrame(bronze_cores)).reset_index()
        bronze_cores.index = bronze_cores.index + 1
        bronze_cores = bronze_cores.drop(bronze_cores.columns[0], axis=1)

        BFC = base.loc[(activity_type == 'BRONZE') & (portfolio == 'Future Core') & (activity_name != 'AON') & (
                    activity_name != 'E-Commerce')]
        bronze_FutureCores = pd.DataFrame
        bronze_FutureCores = {'Activity': BFC['Key'], 'Media Cost': BFC['MEDIA COST'],
                              'iTO': BFC['iTO Euros']}
        bronze_FutureCores = (pd.DataFrame(bronze_FutureCores)).reset_index()
        bronze_FutureCores.index = bronze_FutureCores.index + 1
        bronze_FutureCores = bronze_FutureCores.drop(bronze_FutureCores.columns[0], axis=1)

        BS = base.loc[(activity_type == 'BRONZE') & (portfolio == 'Supporters')]
        bronze_supporter = pd.DataFrame
        bronze_supporter = {'Activity': BS['Key'], 'Media Cost': BS['MEDIA COST'],
                            'iTO': BS['iTO Euros']}
        bronze_supporter = (pd.DataFrame(bronze_supporter)).reset_index()
        bronze_supporter.index = bronze_supporter.index + 1
        bronze_supporter = bronze_supporter.drop(bronze_supporter.columns[0], axis=1)
        r = render_template('index.html', title='Home', gold_cores=gold_cores.to_html(),
                    gold_FutureCores=gold_FutureCores.to_html(), gold_supporter=gold_supporter.to_html(),
                    silver_cores=silver_cores.to_html(), silver_FutureCores=silver_FutureCores.to_html(),
                    silver_supporter=silver_supporter.to_html(),
                    bronze_cores=bronze_cores.to_html(), bronze_FutureCores=bronze_FutureCores.to_html(),
                    bronze_supporter=bronze_supporter.to_html())
   # #print(r)
    except Exception as e:
        r = render_template('index.html', title='Home')

    return r

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


#  xml  文件转化为 excel 文件

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re
import os
import string
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element, SubElement, ElementTree
from openpyxl.workbook import Workbook
# 颜色
from openpyxl.styles import  PatternFill
from openpyxl.styles import Color, Fill,Font,colors,Border,Side,Alignment
from openpyxl.cell import Cell

import string_xml_constants as SC
# import xlwt

# su_string_file_path=r'/Users/hehongqing/Downloads/supply_string_4.xlsx'
su_string_file_path=r'/Users/hehongqing/Downloads/supply_string_3.xlsx'

# 获取每个sheet
def getSheetWs(wb,sheet_title):
    if SC._supply_base_sheet_head_btn==sheet_title:
        ws = wb.worksheets[0]
        ws.title = sheet_title
    else:
        ws = wb.create_sheet(sheet_title)
    ws.append({1: SC._excel_title_value_key, 2:SC._excel_title_value_value, 3: SC._excel_title_value_en, 4: SC._excel_title_value_thai})

    currentRow=ws._current_row
    cellHorizontal='center'

    cell=ws['A'+str(currentRow)]
    aCellColor='d3d3d3'
    cell.alignment=Alignment(horizontal=cellHorizontal)
    cell.fill=PatternFill(fill_type='lightHorizontal',bgColor=aCellColor,fgColor=aCellColor)

    cell=ws['B'+str(currentRow)]
    bCellColor='fff0f5'
    cell.alignment=Alignment(horizontal=cellHorizontal)
    cell.fill=PatternFill(fill_type='lightHorizontal',bgColor=bCellColor,fgColor=bCellColor)

    cell=ws['C'+str(currentRow)]
    cCellColor='ffe4e1'
    cell.alignment=Alignment(horizontal=cellHorizontal)
    cell.fill=PatternFill(fill_type='lightHorizontal',bgColor=cCellColor,fgColor=cCellColor)

    cell=ws['D'+str(currentRow)]
    cell.alignment=Alignment(horizontal=cellHorizontal)
    dCellColor='ffc0cb'
    cell.fill=PatternFill(fill_type='lightHorizontal',bgColor=dCellColor,fgColor=dCellColor)
    return ws

def initExcel(path):
    wb = Workbook()
    fileName = path
    # 开始写入 excel
    return  wb, fileName

# ws= getOnlyWs(TYPE_SUPPLY_BASE_BTNS)
def xmlParse(zhPath, enPath,thaiPath,ws):
    zh_tree = ET.parse(zhPath)
    en_tree = ET.parse(enPath)
    thai_tree = ET.parse(thaiPath)
    # 中文 xml  解析 生成对应的 key 和 value
    for zh_elem in zh_tree.iter(tag='string'):
        zh_key = zh_elem.attrib['name']
        print('zh_key:      ' + str(zh_key))
        zh_value = zh_elem.text
        print('zh_value:    ' + str(zh_value))

        # 获取 key 对应的 en_value
        en_value=''
        for en_elem in en_tree.iter(tag='string'):
            en_key = en_elem.attrib['name']
            if en_key == zh_key:
                en_value = en_elem.text
                break

        # 获取 key 对应的 thai_value
        thai_value = ''
        for thai_elem in thai_tree.iter(tag='string'):
            thai_key = thai_elem.attrib['name']
            if thai_key == zh_key:
                thai_value = thai_elem.text
                break
        #  添加字符串到excel中
        ws.append([zh_key, zh_value, en_value, thai_value])
        # 如果en_value 字符为空，则认为该项没有翻译，进行颜色填充
        if en_value=='':
            currentRow=ws._current_row
            cell=ws['C'+str(currentRow)]
            enEmptyColor='dda0dd'
            cell.fill=PatternFill(fill_type='lightGray',bgColor=enEmptyColor,fgColor=enEmptyColor)
        # if thai_value == '' or  re.findall('%s',zh_value)==1:
        if not zh_value == None:
            if (zh_value.count('%s') > 0 and thai_value.count('%s') <= 0) or (zh_value.count('%d') > 0 and thai_value.count('%d') <= 0) or (zh_value.count('%1$s') > 0 and thai_value.count('%1$s') <= 0) or (thai_value == '') or (zh_value.count('\n')>0 and thai_value.count('\n')<=0):
                currentRow = ws._current_row
                cell = ws['D'+str(currentRow)]
                thaiEmptyColor = 'dda033'
                cell.fill = PatternFill(
                    fill_type='lightGray', bgColor=thaiEmptyColor, fgColor=thaiEmptyColor)
            # cell=ws['D'+str(currentRow+1)]
            # enEmptyColor='ff69b4'
            # cell.fill=PatternFill(fill_type='lightGray',bgColor=enEmptyColor,fgColor=enEmptyColor)

# 设置每个单元格的默认属性
def setCellProperty(worksheet):
    for i in range(1, worksheet.max_row+1):
        worksheet.row_dimensions[i].height=50
        for col in range(ord('A'),ord('E')):
            worksheet[chr(col)+str(i)].font=Font(size=14)
            worksheet[chr(col)+str(i)].alignment=Alignment(wrap_text=True)
            borderStype='thick'
            borderColor='556b2f'
            worksheet[chr(col)+str(i)].border=Border(left=Side(border_style=borderStype,color=borderColor),
            right=Side(border_style=borderStype,color=borderColor),
            top=Side(border_style=borderStype,color=borderColor),
            bottom=Side(border_style=borderStype,color=borderColor))

    worksheet.column_dimensions['A'].width=45
    worksheet.column_dimensions['B'].width=90
    worksheet.column_dimensions['C'].width=115
    worksheet.column_dimensions['D'].width=115

# 转义为excel
def transformToExcel():

    # 初始化excel 的必要参数
    wb, fileName = initExcel(su_string_file_path)
    ws=getSheetWs(wb,SC._supply_base_sheet_head_btn)
    # supplyBase
    xmlParse(SC._supplybase_zh_btns_path, SC._supplybase_en_btns_path,
             SC._supplybase_thai_btns_path,ws)
    setCellProperty(ws)

    ws=getSheetWs(wb,SC._supply_base_sheet_head_page)
    xmlParse(SC._supplybase_zh_pages_path,
             SC._supplybase_en_pages_path, SC._supplybase_thai_pages_path, ws)
    setCellProperty(ws)

    ws=getSheetWs(wb,SC._supply_base_sheet_head_msg)
    xmlParse(SC._supplybase_zh_msgs_path, SC._supplybase_en_msgs_path,
             SC._supplybase_thai_msgs_path, ws)
    setCellProperty(ws)

    # base
    ws=getSheetWs(wb,SC._base_sheet_head_btn)
    xmlParse(SC._base_zh_btns_path, SC._base_en_btns_path,
             SC._base_thai_btns_path, ws)
    setCellProperty(ws)

    ws=getSheetWs(wb,SC._base_sheet_head_page)
    xmlParse(SC._base_zh_pages_path, SC._base_en_pages_path,
             SC._base_thai_pages_path, ws)
    setCellProperty(ws)

    ws=getSheetWs(wb,SC._base_sheet_head_msg)
    xmlParse(SC._base_zh_msgs_path, SC._base_en_msgs_path,
             SC._base_thai_msgs_path, ws)
    setCellProperty(ws)

    # Buy
    ws=getSheetWs(wb,SC._buy_sheet_head_btn)
    xmlParse(SC._buy_zh_btns_path, SC._buy_en_btns_path,
             SC._buy_thai_btns_path, ws)
    setCellProperty(ws)

    ws=getSheetWs(wb,SC._buy_sheet_head_page)
    xmlParse(SC._buy_zh_pages_path, SC._buy_en_pages_path,
             SC._buy_thai_pages_path, ws)
    setCellProperty(ws)

    ws=getSheetWs(wb,SC._buy_sheet_head_msg)
    xmlParse(SC._buy_zh_msgs_path, SC._buy_en_msgs_path,
             SC._buy_thai_msgs_path, ws)
    setCellProperty(ws)

    # 在每个 ws 对象添加节点后对文件做保存操作，不然不会生效
    wb.save(fileName)
if __name__ == "__main__":
    transformToExcel()


from netCDF4 import *
import numpy as np
import numpy.ma as ma
import seawater as sw
import matplotlib.pyplot as plt
import datetime as dt
import os
import pandas as pd
from scipy import interpolate

ctd_data = Dataset('../data/oceanographic_data/GEOTRACES_IDP2017_v2/ctd_sensor_data/netcdf/GEOTRACES_IDP2017_v1_CTD_Sensor_Data.nc')

discrete_data = Dataset('../data/oceanographic_data/GEOTRACES_IDP2017_v2/discrete_sample_data/netcdf/GEOTRACES_IDP2017_v2_Discrete_Sample_Data.nc')

# getting variables from the discrete data
pressure_disc = discrete_data.variables['var1'][:]
temp_disc = discrete_data.variables['var7'][:]
salinity_disc = discrete_data.variables['var8'][:]
depth_disc = discrete_data.variables['var2'][:]

lon_geo_disc = discrete_data.variables['longitude']
lat_geo_disc = discrete_data.variables['latitude']

cruise_name_disc = discrete_data.variables['metavar1'][:]
station_name_disc = discrete_data.variables['metavar2'][:]

# calculate seawater density
density_disc = sw.pden(s=salinity_disc, t=temp_disc, p = pressure_disc)

## getting variables from the ctd data
pressure = ctd_data.variables['var1'][:]
temp = ctd_data.variables['var2'][:]
salinity = ctd_data.variables['var3'][:]
lon_geo = ctd_data.variables['longitude']
lat_geo = ctd_data.variables['latitude']

cruise_name = ctd_data.variables['metavar1'][:]
station_name = ctd_data.variables['metavar2'][:]

# calculate seawater density
density = sw.pden(s=salinity, t=temp, p = pressure)

def get_geo_names(geo_names_masked_array):

    ### extract names from the cruise name variable
    ### this function gets the string and decodes it and then appends to a list

    list_of_names = []
    for string_element in range(len(geo_names_masked_array)):
        blah = geo_names_masked_array[string_element]
        blank_str = ''
        for str_i in range(len(blah)):
            blank_str = blank_str + blah[str_i].decode()
        list_of_names.append(blank_str)

    return(list_of_names)

def get_mixed_layer_depth(density_nc):

    # gets the mixed layer depth from the ctd data

    mld_density_list = []
    # loop through each station
    for station in range(len(density_nc)):
        # get the density at 10 meters (the 9th index) and add 0.03
        mld_density_raw = density_nc[station][9]

        if not isinstance(mld_density_raw, np.float32):
            mld_density_raw = density_nc[station][10] + 0.03

        if not isinstance(mld_density_raw, np.float32):
            mld_density_raw = density_nc[station][8] + 0.03

        else:
            print('argh')

        mld_density = mld_density_raw + 0.03

        # add this density to the mld_density list
        mld_density_list.append(mld_density)

    # go through each station and through the depth profile
    depth_val = []
    depth_val_na = []
    for station_i in range(len(mld_density_list)):
        # the target density layer you are looking for the corresponding depth
        target_density = mld_density_list[station_i]
        # density profile at the given station
        den_0 = density[station_i]
        # go through the depth profile
        # for each density value, is this value less than the mld density?
        for density_value_at_depth in range(9, len(den_0)):
        #     if yes, continue to next metre density
            if den_0[density_value_at_depth] < target_density:
                continue

        #     if not stop and append the depth value
            elif den_0[density_value_at_depth] > target_density:
                depth_val.append(density_value_at_depth + 1)
                break

            else:
                depth_val.append('Na')
                depth_val_na.append(station_i)
                break
    return([depth_val,depth_val_na])

def get_month_from_geotraces(geotraces_ctd_data, ctd_or_disc = 'ctd'):

    ## gets the month associated with a date and time from the ctd data or from the discrete data

    # getting date time
    ctd_dates = geotraces_ctd_data.variables['date_time'][:].tolist()
    # the date_time var is Decimal Gregorian Days of the station	days since 2007-01-01 00:00:00 UTC
    if ctd_or_disc == 'ctd':
        first_sample_ref_date = dt.date(2007, 1, 1)
    if ctd_or_disc == 'disc':
        first_sample_ref_date = dt.date(6, 1, 1)

    geotraces_months = []
    for date_i in range(len(ctd_dates)):
        target_date = first_sample_ref_date + dt.timedelta(days=ctd_dates[date_i])
        geotraces_months.append(target_date.month)

    return(geotraces_months)

def discrete_data_mld(density_profile, depth_profile):

    ## gets mixed layer depth from the discrete data

    ## linear interpolation of density from density profile
    ## quality control that two data points must be above 25 meters
    ## from linear interpolation calculate the density at 10m
    ## figure out the depth at density 10m + 0.03 rho
    ## return MLD per station

    mld_depths = []

    for profile_i in range(len(density_profile)):

        density_profile_i = density_profile[profile_i]
        depth_profile_i = depth_profile[profile_i]

        ## check that there are at least two density measurements above 25m
        # print(depth_profile_i  < 25)
#         print(profile_i)
        if (depth_profile_i[depth_profile_i < 25].count() < 3) or (density_profile_i.count() < 3):
            mld_depths.append('NA')
            continue

        # making the surface density equal to the least dense water
        append_depth = ma.append(depth_profile_i, ma.masked_values([0.01], 0))
        append_density = ma.append(density_profile_i, ma.masked_values([density_profile_i.min()], 0))

        f = interpolate.interp1d(append_depth, append_density)
        rho_at_ten = f(10) + 0.03

        if rho_at_ten > density_profile_i.max():
            mld_depths.append('NA')
            continue

        f2 = interpolate.interp1d(append_density, append_depth)
        mld_output = f2(rho_at_ten)
        mld_depths.append(mld_output.item(0))

    return(mld_depths)

geo_names_formatted_disc = get_geo_names(ma.getdata(cruise_name_disc))
geo_station_names_formatted_disc = get_geo_names(ma.getdata(station_name_disc))

geo_names_formatted = get_geo_names(ma.getdata(cruise_name))
geo_station_names_formatted = get_geo_names(ma.getdata(station_name))

mld_disc = discrete_data_mld(density_profile=density_disc, depth_profile=depth_disc)
geotraces_months_disc = get_month_from_geotraces(geotraces_ctd_data=discrete_data, ctd_or_disc='disc')

mld = get_mixed_layer_depth(density_nc=density)
geotraces_months = get_month_from_geotraces(geotraces_ctd_data=ctd_data, ctd_or_disc ='ctd')

base_dir = '../data/oceanographic_data/ocean_colour_data/'
file_list = os.listdir(base_dir)
par_file_list = ["PAR" in i for i in file_list]
k_file_list = ["490" in i for i in file_list]

month_order_1 = ['2','7','11','5','10','4','12','9','6','3','1','8']
month_order_3 = ['12','1','4','7','5','11','3','8','6','10','9','2']

def get_nc_list(file_list):

    list_of_par_nc = []
    list_of_k_nc = []
    k_file_list_names = []
    par_file_list_names = []

    for un_file in range(len(file_list)):
        print(file_list[un_file])

        if par_file_list[un_file]:
            nc_temp = Dataset(base_dir + file_list[un_file])
            list_of_par_nc.append(nc_temp)
            par_file_list_names.append(file_list[un_file])

        if k_file_list[un_file]:
            nc_temp = Dataset(base_dir + file_list[un_file])
            list_of_k_nc.append(nc_temp)
            k_file_list_names.append(file_list[un_file])

    return([list_of_par_nc, par_file_list_names, list_of_k_nc, k_file_list_names])

# longitude for the par data is from -180 to 180, but longitudes for geotraces data is from 0-360
# must convert the par data longitude by adding *-1 and adding 180 to all negative numbers
def convert_long(long_180_m180):
    for long_i in range(len(long_180_m180)):
        if long_180_m180[long_i] < 0:
            long_180_m180[long_i] = long_180_m180[long_i]*-1 + 180
    return(long_180_m180)

def get_closest_par(get_nc_list_output, month_order_1, month_order_2,
                    long_stations, lat_stations, geotrace_month_per_st):

    # this function takes the above list of nc files for par and kd
    # along with the np array of long and lats from the geotraces data
    # and the month sampled for each station
    # the output is a 2 element list, each with a list of par and Kd_490 values for each station
    # in the GEOTRACES dataset

    station_kd_vars = []
    station_par_vars = []

    # go through each station
    for station_i in range(len(long_stations)):

        target_lon = long_stations[station_i]
        target_lat = lat_stations[station_i]

        ## something here that figures out the month from geotraces
        temp_month = str(geotrace_month_per_st[station_i])

        par_file_index = month_order_1.index(temp_month)
        k_file_index = month_order_2.index(temp_month)

        print(par_file_index)
        print(k_file_index)

        # get the longitude and latitude from those files
        lat_var = get_nc_list_output[0][par_file_index].variables['lat'][:]
        long_var = get_nc_list_output[0][par_file_index].variables['lon'][:]
        # convert the long to 0 -- 360
        lon_converted = convert_long(long_var)

        # get the par values from the file
        par = get_nc_list_output[0][par_file_index].variables['par'][:]
        k_val = get_nc_list_output[2][k_file_index].variables['Kd_490'][:]

        # find which long and lat are closest to the stations long and lat
        closest_lon = min(lon_converted, key=lambda x:abs(x-target_lon))
        closest_lat = min(lat_var, key=lambda x:abs(x-target_lat))

        # find the index of those long and lat
        closest_lat_index = np.where(lat_var == closest_lat)
        closest_lon_index = np.where(long_var == closest_lon)

        # get the corresponding par and k vals from that index
        target_kd_val = k_val[closest_lat_index, closest_lon_index]
        target_par_val = par[closest_lat_index, closest_lon_index]

        station_kd_vars.append(target_kd_val)
        station_par_vars.append(target_par_val)

    return([station_kd_vars, station_par_vars])

master_par_k = get_nc_list(file_list = file_list)

station_vals_disc = get_closest_par(geotrace_month_per_st=geotraces_months_disc,
                               long_stations = lon_geo_disc, lat_stations = lat_geo_disc,
                              get_nc_list_output = master_par_k,
                               month_order_1 = month_order_1,
                              month_order_2 = month_order_3)

def get_median_light(get_closest_par_output_test,
                     station_names_test,
                     cruise_names_test,
                     lats_test,
                     longs_test,
                     mld_function_test):

    par_list = []
    k_list = []

    for un_val in range(len(get_closest_par_output_test[0])):
        k_list.append(get_closest_par_output_test[0][un_val].tolist()[0][0])
        par_list.append(get_closest_par_output_test[1][un_val].tolist()[0][0])

    # convert par units from einstein m^-2 day^-1 into microE m^-2 s^-1
    station_surface_par_converted = par_list

    d = {'cruise':cruise_names_test,
         'station':station_names_test,
        'kd_490':k_list,
        'par':par_list,
        'lat':lats_test,
        'long':longs_test,
        'mld':mld_function_test}
#     print(d)
    df = pd.DataFrame(d)

    return(df)

df = get_median_light(get_closest_par_output_test = station_vals_disc,
                     station_names_test = geo_station_names_formatted_disc,
                     cruise_names_test = geo_names_formatted_disc,
                     lats_test = lat_geo_disc,
                     longs_test = lon_geo_disc,
                     mld_function_test = mld_disc)

df.to_csv('../data/oceanographic_data/geotraces_mld_light_by_station_discrete_data.csv')


# -*- coding=utf-8 -*-
import errno
import logging

from middlewared.client import ClientException, ValidationErrors

from midcli.command.common_syntax.argument import EnumArgument
from midcli.command.generic_call import GenericCallCommand
from midcli.command.generic_call.update import UpdateCommand
from midcli.command.query.command import QueryCommand
from midcli.utils.lang import undefined

from .utils import remove_fields, rows_processor

logger = logging.getLogger(__name__)

__all__ = ["AccountQueryCommand", "AccountCreateCommand", "AccountUpdateCommand", "AccountItemMethodCommand",
           "GroupQueryCommand", "GroupCreateCommand", "GroupUpdateCommand", "GroupItemMethodCommand",
           "ShellChoicesCommand"]

remove_id = remove_fields("id")

def get_groups(context):
    with context.get_client() as c:
        return [g["group"] for g in c.call("group.query", [], {"select": ["group"], "order_by": ["group"]})]

@rows_processor
def patch_users(context, users):
    with context.get_client() as c:
        groups = {
            group["id"]: group["group"]
            for group in c.call("group.query", [], {"select": ["id", "group"]})
        }

    for user in users:
        user["group"].pop("id")
        user["group"] = {k[len("bsdgrp_"):]: v for k, v in user["group"].items()}

        user["groups"] = [groups[id] for id in user["groups"]]

class AccountQueryCommand(QueryCommand):
    output_processors = [remove_id, patch_users]

class AccountCommandMixin:
    def _process_key(self, key):
        with self.context.get_client() as c:
            if isinstance(key, str):
                filter = [["username", "=", key]]
            else:
                filter = [["uid", "=", key]]

            try:
                return c.call(
                    "user.query",
                    filter,
                    {"get": True},
                )["id"]
            except ClientException:
                raise ValidationErrors([(
                    f'{self.method["accepts"][0]["_name_"]}',
                    f"User {key!r} does not exist",
                    errno.ENOENT,
                )])

    def _process_value(self, value):
        with self.context.get_client() as c:
            if "group" in value:
                try:
                    value["group"] = self._get_group(c, value["group"])
                except ClientException:
                    raise ValidationErrors([(
                        f'{self.method["accepts"][0]["_name_"]}.group',
                        f"Group {value['group']!r} does not exist",
                        errno.ENOENT,
                    )])

            if "groups" in value:
                for i, group in enumerate(value["groups"]):
                    try:
                        value["groups"][i] = self._get_group(c, group)
                    except ClientException:
                        raise ValidationErrors([(
                            f'{self.method["accepts"][0]["_name_"]}.groups.{i}',
                            f"Group {group!r} does not exist",
                            errno.ENOENT,
                        )])

    def _get_group(self, c, key):
        if isinstance(key, str):
            filter = [["group", "=", key]]
        else:
            filter = [["gid", "=", key]]

        return c.call(
            "group.query",
            filter,
            {"get": True},
        )["id"]

    def _create_argument(self, item):
        if item["_name_"] == "group":
            return EnumArgument("group", False, item.get("default", undefined), enum=lambda: get_groups(self.context))

        return super()._create_argument(item)

class AccountCreateCommand(AccountCommandMixin, GenericCallCommand):
    def _process_method(self, method):
        method["accepts"][0]["properties"]["group"]["type"] = ["integer", "string"]
        return method

    def _process_call_args(self, values):
        if values:
            self._process_value(values[0])
        return values

class AccountUpdateCommand(AccountCommandMixin, UpdateCommand):
    def _process_method(self, method):
        method["accepts"][0]["_name_"] = "uid_or_username"
        method["accepts"][0]["type"] = ["integer", "string"]
        method["accepts"][1]["properties"]["group"]["type"] = ["integer", "string"]
        return method

    def _process_call_args(self, values):
        values = list(values)
        if values:
            values[0] = self._process_key(values[0])
            if len(values) > 1:
                self._process_value(values[1])
        return values

    def _get_instance_call_arg(self, pk):
        return self._process_key(pk)

class AccountItemMethodCommand(AccountCommandMixin, GenericCallCommand):
    def _process_method(self, method):
        method["accepts"][0]["type"] = ["integer", "string"]
        return method

    def _process_call_args(self, values):
        values = list(values)
        if values:
            values[0] = self._process_key(values[0])
        return values

@rows_processor
def patch_groups(context, groups):
    with context.get_client() as c:
        users = {
            user["id"]: user["username"]
            for user in c.call("user.query", [], {"select": ["id", "username"]})
        }

    for i, group in enumerate(groups):
        groups[i] = group = {
            k: group[k]
            for k in ["gid", "name"] + [k for k in group.keys() if k not in ["gid", "group", "name"]]
            if k in group
        }

        group["users"] = [users[id] for id in group["users"]]

class GroupQueryCommand(QueryCommand):
    output_processors = [remove_id, patch_groups]

class GroupCommandMixin:
    def _process_key(self, key):
        with self.context.get_client() as c:
            if isinstance(key, str):
                filter = [["group", "=", key]]
            else:
                filter = [["gid", "=", key]]

            try:
                return c.call(
                    "group.query",
                    filter,
                    {"get": True},
                )["id"]
            except ClientException:
                raise ValidationErrors([(
                    f'{self.method["accepts"][0]["_name_"]}',
                    f"Group {key!r} does not exist",
                    errno.ENOENT,
                )])

    def _process_value(self, value):
        with self.context.get_client() as c:
            if "users" in value:
                for i, user in enumerate(value["users"]):
                    try:
                        value["users"][i] = self._get_user(c, user)
                    except ClientException:
                        raise ValidationErrors([(
                            f'{self.method["accepts"][0]["_name_"]}.users.{i}',
                            f"User {user!r} does not exist",
                            errno.ENOENT,
                        )])

    def _get_user(self, c, key):
        if isinstance(key, str):
            filter = [["username", "=", key]]
        else:
            filter = [["uid", "=", key]]

        return c.call(
            "user.query",
            filter,
            {"get": True},
        )["id"]

class GroupCreateCommand(GroupCommandMixin, GenericCallCommand):
    def _process_call_args(self, values):
        if values:
            self._process_value(values[0])
        return values

class GroupUpdateCommand(GroupCommandMixin, UpdateCommand):
    def _process_method(self, method):
        method["accepts"][0]["_name_"] = "gid_or_name"
        method["accepts"][0]["type"] = ["integer", "string"]
        return method

    def _process_call_args(self, values):
        values = list(values)
        if values:
            values[0] = self._process_key(values[0])
            if len(values) > 1:
                self._process_value(values[1])
        return values

    def _get_instance_call_arg(self, pk):
        return self._process_key(pk)

class GroupItemMethodCommand(GroupCommandMixin, GenericCallCommand):
    def _process_method(self, method):
        method["accepts"][0]["type"] = ["integer", "string"]
        return method

    def _process_call_args(self, values):
        values = list(values)
        if values:
            values[0] = self._process_key(values[0])
        return values

class ShellChoicesCommand(GroupCommandMixin, GenericCallCommand):
    def _process_method(self, method):
        method["accepts"][0]["items"] = [{"type": "integer"}, {"type": "string"}]
        return method

    def _process_call_args(self, values):
        values = list(values)
        if values:
            values[0] = [self._process_key(v) for v in values[0]]
        return values


import os
import cv2

from processing.dataprocessing import process_input_cv2

HR_FOLDER_NAME = "HR"

def convert_images_in_folder(input_folder, output_folder):
    paths = os.listdir(input_folder)

    os.makedirs(output_folder, exist_ok=True)
    hr_folder_path = os.path.join(output_folder, HR_FOLDER_NAME)
    os.makedirs(hr_folder_path, exist_ok=True)
    length = len(paths)
    for i, path in enumerate(paths):
        try:
            filename_hr = os.path.join(hr_folder_path, path)

            image = cv2.imread(os.path.join(input_folder, path))

            output_image = process_input_cv2(image)

            cv2.imwrite(filename_hr, output_image)
            print(f"{i} of {length}")
        except Exception as e:
            print(e)

if __name__ == "__main__":
    convert_images_in_folder("./../../flowers", "./../../data2")