import logging
import numpy as np
from typing import Dict
from alibi_detect.base import BaseDetector, ThresholdMixin, outlier_prediction_dict

logger = logging.getLogger(__name__)

EPSILON = 1e-8

class SpectralResidual(BaseDetector, ThresholdMixin):

    def __init__(self,
                 threshold: float = None,
                 window_amp: int = None,
                 window_local: int = None,
                 n_est_points: int = None,
                 n_grad_points: int = 5,
                 ) -> None:
        """
        Outlier detector for time-series data using the spectral residual algorithm.
        Based on "Time-Series Anomaly Detection Service at Microsoft" (Ren et al., 2019)
        https://arxiv.org/abs/1906.03821

        Parameters
        ----------
        threshold
            Threshold used to classify outliers. Relative saliency map distance from the moving average.
        window_amp
            Window for the average log amplitude.
        window_local
            Window for the local average of the saliency map.
        n_est_points
            Number of estimated points padded to the end of the sequence.
        n_grad_points
            Number of points used for the gradient estimation of the additional points padded
            to the end of the sequence.
        """
        super().__init__()

        if threshold is None:
            logger.warning('No threshold level set. Need to infer threshold using `infer_threshold`.')

        self.threshold = threshold
        self.window_amp = window_amp
        self.window_local = window_local
        self.conv_amp = np.ones((1, window_amp)).reshape(-1,) / window_amp
        self.conv_local = np.ones((1, window_local)).reshape(-1,) / window_local
        self.n_est_points = n_est_points
        self.n_grad_points = n_grad_points

        # set metadata
        self.meta['detector_type'] = 'online'
        self.meta['data_type'] = 'time-series'

    def infer_threshold(self,
                        X: np.ndarray,
                        t: np.ndarray = None,
                        threshold_perc: float = 95.
                        ) -> None:
        """
        Update threshold by a value inferred from the percentage of instances considered to be
        outliers in a sample of the dataset.

        Parameters
        ----------
        X
            Batch of instances.
        threshold_perc
            Percentage of X considered to be normal based on the outlier score.
        """
        if t is None:
            t = np.arange(X.shape[0])

        # compute outlier scores
        iscore = self.score(X, t)

        # update threshold
        self.threshold = np.percentile(iscore, threshold_perc)

    def saliency_map(self, X: np.ndarray) -> np.ndarray:
        """
        Compute saliency map.

        Parameters
        ----------
        X
            Time series of instances.

        Returns
        -------
        Array with saliency map values.
        """
        fft = np.fft.fft(X)
        amp = np.abs(fft)
        log_amp = np.log(amp)
        phase = np.angle(fft)
        ma_log_amp = np.convolve(log_amp, self.conv_amp, 'same')
        res_amp = log_amp - ma_log_amp
        sr = np.abs(np.fft.ifft(np.exp(res_amp + 1j * phase)))
        return sr

    def compute_grads(self, X: np.ndarray, t: np.ndarray) -> np.ndarray:
        """
        Slope of the straight line between different points of the time series
        multiplied by the average time step size.

        Parameters
        ----------
        X
            Time series of instances.
        t
            Time steps.

        Returns
        -------
        Array with slope values.
        """
        dX = X[-1] - X[-self.n_grad_points-1:-1]
        dt = t[-1] - t[-self.n_grad_points-1:-1]
        mean_grads = np.mean(dX / dt) * np.mean(dt)
        return mean_grads

    def add_est_points(self, X: np.ndarray, t: np.ndarray) -> np.ndarray:
        """
        Pad the time series with additional points since the method works better if the anomaly point
        is towards the center of the sliding window.

        Parameters
        ----------
        X
            Time series of instances.
        t
            Time steps.

        Returns
        -------
        Padded version of X.
        """
        grads = self.compute_grads(X, t)
        X_add = X[-self.n_grad_points] + grads
        X_pad = np.concatenate([X, np.tile(X_add, self.n_est_points)])
        return X_pad

    def score(self, X: np.ndarray, t: np.ndarray = None) -> np.ndarray:
        """
        Compute outlier scores.

        Parameters
        ----------
        X
            Time series of instances.
        t
            Time steps.

        Returns
        -------
        Array with outlier scores for each instance in the batch.
        """
        if t is None:
            t = np.arange(X.shape[0])

        if len(X.shape) == 2:
            n_samples, n_dim = X.shape
            X = X.reshape(-1,)
            if X.shape[0] != n_samples:
                raise ValueError('Only univariate time series allowed for SR method. Number of features '
                                 'of time series equals {}.'.format(n_dim))

        X_pad = self.add_est_points(X, t)  # add padding
        sr = self.saliency_map(X_pad)  # compute saliency map
        sr = sr[:-self.n_est_points]  # remove padding again
        ma_sr = np.convolve(sr, self.conv_local, 'same')
        iscore = (sr - ma_sr) / (ma_sr + EPSILON)
        return iscore

    def predict(self,
                X: np.ndarray,
                t: np.ndarray = None,
                return_instance_score: bool = True) \
            -> Dict[Dict[str, str], Dict[np.ndarray, np.ndarray]]:
        """
        Compute outlier scores and transform into outlier predictions.

        Parameters
        ----------
        X
            Time series of instances.
        t
            Time steps.
        return_instance_score
            Whether to return instance level outlier scores.

        Returns
        -------
        Dictionary containing 'meta' and 'data' dictionaries.
        'meta' has the model's metadata.
        'data' contains the outlier predictions and instance level outlier scores.
        """
        if t is None:
            t = np.arange(X.shape[0])

        # compute outlier scores
        iscore = self.score(X.reshape(-1, ), t)

        # values above threshold are outliers
        outlier_pred = (iscore > self.threshold).astype(int)

        # populate output dict
        od = outlier_prediction_dict()
        od['meta'] = self.meta
        od['data']['is_outlier'] = outlier_pred
        if return_instance_score:
            od['data']['instance_score'] = iscore
        return od


from pydantic import BaseModel
from typing import Optional
from datetime import  datetime
from src.util.dbcontroller import DBController as DB
from src.models.Item import ItemController as Item
from dateutil.relativedelta import relativedelta

class EntryBase(BaseModel):
    item_code:str
    quantity:float
    price:float
    supplier:str
    receive_date:datetime=None

class Entry(EntryBase):
    before_stock:float
    after_stock:float
    created_at:datetime=None
    updated_at:datetime=None

class EntryController():
    __tablename__="entries"

    def is_exist(item_code):
        db=DB()
        sql="SELECT id FROM entries WHERE item_code=%s"
        params=(item_code,)
        results=db.get_specific_sql(sql,None,params)
        Flag=True if len(results)>0 else False
        return Flag

    def receive_item_trans(self,entry):
        item_code=entry["item_code"]
        quantity=float(entry["quantity"])
        before_stock=Item.get_qty_by_itemcode(item_code)["qty"]
        after_stock=float(before_stock)+quantity
        current_date=datetime.today()
        entry["before_stock"]=before_stock
        entry["after_stock"]=after_stock
        entry["created_at"]=current_date
        result=self.create(entry)
        flag_intry= Item.increase_item(item_code,quantity)["Flag"]
        result["flag_entry"]=flag_intry
        return result

    def cancel_item_trans(self,id):
        item_result=Item.get_some_item(id)[0]
        flag_cancel=Item.decrease_item(item_result["item_code"],float(item_result["quantity"]))["Flag"]
        result=self.delete(id)
        result["flag_cancel"]=flag_cancel
        return result

    def create(self,entry):
        db=DB(self.__tablename__)
        result=db.create(entry)
        del db
        return result

    def update(self,entry,id):
        db=DB(self.__tablename__)
        result=db.update(entry,id)
        del db
        return result

    def delete(self,id):
        db=DB(self.__tablename__)
        result=db.delete(id)
        del db
        return result

    def get_data(self,fields=None,id=0):
        db=DB(self.__tablename__)
        result=db.get_data(fields,id)
        del db
        return result

    def search_data(self,keyword):
        db=DB()
        sql="SELECT \
                    A.id,\
                    A.item_code,\
                    B.item_name,\
                    A.quantity,\
                    A.price,\
                    A.quantity*A.price AS sub_total,\
                    A.after_stock \
            FROM entries A INNER JOIN items B \
            ON A.item_code=B.item_code \
            WHERE CONCAT( A.item_code,' ',B.item_name) LIKE %s\
            ORDER BY A.id DESC"
        keyword="%"+keyword+"%"
        params=(keyword,)
        fields=["id","item_code","item_name","quantity","price","sub_total","stock"]
        results=db.get_specific_sql(sql,fields,params)
        del db
        return results

class EntryReport():
    def get_report_entry_by_duration(self,item_code,start_length,segment):
        db=DB()
        finish_date=datetime.today()
        start_date=finish_date-relativedelta(days=start_length)
        difference_in_days = (finish_date - start_date).days
        day_length=round(difference_in_days/segment)
        durations=[]
        cdate=start_date
        for i in range(0,segment-1,1):
            if(i<segment-1):
                fdate=cdate + relativedelta(days=day_length)
                T=self.get_sumary_date_range(db,item_code,cdate,fdate)
                day_criteria={"sdate":cdate,"fdate":fdate,"sub_total":T}
                cdate=fdate+ relativedelta(days=1)
                durations.append(day_criteria)
            else:
                if(i==segment-1):
                    T=self.get_sumary_date_range(db,item_code,cdate,fdate)
                    fdate=finish_date
                    T=self.get_sumary_date_range(db,item_code,cdate,fdate)
                    day_criteria={"sdate":cdate,"fdate":fdate,"sub_total":T}
                    cdate=fdate+ relativedelta(days=1)
                    durations.append(day_criteria)
        del db
        return durations

    def get_sumary_date_range(self,db,item_code,sdate,fdate):

        sql="SELECT SUM(price*quantity) AS T\
        FROM entries \
        WHERE item_code=%s AND \
        receive_date BETWEEN %s AND %s"
        params=(item_code,sdate.strftime('%Y-%m-%d %H:%M:%S'),fdate.strftime('%Y-%m-%d %H:%M:%S'),)
        results=db.get_specific_sql(sql,None,params)
        if(len(results)>0):
            return results[0]["T"]
        return 0


import logging
import logging.config
import os
import re

import flask
import flask_smorest

# __version__ and SOURCE_URL are used by setup.py and docs/conf.py (they are
# parsed with a regular expression, so keep the syntax simple).
__version__ = '0.1.0.dev0'

SOURCE_URL = 'https://github.com/HumanBrainProject/hbp-spatial-backend'
"""URL that holds the source code of the backend.

This should be changed to point to the code of any modified version.
"""

class DefaultConfig:
    # Passed as the 'origins' parameter to flask_cors.CORS, see
    # https://flask-cors.readthedocs.io/en/latest/api.html#flask_cors.CORS
    CORS_ORIGINS = '*'
    # Set to True to enable the /echo endpoint (for debugging)
    ENABLE_ECHO = False
    # Timeout, in seconds, to wait for AimsApplyTransform to reply before
    # cancelling the request. This is useful if running behind a reverse proxy
    # that has its own timeout anyway
    REQUEST_TIMEOUT = None
    # Set up werkzeug.middleware.proxy_fix.ProxyFix with the provided keyword
    # arguments, see
    # https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/
    PROXY_FIX = None
    #
    # Other configuration keys without a default value:
    # DEFAULT_TRANSFORM_GRAPH: full path to the YAML file that contains the
    #     default transform graph (used by v1 API)
    API_VERSION = __version__
    OPENAPI_VERSION = '3.0.2'  # OpenAPI version to generate
    OPENAPI_URL_PREFIX = '/'
    OPENAPI_REDOC_PATH = 'redoc'
    OPENAPI_REDOC_VERSION = '2.0.0-rc.20'
    OPENAPI_SWAGGER_UI_PATH = 'swagger-ui'
    OPENAPI_SWAGGER_UI_VERSION = '3.24.2'
    DEFAULT_TRANSFORM_GRAPH = ''

# This function has a magic name which is recognized by flask as a factory for
# the main app.
def create_app(test_config=None):
    """Instantiate the hbp-spatial-backend Flask application."""
    # logging configuration inspired by
    # http://flask.pocoo.org/docs/1.0/logging/#basic-configuration
    if test_config is None or not test_config.get('TESTING'):
        logging.config.dictConfig({
            'version': 1,
            'disable_existing_loggers': False,  # preserve Gunicorn loggers
            'formatters': {'default': {
                'format': '[%(asctime)s] [%(process)d] %(levelname)s '
                'in %(module)s: %(message)s',
                'datefmt': '%Y-%m-%d %H:%M:%S %z',
            }},
            'handlers': {'wsgi': {
                'class': 'logging.StreamHandler',
                'stream': 'ext://flask.logging.wsgi_errors_stream',
                'formatter': 'default'
            }},
            'root': {
                'level': 'INFO',
                'handlers': ['wsgi']
            }
        })

    # If we are running under Gunicorn, set up the root logger to use the same
    # handler as the Gunicorn error stream.
    if logging.getLogger('gunicorn.error').handlers:
        root_logger = logging.getLogger()
        root_logger.handlers = logging.getLogger('gunicorn.error').handlers
        root_logger.setLevel(logging.getLogger('gunicorn.error').level)

    # Hide Kubernetes health probes from the logs
    access_logger = logging.getLogger('gunicorn.access')
    exclude_useragent_re = re.compile(r'kube-probe')
    access_logger.addFilter(
        lambda record: not (
            record.args['h'].startswith('10.')
            and record.args['m'] == 'GET'
            and record.args['U'] == '/health'
            and exclude_useragent_re.search(record.args['a'])
        )
    )

    app = flask.Flask(__name__,
                      instance_path=os.environ.get("INSTANCE_PATH"),
                      instance_relative_config=True)
    app.config.from_object(DefaultConfig)
    if test_config is None:
        # load the instance config, if it exists, when not testing
        # Looks for config.py in instance dir
        app.config.from_pyfile("config.py", silent=True)
        # Looks for configuration settings file
        # pointed by HBP_SPATIAL_BACKEND_SETTINGS
        app.config.from_envvar("HBP_SPATIAL_BACKEND_SETTINGS", silent=True)
    else:
        # load the test config if passed in
        app.config.from_mapping(test_config)

    # ensure that the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    # Default transform graph is graph.yaml in instance dir
    if not app.config['DEFAULT_TRANSFORM_GRAPH']:
        app.config['DEFAULT_TRANSFORM_GRAPH'] = os.path.join(app.instance_path,
                                                             'graph.yaml')

    # Logs config dictionary
    app.logger.info("Instance path : %s", app.instance_path)
    app_dict = dict(app.config)
    app_str = '\n'.join('{} = {}'.format(k, v) for k, v in app_dict.items())
    app.logger.info("Logging dict ---> {0}".format(app_str))

    @app.route("/")
    def root():
        return flask.redirect('/redoc')

    @app.route("/source")
    def source():
        return flask.redirect(SOURCE_URL)

    # Return success if the app is ready to serve requests. Used in OpenShift
    # health checks.
    @app.route("/health")
    def health():
        return '', 200

    if app.config.get('ENABLE_ECHO'):
        @app.route('/echo')
        def echo():
            app.logger.info('ECHO:\n'
                            'Headers\n'
                            '=======\n'
                            '%s', flask.request.headers)
            return ''

    if app.config.get('CORS_ORIGINS'):
        import flask_cors
        flask_cors.CORS(app, origins=app.config['CORS_ORIGINS'])

    if app.config['ENV'] == 'development':
        local_server = [
            {
                'url': '/',
            },
        ]
    else:
        local_server = []

    smorest_api = flask_smorest.Api(app, spec_kwargs={
        'servers': local_server + [
            {
                'url': 'https://hbp-spatial-backend.apps.hbp.eu/',
                'description': 'Production instance running the *master* '
                               'branch',
            },
            {
                'url': 'https://hbp-spatial-backend.apps-dev.hbp.eu/',
                'description': 'Development instance running the *dev* '
                               'branch',
            },
        ],
        'info': {
            'title': 'hbp-spatial-backend',
            'description': '''\
HTTP backend for transforming coordinates (and, in the future, data) between
the HBP core template spaces.

The cross-template transformations are diffeomorphisms, which are computed
based on the alignment of the folding pattern across the different brains
(DISCO method) ([Auzias 2011], [Glaunès 2004], [Lebenberg 2018]) and
maximization of the grey–white matter segmentation overlap (DARTEL) ([Ashburner
2007]).

[Ashburner 2007]: https://doi.org/10.1016/j.neuroimage.2007.07.007
[Auzias 2011]: https://doi.org/10.1109/TMI.2011.2108665
[Glaunès 2004]: https://doi.org/10.1109/CVPR.2004.1315234
[Lebenberg 2018]: https://doi.org/10.1007/s00429-018-1735-9

For more information, see the **source code repository:** <{SOURCE_URL}>.
'''.format(SOURCE_URL=SOURCE_URL),
            'license': {
                'name': 'Apache 2.0',
                'url': 'https://www.apache.org/licenses/LICENSE-2.0.html',
            },
        },
    })

    from . import api_v1
    smorest_api.register_blueprint(api_v1.bp)

    if app.config.get('PROXY_FIX'):
        from werkzeug.middleware.proxy_fix import ProxyFix
        app.wsgi_app = ProxyFix(app.wsgi_app, **app.config['PROXY_FIX'])

    return app


class Solution(object):
    def restoreIpAddresses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        ans = []
        n = len(s)

        def isValid(num):
            if len(num) == 1:
                return True
            if len(num) > 1 and num[0] != "0" and int(num) <= 255:
                return True
            return False

        for i in range(0, min(3, n - 3)):
            a = s[:i + 1]
            if not isValid(a):
                break
            for j in range(i + 1, min(i + 4, n - 2)):
                b = s[i + 1:j + 1]
                if not isValid(b):
                    break
                for k in range(j + 1, min(j + 4, n - 1)):
                    c = s[j + 1:k + 1]
                    d = s[k + 1:]
                    if not isValid(c):
                        break
                    if not isValid(d):
                        continue
                    ans.append("{}.{}.{}.{}".format(a, b, c, d))
        return ans

if __name__ == '__main__':
    in_file = open('IP.txt', 'r')
    out_file = open('2_ip_count.txt', 'w')
    for line in in_file.readlines():
        line=line.strip()
        solution = Solution()
        result = solution.restoreIpAddresses(line)
        print(result)
        out_file.write(str(len(result))+'\r\n')
    pass


import os

from redhawk.codegen import utils

from redhawk.codegen.jinja.loader import CodegenLoader
from redhawk.codegen.jinja.common import ShellTemplate, AutomakeTemplate, AutoconfTemplate
from redhawk.codegen.jinja.java import JavaCodeGenerator, JavaTemplate
from redhawk.codegen.jinja.java.properties import JavaPropertyMapper
from redhawk.codegen.jinja.java.ports import PortFactoryList, JavaPortMapper
from redhawk.codegen.jinja.java.ports.portfactory import JavaPortFactory
from redhawk.codegen.jinja.java.ports.frontend import FrontendProvidesPortFactory
from redhawk.codegen.jinja.java.component.base import BaseComponentGenerator

from mapping import PullComponentMapper

if not '__package__' in locals():
    # Python 2.4 compatibility
    __package__ = __name__.rsplit('.', 1)[0]

loader = CodegenLoader(__package__,
                       {'base': 'redhawk.codegen.jinja.java.component.base',
                        'common': 'redhawk.codegen.jinja.common'})

class ConsolidatedPortFactory(PortFactoryList):
    def __init__(self):
        factories = (FrontendProvidesPortFactory(), JavaPortFactory())
        super(ConsolidatedPortFactory,self).__init__(*factories)

class PullComponentGenerator(BaseComponentGenerator):
    # Need to keep use_jni, auto_start and queued_ports to handle legacy options
    def parseopts (self, java_package='',use_jni=True, auto_start=True,queued_ports=False):
        self.package = java_package

    def loader(self, component):
        return loader

    def componentMapper(self):
        return PullComponentMapper(self.package)

    def propertyMapper(self):
        return JavaPropertyMapper()

    def portMapper(self):
        return JavaPortMapper()

    def portFactory(self):
        return ConsolidatedPortFactory()

    def templates(self, component):
        # Put generated Java files in "src" subdirectory, followed by their
        # package path.
        pkgpath = os.path.join('src', *component['package'].split('.'))
        userfile = component['userclass']['file']
        basefile = component['baseclass']['file']
        templates = [
            JavaTemplate('resource.java', os.path.join(pkgpath, userfile), userfile=True),
            JavaTemplate('resource_base.java', os.path.join(pkgpath, basefile)),
            AutomakeTemplate('base/Makefile.am'),
            AutoconfTemplate('base/configure.ac'),
            ShellTemplate('base/startJava.sh'),
            ShellTemplate('common/reconf')
        ]

        portpkg = component['package'] + '.' + 'ports'
        portpkgpath = os.path.join(pkgpath, 'ports')
        for generator in component['portgenerators']:
            if not generator.hasImplementation():
                continue
            generator.package = portpkg
            template = generator.implementation()
            filename = os.path.join(portpkgpath, generator.className()+'.java')
            context = {'portgenerator': generator}
            templates.append(JavaTemplate(template, filename, package=portpkg, context=context))

        return templates


#!/usr/bin/env python3
"""
define Positive, Negative, Semidefine or indefine
"""

import numpy as np

def definiteness(matrix):
    """
    * matrix is a numpy.ndarray of shape (n, n) whose definiteness
      should be calculated
    * Return: the string Positive definite, Positive semi-definite,
        Negative semi-definite, Negative definite, or Indefinite if the
        matrix is positive definite, positive semi-definite, negative
        semi-definite, negative definite of indefinite respectively
    If matrix does not fit any of the above categories, return None
    """

    if not isinstance(matrix, np.ndarray):
        raise TypeError("matrix must be a numpy.ndarray")
    if len(matrix.shape) != 2 or (matrix.shape[0] != matrix.shape[1]):
        return None
    if not np.all(matrix.T == matrix):
        return None
    eigenvalues, eigenvector = np.linalg.eig(matrix)

    positive = np.where(eigenvalues > 0)
    ceros = np.where(eigenvalues == 0)
    negative = np.where(eigenvalues < 0)

    pos = eigenvalues[positive]
    cer = eigenvalues[ceros]
    neg = eigenvalues[negative]
    if pos.size and not cer.size and not neg.size:
        return ('Positive definite')
    elif pos.size and cer.size and not neg.size:
        return ('Positive semi-definite')
    elif not pos.size and not cer.size and neg.size:
        return ('Negative definite')
    elif not pos.size and cer.size and neg.size:
        return ('Negative semi-definite')
    elif pos.size and not cer.size and neg.size:
        return ('Indefinite')
    else:
        return None


# from lzl.helper import *
import os
import pandas as pd

data = pd.read_csv("raw/negative/questions.csv").loc[:,["question1", "question2","is_duplicate"]].values

lis = []

def valid(string):
    string = string.lower()
    blacklist = "relationship boyfriend girlfriend rebound marry sexual".split(" ")
    for word in blacklist:
        if word in string:
            return False
    return True

def clean(string):
    return string.lower()

error = 0
for a,b,dup in data:
    try:
        if dup == 0:
            if valid(a):
                lis.append(clean(a))
            if valid(b):
                lis.append(clean(b))
        else:
            if valid(a):
                lis.append(clean(a))
    except:
        error += 1

print(error)

error = 0

with open("data/negative.csv","w") as f:
    for row in lis:
        try:
            f.write(row+"\n")
        except:
            error += 1

print(len(lis), error)


import bpy
from mathutils import Vector
from mathutils.geometry import normal  # takes 3 or more! :)
from bpy.props import (BoolProperty, FloatVectorProperty, StringProperty, FloatProperty)

from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import (
    dataCorrect, node_id, updateNode, fullList, Vector_generate, Matrix_generate)

from sverchok.ui.bgl_callback_3dview import callback_disable, callback_enable
from sverchok.utils.context_managers import sv_preferences
from sverchok.utils.sv_idx_viewer28_draw import draw_indices_2D

# status colors
FAIL_COLOR = (0.1, 0.05, 0)
READY_COLOR = (1, 0.3, 0)

def calc_median(vlist):
    a = Vector((0, 0, 0))
    for v in vlist:
        a += v
    return a / len(vlist)

class SvIDXViewer28(bpy.types.Node, SverchCustomTreeNode):

    ''' IDX ViewerNode '''
    bl_idname = 'SvIDXViewer28'
    bl_label = 'Viewer Index+'
    bl_icon = 'INFO'
    sv_icon = 'SV_INDEX_VIEWER'

    def get_scale(self):
        try:
            with sv_preferences() as prefs:
                scale = prefs.index_viewer_scale
        except:
            scale = 1.0
        return scale

    def make_color_prop(name, col):
        return FloatVectorProperty(
            name=name, description='', size=4, min=0.0, max=1.0,
            default=col, subtype='COLOR', update=updateNode)

    n_id: StringProperty(default='', options={'SKIP_SAVE'})

    activate: BoolProperty(
        name='Show', description='Activate node?',
        default=True,
        update=updateNode)

    # draw_bg: BoolProperty(
    #     name='draw_bg', description='draw background poly?',
    #     default=False, update=updateNode)

    draw_bface: BoolProperty(
        name='draw_bface', description='draw backfacing indices?',
        default=True, update=updateNode)

    display_vert_index: BoolProperty(
        name="Vertices", description="Display vertex indices",
        default=True, update=updateNode)
    display_edge_index: BoolProperty(
        name="Edges", description="Display edge indices", update=updateNode)
    display_face_index: BoolProperty(
        name="Faces", description="Display face indices", update=updateNode)

    # bg_edges_col: make_color_prop("bg_edges", (.2, .2, .2, 1.0))
    # bg_faces_col: make_color_prop("bg_faces", (.2, .2, .2, 1.0))
    # bg_verts_col: make_color_prop("bg_verts", (.2, .2, .2, 1.0))
    numid_edges_col: make_color_prop("numid_edges", (1.0, 1.0, 0.1, 1.0))
    numid_faces_col: make_color_prop("numid_faces", (1.0, .8, .8, 1.0))
    numid_verts_col: make_color_prop("numid_verts", (0.6, 1, 0.3, 1.0))

    def sv_init(self, context):
        inew = self.inputs.new
        inew('SvVerticesSocket', 'verts')
        inew('SvStringsSocket', 'edges')
        inew('SvStringsSocket', 'faces')
        inew('SvMatrixSocket', 'matrix')
        inew('SvStringsSocket', 'text')

    def draw_buttons(self, context, layout):
        view_icon = 'RESTRICT_VIEW_' + ('OFF' if self.activate else 'ON')

        column_all = layout.column()

        row = column_all.row(align=True)
        split = row.split()
        r = split.column()
        r.prop(self, "activate", text="Show", toggle=True, icon=view_icon)
        # row.prop(self, "draw_bg", text="BG", toggle=True)
        row.prop(self, "draw_bface", text="", icon='GHOST_ENABLED', toggle=True)

        col = column_all.column(align=True)
        for item, item_icon in zip(['vert', 'edge', 'face'], ['VERTEXSEL', 'EDGESEL', 'FACESEL']):
            row = col.row(align=True)
            row.prop(self, f"display_{item}_index", toggle=True, icon=item_icon, text='')
            row.prop(self, f"numid_{item}s_col", text="")
            # if self.draw_bg:
            #     row.prop(self, f"bg_{item}s_col", text="")

    def get_settings_dict(self):
        '''Produce a dict of settings for the callback'''
        # A copy is needed, we can't have reference to the
        # node in a callback, it will crash blender on undo
        return {
            # 'bg_edges_col': self.bg_edges_col[:],
            # 'bg_faces_col': self.bg_faces_col[:],
            # 'bg_verts_col': self.bg_verts_col[:],
            'numid_edges_col': self.numid_edges_col[:],
            'numid_faces_col': self.numid_faces_col[:],
            'numid_verts_col': self.numid_verts_col[:],
            'display_vert_index': self.display_vert_index,
            'display_edge_index': self.display_edge_index,
            'display_face_index': self.display_face_index,
            'draw_bface': self.draw_bface,
            # 'draw_bg': self.draw_bg,
            'scale': self.get_scale()
        }.copy()

    def draw_buttons_ext(self, context, layout):
        row = layout.row(align=True)
        box = layout.box()
        little_width = 0.735

        col = box.column(align=True)
        row = col.row(align=True)
        row.label(text='Colors')

        for _icon in ['VERTEXSEL', 'EDGESEL', 'FACESEL']:
            colz = row.column(align=True)
            colz.scale_x = little_width
            colz.label(icon=_icon, text=' ')

        colprops = [
            ['Numbers :', ['numid_verts_col', 'numid_edges_col', 'numid_faces_col']],
            # ['Background :', ['bg_verts_col', 'bg_edges_col', 'bg_faces_col']]
        ]

        for label, geometry_types in colprops:
            row = col.row(align=True)
            row.label(text=label)
            for colprop in geometry_types:
                colx = row.column(align=True)
                colx.scale_x = little_width
                colx.prop(self, colprop, text="")

    def update(self):
        # used because this node should disable itself if no inputs.
        n_id = node_id(self)
        callback_disable(n_id)

    def get_face_extras(self, geom):
        face_medians = []
        face_normals = []
        for obj_index, faces in enumerate(geom.faces):

            verts = geom.verts[obj_index]

            medians = []
            normals = []
            concat_median = medians.append
            concat_normal = normals.append

            for face in faces:
                poly_verts = [verts[idx] for idx in face]
                concat_normal(normal(poly_verts))
                concat_median(calc_median(poly_verts))

            face_medians.append(medians)
            face_normals.append(normals)

        return face_medians, face_normals

    def get_geometry(self):
        inputs = self.inputs
        geom = lambda: None

        for socket in ['matrix', 'verts', 'edges', 'faces', 'text']:
            input_stream = inputs[socket].sv_get(default=[])
            if socket == 'verts' and input_stream:

                # ensure they are Vector()
                input_stream = Vector_generate(input_stream)

                # ensure they are Matrix() multiplied
                for obj_index, verts in enumerate(input_stream):
                    if obj_index < len(geom.matrix):
                        matrix = geom.matrix[obj_index]
                        input_stream[obj_index] = [matrix @ v for v in verts]

            setattr(geom, socket, input_stream)

        if not self.draw_bface:
            geom.face_medians, geom.face_normals = self.get_face_extras(geom)
            return geom

        else:
            # pass only data onto the draw callback that you intend to show.
            display_topology = lambda: None
            display_topology.vert_data = []
            display_topology.edge_data = []
            display_topology.face_data = []
            display_topology.text_data = []

            concat_vert = display_topology.vert_data.append
            concat_edge = display_topology.edge_data.append
            concat_face = display_topology.face_data.append
            concat_text = display_topology.text_data.append

            for obj_index, final_verts in enumerate(geom.verts):

                # can't display vert idx and text simultaneously - ...
                if self.display_vert_index:
                    for idx, vpos in enumerate(final_verts):
                        concat_vert((idx, vpos))
                    if geom.text:

                        text_items = self.get_text_of_correct_length(obj_index, geom, len(final_verts))
                        for text_item, vpos in zip(text_items, final_verts):
                            concat_text(text_item)

                if self.display_edge_index and obj_index < len(geom.edges):
                    for edge_index, (idx1, idx2) in enumerate(geom.edges[obj_index]):
                        loc = final_verts[idx1].lerp(final_verts[idx2], 0.5)
                        concat_edge((edge_index, loc))

                if self.display_face_index and obj_index < len(geom.faces):
                    for face_index, f in enumerate(geom.faces[obj_index]):
                        poly_verts = [final_verts[idx] for idx in f]
                        median = calc_median(poly_verts)
                        concat_face((face_index, median))

            return display_topology

    def get_text_of_correct_length(self, obj_index, geom, num_elements_to_fill):
        """ get text elements, and extend if needed"""
        if obj_index < len(geom.text):
            text_items = geom.text[obj_index]
        else:
            text_items = geom.text[len(geom.text)-1]

        if not (len(text_items) == num_elements_to_fill):

            # ---- this doesn't touch the data, but returns a copy, or a modified copy -----
            if len(text_items) < num_elements_to_fill:
                return text_items + [text_items[-1], ] * (num_elements_to_fill - len(text_items))
            else:
                return text_items[:num_elements_to_fill]

        return text_items

    def process(self):
        n_id = node_id(self)
        callback_disable(n_id)

        if not self.id_data.sv_show:
            return

        self.use_custom_color = True
        if not (self.activate and self.inputs['verts'].is_linked):
            return

        self.generate_callback(n_id)

    def generate_callback(self, n_id):

        verts = self.inputs['verts'].sv_get()
        if not verts:
            return

        config = self.get_settings_dict()
        geom = self.get_geometry()

        draw_data = {
            'tree_name': self.id_data.name[:],
            'custom_function': draw_indices_2D,
            'args': (geom, config)}

        callback_enable(n_id, draw_data, overlay='POST_PIXEL')

    def free(self):
        callback_disable(node_id(self))

    def sv_copy(self, node):
        ''' reset n_id on copy '''
        self.n_id = ''

def register():
    bpy.utils.register_class(SvIDXViewer28)

def unregister():
    bpy.utils.unregister_class(SvIDXViewer28)


import pandas as pd
import numpy as np
import logging

def get_month(data: pd.DataFrame) -> None:
    data.loc[:, 'month'] = data.timestamp.dt.month

def get_day(data: pd.DataFrame) -> None:
    data.loc[:, 'day'] = data.timestamp.dt.day

def get_dayofyear(data: pd.DataFrame) -> None:
    data.loc[:, 'dayofyear'] = data.timestamp.dt.dayofyear

def get_dayofweek(data: pd.DataFrame) -> None:
    data.loc[:, 'dayofweek'] = data.timestamp.dt.dayofweek

def get_hour(data: pd.DataFrame) -> None:
    data.loc[:, 'hour'] = data.timestamp.dt.hour

def get_detailed_datetime(data: pd.DataFrame) -> None:
    get_month(data)
    get_dayofyear(data)
    get_day(data)
    get_dayofweek(data)
    get_hour(data)

def get_building_age(data: pd.DataFrame) -> None:
    data.loc[:, 'building_age'] = data.timestamp.dt.year - data.year_built

def get_site_primary_use(data: pd.DataFrame) -> None:
    data.loc[:, 'site_primary_use'] = data.site_id.map(str) + '_' + data.primary_use

def get_hour_primary_use(data: pd.DataFrame) -> None:
    data.loc[:, 'hour_primary_use'] = data.hour.map(str) + '_' + data.primary_use

def get_month_primary_use(data: pd.DataFrame) -> None:
    data.loc[:, 'month_primary_use'] = data.month.map(str) + '_' + data.primary_use

def transform_wind_direction(data: pd.DataFrame) -> None:
    data.loc[:, 'wind_direction_sin'] = pd.Series(np.sin(np.pi * data.wind_direction.values / 360))

def add_wind_chill(data: pd.DataFrame) -> None:
    def compute_wind_chill(row: pd.Series) -> float:
        v = row['wind_speed'] * 3.6
        T_a = row['air_temperature']
        if T_a <= 10 and v >= 4.8:
            return 13.12 + 0.6215 * T_a - 11.37 * v ** 0.16 + 0.3965 * T_a * v ** 0.16
        return float('nan')
    data.loc[:, 'wind_chill'] = data.apply(compute_wind_chill, axis=1)

def add_relative_humidity(data: pd.DataFrame) -> None:
    def compute_relative_humidity(row: pd.Series) -> float:
        # Magnus formula
        T_a = row['air_temperature']
        T_dp = row['dew_temperature']
        b = 18.678
        c = 257.14 # Celsius
        return 100 * np.exp(T_dp * b / (T_dp + c) - b * T_a / (c + T_a))
    data.loc[:, 'relative_humidity'] = data.apply(compute_relative_humidity, axis=1)

def add_heat_index(data: pd.DataFrame) -> None:
    def compute_heat_index(row: pd.Series) -> float:
        T = row['air_temperature']
        R = row['relative_humidity']
        if R >= 40.0 and T >= 27.0:
            c = [0] * 9
            c[0] = -8.78469475556
            c[1] = 1.61139411
            c[2] = 2.33854883889
            c[3] = -0.14611605
            c[4] = -0.012308094
            c[5] = -0.0164248277778
            c[6] = 0.002211732
            c[7] = 0.00072546
            c[8] = -0.000003582

            vals = [1] * 9
            vals[1] = T
            vals[2] = R
            vals[3] = T * R
            vals[4] = T **2
            vals[5] = R **2
            vals[6] = T **2 * R
            vals[7] = T * R **2
            vals[8] = (T * R) **2

            return sum(a * b for a, b in zip(c, vals))
        return float('nan')
    data.loc[:, 'heat_index'] = data.apply(compute_heat_index, axis=1)

def add_feels_like(data: pd.DataFrame, remove_others: bool = False) -> None:
    add_relative_humidity(data)
    add_heat_index(data)
    add_wind_chill(data)
    data.loc[:, 'feels_like'] = data['heat_index'].combine_first(data['wind_chill']).combine_first(data['air_temperature'])
    if remove_others:
        data.drop(['heat_index', 'wind_chill'], axis=1)

def fill_na_in_weather_data(weather_data: pd.DataFrame) -> None:
    weather_data = weather_data.fillna(method='backfill').fillna(method='ffill')

def add_yesterday_lag_features(weather_data: pd.DataFrame, window_size: int = 24) -> None:
    group_df = weather_data.groupby('site_id')
    cols_mean = [
        'air_temperature',
        'dew_temperature',
        'precip_depth_1_hr',
        'sea_level_pressure',
        'wind_speed',
        'relative_humidity',
        'feels_like'
        ]
    cols_median = ['cloud_coverage']
    rolled_mean = group_df[cols_mean].rolling(window=window_size, min_periods=0, win_type='triang')
    rolled_median = group_df[cols_median].rolling(window=window_size, min_periods=0, win_type=None)
    lag_mean = rolled_mean.mean().reset_index().astype(np.float16)
    lag_median = rolled_median.median().reset_index().astype(np.float16)

    for col in cols_mean:
        weather_data[f'{col}_mean_lag{window_size}'] = lag_mean[col]
    for col in cols_median:
        weather_data[f'{col}_median_lag{window_size}'] = lag_median[col]

def prepare_features(data: pd.DataFrame, weather_data: pd.DataFrame) -> pd.DataFrame:
    get_detailed_datetime(data)
    get_building_age(data)
    get_site_primary_use(data)
    get_month_primary_use(data)
    get_hour_primary_use(data)
    ##fill_na_in_weather_data(weather_data)
    add_feels_like(weather_data)
    add_yesterday_lag_features(weather_data)
    transform_wind_direction(weather_data)
    return data.merge(weather_data, on=['site_id', 'timestamp'], how='left')


#!/usr/bin/env python
""" Some widget extensionts used in the form builder.
    Collected here for better readability.

    Author:     tomio
    License;    MIT
    Date:       2023-02-26
    Warranty:   None
"""
import os
import time
import tkinter as tk
from tkinter import ttk
# from tkinter.filedialog import FileDialog
from tkinter.filedialog import askopenfilenames
from tkinter import StringVar

class FilePickerTextField():
    """ a small class to build a file picker in the form of
        a text field and a button. The button activates a
        file selector widget, and its results fills the text
        field. The text field is editable.
        Use possibly a relative path.

        Using a text field allows one to enter non-existent
        file names if necessary, but the file picker allows
        easy selection of existing ones with relative paths.
        The widget allows to select more than one files.
    """

    def __init__(self,
                 parent:tk.Misc= None,
                 indir:str='.',
                 extension:str= 'yaml') -> None:
        """ Generate the widget and populate its settings
        """
        if parent is None:
            self.parent = tk.Tk()
        else:
            # this can be a frame or similar, we embed into
            self.parent = parent

        frame= ttk.Frame(self.parent)
        # allow positioning after called:
        self.grid = frame.grid

        self.dir = indir
        self.content = StringVar()
        self.required= False
        self.error= False

        entry = ttk.Entry(
                frame,
                width= 30,
                textvariable= self.content
                )

        entry.grid(
                column= 0,
                row= 0
                )

        button = ttk.Button(
                frame,
                text='Select',
                command= lambda: self.get_file(
                    frame,
                    extension
                    )
                )
        button.grid(column= 1, row= 0)
    # end __init__

    def get_file(self,
                 parent:tk.Misc,
                 extension:str) -> None:
        """ bring up a file dialog and get a file name

            parameters:
            parent:     the parent widget, e.g. frame
            extension:  the file extension to be displayed
        """

        d = askopenfilenames(
                master= parent,
                title='Select file',
                defaultextension= extension,
                initialdir= self.dir
                )
        if d:
            fn = [os.path.relpath(i, self.dir) for i in d]
            # to be able to use the text field, we
            # need a comma separated list of file names
            self.content.set( ', '.join(list(fn)))
    # end get_file

    def get(self) -> str|list:
        """ get the file paht(s) out of the widget, and return
            as a string or list.
            Assumes paths are relative (the get_file above
            does convert the path to relative paths).
            It does not test if a file exists, so users can name
            files they would add later.

            Using the list allows a type check to see if
            multiple files are selected.
        """

        fn = self.content.get()
        if not fn:
            return None

        if ',' in fn:
            fn = fn.split(', ')
            # to allow only existing files we can filter:
            #fn = [f'file:{i}' for i in fn \
            #        if os.path.isfile(os.path.join(self.dir, i))]
            #
            # or the user may specify files which do not exist
            # but do not emit empty elements
            # fn = [f'file:{i.strip()}' for i in fn if i.strip()]
            fn = [i.strip() for i in fn if i.strip()]

            if not fn:
                return None

            return fn

        # return f'file:{fn}'
        return fn
    # end get

    def set(self, data:list)->None:
        """ set the content from a list of file names
        """

        if not data:
            return

        text = ', '.join(data)
        self.content.set(text)
    # end of set
# end FilePickerTextField

class MultilineText():
    """ a multiline text widget with scroll bars on it...
    """

    def __init__(self,
                 parent:tk.Misc= None
                 )-> None:
        """ A Tk text area widget coupled to scroll bars in a frame
        """

        if parent is None:
            self.parent = tk.Tk()
        else:
            # this can be a frame or similar, we embed into
            self.parent = parent

        frame= ttk.Frame(self.parent)

        frame.rowconfigure(0, weight=1)
        frame.columnconfigure(0, weight=1)

        self.text = tk.Text(frame,
                            width= 50,
                            height= 10,
                            wrap= 'word')

        self.text.grid(column=0, row=0, sticky='we')
        self.required= False
        self.error = False

        scroll_vertical= tk.Scrollbar(frame,
                                      bg= 'grey',
                                      orient= 'vertical',
                                      command= self.text.yview,
                                      takefocus= True
                                      )
        scroll_vertical.grid(row= 0,
                                   column= 1,
                                   sticky= 'ns')
        self.text.config(yscrollcommand= scroll_vertical.set)

        scroll_horizontal= tk.Scrollbar(frame,
                                        bg= 'grey',
                                        orient= 'horizontal',
                                        command= self.text.xview,
                                        takefocus= True
                                        )
        scroll_horizontal.grid(row= 1,
                                   column= 0,
                                   sticky= 'ew')
        self.text.config(xscrollcommand= scroll_horizontal.set)

        # to allow positioning
        self.grid = frame.grid
    # end __init__

    def get(self)->str:
        """ return the full content of the widget
        """
        v= self.text.get('1.0','end')
        if not v:
            return None

        return v.strip()
    # end of get

    def set(self, content)->None:
        """ set the content of the widget
        """
        if text:
            self.text.insert('END', content)
    # end set

# end of MultilineText

class CheckBox(tk.Checkbutton):
    """ an envelop to ktinter checkbox with a get() to
        read out the value.
    """

    def __init__(self, parent:tk.Misc= None, **kwargs:dict) -> None:
        """ initialize a checkbox widget
        """

        self.parent = parent
        self.error = False
        self.required= False

        if self.parent is None:
            self.parent = tk.Tk()

        self.value = tk.IntVar()
        super().__init__(self.parent,
                         variable= self.value,
                         onvalue= 1,
                         offvalue= 0,
                         **kwargs)

    def get(self)->str:
        """ return back the value of self.value
        """
        return self.value.get() == 1
# end of CheckBox

class EntryBox():
    """ an entry box which can also check its content
        to be: text, file, url, integer, numeric
    """

    def __init__(self,
                 parent:tk.Misc,
                 vartype:str='text',
                 **kwarg:dict) -> None:
        """ Initiate an entry widget, based on its type
        """
        # internally we use strings for any variable
        self.var = tk.StringVar()

        self.type = vartype
        self.error = False
        self.error = False

        self.parent = parent
        self.required= False

        if self.parent is None:
            self.parent = tk.Tk()

        self.entry = ttk.Entry(self.parent,
                               textvariable= self.var,
                               **kwarg)
    # end __init__

    def set(self, value:str|int|float|list) -> None:
        """ Set the internal variable from value
            Use a text tk variable, so convert the incoming
            types to it.
        """
        # since tk does not handle invalid numbers well,
        # we have to take it out of its hands...
        # that would mean that every field is a text field,
        # but if the conversion fails, we make a message and
        # return None. The main FormBuilder then refuses to close

        if self.type == 'list':
            self.var.set(', '.join(value))
        elif self.type == 'numericlist':
            self.var.set(', '.join([str(i) for i in value]))

        else:
            self.var.set(str(value))
    # end of set

    def get(self) -> str|int|float|list:
        """ return the value as a proper python variable
            Handle types:
            string      --> do nothing
            integer     --> convert to integer
            numeric     --> convert to float
            list        --> split by comma and strip
            numericlist --> split, conver to float, use N/A
            url         --> check and add missing https://

            Return
                the value obtained or None if there was no entry
                Upon conversion error, return None
                and set self.error to True
        """
        # reset the error, so it is a clear indication of
        # conversion problems
        self.error= False

        s = self.var.get()
        # no entry:
        if not s:
            return  None

        # the numeric cases:
        res = None
        try:
            if self.type == 'integer':
                res= int(self.var.get())

            elif self.type == 'numeric':
                res= float(self.var.get())

            elif self.type == 'numericlist':
                l = [i.strip() for i in s.split(',')]
                res= [float(i) for i in l]

        except ValueError:
            self.error= 1
            return None

        if res:
            return res

        # the various text cases
        if self.type == 'url':
            if not s.startswith('http://') \
            and not s.startswith('https://'):
                return f'https://{s}'

        if self.type == 'list':
            return [i.strip() for i in s.split(',')]

        # any other text types...
        return s

    # end get()

    def grid(self, **kwargs:dict) -> None:
        """ propagate the grid to the internal
            widget
        """
        self.entry.grid(**kwargs)
# end class EntryBox

class MultiSelect():
    """ a listbox based multiple select box
    """

    def __init__(self,
                 parent:tk.Misc,
                 options:list) -> None:
        """ Create a a widget and list up the options
            in it.
        """
        self.options = options
        self.parent = parent
        self.required= False
        self.error = False

        if self.parent is None:
            self.parent = tk.Tk()
        # end empty window
        self.select = tk.Listbox(self.parent,
                                 # selectmode='multiple')
                                 selectmode='extended')

        for i,j in enumerate(options):
            self.select.insert(i,j)
    # end __init__

    def grid(self, **kwargs):
        """ specify the grid() method for the whole calss
        """
        self.select.grid(**kwargs)
    # end grid

    def get(self) -> list:
        """ return a list of selected values
        """
        l = [self.select.get(i) for i in self.select.curselection()]

        # here is a possibility to convert to numbers
        # for later...
        if not l:
            return None

        return l
    # end get

    def set(self, selected:list)->None:
        """ Set all items in the list selected, based on
            a value returned by get before...
        """
        for i in selected:
            # this will throw a value error if the value is
            # not in the option list
            self.select.select_set(self.options.index(i))
    # end set
# end class MultiSelect

class Select():
    """ a simple class to select an item from a list.
        Basically for the sake of completedness,
        a combo box.
    """

    def __init__(self,
                 parent:tk.Misc,
                 options:list) -> None:
        """ Create a combo box with the list of options
            in it.
            Required is kind of unimportant here, since the
            selector always stands on a value... so, it is
            always set to something.
        """
        self.options = options
        self.parent = parent
        self.required= False
        self.error = False

        if self.parent is None:
            self.parent = tk.Tk()
        # end empty window
        self.select = ttk.Combobox(self.parent)
        self.select['values'] = options
        self.select['state'] = 'readonly'
        self.set(options[0])
    # end __init__

    def set(self, value):
        self.select.set(value)
    # end of set

    def get(self):
        return self.select.get()
    # end of get

    def grid(self, **kwargs):
        self.select.grid(**kwargs)

#end of class Select

class DateRoller():
    """ a simple widget to set up a date using spin boxes

        It takes year, month, day, hour and minute as integer
        numbers. It would not stop anyone typing in wrong values,
        but will invalidate the result (get returns None) and
        sets the error variable, so required check will work.

        It can be initiated with a value in:
        YYY-mm-dd HH:MM form or the set() method can do the same
        any time.
    """

    def __init__(self, parent:tk.Misc= None, value:str='') -> None:
        """ set up the widget and its initial values
        """
        self.parent = parent
        self.value = None
        # get the time tuple
        # (year, month, day, hour,
        # min, sec, wday, yday, isdst)
        now = time.localtime()
        if value != '':
            now = time.strptime(value, '%Y-%m-%d %H:%M')

        if self.parent is None:
            window= tk.Tk()
            window.geometry('200x50')
            window.grid()
            window.title('Date picker')
            frame = tk.Frame(window)
            frame.grid(column=0, row=0, sticky='news')
            self.window = window
        else:
            #window = tk.Toplevel(self.parent)
            frame = tk.Frame(self.parent)
            # make grid availeble for external adjustments
            self.grid = frame.grid

        self.fieldlist=[]
        self.varlist=[]
        mins = [now[0]-5, 1, 1, 0, 0]
        maxs = [now[0]+5, 12, 31, 23, 59]
        for i,v in enumerate(['year','month','day', 'hour', 'minute']):
            label = tk.Label(frame,
                             text= v)
            label.grid(column=i, row=0)

            newvar= tk.StringVar()
            newvar.set(str(now[i]))
            spinner = tk.Spinbox(frame,
                                 from_ = mins[i],
                                 to = maxs[i],
                                 # values= list(range(mins[i],maxs[i]+1)),
                                 textvariable= newvar,
                                 wrap= True,
                                 width= 4 if i == 0 else 2,
                                 # command= lambda event: self.changed(event, i))
                                 )
            # we can directly trace the variables:
            newvar.trace_add('write', lambda var, event, mode: self.changed(var, event, mode, i))

            spinner.grid(column= i, row=1)

            self.fieldlist.append(spinner)
            self.varlist.append(newvar)
        # done adding fields
        # to set the first value
        self.value_set()
    # end of __init__

    def set(self, value):
        """ set the values from value
            The value should be in the form YYY-mm-dd HH:MM
        """
        now = list(time.strptime(value, '%Y-%m-%d %H:%M'))[:5]

        for i,v in enumerate(now):
            self.varlist[i].set(str(v))

        # update the internal variable
        self.value_set()
    # end set

    def changed(self, var, event, mode,  index):
        """ spinner changed. If it is month, adjust the day limit
            This function is a trace method assigned to the variables.
        """
        month_max_list = [31, 28, 31, 30, 31, 30,
                          31, 31, 30, 31, 30, 31]
        try:
            self.error= False
            year = int(self.varlist[0].get())
            month = int(self.varlist[1].get())
            day = int(self.varlist[2].get())

        except ValueError:
            print('invalid value entered!')
            self.error= True
            self.value= None
            return

        if year%4 == 0 and year%100 != 0:
            month_max_list[1] = 29

        # limit the month days up to what the month allows
        self.fieldlist[2].configure(to = month_max_list[month-1])
        if day > month_max_list[month-1]:
            day = month_max_list[month-1]
        self.varlist[2].set(str(day))

        # record the curernt value
        self.value_set()
    # end changed

    def value_set(self):
        """ combine the spin boxes to a value
        """
        try:
            self.error= False
            date = (int(i.get()) for i in self.varlist)

        except ValueError:
            print('Invalid value in date!')
            self.error= True
            self.value = None
            return

        date = tuple(date) + (0,0,0,0)

        self.value = time.strftime('%Y-%m-%d %H:%M', date)
    # end of value_set

    def get(self):
        """ return the actual value
        """
        return self.value
    # end of get

# end class datePicker


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jun  9 02:39:45 2021

@author: woojae-macbook13
"""

from gurobipy import*

try :

    m = Model('ex9_1_3')

    Z = LinExpr()

    NODE = 7

    OA = m.addVar(vtype = GRB.BINARY, name = 'OA')
    OB = m.addVar(vtype = GRB.BINARY, name = 'OB')
    OC = m.addVar(vtype = GRB.BINARY, name = 'OC')

    AB = m.addVar(vtype = GRB.BINARY, name = 'AB')
    AD = m.addVar(vtype = GRB.BINARY, name = 'AD')

    BC = m.addVar(vtype = GRB.BINARY, name = 'BC')
    BD = m.addVar(vtype = GRB.BINARY, name = 'BD')
    BE = m.addVar(vtype = GRB.BINARY, name = 'BE')

    CB = m.addVar(vtype = GRB.BINARY, name = 'CB')
    CE = m.addVar(vtype = GRB.BINARY, name = 'CE')

    DE = m.addVar(vtype = GRB.BINARY, name = 'DE')
    DT = m.addVar(vtype = GRB.BINARY, name = 'DT')

    ED = m.addVar(vtype = GRB.BINARY, name = 'ED')
    ET = m.addVar(vtype = GRB.BINARY, name = 'ET')

    X = [[0, OA, OB, OC, 0, 0, 0],
         [0, 0, AB, 0, AD, 0, 0],
         [0, 0, 0, BC, BD, BE, 0],
         [0, 0, CB, 0, 0, CE, 0],
         [0, 0, 0, 0, 0, DE, DT],
         [0, 0, 0, 0, ED, 0, ET],
         [0, 0, 0, 0, 0, 0, 0]]

    DIST = [[0, 2, 5, 4, 0, 0, 0],
            [0, 0, 2, 0, 7, 0, 0],
            [0, 0, 0, 1, 4, 3, 0],
            [0, 0, 1, 0, 0, 4, 0],
            [0, 0, 0, 0, 0, 1, 5],
            [0, 0, 0, 0, 1, 0, 7],
            [0, 0, 0, 0, 0, 0, 0]]

    # 목적 함수
    Z = 0
    for i in range(NODE) :
        for j in range(NODE) :
            Z += X[i][j]*DIST[i][j]

    # 제약 조건
    for i in range(NODE) :
        tempC = 0
        # From i 더하기
        for j in range(NODE) :
            if DIST[i][j] != 0 :
                tempC += X[i][j]
        # To i 빼기
        for k in range(NODE) :
            if DIST[k][i] != 0 :
                tempC -= X[k][i]
        # 시작점 합 = 1
        if i == 0 :
            c0 = tempC == 1
            m.addConstr(c0, 'c0'+str(i))
        # 끝점 합 = -1
        elif i == NODE - 1 :
            c0 = tempC == -1
            m.addConstr(c0, 'c0'+str(i))
        # 나머지 합 = 0
        else :
            c0 = tempC == 0
            m.addConstr(c0, 'c0'+str(i))

    m.setObjective(Z, GRB.MINIMIZE)

    m.optimize()

    print()
    for v in m.getVars() :
        if v.x != 0 :
            print(v.varName, ':', v.x)
    print()

    print("경로 : ", end = '')
    for v in m.getVars() :
        if v.x != 0 :
            print(v.varName[0], "-> ", end = '')
    print('T')
    print()

    print('총 거리 : ', m.objVal)

except GurobiError() :
    print('Error reported')


import glob
import os

import numpy as np
import pandas as pd

def csv_read(file_path, get_frame_data=True):
    csv_data = pd.read_csv(file_path)
    if not get_frame_data:
        return csv_data
    else:
        col_name = list(csv_data.columns)[1:]
        csv_data = np.array(csv_data.loc[:, :])

        frame_num = np.max(csv_data[:, 0]).astype(np.uint8)  # 从第一列（帧数）中，获取该数据对应的 tif 图像总帧数
        frame_data = list()
        for frame_index in range(1, frame_num + 1):
            frame_data.append(csv_data[csv_data[:, 0] == frame_index, 1:])

        return frame_data, col_name

def csv_particle_detector(csv_path):
    frame_data, _ = csv_read(csv_path)
    y = np.empty(len(frame_data), dtype=object)
    for idx, frame_ndarray in enumerate(frame_data):
        y[idx] = frame_ndarray[:, 1:3]
    return y

def csv_particle_matcher(csv_path):
    frame_data, _ = csv_read(csv_path)
    y = np.empty(len(frame_data), dtype=object)
    for idx, frame_ndarray in enumerate(frame_data):
        y[idx] = (frame_ndarray[:, 0].astype(np.int32), frame_ndarray[:, 1:3])  # 多了一个 ID
    return y

if __name__ == '__main__':
    csv_dir = '../data/synthesized_data_1'
    csv_list = glob.glob(os.path.join(csv_dir, '*.csv'))
    for csv_path in csv_list:
        re = csv_particle_detector(csv_path)

    pass


from rest_framework import serializers
from rest_framework import exceptions
from .models import Profile

class ProfileSerializer(serializers.ModelSerializer):
    is_created = serializers.CharField(read_only=True)

    class Meta:
        model = Profile
        fields = ('nick_name', 'avatar', 'is_created',)

    def create(self, validated_data):
        user = None
        request = self.context.get("request")
        if request and hasattr(request, "user"):
            user = request.user
        validated_data["user"] = user
        try:
            instance, is_created = Profile.objects.get_or_create(**validated_data)
            instance.is_created = is_created
            return instance
        except Exception as ex:
            raise exceptions.ValidationError(str(ex))


import os
import torch
import numpy as np
import torch.nn.functional as F
from functools import partial
import pickle

def save_model(model, checkpoint, num, is_epoch=True):
    if not os.path.exists(checkpoint):
        os.system('mkdir -p '+ checkpoint)
    if is_epoch:
        torch.save(model.state_dict(), os.path.join(checkpoint, 'epoch_{:04d}.pth'.format(num)))
    else:
        torch.save(model.state_dict(), os.path.join(checkpoint, 'iteration_{:09d}.pth'.format(num)))
    torch.save(model.state_dict(), checkpoint + 'weight.pt')

def load_model(model, resume):
    pretrained_dict = torch.load(resume)
    model_dict = model.state_dict()
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
    model_dict.update(pretrained_dict)
    model.load_state_dict({k.replace('module.', ""): v for k, v in torch.load(model_dict).items()})
    model.load_state_dict(model_dict)