"""
Joint Label Fusion algorithm
"""

__all__ = ["joint_label_fusion", "local_joint_label_fusion"]

import os
import numpy as np
import warnings
from pathlib import Path
from tempfile import NamedTemporaryFile
from tempfile import mktemp
import glob
import re
import math

from .. import utils
from ..core import ants_image as iio
from ..core import ants_image_io as iio2
from .. import registration

def joint_label_fusion(
    target_image,
    target_image_mask,
    atlas_list,
    beta=4,
    rad=2,
    label_list=None,
    rho=0.01,
    usecor=False,
    r_search=3,
    nonnegative=False,
    no_zeroes=False,
    max_lab_plus_one=False,
    output_prefix=None,
    verbose=False,
):
    """
    A multiple atlas voting scheme to customize labels for a new subject.
    This function will also perform intensity fusion. It almost directly
    calls the C++ in the ANTs executable so is much faster than other
    variants in ANTsR.

    One may want to normalize image intensities for each input image before
    passing to this function. If no labels are passed, we do intensity fusion.
    Note on computation time: the underlying C++ is multithreaded.
    You can control the number of threads by setting the environment
    variable ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS e.g. to use all or some
    of your CPUs. This will improve performance substantially.
    For instance, on a macbook pro from 2015, 8 cores improves speed by about 4x.

    ANTsR function: `jointLabelFusion`

    Arguments
    ---------
    target_image : ANTsImage
        image to be approximated

    target_image_mask : ANTsImage
        mask with value 1

    atlas_list : list of ANTsImage types
        list containing intensity images

    beta : scalar
        weight sharpness, default to 2

    rad : scalar
        neighborhood radius, default to 2

    label_list : list of ANTsImage types (optional)
        list containing images with segmentation labels

    rho : scalar
        ridge penalty increases robustness to outliers but also makes image converge to average

    usecor : boolean
        employ correlation as local similarity

    r_search : scalar
        radius of search, default is 3

    nonnegative : boolean
        constrain weights to be non-negative

    no_zeroes : boolean
        this will constrain the solution only to voxels that are always non-zero in the label list

    max_lab_plus_one : boolean
        this will add max label plus one to the non-zero parts of each label where the target mask
        is greater than one.  NOTE: this will have a side effect of adding to the original label
        images that are passed to the program.  It also guarantees that every position in the
        labels have some label, rather than none.  Ie it guarantees to explicitly parcellate the
        input data.

    output_prefix: string
        file prefix for storing output probabilityimages to disk

    verbose : boolean
        whether to show status updates

    Returns
    -------
    dictionary w/ following key/value pairs:
        `segmentation` : ANTsImage
            segmentation image

        `intensity` : ANTsImage
            intensity image

        `probabilityimages` : list of ANTsImage types
            probability map image for each label

        `segmentation_numbers` : list of numbers
            segmentation label (number, int) for each probability map

    Example
    -------
    >>> import ants
    >>> ref = ants.image_read( ants.get_ants_data('r16'))
    >>> ref = ants.resample_image(ref, (50,50),1,0)
    >>> ref = ants.iMath(ref,'Normalize')
    >>> mi = ants.image_read( ants.get_ants_data('r27'))
    >>> mi2 = ants.image_read( ants.get_ants_data('r30'))
    >>> mi3 = ants.image_read( ants.get_ants_data('r62'))
    >>> mi4 = ants.image_read( ants.get_ants_data('r64'))
    >>> mi5 = ants.image_read( ants.get_ants_data('r85'))
    >>> refmask = ants.get_mask(ref)
    >>> refmask = ants.iMath(refmask,'ME',2) # just to speed things up
    >>> ilist = [mi,mi2,mi3,mi4,mi5]
    >>> seglist = [None]*len(ilist)
    >>> for i in range(len(ilist)):
    >>>     ilist[i] = ants.iMath(ilist[i],'Normalize')
    >>>     mytx = ants.registration(fixed=ref , moving=ilist[i] ,
    >>>         typeofTransform = ('Affine') )
    >>>     mywarpedimage = ants.apply_transforms(fixed=ref,moving=ilist[i],
    >>>             transformlist=mytx['fwdtransforms'])
    >>>     ilist[i] = mywarpedimage
    >>>     seg = ants.threshold_image(ilist[i],'Otsu', 3)
    >>>     seglist[i] = ( seg ) + ants.threshold_image( seg, 1, 3 ).morphology( operation='dilate', radius=3 )
    >>> r = 2
    >>> pp = ants.joint_label_fusion(ref, refmask, ilist, r_search=2,
    >>>                     label_list=seglist, rad=[r]*ref.dimension )
    >>> pp = ants.joint_label_fusion(ref,refmask,ilist, r_search=2, rad=[r]*ref.dimension)
    """
    segpixtype = "unsigned int"
    if (label_list is None) or (np.any([l is None for l in label_list])):
        doJif = True
    else:
        doJif = False

    if not doJif:
        if len(label_list) != len(atlas_list):
            raise ValueError("len(label_list) != len(atlas_list)")
        if no_zeroes:
            for label in label_list:
                target_image_mask[label == 0] = 0
        inlabs = set()
        for label in label_list:
            values = np.unique(label[target_image_mask != 0 and label != 0])
            inlabs = inlabs.union(values)
        inlabs = sorted(inlabs)
        maxLab = max(inlabs)
        if max_lab_plus_one:
            for label in label_list:
                label[label == 0] = maxLab + 1
        mymask = target_image_mask.clone()
    else:
        mymask = target_image_mask

###### security issues with mktemp but could not figure out the right solution
###### NamedTemporaryFile creates a file with permissions:
###### -rw-------  1 stnava  staff
###### whereas mktemp gives
###### -rw-r--r--  1 stnava  staff
###### the latter is what we want - one solution is to use chmod via os but
###### am currently too lazy to change one line of code to two or more everywhere

#    osegfn = NamedTemporaryFile(prefix="antsr", suffix="myseg.nii.gz",delete=False).name
    osegfn = mktemp(prefix="antsr", suffix="myseg.nii.gz")
    # segdir = osegfn.replace(os.path.basename(osegfn),'')

    if os.path.exists(osegfn):
        os.remove(osegfn)

    if output_prefix is None:
#        probs = NamedTemporaryFile(prefix="antsr", suffix="prob%02d.nii.gz",delete=False).name
        probs = mktemp(prefix="antsr", suffix="prob%02d.nii.gz")
        probsbase = os.path.basename(probs)
        tdir = probs.replace(probsbase, "")
        searchpattern = probsbase.replace("%02d", "*")

    if output_prefix is not None:
        probs = output_prefix + "prob%02d.nii.gz"
        probpath = Path(probs).parent
        Path(probpath).mkdir(parents=True, exist_ok=True)
        probsbase = os.path.basename(probs)
        tdir = probs.replace(probsbase, "")
        searchpattern = probsbase.replace("%02d", "*")

    mydim = target_image_mask.dimension
    if not doJif:
        # not sure if these should be allocated or what their size should be
        outimg = label_list[1].clone(segpixtype)
        outimgi = target_image * 0

        outimg_ptr = utils.get_pointer_string(outimg)
        outimgi_ptr = utils.get_pointer_string(outimgi)
        outs = "[%s,%s,%s]" % (outimg_ptr, outimgi_ptr, probs)
    else:
        outimgi = target_image * 0
        outs = utils.get_pointer_string(outimgi)

    mymask = mymask.clone(segpixtype)
    if (not isinstance(rad, (tuple, list))) or (len(rad) == 1):
        myrad = [rad] * mydim
    else:
        myrad = rad

    if len(myrad) != mydim:
        raise ValueError("path radius dimensionality must equal image dimensionality")

    myrad = "x".join([str(mr) for mr in myrad])
    vnum = 1 if verbose else 0
    nnum = 1 if nonnegative else 0
    mypc = "MSQ"
    if usecor:
        mypc = "PC"

    myargs = {
        "d": mydim,
        "t": target_image,
        "a": rho,
        "b": beta,
        "c": nnum,
        "p": myrad,
        "m": mypc,
        "s": r_search,
        "x": mymask,
        "o": outs,
        "v": vnum,
    }

    kct = len(myargs.keys())
    for k in range(len(atlas_list)):
        kct += 1
        myargs["g-MULTINAME-%i" % kct] = atlas_list[k]
        if not doJif:
            kct += 1
            castseg = label_list[k].clone(segpixtype)
            myargs["l-MULTINAME-%i" % kct] = castseg

    myprocessedargs = utils._int_antsProcessArguments(myargs)

    libfn = utils.get_lib_fn("antsJointFusion")
    rval = libfn(myprocessedargs)
    if rval != 0:
        print("Warning: Non-zero return from antsJointFusion")

    if doJif:
        return outimgi

    probsout = glob.glob(os.path.join(tdir, "*" + searchpattern))
    probsout.sort()
    probimgs = []
#    print( os.system("ls -l "+probsout[0]) )
    for idx in range(len(probsout)):
        probimgs.append(iio2.image_read(probsout[idx]))

    #    if len(probsout) != (len(inlabs)) and max_lab_plus_one == False:
    #        warnings.warn("Length of output probabilities != length of unique input labels")

    segmentation_numbers = [0] * len(probsout)
    for i in range(len(probsout)):
        temp = str.split(probsout[i], "prob")
        segnum = temp[len(temp) - 1].split(".nii.gz")[0]
        segmentation_numbers[i] = int(segnum)

    if max_lab_plus_one == False:
        segmat = iio2.images_to_matrix(probimgs, target_image_mask)
        finalsegvec = segmat.argmax(axis=0)
        finalsegvec2 = finalsegvec.copy()
        # mapfinalsegvec to original labels
        for i in range(len(probsout)):
            temp = str.split(probsout[i], "prob")
            segnum = temp[len(temp) - 1].split(".nii.gz")[0]
            finalsegvec2[finalsegvec == i] = segnum
        outimg = iio2.make_image(target_image_mask, finalsegvec2)

        return {
            "segmentation": outimg,
            "intensity": outimgi,
            "probabilityimages": probimgs,
            "segmentation_numbers": segmentation_numbers,
        }

    if max_lab_plus_one == True:
        mymaxlab = max(segmentation_numbers)
        matchings_indices = [
            i
            for i, segmentation_numbers in enumerate(segmentation_numbers)
            if segmentation_numbers == mymaxlab
        ]
        background_prob = probimgs[matchings_indices[0]]
        background_probfn = probsout[matchings_indices[0]]
        del probimgs[matchings_indices[0]]
        del probsout[matchings_indices[0]]
        del segmentation_numbers[matchings_indices[0]]

        segmat = iio2.images_to_matrix(probimgs, target_image_mask)

        finalsegvec = segmat.argmax(axis=0)
        finalsegvec2 = finalsegvec.copy()
        # mapfinalsegvec to original labels
        for i in range(len(probsout)):
            temp = str.split(probsout[i], "prob")
            segnum = temp[len(temp) - 1].split(".nii.gz")[0]
            finalsegvec2[finalsegvec == i] = segnum

        outimg = iio2.make_image(target_image_mask, finalsegvec2)

        # next decide what is "background" based on the sum of the first k labels vs the prob of the last one
        firstK = probimgs[0] * 0
        for i in range(len(probsout)):
            firstK = firstK + probimgs[i]

        segmat = iio2.images_to_matrix([background_prob, firstK], target_image_mask)
        bkgsegvec = segmat.argmax(axis=0)
        outimg = outimg * iio2.make_image(target_image_mask, bkgsegvec)

        return {
            "segmentation": outimg * iio2.make_image(target_image_mask, bkgsegvec),
            "segmentation_raw": outimg,
            "intensity": outimgi,
            "probabilityimages": probimgs,
            "segmentation_numbers": segmentation_numbers,
            "background_prob": background_prob,
        }

def local_joint_label_fusion(
    target_image,
    which_labels,
    target_mask,
    initial_label,
    atlas_list,
    label_list,
    submask_dilation=10,
    type_of_transform="SyN",
    aff_metric="meansquares",
    syn_metric="mattes",
    syn_sampling=32,
    reg_iterations=(40, 20, 0),
    aff_iterations=(500, 50, 0),
    grad_step=0.2,
    flow_sigma=3,
    total_sigma=0,
    beta=4,
    rad=2,
    rho=0.1,
    usecor=False,
    r_search=3,
    nonnegative=False,
    no_zeroes=False,
    max_lab_plus_one=False,
    local_mask_transform="Similarity",
    output_prefix=None,
    verbose=False,
):
    """
    A local version of joint label fusion that focuses on a subset of labels.
    This is primarily different from standard JLF because it performs
    registration on the label subset and focuses JLF on those labels alone.

    ANTsR function: `localJointLabelFusion`

    Arguments
    ---------
    target_image : ANTsImage
        image to be labeled

    which_labels : numeric vector
        label number(s) that exist(s) in both the template and library

    target_image_mask : ANTsImage
        a mask for the target image (optional), passed to joint fusion

    initial_label : ANTsImage
        initial label set, may be same labels as library or binary.
        typically labels would be produced by a single deformable registration
        or by manual labeling.

    atlas_list : list of ANTsImage types
        list containing intensity images

    label_list : list of ANTsImage types (optional)
        list containing images with segmentation labels

    submask_dilation : integer
        amount to dilate initial mask to define region on which
        we perform focused registration

    type_of_transform : string
        A linear or non-linear registration type. Mutual information metric by default.
        See Notes below for more.

    aff_metric : string
        the metric for the affine part (GC, mattes, meansquares)

    syn_metric : string
        the metric for the syn part (CC, mattes, meansquares, demons)

    syn_sampling : scalar
        the nbins or radius parameter for the syn metric

    reg_iterations : list/tuple of integers
        vector of iterations for syn. we will set the smoothing and multi-resolution parameters based on the length of this vector.

    aff_iterations : list/tuple of integers
        vector of iterations for low-dimensional registration.

    grad_step : scalar
        gradient step size (not for all tx)

    flow_sigma : scalar
        smoothing for update field

    total_sigma : scalar
        smoothing for total field

    beta : scalar
        weight sharpness, default to 2

    rad : scalar
        neighborhood radius, default to 2

    rho : scalar
        ridge penalty increases robustness to outliers but also makes image converge to average

    usecor : boolean
        employ correlation as local similarity

    r_search : scalar
        radius of search, default is 3

    nonnegative : boolean
        constrain weights to be non-negative

    no_zeroes : boolean
        this will constrain the solution only to voxels that are always non-zero in the label list

    max_lab_plus_one : boolean
        this will add max label plus one to the non-zero parts of each label where the target mask
        is greater than one.  NOTE: this will have a side effect of adding to the original label
        images that are passed to the program.  It also guarantees that every position in the
        labels have some label, rather than none.  Ie it guarantees to explicitly parcellate the
        input data.

    local_mask_transform: string
        the type of transform for the local mask alignment - usually translation,
        rigid, similarity or affine.

    output_prefix: string
        file prefix for storing output probabilityimages to disk

    verbose : boolean
        whether to show status updates

    Returns
    -------
    dictionary w/ following key/value pairs:
        `segmentation` : ANTsImage
            segmentation image

        `intensity` : ANTsImage
            intensity image

        `probabilityimages` : list of ANTsImage types
            probability map image for each label

    """
    myregion = utils.mask_image(initial_label, initial_label, which_labels)
    if myregion.max() == 0:
        myregion = utils.threshold_image(initial_label, 1, math.inf)

    myregionb = utils.threshold_image(myregion, 1, math.inf)
    myregionAroundRegion = utils.iMath(myregionb, "MD", submask_dilation)
    if target_mask is not None:
        myregionAroundRegion = myregionAroundRegion * target_mask
    croppedImage = utils.crop_image(target_image, myregionAroundRegion)
    croppedMask = utils.crop_image(myregionAroundRegion, myregionAroundRegion)
    mycroppedregion = utils.crop_image(myregion, myregionAroundRegion)
    croppedmappedImages = []
    croppedmappedSegs = []
    if verbose is True:
        print("Begin registrations:")
    for k in range(len(atlas_list)):

        if verbose is True:
            print(str(k) + "...")

        if verbose is True:
            print( "local-seg-tx: " + local_mask_transform )
        libregion = utils.mask_image(label_list[k], label_list[k], which_labels)
        initMap = registration.registration(
            mycroppedregion, libregion, type_of_transform=local_mask_transform, aff_metric=aff_metric, aff_iterations=aff_iterations, verbose=False
        )["fwdtransforms"]
        if verbose is True:
            print( "local-img-tx: " + type_of_transform )
        localReg = registration.registration(
            croppedImage,
            atlas_list[k],
            reg_iterations=reg_iterations,
            flow_sigma=flow_sigma,
            total_sigma=total_sigma,
            grad_step=grad_step,
            type_of_transform=type_of_transform,
            syn_metric=syn_metric,
            syn_sampling=syn_sampling,
            initial_transform=initMap[0],
            verbose=False,
        )
        transformedImage = registration.apply_transforms(
            croppedImage, atlas_list[k], localReg["fwdtransforms"]
        )
        transformedLabels = registration.apply_transforms(
            croppedImage,
            label_list[k],
            localReg["fwdtransforms"],
            interpolator="nearestNeighbor",
        )
        croppedmappedImages.append(transformedImage)
        croppedmappedSegs.append(transformedLabels)

    ljlf = joint_label_fusion(
        croppedImage,
        croppedMask,
        atlas_list=croppedmappedImages,
        label_list=croppedmappedSegs,
        beta=beta,
        rad=rad,
        rho=rho,
        usecor=usecor,
        r_search=r_search,
        nonnegative=nonnegative,
        no_zeroes=no_zeroes,
        max_lab_plus_one=max_lab_plus_one,
        output_prefix=output_prefix,
        verbose=verbose,
    )

    return {
        "ljlf": ljlf,
        "croppedImage": croppedImage,
        "croppedmappedImages": croppedmappedImages,
        "croppedmappedSegs": croppedmappedSegs,
    }


from datetime import datetime
import matplotlib.pyplot as plt

from raytracer.GeometricObjects.Plane import Plane
from raytracer.GeometricObjects.Sphere import Sphere

# from raytracer.Utilities.Ray import Ray
from raytracer.Utilities.RGBColor import RGBColor
from raytracer.Utilities.Point3D import Point3D
# from raytracer.Utilities.Vector3D import Vector3D
from raytracer.Utilities.Normal import Normal
# from raytracer.Utilities.ShadeRec import ShadeRec

from raytracer.World.World import World

from raytracer.World.ViewPlane import ViewPlane
from raytracer.Tracers.RayCast import RayCast

vp = ViewPlane(hres = 300, vres = 300, pix_size=1.0, num_samples=1.0, gamma=1.0)

world = World(vp=vp, tracer_type=RayCast)

s1 = Sphere(radius=80.0, center=Point3D(0, -25, 0))
s1.set_color(RGBColor(1.0, 0.0, 0.0))

s2 = Sphere(radius=60.0, center=Point3D(0, 30, 0))
s2.set_color(RGBColor(1.0, 1.0, 0.0))

p1 = Plane(Point3D(0, 0, 0), Normal(0, 1, 1))
p1.set_color(RGBColor(0.0, 0.3, 0.0))

p2 = Plane(Point3D(0, 0, 0), Normal(0, 0, 1))
p2.set_color(RGBColor(0.0, 0, 0.3))

world.add_object(p1)
world.add_object(s2)
world.add_object(s1)
#world.add_object(p2)

world.render_scene()
image = world.screen_to_image()

plt.imshow(image)
plt.show()

plt.imsave(f"renders/{datetime.now().strftime('%y%m%d-%H%M%S')}.png", image)

##===================================== TESTS
exit()
class testClass:

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return f"{self.a} -- {self.b}"

def change(tcl: testClass):
    tcl.b = 10000
    tcl.a = 93218745

mcl = testClass(5, 6)
print(mcl)
change(mcl)
print(mcl)


import vot
import sys
import cv2
import time
import torch
import numpy as np
import collections
import os.path

# make sure the paths you need are append
basedir = os.path.dirname(__file__)
sys.path.append(os.path.abspath(os.path.join(basedir, os.path.pardir)))

from modules.sample_generator import *
from modules.actor import Actor
# from option import *
# from data_prov import *

from modules.QNet_cir import QNet_cir
from modules.SiameseNet import SiameseNet
from modules.tem_policy_base import T_Policy
from modules.SiamFcTracker import SiamFCTracker
from modules.EmbeddingNet import BaselineEmbeddingNet

from utils.np2tensor import np2tensor
from utils.crop_image import crop_image_actor_
from utils.crop_image import move_crop_tracking

project_path = os.path.abspath(os.path.join(basedir, os.path.pardir))
T_N = 5

class DATracker(object):

    def __init__(self, image, region):

        self.window = max(region.width, region.height) * 2

        left = max(region.x, 0)
        top = max(region.y, 0)
        #
        # right = min(region.x + region.width, image.shape[1] - 1)
        # bottom = min(region.y + region.height, image.shape[0] - 1)

        self.position = (region.x + region.width / 2, region.y + region.height / 2)
        self.size = (region.width, region.height)

        self.siam = SiameseNet(BaselineEmbeddingNet())
        # weights_init(siam)
        siamfc_path = project_path + "/models/siamfc_pretrained.pth"

        pretrained_siam = torch.load(siamfc_path)
        siam_dict = self.siam.state_dict()
        pretrained_siam = {k: v for k, v in pretrained_siam.items() if k in siam_dict}
        siam_dict.update(pretrained_siam)
        self.siam.load_state_dict(siam_dict)

        self.pi = T_Policy(T_N)

        pretrained_pi_dict = torch.load(project_path + '/models/Qnet/template_policy/10400_template_policy.pth')
        pi_dict = self.pi.state_dict()
        pretrained_pi_dict = {k: v for k, v in pretrained_pi_dict.items() if k in pi_dict}
        # pretrained_pi_dict = {k: v for k, v in pretrained_pi_dict.items() if k in pi_dict and k.startswith("conv")}
        pi_dict.update(pretrained_pi_dict)
        self.pi.load_state_dict(pi_dict)

        self.q = QNet_cir()  # .load_state_dict(torch.load("../Models/500_actor.pth"))
        pretrained_q_dict = torch.load(project_path + "/models/Qnet/QLT/10400_Qnet.pth")
        q_dict = self.q.state_dict()
        pretrained_q_dict = {k: v for k, v in pretrained_q_dict.items() if k in q_dict}
        q_dict.update(pretrained_q_dict)
        self.q.load_state_dict(q_dict)
        self.tracker = SiamFCTracker(model_path=siamfc_path, gpu_id=0)
        if torch.cuda.is_available():
            self.siam = self.siam.cuda()
            self.pi = self.pi.cuda()
            self.q = self.q.cuda()
        init_bbox = np.array([left, top, region.width, region. height])
        self.rate = init_bbox[2] / init_bbox[3]
        self.template = self.tracker.init(image, init_bbox)
        self.templates = []
        for i in range(T_N):
            self.templates.append(self.template)

    def track(self, image):

        np_img = np.array(cv2.resize(image, (255, 255), interpolation=cv2.INTER_AREA)).transpose(2, 0, 1)
        np_imgs = []
        for i in range(T_N):
            np_imgs.append(np_img)

        with torch.no_grad():
            responses = self.siam(torch.Tensor(self.templates).permute(0, 3, 1, 2).float().cuda(), torch.Tensor(np_imgs).float().cuda())
            action = self.pi(responses.permute(1, 0, 2, 3).cuda()).cpu().detach().numpy()
        action_id = np.argmax(action)
        # print(action_id)
        if action[0][action_id] * 0.9 > action[0][0]:
            template = self.templates[action_id]
        else:
            template = self.templates[0]
        with torch.no_grad():
            siam_box = self.tracker.update(image, template)
        siam_box = np.round([siam_box[0], siam_box[1], siam_box[2] -siam_box[0], siam_box[3] - siam_box[1]])
        bbox = siam_box
        for i in range(5):
            img_crop_l, _, _ = crop_image_actor_(np.array(np_img), bbox)
            # imo_crop_l = (np.array(img_crop_l).reshape(3, 107, 107))
            imo_l = np2tensor(np.array(img_crop_l).reshape(1, 107, 107, 3))
            deta_pos = np.zeros(3)
            with torch.no_grad():
                action_q = self.q.sample_action(imo_l)
            deta = 0.04
            if (action_q == 0):
                break
            if (action_q == 1):
                deta_pos[1] -= deta
            if (action_q == 2):
                deta_pos[1] += deta
            if (action_q == 3):
                deta_pos[0] -= deta
            if (action_q == 4):
                deta_pos[0] += deta
            if (action_q == 5):
                deta_pos[2] += deta
            if (action_q == 6):
                deta_pos[2] -= deta

            pos_ = np.round(move_crop_tracking(np.array(siam_box), deta_pos, (image.shape[1], image.shape[0]), self.rate))
            bbox = pos_
        result = bbox
        return vot.Rectangle(result[0], result[1], result[2], result[3])

handle = vot.VOT("rectangle")
selection = handle.region()
imagefile = handle.frame()
if not imagefile:
    sys.exit(0)
rett = dict()
rett["imagefile"] = imagefile
image = cv2.imread(imagefile, cv2.COLOR_BGR2RGB)
# print(image)
tracker = DATracker(image, selection)
while True:
    imagefile = handle.frame()
    rett["imagefile"] = imagefile
    if not imagefile:
        break
    image = cv2.imread(imagefile, cv2.COLOR_BGR2RGB)
    region = tracker.track(image)
    handle.report(region,rett)


import sqlite3
from sqlite3.dbapi2 import Cursor

conn = sqlite3.connect('blackjack_deck.db')

cursor = conn.cursor()

insert_card = '''INSERT INTO deck
                VALUES(?,?);
               '''
card = [ ('Seven of Hearts'), (7) ]
cursor.execute(insert_card, card)
cursor.close()
conn.commit()
conn.close()

# all cards have their number value except for face cards, their value is 10
# an ace can either be 1 or 11 depending on the hand


from __future__ import division, absolute_import, print_function
from past.builtins import xrange

import numpy as np
import os
import sys
import esutil
import scipy.interpolate
import scipy.optimize

import matplotlib.pyplot as plt

from .sharedNumpyMemManager import SharedNumpyMemManager as snmm

from .fgcmUtilities import retrievalFlagDict

class FgcmRetrieveAtmosphere(object):
    """
    Class to convert retrieved integrals into atmosphere parameters.  Experimental.

    parameters
    ----------
    fgcmConfig: FgcmConfig
    fgcmLUT: FgcmLUT
    fgcmPars: FgcmPars
    """

    def __init__(self, fgcmConfig, fgcmLUT, fgcmPars):

        self.fgcmLog = fgcmConfig.fgcmLog

        self.fgcmLog.info('Initializing fgcmRetrieveAtmosphere')

        self.fgcmLUT = fgcmLUT
        self.fgcmPars = fgcmPars

        self.pwvRetrievalSmoothBlock = fgcmConfig.pwvRetrievalSmoothBlock
        self.plotPath = fgcmConfig.plotPath
        self.outfileBaseWithCycle = fgcmConfig.outfileBaseWithCycle
        self.minCCDPerExp = fgcmConfig.minCCDPerExp
        self.illegalValue = fgcmConfig.illegalValue
        self.useNightlyRetrievedPWV = fgcmConfig.useNightlyRetrievedPWV
        self.tauRetrievalMinCCDPerNight = fgcmConfig.tauRetrievalMinCCDPerNight
        self.ccdOffsets = fgcmConfig.ccdOffsets

    def r1ToPWV(self, fgcmRetrieval, doPlots=True):
        """
        Convert R1 values to PWV.  Experimental.

        parameters
        ----------
        fgcmRetrieval: FgcmRetrieval
        doPlots: bool, default=True
        """

        self.fgcmLog.info('Retrieving PWV Values...')

        parArray = self.fgcmPars.getParArray(fitterUnits=False)
        # Note that at this point it doesn't matter if we use the input or not
        self.fgcmPars.parsToExposures(retrievedInput=True)

        expIndexArray = np.repeat(np.arange(self.fgcmPars.nExp), self.fgcmPars.nCCD)
        ccdIndexArray = np.tile(np.arange(self.fgcmPars.nCCD),self.fgcmPars.nExp)

        r0 = snmm.getArray(fgcmRetrieval.r0Handle)
        r10 = snmm.getArray(fgcmRetrieval.r10Handle)

        # Reset values
        self.fgcmPars.compRetrievedPWVRaw[:] = self.illegalValue
        # set this to be the default
        self.fgcmPars.compRetrievedPWVRaw[:] = self.fgcmPars.pwvStd
        self.fgcmPars.compRetrievedPWV[:] = self.fgcmPars.pwvStd
        self.fgcmPars.compRetrievedPWVFlag[:] = retrievalFlagDict['EXPOSURE_STANDARD']

        # FIXME: check that there are actually z-band images...etc.
        try:
            zBandIndex = self.fgcmPars.bands.index('z')
        except ValueError:
            self.fgcmLog.info("No z band, so no PWV retrieval.")
            return

        zUse,=np.where((self.fgcmPars.expBandIndex[expIndexArray] == zBandIndex) &
                       (self.fgcmPars.expFlag[expIndexArray] == 0) &
                       (np.abs(r0[expIndexArray, ccdIndexArray]) < 1000.0) &
                       (np.abs(r10[expIndexArray, ccdIndexArray]) < 1000.0))

        if zUse.size == 0:
            self.fgcmLog.info("Could not find any good z-band exposures for PWV retrieval.")
            return

        o3ZU = self.fgcmPars.expO3[expIndexArray[zUse]]
        #lnTauZU = np.log(self.fgcmPars.expTau[expIndexArray[zUse]])
        lnTauZU = self.fgcmPars.expLnTau[expIndexArray[zUse]]
        alphaZU = self.fgcmPars.expAlpha[expIndexArray[zUse]]
        secZenithZU = 1./(np.sin(self.fgcmPars.expTelDec[expIndexArray[zUse]]) *
                          self.fgcmPars.sinLatitude +
                          np.cos(self.fgcmPars.expTelDec[expIndexArray[zUse]]) *
                          self.fgcmPars.cosLatitude *
                          np.cos(self.fgcmPars.expTelHA[expIndexArray[zUse]]))
        pmbZU = self.fgcmPars.expPmb[expIndexArray[zUse]]

        r1ZU = (r10[expIndexArray[zUse], ccdIndexArray[zUse]] *
                r0[expIndexArray[zUse], ccdIndexArray[zUse]])

        rPWVZU = np.zeros(zUse.size)

        pwvVals = self.fgcmLUT.pwv
        I1Arr = np.zeros((pwvVals.size, zUse.size))

        for i,pwv in enumerate(pwvVals):
            indices = self.fgcmLUT.getIndices(np.repeat(zBandIndex, zUse.size),
                                              np.repeat(pwv, zUse.size),
                                              o3ZU, lnTauZU, alphaZU, secZenithZU,
                                              ccdIndexArray[zUse], pmbZU)
            I1Arr[i, :] = self.fgcmLUT.computeI1(np.repeat(pwv, zUse.size),
                                                 o3ZU, lnTauZU, alphaZU, secZenithZU,
                                                 pmbZU, indices)

        for i in xrange(zUse.size):
            interpolator = scipy.interpolate.interp1d(I1Arr[:,i], pwvVals)
            rPWVZU[i] = interpolator(np.clip(r1ZU[i], I1Arr[:,i].min() + 0.0001,
                                             I1Arr[:,i].max() - 0.0001))

        # next, we median together each exposure...
        minExpIndex = np.min(expIndexArray[zUse])
        h, rev = esutil.stat.histogram(expIndexArray[zUse], min=minExpIndex, rev=True)

        gd, = np.where(h >= self.minCCDPerExp)

        rPWVStruct = np.zeros(gd.size, dtype=[('EXPINDEX', 'i4'),
                                              ('RPWV_MED', 'f8'),
                                              ('RPWV_SMOOTH', 'f8'),
                                              ('MJD', 'f8')])

        rPWVStruct['EXPINDEX'] = minExpIndex + gd

        for i in xrange(gd.size):
            i1a = rev[rev[gd[i]]:rev[gd[i]+1]]

            rPWVStruct['RPWV_MED'][i] = np.mean(rPWVZU[i1a])

        rPWVStruct['MJD'] = self.fgcmPars.expMJD[rPWVStruct['EXPINDEX']]

        # next, we do the median smoothing using pwvRetrievalSmoothBlock
        # self.pwvRetrievalSmoothBlock = fgcmConfig.pwvRetrievalSmoothBlock

        h, rev = esutil.stat.histogram(self.fgcmPars.expNightIndex[rPWVStruct['EXPINDEX']],
                                       rev=True)

        # we do this on any night that we have at least 1
        gd, = np.where(h > 0)

        for i in xrange(gd.size):
            i1a = rev[rev[gd[i]]:rev[gd[i]+1]]

            if (i1a.size == 1):
                rPWVStruct['RPWV_SMOOTH'][i1a[0]] = rPWVStruct['RPWV_MED'][i1a[0]]
            else:
                # these are not sorted out of expNightIndex
                st = np.argsort(rPWVStruct['MJD'][i1a])
                i1a = i1a[st]

                for j in xrange(i1a.size):
                    u = np.arange(np.clip(j - self.pwvRetrievalSmoothBlock/2, 0, i1a.size-1),
                                  np.clip(j + self.pwvRetrievalSmoothBlock/2, 0, i1a.size-1),
                                  1, dtype=np.int32)
                    rPWVStruct['RPWV_SMOOTH'][i1a[j]] = np.median(rPWVStruct['RPWV_MED'][i1a[u]])

        # Record these values and set a flag...
        self.fgcmPars.compRetrievedPWVRaw[rPWVStruct['EXPINDEX']] = rPWVStruct['RPWV_MED']
        self.fgcmPars.compRetrievedPWV[rPWVStruct['EXPINDEX']] = rPWVStruct['RPWV_SMOOTH']
        # unset standard and set that it's been retrieved
        self.fgcmPars.compRetrievedPWVFlag[rPWVStruct['EXPINDEX']] &= ~retrievalFlagDict['EXPOSURE_STANDARD']
        self.fgcmPars.compRetrievedPWVFlag[rPWVStruct['EXPINDEX']] |= retrievalFlagDict['EXPOSURE_RETRIEVED']

        # and finally we do interpolation to all the exposures...

        nightIndexWithPWV = np.unique(self.fgcmPars.expNightIndex[rPWVStruct['EXPINDEX']])

        a, b = esutil.numpy_util.match(nightIndexWithPWV, self.fgcmPars.expNightIndex)
        h, rev = esutil.stat.histogram(self.fgcmPars.expNightIndex[b], rev=True)

        gd, = np.where(h > 0)

        for i in xrange(gd.size):
            i1a = b[rev[rev[gd[i]]:rev[gd[i]+1]]]

            # sort by MJD
            st = np.argsort(self.fgcmPars.expMJD[i1a])
            i1a = i1a[st]

            # base interpolation on the ones with RPWV fits
            hasPWV, = np.where((self.fgcmPars.compRetrievedPWVFlag[i1a] & retrievalFlagDict['EXPOSURE_RETRIEVED']) > 0)

            noPWV, = np.where((self.fgcmPars.compRetrievedPWVFlag[i1a] & retrievalFlagDict['EXPOSURE_RETRIEVED']) == 0)

            # if we have < 3, we have a special branch -- night average
            if hasPWV.size < 3:
                self.fgcmPars.compRetrievedPWV[i1a[noPWV]] = np.mean(self.fgcmPars.compRetrievedPWV[i1a[hasPWV]])
            else:
                # regular interpolation

                interpolator = scipy.interpolate.interp1d(self.fgcmPars.expMJD[i1a[hasPWV]],
                                                          self.fgcmPars.compRetrievedPWV[i1a[hasPWV]],
                                                          bounds_error=False,
                                                          fill_value=(self.fgcmPars.compRetrievedPWV[i1a[hasPWV[0]]],
                                                                      self.fgcmPars.compRetrievedPWV[i1a[hasPWV[-1]]]))
                self.fgcmPars.compRetrievedPWV[i1a[noPWV]] = interpolator(self.fgcmPars.expMJD[i1a[noPWV]])
            # Flagging is the same
            self.fgcmPars.compRetrievedPWVFlag[i1a[noPWV]] &= ~retrievalFlagDict['EXPOSURE_STANDARD']
            self.fgcmPars.compRetrievedPWVFlag[i1a[noPWV]] |= retrievalFlagDict['EXPOSURE_INTERPOLATED']

        if doPlots:
            # if there are fewer than ... 3000 do points, more than do hexbin
            plt.set_cmap('viridis')

            hasPWV, = np.where((self.fgcmPars.compRetrievedPWVFlag & retrievalFlagDict['EXPOSURE_RETRIEVED']) > 0)

            #  RPWV_SMOOTH vs RPWV_SMOOTH_INPUT  (fgcmPars.compRetrievedPWVInput)
            #   (this checks for convergence on the actual measured values)
            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()
            ax = fig.add_subplot(111)

            hadPWV, = np.where((self.fgcmPars.compRetrievedPWVInput[hasPWV] != self.fgcmPars.pwvStd))

            if (hadPWV.size >= 3000):
                ax.hexbin(self.fgcmPars.compRetrievedPWVInput[hasPWV[hadPWV]],
                          self.fgcmPars.compRetrievedPWV[hasPWV[hadPWV]],
                          bins='log')
            else:
                ax.plot(self.fgcmPars.compRetrievedPWVInput[hasPWV[hadPWV]],
                          self.fgcmPars.compRetrievedPWV[hasPWV[hadPWV]], 'b.')
            plotRange = np.array([self.fgcmPars.compRetrievedPWV[hasPWV].min()+0.001,
                                  self.fgcmPars.compRetrievedPWV[hasPWV].max()-0.001])
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('RPWV_INPUT')
            ax.set_ylabel('RPWV')

            fig.savefig('%s/%s_rpwv_vs_rpwv_in.png' % (self.plotPath,
                                                       self.outfileBaseWithCycle))
            plt.close(fig)

            #  RPWV_RAW vs RPWV_SMOOTH (current calculation, just to make sure)
            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()

            ax = fig.add_subplot(111)

            if hasPWV.size >= 3000:
                # we can use hexbin; this is arbitrary.
                ax.hexbin(self.fgcmPars.compRetrievedPWV[hasPWV],
                          self.fgcmPars.compRetrievedPWVRaw[hasPWV], bins='log')
            else:
                ax.plot(self.fgcmPars.compRetrievedPWV[hasPWV],
                          self.fgcmPars.compRetrievedPWVRaw[hasPWV], 'b.')
            plotRange = np.array([self.fgcmPars.compRetrievedPWVRaw[hasPWV].min()+0.001,
                                  self.fgcmPars.compRetrievedPWVRaw[hasPWV].max()-0.001])
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('RPWV_SMOOTH')
            ax.set_ylabel('RPWV_RAW')

            fig.savefig('%s/%s_rpwv_vs_rpwv_smooth.png' % (self.plotPath,
                                                           self.outfileBaseWithCycle))
            plt.close(fig)

            #  PWV vs RPWV_SMOOTH
            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()

            ax = fig.add_subplot(111)

            if hasPWV.size >= 3000:
                # we can use hexbin; this is arbitrary.
                ax.hexbin(self.fgcmPars.compRetrievedPWV[hasPWV],
                          self.fgcmPars.expPWV[hasPWV], bins='log')
            else:
                ax.plot(self.fgcmPars.compRetrievedPWV[hasPWV],
                        self.fgcmPars.expPWV[hasPWV], 'b.')
            plotRange = np.array([self.fgcmPars.compRetrievedPWV[hasPWV].min()+0.001,
                                  self.fgcmPars.compRetrievedPWV[hasPWV].max()-0.001])
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('RPWV')
            ax.set_ylabel('PWV_MODEL')

            fig.savefig('%s/%s_pwv_vs_rpwv.png' % (self.plotPath,
                                                   self.outfileBaseWithCycle))
            plt.close(fig)

            #  PWV vs RPWV_SCALED
            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()

            ax = fig.add_subplot(111)

            #scaledRetrievedPWV = (self.fgcmPars.compRetrievedPWV * self.fgcmPars.parRetrievedPWVScale +
            #                      self.fgcmPars.parRetrievedPWVOffset)
            if self.useNightlyRetrievedPWV:
                scaledRetrievedPWV = (self.fgcmPars.parRetrievedPWVNightlyOffset[self.fgcmPars.expNightIndex] +
                                      self.fgcmPars.parRetrievedPWVScale *
                                      self.fgcmPars.compRetrievedPWV)
            else:
                scaledRetrievedPWV = (self.fgcmPars.parRetrievedPWVOffset +
                                      self.fgcmPars.parRetrievedPWVScale *
                                      self.fgcmPars.compRetrievedPWV)

            if hasPWV.size >= 3000:
                # we can use hexbin; this is arbitrary.
                ax.hexbin(scaledRetrievedPWV[hasPWV],
                          self.fgcmPars.expPWV[hasPWV], bins='log')
            else:
                ax.plot(scaledRetrievedPWV[hasPWV],
                        self.fgcmPars.expPWV[hasPWV], 'b.')
            plotRange = np.array([self.fgcmPars.compRetrievedPWV[hasPWV].min()+0.001,
                                  self.fgcmPars.compRetrievedPWV[hasPWV].max()-0.001])
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('RPWV_SCALED')
            ax.set_ylabel('PWV_MODEL')

            fig.savefig('%s/%s_pwv_vs_rpwv_scaled.png' % (self.plotPath,
                                                         self.outfileBaseWithCycle))
            plt.close(fig)

        # and we're done!  Everything is filled in!
        self.fgcmLog.info('Done computing retrieved PWV values')

    def r0ToNightlyTau(self, fgcmRetrieval, doPlots=True):
        """
        Convert R0 values to nightly Tau, using airmass.  Experimental.

        parameters
        ----------
        fgcmRetrieval: FgcmRetrieval
        doPlots: bool, default=True
        """

        self.fgcmLog.info('Retrieving Nightly Tau Values...')

        #bandIndex, = np.where(self.fgcmPars.bands == 'g')[0]

        r0 = snmm.getArray(fgcmRetrieval.r0Handle)

        expIndexArray = np.repeat(np.arange(self.fgcmPars.nExp), self.fgcmPars.nCCD)
        ccdIndexArray = np.tile(np.arange(self.fgcmPars.nCCD), self.fgcmPars.nExp)

        expSecZenith = 1./(np.sin(self.fgcmPars.expTelDec[expIndexArray]) *
                           self.fgcmPars.sinLatitude +
                           np.cos(self.fgcmPars.expTelDec[expIndexArray]) *
                           self.fgcmPars.cosLatitude *
                           np.cos(self.fgcmPars.expTelHA[expIndexArray]))

        # FIXME make this configurable?
        #tauBands = np.array(['g', 'r', 'i'])
        #nTauBands = tauBands.size
        tauBands = ['g', 'r', 'i']
        nTauBands = len(tauBands)

        tauRetrievedBands = np.zeros((nTauBands, self.fgcmPars.nCampaignNights)) + self.illegalValue

        for i in xrange(nTauBands):
            #bandIndex, = np.where(self.fgcmPars.bands == tauBands[i])[0]
            bandIndex = self.fgcmPars.bands.index(tauBands[i])

            tauScale = (self.fgcmLUT.lambdaStd[bandIndex] / self.fgcmLUT.lambdaNorm) ** (-self.fgcmLUT.alphaStd)

            use,=np.where((self.fgcmPars.expBandIndex[expIndexArray] == bandIndex) &
                          (self.fgcmPars.expFlag[expIndexArray] == 0) &
                          (r0[expIndexArray, ccdIndexArray] > 0.0))

            indices = self.fgcmLUT.getIndices(np.repeat(bandIndex, use.size),
                                              np.repeat(self.fgcmLUT.pwvStd, use.size),
                                              np.repeat(self.fgcmLUT.o3Std, use.size),
                                              np.repeat(np.log(0.00001), use.size),
                                              np.repeat(self.fgcmLUT.alphaStd, use.size),
                                              expSecZenith[use],
                                              ccdIndexArray[use],
                                              np.repeat(self.fgcmLUT.pmbStd, use.size))
            I0Ref = self.fgcmLUT.computeI0(np.repeat(self.fgcmLUT.pwvStd, use.size),
                                           np.repeat(self.fgcmLUT.o3Std, use.size),
                                           np.repeat(np.log(0.00001), use.size),
                                           np.repeat(self.fgcmLUT.alphaStd, use.size),
                                           expSecZenith[use],
                                           np.repeat(self.fgcmLUT.pmbStd, use.size),
                                           indices)

            extDelta = (-2.5*np.log10(r0[expIndexArray[use], ccdIndexArray[use]]) +
                         2.5*np.log10(I0Ref))

            h,rev = esutil.stat.histogram(self.fgcmPars.expNightIndex[expIndexArray[use]],
                                          rev=True, min=0)

            gd, = np.where(h > self.tauRetrievalMinCCDPerNight)
            self.fgcmLog.info( 'Found %d nights to retrieve tau in %s band' %
                             (gd.size, tauBands[i]))

            for j in xrange(gd.size):
                i1a = rev[rev[gd[j]]:rev[gd[j] + 1]]
                fit=np.polyfit(expSecZenith[use[i1a]], extDelta[i1a], 1.0)

                tauRetrievedBands[i, gd[j]] = fit[0] / tauScale

        # now loop over nights and take the average of good ones...
        self.fgcmPars.compRetrievedTauNight[:] = self.fgcmPars.tauStd
        for i in xrange(self.fgcmPars.nCampaignNights):
            u, = np.where(tauRetrievedBands[:, i] > self.illegalValue)
            if u.size > 0:
                self.fgcmPars.compRetrievedTauNight[i] = np.mean(tauRetrievedBands[u, i])

        # and clip to bounds
        self.fgcmPars.compRetrievedTauNight[:] = np.clip(self.fgcmPars.compRetrievedTauNight,
                                                         self.fgcmLUT.tau[0]+0.0001,
                                                         self.fgcmLUT.tau[-1]-0.0001)

        # And the plots
        if doPlots:
            hasTau, = np.where((self.fgcmPars.compRetrievedTauNight != self.fgcmPars.tauStd) &
                               (self.fgcmPars.compRetrievedTauNightInput != self.fgcmPars.tauStd))
            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()
            ax = fig.add_subplot(111)

            ax.plot(self.fgcmPars.compRetrievedTauNightInput[hasTau],
                    self.fgcmPars.compRetrievedTauNight[hasTau], 'b.')
            plotRange = np.array([self.fgcmPars.compRetrievedTauNight.min() + 0.001,
                                  self.fgcmPars.compRetrievedTauNight.max() - 0.001])
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('RTAU_NIGHT_INPUT')
            ax.set_ylabel('RTAU_NIGHT')

            fig.savefig('%s/%s_rtaunight_vs_rtaunight_in.png' % (self.plotPath,
                                                                 self.outfileBaseWithCycle))
            plt.close(fig)

            hasTau, = np.where(self.fgcmPars.compRetrievedTauNight != self.fgcmPars.tauStd)

            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()
            ax = fig.add_subplot(111)

            ax.plot(np.exp(self.fgcmPars.parLnTauIntercept[hasTau]),
                    self.fgcmPars.compRetrievedTauNight[hasTau], 'b.')
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('TAU_INTERCEPT_MODEL')
            ax.set_ylabel('RTAU_NIGHT')

            fig.savefig('%s/%s_rtaunight_vs_tauint.png' % (self.plotPath,
                                                           self.outfileBaseWithCycle))
            plt.close(fig)

    def expGrayToNightlyTau(self, fgcmGray, doPlots=True):
        """
        Convert exposure gray to nightly Tau, using airmass.  Experimental.

        parameters
        ----------
        fgcmGray: FgcmGray
        doPlots: bool, defaults=True
        """

        self.fgcmLog.info( 'Retrieving nightly Tau values...')

        expGray = snmm.getArray(fgcmGray.expGrayHandle)

        expIndexArray = np.repeat(np.arange(self.fgcmPars.nExp), self.fgcmPars.nCCD)
        ccdIndexArray = np.tile(np.arange(self.fgcmPars.nCCD), self.fgcmPars.nExp)

        expSecZenith = 1./(np.sin(self.fgcmPars.expTelDec[expIndexArray]) *
                           self.fgcmPars.sinLatitude +
                           np.cos(self.fgcmPars.expTelDec[expIndexArray]) *
                           self.fgcmPars.cosLatitude *
                           np.cos(self.fgcmPars.expTelHA[expIndexArray]))

        lutIndices = self.fgcmLUT.getIndices(self.fgcmPars.expBandIndex[expIndexArray],
                                             self.fgcmPars.expPWV[expIndexArray],
                                             self.fgcmPars.expO3[expIndexArray],
                                             self.fgcmPars.expLnTau[expIndexArray],
                                             self.fgcmPars.expAlpha[expIndexArray],
                                             expSecZenith,
                                             ccdIndexArray,
                                             self.fgcmPars.expPmb[expIndexArray])
        i0 = self.fgcmLUT.computeI0(self.fgcmPars.expPWV[expIndexArray],
                                    self.fgcmPars.expO3[expIndexArray],
                                    self.fgcmPars.expLnTau[expIndexArray],
                                    self.fgcmPars.expAlpha[expIndexArray],
                                    expSecZenith,
                                    self.fgcmPars.expPmb[expIndexArray],
                                    lutIndices)

        r0Gray = np.zeros(expIndexArray.size)
        ok, = np.where(np.isfinite(expGray[expIndexArray]) &
                       (np.abs(expGray[expIndexArray]) < 1.0) &
                       (self.fgcmPars.expFlag[expIndexArray] == 0))
        r0Gray[ok] = 10.**((expGray[expIndexArray[ok]]/2.5)) * i0[ok]

        # FIXME make configurable
        tauBands = np.array(['g', 'r', 'i'])
        nTauBands = tauBands.size

        def slopeFunc(X, slope):
            return slope*X

        tauRetrievedBands = np.zeros((tauBands.size, self.fgcmPars.nCampaignNights)) + self.illegalValue
        tauModelBands = np.zeros_like(tauRetrievedBands)

        for i in xrange(nTauBands):
            #bandIndex, = np.where(self.fgcmPars.bands == tauBands[i])[0]
            bandIndex = self.fgcmPars.bands.index(tauBands[i])

            # investigate
            tauScale = (self.fgcmLUT.lambdaStd[bandIndex] / self.fgcmLUT.lambdaNorm) ** (-self.fgcmLUT.alphaStd)

            use,=np.where((self.fgcmPars.expBandIndex[expIndexArray] == bandIndex) &
                          (self.fgcmPars.expFlag[expIndexArray] == 0) &
                          (r0Gray > 0.0))

            indices = self.fgcmLUT.getIndices(np.repeat(bandIndex, use.size),
                                              self.fgcmPars.expPWV[expIndexArray[use]],
                                              self.fgcmPars.expO3[expIndexArray[use]],
                                              np.repeat(np.log(0.00001), use.size),
                                              #np.repeat(self.fgcmLUT.alphaStd, use.size),
                                              self.fgcmPars.expAlpha[expIndexArray[use]],
                                              expSecZenith[use],
                                              ccdIndexArray[use],
                                              self.fgcmPars.expPmb[expIndexArray[use]])
            I0Ref = self.fgcmLUT.computeI0(self.fgcmPars.expPWV[expIndexArray[use]],
                                           self.fgcmPars.expO3[expIndexArray[use]],
                                           np.repeat(np.log(0.00001), use.size),
                                           #np.repeat(self.fgcmLUT.alphaStd, use.size),
                                           self.fgcmPars.expAlpha[expIndexArray[use]],
                                           expSecZenith[use],
                                           self.fgcmPars.expPmb[expIndexArray[use]],
                                           indices)

            extDelta = (-2.5*np.log10(r0Gray[use]) +
                         2.5*np.log10(I0Ref))

            h,rev = esutil.stat.histogram(self.fgcmPars.expNightIndex[expIndexArray[use]],
                                          rev=True, min=0)

            gd, = np.where(h > self.tauRetrievalMinCCDPerNight)
            self.fgcmLog.info( 'Found %d nights to retrieve tau in %s band' %
                             (gd.size, tauBands[i]))

            for j in xrange(gd.size):
                i1a = rev[rev[gd[j]]:rev[gd[j] + 1]]
                fit, cov = scipy.optimize.curve_fit(slopeFunc, expSecZenith[use[i1a]],
                                                    extDelta[i1a])
                tauRetrievedBands[i, gd[j]] = fit[0] / tauScale

                tauModelBands[i, gd[j]] = np.exp(np.mean(self.fgcmPars.expLnTau[expIndexArray[use[i1a]]]))

        # now loop over nights and take the average of good ones...
        self.fgcmPars.compRetrievedTauNight[:] = self.fgcmPars.tauStd
        modelTauNight = np.zeros_like(self.fgcmPars.compRetrievedTauNight)
        for i in xrange(self.fgcmPars.nCampaignNights):
            u, = np.where(tauRetrievedBands[:, i] > self.illegalValue)
            if u.size > 0:
                self.fgcmPars.compRetrievedTauNight[i] = np.mean(tauRetrievedBands[u, i])
                modelTauNight[i] = np.mean(tauModelBands[u, i])

        # and clip to bounds
        self.fgcmPars.compRetrievedTauNight[:] = np.clip(self.fgcmPars.compRetrievedTauNight,
                                                         self.fgcmLUT.tau[0]+0.0001,
                                                         self.fgcmLUT.tau[-1]-0.0001)

        # And the plots
        if doPlots:
            hasTau, = np.where((self.fgcmPars.compRetrievedTauNight != self.fgcmPars.tauStd) &
                               (self.fgcmPars.compRetrievedTauNightInput != self.fgcmPars.tauStd))
            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()
            ax = fig.add_subplot(111)

            ax.plot(self.fgcmPars.compRetrievedTauNightInput[hasTau],
                    self.fgcmPars.compRetrievedTauNight[hasTau], 'b.')
            plotRange = np.array([self.fgcmPars.compRetrievedTauNight.min() + 0.001,
                                  self.fgcmPars.compRetrievedTauNight.max() - 0.001])
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('RTAU_NIGHT_INPUT')
            ax.set_ylabel('RTAU_NIGHT')

            fig.savefig('%s/%s_rtaunight_vs_rtaunight_in.png' % (self.plotPath,
                                                                 self.outfileBaseWithCycle))
            plt.close(fig)

            hasTau, = np.where(self.fgcmPars.compRetrievedTauNight != self.fgcmPars.tauStd)

            fig = plt.figure(1, figsize=(8, 6))
            fig.clf()
            ax = fig.add_subplot(111)

            ax.plot(modelTauNight[hasTau],
                    self.fgcmPars.compRetrievedTauNight[hasTau], 'b.')
            ax.plot(plotRange, plotRange, 'r--')
            ax.set_xlabel('TAU_MEAN_MODEL')
            ax.set_ylabel('RTAU_NIGHT')

            fig.savefig('%s/%s_rtaunight_vs_tauint.png' % (self.plotPath,
                                                           self.outfileBaseWithCycle))
            plt.close(fig)


"""
Module for defining the encoder sublayer. This will eventually wrap into the full SentenceEncoder
class
"""

import logging
from rich.logging import RichHandler

LOG_FORMAT = "%(message)s"
logging.basicConfig(level="INFO", format=LOG_FORMAT, datefmt="[%X] ", handlers=[RichHandler()])
LOGGER = logging.getLogger(__name__)

import os
import sys

import torch
from torch import nn
import torch.nn.functional as F

from annotated_mpnet.utils import utils
from annotated_mpnet.transformer_modules import LayerNorm
from annotated_mpnet.transformer_modules import RelativeMultiHeadAttention

class SentenceEncoderLayer(nn.Module):
    """
    Implements the the layers within the full SentenceEncoder
    """

    def __init__(
        self,
        embedding_dim: float = 768,
        ffn_embedding_dim: float = 3072,
        num_attention_heads: float = 8,
        dropout: float = 0.1,
        attention_dropout: float = 0.1,
        activation_dropout: float = 0.1,
        activation_fn: str = "relu",
        add_bias_kv: bool = False,
        add_zero_attn: bool = False,
        normalize_before: bool = True,
        export: bool = False,
    ) -> None:
        """
        Init function for the layer. I will try to summarize all the args here.

        Args:
            embedding_dim: the embedding dimension for the layer. Should always be 768 really
            ffn_embedding_dim: this is the size of the hidden layer in the fully-connected
                subsection of the layer right AFTER self-attention. Also known as the feed-forward
                network component of the encoder layer
            num_attention_heads: the number of attention heads for each layer. Default here is 8,
                but you will usually want to bump this higher if your model is accepting longer
                sequence lengths
            dropout: pretty straightforward, but this is the dropout prob for the FC layers in the
                forward pass
            attention_dropout: similar to above, but is the dropout prob within the self-attention
                mechanism
            activation_fn: the activation function you will be using in this network. Although ReLU
                is the default, more and more evidence points towards GELU being better for large
                NLP-based transformers
            add_bias_kv: boolean that dictates whether or not to add a bias parameter to the K, V
                matrices in the self-attention mechanism
            add_zero_attn: boolean that dictate whether or not to add zero attention to the
                self-attention mechanism
            normalize_before: boolean that determines if the LayerNorm will be applied BEFORE or
                AFTER the self-attention calculation. Functionally they are very similar, but the
                standard is to normalize before
            export: boolean that would enable ONNX tracing for exporting, but I think we won't be
                using this
        """
        super().__init__()

        # Store args
        self.embedding_dim = embedding_dim
        self.dropout = dropout
        self.activation_dropout = activation_dropout

        # Get the submodules we need
        self.activation_fn = utils.get_activation_fn(activation_fn)

        # Initialize the self attention module
        self.self_attn = RelativeMultiHeadAttention(
            self.embedding_dim,
            num_attention_heads,
            dropout=attention_dropout,
            add_bias_kv=add_bias_kv,
            add_zero_attn=add_zero_attn,
            self_attention=True,
        )

        # Get the LayerNorm for the self_attention output
        self.self_attn_layer_norm = LayerNorm(self.embedding_dim, export=export)

        # Get the FC linear layers for the hidden connections in each layer after the self-attention
        # is calculated
        self.fc1 = nn.Linear(self.embedding_dim, ffn_embedding_dim)
        self.fc2 = nn.Linear(ffn_embedding_dim, self.embedding_dim)

        # Get the final LayerNorm
        self.final_layer_norm = LayerNorm(self.embedding_dim, export=export)

        self.normalize_before = normalize_before

    def forward(
        self,
        x: torch.Tensor,
        self_attn_mask: torch.Tensor = None,
        self_attn_padding_mask: torch.Tensor = None,
        positions_bias: torch.Tensor = None,
    ):
        """
        Forward pass of the encoder layer. Calculates self-attention, does normalization (before or
        after depending on args), processes the skip connection, and uses the linear layers at the
        end
        """

        # Keep the residual for the skip connection after self-attention calculation
        residual = x

        # This is a bit of an overloaded function that will check if normalization should be
        # processed before or after self-attention. It will cross reference the "before" or "after"
        # kwarg against self.normalize_before arg and then either do nothing or normalize
        x = self.maybe_layer_norm(self.self_attn_layer_norm, x, before=True)

        # Forward pass of self-attention
        x, attn = self.self_attn(
            query=x,
            key=x,
            value=x,
            key_padding_mask=self_attn_padding_mask,
            need_weights=False,
            attn_mask=self_attn_mask,
            positions_bias=positions_bias,
        )

        # The below operations may look scary, but we will do our best to summarize their use

        # Process the dropout after self-attention is calcualted and then make the skip connection
        # by adding residual to x
        x = F.dropout(x, p=self.dropout, training=self.training)
        x = residual + x

        # Try the maybe_layer_norm function again to potentially normalize after self-attention
        x = self.maybe_layer_norm(self.self_attn_layer_norm, x, after=True)

        # Now we must process the fully connected layer after self-attention. Similarly, there is
        # also a LayerNorm that must be calculated before or after (and is determined by the
        # normalize_before arg)

        # Save the residual for the skip connection after FC layer
        residual = x

        # Process the layer norm
        x = self.maybe_layer_norm(self.final_layer_norm, x, before=True)

        # Process the first layer of the feed-forward network which expands the embedding from
        # embedding_dim to ffn_embedding_dim (Linear + activation)
        x = self.activation_fn(self.fc1(x))

        # Process the dropout once again
        x = F.dropout(x, p=self.activation_dropout, training=self.training)

        # Calculate the second portion of the feed-forward net, converting the hidden size back to
        # our embedding size of embedding_dim. This time we DO NOT add the activation function so
        # as to not kill the neurons
        x = self.fc2(x)

        # Process the droput again
        x = F.dropout(x, p=self.dropout, training=self.training)

        # Calculate the skip connection with the residual and the output of the feed-forward net
        x = x + residual

        # Finally, process the LayerNorm once again
        x = self.maybe_layer_norm(self.final_layer_norm, x, after=True)

        return x, attn

    def maybe_layer_norm(
        self, layer_norm: nn.Module, x: torch.Tensor, before=False, after=False
    ) -> torch.Tensor:
        """
        The key helper function that will only trigger if the before/after bool passed in matches
        what is dictated by the self.normalize_before
        """
        # First make sure before and after both aren't true with a quick XOR
        assert before ^ after, "You must set only one of 'before' or 'after'"

        if after ^ self.normalize_before:
            return layer_norm(x)
        else:
            return x


# import necessary libraries
import pandas as pd
from feature_engine.encoding import OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_regression,\
  mutual_info_regression
pd.set_option('display.width', 75)
pd.set_option('display.max_columns', 20)
pd.set_option('display.max_rows', 100)
pd.options.display.float_format = '{:,.3f}'.format

# load the NLS data
nls97wages = pd.read_csv("data/nls97wages.csv")

feature_cols = ['satverbal','satmath','gpascience',
  'gpaenglish','gpamath','gpaoverall','gender','motherhighgrade',
  'fatherhighgrade','parentincome','completedba']

X_train, X_test, y_train, y_test =  \
  train_test_split(nls97wages[feature_cols],\
  nls97wages[['wageincome']], test_size=0.3, random_state=0)

# encode and scale the data
ohe = OneHotEncoder(drop_last=True, variables=['gender'])
X_train_enc = ohe.fit_transform(X_train)
scaler = StandardScaler()
standcols = X_train_enc.iloc[:,:-1].columns
X_train_enc = \
  pd.DataFrame(scaler.fit_transform(X_train_enc[standcols]),
  columns=standcols, index=X_train_enc.index).\
  join(X_train_enc[['gender_Male']])

y_train = \
  pd.DataFrame(scaler.fit_transform(y_train),
  columns=['wageincome'], index=y_train.index)

# select 5 best features for predicting wage income
ksel = SelectKBest(score_func=f_regression, k=5)
ksel.fit(X_train_enc, y_train.values.ravel())
selcols = X_train_enc.columns[ksel.get_support()]
selcols
pd.DataFrame({'score': ksel.scores_,
  'feature': X_train_enc.columns},
   columns=['feature','score']).\
   sort_values(['score'], ascending=False)

# select the 5 best features using mutual information
from functools import partial
ksel = SelectKBest(score_func=\
  partial(mutual_info_regression, random_state=0),
  k=5)
ksel.fit(X_train_enc, y_train.values.ravel())
selcols = X_train_enc.columns[ksel.get_support()]
selcols
pd.DataFrame({'score': ksel.scores_,
  'feature': X_train_enc.columns},
   columns=['feature','score']).\
   sort_values(['score'], ascending=False)


from xml.etree import ElementTree

data = {}

xmlText = '<cube color="blue"><cube color="red"><cube color="green"></cube></cube><cube color="red"></cube></cube>'
# xmlText = input()

# for child_of_root in tree.iter():
#     print(child_of_root.tag, child_of_root.attrib)

def treeProcessing(tree, lvl, data):
    for child in tree:
        color = child.attrib['color']
        if color in data:
            data[color] += lvl
        else:
            data[color] = lvl
        data = treeProcessing(child, lvl + 1, data)
    return data

tree = ElementTree.fromstring(xmlText)
data[tree.attrib['color']] = 1
data = treeProcessing(tree, 2, data)
print(data['red'], data['green'], data['blue'])
print(*data.values())


from mrcnn.config import Config
from mrcnn.model import MaskRCNN
import matplotlib.pyplot as pyplot
from matplotlib.patches import Rectangle, Arrow
import math
import cv2
from mla.utils import get_random_filename
import matplotlib

matplotlib.use("agg")

def order_frame_halves(unordered_frames):
    ordered_frames = []

    while unordered_frames:
        for frame in unordered_frames:
            for other_frame in unordered_frames:
                if other_frame[3] < frame[1]: # if there is a frame above the current frame
                    break # the current frame is not the next frame to read
            else:
                ordered_frames.append(frame[:-1]) # the current frame is the next frame
                unordered_frames.remove(frame)

    return ordered_frames

def order_text(image, img_width, filename, cfg, model):
    results = model.detect([image], verbose=1)
    r = results[0]

    pyplot.figure(figsize=(10,10))
    pyplot.imshow(image)
    pyplot.title("Order Text")

    ax = pyplot.gca()

    text_centers = []
    total_unordered_frames = []
    count = 0

    for id in list(r["class_ids"]):
        box = list(r["rois"])[count]
        count += 1

        y1, x1, y2, x2 = box
        width, height = x2 - x1, y2 - y1

        if id == 2:
            text_x = (x1 + x2)//2
            text_y = (y1 + y2)//2
            text_center = [text_x, text_y]
            text_centers.append(text_center)

            rect = Rectangle((x1, y1), width, height, fill=False, color="cornflowerblue")
            ax.add_patch(rect)

        elif id == 3:
            frame_x_center = (x1 + x2)//2
            total_unordered_frames.append([x1, y1, x2, y2, frame_x_center]) # the corners are ordered this way to improve sorting later on

    total_unordered_frames.sort(reverse=True)
    ordered_frames = [] # 1st, 2nd, 3rd, ...

    half_line = img_width//2

    unordered_frames_first = [frame for frame in total_unordered_frames if frame[-1] > half_line] # frames to the right of half line
    unordered_frames_second = [frame for frame in total_unordered_frames if frame[-1] <= half_line] # frames to the left of half line

    ordered_frames_first = order_frame_halves(unordered_frames_first)
    ordered_frames_second = order_frame_halves(unordered_frames_second)

    index = 1

    for frame in ordered_frames_first:
        x1, y1, x2, y2 = frame
        text_centers_filtered = []

        for text in text_centers:
            if text[0] < x2 and text[0] > x1 and text[1] < y2 and text[1] > y1:
                text_centers_filtered.append([text[0], -text[1]])

        text_centers_filtered.sort(reverse=True)

        for text in text_centers_filtered:
            pyplot.text(text[0], -text[1], index, color="red")
            index += 1

    for frame in ordered_frames_second:
        x1, y1, x2, y2 = frame
        text_centers_filtered = []

        for text in text_centers:
            if text[0] < x2 and text[0] > x1 and text[1] < y2 and text[1] > y1:
                text_centers_filtered.append([text[0], -text[1]])

        text_centers_filtered.sort(reverse=True)

        for text in text_centers_filtered:
            pyplot.text(text[0], -text[1], index, color="red")
            index += 1

    pyplot.savefig(f"static/{filename}.png", bbox_inches="tight", pad_inches=-0.5, orientation= "landscape")
    pyplot.close()

def TOD():
    image = cv2.imread("static/input.png")
    width = image.shape[1]
    filename = get_random_filename(10)

    class PredictionConfig(Config):
        NAME = "manga_cfg"
        NUM_CLASSES = 1 + 3
        GPU_COUNT = 1
        IMAGES_PER_GPU = 1

    cfg = PredictionConfig()
    model = MaskRCNN(mode="inference", model_dir="models", config=cfg)
    model.load_weights("models/IS.h5", by_name=True)

    order_text(image, width, filename, cfg, model)

    return {"success": True, "filename": filename}


import numpy as np

def boxmuller():
    summa = 1
    size = 1
    x = np.random.uniform(size=size)
    y = np.random.uniform(size=size)
    z = np.sqrt(-2 * np.log(x)) * np.cos(2 * np.pi * y)
    q =  z * summa
    return q

# print(boxmuller()[0])

def main():
    a=[]
    for i in range(10000):
        a.append(boxmuller())
    a=np.array(a)
    # print a
    import matplotlib.pyplot as plt
    plt.hist(a,bins=86)
    # plt.hist
    # plt.plot(range(2000),a)
    plt.show()

main()


#coding=utf-8
import pygame
class Bullet:
    def __init__(self):
        # 初始化成员变量，x，y，image
        self.bullet_x=0
        self.bullet_y=-1
        self.image = pygame.image.load('../img/bullet.png').convert_alpha()
        #默认不激活子弹
        self.active=False

    def move(self):
        #如果激活，向上移动
        if self.active:
            self.bullet_y -=3

        #如果超出屏幕则设置为不激活
        if self.bullet_y<0:
            self.active=False

    def restart(self):
        #重置子弹位置
        mouseX, mouseY = pygame.mouse.get_pos()
        self.bullet_x = mouseX - self.image.get_width() / 2
        self.bullet_y = mouseY - self.image.get_height() / 2
        self.active=True


"""------------------ Mai Idea --------------------------
distance --> This amtrix holds the total distance of that 0 from all the buildings(It increases everytime a new BFS runs as BFS appends to already existing distance)
reachable --> This matrix stores whether the 0 at (i,j) can reach all the buildings or not. Its maximum value at (i,j) can be total number of buildings in the grid i.e total number of ones !
visitied --> During the current BFS has this cell been visited or not

Scan the 2D grid, whenever you encounter a 1 i.e a building start a BFS. For each 0 you encounter
during the BFS, append its distance from the root node(1 from where BFS started) into the distance matrix
Run the BFS for all the buildings in the given grid each time appending to the distance matrix.
At the end distance(i,j) will contain sum of distances of (i,j) from all the buildings(ones) in the grid
At the end go through the entire matrix and choose the minimum value. Also check the reachable matrix to see if there is some 0
which has reachable(i,j) < total no. of buildings. If yes then return -1 else return the shortest distance
"""

from collections import deque
class Solution(object):
    def shortestDistance(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        rows = len(grid)
        cols = len(grid[0])
        distance = [[0 for i in range(cols)]for i in range(rows)]
        reachable = [[0 for i in range(cols)]for i in range(rows)]      # Here index r,c stores how many buildings can the 0 at (r,c) reach. Maximum value can be total number of buildings in the given grid
        number_of_buildings = 0
        for r in range(rows):
            for c in range(cols):
                if grid[r][c] == 1:                                 # If you get a 1, run a BFS and increment toal no. of buildings
                    number_of_buildings += 1
                    self.BFS(r,c,grid,distance,reachable)

        shortest = float("inf")
        for i in range(rows):
            for j in range(cols):
                if grid[i][j] == 0 and reachable[i][j] == number_of_buildings:      # Scan through grid at the end and return shortest distance if that cell satisfies the given constraints
                    shortest = min(shortest,distance[i][j])
        if shortest == float("inf"):
            return -1
        else:
            return shortest

    def BFS(self,r,c,grid,distance,reachable):
        queue = deque()
        rows = len(grid)
        cols = len(grid[0])
        visited = [[0 for i in range(cols)]for i in range(rows)]            # Visited 2d grid declared inside BFS because its created fresh for each BFS traversal and erased at the end
        queue.append((r,c,0))                                               # Intially to start BFS append root node into queue with distance = 0
        while queue:
            curr_r,curr_c,curr_dist = queue.popleft()
            for nb in [(curr_r+1,curr_c),(curr_r-1,curr_c),(curr_r,curr_c+1),(curr_r,curr_c-1)]:    # left,right,up,down neighbours of current cell
                nb_row = nb[0]                                              # nb means neighbour, nb_row/nb_col
                nb_col = nb[1]
                if 0 <= nb_row <= rows-1 and 0 <= nb_col <= cols-1 and grid[nb_row][nb_col] == 0 and visited[nb_row][nb_col] != 'Visited':
                    distance[nb_row][nb_col] += curr_dist + 1
                    visited[nb_row][nb_col] = 'Visited'
                    reachable[nb_row][nb_col] += 1
                    queue.append((nb_row,nb_col,curr_dist+1))

grid = [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]
s = Solution()
print(s.shortestDistance(grid))


from vosk import Model, KaldiRecognizer
import json
import pyaudio
import pyttsx3

p=pyttsx3.init('sapi5')
voices=p.getProperty('voices')
p.setProperty('voice',voices[1].id)
p.setProperty('rate',190)
p.setProperty('volume',1.0)

def speak(audio):
    print('')
    p.say(audio)
    print(audio)
    p.runAndWait()

# Download vosk-model-small-en-us-0.15
# add it path
model=Model("W:\\Projects\\Projects\\vosk-model-small-en-us-0.15")
recognizer=KaldiRecognizer(model,16000)
mic=pyaudio.PyAudio()
stream=mic.open(format=pyaudio.paInt16,channels=1,rate=16000,input=True,frames_per_buffer=8192)
while True:
    data=stream.read(4096,exception_on_overflow=False)
    if len(data)==0:
        break
    if recognizer.AcceptWaveform(data):
          rec=recognizer.Result()
          command=json.loads(rec)
          print(command['text'])

        #   if 'hello' in command['text']:
        #       stream.stop_stream()
        #       print('\t\t\t\t\t\t\t\t\t\t\t\t\t'+command['text'])
        #       speak('Hi sir, I am Py assist,your personal assistant')
        #       speak('How may i help you?')
        #       stream.start_stream()
        #       print('')
        #       print('Listening')
        #       print('')


from spacy.language import Language
from spacy.matcher import Matcher

from .components.base import Masker
from .components.base import mask_decorator

@Language.factory("cash_mask")
class CashMasker(Masker):
    def __init__(self, nlp, name):
        super().__init__(nlp, name)
        self.matcher = make_cash_matcher(nlp)

    @mask_decorator
    def __call__(self, doc):
        masked_tokens = list()

        matches = self.matcher(doc)
        for match_id, start, end in matches:
            tokens = [token for token in doc[start:end] if not token._.priv_currency]
            masked_tokens = masked_tokens + tokens

        cash_tokens = search_with_key_words(doc)
        masked_tokens = masked_tokens+cash_tokens
        return masked_tokens

def search_with_key_words(doc):
    out_tokens = list()
    phrases = doc._.priv_nominal_phrases
    for phrase in phrases:
        num_tokens = list()
        cash_token_flag = False
        for token in phrase:
            if token._.priv_currency:
                cash_token_flag = True
            elif token._.priv_number:
                num_tokens.append(token)
        if cash_token_flag:
            out_tokens = out_tokens+num_tokens
    return out_tokens

def make_cash_matcher(nlp):
    matcher = Matcher(nlp.vocab)
    matcher.add("Rule", [
            [{'_': {'priv_number': True}, 'OP': '+'}, {'_': {'priv_currency': True}}],
    ])
    return matcher


'''
@Description: BTC市值走势绘制
@Author: Yang Boyu
@Email: bradleyboyuyang@gmail.com
'''

import pandas as pd
from pyecharts.charts import Line
import pyecharts.options as opts

pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)
pd.set_option('display.width', 180)

df = pd.read_csv("btc_mv.csv")
print(df.head(20))

# 市值的单位是亿美元
x_data = df['datetime'].tolist()
y_data = df['mv'].round(1).tolist()

# 绘制折线图
line = Line()
line.add_xaxis(xaxis_data=x_data)
line.add_yaxis(
    series_name="BTC/USDT",
    y_axis=y_data,
    symbol="emptyCircle",
    is_symbol_show=True,
    areastyle_opts=opts.AreaStyleOpts(opacity=0.5, color='#00FFFF'),  # 设置图形透明度与填充颜色
    label_opts=opts.LabelOpts(is_show=False),   # 标签配置项
    markpoint_opts=opts.MarkPointOpts(         # 标记点配置项
        data=[
                opts.MarkPointItem(type_="max", name="max"),
                opts.MarkPointItem(type_="average", name="avg")
        ]
    ),
    markline_opts=opts.MarkLineOpts(           # 标记线配置项
        data=[opts.MarkLineItem(type_="average", name="avg")])
)
line.set_global_opts(
    title_opts=opts.TitleOpts(title='Bitcoin Market Value (2013-2021)')
)
line.render("btc_mv_plot.html")


"""
University of Amsterdam: MSc AI: NLP2 2019 Spring
Project 2: Sentence VAE
Team 3: Gururaja P Rao, Manasa J Bhat
"""

from nltk.tree import Tree
from collections import defaultdict
import torch
import dill
import pickle
import os

class Data:
    """
    The base data that holds the vocabulary and the tokenized data
    """
    def __init__(self):
        """"Initialization of the vocabulary and the word token"""
        self.vocab = []
        self.word2token = {}

    def add_word(self, word):
        """"Add a new word to the vocabulary and tokenizer"""
        if word not in self.vocab:
            self.vocab.append(word)
            self.word2token[word] = len(self.vocab) - 1

        return self.word2token[word]

    def __len__(self):
        """Returns the length of the vocabulary"""
        return len(self.vocab)

class DataLoader():
    """
    The data loading class
    This class handles the data loading and pre-processing of the data
    """

    def __init__(self, opt):
        """
        Initialization fo the DataLoader
        """
        self.train_batch_size = opt.batch_size
        self.test_batch_size = opt.test_batch
        self.max_seq_len = opt.seq_length

        if os.path.isfile(opt.dataroot + 'vocabulary.pkl'):
            print("Loading processed vocabulary from file")
            with open(opt.dataroot + 'vocabulary.pkl', 'rb') as in_file:
                self.vocabulary = dill.load(in_file)
            in_file.close()
        else:
            self.vocabulary = Data()
            special_words = ['-PAD-', '-UNK-', '-SOS-', '-EOS-']
            for word in special_words:
                self.vocabulary.add_word(word)

        if opt.mode == 'train':
            self.mode = 'train'

            # Get the processed training dataset
            if os.path.isfile(opt.dataroot + 'train_data.pkl'):
                print("Loading the processed training data from file")
                with open(opt.dataroot + 'train_data.pkl', 'rb') as in_file:
                    self.train_data = dill.load(in_file)
                in_file.close()
            else:
                print("Processing Training data")
                train_data_path = opt.dataroot+"/Training/02-21.10way.clean"
                self.train_data = self.get_data(train_data_path)
                # Save the processed model for future loading
                with open(opt.dataroot + 'train_data.pkl', 'wb') as f:
                    dill.dump(self.train_data, f, pickle.HIGHEST_PROTOCOL)
                f.close()

            # Get the processed validation dataset
            if os.path.isfile(opt.dataroot + 'val_data.pkl'):
                print("Loading the processed validation data file")
                with open(opt.dataroot + 'val_data.pkl', 'rb') as in_file:
                    self.val_data = dill.load(in_file)
                in_file.close()
            else:
                self.val_data_path = opt.dataroot + "/Validation/22.auto.clean"
                print("Processing Validation data")
                self.val_data = self.get_data(self.val_data_path)
                with open(opt.dataroot + 'val_data.pkl', 'wb') as f:
                    dill.dump(self.val_data, f, pickle.HIGHEST_PROTOCOL)
                f.close()

            # Get the processed testing dataset
            if os.path.isfile(opt.dataroot + 'test_data.pkl'):
                print("Loading the processed testing data file")
                with open(opt.dataroot + 'test_data.pkl', 'rb') as in_file:
                    self.test_data = dill.load(in_file)
                in_file.close()
            else:
                print("Processing Testing data")
                self.test_data_path = opt.dataroot+"/Testing/23.auto.clean"
                self.test_data = self.get_data(self.test_data_path)
                with open(opt.dataroot + 'test_data.pkl', 'wb') as f:
                    dill.dump(self.test_data, f, pickle.HIGHEST_PROTOCOL)
                f.close()

            if not os.path.isfile(opt.dataroot + 'vocabulary.pkl'):
                with open(opt.dataroot + 'vocabulary.pkl', 'wb') as f:
                    dill.dump(self.vocabulary, f, pickle.HIGHEST_PROTOCOL)
                f.close()
        else:
            self.mode = 'test'
            if os.path.isfile(opt.dataroot + 'test_data.pkl'):
                print("Loading the processed testing data file")
                with open(opt.dataroot + 'test_data.pkl', 'rb') as in_file:
                    self.test_data = dill.load(in_file)
                in_file.close()
            else:
                assert "Missing processed test dataset"

    def get_data(self, data_path):
        """
        Obtain the parsed data using the provided data file path

        Parameters:
            data_path  : Path to the data file

        Returns:
            The parsed data in a list format
        """
        file = open(data_path, 'r', encoding='utf8')
        lines = file.readlines()

        data = defaultdict(dict)
        for idx, line in enumerate(lines):
            source, target, length = self.pre_process_data(line)
            input = []
            for word in source:
                self.vocabulary.add_word(word)
                token = self.vocabulary.word2token[word]
                input.append(token)
            target = [self.vocabulary.word2token[word] for word in target]

            data[idx]['input'] = torch.LongTensor(input)
            data[idx]['target'] = torch.LongTensor(target)
            data[idx]['length'] = length

        file.close()

        return data

    def pre_process_data(self, line):
        """
        Parse the line in the semantic tree structure and get the sentence
        Also, performs few pre-processing to get rid of unwanted strings

        Parameters:
            line:   Unparsed raw line from the file

        Returns:
            Parsed line with some pre-processing
        """
        tree = Tree.fromstring(line)
        words = tree.leaves()

        # Remove some unwanted characters such as punctuation marks and special characters
        unwanted = ['``', '\'\'', '&', '!', '?', '@', '#', '$', '%', '\"\"']
        sentence = [word for word in words if word not in unwanted]

        # Add the Start-Of-Sentence (SOS) for the sentence
        # sentence = ['-SOS-'] + sentence + ['-EOS-']
        source = ['-SOS-'] + sentence
        source = source[:self.max_seq_len]
        target = sentence[:self.max_seq_len-1] + ['-EOS-']

        assert len(source) == len(target), "Mis-match in the source and target length"

        length = len(source)
        source.extend(['-PAD-'] * (self.max_seq_len - length))
        target.extend(['-PAD-'] * (self.max_seq_len - length))

        return source, target, length

    def load_data(self, mode, index, batch_size):
        """
        Return the data from a specific index
        """
        if mode == 'train':
            data = self.train_data
        elif mode == 'val':
            data = self.val_data
        else:
            data = self.test_data

        if (index + batch_size) > (len(data) - 1):
            return None, None, 0

        indices = [i for i in range(index, index+batch_size)]
        source = torch.LongTensor()
        target = torch.LongTensor()
        length = []

        for idx in indices:
            source = torch.cat((source, data[idx]['input'].view(1, -1)), dim=0)
            target = torch.cat((target, data[idx]['target'].view(1, -1)), dim=0)
            length.append(data[idx]['length'])

        return source, target, length

    def get_batched_data(self, mode):
        """Divide the data to batched chunks"""
        if mode == 'train':
            data = self.train_data
            batch_size = self.train_batch_size
        elif mode == 'val':
            data = self.val_data
            batch_size = self.test_batch_size
        else:
            data = self.test_data
            batch_size = self.test_batch_size

        num_batches = data.size(0) // batch_size
        data = data.narrow(0, 0, num_batches * batch_size)
        data = data.view(batch_size, -1).t().contiguous()

        return data


from collections import defaultdict
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import json

# load graph from json file and return series of graph-related variables
def init_graph(file_path, graph_num):
	graph_obj = json.loads(open(file_path,'r').read())
	graph_obj = graph_obj["graph" + graph_num]
	adjacency_list = graph_obj['diagraphModel']['adjacencyList']
	edges = graph_obj['diagraphModel']['edges']
	nodes = graph_obj['diagraphModel']['nodes']
	depiction_level = graph_obj['diagraphView']['depictionLevel']

	# remove all parents except one fron 'nodes' for coordinate-generation purposes
	for node in nodes:
		while len(nodes[node]["parent"]) > 1:
			par = nodes[node]["parent"].pop()
			nodes[par]["child"].remove(node)

	return (graph_obj, edges, nodes, adjacency_list, depiction_level)

# conduct depth-first traversal of graph to build list of childless nodes
def build_childless_list(l, present_node, nodes):
	# base case: if list is empty, simply add node
	if nodes[present_node]["child"] == []:
		l.append(present_node)
	else:
		for node in nodes[present_node]["child"]:
			if int(nodes[present_node]["_level"]) < int(nodes[node]["_level"]):
				build_childless_list(l, node, nodes)

# generate x-coordinates given adjacency_list and H
def generate_x_coordinates(depiction_level, H):
	inith = 0.0
	x_coord_dict = defaultdict(set)
	for level in depiction_level:
		for node in depiction_level[level]:
			n1 = len(depiction_level[level])
			x_coord_dict[node] = inith + (n1-1)*H
		inith += n1 * H

	return x_coord_dict

# adjust y-coordinates for proximity
def adjust_proximity(y_coord_dict, nodes, edges, mode = 'vertical'):
	for edge in edges:
		node1, node2 = edge.split("::")
		proxim = edges[edge]["proximity"]
		if proxim:
			# distance between the centres of the two nodes
			if mode == 'horizontal':
				dist = (nodes[node1]["height"] + nodes[node2]["height"]) / 2
			if mode == 'vertical':
				dist = (nodes[node1]["width"] + nodes[node2]["width"]) / 2
			if y_coord_dict[node1] < y_coord_dict[node2]:
				y_coord_dict[node2] = y_coord_dict[node1] + dist
			elif y_coord_dict[node1] > y_coord_dict[node2]:
				y_coord_dict[node2] = y_coord_dict[node1] - dist

	return y_coord_dict

# generate y-coordinates given depiction_level, nodes, edges, childless_list and V
def generate_y_coordinates(nodes, edges, depiction_level, childless_list, V, mode='vertical'):
	n = len(depiction_level)
	y_coord_dict = defaultdict(set)

	# set equally spaced y-coords for childless nodes: shadow points
	n1 = len(childless_list)
	Y_MAX = (n1//2) * V
	y_coords = list(np.linspace(-Y_MAX, Y_MAX, num = n1))
	for i in range(n1):
		node = childless_list[i]
		y_coord_dict[node] = y_coords[i]

	# based on positions of childless nodes, take averages of children to get y-coordinates of parent nodes
	for i in range(n-2,-1,-1):
		current_layer = depiction_level[str(i)]
		for node in current_layer:
			if node not in y_coord_dict:
				y_children = [y_coord_dict[i] for i in nodes[node]["child"] if i not in current_layer]
				y_coord_dict[node] = np.mean(y_children)

	if n == 1:
		current_layer = depiction_level["0"]
		for node in current_layer:
			if node not in y_coord_dict:
				y_children = [y_coord_dict[i] for i in nodes[node]["child"]]
				y_coord_dict[node] = np.mean(y_children)

	y_coord_dict = adjust_proximity(y_coord_dict, nodes, edges, mode)

	return y_coord_dict

# generate all coordinates
def generate_coordinates(nodes, edges, depiction_level, childless_list, mode = 'vertical'):
	n = len(depiction_level)
	coord_dict = defaultdict(set)

	# set V, H based on max height, width of nodes
	maxHeight = 5
	maxWidth = 10
	for node in nodes:
		if nodes[node]["height"] > maxHeight:
			maxHeight = nodes[node]["height"]
		if nodes[node]["width"] > maxWidth:
			maxWidth = nodes[node]["width"]

	if mode == 'horizontal':
		V = maxHeight*3/4
		H = max(2*V, maxWidth)
	if mode == 'vertical':
		V = maxWidth*3/4
		H = max(2*V, maxHeight)

	x_coord_dict = generate_x_coordinates(depiction_level, H)
	y_coord_dict = generate_y_coordinates(nodes, edges, depiction_level, childless_list, V)

	for node in x_coord_dict:
		if mode == 'horizontal':
			coord_dict[node] = (x_coord_dict[node], y_coord_dict[node])
		if mode == 'vertical':
			coord_dict[node] = (y_coord_dict[node], -x_coord_dict[node])

	return coord_dict

# generates desired graph from given graph, coordinates
def plot_coord_graph(adjacency_list, depiction_level, coord_dict, nodes, mode='vertical'):
	fig = plt.figure()
	ax = fig.add_subplot(111)

	# plot nodes
	for node in coord_dict:
		height, width = nodes[node]["height"], nodes[node]["width"]
		startx = coord_dict[node][0] - width/2
		starty = coord_dict[node][1] - height/2
		ax.add_patch( Rectangle((startx, starty), width, height, fc='b', ec='black', lw=0.5) )
		if mode == 'vertical':
			ax.annotate(node, (startx+width/2, starty-height))
		if mode == 'horizontal':
			ax.annotate(node, (startx+width/2, starty+height))

	# generate list of edges
	edge_list = []
	for cons in list(adjacency_list.values()):
		for i in cons:
			node1, node2 = i.split('::')
			edge_list.append((node1, node2))

	# plot arrows between connections, parent to child
	for node1, node2 in edge_list:
		x,y = coord_dict[node1]
		x1,y1 = coord_dict[node2][0], coord_dict[node2][1]
		posx, posy = (x+x1)/2, (y+y1)/2
		y_step = 0.05 * (y1-y)
		x_step = 0.05 * (x1-x)
		line = ax.plot([x,x1],[y,y1],color='black')[0]
		#plt.arrow(posx, posy, x_step, y_step, shape='full', length_includes_head=True, head_width=0.001)
		line.axes.annotate("", xy=(posx+x_step,posy+y_step), xytext=(posx, posy), arrowprops=dict(arrowstyle="-|>"))

	# get and set axes limits
	MIN_LIM = 7.5
	left, right = ax.get_xlim()
	if np.abs(left-right) < MIN_LIM:
		ax.set_xlim((left-MIN_LIM, right+MIN_LIM))
	bottom, top = ax.get_ylim()
	if np.abs(bottom-top) < MIN_LIM:
		ax.set_ylim((bottom-MIN_LIM, top+MIN_LIM))

	# show graph
	plt.show()

def main():
	# input file_path and graph_num
	file_path = input("Enter graph file path: ")
	graph_num = input("Enter graph number: ")
	# load graph
	graph_obj, edges, nodes, adjacency_list, depiction_level = init_graph(file_path, graph_num)

	# build childless_list
	childless_list = []
	for i in depiction_level["0"]:
		build_childless_list(childless_list, i, nodes)

	mode = input("Enter view (vertical/horizontal): ")
	coord_dict = generate_coordinates(nodes, edges, depiction_level, childless_list, mode)
	#print(depiction_level)
	#print(coord_dict)

	# plot graph
	plot_coord_graph(adjacency_list, depiction_level, coord_dict, nodes, mode)

main()


# coding=utf-8
import urllib2
from bs4 import BeautifulSoup as bs
import hashlib, time, json

_time = time.strftime('%Y%m%d',time.localtime(time.time())) # 当前时间 格式为yearmonthday

def moviespider():
    url = 'http://theater.mtime.com/China_Zhejiang_Province_Fenghua/3869/'

    page = urllib2.urlopen(url)
    soup = bs(page)

    original = soup.find_all(class_='table')
    m_count = len(original)
    movie_list = []
    movie_name = []
    movie_time = []
    movie_price = []

    for i in range(0, m_count):
        name_temp = []
        time_temp = []
        price_temp = []

        name_temp.append(original[i].find(class_='c_000').text)

        for t in original[i].find_all('strong'):
            time_temp.append(t.text)
        #time_temp=qc(time_temp)
        for p in original[i].find_all('em'):
            price_temp.append(p.text)

        movie_name.extend(name_temp)
        movie_time.append(time_temp)
        movie_price.append(price_temp)

    movie_list.append(movie_name)
    movie_list.append(movie_time)
    movie_list.append(movie_price)

    return movie_list

def verification(request):
    """
    接入和消息推送校验
    """
    signature = request.GET.get('signature')
    timestamp = request.GET.get('timestamp')
    nonce = request.GET.get('nonce')

    token = 'seyren'
    tmplist = [token, timestamp, nonce]
    tmplist.sort()
    tmpstr = ''.join(tmplist)
    hashstr = hashlib.sha1(tmpstr).hexdigest()

    if hashstr == signature:
        return True
    return False

def parse_movie_list(movie_list):
    for x in xrange(len(movie_list[0])):
        for y in xrange(len(movie_list[1][x])):
            return movie_list[0][x] + '\n' + movie_list[1][x][y] + movie_list[2][x][y]