"""
GOL: Graphics in One Line

A collection of functions to create matplotlib plots in a single command line.

(This has been written after getting tired of polluting code with matplotlib instructions).
"""

__author__ = "Manuel Sanchez del Rio"
__contact__ = "srio@esrf.eu"
__copyright = "ESRF, 2016"

import numpy as np
try:
    import matplotlib.pylab as plt
except:
    raise ImportError("Please install matplotlib to allow graphics")

def set_qt():
    """
    Sets the 'correct' qt backend: plt.switch_backend("Qt5Agg").
    This is useful in python scripts making graphs inside oasys in some platforms.
    """
    try:
        plt.switch_backend("Qt5Agg")
    except:
        raise Exception("Failed to set matplotlib backend to Qt5Agg")

def plot_show():
    """
    executes matplotlib's plt.show().
    """
    plt.show()

def plot_image(*positional_parameters,title="TITLE",xtitle=r"X",ytitle=r"Y",
               xrange=None, yrange=None,
               cmap=None,aspect=None,show=1,
               add_colorbar=True,figsize=None):
    """
    Plots an image.

    Parameters
    ----------
    *positional_parameters : tuple(s)
        z [, x, y]
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.
    xrange : 2D tuple or list
        [min, max] values.
    yrange : 2D tuple or list
        [min, max] values.
    cmap : str, optional
        The matplotlin color map.
    aspect : str, optional
        The matplotlib aspect (e..g. 'auto')
    show : int, optional
        if 1 executes show_plot()
    add_colorbar : boolean, optional
        if True adds the color bar.
    figsize : tuple
        The matplotlib figure size.

    Returns
    -------
    tuple
        The matplotlib (fig, ax).

    """
    n_arguments = len(positional_parameters)
    if n_arguments == 1:
        z = positional_parameters[0]
        x = np.arange(0,z.shape[0])
        y = np.arange(0,z.shape[1])
    elif n_arguments == 2:
        z = positional_parameters[0]
        x = positional_parameters[1]
        y = positional_parameters[1]
    elif n_arguments == 3:
        z = positional_parameters[0]
        x = positional_parameters[1]
        y = positional_parameters[2]
    else:
        raise Exception("Bad number of inputs")

    fig = plt.figure(figsize=figsize)

    # cmap = plt.cm.Greys
    plt.imshow(z.T,origin='lower',extent=[x[0],x[-1],y[0],y[-1]],cmap=cmap,aspect=aspect)
    if add_colorbar:
        plt.colorbar()
    ax = fig.gca()
    ax.set_xlabel(xtitle)
    ax.set_ylabel(ytitle)

    plt.title(title)

    plt.xlim( xrange )
    plt.ylim( yrange )

    if show:
        plt.show()

    return fig, ax

def plot_image_with_histograms(*positional_parameters,
                               title="", xtitle=r"X", ytitle=r"Y",
                               xrange=None, yrange=None,
                               cmap=None, aspect='auto', show=True,
                               add_colorbar=False, figsize=(8,8),
                               use_profiles_instead_histograms=False,
                               ):
    """
    Plots an image with an histogram.

    Parameters
    ----------
    *positional_parameters : tuple(s)
        z [, x, y]  Note that here, z array has Y in the first index z(y,x)!!!!
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.
    xrange : 2D tuple or list
        [min, max] values.
    yrange : 2D tuple or list
        [min, max] values.
    cmap : str, optional
        The matplotlin color map.
    aspect : str, optional
        The matplotlib aspect (e..g. 'auto')
    show : int, optional
        if 1 executes show_plot()
    add_colorbar : boolean, optional
        if True adds the color bar.
    figsize : tuple
        The matplotlib figure size.
    use_profiles_instead_histograms : boolean, optional
        If True, display the profiles at (0,0) instead of the histograms.

    Returns
    -------
    tuple
        The matplotlib objects (figure, axScatter, axHistx, axHisty).

    """

    if aspect is None: aspect == 'auto'

    n_arguments = len(positional_parameters)
    if n_arguments == 1:
        z = positional_parameters[0].T
        x = np.arange(0,z.shape[0])
        y = np.arange(0,z.shape[1])
    elif n_arguments == 2:
        z = positional_parameters[0].T
        x = positional_parameters[1]
        y = positional_parameters[1]
    elif n_arguments == 3:
        z = positional_parameters[0].T
        x = positional_parameters[1]
        y = positional_parameters[2]
    else:
        raise Exception("Bad number of inputs")

    if xrange is None:
        xrange = [x.min(),x.max()]

    if yrange is None:
        yrange = [y.min(),y.max()]

    figure = plt.figure(figsize=figsize)

    hfactor = 1.0
    vfactor = 1.0

    left, width = 0.1, 0.6
    bottom, height = 0.1, 0.6
    bottom_h = left_h = left + width + 0.02
    rect_scatter = [left, bottom, width, height]
    rect_histx = [left, bottom_h, width, 0.2]
    rect_histy = [left_h, bottom, 0.2, height]

    #
    #main plot
    #
    axScatter = figure.add_axes(rect_scatter)

    axScatter.set_xlabel(xtitle)
    axScatter.set_ylabel(ytitle)

    if aspect == 'equal':
        axScatter.set_aspect(aspect)

    axScatter.axis(xmin=hfactor*xrange[0],xmax=xrange[1])
    axScatter.axis(ymin=vfactor*yrange[0],ymax=yrange[1])

    axs = axScatter.pcolormesh(x,y,z,cmap=cmap)

    #
    #histograms
    #

    if aspect == 'equal':
        pos0 = axScatter.get_position()
        mm = np.min((pos0.height, pos0.width)) * 0.6
        axHistx = figure.add_axes([pos0.x0, pos0.y0 +pos0.height, pos0.width, mm], sharex=axScatter)
        axHisty = figure.add_axes([pos0.x0 + pos0.width, pos0.y0, mm * figsize[1] / figsize[0], pos0.height], sharey=axScatter)
    else:
        axHistx = figure.add_axes(rect_histx, sharex=axScatter)
        axHisty = figure.add_axes(rect_histy, sharey=axScatter)

    if use_profiles_instead_histograms:
        hx = z[z.shape[0]//2, :]
        hy = z[:, z.shape[1]//2]
    else:
        hx = z.sum(axis=0)
        hy = z.sum(axis=1)

    axHistx.plot(x,hx)
    axHisty.plot(hy,y)

    # tt = np.where(hx >= hx.max() * 0.5)
    # if hx[tt].size > 1:
    #     binSize = x[1] - x[0]
    #     print("FWHM X: ",binSize * (tt[0][-1] - tt[0][0]))
    #
    #
    # tt = np.where(hy >= hy.max() * 0.5)
    # if hx[tt].size > 1:
    #     binSize = y[1] - y[0]
    #     print("FWHM Y: ",binSize * (tt[0][-1] - tt[0][0]))

    # supress ordinates labels ans ticks
    axHistx.get_yaxis().set_visible(False)
    axHisty.get_xaxis().set_visible(False)
    axHistx.set_ylim(ymin=0, ymax=hy.max()*1.1)
    axHisty.set_xlim(xmin=0, xmax=hx.max() * 1.1)
    # supress abscissas labels (keep ticks)
    for tl in axHistx.get_xticklabels(): tl.set_visible(False)
    for tl in axHisty.get_yticklabels(): tl.set_visible(False)

    if title != "":
        axHistx.set_title(title)

    if add_colorbar:
        plt.colorbar(axs)

    if show:
        plt.show()

    return figure, axScatter, axHistx, axHisty

def plot(*positional_parameters, title="", xtitle="", ytitle="",
         xrange=None, yrange=None, show=1, legend=None, legend_position=None, color=None, marker=None, linestyle=None,
         xlog=False, ylog=False, figsize=None):
    """
    Makes a plot of a dataset (XY plot).

    Parameters
    ----------
    *positional_parameters : numpy arrays
        x1, y1 [, x2, y2, x3, y3, ...]
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.
    xrange : 2D tuple or list
        [min, max] values.
    yrange : 2D tuple or list
        [min, max] values.
    show : int, optional
        if 1 executes show_plot()
    legend : str or list
        The legend for the different datasets.
    legend_position : list or tuple
        2D list with coordinates of the legend.
    color : str
        The matplotlib color code.
    marker : str or list
        The matplotlib marker or symbol.
    linestyle : str or list
        The matplotlib linestyle code.
    xlog : boolean, optional
        Set to True for logarithmic plot axis.
    ylog : boolean, optional
        Set to True for logarithmic plot axis.
    figsize : tuple
        The matplotlib figure size.

    Returns
    -------
    tuple
        The matplotmib (fig, ax).

    """

    if isinstance(positional_parameters,tuple):
        if len(positional_parameters) == 1: # in the cvase that input is a tuple with all curves
            positional_parameters = positional_parameters[0]

    n_arguments = len(positional_parameters)
    if n_arguments == 0:
        return

    fig = plt.figure(figsize=figsize)
    if n_arguments == 1:
        y = positional_parameters[0]
        x = np.arange(y.size)
        if linestyle == None:
            linestyle = '-'
        plt.plot(x,y,label=legend,marker=marker,color=color,linestyle=linestyle)
    elif n_arguments == 2:
        x = positional_parameters[0]
        y = positional_parameters[1]
        if linestyle == None:
            linestyle = '-'
        plt.plot(x, y, label=legend, color=color, marker=marker, linestyle=linestyle)
    elif n_arguments % 2 == 0:
        if legend is None:
            legend = [None] * (n_arguments // 2)
        if color is None:
            color = [None] * (n_arguments // 2)

        if marker is None:
            marker = [None] * (n_arguments // 2)

        if linestyle is None:
            linestyle = ['-'] * (n_arguments // 2)

        for i in range(n_arguments // 2):
            plt.plot(positional_parameters[2*i],positional_parameters[2*i+1],label=legend[i],marker=marker[i],linestyle=linestyle[i],color=color[i])
    else:
        raise Exception("Incorrect number of arguments: found an odd number of data sets")
        # x = positional_parameters[0]
        # y = positional_parameters[1]
        # plt.plot(x,y,label=legend)

    ax = plt.subplot(111)
    if legend is not None:
        ax.legend(bbox_to_anchor=legend_position)

    if xlog:
        ax.set_xscale("log")

    if ylog:
        ax.set_yscale("log")

    plt.xlim( xrange )
    plt.ylim( yrange )

    plt.title(title)
    plt.xlabel(xtitle)
    plt.ylabel(ytitle)

    if show:
        plt.show()

    return fig, ax

def plot_table(*positional_parameters, errorbars=None, xrange=None, yrange=None,
               title="", xtitle="", ytitle="", show=1,
               legend=None, legend_position=None, color=None,
               xlog=False, ylog=False, figsize=None):
    """
    Makes a plot with data in tabular arrays using one array with abscissas X (Nx values), and another array
    (N, Nx) with ordinates Y for N datasets.

    Parameters
    ----------

    *positional_parameters : numpy arrays
        [X, ] Y
    errorbars : numpy array
        The values for the error bars.
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.
    xrange : 2D tuple or list
        [min, max] values.
    yrange : 2D tuple or list
        [min, max] values.
    show : int, optional
        if 1 executes show_plot()
    legend : str or list
        The legend for the different datasets.
    legend_position : list or tuple
        2D list with coordinates of the legend.
    color : str
        The matplotlib color code.
    xlog : boolean, optional
        Set to True for logarithmic plot axis.
    ylog : boolean, optional
        Set to True for logarithmic plot axis.
    figsize : tuple
        The matplotlib figure size.

    Returns
    -------
    tuple
       The matplotlib objects (fig, ax).

    """

    n_arguments = len(positional_parameters)
    if n_arguments == 0:
        return

    fig = plt.figure(figsize=figsize)

    if n_arguments == 1:
        y = positional_parameters[0]
        x = np.arange(y.size)
        plt.plot(x,y,label=legend)
    elif n_arguments == 2:
        x = positional_parameters[0]
        y = positional_parameters[1]

        if len(y.shape) == 1:
            y = np.reshape(y,(1,y.size))
            if isinstance(legend,str):
                legend = [legend]
            if isinstance(color,str):
                color = [color]

        for i in range(y.shape[0]):
            if legend is None:
                ilegend = None
            else:
                ilegend = legend[i]

            if color is None:
                icolor = None
            else:
                icolor = color[i]

            if errorbars is None:
                plt.plot(x,y[i],label=ilegend,color=icolor)
            else:
                plt.errorbar(x,y[i],yerr=errorbars[i],label=ilegend,color=icolor)
    else:
        raise Exception("Incorrect number of arguments")

    ax = plt.subplot(111)

    if xlog:
        ax.set_xscale("log")

    if ylog:
        ax.set_yscale("log")

    if legend is not None:
        if legend_position is None:
            legend_position = (1.1, 1.05)
        ax.legend(bbox_to_anchor=legend_position)

    plt.xlim( xrange )
    plt.ylim( yrange )

    plt.title(title)
    plt.xlabel(xtitle)
    plt.ylabel(ytitle)

    if show:
        plt.show()

    return fig, ax

def four_plots(x1, y1, x2, y2, x3, y3, x4, y4, title="", xtitle="", ytitle="", xrange=None, yrange=None, show=True):
    """
    Creates four plots in a window.

    Parameters
    ----------
    x1 : numpy array
        abscissas for plot 1.
    y1 : numpy array
        ordinates for plot 1.
    x2 : numpy array
        abscissas for plot 2.
    y2 : numpy array
        ordinates for plot 2.
    x3 : numpy array
        abscissas for plot 3.
    y3 : numpy array
        ordinates for plot 3.
    x4 : numpy array
        abscissas for plot 4.
    y4 : numpy array
        ordinates for plot 4.
    title : str or list, optional
        a string or list of 4 strings with title.
    xtitle : str or list, optional
        a string or list of 4 strings with title for X.
    ytitle : str or list, optional
        a string or list of 4 strings with title for Y.
    xrange : tuple or list, optional
        the X range for all plots.
    yrange : tuple or list, optional
        the Y range for all plots.
    show : boolean, optional
        if True, execute plot_show() at the end.

    Returns
    -------
    tuple
        The matplotlib objects (f, ax00, ax01, ax10, ax11).

    """

    if isinstance(title,list):
        Title = title
    else:
        Title = [title,title,title,title]

    if isinstance(xtitle,list):
        Xtitle = xtitle
    else:
        Xtitle = [xtitle,xtitle,xtitle,xtitle]

    if isinstance(ytitle,list):
        Ytitle = ytitle
    else:
        Ytitle = [ytitle,ytitle,ytitle,ytitle]

    # Create subplots.
    f, ((ax00, ax01), (ax10, ax11)) = plt.subplots(2, 2, sharex="all", sharey="all")

    ax00.plot(x1,y1, "-")
    ax00.set_title(  Title[0])
    ax00.set_xlabel(Xtitle[0])
    ax00.set_ylabel(Ytitle[0])
    ax00.set_xlim(xrange)
    ax00.set_ylim(yrange)

    ax01.plot(x2,y2, "-")
    ax01.set_title(  Title[1])
    ax01.set_xlabel(Xtitle[1])
    ax01.set_ylabel(Ytitle[1])
    ax01.set_xlim(xrange)
    ax01.set_ylim(yrange)

    ax10.plot(x3,y3, "-")
    ax10.set_title(  Title[2])
    ax10.set_xlabel(Xtitle[2])
    ax10.set_ylabel(Ytitle[2])
    ax10.set_xlim(xrange)
    ax10.set_ylim(yrange)

    ax11.plot(x4,y4, "-")
    ax11.set_title(  Title[3])
    ax11.set_xlabel(Xtitle[3])
    ax11.set_ylabel(Ytitle[3])
    ax11.set_xlim(xrange)
    ax11.set_ylim(yrange)

    if show: plt.show()

    return f, ax00, ax01, ax10, ax11

def plot_surface(mymode, theta, psi, title="TITLE", xtitle="", ytitle="", ztitle="", legend=None, cmap=None,
                 figsize=None,show=1):
    """
    Plots a 2D surface given by an array mymode(theta, phi).

    Parameters
    ----------
    mymode : numpy array
        The 2D array with the surface to plot.
    theta : numpy array
        The array with X (H) values.
    psi : numpy array
        The array with Y (V) values.
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.
    ztitle : str, optional
        The main title.
    legend : str or list
        The legend for the different datasets.
    cmap : str, optional
        The matplotlib color map.
    figsize : tuple
        The matplotlib figure size.
    show : boolean, optional
        If True, executes plot_show() at the end.

    Returns
    -------
    tuple
        The matplotlib objects (fig, ax).

    """

    from matplotlib import cm
    from matplotlib.ticker import LinearLocator, FormatStrFormatter
    from mpl_toolkits.mplot3d import Axes3D

    ftheta, fpsi = np.meshgrid(theta, psi)
    fig = plt.figure(figsize=figsize)
    ax = fig.gca(projection='3d')

    II0 = mymode.T

    if cmap == None:
        cmap = cm.coolwarm

    print(II0.shape,ftheta.shape,fpsi.shape)
    surf = ax.plot_surface(ftheta, fpsi, II0, rstride=1, cstride=1, cmap=cmap,
                           linewidth=0, antialiased=False)

    ax.set_zlim(II0.min(),II0.max())
    ax.zaxis.set_major_locator(LinearLocator(10))
    ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
    fig.colorbar(surf, shrink=0.5, aspect=5)
    plt.title(title)
    ax.set_xlabel(xtitle)
    ax.set_ylabel(ytitle)
    ax.set_zlabel(ztitle)

    if show:
        plt.show()

    return fig, ax

def plot_scatter(x, y, show=1, nbins=100, xrange=None, yrange=None, plot_histograms=True, title="", xtitle="", ytitle=""):
    """
    makes a scatter plot with histograms.

    Parameters
    ----------
    x : numpy array
        x data array.
    y : numpy array
        y data array.
    show : boolean, optional
        If True, executes plot_show() at the end.
    nbins : int
        The number of bins for the histograms.
    xrange : tuple or list, optional
        the X range for all plots.
    yrange : tuple or list, optional
        the Y range for all plots.
    plot_histograms : boolean, optional
        Flag for plotting histograms: False or 0: plot no histograms;
            True or 1: plot both histograms;
            2: plot histograms vs abscissas only;
            3: plot histogram vs ordinates only.
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.

    Returns
    -------
    tuple
        The matplotlib objects (fig, axScatter).

    """
    from matplotlib.ticker import NullFormatter

    # the random data

    nullfmt   = NullFormatter()         # no labels

    # definitions for the axes

    if plot_histograms:
        left, width    = 0.1, 0.65
        bottom, height = 0.1, 0.65
        bottom_h = left_h = left+width+0.02
        rect_scatter = [left, bottom, width, height]
        rect_histx   = [left, bottom_h, width, 0.2]
        rect_histy   = [left_h, bottom, 0.2, height]
    else:
        left, width    = 0.1, 0.8
        bottom, height = 0.1, 0.8
        rect_scatter = [left, bottom, width, height]

    # start with a rectangular Figure
    fig = plt.figure(figsize=(8,8))

    axScatter = plt.axes(rect_scatter)
    if plot_histograms:
        if plot_histograms == 2:
            axHistx = plt.axes(rect_histx)
            axHistx.xaxis.set_major_formatter(nullfmt)
        elif plot_histograms == 3:
            axHisty = plt.axes(rect_histy)
            axHisty.yaxis.set_major_formatter(nullfmt)
        else:
            axHistx = plt.axes(rect_histx)
            axHisty = plt.axes(rect_histy)
            # no labels
            axHistx.xaxis.set_major_formatter(nullfmt)
            axHisty.yaxis.set_major_formatter(nullfmt)

    # now determine nice limits by hand:
    binwidth = np.array([x.max() - x.min(), y.max() - y.min()]).max() / nbins

    if xrange == None:
        xrange = np.array((x.min(), x.max()))
    if yrange == None:
        yrange = np.array((y.min(), y.max()))

    # the scatter plot:
    axScatter.scatter(x, y, marker='.', edgecolor='b', s=.1)

    axScatter.set_xlabel(xtitle)
    axScatter.set_ylabel(ytitle)
    if not plot_histograms:
        axScatter.set_title(title)

    axScatter.set_xlim( xrange )
    axScatter.set_ylim( yrange )

    if plot_histograms:
        bins_x = np.arange(xrange[0], xrange[1] + binwidth, binwidth)
        if plot_histograms == 2:
            axHistx.hist(x, bins=nbins)
            axHistx.set_xlim( axScatter.get_xlim() )
            axHistx.set_title(title)
        elif plot_histograms == 3:
            axHisty.hist(y, bins=nbins, orientation='horizontal')
            axHisty.set_ylim( axScatter.get_ylim() )
        else:
            axHistx.hist(x, bins=nbins, range=xrange)
            axHisty.hist(y, bins=nbins, range=yrange, orientation='horizontal')

            axHistx.set_xlim( axScatter.get_xlim() )

            axHistx.set_title(title)
            axHisty.set_ylim( axScatter.get_ylim() )

    if show: plt.show()

    if plot_histograms:
        if plot_histograms == 2:
            return fig,axScatter,axHistx
        elif plot_histograms == 3:
            return fig,axScatter,axHisty
        else:
            return fig,axScatter,axHistx,axHisty
    else:
        return fig, axScatter

def plot_contour(z, x, y, title="TITLE", xtitle="", ytitle="", xrange=None, yrange=None, plot_points=0, contour_levels=20,
                 cmap=None, cbar=True, fill=False, cbar_title="", figsize=None, show=1):
    """
    Plot a contour curves plot from data z(x,y).

    Parameters
    ----------
    z : numpy array
        The 2D data to plot.
    x : numpy array
        The 1D data for X axis.
    y : numpy array
        The 1D data for Y axis.
    title : str, optional
        The main title.
    xtitle : str, optional
        The X title.
    ytitle : str, optional
        The Y title.
    xrange : tuple or list, optional
        the X range for all plots.
    yrange : tuple or list, optional
        the Y range for all plots.
    plot_points : int, optional
        The number of ppoints for the contours.
    contour_levels : int, optional
        The number of contour levels.
    cmap : str, optional
        The matplotlib color map.
    cbar : boolean, optional
        Flag to plot the color table.
    fill : boolean, optional
        Flag to fill the contours.
    cbar_title : str, optional
        The titles for the contours.
    figsize : tuple
        The matplotlib figure size.
    show : boolean, optional
        If True, executes plot_show() at the end.

    Returns
    -------
    instance of plt.contourf
        The matplotlib plt.contourf instance.

    """

    fig = plt.figure(figsize=figsize)

    if fill:
        fig = plt.contourf(x, y, z.T, contour_levels, cmap=cmap, origin='lower')
    else:
        fig = plt.contour( x, y, z.T, contour_levels, cmap=cmap, origin='lower')

    if cbar:
        cbar = plt.colorbar(fig)
        cbar.ax.set_ylabel(cbar_title)

    plt.title(title)
    plt.xlabel(xtitle)
    plt.ylabel(ytitle)

    # the scatter plot:
    if plot_points:
        axScatter = plt.subplot(111)
        axScatter.scatter( np.outer(x,np.ones_like(y)), np.outer(np.ones_like(x),y))

    # set axes range
    plt.xlim(xrange)
    plt.ylim(yrange)

    if show:
        plt.show()

    return fig


import ast
from typing import Any, Generator, List, Tuple, Type

MSG = "UTC001 don't use datetime.utcnow(), use datetime.now(timezone.utc) instead"  # noqa: E501

class Visitor(ast.NodeVisitor):
    def __init__(self) -> None:
        self.assignments: List[Tuple[int, int]] = []

    def visit_Call(self, node: ast.Call) -> None:
        if isinstance(node.func, ast.Name) and node.func.id == "utcnow":
            self.assignments.append((node.lineno, node.col_offset))

        self.generic_visit(node)

    def visit_Attribute(self, node: ast.Attribute) -> None:
        if (
            isinstance(node.value, ast.Attribute)
            and node.attr == "utcnow"
            and node.value.attr == "datetime"
        ) or (
            isinstance(node.value, ast.Name)
            and node.attr == "utcnow"
            and node.value.id == "datetime"
        ):
            self.assignments.append((node.lineno, node.col_offset))

        self.generic_visit(node)

class Plugin:
    name = "Ban utcnow()"
    version = "0.2.0"

    def __init__(self, tree: ast.AST):
        self._tree = tree

    def run(self) -> Generator[Tuple[int, int, str, Type[Any]], None, None]:
        visitor = Visitor()
        visitor.visit(self._tree)
        for line, col in visitor.assignments:
            yield line, col, MSG, type(self)


import heapq
from collections import defaultdict

n, m = map(int, input().split())
c = [0] * (n + 1)
g = defaultdict(set)
for _ in range(m):
    a, b = map(int, input().split())
    if b not in g[a]:
        g[a].add(b)
        c[b] += 1

q = []
for i in range(1, n + 1):
    if c[i] == 0:
        heapq.heappush(q, i)

s = []
while q:
    x = heapq.heappop(q)
    s.append(x)
    for y in g[x]:
        if c[y] == 0:
            continue
        c[y] -= 1
        if c[y] == 0:
            heapq.heappush(q, y)

if sum(c) == 0:
    print(' '.join(map(str, s)))
else:
    print('-1')


from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *
from simtk.openmm import app
from sys import stdout
import mdtraj as md
import numpy as np
import parmed
import os
import sys
import re
import subprocess as prcs
import shutil
import time

#First we define utility functions to get information about a system
def groupForces(sysObj):
	#Assign each for a name and an index
	#Returns a dictionary with force names as keys and force indices in the system object as definitions
	# i.e. HarmonicBondForce, HarmonicAngleForce, PeriodicTorsionForce, NonbondedForce, CMMotionRemover
	forces = {}
	forcesCounts = {}
	for k, frc in enumerate(sysObj.getForces()):
		frcName = frc.__class__.__name__
		if frcName in forces.keys():
			forcesCounts[frcName] += 1
			frcName += '_%i'%forcesCounts[frcName]
		else:
			forcesCounts[frcName] = 1
		forces[frcName] = k
	return forces

logname = 'log.out'
def write2log(logname,text):
    try:
        f = open(logname,'a')
    except:
        f = open(logname,'w')
    f.write(text)
    f.close()

''' Simulation Settings '''
Pressure = 1.0 # in units of bar
Temperature = 463 # units kelvin
barostatfreq = 20
BoxL = 50.0 # Angstrom

NPol = 40
DOP = 10

IncludeHydrogens = False
Toulene = True
BuildPackmol = True
RunNPT = True
TestBenzeneGeom = True
AddContraints = False
useGPU = True
PS = True

''' --- the actual work of creating the topology --- '''
top = app.topology.Topology()

chains = []
residues = []
constrainedpairs = []
atomsbackbone = []

if PS == False:
    # add Benzene
    for _i in range(NPol): # quick-n-dirty Benzene topology
        chain = top.addChain() #Create new chain for each molecule
        chains.append(chain)
        resname = 'BEN'
        res = top.addResidue(resname,chains[-1])
        residues.append(res)

        _C = app.element.Element.getBySymbol("C")
        _H = app.element.Element.getBySymbol("H")
        a1 = top.addAtom('C1', _C, residues[-1] )
        a2 = top.addAtom('C2', _C, residues[-1] )
        a3 = top.addAtom('C3', _C, residues[-1] )
        a4 = top.addAtom('C4', _C, residues[-1] )
        a5 = top.addAtom('C5', _C, residues[-1] )
        a6 = top.addAtom('C6', _C, residues[-1] )

        top.addBond( a1, a2 )
        top.addBond( a2, a3 )
        top.addBond( a3, a4 )
        top.addBond( a4, a5 )
        top.addBond( a5, a6 )
        top.addBond( a6, a1 )

        if Toulene: # add toulene
            a7 = top.addAtom('C7', _C, residues[-1] )
            top.addBond( a4, a7 )

        _temppairs = [[a1.index,a2.index],
                      [a2.index,a3.index],
                      [a3.index,a4.index],
                      [a4.index,a5.index],
                      [a5.index,a6.index],
                      [a6.index,a1.index],
                      [a4.index,a7.index]]

        constrainedpairs.extend(_temppairs)

        if IncludeHydrogens:
            a7 = top.addAtom('H1', _H, residues[-1] )
            a8 = top.addAtom('H2', _H, residues[-1] )
            a9 = top.addAtom('H3', _H, residues[-1] )
            a10 = top.addAtom('H4', _H, residues[-1] )
            a11 = top.addAtom('H5', _H, residues[-1] )
            a12 = top.addAtom('H6', _H, residues[-1] )
            if Toulene:
                a13 = top.addAtom('H7', _H, residues[-1] )
                a14 = top.addAtom('H8', _H, residues[-1] )
                a15 = top.addAtom('H9', _H, residues[-1] )

            top.addBond( a1, a7 )
            top.addBond( a2, a8 )
            top.addBond( a3, a9 )
            top.addBond( a4, a10 )
            top.addBond( a5, a11 )
            top.addBond( a6, a12 )
            if Toulene:
                top.addBond( a4, a13 )
                top.addBond( a4, a14 )
                top.addBond( a4, a15 )
elif PS:
    # add Polystrene
    for _i in range(NPol): # quick-n-dirty PS topology
        chain = top.addChain() #Create new chain for each molecule
        chains.append(chain)
        for _j in range(DOP):
            resname = 'PS'
            res = top.addResidue(resname,chains[-1])
            residues.append(res)

            # add the atoms
            if _j == 0: # first monomer
                _C = app.element.Element.getBySymbol("C")
                _O = app.element.Element.getBySymbol("O")
                _H = app.element.Element.getBySymbol("H")
                a1 = top.addAtom('C1', _C, residues[-1] )
                a2 = top.addAtom('C2', _C, residues[-1] )
                a3 = top.addAtom('C3', _C, residues[-1] )
                a4 = top.addAtom('C4', _C, residues[-1] )
                a5 = top.addAtom('C5', _C, residues[-1] )
                a6 = top.addAtom('C6', _C, residues[-1] )
                a7 = top.addAtom('C7', _C, residues[-1] )
                a8 = top.addAtom('C8', _C, residues[-1] )

                top.addBond( a1, a2 )
                top.addBond( a2, a3 )
                top.addBond( a3, a4 )
                top.addBond( a4, a5 )
                top.addBond( a5, a6 )
                top.addBond( a6, a1 )
                top.addBond( a7, a1 )
                top.addBond( a7, a8 )

                atomsbackbone.append([a7,a8])

            elif _j == int(DOP-1): # last monomer
                _C = app.element.Element.getBySymbol("C")
                _O = app.element.Element.getBySymbol("O")
                _H = app.element.Element.getBySymbol("H")
                a1 = top.addAtom('C1', _C, residues[-1] )
                a2 = top.addAtom('C2', _C, residues[-1] )
                a3 = top.addAtom('C3', _C, residues[-1] )
                a4 = top.addAtom('C4', _C, residues[-1] )
                a5 = top.addAtom('C5', _C, residues[-1] )
                a6 = top.addAtom('C6', _C, residues[-1] )
                a7 = top.addAtom('C7', _C, residues[-1] )
                a8 = top.addAtom('C8', _C, residues[-1] )

                top.addBond( a1, a2 )
                top.addBond( a2, a3 )
                top.addBond( a3, a4 )
                top.addBond( a4, a5 )
                top.addBond( a5, a6 )
                top.addBond( a6, a1 )
                top.addBond( a7, a1 )
                top.addBond( a7, a8 )

                top.addBond( a7, atomsbackbone[-1][-1])
                atomsbackbone.append([a7,a8])

            else: # middle monomers
                _C = app.element.Element.getBySymbol("C")
                _O = app.element.Element.getBySymbol("O")
                _H = app.element.Element.getBySymbol("H")

                a1 = top.addAtom('C1', _C, residues[-1] )
                a2 = top.addAtom('C2', _C, residues[-1] )
                a3 = top.addAtom('C3', _C, residues[-1] )
                a4 = top.addAtom('C4', _C, residues[-1] )
                a5 = top.addAtom('C5', _C, residues[-1] )
                a6 = top.addAtom('C6', _C, residues[-1] )
                a7 = top.addAtom('C7', _C, residues[-1] )
                a8 = top.addAtom('C8', _C, residues[-1] )

                top.addBond( a1, a2 )
                top.addBond( a2, a3 )
                top.addBond( a3, a4 )
                top.addBond( a4, a5 )
                top.addBond( a5, a6 )
                top.addBond( a6, a1 )
                top.addBond( a7, a1 )
                top.addBond( a7, a8 )

                top.addBond( a7, atomsbackbone[-1][-1])
                atomsbackbone.append([a7,a8])

element_VS = app.element.Element(201, "M", "VS", 0.*dalton)

# create force field
# load in forcefield
forcefield = ForceField('TrappeUA_Styrene_Gromos.xml','tip4pew.xml')
# look for unmatched residues
unmatched_residues = forcefield.getUnmatchedResidues(top)
write2log(logname,"Unmatched\n")
if len(unmatched_residues) > 0:
    write2log(logname,"{} \n".format(unmatched_residues))
else:
    write2log(logname,"{} \n".format('None'))

# Get positions
if BuildPackmol == False:
    Pos = np.random.random((top.getNumAtoms(),3))*BoxL
    print("Position Shape: {}".format(np.shape(Pos)))

periodicboxvectors = [[BoxL/10.,0.,0.],[0.,BoxL/10.,0.],[0.,0.,BoxL/10.]]
top.setPeriodicBoxVectors(periodicboxvectors*nanometer)

''' Build Packmol File '''
if BuildPackmol:
    cwd = os.getcwd()
    PackmolDir = 'packmol'
    PDB = 'loadpdb_np_01_N_10.pdb'
    BoxShell = 0.1
    Tolerance = 2.5
    try:
        os.mkdir(PackmolDir)
    except:
        shutil.rmtree(PackmolDir)
        os.mkdir(PackmolDir)

    os.chdir(PackmolDir)
    shutil.copyfile(os.path.join(cwd,PDB), os.path.join(cwd,PackmolDir,PDB))

    # build packmol
    Packmol_Input = open('mixture.inp','w')

    Packmol_Input.write('tolerance {}\n'.format(float(Tolerance)))
    Packmol_Input.write('\noutput mixture.pdb\n')

    Packmol_Input.write('\nstructure {}\n'.format(PDB))
    Packmol_Input.write('  number {}\n'.format(NPol))
    Packmol_Input.write('  inside box {} {} {} {} {} {}\n'.format(BoxShell,BoxShell,BoxShell,(BoxL*10-BoxShell),(BoxL*10-BoxShell),(BoxL*10-BoxShell)))
    Packmol_Input.write('end structure\n')
    Packmol_Input.close()

    call_1 = 'packmol < mixture.inp'

    print(call_1)
    p1 = prcs.Popen(call_1, stdout=prcs.PIPE, shell=True)
    print("p1:\n {}".format(p1.communicate()))

    shutil.copyfile(os.path.join(cwd,PackmolDir,'mixture.pdb'), os.path.join(cwd,'mixture.pdb'))
    os.chdir('..')

''' Create System '''
system = forcefield.createSystem(top,
                                nonbondedMethod=LJPME,
                                nonbondedCutoff=1.*nanometer,
                                ewaldErrorTolerance=0.0001,
                                rigidWater=True,
                                constraints=None)

integrator = LangevinIntegrator(Temperature*kelvin, 1/picosecond, 0.002*picoseconds)
write2log(logname,'Integrator Constraint Tolerance: {}'.format(integrator.getConstraintTolerance()))
barostat = MonteCarloBarostat(Pressure*bar, Temperature*kelvin, barostatfreq)
if RunNPT: # add barostat
    write2log(logname,"Adding Barostat \n")
    system.addForce(barostat)

if useGPU:
	platform = Platform.getPlatformByName('OpenCL')
	properties = {'DeviceIndex': '1', 'Precision': 'mixed'}
else:
	platform = Platform.getPlatformByName('CPU')
	properties = {'Threads': '10'}

# add benzene ring constraints
if AddContraints:
    write2log(logname,"Shape of constrained pairs: {} \n".format(np.shape(constrainedpairs)))
    for _i,pair in enumerate(constrainedpairs):
        length = 0.140
        system.addConstraint(pair[0],pair[1],length*nanometer)

# setup simulation
simulation = Simulation(top, system, integrator, platform, properties)
if BuildPackmol:
    pdb = PDBFile('mixture.pdb')
    positions = pdb.positions # these are in nanometers
else:
    positions = Pos*nanometer

simulation.context.setPositions(positions)
app.pdbfile.PDBFile.writeModel(simulation.topology,positions,open('test.pdb','w'))
simulation.context.setPeriodicBoxVectors(periodicboxvectors[0],periodicboxvectors[1],periodicboxvectors[2]) # Set the periodic box vectors

# write out xml
from simtk.openmm import XmlSerializer
serialized_system_gromacs = XmlSerializer.serialize(system)
outfile = open('system.xml','w')
outfile.write(serialized_system_gromacs)
outfile.close()

# report on platform
periodicboxvectors = simulation.context.getState().getPeriodicBoxVectors() # Get the periodic box vectors
p = simulation.context.getPlatform()
force_dict = groupForces(system)
nbf_obj = system.getForces()[force_dict['NonbondedForce']]

write2log(logname,"Box Size: {}".format(periodicboxvectors))
write2log(logname,"simulation platform: {} \n".format(p.getName()) )
write2log(logname,"{} \n".format(p.getPropertyNames()))
if useGPU:
    write2log(logname,"Device name: {} \n".format(p.getPropertyValue(simulation.context,'DeviceName')))
    write2log(logname,"Use CPU PME: {} \n".format(p.getPropertyValue(simulation.context,'UseCpuPme')))
    write2log(logname,"Disable PME Stream: {} \n".format(p.getPropertyValue(simulation.context,'DisablePmeStream')))
    write2log(logname,"Device Index: {} \n".format(p.getPropertyValue(simulation.context,'DeviceIndex')))
write2log(logname,"Nonbonded method: {} \n".format(nbf_obj.getNonbondedMethod()))
write2log(logname,'The dispersion correction setting is: {}.\n'.format(nbf_obj.getUseDispersionCorrection()))

''' Save bond parameters to file. '''
numBonds = system.getForces()[force_dict['HarmonicBondForce']].getNumBonds()
with open("bond.parameters", 'w') as g:
	for i in range(numBonds):
		g.write('bond {}: {} \n'.format(i,system.getForces()[force_dict['HarmonicBondForce']].getBondParameters(i)))

''' Save angle parameters to file. '''
numAngles = system.getForces()[force_dict['HarmonicAngleForce']].getNumAngles()
with open("Angle.parameters", 'w') as g:
	for i in range(numAngles):
		g.write('angle {}: {} \n'.format(i,system.getForces()[force_dict['HarmonicAngleForce']].getAngleParameters(i)))

''' Save torsion parameters to file. '''
numTorsions = system.getForces()[force_dict['CustomTorsionForce']].getNumTorsions()
with open("Torsion.parameters", 'w') as g:
	for i in range(numTorsions):
		g.write('torsion {}: {} \n'.format(i,system.getForces()[force_dict['CustomTorsionForce']].getTorsionParameters(i)))

''' Save non-bonded parameters to file. '''
numAtoms = nbf_obj.getNumParticles()
with open("nonbonded.parameters", "w") as g:
	for i in range(numAtoms):
		param = nbf_obj.getParticleParameters(i)
		''' Modify non-bonded forces if desired. '''
		#nbf_obj.setParticleParameters(index=i, charge=scalecharge*param[0].value_in_unit(elementary_charge), sigma=param[1].value_in_unit(nanometer), epsilon=param[2].value_in_unit(kilojoules_per_mole) )
		#param_updated = nbf_obj.getParticleParameters(i)
		mass = system.getParticleMass(i)
		g.write('atom {} and mass {}: {}\n'.format(i,mass,param))

# minimize and run simulation
simulation.context.applyConstraints(1e-8)
positions = simulation.context.getState(getPositions=True).getPositions()

# get forces on each particle
forces = simulation.context.getState(getForces=True).getForces()
flog = open('forces.out', 'w')
for i, f in enumerate(forces):
    if norm(f) > 1e4*kilojoules_per_mole/nanometer:
        flog.write("{} {}\n".format(i,f))
flog.close()

write2log(logname,"Done with Constraints \n")
timestart = time.time()
write2log(logname,'pre minimization potential energy: {} \n'.format(simulation.context.getState(getEnergy=True).getPotentialEnergy()))
simulation.minimizeEnergy(tolerance=0.01*kilojoules_per_mole,maxIterations=1000000)
write2log(logname,'post minimization potential energy: {} \n'.format(simulation.context.getState(getEnergy=True).getPotentialEnergy()))
timeend = time.time()
write2log(logname,"Done with Minimization in {} mininutes\n".format((timeend-timestart)/60.))
simulation.reporters.append(app.dcdreporter.DCDReporter('npt.dcd', 1000))
simulation.reporters.append(StateDataReporter('thermo.out', 1000, step=True, potentialEnergy=True, kineticEnergy=True, totalEnergy=True, temperature=True, volume=True, density=True, speed=True))

forces = simulation.context.getState(getForces=True).getForces()
flog = open('forces_1.out', 'w')
for i, f in enumerate(forces):
    if norm(f) > 1e4*kilojoules_per_mole/nanometer:
        flog.write("{} {}\n".format(i,f))
flog.close()

simulation.step(5000) # run short NVT
write2log(logname,"Done with Short NVT \n")

if TestBenzeneGeom: # check if ring planar
    gout = open('geom.out','w')
    gout.write('#  d25  d36  d47  |  d37  ||  d25-d36  d25-d47  d36-d47  |||  chk1  chk2  control\n')
    gout.close()
    for _i in range(100):
        positions = simulation.context.getState(getPositions=True).getPositions()
        d25 = norm(positions[0]-positions[3])
        d36 = norm(positions[1]-positions[4])
        d47 = norm(positions[2]-positions[5])
        d37 = norm(positions[1]-positions[5])
        pvec = np.cross(positions[0],positions[3])
        chk1 = np.inner(positions[2],pvec)
        chk2 = np.inner(positions[4],pvec)
        chk3 = np.inner(positions[0],pvec)
        gout = open('geom.out','a')
        gout.write('{}  {}  {}  {}  |  {}  ||  {}  {}  {}  |||  {}  {}  {}\n'.format(_i,d25,d36,d47,d37,d25-d36,d25-d47,d36-d47,chk1,chk2,chk3))
        gout.close()
        simulation.step(200)

positions = simulation.context.getState(getPositions=True).getPositions()
app.pdbfile.PDBFile.writeModel(simulation.topology,positions,open('loadpdb.pdb','w'))
simulation.step(50E6)


# -*- coding:utf-8 -*-

from tkinter import *
from PIL import ImageGrab,Image
import random,os
import numpy as np
import NeuralNet

class Paint(Frame):
    width = 200
    height = 200
    alphabet = ['А','Б','В','Г','Д','Е','Ё','Ж','З','И','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ь','Ы','Э','Ю','Я','0','1','2','3','4','5','6','7','8','9']
    # alphabet = ['0','1','2','3','4']
    learned = []

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.hnodes = 400
        self.learning_rate = 0.0005
        self.nnet = NeuralNet.NeuralNet((self.width * self.height), self.hnodes,len(self.alphabet),self.learning_rate)
        # self.nnet = NeuralNet.NeuralNet(2, 2,2,self.learning_rate)

        self.setUI()
        self.brush_size = 8
        self.brush_color="black"

    def setUI(self):

        self.parent.title("Handwriting recognition")
        self.pack(side=RIGHT,fill=BOTH)
        self.canv = Canvas(self, bg="white", width=self.width, height=self.height)
        self.canv.grid(row=0, rowspan=10,columnspan=5)
        self.canv.bind("<B1-Motion>", self.draw)
        self.canv.bind("<Button-3>", self.clear)

        learn_label = Label(self, text="-" * 5 + " Add training examples " + "-" * 5)
        learn_label.grid(row=0, column=5, columnspan=5)

        learn_first = Label(self, text="1. Write a letter       ")
        learn_first.grid(row=1, column=5,columnspan=2)

        learn_second = Label(self, text="2. Select the letter   ")
        learn_second.grid(row=2, column=5,columnspan=2)
        self.var = StringVar(self)
        learn_second_input = OptionMenu(self, self.var, *self.alphabet,command=self.get_value)
        learn_second_input.grid(row=2, column=7,columnspan=3)

        learn_third_label = Label(self, text="3. Push the button  ")
        learn_third_label.grid(row=3, column=5,columnspan=2)
        learn_third_btn = Button(self, text="Add", width=8, command=lambda: self.add_btn(self))
        learn_third_btn.grid(row=3, column=7, padx=5,columnspan=3)

        separator_label = Label(self, text="-" * 34)
        separator_label.grid(row=4, column=5, columnspan=5)

        learn_btn = Button(self, text="Learn!", width=8, command=lambda: self.learn())
        learn_btn.grid(row=5, column=5, padx=5,columnspan=2)

        recognize_second_btn = Button(self, text="Recognize", width=8,command=lambda: self.recognize(self))
        recognize_second_btn.grid(row=5, column=7, padx=5,columnspan=3)

        load_btn = Button(self, text="Load", width=8, command=lambda: self.load())
        load_btn.grid(row=6, column=5, padx=5,columnspan=2)

        save_btn = Button(self, text="Save", width=8,command=lambda: self.save())
        save_btn.grid(row=6, column=7, padx=5,columnspan=3)

        learned_label = Label(self, text="-" * 32 + " Learned " + "-" * 32)
        learned_label.grid(row=11, column=0, columnspan=10)

        result_label = Label(self, text="-" * 33 + " Result " + "-" * 33)
        result_label.grid(row=20, column=0, columnspan=10)

        # col = 0
        # row = 0
        # for i in range(len(self.alphabet)):
        #     if i % 6 == 0 and i != 0:
        #         col+=1
        #         row=0
        #     Label(self, text="%s:%1.3f" % (self.alphabet[i],0)).grid(row=21+row, column=col+1,sticky=W)
        #     row+=1

    def draw(self,event):
        self.canv.create_oval(event.x - self.brush_size,event.y - self.brush_size,
                              event.x + self.brush_size,event.y + self.brush_size,
                              fill=self.brush_color, outline=self.brush_color)

    def clear(self, event):
        self.canv.delete("all")

    def add_btn(self, widget):
        x = self.winfo_rootx()
        y = self.winfo_rooty()
        x1 = x + self.width
        y1 = y + self.height
        im = ImageGrab.grab().crop((x, y, x1, y1))
        numimage = np.dot(np.array(im),[0.299, 0.587, 0.114]).ravel()
        # im.save(os.getcwd()+"\\img\\" + str(random.randint(1, 1000000000))+".JPG")
        scaled_image = (numimage / 255 * 0.98) + 0.01
        a_str = ','.join(str(x) for x in scaled_image)
        output = [0.99 if self.curval == x else 0.01 for x in self.alphabet ]
        o_str = ','.join(str(x) for x in output)

        f = open(os.getcwd()+"\\data.txt",'a')
        f.write(self.curval+','+o_str+','+a_str+'\n')
        f.close()

        if self.curval not in self.learned:
            self.learned.append(self.curval)

        r = 12
        c = 0
        for i in range(len(self.learned)):
            if i % 10 == 0 and i != 0:
                r += 1
                c = 0
            Label(self, text="%s " % self.learned[i]).grid(row=r, column=c)
            c+=1
        self.clear(None)

    def learn(self):
        # try:
            for i in range(10):
                f = open(os.getcwd()+"\\data.txt",'r')
                for line in f:
                    label = line.split(',')[0]
                    output = list(map(float,line.split(',')[1:len(self.alphabet)+1]))
                    data = list(map(float,line.split(',')[len(self.alphabet) + 1:]))
                    self.nnet.train(data,output)
                print(i)
        # except:
        #     print("Не удалось открыть файл")
        # finally:
        #     f.close()

    def recognize(self,widget):
        x = self.winfo_rootx()
        y = self.winfo_rooty()
        x1 = x + self.width
        y1 = y + self.height
        im = ImageGrab.grab().crop((x, y, x1, y1))
        numimage = np.dot(np.array(im),[0.299, 0.587, 0.114]).ravel()
        scaled_image = (numimage / 255 * 0.98) + 0.01
        result = self.nnet.work(scaled_image)

        col = 0
        row = 0
        for i in range(len(result)):
            if i % 6 == 0 and i != 0:
                col+=1
                row=0
            Label(self, text="%s:%3.2f " % (self.alphabet[i],result[i]*100)).grid(row=21+row, column=col+1,sticky=W)
            row+=1

    def save(self):
        f = open(os.getcwd()+"\\weights.txt",'w')
        # wih = '\n'.join([','.join(str(number) for number in line) for line in self.nnet.wih])
        # who = '\n'.join([','.join(str(number) for number in line) for line in self.nnet.who])
        wih =  ','.join(str(x) for x in self.nnet.wih.ravel())
        who =  ','.join(str(x) for x in self.nnet.who.ravel())
        f.write(wih+','+who)
        print(self.nnet.wih)
        print(self.nnet.who)
        print(self.nnet.who.shape)
        f.close()

    def load(self):
        # try:
            f = open(os.getcwd()+"\\weights.txt",'r')
            weights = f.readline().split(',')
            self.nnet.wih = np.array(weights[ : self.nnet.wih.shape[0] * self.nnet.wih.shape[1]]).reshape(self.nnet.wih.shape)
            self.nnet.who = np.array(weights[self.nnet.who.shape[0] * self.nnet.who.shape[1]: ]).reshape(self.nnet.who.shape)

        # except:
        #     print("Не удалось открыть файл")
        # finally:
        #     f.close()
    def get_value(self,value):
        self.curval = value

def main():
    root = Tk()
    root.geometry("390x475")
    root.resizable(width=FALSE, height=FALSE)
    app = Paint(root)
    root.mainloop()

if __name__ == "__main__":
    main()


"""
Configuration file for TauOpt

The following configuration variables determine overall behaviour of TauOpt

The values of these variables in this file determine the default behaviour of TauOpt
These values can be overridden by passing a user-created configuration file to TauOpt.py
Example : " TauOpt.py --user_config.py "

The user-created configuration file is also a python file which contains distinct values of the varaibles
and function reference defined below

"""

#Full/absolute path to the project folder
# "project_folder" directory contains the source code all files/folder produced by TauOpt
project_folder=''

# Name of the simulation code
# The source code must be within the directory  "project_folder/code_name/"
code_name =''

#Name of the executable
exec_name = ''

#list of all files that contain chaging "input variables" defined in var_names below
input_files = []

# list of all auxiliary files. These files are simply copied from the code folder
# to the run folder (no modification) for each run
aux_files = []

#list containing names of the all varaibles are the changed from one run to another.
#the files listed in "input_files" contain elements of var_names (with prefix "var_names_prefix") which are automatically replaced by
#a valid numeral value
#Example : var_names = ['x1','x2']
var_names = ['']

#This prefix is combined with elements of var_names to indetify strings that are replaced by numeral values
var_names_prefix = '$'

# scan_type defines how the input varaibles are changed
#
# 'func'   : get new set of varaibles from a user defined function
# 'opt'    : automatically adjust the values of input varaibles with optimization (default)
# 'file'   : read the values sequentially from a file
# 'grid'   : input varaibles uniformly spaced () in the specified range (var_range)
# 'random' : input varaibles are randomly selected in the specified range (var_range)
# each mode listed above requires additional configuration varaibles defined below

scan_type = 'opt'

"""

Configuration for optimization

The values of "var_names" are varied automatically

scan_type = 'opt'

"""

#list : initial values of the varaibles listed in "var_names"
#Example : var_val0 = [3, 8.2]
var_val0 = []

#range of the varaibles, if the values are determined using an optimization algorithm
#Example : var_range = {'x1':[1, 10], 'x2':[2.0, 10.0]}
var_range = {}

#tolerance in the determination of the optimal values
#Example : var_tolerance = {'x1': 0.1, 'x2': 0.1 }
var_tolerance = {}

#num. of grid points for each varaible if scan_type == 'grid'; default is 2
var_grid_npoints = {}

#grid spacing ('log' or 'linear') for the input varaible grid
#set to 'linear' by default if not specified and scan_type == 'grid' or random
var_grid_spacing = {}

#configuration for the optimization algorithms
#default choice is the Coordinate Descent algorithm with 4th degree polynomial surrogate model
opt_algo_config = { 'type'            : 'cord_desc',
                    'model'           : 'gp',
                    'num_warm_points' : 3
                  }

#configuration for the surrogate model
model_poly_config = { 'max_deg' : 4
                    }

model_gp_config   = { 'kernel' : 'Matern'
                    }

"""

Configuration for sequential scan

The values of "var_names" are read from a file

scan_type = 'file'

"""

#name of the file containing values of the variables
#supported formats/extensions : .txt, .csv, .xls, .xlsx, .h5, .hdf5
#Example : var_filename = 'test_param.txt'
var_filename = ''

"""

Configuration for sequential scan

The values of "var_names" are obtained from a user-defined function

scan_type = 'func'

"""

var_func = ''

"""

Configuration for code execution, queue managment

"""

#name of the job submission script. The file must be located in "project_folder/code_name"
#Example : submission_script = 'pictor.slurm'
submission_script = ''

# username, if the simulations are run submitted to a queue manager (slurm, PBS)
# Example : username = 'rahulkr'
# Default : username = '' implies running on the local computer
username = ''

#command for the local execution
#Default : ./exec_name
#Example : local_exec_cmd = ['mpirun','-np','4','./PICTOR']
local_exec_cmd = []

#maximum number of simulations run by TauOpt
max_num_runs = 100

#maximum number of jobs in the queue (waiting+running)
max_num_jobs = 10

"""

Dictionaries :: set of config. parameters that user can pass to configure some specific functions used internally

"""

"""

Function/Dictionaries for interacting with the simulation code

Note: functions defined in the config. files are called from the run folder (project_folder/run$sim_num)

"""

# Determine if the simulation finished sucessfully
# callable function, or
# based on whether a file/folder exists or not
# Example :
# finished_successfully = { 'Folder'    : 'data' # relative path (from project_folder/run$sim_num/) of the file that is looked for
#                           'FileName'  :  name of the file
#                        }

finished_successfully = None

#objective function whose output is optimized
objective_function = None

#function detailing compilation steps
compile_source_code = None

#function detailing the steps for restart
restart = None

"""
Configuration for compiling source codes
"""

# Default compilers to compile simple source codes
# Key: file extension, Value: compiler with flags/options
# To use different compilers/flags, define the 'standard_compilation' dict. in your configulation file to override the default here
standard_compilation =   { '.c'   : 'gcc',
                           '.cpp' : 'g++',
                           '.f90' : 'gfortran'
                         }


import os

import matplotlib.pyplot as plt

from r2d2.plotting.analysis_func import *
from r2d2.plotting.misc import *
from r2d2.plotting.text import *

# Gather Graphical Data #
data_path = None  # "/Volumes/R2D2_Drive/MyDrive/R2D2: Weekly Lab Data/IPRL"
dir_path = os.path.dirname(os.path.realpath(__file__))
data_directory = os.path.join(dir_path, "../../", "data") if data_path is None else data_path
PLOT_FOLDERPATH = os.path.join(dir_path, "../../", "plots")
if not os.path.exists(PLOT_FOLDERPATH):
    os.makedirs(PLOT_FOLDERPATH)

# Run Data Crawler #
data_crawler(data_directory, func_list=[analysis_func])

# Prepare Cumulative Values #
cumulative_dicts = [traj_progress_dict, scene_progress_dict]
for curr_dict in cumulative_dicts:
    all_dict_keys = list(curr_dict.keys())
    for key in all_dict_keys:
        curr_dict[key] = np.cumsum(curr_dict[key])
        curr_dict["R2D2"] += curr_dict[key]

# Make Figure #
fig = plt.figure()

# Plot Trajectory Progress #
plt.xticks(all_month_timestamps, labels=all_month_names)
for key in traj_progress_dict:
    lab_progress = traj_progress_dict[key]
    plt.plot(DAY_TIMESTAMPS, lab_progress, label=key)

plt.legend(loc="center left", bbox_to_anchor=(1, 0.5))
plt.title("Trajectories Collected", fontweight="bold")
plt.savefig(PLOT_FOLDERPATH + "/trajectory_progress.png", bbox_inches="tight")

# Plot Scene Progress #
plt.clf()
plt.xticks(all_month_timestamps, labels=all_month_names)
for key in scene_progress_dict:
    lab_progress = scene_progress_dict[key]
    plt.plot(DAY_TIMESTAMPS, lab_progress, label=key)

plt.legend(loc="center left", bbox_to_anchor=(1, 0.5))
plt.title("Scenes Collected", fontweight="bold")
plt.savefig(PLOT_FOLDERPATH + "/scene_progress.png", bbox_inches="tight")

# Plot Week Summary #
plt.clf()
weekly_threshold = 150000
lab_names = list(weekly_progress_dict.keys())
lab_quantities = [weekly_progress_dict[key] for key in lab_names]
plt.bar(lab_names, lab_quantities)
plt.axhline(weekly_threshold, color="black", ls="dotted")
plt.title("Week Summary: Samples Collected", fontweight="bold")
plt.savefig(PLOT_FOLDERPATH + "/week_progress.png", bbox_inches="tight")

# Plot User Progress #
plt.clf()
user_threshold = 500000
user_names = list(user_progress_dict.keys())
user_quantities = [user_progress_dict[key] for key in user_names]
tick_names = ["{0}K".format(100 * i) if i < 10 else "1M" for i in range(6)]
tick_values = [1e5 * i for i in range(len(tick_names))]
plt.xticks(tick_values, labels=tick_names)
plt.barh(user_names, user_quantities)
plt.axvline(user_threshold, color="blue", ls="dotted", label="Standard Requirement")
plt.axvline(user_threshold // 2, color="green", ls="dotted", label="Lab Lead Requirement")
plt.title("Per Person Progress", fontweight="bold")
plt.xlabel("Data Points Collected")
plt.legend(loc="center left", bbox_to_anchor=(1, 0.5))
plt.savefig(PLOT_FOLDERPATH + "/personal_progress.png", bbox_inches="tight")

# Plot Task Distribution #
plt.clf()
task_names = list(task_distribution_dict.keys())
task_quantities = [task_distribution_dict[key] for key in task_names]
sections, texts = plt.pie(task_quantities)
plt.legend(sections, task_names, loc="center left", bbox_to_anchor=(1, 0.5))
plt.title("Task Distribution", fontweight="bold")
plt.savefig(PLOT_FOLDERPATH + "/task_distribution.png", bbox_inches="tight")

# Plot Trajectory Length Distribution #
plt.clf()
plt.hist(all_traj_lengths, bins=100)
plt.xlim([0, 1000])
plt.title("Horizon Distribution", fontweight="bold")
plt.savefig(PLOT_FOLDERPATH + "/horizon_distribution.png", bbox_inches="tight")

# Plot Camera Pose Distribution #
plt.clf()
ax_pos = fig.add_subplot(1, 2, 1, projection="3d")
ax_ang = fig.add_subplot(1, 2, 2, projection="3d")
pos_values, pos_density, ang_values, ang_density = estimate_pos_angle_density(all_camera_poses)
ax_pos.scatter(pos_values[0], pos_values[1], pos_values[2], c=pos_density, cmap="viridis", linewidth=0.5)
ax_ang.scatter(ang_values[0], ang_values[1], ang_values[2], c=ang_density, cmap="viridis", linewidth=0.5)
ax_pos.set_title("Camera Positions", fontweight="bold")
ax_ang.set_title("Camera Angles", fontweight="bold")
ax_pos.view_init(elev=20, azim=-23)
ax_ang.view_init(elev=14, azim=-143)
plt.savefig(PLOT_FOLDERPATH + "/camera_poses.png", bbox_inches="tight")
plt.show()


import logging
import unittest

import dbldatagen as dg

spark = dg.SparkSingleton.getLocalInstance("unit tests")

class TestRanges(unittest.TestCase):
    testDataSpec = None
    dfTestData = None
    row_count = 100000
    column_count = 50

    def setUp(self):
        print("setting up")
        FORMAT = '%(asctime)-15s %(message)s'
        logging.basicConfig(format=FORMAT)

    @classmethod
    def setUpClass(cls):
        pass

    def test_numeric_range1(self):
        r1 = dg.NRange(1, 20, 1)

        self.assertEqual(r1.getDiscreteRange(), 19)
        print(r1.getDiscreteRange())

    def test_numeric_range2(self):
        r1 = dg.NRange(1.5, 2.5, 0.35)

        print(r1.getDiscreteRange())
        self.assertEqual(r1.getDiscreteRange(), 2.0)

        self.assertEqual(r1.getScale(), 2)

    def test_numeric_range3(self):
        r1 = dg.NRange(1.5, 2.5, 0.5)

        print(r1.getDiscreteRange())

    def test_numeric_range4(self):
        r1 = dg.NRange(0, 4, 0.5)
        self.assertEqual(r1.getDiscreteRange(), 8.0)

        print(r1.getDiscreteRange())

    def test_optional_min_max(self):

        r1 = dg.NRange(-1, 100)

        self.assertEqual(r1.minValue, -1)
        self.assertEqual(r1.maxValue, 100)

        r2 = dg.NRange(min=-1, max=100)

        self.assertEqual(r2.minValue, -1)
        self.assertEqual(r2.maxValue, 100)

        r3 = dg.NRange(minValue=-1, maxValue=100)

        self.assertEqual(r3.minValue, -1)
        self.assertEqual(r3.maxValue, 100)

# run the tests
# if __name__ == '__main__':
#  print("Trying to run tests")
#  unittest.main(argv=['first-arg-is-ignored'],verbosity=2,exit=False)

# def runTests(suites):
#    suite = unittest.TestSuite()
#    result = unittest.TestResult()
#    for testSuite in suites:
#        suite.addTest(unittest.makeSuite(testSuite))
#    runner = unittest.TextTestRunner()
#    print(runner.run(suite))

# runTests([TestBasicOperation])

if __name__ == '__main__':
    unittest.main()


# -*- coding: utf-8 -*-
"""
使用Ltp3.4进行中文分词词性标注

"""
import os
from pyltp import Postagger

# ltp模型目录的路径
LTP_DATA_DIR = 'D:\ltp_data_v3.4.0\ltp_data_v3.4.0'
# 词性标注模型路径，模型名称为`pos.model`
pos_model_path = os.path.join(LTP_DATA_DIR, 'pos.model')
# 初始化实例
posttagger = Postagger()
# 加载词性标注模型
posttagger.load(pos_model_path)
# 分词结果
words = ['元芳', '你', '怎么', '看']
# 词性标注
postags = posttagger.postag(words)
# Ltp的词性标注遵从国标863词性标注集
for word,postag in zip(words,postags):
    print(word+"/"+postag)
# 释放模型
posttagger.release()


from datetime import datetime, date
from matplotlib import pyplot as plt
import numpy as np
from  bcb import sgs

def checking_dates_and_frequency():

    capital = input(f"Digite o capital investido R$: ")
    frequency = input("Digite a frequência do periodo: ").lower()
    start = input("Digite a data inicial maior do que 1995/01/01 no seguinte formato YYYY/mm/dd: ")
    end = input(f"Digite a data final menor do que {date.today()} no seguinte formato YYYY/mm/dd: ")
    start = datetime.strptime(start, '%Y/%m/%d').date()
    end = datetime.strptime(end, '%Y/%m/%d').date()

    return capital, start, end, frequency

def challenge(selic, capital, start_date, end_date, frequency):

    selic_challenge = selic[(selic.index.date >= start_date ) & (selic.index.date < end_date)]

    selic_acum_return = (selic_challenge + 1).cumprod() - 1
    selic_acum_return = selic_acum_return.resample(f"{frequency.upper()}").last()

    selic_acum_return["capital"] = (selic_acum_return["juros"] * float(capital)) + float(capital)
    selic_acum_return["earned"] = selic_acum_return["capital"] - selic_acum_return["capital"].iloc[0]
    selic_acum_return.fillna(0,inplace=True)

    print(selic_acum_return)

def question(selic):

    initial_date = date(2000,1,1)
    final_date = date(2022,3,31)
    selic_question = selic[(selic.index.date >= initial_date ) & (selic.index.date < final_date)]

    windows = ((1 + selic_question).rolling(window=500).apply(np.prod) - 1)
    windows.plot()
    windows = windows.reset_index()
    windows.columns = ["end_date","returns"]
    windows.insert(0,"init_date",0)
    windows["init_date"] = windows["end_date"].shift(499)
    windows.dropna(inplace=True)
    plt.show()

    id_row = windows["returns"].idxmax()
    row = windows.loc[id_row]
    initial_return_date = row[0]
    final_return_date  = row[1]
    max_return = row[2]
    print(f'''O intervalo de datas de maior retorno foi:
          {initial_return_date} até {final_return_date} com retorno de {round(max_return,3)*100} %''')
    selic_range = selic_question[(selic_question.index >= initial_return_date) & (selic_question.index <= final_return_date)]
    acum_return_range = (selic_range + 1).cumprod() - 1
    acum_return_range.plot()
    plt.show()

capital, start_date, end_date, frequency = checking_dates_and_frequency()

date_min = date(1995,1,1)
selic = sgs.get({"juros":11}, start=date_min)/100

challenge(selic, capital, start_date, end_date, frequency)
question(selic)


BOT_NAME = 'reddit'
SPIDER_MODULES = ['reddit.spiders']
NEWSPIDER_MODULES = ['reddit.spiders']
DOWNLOAD_DELAY = 2

ITEM_PIPELINES = {
	'reddit.pipelines.DuplicatesPipeline': 300,
	'reddit.pipelines.MongoDBPipeline': 800,
}

MONGODB_SERVER = 'localhost'
MONGODB_PORT = 27017
MONGODB_DB = 'bytom_info'
MONGODB_COLLECTION = 'reddit'


# -*- coding: utf-8 -*-
"""
Created on Sunday Dec. 24th
============================================================
@author: Tiger

Add:
        - loss plot only accumulated loss
        - validation over 1000 images per epoch
        - smaller kernel size
        - smaller image crop
        - RAM???
"""
""" Install for Pytorch:

     1) must first install cuda
     2) conda install pytorch torchvision cudatoolkit=10.2 -c pytorch   # Must indicate cuda version???

     3) pip install torchio

     torch.__version__

     *** must add device(device) ==> to send things to GPU!

     ***crazy speed up with line below
     torch.backends.cudnn.benchmark = True

     torch.backends.cudnn.deterministic=True

     ***For uninstall:
     conda install pytorch torchvision cudatoolkit=10.2 -c pytorch

     put import statements at top of file or may crash???

     Add main function so can do multi-threading?
     no classes within main function

     use volatile == True for inference mode???
"""

""" ALLOWS print out of results on compute canada """
import matplotlib
matplotlib.rc('xtick', labelsize=8)
matplotlib.rc('ytick', labelsize=8)
#matplotlib.use('Agg')
import matplotlib.pyplot as plt

""" Libraries to load """
import numpy as np
from plot_functions_CLEANED import *
from data_functions_CLEANED import *
from data_functions_3D import *
from tracker import *
import glob, os
import datetime
import time
from natsort import natsort_keygen, ns
natsort_key1 = natsort_keygen(key = lambda y: y.lower())      # natural sorting order

import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from UNet_pytorch import *
from UNet_pytorch_online import *
from PYTORCH_dataloader import *
from HD_loss import *

from sklearn.model_selection import train_test_split

from unet_nested import *

torch.backends.cudnn.benchmark = True
torch.backends.cudnn.enabled = True

if __name__ == '__main__':

    """ Define GPU to use """
    device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
    print(device)

    """" Input paths """
    HD = 0; alpha = 1; dist_loss = 0; deep_sup = 0;
    #s_path = './(1) Checkpoints_full_auto_no_spatialW_TRACKER/';
    #s_path = './(2) Checkpoints_full_auto_spatialW/'

    #s_path = './(3) Checkpoints_full_auto_no_spatialW_nested_unet/'

    s_path = './(4) Checkpoints_full_auto_no_spatialW_large_TRACKER/'

    #s_path = './(5) Checkpoints_full_auto_no_spatialW_large_TRACKER_switch_norm/'

    s_path = './(6) Checkpoints_full_auto_no_spatialW_large_TRACKER_NO_NEXT_SEG/'

    s_path = './(7) Checkpoints_full_auto_no_spatialW_large_TRACKER_CROP_PADS_NO_NEXT_SEG_skipped/'; next_seg = 0;

    #s_path = './(8) Checkpoints_full_auto_no_spatialW_large_TRACKER_CROP_PADS_YES_NEXT_SEG/'; next_seg = 1;

    s_path = './(9) Checkpoints_full_auto_no_spatialW_large_TRACKER_CROP_PADS_NO_NEXT_hausdorf/'; next_seg = 0; HD = 1; alpha = 1;

    #s_path = './(10) Checkpoints_full_auto_no_spatialW_large_TRACKER_CROP_PADS_NO_NEXT/'; next_seg = 0;

    input_path = '/media/user/storage/Data/(2) cell tracking project/a_training_data_GENERATE_FULL_AUTO/Training_cell_track_full_auto_COMPLETED_crop_pads/'

    resume = 0
    """ TO LOAD OLD CHECKPOINT """
    # Read in file names
    onlyfiles_check = glob.glob(os.path.join(s_path,'check_*'))
    onlyfiles_check.sort(key = natsort_key1)

    # """ load mean and std """
    mean_arr = np.load('./normalize_pytorch_CLEANED/mean_VERIFIED.npy')
    std_arr = np.load('./normalize_pytorch_CLEANED/std_VERIFIED.npy')

    num_workers = 2;

    save_every_num_epochs = 1;    plot_every_num_epochs = 1;    validate_every_num_epochs = 1;

    deep_supervision = False;

    """ Load filenames from tiff """
    images = glob.glob(os.path.join(input_path,'*_crop_input_cur.tif'))    # can switch this to "*truth.tif" if there is no name for "input"
    images.sort(key=natsort_keygen(alg=ns.REAL))  # natural sorting
    examples = [dict(input=i,seed          = i.replace('_crop_input_cur.tif','_crop_input_cur_seed.tif'),
                             cur_full_seg  = i.replace('_crop_input_cur.tif','_crop_input_cur_seg_FULL.tif'),
                             next_input    = i.replace('_crop_input_cur.tif','_crop_input_next.tif'),
                             next_full_seg = i.replace('_crop_input_cur.tif','_crop_input_next_seg_FULL.tif'),
                             truth         = i.replace('_crop_input_cur.tif','_crop_truth.tif')) for i in images]

    # ### REMOVE FULL TIMESERIES from training data
    idx_skip = []
    for idx, im in enumerate(examples):
        filename = im['input']
        if 'MOBPF_190105w_1_cuprBZA_10x' in filename:
            print('skip')
            idx_skip.append(idx)

    ### USE THE EXCLUDED IMAGE AS VALIDATION/TESTING
    examples_test = examples[0:len(idx_skip)]

    examples = [i for j, i in enumerate(examples) if j not in idx_skip]

    counter = list(range(len(examples)))

    if not onlyfiles_check:   ### if no old checkpoints found, start new network and tracker

        """ Hyper-parameters """
        deep_sup = False
        switch_norm = False
        sp_weight_bool = 0
        #transforms = initialize_transforms(p=0.5)
        #transforms = initialize_transforms_simple(p=0.5)
        transforms = 0
        batch_size = 4;
        test_size = 0.1

        if next_seg:
            in_channels = 4
        else:
            in_channels = 3

        """ Initialize network """
        kernel_size = 7
        pad = int((kernel_size - 1)/2)
        unet = UNet_online(in_channels=in_channels, n_classes=2, depth=5, wf=4, kernel_size = kernel_size, padding= int((kernel_size - 1)/2),
                            batch_norm=True, batch_norm_switchable=switch_norm, up_mode='upsample')
        #unet = NestedUNet(num_classes=2, input_channels=2, deep_sup=deep_sup, padding=pad, batch_norm_switchable=switch_norm)
        #unet = UNet_3Plus(num_classes=2, input_channels=2, kernel_size=kernel_size, padding=pad)

        unet.train()
        unet.to(device)
        print('parameters:', sum(param.numel() for param in unet.parameters()))

        """ Select loss function *** unimportant if using HD loss """
        if not HD:    loss_function = torch.nn.CrossEntropyLoss(reduction='none')
        else:         loss_function = 'Haussdorf'

        """ Select optimizer """
        lr = 1e-5; milestones = [20, 100]  # with AdamW slow down
        optimizer = torch.optim.AdamW(unet.parameters(), lr=lr, betas=(0.9, 0.999), eps=1e-08, weight_decay=0.01, amsgrad=False)

        """ Add scheduler """
        scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)

        """ initialize index of training set and validation set, split using size of test_size """

        idx_train, idx_valid, empty, empty = train_test_split(counter, counter, test_size=test_size, random_state=2018)

        """ initialize training_tracker """
        # idx_valid = idx_skip
        # idx_train = counter

        tracker = tracker(batch_size, test_size, mean_arr, std_arr, idx_train, idx_valid, deep_sup=deep_sup, switch_norm=switch_norm, alpha=alpha, HD=HD,
                                          sp_weight_bool=sp_weight_bool, transforms=transforms, dataset=input_path)

        tracker.next_seg = next_seg

    else:
        """ Find last checkpoint """
        last_file = onlyfiles_check[-1]
        split = last_file.split('check_')[-1]
        num_check = split.split('.')
        checkpoint = num_check[0]
        checkpoint = 'check_' + checkpoint

        print('restoring weights from: ' + checkpoint)
        check = torch.load(s_path + checkpoint, map_location=lambda storage, loc: storage)
        #check = torch.load(s_path + checkpoint, map_location='cpu')
        #check = torch.load(s_path + checkpoint, map_location=device)

        tracker = check['tracker']

        unet = check['model_type']
        optimizer = check['optimizer_type']
        scheduler = check['scheduler_type']
        unet.load_state_dict(check['model_state_dict'])
        unet.to(device)
        optimizer.load_state_dict(check['optimizer_state_dict'])
        scheduler.load_state_dict(check['scheduler'])
        loss_function = check['loss_function']

        print('parameters:', sum(param.numel() for param in unet.parameters()))

        """ Clean up checkpoint file """
        del check
        torch.cuda.empty_cache()

    """
        Time for 50 iterations (batch size 2)
        411.34 ==> 0 workers
        183.78438819999997 ==> 2 workers
        127 ==> 4 workers ==> 60 secs training generator time
        111.03402260000001 ==> no transform
        109 ==> 6 workers ==> 90 secs training generator time
        110.0 ==> 6 workers WITH DIRECT LOADING FROM BCOLZ ==> 30 secs generator tim
        max is 1000 samples loaded with batch size 2 and even with batch size 1???

        On Titan:
            time for 50 batch size 2 ==> 71 secs
            time for 50 batch size 4 ==> 116 secs (with transforms)

    """

    """ Create datasets for dataloader """
    training_set = Dataset_tiffs(tracker.idx_train, examples, tracker.mean_arr, tracker.std_arr,
                                           sp_weight_bool=tracker.sp_weight_bool, transforms = tracker.transforms, next_seg=tracker.next_seg)
    val_set = Dataset_tiffs(tracker.idx_valid, examples, tracker.mean_arr, tracker.std_arr,
                                      sp_weight_bool=tracker.sp_weight_bool, transforms = 0, next_seg=tracker.next_seg)

    """ Create training and validation generators"""
    val_generator = data.DataLoader(val_set, batch_size=tracker.batch_size, shuffle=False, num_workers=num_workers,
                    pin_memory=True, drop_last = True)

    training_generator = data.DataLoader(training_set, batch_size=tracker.batch_size, shuffle=True, num_workers=num_workers,
                      pin_memory=True, drop_last=True)

    print('Total # training images per epoch: ' + str(len(training_set)))
    print('Total # validation images: ' + str(len(val_set)))

    """ Epoch info """
    train_steps_per_epoch = len(tracker.idx_train)/tracker.batch_size
    validation_size = len(tracker.idx_valid)
    epoch_size = len(tracker.idx_train)

    print('Total # training images per epoch: ' + str(len(training_set)))
    print('Total # validation images: ' + str(len(val_set)))

    """ Epoch info """
    train_steps_per_epoch = len(tracker.idx_train)/tracker.batch_size
    validation_size = len(tracker.idx_valid)
    epoch_size = len(tracker.idx_train)

    """ Start training """
    starter = 0
    for cur_epoch in range(len(tracker.train_loss_per_epoch), 10000):
         unet.train
         loss_train = 0
         jacc_train = 0

         """ check and plot params during training """
         for param_group in optimizer.param_groups:
               #tracker.alpha = 0.5
               param_group['lr'] = 1e-6   # manually sets learning rate
               cur_lr = param_group['lr']
               tracker.lr_plot.append(cur_lr)
               tracker.print_essential()

         iter_cur_epoch = 0;
         ce_train = 0; dc_train = 0; hd_train = 0;
         for batch_x, batch_y, spatial_weight in training_generator:
                starter += 1
                if starter == 1:
                    start = time.perf_counter()
                if starter == 50:
                    stop = time.perf_counter(); diff = stop - start; print(diff)

                # PRINT OUT THE SHAPE OF THE INPUT
                if iter_cur_epoch == 0:
                    print('input size is' + str(batch_x.shape))

                """ Plot for debug """
                # np_inputs = np.asarray(batch_x.numpy()[0], dtype=np.uint8)
                # np_labels = np.asarray(batch_y.numpy()[0], dtype=np.uint8)
                # np_labels[np_labels > 0] = 255

                # imsave(s_path + str(iterations) + '_input.tif', np_inputs)
                # imsave(s_path + str(iterations) + '_label.tif', np_labels)

                # in_max = plot_max(np_inputs, plot=0)
                # lb_max = plot_max(np_labels, plot=0)

                # imsave(s_path + str(iterations) + '_max_input.tif', in_max)
                # imsave(s_path + str(iterations) + '_max_label.tif', lb_max)

                """ Load data ==> shape is (batch_size, num_channels, depth, height, width)
                     (1) converts to Tensor
                     (2) normalizes + appl other transforms on GPU
                     (3) ***add non-blocking???
                     ***INPUT LABELS MUST BE < 255??? or else get CudNN error

                """
                inputs, labels = transfer_to_GPU(batch_x, batch_y, device,  tracker.mean_arr, tracker.std_arr)

                """ zero the parameter gradients"""
                optimizer.zero_grad()

                """ forward + backward + optimize """
                output_train = unet(inputs)

                """ calculate loss: includes HD loss functions """
                if tracker.HD:
                    loss, tracker, ce_train, dc_train, hd_train = compute_HD_loss(output_train, labels, tracker.alpha, tracker,
                                                                                ce_train, dc_train, hd_train, val_bool=0)
                else:
                     if deep_sup:   ### IF DEEP SUPERVISION
                        # compute output
                        loss = 0
                        for output in output_train:
                             loss += loss_function(output, labels)
                        loss /= len(output_train)
                        output_train = output_train[-1]  # set this so can eval jaccard later

                     else:   ### IF NORMAL LOSS CALCULATION
                        loss = loss_function(output_train, labels)
                        if torch.is_tensor(spatial_weight):   ### WITH SPATIAL WEIGHTING
                             spatial_tensor = torch.tensor(spatial_weight, dtype = torch.float, device=device, requires_grad=False)
                             weighted = loss * spatial_tensor
                             loss = torch.mean(weighted)

                        else:  ### NO WEIGHTING AT ALL
                             loss = torch.mean(loss)

                loss.backward()
                optimizer.step()

                """ Training loss """
                """ ********************* figure out how to do spatial weighting??? """
                """ Training loss """
                tracker.train_loss_per_batch.append(loss.cpu().data.numpy());  # Training loss
                loss_train += loss.cpu().data.numpy()

                """ Calculate Jaccard on GPU """
                jacc = jacc_eval_GPU_torch(output_train, labels)
                jacc = jacc.cpu().data.numpy()

                jacc_train += jacc # Training jacc
                tracker.train_jacc_per_batch.append(jacc)

                tracker.iterations = tracker.iterations + 1
                iter_cur_epoch += 1
                if tracker.iterations % 100 == 0:
                     print('Trained: %d' %(tracker.iterations))

         tracker.train_loss_per_epoch.append(loss_train/iter_cur_epoch)
         tracker.train_jacc_per_epoch.append(jacc_train/iter_cur_epoch)

         """ Should I keep track of loss on every single sample? and iteration? Just not plot it??? """
         loss_val = 0; jacc_val = 0
         precision_val = 0; sensitivity_val = 0; val_idx = 0;
         iter_cur_epoch = 0;
         ce_val = 0; dc_val = 0; hd_val = 0;
         total_FPs = 0; total_TPs = 0; total_FNs = 0; total_TNs = 0;
         if cur_epoch % validate_every_num_epochs == 0:

              with torch.set_grad_enabled(False):  # saves GPU RAM
                  unet.eval()
                  for batch_x_val, batch_y_val, spatial_weight in val_generator:

                        """ Transfer to GPU to normalize ect... """
                        inputs_val, labels_val = transfer_to_GPU(batch_x_val, batch_y_val, device, mean_arr, std_arr)
                        output_val = unet(inputs_val)

                        """ calculate loss
                                include HD loss functions """
                        if tracker.HD:
                            loss, tracker, ce_val, dc_val, hd_val = compute_HD_loss(output_val, labels_val, tracker.alpha, tracker,
                                                                                ce_val, dc_val, hd_val, val_bool=1)
                        else:
                            if deep_sup:
                                # compute output
                                loss = 0
                                for output in output_val:
                                     loss += loss_function(output, labels_val)
                                loss /= len(output_val)
                                output_val = output_val[-1]  # set this so can eval jaccard later
                            else:

                                loss = loss_function(output_val, labels_val)
                                if torch.is_tensor(spatial_weight):
                                       spatial_tensor = torch.tensor(spatial_weight, dtype = torch.float, device=device, requires_grad=False)
                                       weighted = loss * spatial_tensor
                                       loss = torch.mean(weighted)
                                elif dist_loss:
                                       loss  # do not do anything if do not need to reduce

                                else:
                                       loss = torch.mean(loss)

                        """ Training loss """
                        tracker.val_loss_per_batch.append(loss.cpu().data.numpy());  # Training loss
                        loss_val += loss.cpu().data.numpy()

                        """ Calculate jaccard on GPU """
                        jacc = jacc_eval_GPU_torch(output_val, labels_val)
                        jacc = jacc.cpu().data.numpy()

                        jacc_val += jacc
                        tracker.val_jacc_per_batch.append(jacc)

                        """ Convert back to cpu """
                        output_val = output_val.cpu().data.numpy()
                        output_val = np.moveaxis(output_val, 1, -1)

                        """ Calculate # of TP, FP, FN, TN for every image in the batch"""
                        batch_y_val = batch_y_val.cpu().data.numpy()
                        labels_val = labels_val.cpu().data.numpy()
                        for b_idx in range(len(batch_y_val)):

                            # get image from current batch
                            seg_val = np.argmax(output_val[b_idx], axis=-1)
                            cur_label = labels_val[b_idx]

                            ### (1) If is TN or FN, the seg_val is blank
                            if not np.count_nonzero(seg_val):

                                ### It is a true negative if the seg_val is ALSO blank
                                if not np.count_nonzero(cur_label):
                                   total_TNs += 1

                                else:
                                   ### otherwise, calculate number of FN's
                                   # seg_val[seg_val > 0] = 1
                                   # labelled = measure.label(seg_val)
                                   # cc_coloc = measure.regionprops(labelled)

                                   total_FNs += 1

                            else:
                                ### (2) otherwise, test for TP and FP
                                only_coloc, TP, FP = find_overlap_objs(cur_label, seg_val)

                                total_TPs += TP
                                total_FPs += FP

                        #zzz
                        val_idx = val_idx + tracker.batch_size
                        print('Validation: ' + str(val_idx) + ' of total: ' + str(validation_size))
                        iter_cur_epoch += 1

              accuracy = (total_TPs + total_TNs)/(total_TPs + total_TNs + total_FPs + total_FNs)
              sensitivity = total_TPs/(total_TPs + total_FNs);
              precision = total_TPs/(total_TPs + total_FPs);

              tracker.val_loss_per_eval.append(loss_val/iter_cur_epoch)
              tracker.val_jacc_per_eval.append(jacc_val/iter_cur_epoch)

              tracker.plot_prec.append(precision)
              tracker.plot_sens.append(sensitivity)

              tracker.plot_acc.append(accuracy)

              """ Add to scheduler to do LR decay """
              scheduler.step()

         """ calculate new alpha for next epoch """
         if tracker.HD:
            tracker.alpha = alpha_step(ce_train, dc_train, hd_train, iter_cur_epoch)

         if cur_epoch % plot_every_num_epochs == 0:

              """ Plot sens + precision + jaccard + loss """
              plot_metric_fun(tracker.plot_acc, tracker.plot_acc, class_name='', metric_name='accuracy', plot_num=29)
              plt.figure(29); plt.savefig(s_path + 'Accuracy.png')

              plot_metric_fun(tracker.plot_sens, tracker.plot_sens_val, class_name='', metric_name='sensitivity', plot_num=30)
              plt.figure(30); plt.savefig(s_path + 'Sensitivity.png')

              plot_metric_fun(tracker.plot_prec, tracker.plot_prec_val, class_name='', metric_name='precision', plot_num=31)
              plt.figure(31); plt.savefig(s_path + 'Precision.png')

              plot_metric_fun(tracker.train_jacc_per_epoch, tracker.val_jacc_per_eval, class_name='', metric_name='jaccard', plot_num=32)
              plt.figure(32); plt.savefig(s_path + 'Jaccard.png')

              plot_metric_fun(tracker.train_loss_per_epoch, tracker.val_loss_per_eval, class_name='', metric_name='loss', plot_num=33)
              plt.figure(33); plt.yscale('log'); plt.savefig(s_path + 'loss_per_epoch.png')

              plot_metric_fun(tracker.lr_plot, [], class_name='', metric_name='learning rate', plot_num=35)
              plt.figure(35); plt.savefig(s_path + 'lr_per_epoch.png')

              """ Plot metrics per batch """
              plot_metric_fun(tracker.train_jacc_per_batch, [], class_name='', metric_name='jaccard', plot_num=34)
              plt.figure(34); plt.savefig(s_path + 'Jaccard_per_batch.png')

              plot_cost_fun(tracker.train_loss_per_batch, tracker.train_loss_per_batch)
              plt.figure(18); plt.savefig(s_path + 'global_loss.png')
              plt.figure(19); plt.savefig(s_path + 'detailed_loss.png')
              plt.figure(25); plt.savefig(s_path + 'global_loss_LOG.png')
              plt.close('all')

              plot_depth = 8
              output_train = output_train.cpu().data.numpy()
              output_train = np.moveaxis(output_train, 1, -1)
              seg_train = np.argmax(output_train[0], axis=-1)

              # convert back to CPU
              batch_x = batch_x.cpu().data.numpy()
              batch_y = batch_y.cpu().data.numpy()
              batch_x_val = batch_x_val.cpu().data.numpy()

              seg_val = np.argmax(output_val[0], axis=-1)

              plot_trainer_3D_PYTORCH_cell_track_AUTO(seg_train, seg_val, batch_x[0, 0:2, ...], batch_x_val[0, 0:2, ...], batch_y[0], batch_y_val[0],
                                       s_path, tracker.iterations, plot_depth=plot_depth)

         """ To save (every x iterations) """
         if cur_epoch % save_every_num_epochs == 0:

               save_name = s_path + 'check_' +  str(tracker.iterations)
               torch.save({
                'tracker': tracker,

                'model_type': unet,
                'optimizer_type': optimizer,
                'scheduler_type': scheduler,

                'model_state_dict': unet.state_dict(),
                'optimizer_state_dict': optimizer.state_dict(),
                'scheduler': scheduler.state_dict(),
                'loss_function': loss_function,

                }, save_name)


# Python 3.8.5

''' The Tech Academy p159 - exercise
    Nice or Mean Game
    basic Python program
    --> demonstrate how to pass variables from function to function
    --> return values will be returned back to the calling function
'''

def start(nice=0, mean=0, name=""): # that is controlling the default values
    # sets the default values for 3 variables - variable name is empty as its value will be given by user input
    # invite user to give a name which will really start the program
    name = describe_game(name)
    #now we need to call the function that will change the default values for nice and mean and store them
    nice, mean, name = nice_mean(nice,mean,name)

def describe_game(name): # this is the first function that the start function is calling
    """
        this will check if this is a new game or not (either the program has just opened, or this is another round.
        If it is new, we will need to obtain a name from the user.
        If it is not new, we thank the player for playing again and continue with the game
    """
    print(name)
    #to check whether this is a new game, we check whether we already have a name (FROM A PREVIOUS GAME)
    if name !="":
        print("\nThank you for playing again, {}".format(name))
    #if the name variable is empty, then we ask for a name and tell the player how the game is played
    else: # that is really what fires up the game
        stop = True # we are creating a variable that will act like a switch
        while stop is True: # as long as the name variable is empty, do all these things until stop is no longer true, meaning we have obtained a name
            if name == "": # and it is (because we are in the else statement)
                name = input ("\nWhat is your name? \n>>>").capitalize() # we are getting a name, and now the variable is no longer empty
            if name != "": #if the input from the user is not empty
                print("\nWelcome, {}".format(name))
                print("\nIn this game you will be greeted \n by several different people. \nYou can choose to be nice or mean")
                print("but at the end of the game your fate \nwill be sealed by your actions.")
                stop = False #that ends the while loop, the switch is now off
    return name

def nice_mean(nice, mean, name): # this is the second function that the start function is calling - that is the game function
    # in the start function nice and mean were set at 0 by default
    # now we need to create a swtich on/off which are the conditions under which the games goes on or off
    stop = True
    while stop:
        # show the current scores and the scores after the player's input
        show_score(nice, mean, name)# this is calling a show_score function that will be defined in our next block of code
        pick = input("\nA stranger approaches you for a conversation. Will you be nice or mean? (N/M) \n>>>:").lower()
        if pick == "n":
            print("\nThe stranger walks away smiling...")
            nice = nice + 1
            stop = False # we stop asking the "pick" question
        if pick == "m":
            print("\nThe stranger glares at you \nmenacingly and storms off...")
            mean = mean + 1
            stop = False

    score(nice, mean, name) # calling the next function that now has current values

def score(nice, mean,name): # this function is getting its values obtain when running the previous function (nice_mean)
    if nice > 2:
        win(nice,mean,name) # calling the win function not yet defined
    if mean > 2:
        lose(nice,mean,name) # calling the lose function not yet defined
    else: #calling the nice_mean function again and passing the 3 variables as the new starting points
        nice_mean(nice,mean,name)

def show_score(nice, mean, name): # we got the name from the beginning of the game, and now the nice-mean function gave us current scores
    print("\n{},your current total: \n({}, Nice) and ({}, Mean)".format(name, nice, mean))

def win(nice, mean, name): # just interacting with the user in a personal way (message to user using its name)
    print("\nNice job {}, you win! \nEveryone loves you and you've \nmade lots of friends along the way".format(name))
    again(nice, mean, name) # calling the next function which asks whether to play again

def lose(nice, mean, name):
    print("\nGame over: you were too mean, {}!".format(name))
    again(nice, mean, name)

def again(nice, mean, name): # asking user if they want to play again
    # once again we need to create a switch
    stop = True
    while stop:
        choice = input("\nDo you want to play again? (y/n):\n>>>").lower()
        if choice == "y":
            stop = False # this stops the request for input
            reset(nice,mean,name) # calling the reset game function not yet defined
        if choice == "n":
            print("\nOh, no, so sad, sorry to see you go")
            stop = False
            quit()
        else: # this is forcing the user to provide an answer to the question "play again?"
            print("\nEnter (Y) for 'YES', (N) for 'NO': \n>>> ")

def reset(nice, mean, name):
    nice = 0
    mean = 0
    start(nice, mean, name)

if __name__ == "__main__":
    start()


import sys

sys.path.append("..")

from loguru import logger
from concurrent.futures import ThreadPoolExecutor, as_completed
from network_information_source.config import settings, FindRedisTaskTopic
from network_information_source.nis_utils import task_tools
from network_information_source.scheduler import deploy
from task_find_outbound import tsa
import traceback
RedisTaskTopic = FindRedisTaskTopic

task_topic = f'{RedisTaskTopic.test_task.value}_{settings.REGION.name}' if settings.DEPLOY_VERIFY_DEBUG else f'{RedisTaskTopic.task.value}_{settings.REGION.name}'

options = {
    'topic': 'topic_c1_original_site_dis',
    'tag_topic': RedisTaskTopic.tag_task.value,
    'push_debug': settings.DEPLOY_FIND_PUSH_DEBUG,
    'up_status_debug': settings.DEPLOY_FIND_PUSH_DEBUG,
    'extract_method': 'extract_find_data',
}

if __name__ == '__main__':
    with ThreadPoolExecutor(max_workers=settings.DEPLOY_FIND_THREAD_COUNT) as t:
        try:
            tasks = task_tools.pull(topic=task_topic, count=settings.DEPLOY_FIND_SINGLE_THREAD_TASK_COUNT,
                                    is_json=True)
            logger.info(f'正常运行')
            all_task = []
            for task in tasks:
                # deploy(
                #     task_obj=tsa,
                #     task=task,
                #     crawl_type_method=[
                #         'website_find'
                #     ],
                #     **options
                # )
                all_task.append(t.submit(
                    deploy,
                    task_obj=tsa,
                    task=task,
                    crawl_type_method=[
                        'website_find'
                    ],
                    **options
                ))

            for future in as_completed(all_task):
                try:
                    print(future.result())
                except Exception as ex:
                    logger.error(f'{ex}')
        except Exception as ex:
            logger.error(f'{traceback.format_exc()}')


#!/usr/bin/env python3

import sys
import socket

class Server():
    def __init__(self):
        super().__init__()

    def startServer(self,host,port):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            sock.bind((host, port))
            print("Socket Binded!")
        except socket.error as e:
            print("Bind Error:",e)
            sys.exit()
        sock.listen()
        connection, addr = sock.accept()

        print("Connection established on {0}:{1}".format(host,port))

serve = Server()
serve.startServer('127.0.0.1',443)


# -*- coding: utf-8 -*-

"""
类/继承类
"""

from __future__ import print_function

class People:
    def __init__(self, n, a, s):
        self.name = n
        self.age = a
        self.__score = s
        self.print_people()
        # self.__print_people() # 私有函数的作用

    def print_people(self):
        str = u'%s的年龄：%d, 成绩为：%.2f' % (self.name, self.age, self.__score)
        print(str)

    __print_people = print_people

class Student(People):
    def __init__(self, n, a, w):
        People.__init__(self, n, a, w)
        self.name = 'Student ' + self.name

    def print_people(self):
        str = u'%s的年龄：%d' % (self.name, self.age)
        print(str)

def func(p):
    p.age = 11

if __name__ == '__main__':
    p = People('Tom', 10, 3.14159) # 实例化类People时，会初始化People，同时调用了print_people(self):方法
    func(p) # p传入的是引用类型。对类People的参数self.age重新赋值
    p.print_people() # 调用print_people（）方法，此时已经对age参数重新赋值了

    # 注意分析下面语句的打印结果，是否觉得有些“怪异”
    j = Student('Jerry', 12, 2.71828) # 因为继承了people类，此时会先初始化变量，self.name， self.age，self.__score，self.print_people() （会调用student类的print_people方法）

    # 成员函数
    j.print_people() # 此时已经对self.name重新赋值
    People.print_people(j) # 此时已经对self.name重新赋值


from datetime import datetime

import pytz
from pydantic import BaseModel, root_validator, validator

from db import MessageType

class MessageModel(BaseModel):
    chat: int
    utctime: int
    msg_type: str
    nick: str
    text: str = ""
    outgoing: bool

    @validator("msg_type", pre=True)
    def get_message_type(cls, v):
        return MessageType(v).name

    @validator("utctime", pre=True)
    def get_timestamp(cls, v: datetime):
        dt_utc = pytz.utc.normalize(pytz.utc.localize(v))
        return int(dt_utc.timestamp() * 1000)

    @validator("chat", pre=True)
    def get_chat_id(cls, v):
        return v.id

    class Config:
        orm_mode = True

class ChatModel(BaseModel):
    id: int
    jid: str
    name: str
    is_muc: bool

    @root_validator()
    def add_type(cls, values):
        values["type"] = "muc" if values["is_muc"] else "user"
        return values

    class Config:
        orm_mode = True


from django.conf import settings
from django.core import validators
from django.db import models

class Tag(models.Model):
    name = models.CharField(
        'Название',
        unique=True,
        max_length=settings.NAME_MAX_LENGTH,
        help_text='Введите, пожалуйста, название',
    )
    color = models.CharField(
        'Цвет',
        unique=True,
        max_length=settings.COLOR_MAX_LENGTH,
        help_text='Введите цвет в формате RGB (#rrggbb)',
        validators=[
            validators.RegexValidator(
                r'^#[a-fA-F0-9]{6}$',
                'Используйте RGB-формат для указания цвета (#AABBCC)',
            )
        ],
    )
    slug = models.SlugField(
        'Slug',
        unique=True,
        max_length=settings.SLUG_MAX_LENGTH,
        help_text='Введите slug',
    )

    class Meta:
        ordering = ('name',)
        verbose_name = 'Тег'
        verbose_name_plural = 'Теги'

    def __str__(self) -> str:
        return f'{self.name} ({self.slug}).'