# Copyright (C) to Yingcong Tan, Andrew Delong, Daria Terekhov. All Rights Reserved.

import numpy as np
import torch
from .util import as_tensor
from .util import as_numpy

_LINPROG_CENTRAL_PATH = []

def _collect_linprog_central_path(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t):
    global _LINPROG_CENTRAL_PATH
    if step == 0:
        _LINPROG_CENTRAL_PATH = []
    _LINPROG_CENTRAL_PATH.append((step, as_numpy(x), as_numpy(dx)))
    return _LINPROG_CENTRAL_PATH

def _arr2str(x, indent=0):
    return np.array2string(x, precision=4, max_line_width=100, threshold=5, floatmode='fixed', suppress_small=True, prefix=' '*indent)

def _eps_schedule_decay(start, end, steps):
    k = np.log(end/start)/steps
    return lambda step: np.maximum(end, start*np.exp(k*step))

def _eps_schedule_const(eps):
    return lambda step: eps

def linprog_step_printer():
    """Returns a callback that prints the state of each linprog step."""

    def callback(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t):
        c = as_numpy(c).ravel()
        x = as_numpy(x).ravel()
        cx = np.dot(x, c)
        step_str = "done" if step is None else "%04d" % step
        print("linprog[%s]: x=%s cx=%s t=%.2f" % (step_str, _arr2str(x), _arr2str(cx), t))

    return callback

def inverse_linprog_step_printer(want_constraints=False):
    """Returns a callback that prints the state of each inverse_linprog step."""

    def callback(step,
                 c, A_ub, b_ub, A_eq, b_eq,
                 dc, dA_ub, db_ub, dA_eq, db_eq,
                 x_target, x_predict, loss):

        c = as_numpy(c).ravel()
        x = as_numpy(x_predict).ravel()
        step_str = "done" if step is None else "%04d" % step
        print("inverse_linprog[%s]: c=%s x*=%s loss=%.5f" % (step_str, _arr2str(c), _arr2str(x), loss))
        if want_constraints:
            print("   A_ub: %s" % _arr2str(as_numpy(A_ub), 9))
            print("   b_ub: %s" % _arr2str(as_numpy(b_ub), 9))
            if A_eq is not None:
                print("   A_eq: %s" % _arr2str(as_numpy(A_eq), 9))
                print("   b_eq: %s" % _arr2str(as_numpy(b_eq), 9))

    return callback

def _line_search(f, x, dx, f_x, grad_f_x, alpha=0.3, beta=0.25):
    # Algorithm 9.2 from the BV book
    # Use "not a < b" rather than "a > b" so that loop continues while a is nan
    step_size = 1.0
    while not f(x + step_size * dx) <= f_x + (alpha*step_size) * (grad_f_x.t() @ dx):
        step_size *= beta
        if step_size == 0.0:
            raise RuntimeError("line search encountered a step size of zero!")
    return step_size

# Allows _linprog_ip to raise an error that specifically
# identifies that matrix inverse failed (probably non-singular)
# Useful for backing up in line search.
class MatrixInverseError(RuntimeError):
    pass

def _linprog_ip(x, c, A_ub, b_ub, A_eq, b_eq,
                 max_steps, t0, mu, eps, callback):
    """Returns a solution to the given LP using the interior point method."""
    assert (A_eq is None) == (b_eq is None)

    # TODO: Unfortunately PyTorch doesn't handle zero-length tensor dimensions correctly yet (unlike numpy)
    #       so we cannot simply sete A_eq to a (0, m)-tensor and let the remaining code go through.
    #       Instead we must constantly check if A_eq is None and do something special.

    m = len(c)        # Number of variables
    n_ub = len(A_ub)  # Number inequality constraints
    n_eq = len(A_eq) if A_eq is not None else 0  # Number equality constraints

    # Parameters of the algorithm
    t = t0

    # Objective function of barrier method f(x) = t * c'x - \sum_i log(-ai'x +bi)
    # Note that x inside the lambda does not refer to the _linprog_ip argument x already in scope,
    # but the t value is captured by reference from _linprog_ip and will be whatever the
    # current value of t is whenever it's invoked
    f = lambda x: t*(c.t() @ x) - torch.sum(torch.log(-(A_ub @ x - b_ub)))

    # Initial callback at step 0
    if callback:
        if callback(0, c, A_ub, b_ub, A_eq, b_eq, x, None, t) == True:
            return x

    # Run interior point inner loop
    for step in range(1, max_steps+1):

        # Newton step to next point on central path
        d = 1 / (b_ub - A_ub @ x)
        grad_phi = A_ub.t() @ d                # Gradient of barrier phi(x)
        hess_phi = A_ub.t() @ ((d**2) * A_ub)  # Hessian of barrier phi(x)
                                               # (Equiv to A.t() @ torch.diagflat(d**2) @ A)
        grad_obj = t*c  # Gradient of t c'x
        hess_obj = 0    # Hessian of t c'x

        grad_f = grad_obj + grad_phi  # Gradient of f(x) = tc'x + phi(x)
        hess_f = hess_obj + hess_phi  # Hessian of f(x) = tc'x + phi(x)

        if A_eq is not None:
            # Newton WITH equality constraints
            # M = [[ H  A' ],
            #      [ A  0  ]]
            # where H is Hessian of the entire objective f(x) = t*c'x + phi(x)
            # (10.19 in BV book)
            M = torch.cat((torch.cat((hess_f, A_eq.t()), 1),
                           torch.cat((A_eq, torch.zeros(n_eq, n_eq, dtype=A_eq.dtype)), 1)), 0)
            # v =  [[     -g ],
            #       [ b - Ax ]],
            # where g is gradient of the entire objective f(x) = t*c'x + phi(x)
            # (10.19 in BV book)
            v = torch.cat((-grad_f, b_eq - A_eq @ x), 0)

        else:
            # Newton WITHOUT equality constraints
            M = hess_f
            v = -grad_f

        # Compute Newton step for infeasible points
        try:
            dxw = torch.inverse(M) @ v      # Direction of Newton step with slack variables w
        except RuntimeError as e:
            if any("Lapack Error" in arg for arg in e.args):
                raise MatrixInverseError(*e.args)
            raise
        dx = dxw[:m]                    # Strip off slack variables w

        # Checking stopping criterion of newton's method
        lamb = v.t() @ dxw
        if lamb*0.5 <= eps:  # Stopping criterion of newton's method
            t *= mu     # Update t

            # Report current state. If callback returns True, terminate
            if callback:
                if callback(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t) == True:
                    break
        else:           # Update x based on gradient if stopping criterion is not met
            step_size = _line_search(f, x, dx, f(x), grad_f)
            x = x + step_size*dx
            if max(abs(x)>1e30):
                raise UnboundedConstraintsError

        # Report current state. If callback returns True, terminate
        if callback:
            if callback(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t) == True:
                break

        # Stop when accuracy below eps
        if n_ub/t < eps:
            break

        step += 1

    # Report final state
    if callback:
        callback(None, c, A_ub, b_ub, A_eq, b_eq, x, None, t)

    return x

# Allows linprog_feasible to raise an error that specifically
# identifies that an infeasible instance was detected and that no feasible
# point will be returned. Useful for backing up in line search.
class InfeasibleConstraintsError(RuntimeError):
    pass
class UnboundedConstraintsError(RuntimeError):
    pass

def linprog_feasible(A_ub, b_ub, A_eq=None, b_eq=None,
                     max_steps=100, t0=1.0, mu=2.0, eps=0.001,
                     callback=None):  # TODO increase t0 once line search implemented
    """Returns a strictly feasible point for the given LP."""
    assert max_steps >= 1
    assert (A_eq is None) == (b_eq is None)

    # If slack variable < 0 and the equality constraints are satisfied, then we can stop.
    def is_feasible(x, A_eq, b_eq):
        return x[-1] < 0 and (A_eq is None or torch.allclose(A_eq @ x - b_eq, torch.zeros_like(b_eq), atol=1e-5))

    # Terminates _linprog_ip as soon as a feasible point is found
    def check_feasible(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t):
        if callback is not None:
            callback(step, c, A_ub, b_ub, A_eq, b_eq, x, dx, t)  # Forward args to user callback if applicable
        return is_feasible(x, A_eq, b_eq)

    n_ub, m = A_ub.shape
    n_eq, _ = A_eq.shape if A_eq is not None else (0, m)
    assert m == _, "expected same number of columns in A_ub and A_eq"

    # Construct x_init=(x0, s0) such that x_init is strictly feasible wrt inequalities of the max-infeasibility LP
    x0 = torch.zeros((m, 1), dtype=torch.double)
    s0 = torch.min(b_ub).view(-1, 1) * -1.5 + 1 # Equivalent to max(A_ub @ x0 - b_ub) when x0=0
    x_init = torch.cat((x0, s0), 0)

    # Construct the max-infeasibility LP
    c = torch.cat((torch.zeros((m, 1), dtype=torch.double),
                   torch.ones((1, 1), dtype=torch.double)), 0)
    A_ub = torch.cat((A_ub, -torch.ones((n_ub, 1), dtype=torch.double)), 1)
    A_eq = torch.cat((A_eq, torch.zeros((n_eq, 1), dtype=torch.double)), 1) if A_eq is not None else None

    # Hack to prevent infeasibility problem instance from being unbounded (nonsingular Hessian)
    s_lower_bound = 10.0*(1.0 + torch.max(torch.abs(A_ub.detach()))).view(1, 1)   # Make lower bound dependent on scale of constraint coefficients
    A_ub = torch.cat((A_ub, -c.t()), 0)
    b_ub = torch.cat((b_ub, s_lower_bound), 0)

    # Solve the max-infeasible LP with interior point
    x_center = _linprog_ip(x_init, c, A_ub, b_ub, A_eq, b_eq,
                           max_steps=max_steps, t0=t0, mu=mu, eps=eps,
                           callback=check_feasible)

    # Check strict feasibility
    if not is_feasible(x_center, A_eq, b_eq):
        raise InfeasibleConstraintsError("Constraints were not strictly feasible, or strictly feasible point not found in allotted steps.")

    # Return strictly feasible point for original LP
    return x_center[:-1]

def linprog(c, A_ub, b_ub, A_eq=None, b_eq=None,
            max_steps=100, t0=1.0, mu=2.0, eps=1e-5,
            callback=None):
    """Returns a solution to the given LP using the interior point method."""

    x = linprog_feasible(A_ub, b_ub, A_eq, b_eq)  # A_eq, b_eq deliberately omitted, since subsequent _linprog_ip is infeasible start Newton
    x = _linprog_ip(x, c, A_ub, b_ub, A_eq, b_eq,
                    max_steps=max_steps, t0=t0, mu=mu, eps=eps,
                    callback=callback)

    # Sanity check that equality constraints are satisfied.
    # If the system is properly infeasible, it should have been caught by linprog_feasible raising an exception, so this is an internal check.
    if A_eq is not None:
        assert torch.allclose(A_eq @ x - b_eq, torch.zeros_like(b_eq), atol=1e-5), "linprog failed to satisfy equality constraints, but also failed to detect infeasibility, so there's something wrong"

    return x

def custom_linprog(**custom_linprog_kwargs):
    """Returns a callable linprog() with custom default settngs.

    Useful for specifying a new default eps, for example.
    """
    def callback(*args, **kwargs):
        kwargs.update(custom_linprog_kwargs)
        return linprog(*args, **kwargs)
    return callback

def squared_error(c, x_target, x_predict):
    return (x_target - x_predict)**2

def abs_duality_gap(c, x_target, x_predict):
    return torch.abs(c.t() @ (x_target - x_predict))

def inverse_linprog(x_target, c, A_ub, b_ub, A_eq=None, b_eq=None,
                    max_steps=100,
                    eps=1e-5, #defaul value for the end of eps_decay
                    eps_decay=False,
                    learn_rate_c=10.0,
                    learn_rate_ub=0.0,
                    learn_rate_eq=0.0,
                    loss=squared_error,
                    callback=None,
                    normalize=True,
                    return_loss=False,
                    solver=linprog):
    """Solves the inverse linear programming problem."""

    # TODO: Unfortunately PyTorch doesn't handle zero-length tensor dimensions correctly yet (unlike numpy)
    #       so we cannot simply replace A_eq with a (0, m) and let the remaining code go through.
    #       Instead we must constantly check if A_eq is None.

    c = c.clone()
    A_ub = A_ub.clone()
    b_ub = b_ub.clone()
    A_eq = A_eq.clone() if A_eq is not None else None
    b_eq = b_eq.clone() if b_eq is not None else None

    solver_callback = _collect_linprog_central_path if callback else None

    # Project c to have unit norm. TODO also normalize constraint coefficients?
    if normalize and len(c) > 1:
        c /= sum(abs(c))

    def reset_grads():
        for p in (c, A_ub, b_ub, A_eq, b_eq):
            if p is not None:
                p.requires_grad_()         # Flag the parameters as needing a gradient
                if p.grad is not None:
                    p.grad.data.zero_()    # But also zero out inplace any values leftover from the previous gradient

    def detach_params():
        for p in (c, A_ub, b_ub, A_eq, b_eq):
            if p is not None:
                p.detach_()                # Stop tracing computations made with these parameters, essentially fixing them

    def run_forward_loss(c, A_ub, b_ub, A_eq, b_eq, eps, solver_callback):
        # Solve for x given fixed problem coefficients
        x_predict = solver(c, A_ub, b_ub, A_eq, b_eq, eps = eps, callback=solver_callback)
        # Compute error with respect to training target
        curr_loss = torch.mean(torch.sum(loss(c, x_target, x_predict), 0))

        # Currently the loss is just the error.
        # In future it may include priors on c and constraints.
        return curr_loss, x_predict

    # compute the eps at each step which decay from 0.1 (at step 0) to eps (at final step)
    if eps_decay:
        eps_schedule = _eps_schedule_decay(0.1, eps, max_steps)
    else:
        eps_schedule = _eps_schedule_const(eps)

    # Outer loop trains the coefficients defining the LP
    step_size = 0.05
    for step in range(1, max_steps+1):
        reset_grads()  # Reset the gradients so that they don't accumulate from previous outer loop iteration

        # Compute the current loss and backpropagate it to the initial parameters
        curr_loss, x_predict = run_forward_loss(c, A_ub, b_ub, A_eq, b_eq,
                                                eps_schedule(step-1), solver_callback)
                                                # steps start at 0
        curr_loss.backward()
        if step == 1:
            inital_loss = as_numpy(curr_loss)
        # Detach the parameters once gradient for this iteration is computed
        detach_params()

        with torch.no_grad():

            dc = -learn_rate_c*c.grad
            dA_ub = -learn_rate_ub*A_ub.grad
            db_ub = -learn_rate_ub*b_ub.grad
            dA_eq = -learn_rate_eq*A_eq.grad if A_eq is not None else None
            db_eq = -learn_rate_eq*b_eq.grad if b_eq is not None else None

            # Linesearch which heuristically accepts any decrement.
            beta = 0.5
            step_size = min(1.0, step_size/beta)  # Give the step size a boost compared to last time
            while step_size > 1e-8:
                # Create step in parameter space
                _c = c + step_size*dc
                _A_ub = A_ub + step_size*dA_ub
                _b_ub = b_ub + step_size*db_ub
                _A_eq = A_eq + step_size*dA_eq if A_eq is not None else None
                _b_eq = b_eq + step_size*db_eq if A_eq is not None else None
                if normalize and len(_c) > 1:
                    _c /= sum(abs(_c))

                # Evaluate loss at that point, and accept the step if loss is an improvement.
                try:
                    trial_loss, trial_x_predict = run_forward_loss(_c, _A_ub, _b_ub, _A_eq, _b_eq, eps_schedule(step-1), None)
                    if trial_loss < curr_loss:
                        break
                except InfeasibleConstraintsError:
                    pass  # linprog_feasible failed
                except UnboundedConstraintsError:
                    pass  # unbounded solution
                except RuntimeError as err:
                    msg, *_ = err.args
                    if "Lapack Error" not in msg:  # torch.inverse probably failed
                        raise

                # Otherwise reduce step size by factor beta
                step_size *= beta
            else:
                # If step size got to floating point zero, then give up
                break

            # Report current state
            if callback:
                callback(step, c, A_ub, b_ub, A_eq, b_eq, dc, dA_ub, db_ub, dA_eq, db_eq, x_target, x_predict, curr_loss.item())

            # Take a learning step
            c = _c
            A_ub = _A_ub
            b_ub = _b_ub
            A_eq = _A_eq
            b_eq = _b_eq

            # Project c to have unit norm.
            if normalize and len(c) > 1:
                c /= sum(abs(c))

    # Report final state
    if callback:
        callback(None, c, A_ub, b_ub, A_eq, b_eq, None, None, None, None, None, x_target, x_predict, curr_loss.item())

    # Only return as many parameters as the user specified.
    if return_loss == True:
        # using low eps value to compute loss and x_final with high accuracy
        final_loss, x_final = run_forward_loss(c, A_ub, b_ub, A_eq, b_eq, 1e-7, solver_callback)
        if A_eq is None:
            return c, A_ub, b_ub, final_loss, x_final, inital_loss
        else:
            return c, A_ub, b_ub, A_eq, b_eq, final_loss, x_final,inital_loss
    else:
        if A_eq is None:
            return c, A_ub, b_ub
        else:
            return c, A_ub, b_ub, A_eq, b_eq


from flask import Blueprint, request,jsonify
from handler.organizations import OrganizationsHandler
organizations = Blueprint('organizations', __name__)

@organizations.route('/', methods=['GET', 'POST'])
def getAllOrganizations():
    if request.method == 'POST':
      return jsonify(Message="Organization created."), 200
    else:
        if not request.args:
            return OrganizationsHandler().getAllOrganizations()
        else:
            return OrganizationsHandler().searchOrganizations(request.args)

@organizations.route('/<int:organization_id>', methods=['GET', 'PUT', 'DELETE'])
def getOrganizationById(organization_id):
    if request.method == 'GET':
        return OrganizationsHandler().getOrganizationById(organization_id)
    elif request.method == 'PUT':
        #OrganizationsHandler().updateOrganization(organization_id,request.form)
        return jsonify(Message="Organization update successful"), 200
    elif request.method == 'DELETE':
        #OrganizationsHandler().deleteOrganization(organization_id)
        return jsonify(Message="Organization delete successful"), 200
    else:
        return jsonify(Error="Method not allowed."), 405


from django.conf.urls import url

from .views import index, enroll, lottery, receiver

urlpatterns = [
    url(r'^$', index, name='index'),
    url(r'^enroll/$', enroll, name='enroll'),
    url(r'^do_lottery/$', lottery, name='lottery'),
    url(r'^receiver/$', receiver, name='receiver'),
]


import multiprocessing as mp

def worker():
    print("SubProcess End")

if __name__ == "__main__":
    # process spawning: 부모 프로세스(Parent Proecess)가 운영체제에 요청하여 자식 프로세스(Child Process)를 새로 만들어내는 과정
    # MainProcess가 부모
    # SubProcess가 자식
    p = mp.Process(name="SubProcess", target=worker)
    p.start()

# https://wikidocs.net/85603


"""Shared plotting functions
"""
import json
import os

from math import log10, floor

from boltons.iterutils import pairwise
from geopy.distance import vincenty
from osgeo import gdal
from matplotlib.colors import LogNorm, ListedColormap, BoundaryNorm
from matplotlib.image import BboxImage
from matplotlib.legend_handler import HandlerBase
from matplotlib.transforms import Bbox, TransformedBbox

import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

def load_config():
    """Read config.json
    """
    config_path = os.path.join(os.path.dirname(__file__), '..', 'config.json')
    with open(config_path, 'r') as config_fh:
        config = json.load(config_fh)
    return config

def get_data(filename):
    """Read in data (as array) and extent of each raster
    """
    gdal.UseExceptions()
    ds = gdal.Open(filename)
    data = ds.ReadAsArray()
    data[data < 0] = 0

    gt = ds.GetGeoTransform()

    # get the edge coordinates
    width = ds.RasterXSize
    height = ds.RasterYSize
    xres = gt[1]
    yres = gt[5]

    xmin = gt[0]
    xmax = gt[0] + (xres * width)
    ymin = gt[3] + (yres * height)
    ymax = gt[3]

    lat_lon_extent = (xmin, xmax, ymax, ymin)

    return data, lat_lon_extent

def get_tz_axes():
    """Setup plot figure and return Tanzania axes
    """
    plt.figure(figsize=(7, 7), dpi=300)
    proj_lat_lon = ccrs.PlateCarree()
    ax = plt.axes([0.025, 0.025, 0.95, 0.93], projection=proj_lat_lon)
    x0 = 28.6
    x1 = 41.4
    y0 = 0.5
    y1 = -12.5
    ax.set_extent([x0, x1, y0, y1], crs=proj_lat_lon)
    set_ax_bg(ax)
    return ax

def hazard_legend(im, ax):
    # Add colorbar
    cbar = plt.colorbar(
        im, ax=ax, fraction=0.05, pad=0.04, drawedges=False,
        shrink=0.9, orientation='horizontal',
        ticks=[0.5, 1, 1.5, 2, 998],
        boundaries=[0.01,0.5,1,1.5,2,998]
    )
    cbar.ax.set_xticklabels(["0.5", "1.0", "1.5", "2.0", ">2.0"])
    cbar.outline.set_color("none")
    cbar.ax.set_xlabel('Flood depth (m)')

def get_hazard_cmap_norm():
    cmap = ListedColormap(['none', '#d8efff', '#bfe4ff', '#93d4ff', '#2d8ccb', '#00519e'])
    norm = BoundaryNorm([0, 0.01, 0.5, 1, 1.5, 2, 998], cmap.N)
    return cmap, norm

def set_ax_bg(ax):
    ax.background_patch.set_facecolor('#c6e0ff')

def save_fig(output_filename):
    plt.savefig(output_filename)
    plt.savefig(output_filename.replace("png", "svg"))

def plot_basemap(ax, data_path):
    """Plot countries and regions background
    """
    proj = ccrs.PlateCarree()

    states_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_admin_0_countries_lakes.shp'
    )

    states_over_lakes_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_admin_0_countries.shp'
    )

    provinces_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_admin_1_states_provinces_lakes.shp'
    )

    lakes_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_lakes.shp'
    )

    # Neighbours
    for record in shpreader.Reader(states_filename).records():
        country_code = record.attributes['ISO_A2']
        if country_code in ('BI', 'RW', 'CD', 'UG', 'KE', 'ZM', 'MW', 'MZ', 'SO'):
            geom = record.geometry
            ax.add_geometries(
                [geom],
                crs=proj,
                edgecolor='white',
                facecolor='#e0e0e0',
                zorder=1)

    # Regions
    for record in shpreader.Reader(provinces_filename).records():
        country_code = record.attributes['iso_a2']
        if country_code == 'TZ':
            geom = record.geometry
            ax.add_geometries([geom], crs=proj, edgecolor='#ffffff', facecolor='#d2d2d2')

    # Lakes
    for record in shpreader.Reader(lakes_filename).records():
        name = record.attributes['name']
        geom = record.geometry

        if name in (
                'Lake Victoria',
                'Lake Tanganyika',
                'Lake Malawi',
                'Lake Kivu',
                'Lake Edward',
                'Lake Rukwa',
                'Lake Bunyoni',
                'Lake Natron',
                'Lake Manyara',
                'Lake Lembeni',
                'Lake Eyasi'):
            ax.add_geometries(
                [geom],
                crs=proj,
                edgecolor='none',
                facecolor='#c6e0ff',
                zorder=1)

    # Tanzania, political border
    for record in shpreader.Reader(states_over_lakes_filename).records():
        country_code = record.attributes['ISO_A2']
        if country_code == 'TZ':
            geom = record.geometry
            ax.add_geometries([geom], crs=proj, edgecolor='#a0a0a0', facecolor='none')

def plot_basemap_labels(ax, data_path):
    """Plot countries and regions background
    """
    proj = ccrs.PlateCarree()
    extent = ax.get_extent()

    provinces_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_admin_1_states_provinces_lakes.shp'
    )

    lakes_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_lakes.shp'
    )

    # Neighbour labels
    neighbours = [
        {'country': 'Kenya', 'cx': 36.9, 'cy': -2.1},
        {'country': 'Uganda', 'cx': 29.9, 'cy': -0.8},
        {'country': 'Rwanda', 'cx': 29.5, 'cy': -1.9},
        {'country': 'Burundi', 'cx': 29.3, 'cy': -3.2},
        {'country': 'DRC', 'cx': 28.7, 'cy': -5.8},
        {'country': 'Zambia', 'cx': 32.1, 'cy': -10.5},
        {'country': 'Malawi', 'cx': 33.5, 'cy': -11.7},
        {'country': 'Mozambique', 'cx': 37.1, 'cy': -12.3}
    ]
    for neighbour in neighbours:
        x = neighbour['cx']
        y = neighbour['cy']
        if within_extent(x, y, extent):
            ax.text(
                x, y,
                neighbour['country'].upper(),
                alpha=0.7,
                size=9,
                horizontalalignment='left',
                transform=proj)

    # Regions
    nudge_regions = {
        'Dar-Es-Salaam': (0.2, 0),
        'Kagera': (0.2, 0),
        'Kilimanjaro': (0.2, 0),
        'Manyara': (0.15, 0.1),
        'Morogoro': (0.25, 0),
        'Pwani': (0.1, -0.2),
    }

    no_label_regions = [
        'Kaskazini-Pemba',
        'Kaskazini-Unguja',
        'Kusini-Pemba',
        'Zanzibar South and Central',
        'Zanzibar West'
    ]

    for record in shpreader.Reader(provinces_filename).records():
        country_code = record.attributes['iso_a2']
        if country_code == 'TZ':
            geom = record.geometry
            centroid = geom.centroid
            cx = geom.centroid.x
            cy = geom.centroid.y
            name = record.attributes['name']

            if name in no_label_regions:
                continue

            if name in nudge_regions:
                dx, dy = nudge_regions[name]
                cx += dx
                cy += dy

            if name == 'Dar-Es-Salaam':
                ha = 'left'
            else:
                ha = 'center'

            if within_extent(cx, cy, extent):
                ax.text(
                    cx,
                    cy,
                    name,
                    alpha=0.7,
                    size=8,
                    horizontalalignment=ha,
                    transform=proj)

    # Lakes
    for record in shpreader.Reader(lakes_filename).records():
        name = record.attributes['name']
        geom = record.geometry
        if name in (
                'Lake Victoria',
                'Lake Tanganyika',
                'Lake Malawi'):
            cx = geom.centroid.x
            cy = geom.centroid.y
            # nudge
            if name == 'Lake Victoria':
                cy -= 0.2

            if within_extent(cx, cy, extent):
                ax.text(
                    cx,
                    cy,
                    name,
                    alpha=0.7,
                    size=7,
                    horizontalalignment='center',
                    transform=proj)

    # Ocean
    cx = 39.8
    cy = -7.3
    if within_extent(cx, cy, extent):
        ax.text(
            cx,
            cy,
            'Indian Ocean',
            alpha=0.7,
            size=7,
            horizontalalignment='left',
            transform=proj)

def within_extent(x, y, extent):
    xmin, xmax, ymin, ymax = extent
    return xmin < x and x < xmax and ymin < y and y < ymax

def scale_bar(ax, length=100, location=(0.5, 0.05), linewidth=3):
    """Draw a scale bar

    Adapted from https://stackoverflow.com/questions/32333870/how-can-i-show-a-km-ruler-on-a-cartopy-matplotlib-plot/35705477#35705477

    Parameters
    ----------
    ax : axes
    length : int
        length of the scalebar in km.
    location: tuple
        center of the scalebar in axis coordinates (ie. 0.5 is the middle of the plot)
    linewidth: float
        thickness of the scalebar.
    """
    # lat-lon limits
    llx0, llx1, lly0, lly1 = ax.get_extent(ccrs.PlateCarree())

    # Transverse mercator for length
    x = (llx1 + llx0) / 2
    y = lly0 + (lly1 - lly0) * location[1]
    tmc = ccrs.TransverseMercator(x, y)

    # Extent of the plotted area in coordinates in metres
    x0, x1, y0, y1 = ax.get_extent(tmc)

    # Scalebar location coordinates in metres
    sbx = x0 + (x1 - x0) * location[0]
    sby = y0 + (y1 - y0) * location[1]
    bar_xs = [sbx - length * 500, sbx + length * 500]

    # Plot the scalebar and label
    ax.plot(bar_xs, [sby, sby], transform=tmc, color='k', linewidth=linewidth)
    ax.text(sbx, sby + 10*length, str(length) + ' km', transform=tmc,
            horizontalalignment='center', verticalalignment='bottom')

def plot_pop(plt, ax, data_path):
    """Plot population background
    """
    # WorldPop TZA_popmap15adj_v2b
    population_filename = os.path.join(data_path, 'Infrastructure', 'Population',
                                       'TZA_popmap15adj_v2b_resampled.tif')

    # Read in raster data
    gdal.UseExceptions()
    ds = gdal.Open(population_filename)
    data = ds.ReadAsArray()
    data[data < 0] = 0

    gt = ds.GetGeoTransform()

    # get the edge coordinates
    width = ds.RasterXSize
    height = ds.RasterYSize
    xres = gt[1]
    yres = gt[5]

    xmin = gt[0]
    xmax = gt[0] + (xres * width)
    ymin = gt[3] + (yres * height)
    ymax = gt[3]

    lat_lon_extent = (xmin, xmax, ymax, ymin)

    # Create color map
    colors = plt.get_cmap('Greys')

    # Plot population data
    ax.imshow(data, extent=lat_lon_extent, cmap=colors, norm=LogNorm(vmin=0.1, vmax=10000), zorder=1, alpha=0.5)

def plot_regions(ax, data_path):
    """Plot regions background
    """
    proj_lat_lon = ccrs.PlateCarree()

    # Regions
    provinces_filename = os.path.join(
        data_path,
        'Infrastructure',
        'Boundaries',
        'ne_10m_admin_1_states_provinces_lakes.shp'
    )

    # Regions
    for record in shpreader.Reader(provinces_filename).records():
        country_code = record.attributes['iso_a2']
        if country_code == 'TZ':
            geom = record.geometry
            ax.add_geometries([geom], crs=proj_lat_lon, edgecolor='#ffffff', facecolor=(1, 1, 1, 0), zorder=2)

            centroid = geom.centroid
            cx = geom.centroid.x
            cy = geom.centroid.y
            name = record.attributes['name']

            skip_regions = [
                'Dar-Es-Salaam',
                'Kusini-Pemba',
                'Kaskazini-Pemba',
                'Kaskazini-Unguja',
                'Zanzibar South and Central',
                'Zanzibar West',
            ]
            if name in skip_regions:
                continue

            nudge_regions = {
                'Kagera': (0.2, 0),
                'Manyara': (0.1, 0.1),
                'Pwani': (0.1, -0.2),
            }

            if name in nudge_regions:
                dx, dy = nudge_regions[name]
                cx += dx
                cy += dy

            if name == 'Dar-Es-Salaam':
                ha = 'left'
            else:
                ha = 'center'

            ax.text(
                cx,
                cy,
                name.upper(),
                alpha=0.3,
                size=6,
                horizontalalignment=ha,
                transform=proj_lat_lon)

def line_length(line, ellipsoid='WGS-84'):
    """Length of a line in meters, given in geographic coordinates

    Adapted from https://gis.stackexchange.com/questions/4022/looking-for-a-pythonic-way-to-calculate-the-length-of-a-wkt-linestring#answer-115285

    Args:
        line: a shapely LineString object with WGS-84 coordinates
        ellipsoid: string name of an ellipsoid that `geopy` understands (see
            http://geopy.readthedocs.io/en/latest/#module-geopy.distance)

    Returns:
        Length of line in meters
    """
    if line.geometryType() == 'MultiLineString':
        return sum(line_length(segment) for segment in line)

    return sum(
        vincenty(a, b, ellipsoid=ellipsoid).meters
        for a, b in pairwise(line.coords)
    )

class HandlerImage(HandlerBase):
    """Use image in legend

    Adapted from https://stackoverflow.com/questions/42155119/replace-matplotlib-legends-labels-with-image
    """
    def __init__(self, path, space=15, offset=5):
        self.space = space
        self.offset = offset
        self.image_data = plt.imread(path)
        super(HandlerImage, self).__init__()

    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        scale = 1.5
        bb = Bbox.from_bounds(
            xdescent + self.offset,
            ydescent,
            height * self.image_data.shape[1] / self.image_data.shape[0] * scale,
            height * scale)

        tbb = TransformedBbox(bb, trans)
        image = BboxImage(tbb)
        image.set_data(self.image_data)

        self.update_prop(image, orig_handle, legend)
        return [image]

def get_border_points():
    """Return id=>label dictionary of border crossing points
    """
    return {
        'air': {
            'HTAR': 'Arusha',
            'HTDA': 'Julius Nyerere',
            'HTKJ': 'Kilimanjaro ',
        },
        'road': {
            7507: 'Sirari',
            6306: 'Namanga',
            4028: 'Kasumulu',
            8406: 'Rusumo',
            5822: 'Holili',
            5313: 'Horohoro',
            4012: 'Tunduma',
            8529: 'Kabanga',
            8407: 'Mutukula',
        },
        'port': {
            'port_1': 'Dar es Salaam port',
            'port_2': 'Mtwara',
            'port_3': 'Tanga',
            'port_4': 'Mwanza',
            'port_9': 'Kigoma',
        },
        'rail': {
            'rail_node_16': 'Tunduma Station',
        }
    }

def read_border_geoms_and_labels(sector, filename):
    """Read filename, returning (geom, label) tuples for each border point in
    border_points_info for given sector
    """
    border_points_info = get_border_points()
    nodes = []
    id_by_sector = {
        "road": "nodenumber",
        "rail": "id",
        "port": "id",
        "air": "ident",
    }
    for record in shpreader.Reader(filename).records():
        id_ = record.attributes[id_by_sector[sector]]
        if id_ in border_points_info[sector]:
            nodes.append((record.geometry, border_points_info[sector][id_]))
    return nodes

def plot_border_crossings(ax, nodes, resource_path, show_labels=True):
    """Plot airport, port, road and rail border crossings
    """
    proj_lat_lon = ccrs.PlateCarree()
    # Icons
    boat_icon_filename = os.path.join(resource_path, 'boat.png')
    ferry_im = plt.imread(boat_icon_filename)
    plane_icon_filename = os.path.join(resource_path, 'plane.png')
    plane_im = plt.imread(plane_icon_filename)

    node_buffer = 0.08

    # Roads
    xs = []
    ys = []
    for geom, label in nodes["road"]:
        xs.append(geom.x)
        ys.append(geom.y)
        if show_labels:
            ax.text(
                geom.x + node_buffer, geom.y + node_buffer,
                label,
                transform=proj_lat_lon,
                zorder=4,
                size=8
            )
    ax.scatter(xs, ys, facecolor='#d1170a', s=11, zorder=3)

    # Railways
    xs = []
    ys = []
    for geom, label in nodes["rail"]:
        x = geom.x - 0.1
        xs.append(x)
        ys.append(geom.y)
        if show_labels:
            ax.text(
                x + node_buffer,  geom.y + node_buffer,
                label,
                transform=proj_lat_lon, zorder=4, ha='right', size=8
            )
    ax.scatter(xs, ys, facecolor='#33a02c', s=11, zorder=3)

    # Offset defines icon size
    offset = 0.15

    # Ports
    for geom, label in nodes["port"]:
        x = geom.x
        y = geom.y

        img_extent = (
            x - offset,
            x + offset,
            y - offset,
            y + offset
        )
        ax.imshow(
            ferry_im,
            origin='upper', extent=img_extent, transform=proj_lat_lon, zorder=4)

        if show_labels:
            ax.text(
                x + offset/2, y + offset/2,
                label,
                transform=proj_lat_lon, zorder=4, size=8)

    # Airports
    for geom, label in nodes["air"]:
        x = geom.x
        y = geom.y

        # Nudge airports which are next to ports
        if label == 'Julius Nyerere':
            x -= 0.2

        img_extent = (
            x - offset,
            x + offset,
            y - offset,
            y + offset
        )
        ax.imshow(
            plane_im,
            origin='upper', extent=img_extent, transform=proj_lat_lon, zorder=5)

        if show_labels:
            if label == 'Arusha':
                y += 0.07
                x += 0.05
                align = 'right'
            elif label == 'Julius Nyerere':
                y -= 0.21
                x -= 0.05
                align = 'right'
            else:
                y -= 0.21
                x += 0.05
                align = 'right'

            ax.text(
                x, y,
                label,
                transform=proj_lat_lon, zorder=4, ha=align, size=8)

def round_sf(x, places=1):
    """Round number to significant figures
    """
    if x == 0:
        return 0
    sign = x / abs(x)
    x = abs(x)
    exp = floor(log10(x)) + 1
    shift = 10 ** (exp - places)
    rounded = round(x / shift) * shift
    return rounded * sign


import urllib.request
from bs4 import BeautifulSoup
import os

# Assigning link to a variable

myLink = "https://www.fantasypros.com/nfl/reports/leaders/qb.php?year=2015"

# Opens the URL
getLink=urllib.request.urlopen(myLink)
f = open('game.txt', 'w+')
# Converts to HTML
soup = BeautifulSoup(getLink,  "html.parser")
# Prints Header for the wiki page
print(soup.h1.text)
for link in soup.findAll('div'):
    # Goes to the table and collects data from the class  wikitable sortable plainrowheaders
   table = soup.find("table", { "class" : "table table-bordered table-striped table-hover" })

# looping all elements in tr tags
for row in table.findAll('tr'):
    for h in row.findAll('th'):
        f.write(h.text+' ')
    for r in row.findAll('td'):
       cells = r.text
        # prints td elements
       print(cells)
       f.write(cells+'  ')
    f.write('\n')

       # elements = row.find('th')
        # prints th elements
        #print(elements.text)
f.close()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings

class Migration(migrations.Migration):

    dependencies = [
        ('contant', '0001_initial'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Playlist',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=60)),
                ('specification', models.TextField(null=True)),
                ('rating', models.FloatField(default=0)),
            ],
            options={
                'db_table': 'playlists',
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='PlaylistComposition',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('composition', models.ForeignKey(related_name='composition', to='contant.Compositions')),
                ('playlist', models.ForeignKey(related_name='playlist', to='playlist.Playlist')),
            ],
            options={
                'db_table': 'playlist_composition',
            },
            bases=(models.Model,),
        ),
        migrations.AddField(
            model_name='playlist',
            name='compositions',
            field=models.ManyToManyField(to='contant.Compositions', through='playlist.PlaylistComposition'),
            preserve_default=True,
        ),
        migrations.AddField(
            model_name='playlist',
            name='user_id',
            field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
            preserve_default=True,
        ),
    ]


from bisect import bisect_left
from itertools import accumulate

n, m = map(int, input().split())
a = list(map(int, input().split()))
a.sort()

b = [0] + a
b.sort(reverse=True)
b = [0] +b
b = list(accumulate(b))

def isok(sum_):
    n_pattern = 0
    for i in range(n):
        n_pattern += n - bisect_left(a, sum_ - a[i])
        if n_pattern >= m:
            return True

    return False

ok = min(a)*2
ng = max(a)*2 +1

while ng - ok > 1:
    mid = (ok+ng)//2
    if isok(mid):
        ok = mid
    else:
        ng = mid

sum_ng = ng
sum_ok = ok

m_counter_ng = 0

ans = 0
for i in range(n):
    id_ng = bisect_left(a, sum_ng - a[i])
    ans += b[n-id_ng]
    ans += a[i]*(n - id_ng)
    m_counter_ng += n - id_ng

ans += sum_ok * (m - m_counter_ng)

print(ans)


from flask import Blueprint, render_template, abort, request, current_app
from flask_login import login_required

from simpledu.models import Live

live = Blueprint('live', __name__, url_prefix='/live')

@live.route('/')
@login_required
def index():
    page = request.args.get('page', default=1, type=int)
    pagination = Live.get_page(page=page, per_page=current_app.config['INDEX_PER_PAGE'])
    return render_template('live/index.html', pagination=pagination)

@live.route('/<int:id>')
@login_required
def detail(id):
    live = Live.query.get_or_404(id)
    return render_template('live/live.html', live=live)


#!/usr/bin/python3

from itertools import groupby

filepath = input()
result = []
with open(filepath) as f:
	while True:
		line = f.readline()
		if not line:
			break
		if not line.startswith('#'):
			result.append(line)

split_tuples = [string.split() for string in result]
grouped_by_protein = groupby(split_tuples, key=lambda x: x[0])
max_tuples = [max(t[1], key=lambda x: x[2])   for t in grouped_by_protein]
tuples_to_print = [' '.join(l) for l in max_tuples]
print('\n'.join(tuples_to_print))


"""
@author: Anthony Soulain (University of Sydney)

-------------------------------------------------------------------------
AMICAL: Aperture Masking Interferometry Calibration and Analysis Library
-------------------------------------------------------------------------

Function related to data cleaning (ghost, background correction,
centering, etc.) and data selection (sigma-clipping, centered flux,).

--------------------------------------------------------------------
"""

import numpy as np
from astropy.convolution import Gaussian2DKernel, interpolate_replace_nans
from astropy.io import fits
from matplotlib import pyplot as plt
from matplotlib.colors import PowerNorm
from termcolor import cprint
from tqdm import tqdm

from amical.tools import apply_windowing, crop_max

def _apply_patch_ghost(cube, xc, yc, radius=20, dx=0, dy=-200, method='bg'):
    """Apply a patch on an eventual artifacts/ghosts on the spectral filter (i.e.
    K1 filter of SPHERE presents an artifact/ghost at (392, 360)).

    Arguments:
    ----------
    `cube` {array} -- Data cube,\n
    `xc` {int} -- x-axis position of the artifact,\n
    `yc` {int} -- y-axis position of the artifact.

    Keyword Arguments:
    ----------
    `radius` {int} -- Radius to apply the patch in a circle (default: {10}),\n
    `dy` {int} -- Offset pixel number to compute background values (default: {0}),\n
    `dx` {int} -- Same along y-axis (default: {0}),\n
    `method` {str} -- If 'bg', the replacement values are the background computed at
    xc+dx, yx+dy, else zero is apply (default: {'bg'}).
    """
    cube_corrected = []
    for i in range(len(cube)):
        imA = cube[i].copy()
        isz = imA.shape[0]
        xc_off, yc_off = xc+dx, yc+dy
        xx, yy = np.arange(isz), np.arange(isz)
        xx_c = (xx-xc)
        yy_c = (yc-yy)
        xx_off = (xx-xc_off)
        yy_off = (yc_off-yy)
        distance = np.sqrt(xx_c**2 + yy_c[:, np.newaxis]**2)
        distance_off = np.sqrt(xx_off**2 + yy_off[:, np.newaxis]**2)
        cond_patch = (distance <= radius)
        cond_bg = (distance_off <= radius)
        if method == 'bg':
            imA[cond_patch] = imA[cond_bg]
        elif method == 'zero':
            imA[cond_patch] = 0
        cube_corrected.append(imA)
    cube_corrected = np.array(cube_corrected)
    return cube_corrected

def select_data(cube, clip_fact=0.5, clip=False, verbose=True, display=True):
    """ Check the cleaned data cube using the position of the maximum in the
    fft image (supposed to be zero). If not in zero position, the fram is
    rejected. It can apply a sigma-clipping to select only the frames with the
    highest total fluxes.

    Parameters:
    -----------
    `cube` {array} -- Data cube,\n
    `clip_fact` {float} -- Relative sigma if rejecting frames by
    sigma-clipping (default=False),\n
    `clip` {bool} -- If True, sigma-clipping is used,\n
    `verbose` {bool} -- If True, print informations in the terminal,\n
    `display` {bool} -- If True, plot figures.

    """
    fft_fram = abs(np.fft.fft2(cube))
    # flag_fram, cube_flagged, cube_cleaned_checked = [], [], []

    fluxes, flag_fram, good_fram = [], [], []
    for i in range(len(fft_fram)):
        fluxes.append(fft_fram[i][0, 0])
        pos_max = np.argmax(fft_fram[i])
        if pos_max != 0:
            flag_fram.append(i)
        else:
            good_fram.append(cube[i])

    fluxes = np.array(fluxes)
    flag_fram = np.array(flag_fram)

    best_fr = np.argmax(fluxes)
    worst_fr = np.argmin(fluxes)

    std_flux = np.std(fluxes)
    med_flux = np.median(fluxes)

    if verbose:
        if (med_flux/std_flux) <= 5.:
            cprint('\nStd of the fluxes along the cube < 5 (%2.1f):\n -> sigma clipping is suggested (clip=True).' % (
                (med_flux/std_flux)), 'cyan')

    limit_flux = med_flux - clip_fact*std_flux

    if clip:
        cond_clip = (fluxes > limit_flux)
        cube_cleaned_checked = cube[cond_clip]
        ind_clip = np.where(fluxes <= limit_flux)[0]
    else:
        ind_clip = []
        cube_cleaned_checked = np.array(good_fram)

    ind_clip2 = np.where(fluxes <= limit_flux)[0]
    if ((worst_fr in ind_clip2) and clip) or (worst_fr in flag_fram):
        ext = '(rejected)'
    else:
        ext = ''

    diffmm = 100*abs(np.max(fluxes) - np.min(fluxes))/med_flux
    if display:
        plt.figure()
        plt.plot(fluxes, label=r'|$\Delta F$|/$\sigma_F$=%2.0f (%2.2f %%)' %
                 (med_flux/std_flux, diffmm))
        if len(flag_fram) > 0:
            plt.scatter(flag_fram, fluxes[flag_fram],
                        s=52, facecolors='none', edgecolors='r', label='Rejected frames (maximum fluxes)')
        if clip:
            if len(ind_clip) > 0:
                plt.plot(ind_clip, fluxes[ind_clip], 'rx',
                         label='Rejected frames (clipping)')
            else:
                print('0')
        plt.hlines(limit_flux, 0, len(fluxes), lw=1,
                   ls='--', label='Clipping limit', zorder=10)
        plt.legend(loc='best', fontsize=9)
        plt.ylabel('Flux [counts]')
        plt.xlabel('# frames')
        plt.grid(alpha=.2)
        plt.tight_layout()

        plt.figure(figsize=(7, 7))
        plt.subplot(2, 2, 1)
        plt.title('Best fram (%i)' % best_fr)
        plt.imshow(cube[best_fr], norm=PowerNorm(.5), cmap='afmhot', vmin=0)
        plt.subplot(2, 2, 2)
        plt.imshow(np.fft.fftshift(fft_fram[best_fr]), cmap='gist_stern')
        plt.subplot(2, 2, 3)
        plt.title('Worst fram (%i) %s' % (worst_fr, ext))
        plt.imshow(cube[worst_fr], norm=PowerNorm(.5), cmap='afmhot', vmin=0)
        plt.subplot(2, 2, 4)
        plt.imshow(np.fft.fftshift(fft_fram[worst_fr]), cmap='gist_stern')
        plt.tight_layout()
        plt.show(block=False)
    if verbose:
        n_good = len(cube_cleaned_checked)
        n_bad = len(cube) - n_good
        if clip:
            cprint('\n---- σ-clip + centered fluxes selection ---', 'cyan')
        else:
            cprint('\n---- centered fluxes selection ---', 'cyan')
        print('%i/%i (%2.1f%%) are flagged as bad frames' %
              (n_bad, len(cube), 100*float(n_bad)/len(cube)))
    return cube_cleaned_checked

def sky_correction(imA, r1=100, dr=20, verbose=False):
    """
    Perform background sky correction to be as close to zero as possible.
    """
    isz = imA.shape[0]
    xc, yc = isz//2, isz//2
    xx, yy = np.arange(isz), np.arange(isz)
    xx2 = (xx-xc)
    yy2 = (yc-yy)
    r2 = r1 + dr

    distance = np.sqrt(xx2**2 + yy2[:, np.newaxis]**2)
    cond_bg = (r1 <= distance) & (distance <= r2)

    try:
        minA = imA.min()
        imB = imA + 1.01*abs(minA)
        backgroundB = np.mean(imB[cond_bg])
        imC = imB - backgroundB
        backgroundC = np.mean(imC[cond_bg])
    except IndexError:
        imC = imA.copy()
        backgroundC = 0
        if verbose:
            cprint('Warning: Background not computed', 'green')
            cprint(
                '-> check the inner and outer radius rings (checkrad option).', 'green')
    return imC, backgroundC

def fix_bad_pixels(image, bad_map, add_bad=[], x_stddev=1):
    """ Replace bad pixels with values interpolated from their neighbors (interpolation
    is made with a gaussian kernel convolution)."""
    if len(add_bad) != 0:
        for j in range(len(add_bad)):
            bad_map[add_bad[j][1], add_bad[j][0]] = 1

    img_nan = image.copy()
    img_nan[bad_map == 1] = np.nan
    kernel = Gaussian2DKernel(x_stddev=x_stddev)
    fixed_image = interpolate_replace_nans(img_nan, kernel)
    return fixed_image

def check_data_params(filename, isz, r1, dr, bad_map=None, add_bad=[],
                      edge=0, remove_bad=True, nframe=0, ihdu=0, f_kernel=3,
                      offx=0, offy=0, apod=False, window=None):
    """ Check the input parameters for the cleaning.

    Parameters:
    -----------

    `filename` {str}: filename containing the datacube,\n
    `isz` {int}: Size of the cropped image (default: 256)\n
    `r1` {int}: Radius of the rings to compute background sky (default: 100)\n
    `dr` {int}: Outer radius to compute sky (default: 10)\n
    `bad_map` {array}: Bad pixel map with 0 and 1 where 1 set for a bad pixel (default: None),\n
    `add_bad` {list}: List of 2d coordinates of bad pixels/cosmic rays (default: []),\n
    `edge` {int}: Number of pixel to be removed on the edge of the image (SPHERE),\n
    `remove_bad` {bool}: If True, the bad pixels are removed using a gaussian interpolation,\n
    `nframe` {int}: Frame number to be shown (default: 0),\n
    `ihdu` {int}: Hdu number of the fits file. Normally 1 for NIRISS and 0 for SPHERE (default: 0).
    """
    data = fits.open(filename)[ihdu].data
    img0 = data[nframe]

    if (bad_map is None) and (len(add_bad) != 0):
        bad_map = np.zeros(img0.shape)

    if edge != 0:
        img0[:, 0:edge] = 0
        img0[:, -edge:-1] = 0
        img0[0:edge, :] = 0
        img0[-edge:-1, :] = 0
    if (bad_map is not None) & (remove_bad):
        img1 = fix_bad_pixels(img0, bad_map, add_bad=add_bad)
    else:
        img1 = img0.copy()
    cropped_infos = crop_max(img1, isz, offx=offx, offy=offy, f=f_kernel)
    pos = cropped_infos[1]

    noBadPixel = False
    bad_pix_x, bad_pix_y = [], []
    if (bad_map is not None) & (len(add_bad) != 0):
        for j in range(len(add_bad)):
            bad_map[add_bad[j][1], add_bad[j][0]] = 1
        bad_pix = np.where(bad_map == 1)
        bad_pix_x = bad_pix[0]
        bad_pix_y = bad_pix[1]
    else:
        noBadPixel = True

    r2 = r1 + dr
    theta = np.linspace(0, 2*np.pi, 100)
    x0 = pos[0]
    y0 = pos[1]

    x1 = r1 * np.cos(theta) + x0
    y1 = r1 * np.sin(theta) + y0
    x2 = r2 * np.cos(theta) + x0
    y2 = r2 * np.sin(theta) + y0
    if window is not None:
        r3 = window
        x3 = r3 * np.cos(theta) + x0
        y3 = r3 * np.sin(theta) + y0

    xs1, ys1 = x0 + isz//2, y0 + isz//2
    xs2, ys2 = x0 - isz//2, y0 + isz//2
    xs3, ys3 = x0 - isz//2, y0 - isz//2
    xs4, ys4 = x0 + isz//2, y0 - isz//2

    max_val = img1[y0, x0]
    fig = plt.figure(figsize=(5, 5))
    plt.title("--- CLEANING PARAMETERS ---")
    plt.imshow(img1, norm=PowerNorm(.5), cmap='afmhot', vmin=0, vmax=max_val)
    plt.plot(x1, y1, label='Inner radius for sky subtraction')
    plt.plot(x2, y2, label='Outer radius for sky subtraction')
    if apod:
        if window is not None:
            plt.plot(x3, y3, '--', label='Super-gaussian windowing')
    plt.plot(x0, y0, '+', color='c', ms=10, label='Centering position')
    plt.plot([xs1, xs2, xs3, xs4, xs1], [ys1, ys2, ys3, ys4, ys1], 'w--',
             label='Resized image')
    if not noBadPixel:
        if remove_bad:
            label = 'Fixed hot/bad pixels'
        else:
            label = 'Hot/bad pixels'
        plt.scatter(bad_pix_y, bad_pix_x, color='', marker='s',
                    edgecolors='r', s=20, label=label)

    plt.xlabel('X [pix]')
    plt.ylabel('Y [pix]')
    plt.legend(fontsize=8, loc=1)
    plt.tight_layout()
    return fig

def _apply_edge_correction(img0, edge=0):
    """ Remove the bright edges (set to 0) observed for
    some detectors (SPHERE). """
    if edge != 0:
        img0[:, 0:edge] = 0
        img0[:, -edge:-1] = 0
        img0[0:edge, :] = 0
        img0[-edge:-1, :] = 0
    return img0

def _remove_dark(img1, darkfile=None, ihdu=0,
                 verbose=False):
    if darkfile is not None:
        hdu = fits.open(darkfile)
        dark = hdu[ihdu].data
        hdu.close()
        if verbose:
            print('Dark cube shape is:', dark.shape)
        master_dark = np.mean(dark, axis=0)
        img1 -= master_dark
    return img1

def clean_data(data, isz=None, r1=None, dr=None, edge=0,
               bad_map=None, add_bad=[], apod=True,
               offx=0, offy=0, sky=True, window=None,
               darkfile=None, f_kernel=3, verbose=False):
    """ Clean data.

    Parameters:
    -----------

    `data` {np.array} -- datacube containing the NRM data\n
    `isz` {int} -- Size of the cropped image (default: {None})\n
    `r1` {int} -- Radius of the rings to compute background sky (default: {None})\n
    `dr` {int} -- Outer radius to compute sky (default: {None})\n
    `edge` {int} -- Patch the edges of the image (VLT/SPHERE artifact, default: {200}),\n
    `checkrad` {bool} -- If True, check the resizing and sky substraction parameters (default: {False})\n

    Returns:
    --------
    `cube` {np.array} -- Cleaned datacube.
    """
    n_im = data.shape[0]
    cube_cleaned = []  # np.zeros([n_im, isz, isz])
    l_bad_frame = []
    for i in tqdm(range(n_im), ncols=100, desc='Cleaning', leave=False):
        img0 = data[i]
        img0 = _apply_edge_correction(img0, edge=edge)
        if bad_map is not None:
            img1 = fix_bad_pixels(img0, bad_map, add_bad=add_bad)
        else:
            img1 = img0.copy()

        img1 = _remove_dark(img1, darkfile=darkfile, verbose=verbose)
        im_rec_max = crop_max(img1, isz, offx=offx, offy=offy, f=f_kernel)[0]
        if sky:
            img_biased = sky_correction(im_rec_max, r1=r1, dr=dr,
                                        verbose=verbose)[0]
        else:
            img_biased = im_rec_max.copy()
        img_biased[img_biased < 0] = 0  # Remove negative pixels

        if (img_biased.shape[0] != img_biased.shape[1]) or (img_biased.shape[0] != isz):
            l_bad_frame.append(i)
        else:
            if apod:
                img = apply_windowing(img_biased, window=window)
            else:
                img = img_biased.copy()
            cube_cleaned.append(img)
    if verbose:
        print('Bad centering frame number:', l_bad_frame)
    cube_cleaned = np.array(cube_cleaned)
    return cube_cleaned

def select_clean_data(filename, isz=256, r1=100, dr=10, edge=0,
                      clip=True, bad_map=None, add_bad=[], offx=0, offy=0,
                      clip_fact=0.5, apod=True, sky=True, window=None,
                      darkfile=None, f_kernel=3, verbose=False, ihdu=0,
                      display=False):
    """ Clean and select good datacube (sigma-clipping using fluxes variations).

    Parameters:
    -----------

    `filename` {str}: filename containing the datacube,\n
    `isz` {int}: Size of the cropped image (default: {256})\n
    `r1` {int}: Radius of the rings to compute background sky (default: {100})\n
    `dr` {int}: Outer radius to compute sky (default: {10})\n
    `edge` {int}: Patch the edges of the image (VLT/SPHERE artifact, default: {0}),\n
    `clip` {bool}: If True, sigma-clipping is used to reject frames with low integrated flux,\n
    `clip_fact` {float}: Relative sigma if rejecting frames by sigma-clipping,\n
    `apod` {bool}: If True, apodisation is performed in the image plan using a super-gaussian
    function (known as windowing). The gaussian FWHM is set by the parameter `window`,\n
    `window` {float}: FWHM of the super-gaussian to apodise the image (smoothly go to zero
    on the edges),\n
    `sky` {bool}: If True, the sky is remove using the annulus technique (computed between `r1`
    and `r1` + `dr`),
    `darkfile` {str}: If specified (default: None), the input dark (master_dark averaged if
    multiple integrations) is substracted from the raw image,\n
    image,\
    `f_kernel` {float}: kernel size used in the applied median filter (to find the center),\n
    (default=0.5),\n

    Returns:
    --------
    `cube_final` {np.array}: Cleaned and selected datacube.
    """
    hdu = fits.open(filename)
    cube = hdu[ihdu].data
    hdr = hdu[0].header

    ins = hdr.get('INSTRUME', None)

    if ins == 'SPHERE':
        seeing_start = float(hdr['HIERARCH ESO TEL AMBI FWHM START'])
        seeing = float(hdr['HIERARCH ESO TEL IA FWHM'])
        seeing_end = float(hdr['HIERARCH ESO TEL AMBI FWHM END'])

        if verbose:
            print('\n----- Seeing conditions -----')
            print("%2.2f (start), %2.2f (end), %2.2f (Corrected AirMass)" %
                  (seeing_start, seeing_end, seeing))

    raw_size = cube.shape[1]
    if isz > raw_size:
        raise ValueError(
            'Reshape factor is larger than the data size (choose a smaller isz).')

    cube_cleaned = clean_data(cube, isz=isz, r1=r1, edge=edge,
                              bad_map=bad_map, add_bad=add_bad,
                              dr=dr, sky=sky, apod=apod, window=window,
                              f_kernel=f_kernel, offx=offx, offy=offy,
                              darkfile=darkfile, verbose=verbose)

    if cube_cleaned is None:
        return None

    cube_final = select_data(cube_cleaned, clip=clip, clip_fact=clip_fact,
                             verbose=verbose, display=display)
    return cube_final


import torch
import os
#! /usr/bin/env python

import tensorflow as tf
import numpy as np
import os
import time
import datetime
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from corpus import *
from models_CapsE import CapsE

np.random.seed(1234)
tf.set_random_seed(1234)

from models import SpKBGATModified, SpKBGATConvOnly
from torch.autograd import Variable
import numpy as np
from utils import save_model, load_object, load_model, save_object
import random
import time
from config import Config

args = Config()
args.load_config()
device = "cuda" if args.cuda else "cpu"

with tf.Graph().as_default():
    session_conf = tf.ConfigProto(allow_soft_placement=args.allow_soft_placement, log_device_placement=args.log_device_placement)
    session_conf.gpu_options.allow_growth = True
    sess = tf.Session(config=session_conf)
    with sess.as_default():
        global_step = tf.Variable(0, name="global_step", trainable=False)
        capse = CapsE(sequence_length=x_valid.shape[1],
                            initialization=initialization,
                            embedding_size=args.embedding_dim,
                            filter_size=args.filter_size,
                            num_filters=args.num_filters,
                            vocab_size=len(words_indexes),
                            iter_routing=args.iter_routing,
                            batch_size=2*args.batch_size,
                            num_outputs_secondCaps=args.num_outputs_secondCaps,
                            vec_len_secondCaps=args.vec_len_secondCaps,
                            useConstantInit=args.useConstantInit
                            )

        # Define Training procedure
        #optimizer = tf.contrib.opt.NadamOptimizer(1e-3)
        optimizer = tf.train.AdamOptimizer(learning_rate=args.learning_rate)
        #optimizer = tf.train.RMSPropOptimizer(learning_rate=args.learning_rate)
        #optimizer = tf.train.GradientDescentOptimizer(learning_rate=args.learning_rate)
        grads_and_vars = optimizer.compute_gradients(capse.total_loss)
        train_op = optimizer.apply_gradients(grads_and_vars, global_step=global_step)

        out_dir = os.path.abspath(os.path.join(args.run_folder, "runs_CapsE", args.model_name))
        print("Writing to {}\n".format(out_dir))

        checkpoint_dir = os.path.abspath(os.path.join(out_dir, "checkpoints"))
        checkpoint_prefix = os.path.join(checkpoint_dir, "model")
        if not os.path.exists(checkpoint_dir):
            os.makedirs(checkpoint_dir)
        # Initialize all variables
        sess.run(tf.global_variables_initializer())

        def train_step(x_batch, y_batch):
            """
            A single training step
            """
            feed_dict = {
                capse.input_x: x_batch,
                capse.input_y: y_batch
            }
            _, step, loss = sess.run([train_op, global_step, capse.total_loss], feed_dict)
            return loss

        num_batches_per_epoch = int((data_size - 1) / args.batch_size) + 1
        for epoch in range(args.num_epochs):
            for batch_num in range(num_batches_per_epoch):
                x_batch, y_batch = train_batch()
                loss = train_step(x_batch, y_batch)
                current_step = tf.train.global_step(sess, global_step)
                #print(loss)
            if epoch > 0:
                if epoch % args.savedEpochs == 0:
                    path = capse.saver.save(sess, checkpoint_prefix, global_step=epoch)
                    print("Saved model checkpoint to {}\n".format(path))


import pygame
import numpy as np
import time
from random import randrange

class Wall():
    def __init__(self, rows, cols, screen_width, screen_height):
        width = screen_width // cols
        height = int(screen_height * 0.1)
        self.blocks = []
        self.blocks_exist = []
        for row in range(rows):
            block_row = []
            block_exist_row = []
            for col in range(cols):
                block_x = col * width
                block_y = row * height
                rect = pygame.Rect(block_x, block_y, width, height)
                block_row.append(rect)
                block_exist_row.append(True)
            self.blocks.append(block_row)
            self.blocks_exist.append(block_exist_row)

class Paddle():
    def __init__(self, rows, cols, screen_width, screen_height):
        self.screen_width = screen_width
        self.height = int(screen_height * 0.05)
        self.width = int(screen_width / cols)
        self.x = int(screen_width / 2 - self.width / 2)
        self.y = screen_height - (self.height * 2)
        self.speed = int(screen_width / 60) * 2
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)

    def move(self, action):
        if 2 > action < 0:
            print(f"ERROR IN BREAKOUT ENVIRONMENT: received action {action}")
            exit()
        if action == 1 and self.rect.left > 0:
            self.rect.x -= self.speed
        if action == 2 and self.rect.right < self.screen_width:
            self.rect.x += self.speed

class Ball:
    def __init__(self, start_x, start_y, screen_width, screen_height):
        self.screen_width = screen_width
        self.screen_height = screen_height
        self.radius = int(screen_width * 0.015)
        self.x = start_x - self.radius
        self.y = start_y
        self.rect = pygame.Rect(self.x, self.y, self.radius * 2, self.radius * 2)
        self.speed_x = 4 * 2
        self.speed_y = -4 * 2
        self.speed_max = 5 * 2

    def move(self, blocks, blocks_exist, paddle):
        collision_thresh = 5 * 2

        reward = 0

        for row_id, row in enumerate(blocks):
            for block_id, block in enumerate(row):
                if not blocks_exist[row_id][block_id]:
                    continue
                if self.rect.colliderect(block):
                    # collision from above
                    if abs(self.rect.bottom - block.top) < collision_thresh and self.speed_y > 0:
                        self.speed_y *= -1
                    # collision from bellow
                    if abs(self.rect.top - block.bottom) < collision_thresh and self.speed_y < 0:
                        self.speed_y *= -1
                    # collision from left
                    if abs(self.rect.right - block.left) < collision_thresh and self.speed_x > 0:
                        self.speed_x *= -1
                    # collision from right
                    if abs(self.rect.left - block.right) < collision_thresh and self.speed_x < 0:
                        self.speed_x *= -1
                    blocks_exist[row_id][block_id] = False
                    # del wall.blocks[row_id][block_id]
                    reward += 1

        done_ = True
        for row in blocks_exist:
            for block_exists in row:
                if block_exists:
                    done_ = False
                    break
        if done_:
            reward = 10
        done = done_

        # Check collision on wall
        if self.rect.left < 0 or self.rect.right > self.screen_width:
            self.speed_x *= -1
        if self.rect.top < 0:
            self.speed_y *= -1

        # Check bottom of screen
        if self.rect.bottom > self.screen_height:
            done = True
            reward -= 10

        # Check paddle
        if self.rect.colliderect(paddle):
            if abs(self.rect.bottom - paddle.rect.top) < collision_thresh and self.speed_y > 0:
                self.speed_y *= -1
            else:
                self.speed_x *= -1

        self.rect.x += self.speed_x
        self.rect.y += self.speed_y
        return reward, done, blocks, blocks_exist

class Game():
    def __init__(self):
        pygame.init()

        self.done = False

        self.screen_width = 600  # todo change later
        self.screen_height = 600  # todo change later
        self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
        pygame.display.set_caption("Breakout")

        self.bg = (234, 218, 184)
        self.block_color = (242, 85, 96)
        self.paddle_color = (142, 135, 123)
        self.paddle_outline = (100, 100, 100)

        self.rows = 6
        self.cols = 6

        self.n_actions = 3
        self.n_states_disc = 10 * 10 * 2 * 2 * 10

    def reset(self):
        # initialize wall, ball, paddle
        self.wall = Wall(self.rows, self.cols, self.screen_width, self.screen_height)
        self.paddle = Paddle(self.rows, self.cols, self.screen_width, self.screen_height)
        self.ball = Ball(randrange(20, 560),
                         randrange(380, 520), self.screen_width,
                         self.screen_height)  # 380
        # return state
        return self.get_current_state()

    def get_current_state(self):
        # for image: return self.screen
        ball_x = self.ball.rect.x
        ball_y = self.ball.rect.y
        abs_speed = abs(self.ball.speed_x)
        ball_speed_x = self.ball.speed_x / abs_speed
        ball_speed_y = self.ball.speed_y / abs_speed
        paddle_x = self.paddle.rect.x + self.paddle.width / 2
        return self.discretize_state([ball_x, ball_y, ball_speed_x, ball_speed_y, paddle_x])

    def step(self, action):
        # move paddle
        self.paddle.move(action)

        # move ball and potentially break the bricks
        reward, done, blocks, blocks_exist = self.ball.move(self.wall.blocks, self.wall.blocks_exist, self.paddle)
        self.wall.blocks_exist = blocks_exist
        self.wall.blocks = blocks

        state = self.get_current_state()

        # Feedback
        ball_x = self.ball.rect.x
        feedback = 1 if self.paddle.rect.x <= ball_x < self.paddle.rect.x + self.paddle.width else -1

        return state, reward, done, feedback

    def draw(self):
        self.screen.fill(self.bg)
        self.draw_wall()
        self.draw_paddle()
        self.draw_ball()
        pygame.display.update()

    def draw_wall(self):
        for row_id, row in enumerate(self.wall.blocks):
            for b_id, block in enumerate(row):
                if not self.wall.blocks_exist[row_id][b_id]:
                    continue
                pygame.draw.rect(self.screen, self.block_color, block)
                pygame.draw.rect(self.screen, self.bg, (block), 2)

    def draw_paddle(self):
        pygame.draw.rect(self.screen, self.paddle_color, self.paddle.rect)
        pygame.draw.rect(self.screen, self.paddle_outline, self.paddle.rect, 2)

    def draw_ball(self):
        pygame.draw.circle(self.screen, self.paddle_color,
                           (self.ball.rect.x + self.ball.radius, self.ball.rect.y + self.ball.radius), self.ball.radius)
        pygame.draw.circle(self.screen, self.paddle_outline,
                           (self.ball.rect.x + self.ball.radius, self.ball.rect.y + self.ball.radius), self.ball.radius,
                           2)

    def discretize_state(self, state):
        ball_x = 9 if state[0] >= 600 else int(state[0] / 60)
        ball_y = 9 if state[1] >= 600 else int(state[1] / 60)
        ball_speed_x = 0 if state[2] == -1 else 1
        ball_speed_y = 0 if state[3] == -1 else 1
        paddle_x = 9 if state[4] >= 600 else int(state[4] / 60)
        return [ball_x, ball_y, ball_speed_x, ball_speed_y, paddle_x]

"""
# Example
env = Game()
for episode in range(10):
    state = env.reset()

    for step in range(100):
        # action = np.random.choice([0, 1, 2])
        action = 2
        new_state, reward, done, feedback = env.step(action)

        env.draw()
        time.sleep(0.1)
        print(new_state, ",", reward, ",", done)

        if done == True:
            break
"""


import face_recognition
import os
import cv2
import pickle
from PIL import Image
import shutil
import PySimpleGUI as psg
import pyttsx3
import random
import datetime

from threading import Thread
from queue import Queue

from cvlib import detect_face

global engine, run, speech
engine = pyttsx3.init()
run = True
speech = Queue()

def tts():
    while speech.qsize():
        run = False
        engine.say(speech.get())
        engine.runAndWait()
    run = True
    return

def say(text):
    speech.put(text)
    if run:
        Thread(target=tts).start()
    return

ENCODINGS_DIR = 'known_faces_encodings'
PIC_DIR = 'known_faces_pic'

TOLERANCE = float(input("Please specify desired tolerance (0.0 < Tolerance < 1.0): "))

FRAME_THICKNESS = 3
FONT_THICKNESS = 2

known_faces = [] # list of encodings
known_names = []

for name in os.listdir(ENCODINGS_DIR):
    for filename in os.listdir(f'{ENCODINGS_DIR}/{name}'):
        with open(f'{ENCODINGS_DIR}/{name}/{filename}', 'rb') as pklfile:
            encoding = pickle.load(pklfile)
            known_faces.append(encoding)
            known_names.append(name)

next_id = len(known_names)+1
copied_lst = []

video = cv2.VideoCapture(0)
colors = {}
tts_lst = []
tts_counter = 0
previous_locations = []
previous_matches_index = []
while True:
    #to put in the current TOP LEFT locations of the detected faces later, and also acts as a reset
    current_locations = [] # will consist of lists of [Left, Top]
    current_matches_index = [] #also acts as reset

    #Load video and flip
    image = cv2.flip(video.read()[1], 1)

    # This grabs the face locations, need them to draw boxes
    locations = [(i[1], i[2], i[3], i[0]) for i in detect_face(image)[0]]
                #top, right, bottom, left

    for face_location in locations:
        results = []
        match = None

        #check for every location, if the location is close to a previous location
        top, left = face_location[0], face_location[3]
        counter = 0 #so i know the index
        found_flag = False

        for location in previous_locations: #if its empty it'll just skip
            #if the difference in pixels are less than 20, can assume its the same face
            if abs(location[0] - left) < 20 and abs(location[1] - top) < 20:
                match = known_names[previous_matches_index[counter]]
                found_flag = True
                current_locations.append([left, top])
                current_matches_index.append(previous_matches_index[counter])

                # greet the match
                if match not in tts_lst:
                    tts_lst.append(match)
                    sylables = str(match).replace('_', ' ', 10)
                    say(f'Hello there! {str(sylables)}')
                    say(random.choice(['Nice to meet you!', 'You look familiar.', 'How do you do?']))

                    #if more than 6 names will remove the first name(refrshing temp memory)
                    if len(tts_lst) > 6:
                        tts_lst.pop(0)

                if match in tts_lst:
                    tts_counter += 1
                    if tts_counter % 500 == 0: #every 500th loop
                        tts_counter = 0
                        sylables = str(match).replace('_', ' ', 10)
                        say(f'Ohh Hi, {str(sylables)}. You are still here.')

                break #since found already, break

            else:
                counter += 1

        #if theres no proximity matches from the last frame, then must run the whole thing to check who is it
        if found_flag == False:
           #face_dstance returns a confidence score,
           #the lower the scorer the 'closer' the encoding is to the known encoding, thus higher confidence, vice versa
            #encoding is the most time psending part, so only check when its necessary
            face_encoding = (face_recognition.face_encodings(image, [face_location]))[0] #it returns a list, of 1 element, so i take the first
            for i in list(face_recognition.face_distance(known_faces, face_encoding)): # returns confidence
                if i not in results: #prevent duplicates(for some reason theres occasionally duplicates due to zip i think)
                    results.append(i)
            try: #in case results are 0, meaning a new run
                closest = min(results)
            except:
                closest = 1

            if closest < TOLERANCE:
                #Identify the match from known_names, which have the same length as results
                match = known_names[results.index(closest)]

                #append the data of this location into the respective lists
                current_locations.append([face_location[3], face_location[0]])
                current_matches_index.append(results.index(closest))

                # greet the match
                if match not in tts_lst:
                    tts_lst.append(match)
                    #print(tts_lst)
                    sylables = str(match).replace('_', ' ', 10)
                    say(f'Hello there! {str(sylables)}')
                    say(random.choice(['Nice to meet you!', 'You look familiar.', 'How do you do?']))

                    #if more than 6 names will remove the first name(refrshing temp memory)
                    if len(tts_lst) > 6:
                        tts_lst.pop(0)

                if match in tts_lst:
                    tts_counter += 1
                    if tts_counter % 500 == 0: #every 500th loop
                        tts_counter = 0
                        sylables = str(match).replace('_', ' ', 10)
                        say(f'Ohh Hi! {str(sylables)}. You are still here.')

            else:
                #Creates a new folder to store the unknown face, thus now known

                match = str(next_id)
                next_id += 1
                known_names.append(match)
                index = known_names.index(match) #so i know what index to change
                known_faces.append(face_encoding)
                try: #need this to prevent FileExistError
                  os.mkdir(f'{ENCODINGS_DIR}/{match}')
                except:
                  pass
                timestamp = int(datetime.datetime.utcnow().timestamp())
                with open(f'{ENCODINGS_DIR}/{match}/{match}-{timestamp}.pkl', 'wb') as pkl_file:
                    pickle.dump(face_encoding, pkl_file)

                try: #Same
                  os.mkdir(f'known_faces_pic/{match}_Pic')
                except:
                  pass

                top, right, bottom, left = face_location

                face_image = image[top:bottom, left:right]
                pil_image = Image.fromarray(face_image)
                image_file = f'known_faces_pic/{match}_Pic/{match}-{timestamp}.png'
                pil_image.save(image_file)

                #UPDATING THE DATABASE IMMEDIATELY
                #greetunknown
                say('Hello, who are you?',)

                #Asking for input and showing the picture at the same time using pysimple gui
                name = psg.popup_get_text(f"Who is ID {match}? Press ENTER to skip this ID, Press 'D' to Delete this ID: ", title = f'ID {match}', image = image_file)

                #Iterate through each encoding in the folder(the encoding is a pickle)
                for encoding in os.listdir(f'{ENCODINGS_DIR}/{match}'): #just putting folder doesnt seem to work

                    #If ENTER or D
                    if name == '' or name == None or name == 'd' or name == 'D':
                        #just delete it , save alot of errors and trouble, regardless
                        shutil.rmtree(f'{ENCODINGS_DIR}/{match}')
                        shutil.rmtree(f'{PIC_DIR}/{match}_Pic')

                        #since i removed it, i should pop it out of the knwon_names and known_faces, which i just added earlier jn
                        known_names.pop()
                        known_faces.pop()

                    #if a name was actually inputed
                    else:
                        #if its an existing name
                        if name in os.listdir(ENCODINGS_DIR):
                            #so i know what to delete later
                            copied_lst.append(match)

                            shutil.copy(f'{ENCODINGS_DIR}/{match}/{encoding}', f'{ENCODINGS_DIR}/{name}/{encoding}')
                            #to remove .pkl extension
                            shutil.copy(f'{PIC_DIR}/{match}_Pic/{encoding[:-4]}.png', f'{PIC_DIR}/{name}/{encoding[:-4]}.png')

                        #if the name does not exist yet
                        else:
                            copied_lst.append(match)
                            os.mkdir(f'{ENCODINGS_DIR}/{name}')
                            os.mkdir(f'{PIC_DIR}/{name}')

                            shutil.copy(f'{ENCODINGS_DIR}/{match}/{encoding}', f'{ENCODINGS_DIR}/{name}/{encoding}')

                            #to remove .pkl extension
                            shutil.copy(f'{PIC_DIR}/{match}_Pic/{encoding[:-4]}.png', f'{PIC_DIR}/{name}/{encoding[:-4]}.png')

                        known_names[index] = name

                        #same thing
                        current_locations.append([face_location[3], face_location[0]])
                        current_matches_index.append(index)

                    print('Done!')

                    if match in copied_lst:
                        shutil.rmtree(f'{ENCODINGS_DIR}/{match}')
                        shutil.rmtree(f'{PIC_DIR}/{match}_Pic')

        top, right, bottom, left = face_location

        try:
            color = colors[match]
        except:
            color = random.choice([(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255), (255, 255, 0), (255, 0, 255)])
            colors[match] = color

       # Paint frame
        cv2.rectangle(image, (left, top), (right, bottom), color, FRAME_THICKNESS)
        cv2.rectangle(image, (left, bottom), (right, bottom+22), color, cv2.FILLED)
        # Wite a name
        cv2.putText(image, match, (left + 10, bottom + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 200, 200), FONT_THICKNESS)

    #update previous
    previous_locations = current_locations
    previous_matches_index = current_matches_index

    cv2.imshow('', image)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        video.release()
        cv2.destroyAllWindows()
        break

Python/Face Recognition with Python/BBCS-Optimised.py


import feedparser

import requests

#import multiprocessing as mp
from pathos.multiprocessing import ProcessingPool as Pool
from datetime import datetime
from dateutil.parser import parse
import dateparser
from time import mktime, strftime, sleep
from calendar import timegm
import random
import os
from feeds_db import *
from bs4 import BeautifulSoup

def cestDateHandler(date_string):
    '''
    custom date handler for feedparser
    handles cest
    '''
    if 'CEST' in date_string:
        date_string = date_string.replace('CEST', '+0200')
        return feedparser._parse_date_rfc822(date_string)
    else:
        return None
feedparser.registerDateHandler(cestDateHandler)

def time_struct_to_datetime(time_struct):
    return datetime.utcfromtimestamp(timegm(time_struct))

def opml_to_db():
    import opml
    outline = opml.parse('news.xml')
    urls = []
    for category in outline:
        for source in category:
            urls.append(source.xmlUrl)
    for url, i in download_multiple(urls):
        insert_new_feed(url=url, title=i.feed.title, last_parsed=datetime.utcnow())

def download(url, save = True):
    # conditional get
    headers_path = 'xml_files/headers/'+url.replace('/','_').replace(':','')+'.headers'
    last_modified, etag = None, None
    if os.path.exists(headers_path):
        h = [i.rstrip() for i in open(headers_path, 'r').read().split('\n')]
        last_modified = h[0] if h[0] != 'None' else None
        etag = h[1] if h[1] != 'None' else None
    headers = {'If-Modified-Since':last_modified, 'If-None-Match':etag,
            'Last-Modified':last_modified}
    r = requests.get(url, headers=headers)
    if r.status_code != 200 and r.status_code != 304:
        return None, None
    etag = r.headers.get('ETag')
    last_modified = r.headers.get('Last-Modified')
    with open(headers_path, 'w') as h:
        h.write(str(last_modified)+'\n'+str(etag))
    # parsing
    if r.status_code == 200:
        try:
            feed = feedparser.parse(r.text)
        except Exception as e:
            print(e)
            return None, None

        # save xml
        if save:
            dir_path = 'xml_files/'+feed.channel.link.replace('/','_').replace(':','')
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
            dt = datetime.utcnow().strftime('%Y%m%d-%H%M%S')
            with open(dir_path+'/'+dt+'.xml', 'w') as f:
                f.write(r.text)
        return url, feed
    return None, None

def download_multiple(url_list):
    #num_workers = mp.cpu_count()*2
    num_workers = 1
    #pool = mp.Pool(num_workers)
    #pool = Pool(num_workers)
    #feeds = pool.map(download, url_list)
    feeds = []
    for a in url_list:
        feeds.append(download(a))
    return feeds

def input_entries_into_db(feeds, url_feeds):
    feed_ids = dict([(i[2],i[0]) for i in url_feeds])
    entries = []
    for url, i in feeds:
        if url != None:
            print(i.feed.title, len(i.entries), url)
            for entry in i.entries:
                if entry:
                    try:
                        summary = entry.summary
                    except:
                        summary = None
                    dt = time_struct_to_datetime(entry.published_parsed)
                    #print(entry.published, time_struct_to_datetime(entry.published_parsed), entry.link)
                    if dt:
                        if summary:
                            summary = BeautifulSoup(entry.summary, "lxml").text
                        title = BeautifulSoup(entry.title, "lxml").text

                        e = (title, entry.link, datetime.utcnow(),dt,summary, int(feed_ids[url]))
                        entries.append(e)
            update_last_parsed(url, datetime.utcnow(), website_link=i.feed.link)
        insert_new_entries(entries)

def create_file_structure():
    if not os.path.exists('xml_files/'):
        os.mkdir('xml_files/')
    if not os.path.exists('xml_files/headers/'):
        os.mkdir('xml_files/headers/')

def main():
    # url_feeds = select_all_feeds()
    url_feeds = select_need_parsed_feeds()
    url_list = [i[2] for i in url_feeds]
    input_entries_into_db(download_multiple(url_list), url_feeds)

if __name__ == '__main__':
    #opml_to_db()
    create_file_structure()
    print(datetime.utcnow()) # for log
    main()


#!/usr/bin/python3

import time
import serial
import os
import sys
import threading
import socket
import base64

import numpy as np
from statsmodels import robust
import pickle
import logging
from sklearn.preprocessing import StandardScaler, MinMaxScaler, MaxAbsScaler, RobustScaler, QuantileTransformer, Normalizer
from obspy.signal.filter import highpass
from scipy.signal import savgol_filter
from keras.models import load_model

N = 128
CONFIDENCE_THRESHOLD = 0.95

'''
The following move states are used:
IDLE (with move_state as 1)
DETERMINING_DANCE_MOVE (with move_state as 2)

The machine begins in IDLE state. When idle dance move is received, it moves to DETERMINING_DANCE_MOVE state.
When dance move is successfully determined and sent to the server, it moves back to IDLE state.
'''

# Begin with IDLE state
move_state = 1

ENC_LIST = [
    ('IDLE', 0),
    ('wipers', 1),
    ('number7', 2),
    ('chicken', 3),
    ('sidestep', 4),
    ('turnclap', 5),
    # ('numbersix', 6),
    # ('salute', 7),
    # ('mermaid', 8),
    # ('swing', 9),
    # ('cowboy', 10),
    # ('logout', 11)
]

ENC_DICT = {
    0: 'IDLE',
    1: 'wipers',
    2: 'number7',
    3: 'chicken',
    4: 'sidestep',
    5: 'turnclap',
    # 6: 'numbersix',
    # 7: 'salute',
    # 8: 'mermaid',
    # 9: 'swing',
    # 10: 'cowboy',
    # 11: 'logout'
}

CLASSLIST = [ pair[0] for pair in ENC_LIST ]

# Obtain best class from a given list of class probabilities for every prediction
def onehot2str(onehot):
       enc_dict = dict([(i[1],i[0]) for i in ENC_LIST])
       idx_list = np.argmax(onehot, axis=1).tolist()
       result_str = []
       for i in idx_list:
               result_str.append(enc_dict[i])
       return np.asarray(result_str)

# Convert a class to its corresponding one hot vector
def str2onehot(Y):
   enc_dict = dict(ENC_LIST)
   new_Y = []
   for y in Y:
       vec = np.zeros((1,len(ENC_LIST)),dtype='float64')
       vec[ 0, enc_dict[y] ] = 1.
       new_Y.append(vec)
   del Y
   new_Y = np.vstack(new_Y)
   return new_Y

# Load model from pickle/hdf5 file
model = load_model(os.path.join('nn_models', 'nn_model.hdf5'))
# model = pickle.load(open('classifier_models\\model_RandomForestClassifier200.pkl', 'rb'))
# Load scalers
min_max_scaler = pickle.load(open(os.path.join('scaler', 'min_max_scaler.pkl'), 'rb'))
standard_scaler = pickle.load(open(os.path.join('scaler', 'standard_scaler.pkl'), 'rb'))

# for every segment of data (128 sets per segment with 0% overlap for now), extract the feature vector
def extract_feature_vector(X):
    # preprocess data
    X = savgol_filter(X, 3, 2)
    X = highpass(X, 3, 50)
    X = min_max_scaler.transform(X)
    # extract time domain features
    X_mean = np.mean(X, axis=0)
    X_var = np.var(X, axis=0)
    X_max = np.max(X, axis=0)
    X_min = np.min(X, axis=0)
    X_off = np.subtract(X_max, X_min)
    X_mad = robust.mad(X, axis=0)
    # extract frequency domain features - unused for now
    X_psd = []
    X_peakF = []
    # obtain feature vector by appending all vectors above as one d-dimension feature vector
    X = np.append(X_mean, [X_var, X_max, X_min, X_off, X_mad])
    return standard_scaler.transform([X])

def predict_dance_move(segment):
    X = extract_feature_vector(segment)
    Y = model.predict(X)
    # return model.predict(X).tolist()[0]
    return onehot2str(Y)[0], max(Y[0])

def readLineCR(port):
    rv = ""
    while True:
        ch = port.read().decode()
        rv += ch
        if ch == '\r':
            return rv

def testReadLineCR(port):
    read_flag = 1
    rv = ""
    while (read_flag == 1):
        ch = port.read()
        rv += ch
        if ch == '\r':
            data = rv
            read_flag = 0

# dataArray = [] # N objects in array, per 20ms
handshake_flag = False
data_flag = False
print("test")
port=serial.Serial("/dev/serial0", baudrate=115200, timeout=3.0)
print("set up")
# port.reset_input_buffer()
# port.reset_output_buffer()
while (handshake_flag == False):
    port.write('H'.encode())
    print("H sent")
    response = port.read()
    if (response.decode() == 'A'):
        print("A received, sending N")
        port.write('N'.encode())
        handshake_flag= True
        port.read()

# port.reset_input_buffer()
# port.reset_output_buffer()
print("connected")

while (data_flag == False):

    print("ENTERING")

    movementData = []
    otherData = []
    for i in range(N): # extract from 0->N-1 = N sets of readings
        data = readLineCR(port).split(',')
        data = [ float(val.strip()) for val in data ]
        movementData.append(data[:10]) # extract acc1[3], acc2[3] and gyro[3] values
        otherData.append(data[10:]) # extract voltage, current, power and cumulativepower

    # Add ML Logic
    # Precondition 1: dataArray has values for acc1[3], acc2[3], gyro[3], voltage[1], current[1], power[1] and energy[1] in that order
    # Precondition 2: dataArray has N sets of readings, where N is the segment size, hence it has dimensions N*13
    danceMove, predictionConfidence = predict_dance_move(movementData)
    if move_state == 2 and not danceMove == "IDLE" and predictionConfidence >= CONFIDENCE_THRESHOLD:
        voltage, current, power, energy = tuple(map(tuple, np.mean(otherData, axis=0)))
        output = "#" + danceMove + "|" + str(round(voltage, 2)) + "|" + str(round(current, 2)) + "|" + str(round(power, 2)) + "|" + str(round(energy, 2)) + "|"
        if danceMove == "logout":
            output = danceMove # with logout command, no other values are sent
        # TODO @ Ng Jin: Add code to send output to server below

        # Add code to send output to server above
        move_state = 1
    elif move_state == 1 and danceMove == "IDLE":
        move_state = 2

    print("Print array: ")
    output = "1.0,2.0,3.0,4.0,5.0"
    output = output.replace(',', '|')
    print(output)
    action, voltage, current, power, cumulativepower = output.split('|')
    print("action: " + action + '\n' + "voltage: " + voltage + '\n' + "current: " + current + '\n' +
          "power: " + power + '\n' + "cumulativepower: " + cumulativepower + '\n')

    data_flag = True


#coding:utf-8
from django.shortcuts import render
from .models import ArticleColumn,ArticlePost
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger  #分页
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User

from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.http import  HttpResponse

import redis
from django.conf import settings
r= redis.StrictRedis(host=settings.REDIS_HOST,port=settings.REDIS_PORT,db=settings.REDIS_DB)

#根据username决定显示所有文章还是个人名下文章
def article_titles(request,username=None):
    if username:
        user = User.objects.get(username=username)
        article_title = ArticlePost.objects.filter(author=user)
        try:
            userinfo = user.userinfo
        except:
            userinfo = None
    else:
        article_title = ArticlePost.objects.all()

    paginator = Paginator(article_title,8)
    page = request.GET.get('page')#获取GET请求中的page值
    try:
        current_page = paginator.page(page)#得到指定页面内容
        articles = current_page.object_list #得到该页面所有的对象列表
    except PageNotAnInteger:
        current_page = paginator.page(1)#得到指定页面内容
        articles = current_page.object_list #得到该页面所有的对象列表
    except EmptyPage:
        current_page = paginator.page(paginator.num_pages)#得到指定页面内容
        articles = current_page.object_list #得到该页面所有的对象列表

    if username:
        return render(request,"article/list/author_articles.html",{"articles":articles,"page":current_page,"userinfo":userinfo,"user":user})
    else:
        return render(request,"article/list/article_titles.html",{"articles":articles,"page":current_page})

#文章详情
def article_detail(request,id,slug):
    article =get_object_or_404(ArticlePost,id=id,slug=slug)
    total_views = r.incr("article.{}.views".format(article.id))
    print("article.id:%s" %article.id)
    r.zincrby('article_ranking', 1, article.id)#文章被访问一次，article_rankig就将该文章的id值加1

    article_ranking = r.zrange('article_ranking',0,-1,desc=True)[:10]
    print("article_ranking:%s" %article_ranking)
    article_ranking_ids = [int(id) for id in article_ranking]
    print("article_ranking_ids:%s" %article_ranking_ids)
    most_viewed = list(ArticlePost.objects.filter(id__in=article_ranking_ids))
    most_viewed.sort(key=lambda x:article_ranking_ids.index(x.id))

    return render(request,"article/list/article_detail.html",{"article":article,"total_views":total_views,"most_viewed":most_viewed})

#文章点赞
@csrf_exempt
@require_POST
@login_required(login_url='/account/login/')
def like_article(request):
    article_id = request.POST.get("id")
    action = request.POST.get("action")
    if article_id and action:
        try:
            article = ArticlePost.objects.get(id=article_id)
            if action == "like":   #点赞
                article.users_like.add(request.user)#该用户点赞了该文章
                return HttpResponse("1")
            else:#踩你
                article.users_like.remove(request.user)
                return HttpResponse("2")
        except:
            return HttpResponse("no")