text:
#Author: Gentry Atkinson
#Organization: Texas University
#Data: 29 October, 2020
#Build, compile and return a convolutional autoencoder

#from tensorflow import keras
import numpy as np
import random as rand
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dropout, Dense
from tensorflow.keras.layers import Input, Conv1DTranspose, Lambda, Reshape, BatchNormalization
from tensorflow.keras.layers import UpSampling1D
from tensorflow.keras.callbacks import EarlyStopping
from matplotlib import pyplot as plt
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
from tensorflow.keras.utils import to_categorical

#tf.config.threading.set_inter_op_parallelism_threads(8)

def build_sfe(train_example, features_per_channel=30, num_labels=2):
    print("Input shape: ", train_example.shape)
    s=[1,1]
    if train_example.ndim==1:
        s[1] = len(train_example)
    else:
        s[0] = train_example.shape[0]
        s[1] = train_example.shape[1]
    model = Sequential([
        Input(shape=train_example.shape),
        BatchNormalization(scale=False),
        Reshape((s[0], s[1])),
        Conv1D(filters=128, kernel_size=16, activation='relu', padding='same'),
        Conv1D(filters=128, kernel_size=16, activation='relu', padding='same'),
        MaxPooling1D(pool_size=(16), data_format='channels_first'),
        Flatten(),
        Dense(features_per_channel*s[0], activation='sigmoid', name='Embedding'),
        Dense(features_per_channel*s[0], activation='sigmoid'),
        Dense(features_per_channel*s[0]/2, activation='sigmoid'),
        Dense(num_labels, activation='softmax')
    ])
    model.compile(optimizer='RMSprop', loss='mse', metrics=['acc'])
    model.summary()
    print("Output shape: ", model.output.shape)
    return model

def trim_classifier(sfe):
    print("Removing classification layers")
    o = sfe.layers[-4].output
    extractor = Model(sfe.input, [o])
    #extractor.summary()
    return extractor

def train_sfe(sfe, X, y, withEvaluation=False):
    if withEvaluation:
        X, X_test, y, y_test = train_test_split(X, y, test_size=0.1, random_state=23)

    es = EarlyStopping(monitor='val_acc', mode='max', verbose=1, patience=5)
    sfe.fit(X, y, epochs=100, verbose=1, callbacks=[es], validation_split=0.1, batch_size=10)

    if withEvaluation:
        #y_pred = sfe.predict_classes(X_test)
        y_pred = np.argmax(sfe.predict(X_test), axis=-1)
        y_test = np.argmax(y_test, axis=-1)
        mat = confusion_matrix(y_test, y_pred)
        print("predicted labels ", y_pred)
        print("true labels ", y_test)
        print("Confuxion matrix: ")
        print(mat)

    return sfe

def get_trained_sfe(X, y):
    if y.ndim == 1:
        y = to_categorical(y)
    numLabels = y.shape[1]
    sfe = build_sfe(X[0], num_labels=numLabels)
    sfe = train_sfe(sfe, X, y)
    sfe = trim_classifier(sfe)
    sfe.summary()
    return sfe

if __name__ == "__main__":
    print("Test model building")
    X = np.genfromtxt('data/synthetic_test_data.csv', delimiter=',')
    y = np.genfromtxt('data/synthetic_test_labels.csv', delimiter=',')
    y = to_categorical(y)
    print("data shape: ", X.shape)
    print("label shape: ", y.shape)
    norm = np.max(X)
    X = X/norm
    X = np.resize(X, (len(X), 1, len(X[0])))
    print("labels", y)

    sfe = build_sfe(X[0], num_labels=3)
    sfe = train_sfe(sfe, X, y, withEvaluation=True)
    sfe = trim_classifier(sfe)
    predict = sfe.predict(X)
    print("Output feature set: ", predict.shape)

ext: py

max_stars_repo_name: gentry-atkinson/tsar

max_issues_repo_name: gentry-atkinson/tsar

max_forks_repo_name: gentry-atkinson/tsar

reason: import numpy


text:
"""
Script to train and eval the nbow to attribute model
"""

from data.dictionary_dataset import load_vocab
from sklearn.linear_model import LogisticRegression
from lib.attribute_loss import evaluate_accuracy
from data.attribute_loader import Attributes
import numpy as np
import pandas as pd
from collections import defaultdict
import pickle as pkl
VOCAB_SIZE = 5000
dict_field, _ = load_vocab()

def bowize(text_defn, emb=None):
    """
    Gets the embedding.
    :param text_defn:
    :param emb:
    :return:
    """
    inds = [dict_field.vocab.stoi[x] for x in dict_field.preprocess(text_defn)]
    bow = np.zeros(VOCAB_SIZE, dtype=np.float64)
    bow[[i for i in inds if i < VOCAB_SIZE]] = 1.0
    return bow

def nbowize(text_defn, emb=None):
    """
    Gets the embedding.
    :param text_defn:
    :param emb:
    :return:
    """
    inds = [dict_field.vocab.stoi[x] for x in dict_field.preprocess(text_defn)]
    nbow = np.stack([dict_field.vocab.vectors[i].squeeze().numpy() for i in inds]).mean(0)

    if emb is not None:
        feats = np.concatenate((nbow, emb))
        return feats
    return nbow

def get_x(data, enc_fn, use_emb=False):
    embeds_to_use = data.embeds.data.numpy()
    defns_to_use = list(data.atts_df['defn'])
    atts_to_use = data.atts_matrix.data.numpy()

    if use_emb:
        return np.stack([enc_fn(d,e) for d, e in zip(defns_to_use, embeds_to_use)]), atts_to_use
    else:
        return np.stack([enc_fn(d) for d in defns_to_use]), atts_to_use

def get_stacked_x(data, enc_fn, use_emb=False):
    embeds = data.embeds.data.numpy()
    atts = data.atts_matrix.data.numpy()
    embeds_to_use = []
    defns_to_use = []
    atts_to_use = []
    i = 0
    for _, df in data.atts_df.groupby('template'):
        embeds_to_use.append(embeds[i])
        atts_to_use.append(atts[i])
        i += df.shape[0]
        defns_to_use.append(' '.join(df))
    embeds_to_use = np.stack(embeds_to_use)
    atts_to_use = np.stack(atts_to_use)

    if use_emb:
        return np.stack([enc_fn(d,e) for d, e in zip(defns_to_use, embeds_to_use)]), atts_to_use
    else:
        return np.stack([enc_fn(d) for d in defns_to_use]), atts_to_use

def defn_to_atts(defn_type, use_emb=False, first_defn=True):

    train_data, val_data, test_data = Attributes.splits(use_defns=True, cuda=False,
                                                        first_defn_at_test=first_defn)
    enc_fn = {'bow': bowize, 'nbow': nbowize}[defn_type]
    if first_defn:
        # We want to oversample
        balanced_train_inds = train_data._balanced_inds

        X_train, Y_train = get_x(train_data, enc_fn, use_emb=use_emb)
        X_train = X_train[balanced_train_inds]
        Y_train = Y_train[balanced_train_inds]
        X_val, Y_val = get_x(val_data, enc_fn, use_emb=use_emb)
        X_test, Y_test = get_x(test_data, enc_fn, use_emb=use_emb)

    else:
        # We want to undersample
        X_train, Y_train = get_stacked_x(train_data, enc_fn, use_emb=use_emb)
        X_val, Y_val = get_stacked_x(val_data, enc_fn, use_emb=use_emb)
        X_test, Y_test = get_stacked_x(test_data, enc_fn, use_emb=use_emb)

    # cross validate
    cs = np.power(10., [-3,-2,-1,0])
    accs = defaultdict(list)
    for c in cs:
        for d, (dom_name, dom_size) in enumerate(train_data.domains):
            M = LogisticRegression(C=c)
            print("fitting {}".format(d))
            M.fit(X_train, Y_train[:, d])
            s = M.score(X_val, Y_val[:, d])
            accs[d].append(s)

    c_to_use = {d:cs[np.argmax(scores)] for d, scores in accs.items()}
    print("Using c={}, acc of {:.3f} on val".format(
        '\n'.join('{:2d}:{:.3f}'.format(d,c) for d,c in c_to_use.items()),
        np.mean([max(accs[d]) for d in c_to_use.keys()])
    ))

    # -----------------------------------------------
    preds = []
    for d, (dom_name, dom_size) in enumerate(train_data.domains):
        M = LogisticRegression(C=c_to_use[d])
        print("fitting {}".format(d))
        M.fit(X_train, Y_train[:,d])
        s = M.score(X_test, Y_test[:,d])
        print("Score for {} is {}".format(dom_name, s))

        preds.append(M.predict(X_test))

    preds_full = np.array(preds).T
    acc_table = evaluate_accuracy(preds_full, Y_test)

    acc_table.index = ['{}{}({})'.format(defn_type, ' +GloVe' if use_emb else '',
                                         'firstdefn' if first_defn else 'concat')]

    np.save('{}{}.pkl'.format(defn_type, ' +GloVe' if use_emb else ''), preds_full)
    return acc_table

if __name__ == '__main__':
    results = pd.concat([defn_to_atts(t, e) for t in ('bow', 'nbow') for e in (True, False)], axis=0)
    results.to_csv('defn.csv', float_format='%.2f')

max_stars_repo_name: rowanz/verb-attributes

max_issues_repo_name: rowanz/verb-attributes

max_forks_repo_name: rowanz/verb-attributes


text:
# Copyright (c) 2015-2020, Swiss Federal Institute of Technology (ETH Zurich)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""Mixin helper classes"""

import abc
import copy
import io
import itertools
import os
import pickle
import typing as t
import warnings
from pathlib import Path
from types import SimpleNamespace

import numpy as np
import pandas as pd
import yaml

from exot.exceptions import *
from exot.util.attributedict import AttributeDict
from exot.util.decorators import read_only
from exot.util.file import check_access
from exot.util.logging import get_root_logger
from exot.util.misc import (
    flatten_dict,
    get_valid_access_paths,
    getitem,
    has_method,
    has_property,
    has_type,
    is_abstract,
    leaves,
    mro_getattr,
    mro_hasattr,
    setgetattr,
    setitem,
    stub_recursively,
)

# Ignore NaturalNameWarning(s) produced by the pytables module
warnings.filterwarnings("ignore", module="tables")

try:
    from yaml import CDumper as Dumper, CLoader as Loader
except ImportError:
    from yaml import Dumper, Loader

__all__ = (
    "Configurable",
    "HasParent",
    "SubclassTracker",
    "Serialisable",
    "Pickleable",
    "YamlSerialisable",
    "IntermediatesHolder",
    "IntermediatesHandler",
    "LabelConversions",
)

"""
Configurable
------------

Configurable mixin can be used to add to a class an ability to add a `config` property
that performs type checks and verifies that a provided dict-like structure contains
at least a required set of keys. Moreover,
"""

# shorthands for attribute names
class _Configurable(SimpleNamespace):
    config_arg = read_only("__config_arg__")

class Configurable(metaclass=abc.ABCMeta):
    def __init_subclass__(cls, **kwargs: t.Any) -> None:
        """Initialise a subclass of Configurable"""
        if "configure" in kwargs:
            configure = kwargs.pop("configure")
        else:
            # the default value
            configure = mro_getattr(cls, _Configurable.config_arg, "config")

        if not configure:
            raise ValueError(
                "empty 'configure' in creation of {cls.__name__} subclass", configure, cls
            )

        elif not isinstance(configure, str):
            raise TypeError("'configure' is not a str", configure, cls)

        setattr(cls, _Configurable.config_arg, configure)
        super().__init_subclass__(**kwargs)

    def __init__(self, *args: t.Dict, **kwargs: t.Dict) -> None:
        """Initialise the Configurable"""
        if len(args) > 1:
            raise ValueError("at most 1 positional argument is accepted")

        self._config = None  # type: t.Optional[AttributeDict]

        if args:
            self.config = args[0]
        else:
            config_arg = getattr(self, _Configurable.config_arg)
            if config_arg in kwargs:
                self.config = AttributeDict(kwargs.pop(config_arg))

    @classmethod
    def __subclasshook__(cls, klass: type) -> t.Union[bool, type(NotImplemented)]:
        """Subclass checking hook for types that are alike"""
        if cls is Configurable:
            if all(
                [
                    has_property(klass, "config"),
                    has_property(klass, "configured"),
                    has_property(klass, "required_config_keys"),
                ]
            ):
                return True
        return NotImplemented

    @property
    def required_config_keys(self) -> t.List[str]:
        """Produce a list of required keys"""
        return []

    @property
    def configured(self) -> bool:
        """Is the Configurable configured?"""
        return self.config is not None

    @property
    def config(self) -> t.Optional[AttributeDict]:
        """Access the config"""
        return getattr(self, "_config", None)

    @config.setter
    def config(self, value: t.MutableMapping) -> None:
        """Set the config with key requirements and validation"""
        if not isinstance(value, t.MutableMapping):
            raise TypeError("'config' can be only set with a MutableMapping", value)

        _ = [k for k in self.required_config_keys if k not in value]
        if _:
            raise RequiredKeysMissingError(f"required keys missing: {_!r}")

        self._config = AttributeDict.from_dict(value)
        self.validate()

    def validate(self) -> t.NoReturn:
        """Check if the config has desired values and/or types"""
        pass

"""
HasParent
---------

This mixin allows for easier handling of class hierarchies. A parent type is set and
a :meth:`parent` property is set in an inheriting class.
"""

# shorthands for attribute names
class _HasParent(SimpleNamespace):
    parent_type = read_only("__parent__")
    parent_instance = read_only("_parent")

class HasParent(metaclass=abc.ABCMeta):
    def __init_subclass__(cls, parent: type, **kwargs):
        if not parent and not isinstance(parent, type):
            raise HasParentTypeError("'parent' should be a type", cls)

        setattr(cls, _HasParent.parent_type, parent)

        super().__init_subclass__(**kwargs)

    def __init__(self, *args, **kwargs):
        if "parent" in kwargs:
            self.parent = kwargs.pop("parent")

    @property
    def parent(self):
        return getattr(self, _HasParent.parent_instance, None)

    @parent.setter
    def parent(self, value):
        if not isinstance(value, getattr(self, _HasParent.parent_type)):
            raise WrongParentTypeError(type(value), value)

        setattr(self, _HasParent.parent_instance, value)

"""
SubclassTracker
---------------

Subclass tracker can be used to keep account of derived classes, and concrete
derived classes for any class that inherits from it.

If a type has a member type 'Type' that is an Enum, the tracking will also be
done by type.
"""

# shorthands for attribute names
class _SubclassTracker(SimpleNamespace):
    type_attr = read_only("__type__")
    track = read_only("__track__")
    derived = read_only("__derived__")
    concrete = read_only("__concrete__")
    derived_bt = read_only("__derived_by_type__")
    concrete_bt = read_only("__concrete_by_type__")

class SubclassTracker(metaclass=abc.ABCMeta):
    """A mixin class for tracking derived and concrete derived classes

    .. note::
        The proper functioning of this class depends on the MRO (method
        resolution order). The subclass initialiser looks for itself in the
        hierarchy, and considers the previous class in the instance as the
        "root" to be tracked.

        For example:

        >>> class X(SomeClass, SubclassTracker): pass

        will "apply" the tracking to SomeClass. To track X, put the mixin
        as the first inherited class:

        >>> class X(SubclassTracker, SomeClass): pass
    """

    def __init_subclass__(cls, track: str = None, **kwargs: t.Dict) -> None:
        __ = _SubclassTracker()

        # get root and previous classes
        mixin_idx = cls.mro().index(SubclassTracker)
        root_idx = mixin_idx - 1  # root is the class preceding this mixin
        root = cls.mro()[root_idx]
        prev = cls.mro()[1] if mixin_idx != 1 else None

        if cls is root:
            # set up the root class for tracking
            setgetattr(root, __.derived, default=set())
            setgetattr(root, __.concrete, default=set())
            setgetattr(root, __.track, default=track)

            if has_type(root):
                _rtrack = getattr(root, __.track)
                kwargs_type = kwargs.pop(_rtrack) if _rtrack in kwargs else None
                setgetattr(root, __.type_attr, default=kwargs_type)
                setgetattr(
                    root, __.derived_bt, {k: set() for k in [*getattr(root, "Type"), None]}
                )
                setgetattr(
                    root, __.concrete_bt, {k: set() for k in [*getattr(root, "Type"), None]}
                )

                if not is_abstract(root):
                    getattr(root, __.concrete_bt)[getattr(root, __.type_attr)].add(cls)
        else:
            # bootstrap a derived class
            _root = root.__name__
            _cls = cls.__name__

            getattr(root, __.derived).add(cls)

            if not is_abstract(cls):
                getattr(root, __.concrete).add(cls)

            if has_type(root):
                if not has_type(cls):
                    raise SubclassTrackerTypeError(
                        f"root ({_root}) has Type but {_cls} does not", cls
                    )

                _rtrack = getattr(root, __.track)
                cls_type = getattr(cls, __.type_attr, None)
                prev_type = getattr(prev, __.type_attr, None)
                kwargs_type = kwargs.pop(_rtrack) if _rtrack in kwargs else None

                if cls_type and kwargs_type:
                    raise SubclassTrackerValueError(
                        f"{__.type_attr} and class argument {_rtrack} are both present", cls
                    )

                if not cls_type and prev_type:
                    setattr(cls, __.type_attr, prev_type)
                elif not cls_type and kwargs_type:
                    setattr(cls, __.type_attr, kwargs_type)
                else:  # type of cls already set
                    setgetattr(cls, __.type_attr, None)

                getattr(root, __.derived_bt)[getattr(cls, __.type_attr)].add(cls)

                if not is_abstract(cls):
                    getattr(root, __.concrete_bt)[getattr(cls, __.type_attr)].add(cls)

        super().__init_subclass__(**kwargs)

"""
Serialisable
------------

Base class for serialisation mixins.
"""

class Serialisable(metaclass=abc.ABCMeta):
    """Abstract base class for serialisers"""

    def __init_subclass__(cls, **kwargs):
        """Initialise a subclass

        -   Attributes in `serialise_ignore` will be deleted from the instance before
            serialisation.
        -   Attributes in `serialise_stub` will be 'stubbed', i.e. all leaf nodes will
            be replaced with `None`.
        -   If `serialise_no_parent` is set, a parent object, as defined by HasParent,
            will not be serialised.
        -   If `serialise_inherit` is set, serialise

        A concrete class has to implement the following methods:

        -   def dumps(self) -> t.Union[str, bytes]
        -   def dump(self, file: t.Union[Path, io.TextIOBase]) -> None

        And the following class methods:

        -   def loads(cls, source: t.Union[str, bytes]) -> object
        -   def load(cls, source: t.Union[Path, io.TextIOBase]) -> object

        Args:
            serialise_ignore (t.List[str], optional): list of attributes to ignore
            serialise_stub (t.List[str], optional): list of attributes to stub
            serialise_no_parent (bool, optional): serialise parent class?
            serialise_inherit (bool, optional): inherit serialise settings from base?
        """

        def getter(attr, df):
            if attr in kwargs:
                return kwargs.pop(attr)
            else:
                return df

        cls._serialise_inherit = getter(
            "serialise_inherit", mro_getattr(cls, "_serialise_inherit", True)
        )

        def inherit(attr, df):
            return copy.copy(mro_getattr(cls, attr, df) if cls._serialise_inherit else df)

        cls._serialise_to_ignore: t.Set[str] = inherit("_serialise_to_ignore", set())
        cls._serialise_to_stub: t.Set[str] = inherit("_serialise_to_stub", set())
        cls._serialise_to_save: t.Set[str] = inherit("_serialise_to_save", set())
        cls._serialise_io_type: str = inherit(
            "_serialise_io_type", getter("serialise_io_type", "text")
        )
        cls._serialise_no_parent = inherit(
            "_serialise_no_parent", getter("serialise_no_parent", True)
        )
        cls._serialise_sep = "."

        serialise_ignore = getter("serialise_ignore", [])
        serialise_stub = getter("serialise_stub", [])
        serialise_save = getter("serialise_save", [])

        if not isinstance(cls._serialise_io_type, str) and not any(
            (cls._serialise_io_type == "text", cls._serialise_io_type == "binary")
        ):
            raise TypeError(
                f"{serialise_io_type!r} is not a recognised io type (either 'text' "
                "or 'binary')"
            )

        if cls._serialise_no_parent:
            cls._serialise_to_ignore.add(_HasParent.parent_instance)

        for attr_to_ignore in serialise_ignore:
            if not isinstance(attr_to_ignore, str):
                raise SerialisableValueError(
                    "'serialise_ignore' should only have string objects"
                )

            cls._serialise_to_ignore.add(attr_to_ignore)

        for attr_to_stub in serialise_stub:
            if not isinstance(attr_to_stub, str):
                raise SerialisableValueError("'serialise_stub' should only have string objects")

            cls._serialise_to_stub.add(attr_to_stub)

        for attr_to_save in serialise_save:
            if not isinstance(attr_to_save, str):
                raise SerialisableValueError("'serialise_save' should only have string objects")
            if cls._serialise_sep in attr_to_save:
                raise SerialisableValueError(
                    "the attribute to save contains the reserved special character "
                    "{!r} used in the serialisation process".format(cls._serialise_sep)
                )

            cls._serialise_to_save.add(attr_to_save)

        # Check all pairwise combinations for conflicts
        intersections = map(
            lambda combination: set.intersection(*map(set, combination)),
            itertools.combinations([serialise_ignore, serialise_stub, serialise_save], 2),
        )
        if not all([not len(_) for _ in intersections]):
            raise SerialisableValueError(
                "'serialise_ignore', 'serialise_stub', and 'serialise_save' should be disjoint",
                serialise_ignore,
                serialise_stub,
                serialise_save,
            )

        super().__init_subclass__(**kwargs)

    @abc.abstractmethod
    def dumps(self) -> t.Union[str, bytes]:
        """Dump an instance to a string or bytes"""
        pass

    @abc.abstractmethod
    def dump(self, file: io.IOBase) -> None:
        """Dump an instance to a file

        Args:
            file (t.Union[Path, io.TextIOBase]): a file path or an io wrapper
        """
        pass

    @classmethod
    @abc.abstractmethod
    def loads(cls, source: t.Union[str, bytes]) -> object:
        """Load an instance from a string or bytes

        Args:
            source (t.Union[str, bytes]): a serialised object as a string or bytes
        """
        pass

    @classmethod
    @abc.abstractmethod
    def load(cls, source: io.IOBase) -> object:
        """Load an instance from a file

        Args:
            source (t.Union[Path, io.TextIOBase]): a file path or an io wrapper
        """
        pass

    @classmethod
    def deserialise(cls, source=t.Union[str, bytes, Path, t.IO]) -> object:
        local: bool = False
        valid_types = [str, bytes, Path, t.IO]
        if not any(isinstance(source, v) for v in valid_types):
            raise SerialisableTypeError(f"'source' must be one of {valid_types!r}", source)

        if isinstance(source, Path):
            if cls._serialise_io_type == "text":
                source = source.open("r")
            else:
                source = source.open("rb")
            local = True

        if isinstance(source, io.IOBase):
            assert source.readable()
            if cls._serialise_io_type == "text":
                assert isinstance(source, io.TextIOBase)
            else:
                assert isinstance(source, io.BufferedIOBase)

        if isinstance(source, (str, bytes)):
            instance = cls.loads(source)
        else:
            instance = cls.load(source)

        if local:
            source.close()

        assert isinstance(instance, cls)
        return instance

    def serialise(self, file: t.Optional[t.Union[Path, t.IO]] = None) -> t.Optional[str]:
        local: bool = False

        if file:
            if isinstance(file, Path):
                assert check_access(file, "w"), "'file' must be writable"
                if self._serialise_io_type == "text":
                    file = file.open("w")
                else:
                    file = file.open("wb")
                local = True
            elif isinstance(file, io.IOBase):
                assert file.writable()
                if self._serialise_io_type == "text":
                    assert isinstance(file, io.TextIOBase)
                else:
                    assert isinstance(file, io.BufferedIOBase)
            else:
                raise SerialisableTypeError("'file' not one of [str, Path, t.IO]", file)

        serialise_backup = dict()

        for k in self._serialise_to_ignore:
            if hasattr(self, k):
                serialise_backup[k] = getattr(self, k)
                delattr(self, k)

        for k in self._serialise_to_stub:
            if hasattr(self, k):
                serialise_backup[k] = getattr(self, k)
                setattr(self, k, stub_recursively(getattr(self, k)))

        for k in self._serialise_to_save:
            if hasattr(self, k):
                serialise_backup[k] = getattr(self, k)

                # if a mapping is given, stub it, otherwise delete the attribute before serialising
                if isinstance(getattr(self, k), t.Mapping):
                    setattr(self, k, stub_recursively(getattr(self, k)))
                else:
                    delattr(self, k)

        try:
            if file:
                self.dump(file)
            else:
                return self.dumps()
        finally:
            if local:
                file.close()

            for k, v in serialise_backup.items():
                setattr(self, k, v)

    def _save_npz(self, npz_path, npz_data):
        np.savez_compressed(npz_path, **npz_data)
        return npz_path

    def _save_hdf(self, hdf_path, hdf_data):
        with pd.HDFStore(hdf_path, "w") as _pd_store:
            for name, values in hdf_data.items():
                _pd_store.put(name, values)
        return hdf_path

    def save_data(
        self, *, prefix: t.Optional[str] = "", path: t.Optional[Path] = None
    ) -> t.List[Path]:
        """Save input and output data in NumPy archives and/or HDF5 stores.

        Args:
            prefix (t.Optional[str], optional):
                The file prefix, e.g. "my_data" will produce archives my_data.npz and my_data.h5
            path (t.Optional[Path], optional):
                The save path, if different than self.path
        """
        if not path and not hasattr(self, "path"):
            raise ValueError(
                "Path has to be either available as an attribute or provided to the "
                "'load_data' function."
            )

        _saved_paths = []

        _filepath = path if path and path.is_dir() else self.path
        for attribute in self._serialise_to_save:
            if getattr(self, attribute, None) is None:
                continue

            if isinstance(getattr(self, attribute), np.ndarray):
                _saved_paths.append(
                    self._save_npz(
                        _filepath / (prefix + attribute + ".npz"),
                        {attribute: getattr(self, attribute)},
                    )
                )
            elif isinstance(getattr(self, attribute), (pd.DataFrame, pd.Series, pd.Panel)):
                _saved_paths.append(
                    self._save_hdf(
                        _filepath / (prefix + attribute + ".h5"),
                        {attribute: getattr(self, attribute)},
                    )
                )
            elif isinstance(getattr(self, attribute), t.Mapping):
                _saved_paths.append(
                    self.save_mapping(attribute, prefix, path, save_bundled=True)
                )
            else:
                raise SerialisableDataSaveError(
                    f"Failed saving {attribute} from 'serialise_to_save', "
                    "can only save NumPy or Pandas data!"
                )

        return _saved_paths

    def save_mapping(
        self,
        attribute,
        prefix: t.Optional[str] = "",
        path: t.Optional[Path] = None,
        save_bundled: t.Optional[bool] = False,
    ) -> t.List[Path]:
        _saved_paths = list()
        _flattened_holder = flatten_dict(getattr(self, attribute), self._serialise_sep)
        _filepath = path if path and path.is_dir() else self.path

        if not _filepath.exists():
            _filepath.mkdir()
        if save_bundled:
            _np_holder = dict()
            _pd_holder = dict()
            for name, value in _flattened_holder.items():
                if isinstance(value, np.ndarray):
                    if name in _np_holder:
                        raise SerialisableDataSaveError(
                            f"{name!r} already contained in NumPy attribute holder {_np_holder!r}"
                        )
                    _np_holder[name] = value
                elif isinstance(value, (pd.DataFrame, pd.Series, pd.Panel)):
                    if name in _pd_holder:
                        raise SerialisableDataSaveError(
                            f"{name!r} already contained in Pandas attribute holder {_pd_holder!r}"
                        )
                    _pd_holder[name] = value
                else:
                    raise SerialisableDataSaveError(
                        f"type {type(value)!r} in {name!r} cannot be serialised"
                    )

            if _np_holder:
                _np_path = _filepath / (prefix + attribute + ".npz")
                np.savez_compressed(_np_path, **_np_holder)
                _saved_paths.append(_np_path)

            if _pd_holder:
                _pd_path = _filepath / (prefix + attribute + ".h5")
                with pd.HDFStore(_pd_path, "w") as _pd_store:
                    for name, value in _pd_holder.items():
                        _pd_store.put(name, value)
                _saved_paths.append(_pd_path)
        else:
            for name, value in _flattened_holder.items():
                if isinstance(value, np.ndarray):
                    _saved_paths.append(
                        self._save_npz(_filepath / (prefix + name + ".npz"), {name: value})
                    )
                elif isinstance(value, (pd.DataFrame, pd.Series, pd.Panel)):
                    _saved_paths.append(
                        self._save_hdf(_filepath / (prefix + name + ".h5"), {name: value})
                    )
                else:
                    # raise SerialisableDataSaveError(
                    get_root_logger().info(
                        f"type {type(value)!r} in {name!r} cannot be serialised"
                    )

        return _saved_paths

    def remove_mapping(
        self,
        attribute,
        prefix: t.Optional[str] = "",
        path: t.Optional[Path] = None,
        saved_bundled: t.Optional[bool] = False,
    ) -> t.List[Path]:
        _removed_paths = list()
        _flattened_holder = flatten_dict(getattr(self, attribute), self._serialise_sep)
        _filepath = path if path and path.is_dir() else self.path

        if not _filepath.exists():
            _filepath.mkdir()
        if saved_bundled:
            _np_path = _filepath / (prefix + attribute + ".npz")
            if _np_path.exists():
                os.remove(_np_path)
                _saved_paths.append(_np_path)

            _pd_path = _filepath / (prefix + attribute + ".h5")
            if _pd_path.exists():
                os.remove(_pd_path)
                _removed_paths.append(_pd_path)
        else:
            for name, value in _flattened_holder.items():
                _np_path = _filepath / (prefix + name + ".npz")
                if _np_path.exists():
                    os.remove(_np_path)
                    _removed_paths.append(_np_path)

                _pd_path = _filepath / (prefix + name + ".h5")
                if _pd_path.exists():
                    os.remove(_pd_path)
                    _removed_paths.append(_pd_path)
        return _removed_paths

    def save_data_bundled(
        self, *, prefix: t.Optional[str] = None, path: t.Optional[Path] = None
    ) -> t.List[Path]:
        """Save input and output data in NumPy archives and/or HDF5 stores.

        Args:
            prefix (t.Optional[str], optional):
                The file prefix, e.g. "my_data" will produce archives my_data.npz and my_data.h5
            path (t.Optional[Path], optional):
                The save path, if different than self.path
        """
        if not path and not hasattr(self, "path"):
            raise ValueError(
                "Path has to be either available as an attribute or provided to the "
                "'load_data' function."
            )

        _np_holder = dict()
        _pd_holder = dict()
        _mapping_holder = dict()

        _saved_paths = []
        _np_file = prefix + ".npz" if prefix else "streams.npz"
        _np_path = path / _np_file if path and path.is_dir() else self.path / _np_file
        _pd_file = prefix + ".h5" if prefix else "streams.h5"
        _pd_path = path / _pd_file if path and path.is_dir() else self.path / _pd_file

        for attribute in self._serialise_to_save:
            if getattr(self, attribute, None) is None:
                continue

            if isinstance(getattr(self, attribute), np.ndarray):
                _np_holder[attribute] = getattr(self, attribute)
            elif isinstance(getattr(self, attribute), (pd.DataFrame, pd.Series, pd.Panel)):
                _pd_holder[attribute] = getattr(self, attribute)
            elif isinstance(getattr(self, attribute), t.Mapping):
                _mapping_holder[attribute] = getattr(self, attribute)
            else:
                raise SerialisableDataSaveError(
                    f"Failed saving {attribute} from 'serialise_to_save', "
                    "can only save NumPy or Pandas data!"
                )

        # For all serialisable-save attributes that were mappings, flatten them and assign to
        # NumPy and Pandas holders.
        if _mapping_holder:
            _flattened_holder = flatten_dict(_mapping_holder, self._serialise_sep)
            for name, value in _flattened_holder.items():
                if isinstance(value, np.ndarray):
                    if name in _np_holder:
                        raise SerialisableDataSaveError(
                            f"{name!r} already contained in NumPy attribute holder {_np_holder!r}"
                        )
                    _np_holder[name] = value
                elif isinstance(value, (pd.DataFrame, pd.Series, pd.Panel)):
                    if name in _pd_holder:
                        raise SerialisableDataSaveError(
                            f"{name!r} already contained in Pandas attribute holder {_pd_holder!r}"
                        )
                    _pd_holder[name] = value
                else:
                    raise SerialisableDataSaveError(
                        f"type {type(value)!r} in {name!r} cannot be serialised"
                    )

        if _np_holder:
            np.savez_compressed(_np_path, **_np_holder)
            _saved_paths.append(_np_path)

        if _pd_holder:
            with pd.HDFStore(_pd_path, "w") as _pd_store:
                for name, value in _pd_holder.items():
                    _pd_store.put(name, value)
            _saved_paths.append(_pd_path)

        return _saved_paths

    def load_data(self, *, prefix: t.Optional[str] = "", path: t.Optional[Path] = None) -> None:
        """Loads input and output stream data from NumPy archives and/or HDF5 stores.

        Args:
            prefix (t.Optional[str], optional):
                The file prefix, e.g. "my_data" will produce archives my_data.npz and my_data.h5
            path (t.Optional[Path], optional):
                The load path, if different than self.path
        """
        if not path and not hasattr(self, "path"):
            raise ValueError(
                "Path has to be either available as an attribute or provided to the "
                "'load_data' function."
            )

        # Get names and valid paths of
        stubbed = {
            _: list(
                get_valid_access_paths(
                    getattr(self, _),
                    _leaf_only=True,
                    _use_lists=False,
                    _fallthrough_empty=False,
                )
            )
            for _ in self._serialise_to_save
            if hasattr(self, _) and isinstance(getattr(self, _), t.Mapping)
        }

        _filepath = path if path and path.is_dir() else self.path
        for attribute in self._serialise_to_save:
            _np_path = _filepath / (prefix + attribute + ".npz")
            _pd_path = _filepath / (prefix + attribute + ".h5")
            if _np_path.exists():
                with np.load(_np_path) as _np_store:
                    for _data in _np_store.files:
                        sub_attribute, delimiter, rest = _data.partition(self._serialise_sep)
                        setattr(self, _data, _np_store[_data])

            elif _pd_path.exists():
                with pd.HDFStore(_pd_path, "r") as _pd_store:
                    for _data in _pd_store:
                        sub_attribute, delimiter, rest = _data.strip("/").partition(
                            self._serialise_sep
                        )
                        setattr(self, attribute, _pd_store.get(_data))
            else:
                get_root_logger().warning(f"No file found to load attribute{attribute!r}!")

    def load_mapping(self, path: Path, prefix: t.Optional[str] = None) -> AttributeDict:
        """
        Loads data from files specified using path and regex. Different to load_data, the data is not saved
        in the parent object (self) but in a AttributeDict, which is then returned.
        """
        if not path:
            raise ValueError("Path has to be provided to the 'load_mapping' function.")

        def _load_data_file(_data_file_path, _fileextension):
            if _fileextension == "npz":
                with np.load(_data_file_path) as _np_store:
                    if len(_np_store) == 1:
                        _data = _np_store[_np_store.files[0]]
                    else:
                        _data = AttributeDict()
                        for data_key in _np_store:
                            _data[data_key] = _np_store[data_key]
            elif _fileextension == "h5":
                with pd.HDFStore(_data_file_path, "r") as _pd_store:
                    if len(_pd_store) == 1:
                        _data = _pd_store.get(_pd_store.keys()[0])
                    else:
                        _data = AttributeDict()
                        for data_key in _pd_store:
                            _data[data_key] = _pd_store[data_key]
            else:
                raise Exception(f"Unknown file extension for file {_data_file_path}")
            return _data

        data = AttributeDict()
        for filepath in path.glob(prefix + "*"):
            filename = filepath.name.replace(prefix, "")
            filename_split = filename.split(".")
            if len(filename_split) == 2:
                attribute = filename_split[0]
                data[attribute] = _load_data_file(filepath, filename_split[-1])
            elif len(filename_split) == 3:
                attribute_outer = filename_split[0]
                attribute_inner = filename_split[1]
                if attribute_outer not in data.keys():
                    data[attribute_outer] = AttributeDict()
                data[attribute_outer][attribute_inner] = _load_data_file(
                    filepath, filename_split[-1]
                )
            else:
                raise Exception(
                    f"Filename {filename} is not fitting. Has to consist of two or three comma separated substrings"
                )
        return data

    def load_data_bundled(
        self, *, prefix: t.Optional[str] = None, path: t.Optional[Path] = None
    ) -> None:
        """Loads input and output stream data from NumPy archives and/or HDF5 stores.

        Args:
            prefix (t.Optional[str], optional):
                The file prefix, e.g. "my_data" will produce archives my_data.npz and my_data.h5
            path (t.Optional[Path], optional):
                The load path, if different than self.path
        """
        if not path and not hasattr(self, "path"):
            raise ValueError(
                "Path has to be either available as an attribute or provided to the "
                "'load_data' function."
            )

        _np_file = prefix + ".npz" if prefix else "streams.npz"
        _pd_file = prefix + ".h5" if prefix else "streams.h5"
        _np_path = path / _np_file if path and path.is_dir() else self.path / _np_file
        _pd_path = path / _pd_file if path and path.is_dir() else self.path / _pd_file

        # Get names and valid paths of
        stubbed = {
            _: list(
                get_valid_access_paths(
                    getattr(self, _),
                    _leaf_only=True,
                    _use_lists=False,
                    _fallthrough_empty=False,
                )
            )
            for _ in self._serialise_to_save
            if hasattr(self, _) and isinstance(getattr(self, _), t.Mapping)
        }

        if _np_path.exists():
            with np.load(_np_path) as _np_store:
                for _data in _np_store.files:
                    attribute, delimiter, rest = _data.partition(self._serialise_sep)
                    if delimiter and attribute in stubbed:
                        # Split the 'rest' and form an access query tuple, check if it's valid
                        query = tuple(rest.split(self._serialise_sep))
                        if query not in stubbed[attribute]:
                            raise SerialisableDataLoadError(
                                f"Access query {query!r} not valid for attribute{attribute!r}"
                            )

                        setitem(getattr(self, attribute), query, _np_store[_data])
                    else:
                        setattr(self, _data, _np_store[_data])

        if _pd_path.exists():
            with pd.HDFStore(_pd_path, "r") as _pd_store:
                for _data in _pd_store:
                    attribute, delimiter, rest = _data.strip("/").partition(self._serialise_sep)
                    if delimiter and attribute in stubbed:
                        # Split the 'rest' and form an access query tuple, check if it's valid
                        query = tuple(rest.split(self._serialise_sep))
                        if query not in stubbed[attribute]:
                            raise SerialisableDataLoadError(
                                f"Access query {query!r} not valid for attribute{attribute!r}"
                            )

                        setitem(getattr(self, attribute), query, _pd_store.get(_data))
                    elif attribute in self._serialise_to_save:
                        setattr(self, attribute, _pd_store.get(_data))

"""
Pickleable
----------

Implementation of Serialisable for the pickle binary serialisation format.
"""

class Pickleable(Serialisable, serialise_io_type="binary"):
    pickle_version = read_only(-1)

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)

    def dumps(self) -> t.Union[str, bytes]:
        return pickle.dumps(self, self.pickle_version)

    def dump(self, file: io.IOBase) -> None:
        assert isinstance(file, io.BufferedIOBase), "expects a buffered I/O"
        pickle.dump(self, file, self.pickle_version)

    @classmethod
    def loads(cls, source: t.Union[str, bytes]) -> object:
        return pickle.loads(source)

    @classmethod
    def load(cls, source: io.IOBase) -> object:
        assert isinstance(source, io.BufferedIOBase), "expects a buffered I/O"
        return pickle.load(source)

"""
YamlSerialisable
----------------

Implementation of Serialisable for YAML using the PyYAML library.
"""

class YamlSerialisable(Serialisable, serialise_io_type="text"):
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)

    def dumps(self) -> t.Union[str, bytes]:
        return yaml.dump(self, Dumper=Dumper)

    def dump(self, file: t.Union[Path, io.TextIOBase]) -> None:
        yaml.dump(self, file, Dumper=Dumper)

    @classmethod
    def loads(cls, source: t.Union[str, bytes]) -> object:
        return yaml.load(source, Loader=Loader)

    @classmethod
    def load(cls, source: t.Union[Path, io.TextIOBase]) -> object:
        return yaml.load(source, Loader=Loader)

"""
Intermediates
-------------

Factory for class member variables that are used to save intermediate results needed for closer
data inspection.
"""

class IntermediatesHolder(metaclass=abc.ABCMeta):
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)

        if mro_hasattr(cls, "_serialise_to_ignore"):
            cls._serialise_to_ignore.add("intermediates")

    def __init__(self, *args, **kwargs):
        self._intermediates = AttributeDict()

    @property
    def intermediates(self):
        if not hasattr(self, "_intermediates"):
            self._intermediates = AttributeDict()
        return getattr(self, "_intermediates")

    @intermediates.setter
    def intermediates(self, value):
        if not isinstance(value, t.Mapping):
            raise IntermediatesTypeError("intermediates can only be set to mappings")

        setattr(
            self,
            "_intermediates",
            value if isinstance(value, AttributeDict) else AttributeDict.from_dict(value),
        )

    @intermediates.deleter
    def intermediates(self):
        delattr(self, "_intermediates")

    def add_intermediate(self, name, value):
        self.intermediates[name] = value

    def del_intermediate(self, name):
        if name in self.intermediates:
            del self.intermediates[name]

    def clear_intermediates(self):
        self.intermediates.clear()

    def get_intermediate(self, name):
        return self.intermediates.get(name, None)

class IntermediatesHandler(IntermediatesHolder):
    @staticmethod
    def _is_intermediate_holder(value):
        if hasattr(value, "intermediates"):
            return True
        else:
            return False

    def collect_intermediates(self, source: object, namespace: t.Optional[str] = None):
        if isinstance(source, t.Mapping):
            candidates = {
                k: v
                for k, v in source.items()
                if self._is_intermediate_holder(v) and len(v.intermediates)
            }

            copies = {k: v.intermediates.copy() for k, v in candidates.items()}

            if namespace:
                self.intermediates[namespace] = AttributeDict.from_dict(copies)
            else:
                self.intermediates.update(copies)

            # Collected layers need to be cleared to prevent unnecessary serialisation:
            # IntermediatesHolder instances usually do not derive from any Serialisable
            # subclasses.
            for name, obj in candidates.items():
                obj.clear_intermediates()
        else:
            raise TypeError(
                "Can only collect intermediates from mappings, got: {!r}".format(type(source))
            )

"""
Conversion
----------

This class can be used to convert unit labels according to powers of 10 prefixes
"""

class LabelConversions(metaclass=abc.ABCMeta):
    @property
    def _unit_prefixes(self):
        return {
            0.000000000000000000000000000000000000000000000000000001: {
                "name": "Septendecillionth",
                "power": -54,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000000000000000000000001: {
                "name": "Sedecillionth",
                "power": -51,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000000000000000000001: {
                "name": "Quindecillionth",
                "power": -48,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000000000000000001: {
                "name": "Quattuordecillionth",
                "power": -45,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000000000000001: {
                "name": "Tredecillionth",
                "power": -42,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000000000001: {
                "name": "Duodecillionth",
                "power": -39,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000000001: {
                "name": "Undecillionth",
                "power": -36,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000000001: {
                "name": "Decillionth",
                "power": -33,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000000001: {
                "name": "Nonillionth",
                "power": -30,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000000001: {
                "name": "Octillionth",
                "power": -27,
                "symbol": "",
                "prefix": "",
            },
            0.000000000000000000000001: {
                "name": "Septillionth",
                "power": -24,
                "symbol": "y",
                "prefix": "Yocto",
            },
            0.000000000000000000001: {
                "name": "Sextillionth",
                "power": -21,
                "symbol": "z",
                "prefix": "Zepto",
            },
            0.000000000000000001: {
                "name": "Quintillionth",
                "power": -18,
                "symbol": "a",
                "prefix": "Atto",
            },
            0.000000000000001: {
                "name": "Quadrillionth",
                "power": -15,
                "symbol": "f",
                "prefix": "Femto",
            },
            0.000000000001: {
                "name": "Trillionth",
                "power": -12,
                "symbol": "p",
                "prefix": "Pico",
            },
            0.000000001: {"name": "Billionth", "power": -9, "symbol": "n", "prefix": "Nano"},
            0.000001: {"name": "Millionth", "power": -6, "symbol": "μ", "prefix": "Micro"},
            0.00001: {
                "name": "Hundred-thousandth (Lakh|Lacth)",
                "power": -5,
                "symbol": "",
                "prefix": "",
            },
            0.0001: {
                "name": "Ten-thousandth (Myriadth)",
                "power": -4,
                "symbol": "",
                "prefix": "",
            },
            0.001: {"name": "Thousandth", "power": -3, "symbol": "m", "prefix": "Milli"},
            0.01: {"name": "Hundredth", "power": -2, "symbol": "c", "prefix": "Centi"},
            0.1: {"name": "Tenth", "power": -1, "symbol": "d", "prefix": "Deci"},
            1: {"name": "One", "power": 0, "symbol": "", "prefix": ""},
            10: {"name": "Ten", "power": 1, "symbol": "D", "prefix": "Deca"},
            100: {"name": "Hundred", "power": 2, "symbol": "H", "prefix": "Hecto"},
            1000: {"name": "Thousand", "power": 3, "symbol": "K", "prefix": "Kilo"},
            10000: {"name": "Ten Thousand (Myriad)", "power": 4, "symbol": "", "prefix": ""},
            100000: {"name": "Hundred Thousand (Lakh)", "power": 5, "symbol": "", "prefix": ""},
            1000000: {"name": "Million", "power": 6, "symbol": "M", "prefix": "Mega"},
            10000000: {"name": "Ten Million (Crore)", "power": 7, "symbol": "", "prefix": ""},
            100000000: {"name": "Hundred Million", "power": 8, "symbol": "", "prefix": ""},
            1000000000: {
                "name": "Billion (Milliard)",
                "power": 9,
                "symbol": "G",
                "prefix": "Giga",
            },
            1000000000000: {
                "name": "Trillion (Billion)",
                "power": 12,
                "symbol": "T",
                "prefix": "Tera",
            },
            1000000000000000: {
                "name": "Quadrillion (Billiard)",
                "power": 15,
                "symbol": "P",
                "prefix": "Peta",
            },
            1000000000000000000: {
                "name": "Quintillion (Trillion)",
                "power": 18,
                "symbol": "E",
                "prefix": "Exa",
            },
            1000000000000000000000: {
                "name": "Sextillion (Trilliard)",
                "power": 21,
                "symbol": "Z",
                "prefix": "Zetta",
            },
            1000000000000000000000000: {
                "name": "Septillion (Quadrillion)",
                "power": 24,
                "symbol": "Y",
                "prefix": "Yotta",
            },
            1000000000000000000000000000: {
                "name": "Octillion (Quadrilliard)",
                "power": 27,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000: {
                "name": "Nonillion (Quintillion)",
                "power": 30,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000: {
                "name": "Decillion (Quintilliard)",
                "power": 33,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000: {
                "name": "Undecillion (Sextillion)",
                "power": 36,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000: {
                "name": "Duodecillion (Sextilliard)",
                "power": 39,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000000: {
                "name": "Tredecillion (Septillion)",
                "power": 42,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000000000: {
                "name": "Quattuordecillion (Septilliard)",
                "power": 45,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000000000000: {
                "name": "Quindecillion (Octillion)",
                "power": 48,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000000000000000: {
                "name": "Sexdecillion (Octilliard)",
                "power": 51,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000000000000000000: {
                "name": "Septendecillion (Nonillion)",
                "power": 54,
                "symbol": "",
                "prefix": "",
            },
            1000000000000000000000000000000000000000000000000000000000000000: {
                "name": "Vigintillion (Decilliard)",
                "power": 63,
                "symbol": "",
                "prefix": "",
            },
            10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000: {
                "name": "Googol",
                "power": 100,
                "symbol": "",
                "prefix": "",
            },
        }

    def _label_unit_conversion(self, label, factor):
        label_unit_symbol = label.split("::")[-1][0]
        for lbl_factor in self._unit_prefixes:
            if self._unit_prefixes[lbl_factor]["symbol"] == label_unit_symbol:
                new_label_unit_symbol = self._unit_prefixes[lbl_factor * factor]["symbol"]
                break
        if len(new_label_unit_symbol) == 0 and (lbl_factor * factor) != 1:
            new_label_unit_symbol = self._unit_prefixes[lbl_factor * factor]["name"] + " "
        return label.replace("::" + label_unit_symbol, "::" + new_label_unit_symbol)


text:
import bin
import tests
import theano

max_stars_repo_name: fleimgruber/python

max_issues_repo_name: fleimgruber/python

max_forks_repo_name: fleimgruber/python

reason: import theano


text:
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from PIL import Image
from PIL import ImageTk
import threading
import shutil
from facerec import *
from register import *
from face_detection import *
# from dbHandler import *
from handler import *
import time
import csv
import numpy as np
import ntpath
import os

active_page = 0
thread_event = None
left_frame = None
right_frame = None
heading = None
webcam = None
img_label = None
img_read = None
img_list = []
slide_caption = None
slide_control_panel = None
current_slide = -1

root = tk.Tk()
root.geometry("1000x900+200+100")

# create Pages
pages = []
for i in range(5):
    pages.append(tk.Frame(root, bg="#3E3B3C"))
    pages[i].pack(side="top", fill="both", expand=True)
    pages[i].place(x=0, y=0, relwidth=1, relheight=1)

def goBack():
    global active_page, thread_event, webcam

    if (active_page==4 and not thread_event.is_set()):
        thread_event.set()
        webcam.release()

    for widget in pages[active_page].winfo_children():
        widget.destroy()

    pages[0].lift()
    active_page = 0

def basicPageSetup(pageNo):
    global left_frame, right_frame, heading

    back_img = tk.PhotoImage(file= r"C:\Users\hp\Documents\GitHub\Face-Recognition-For-Criminal-Detection-GUi\img\back.png")
    back_button = tk.Button(pages[pageNo], image=back_img, bg="#3E3B3C", bd=0, highlightthickness=0,
           activebackground="#3E3B3C", command=goBack)
    back_button.image = back_img
    back_button.place(x=10, y=10)

    heading = tk.Label(pages[pageNo], fg="white", bg="#3E3B3C", font="Arial 20 bold", pady=10)
    heading.pack()

    content = tk.Frame(pages[pageNo], bg="#3E3B3C", pady=20)
    content.pack(expand="true", fill="both")

    left_frame = tk.Frame(content, bg="#3E3B3C")
    left_frame.grid(row=0, column=0, sticky="nsew")

    right_frame = tk.LabelFrame(content, text="Detected Criminals", bg="#3E3B3C", font="Arial 20 bold", bd=4,
                             foreground="#2ea3ef", labelanchor="n")
    right_frame.grid(row=0, column=1, sticky="nsew", padx=20, pady=20)

    content.grid_columnconfigure(0, weight=1, uniform="group1")
    content.grid_columnconfigure(1, weight=1, uniform="group1")
    content.grid_rowconfigure(0, weight=1)

def showImage(frame, img_size):
    global img_label, left_frame

    img = cv2.resize(frame, (img_size, img_size))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = Image.fromarray(img)
    img = ImageTk.PhotoImage(img)
    if (img_label == None):
        img_label = tk.Label(left_frame, image=img, bg="#202d42")
        img_label.image = img
        img_label.pack(padx=20)
    else:
        img_label.configure(image=img)
        img_label.image = img

def getNewSlide(control):
    global img_list, current_slide

    if(len(img_list) > 1):
        if(control == "prev"):
            current_slide = (current_slide-1) % len(img_list)
        else:
            current_slide = (current_slide+1) % len(img_list)

        img_size = left_frame.winfo_height() - 200
        showImage(img_list[current_slide], img_size)

        slide_caption.configure(text = "Image {} of {}".format(current_slide+1, len(img_list)))

def selectMultiImage(opt_menu, menu_var):
    global img_list, current_slide, slide_caption, slide_control_panel

    filetype = [("images", "*.jpg *.jpeg *.png")]
    path_list = filedialog.askopenfilenames(title="Choose atleast 5 images", filetypes=filetype)

    if(len(path_list) < 5):
        messagebox.showerror("Error", "Choose atleast 5 images.")
    else:
        img_list = []
        current_slide = -1

        # Resetting slide control panel
        if (slide_control_panel != None):
            slide_control_panel.destroy()

        # Creating Image list
        for path in path_list:
            img_list.append(cv2.imread(path))

        # Creating choices for profile pic menu
        menu_var.set("")
        opt_menu['menu'].delete(0, 'end')

        for i in range(len(img_list)):
            ch = "Image " + str(i+1)
            opt_menu['menu'].add_command(label=ch, command= tk._setit(menu_var, ch))
            menu_var.set("Image 1")

        # Creating slideshow of images
        img_size =  left_frame.winfo_height() - 200
        current_slide += 1
        showImage(img_list[current_slide], img_size)

        slide_control_panel = tk.Frame(left_frame, bg="#202d42", pady=20)
        slide_control_panel.pack()

        back_img = tk.PhotoImage(file="previous.png")
        next_img = tk.PhotoImage(file="next.png")

        prev_slide = tk.Button(slide_control_panel, image=back_img, bg="#202d42", bd=0, highlightthickness=0,
                            activebackground="#202d42", command=lambda : getNewSlide("prev"))
        prev_slide.image = back_img
        prev_slide.grid(row=0, column=0, padx=60)

        slide_caption = tk.Label(slide_control_panel, text="Image 1 of {}".format(len(img_list)), fg="#ff9800",
                              bg="#202d42", font="Arial 15 bold")
        slide_caption.grid(row=0, column=1)

        next_slide = tk.Button(slide_control_panel, image=next_img, bg="#202d42", bd=0, highlightthickness=0,
                            activebackground="#202d42", command=lambda : getNewSlide("next"))
        next_slide.image = next_img
        next_slide.grid(row=0, column=2, padx=60)

def register(entries, required, menu_var):
    global img_list

    # Checking if no image selected
    if(len(img_list) == 0):
        messagebox.showerror("Error", "Select Images first.")
        return

    # Fetching data from entries
    entry_data = {}
    for i, entry in enumerate(entries):
        # print(i)
        val = entry[1].get()
        # print(val)

        if (len(val) == 0 and required[i] == 1):
            messagebox.showerror("Field Error", "Required field missing :\n\n%s" % (entry[0]))
            return
        else:
            entry_data[entry[0]] = val.lower()

    # Setting Directory
    path = os.path.join('face_samples', "temp_criminal")
    if not os.path.isdir(path):
        os.mkdir(path)

    no_face = []
    for i, img in enumerate(img_list):
        # Storing Images in directory
        id = registerCriminal(img, path, i + 1)
        if(id != None):
            no_face.append(id)

    # check if any image doesn't contain face
    if(len(no_face) > 0):
        no_face_st = ""
        for i in no_face:
            no_face_st += "Image " + str(i) + ", "
        messagebox.showerror("Registration Error", "Registration failed!\n\nFollowing images doesn't contain"
                        " face or Face is too small:\n\n%s"%(no_face_st))
        shutil.rmtree(path, ignore_errors=True)
    else:
        # Storing data in database
        insertData(entry_data)
        rowId=1
        if(rowId >= 0):
            messagebox.showinfo("Success", "Criminal Registered Successfully.")
            shutil.move(path, os.path.join('face_samples', entry_data["Name"]))

            # save profile pic
            profile_img_num = int(menu_var.get().split(' ')[1]) - 1
            if not os.path.isdir("profile_pics"):
                os.mkdir("profile_pics")
            cv2.imwrite("profile_pics/criminal %d.png"%rowId, img_list[profile_img_num])

            goBack()
        else:
            shutil.rmtree(path, ignore_errors=True)
            messagebox.showerror("Database Error", "Some error occured while storing data.")

## update scrollregion when all widgets are in canvas
def on_configure(event, canvas, win):
    canvas.configure(scrollregion=canvas.bbox('all'))
    canvas.itemconfig(win, width=event.width)

## Register Page ##
def getPage1():
    global active_page, left_frame, right_frame, heading, img_label
    active_page = 1
    img_label = None
    opt_menu = None
    menu_var = tk.StringVar(root)
    pages[1].lift()

    basicPageSetup(1)
    heading.configure(text="Register Criminal", bg="#3E3B3C")
    right_frame.configure(text="Enter Details", fg="white", bg="#3E3B3C")

    btn_grid = tk.Frame(left_frame, bg="#3E3B3C")
    btn_grid.pack()

    tk.Button(btn_grid, text="Select Images", command=lambda: selectMultiImage(opt_menu, menu_var), font="Arial 15 bold", bg="#000000",
           fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
           activeforeground="white").grid(row=0, column=0, padx=25, pady=25)

    # Creating Scrollable Frame
    canvas = tk.Canvas(right_frame, bg="#202d42", highlightthickness=0)
    canvas.pack(side="left", fill="both", expand="true", padx=30)
    scrollbar = tk.Scrollbar(right_frame, command=canvas.yview, width=20, troughcolor="#3E3B3C", bd=0,
                          activebackground="#3E3B3C", bg="#000000", relief="raised")
    scrollbar.pack(side="left", fill="y")

    scroll_frame = tk.Frame(canvas, bg="#3E3B3C", pady=20)
    scroll_win = canvas.create_window((0, 0), window=scroll_frame, anchor='nw')

    canvas.configure(yscrollcommand=scrollbar.set)
    canvas.bind('<Configure>', lambda event, canvas=canvas, win=scroll_win: on_configure(event, canvas, win))

    tk.Label(scroll_frame, text="* Required Fields", bg="#3E3B3C", fg="yellow", font="Arial 13 bold").pack()
    # Adding Input Fields
    input_fields = ("Name", "Father's Name", "Gender", "DOB(yyyy-mm-dd)", "Crimes Done", "Profile Image")
    ip_len = len(input_fields)
    required = [1, 1, 1, 1, 1, 1]

    entries = []
    for i, field in enumerate(input_fields):
        print()
        row = tk.Frame(scroll_frame, bg="#3E3B3C")
        row.pack(side="top", fill="x", pady=15)

        label = tk.Text(row, width=20, height=1, bg="#3E3B3C", fg="#ffffff", font="Arial 13", highlightthickness=0, bd=0)
        label.insert("insert", field)
        label.pack(side="left")

        if(required[i] == 1):
            label.tag_configure("star", foreground="yellow", font="Arial 13 bold")
            label.insert("end", "  *", "star")
        label.configure(state="disabled")

        if(i != ip_len-1):
            ent = tk.Entry(row, font="Arial 13", selectbackground="#90ceff")
            ent.pack(side="right", expand="true", fill="x", padx=10)
            entries.append((field, ent))
        else:
            menu_var.set("Image 1")
            choices = ["Image 1"]
            opt_menu = tk.OptionMenu(row, menu_var, *choices)
            opt_menu.pack(side="right", fill="x", expand="true", padx=10)
            opt_menu.configure(font="Arial 13", bg="#000000", fg="white", bd=0, highlightthickness=0, activebackground="#3E3B3C")
            menu = opt_menu.nametowidget(opt_menu.menuname)
            menu.configure(font="Arial 13", bg="white", activebackground="#90ceff", bd=0)

    # print(entries)

    tk.Button(scroll_frame, text="Register", command=lambda: register(entries, required, menu_var), font="Arial 15 bold",
           bg="#000000", fg="white", pady=10, padx=30, bd=0, highlightthickness=0, activebackground="#3E3B3C",
           activeforeground="white").pack(pady=25)

def showCriminalProfile(name):
    top = tk.Toplevel(bg="#202d42")
    top.title("Criminal Profile")
    top.geometry("1500x900+%d+%d"%(root.winfo_x()+10, root.winfo_y()+10))

    tk.Label(top, text="Criminal Profile", fg="white", bg="#202d42", font="Arial 20 bold", pady=10).pack()

    content = tk.Frame(top, bg="#202d42", pady=20)
    content.pack(expand="true", fill="both")
    content.grid_columnconfigure(0, weight=3, uniform="group1")
    content.grid_columnconfigure(1, weight=5, uniform="group1")
    content.grid_rowconfigure(0, weight=1)

    (id, crim_data) = retrieveData(name)

    path = os.path.join("profile_pics", "criminal %d.png"%id)
    profile_img = cv2.imread(path)

    profile_img = cv2.resize(profile_img, (500, 500))
    img = cv2.cvtColor(profile_img, cv2.COLOR_BGR2RGB)
    img = Image.fromarray(img)
    img = ImageTk.PhotoImage(img)
    img_label = tk.Label(content, image=img, bg="#202d42")
    img_label.image = img
    img_label.grid(row=0, column=0)

    info_frame = tk.Frame(content, bg="#202d42")
    info_frame.grid(row=0, column=1, sticky='w')

    for i, item in enumerate(crim_data.items()):
        tk.Label(info_frame, text=item[0], pady=15, fg="yellow", font="Arial 15 bold", bg="#202d42").grid(row=i, column=0, sticky='w')
        tk.Label(info_frame, text=":", fg="yellow", padx=50, font="Arial 15 bold", bg="#202d42").grid(row=i, column=1)
        val = "---" if (item[1]=="") else item[1]
        tk.Label(info_frame, text=val.capitalize(), fg="white", font="Arial 15", bg="#202d42").grid(row=i, column=2, sticky='w')

def startRecognition():
    global img_read, img_label

    if(img_label == None):
        messagebox.showerror("Error", "No image selected. ")
        return

    crims_found_labels = []
    for wid in right_frame.winfo_children():
        wid.destroy()

    frame = cv2.flip(img_read, 1, 0)
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    face_coords = detect_faces(gray_frame)

    if (len(face_coords) == 0):
        messagebox.showerror("Error", "Image doesn't contain any face or face is too small.")
    else:
        (model, names) = train_model()
        print('Training Successful. Detecting Faces')
        (frame, recognized) = recognize_face(model, frame, gray_frame, face_coords, names)

        img_size = left_frame.winfo_height() - 40
        frame = cv2.flip(frame, 1, 0)
        showImage(frame, img_size)

        if (len(recognized) == 0):
            messagebox.showerror("Error", "No criminal recognized.")
            return

        for i, crim in enumerate(recognized):
            crims_found_labels.append(tk.Label(right_frame, text=crim[0], bg="orange",
                                            font="Arial 15 bold", pady=20))
            crims_found_labels[i].pack(fill="x", padx=20, pady=10)
            crims_found_labels[i].bind("<Button-1>", lambda e, name=crim[0]:showCriminalProfile(name))

def selectImage():
    global left_frame, img_label, img_read
    for wid in right_frame.winfo_children():
        wid.destroy()

    filetype = [("images", "*.jpg *.jpeg *.png")]
    path = filedialog.askopenfilename(title="Choose a image", filetypes=filetype)

    if(len(path) > 0):
        img_read = cv2.imread(path)

        img_size =  left_frame.winfo_height() - 40
        showImage(img_read, img_size)

## Detection Page ##
def getPage2():
    global active_page, left_frame, right_frame, img_label, heading
    img_label = None
    active_page = 2
    pages[2].lift()

    basicPageSetup(2)
    heading.configure(text="Detect Criminal")
    right_frame.configure(text="Detected Criminals", fg="white")

    btn_grid = tk.Frame(left_frame, bg="#3E3B3C")
    btn_grid.pack()

    tk.Button(btn_grid, text="Select Image", command=selectImage, font="Arial 15 bold", padx=20, bg="#000000",
            fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
            activeforeground="white").grid(row=0, column=0, padx=25, pady=25)
    tk.Button(btn_grid, text="Recognize", command=startRecognition, font="Arial 15 bold", padx=20, bg="#000000",
           fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
           activeforeground="white").grid(row=0, column=1, padx=25, pady=25)

# def path_leaf(path):
#     head,tail = ntpath.split(path)

def videoLoop(path,model, names):
    p=path
    q=ntpath.basename(p)
    filenam, file_extension = os.path.splitext(q)
    # print(filename)
    global thread_event, left_frame, webcam, img_label
    start=time.time()
    webcam = cv2.VideoCapture(p)
    old_recognized = []
    crims_found_labels = []
    times = []
    img_label = None
    field=['S.No.', 'Name', 'Time']
    g=filenam+'.csv'
    # filename = "g.csv"
    filename = g
    # with open('people.csv', 'w', ) as csvfile:
    # peoplewriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
    # os.path.join(path, vid.split('.')[0]+'_'+str(count)+'.png'
    num=0
    try:
        # with open('people_Details.csv', 'w', ) as csvfile:
        with open(filename, 'w') as csvfile:
            # peoplewriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(field)
            while not thread_event.is_set():

                # Loop until the camera is working

                    while (True):
                        # Put the image from the webcam into 'frame'
                        (return_val, frame) = webcam.read()
                        if (return_val == True):
                            break
                        # else:
                        #     print("Failed to open webcam. Trying again...")

                    # Flip the image (optional)
                    frame = cv2.flip(frame, 1, 0)
                    # Convert frame to grayscale
                    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

                    # Detect Faces
                    face_coords = detect_faces(gray_frame)
                    (frame, recognized) = recognize_face(model, frame, gray_frame, face_coords, names)

                    # Recognize Faces
                    recog_names = [item[0] for item in recognized]
                    if(recog_names != old_recognized):
                        for wid in right_frame.winfo_children():
                            wid.destroy()
                        del(crims_found_labels[:])

                        for i, crim in enumerate(recognized):
                            num+=1
                            x=time.time()-start
                            crims_found_labels.append(tk.Label(right_frame, text=crim[0], bg="orange",
                                                            font="Arial 15 bold", pady=20))
                            crims_found_labels[i].pack(fill="x", padx=20, pady=10)
                            crims_found_labels[i].bind("<Button-1>", lambda e, name=crim[0]: showCriminalProfile(name))
                            y=crim[0]
                            print(x,y)
                            arr = [num,y,x]
                            # peoplewriter.writerow(arr)
                            csvwriter.writerow(arr)

                            # print('hello')
                        old_recognized = recog_names

                    # Display Video stream
                    img_size = min(left_frame.winfo_width(), left_frame.winfo_height()) - 20

                    showImage(frame, img_size)

    except RuntimeError:
        print("[INFO]Caught Runtime Error")
    except tk.TclError:
        print("[INFO]Caught Tcl Error")

# video surveillance Page ##
def getPage4(path):
    p=path
    # print(p)
    global active_page, video_loop, left_frame, right_frame, thread_event, heading
    active_page = 4
    pages[4].lift()

    basicPageSetup(4)
    heading.configure(text="Video Surveillance")
    right_frame.configure(text="Detected Criminals")
    left_frame.configure(pady=40)

    btn_grid = tk.Frame(right_frame, bg="#3E3B3C")
    btn_grid.pack()

    (model, names) = train_model()
    print('Training Successful. Detecting Faces')

    thread_event = threading.Event()
    thread = threading.Thread(target=videoLoop, args=(p,model, names))
    thread.start()

def getPage3():
    global active_page, video_loop, left_frame, right_frame, thread_event, heading
    active_page = 3
    pages[3].lift()

    basicPageSetup(3)
    heading.configure(text="Video Surveillance")

    btn_grid = tk.Frame(left_frame,bg="#3E3B3C")
    btn_grid.pack()

    tk.Button(btn_grid, text="Select Video", command=selectvideo, font="Arial 15 bold", padx=20, bg="#000000",
                fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
                activeforeground="white").grid(row=0, column=0, padx=25, pady=25)

    # tk.Button(btn_grid, text="Recognize", command=getPage3(), font="Arial 15 bold", padx=20, bg="#000000",
    #        fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
    #        activeforeground="white").grid(row=0, column=1, padx=25, pady=25)

def selectvideo():
    global left_frame, img_label, img_read
    for wid in right_frame.winfo_children():
        wid.destroy()

    filetype = [("video", "*.mp4 *.mkv")]
    path = filedialog.askopenfilename(title="Choose a video", filetypes=filetype)
    p=''
    p=path

    if(len(path) > 0):
        # vid_read = cv2.imread(path)
        # print(vid_read)
        getPage4(p)
        # img_read = cv2.imread(path)

    #     img_size =  left_frame.winfo_height() - 40
    #     showImage(img_read, img_size)

# def getPage3():
#     global active_page, left_frame, right_frame, img_label, heading
#     img_label = None
#     active_page = 2
#     pages[2].lift()

#     basicPageSetup(2)
#     heading.configure(text="Video Surveillance")
#     right_frame.configure(text="Detected Criminals")

#     btn_grid = tk.Frame(left_frame, bg="#3E3B3C")
#     btn_grid.pack()

#     tk.Button(btn_grid, text="Select video", command=selectvideo, font="Arial 15 bold", padx=20, bg="#000000",
#             fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
#             activeforeground="white").grid(row=0, column=0, padx=25, pady=25)
#     tk.Button(btn_grid, text="Recognize", command=startRecognition, font="Arial 15 bold", padx=20, bg="#000000",
#            fg="white", pady=10, bd=0, highlightthickness=0, activebackground="#3E3B3C",
#            activeforeground="white").grid(row=0, column=1, padx=25, pady=25)

def selectvideo1():
    # global left_frame, img_label, img_read
    # for wid in right_frame.winfo_children():
    #     wid.destroy()

    filetype = [("video", "*.mp4 *.mkv")]
    path = filedialog.askopenfilename(title="Choose a video", filetypes=filetype)
    p=''
    p=path

    if(len(path) > 0):
        # vid_read = cv2.imread(path)
        # print(vid_read)
       detect(p)

######################################## Home Page ####################################
tk.Label(pages[0], text="Face Recognition System for Criminal Detection", fg="black", bg="#3E3B3C",
      font="Arial 25 bold", pady=30).pack()

logo = tk.PhotoImage(file = r"C:\Users\hp\Documents\GitHub\Face-Recognition-For-Criminal-Detection-GUi\img\logo2.png")
tk.Label(pages[0], image=logo, bg="#3E3B3C").pack(side='left')

btn_frame = tk.Frame(pages[0], bg="#3E3B3C", pady=30)
btn_frame.pack()

tk.Button(btn_frame, text="Input Video", command=selectvideo1)
tk.Button(btn_frame, text="Add Criminal Details", command=getPage1)
tk.Button(btn_frame, text="Image Surveillance", command=getPage2)
tk.Button(btn_frame, text="Video Surveillance", command=getPage3)

for btn in btn_frame.winfo_children():
    btn.configure(font="Arial 20", width=17, bg="#000000", fg="white",
        pady=15, bd=0, highlightthickness=0, activebackground="#3E3B3C", activeforeground="white")
    btn.pack(pady=30)

pages[0].lift()
root.mainloop()


text:
"""
파라미터 최적화 알고리즘
    Adam(Adaptive Moment estimative)
        AdaGrad + Momentum 알고리즘
        t: timestamp. 반복할 때마다 증가하는 숫자. update 메소드가 호출될 때마다 +1
        beta1:

"""
import matplotlib.pyplot as plt
import numpy as np
from ch06.ex01_matplot3d import fn_derivative, fn

class Adam:
    def __init__(self, lr=0.01):
        self.lr = lr  # 학습률
        self.t = 0
        self.m = dict()
        self.v = dict()
        self.beta_1 = 0.9
        self.beta_2 = 0.999
        self.etha = 1e-8

    def update(self, params, gradients):
        self.t += 1
        if not self.m:
            for key in params:
                self.m[key] = np.zeros_like(params[key])
                self.v[key] = np.zeros_like(params[key])
        else:
            for key in params:
                self.m[key] = self.beta_1 * self.m[key] + (1 - self.beta_1) * gradients[key]
                self.v[key] = self.beta_2 * self.v[key] + (1 - self.beta_2) * gradients[key] * gradients[key]
                m_hat = self.m[key] / (1 - self.beta_1 ** self.t)
                v_hat = self.v[key] / (1 - self.beta_2 ** self.t)
                params[key] -= self.lr * m_hat / np.sqrt(v_hat + self.etha)

if __name__ == '__main__':
    adam = Adam(0.1)
    params = {'x': -7., 'y': 2.}
    gradients = {'x': 0., 'y': 0.}
    x_history = []
    y_history = []
    for i in range(100):
        x_history.append(params['x'])
        y_history.append(params['y'])
        gradients['x'], gradients['y'] = fn_derivative(params['x'], params['y'])
        adam.update(params, gradients)

    for x, y in zip(x_history, y_history):
        print(f'({x}, {y})')

    # f(x, y) 함수를 등고선으로 표현
    x = np.linspace(-10, 10, 200)
    y = np.linspace(-5, 5, 200)
    X, Y = np.meshgrid(x, y)
    Z = fn(X, Y)

    mask = Z > 7
    Z[mask] = 0

    plt.contour(X, Y, Z, 10)
    plt.title('Adam')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.axis('equal')

    plt.plot(x_history, y_history, 'o-', color='red')
    plt.show()


text:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2019 Albert Berahas, Majid Jahani, Martin Takáč
#
# All Rights Reserved.
#
# Authors: Albert Berahas, Majid Jahani, Martin Takáč
#
# Please cite:
#
#   A. S. Berahas, M. Jahani, and M. Takáč, "Quasi-Newton Methods for
#   Deep Learning: Forget the Past, Just Sample." (2019). Lehigh University.
#   http://arxiv.org/abs/1901.09997
# ==========================================================================

import numpy as np
import random
from numpy import linalg as LA
import math

# ==========================================================================
def CG_Steinhaug_matFree(epsTR, g , deltak, S,Y,nv):
  """
  The following function is used for sloving the trust region subproblem
  by utilizing "CG_Steinhaug" algorithm discussed in
  Nocedal, J., & Wright, S. J. (2006). Nonlinear Equations (pp. 270-302). Springer New York.;
  moreover, for Hessian-free implementation, we used the compact form of Hessian
  approximation discussed in Byrd, Richard H., Jorge Nocedal, and Robert B. Schnabel.
  "Representations of quasi-Newton matrices and their use in limited memory methods."
  Mathematical Programming 63.1-3 (1994): 129-156
  """
  zOld = np.zeros((nv,1))
  rOld = g
  dOld = -g
  trsLoop = 1e-12
  if LA.norm(rOld) < epsTR:
    return zOld
  flag = True
  pk= np.zeros((nv,1))

# for Hessfree
  L = np.zeros((Y.shape[1],Y.shape[1]))
  for ii in xrange(Y.shape[1]):
     for jj in range(0,ii):
            L[ii,jj] = S[:,ii].dot(Y[:,jj])

  tmp = np.sum((S * Y),axis=0)

  D = np.diag(tmp)
  M = (D + L + L.T)
  Minv = np.linalg.inv(M)

  while flag:

    ################
    tmp1 = np.matmul(Y.T,dOld)
    tmp2 = np.matmul(Minv,tmp1)
    Bk_d = np.matmul(Y,tmp2)

    ################

    if dOld.T.dot(Bk_d) < trsLoop:
      tau = rootFinder(LA.norm(dOld)**2, 2*zOld.T.dot(dOld), (LA.norm(zOld)**2 - deltak**2))
      pk = zOld + tau*dOld
      flag = False
      break
    alphaj = rOld.T.dot(rOld) / (dOld.T.dot(Bk_d))
    zNew = zOld +alphaj*dOld

    if LA.norm(zNew) >= deltak:
      tau = rootFinder(LA.norm(dOld)**2, 2*zOld.T.dot(dOld), (LA.norm(zOld)**2 - deltak**2))
      pk = zOld + tau*dOld
      flag = False
      break
    rNew = rOld + alphaj*Bk_d

    if LA.norm(rNew) < epsTR:
      pk = zNew
      flag = False
      break
    betajplus1 = rNew.T.dot(rNew) /(rOld.T.dot(rOld))
    dNew = -rNew + betajplus1*dOld

    zOld = zNew
    dOld = dNew
    rOld = rNew
  return pk

# ==========================================================================
def rootFinder(a,b,c):
  """return the root of (a * x^2) + b*x + c =0"""
  r = b**2 - 4*a*c

  if r > 0:
      num_roots = 2
      x1 = ((-b) + np.sqrt(r))/(2*a+0.0)
      x2 = ((-b) - np.sqrt(r))/(2*a+0.0)
      x = max(x1,x2)
      if x>=0:
        return x
      else:
        print "no positive root!"
  elif r == 0:
      num_roots = 1
      x = (-b) / (2*a+0.0)
      if x>=0:
        return x
      else:
        print "no positive root!"
  else:
      print("No roots")

def L_BFGS_two_loop_recursion(g_k,S,Y,k,mmr,gamma_k,nv):
  """
  The following function returns the serach direction based
  on LBFGS two loop recursion discussed in
  Nocedal, J., & Wright, S. J. (2006). Nonlinear Equations (pp. 270-302). Springer New York.
  """
#   idx = min(k,mmr)
  idx = min(S.shape[1],mmr)
  rho = np.zeros((idx,1))

  theta = np.zeros((idx,1))
  q = g_k
  for i in xrange(idx):
    rho[idx-i-1] = 1/ S[:,idx-i-1].reshape(nv,1).T.dot(Y[:,idx-i-1].reshape(nv,1))
    theta[idx-i-1] =(rho[idx-i-1])*(S[:,idx-i-1].reshape(nv,1).T.dot(q))
    q = q - theta[idx-i-1]*Y[:,idx-i-1].reshape(nv,1)

  r = gamma_k*q
  for j in xrange(idx):
    beta = (rho[j])*(Y[:,j].reshape(nv,1).T.dot(r))
    r = r + S[:,j].reshape(nv,1)*(theta[j] - beta)

  return r

max_stars_repo_name: OptMLGroup/SQN

max_issues_repo_name: OptMLGroup/SQN

max_forks_repo_name: OptMLGroup/SQN

reason: import numpy,from numpy


text:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# File: utils_loc.py

# Written by Junsuk Choe <skykite@yonsei.ac.kr>
# Function Code for visualizing heatmap of learned CNNs.
# Including CAM and Grad-CAM.

import cv2
import sys
import numpy as np
import os
import tensorflow as tf

from tensorpack import *
from tensorpack.tfutils.symbolic_functions import *
from tensorpack.utils import viz
from tensorpack.utils.fs import mkdir_p

from utils import get_data
from dataflow import Imagenet, CUB200

def cam(model, option, gradcam=False, flag=None):
    model_file = option.load
    data_dir = option.data
    if option.imagenet:
        valnum = 50000
    elif option.cub:
        valnum = 5794

    ds = get_data('val', option)

    pred_config = PredictConfig(
        model=model,
        session_init=get_model_loader(model_file),
        input_names=['input', 'label','bbox'],
        output_names=
            ['wrong-top1', 'top5', 'actmap', 'grad'],
        return_input=True
    )

    if option.imagenet:
        meta = Imagenet.ImagenetMeta(dir=option.data). \
                get_synset_words_1000(option.dataname)
        meta_labels = Imagenet.ImagenetMeta(dir=option.data). \
                get_synset_1000(option.dataname)
    elif option.cub:
        meta = CUB200.CUB200Meta(dir=option.data). \
                get_synset_words_1000(option.dataname)
        meta_labels = CUB200.CUB200Meta(dir=option.data). \
                get_synset_1000(option.dataname)
    pred = SimpleDatasetPredictor(pred_config, ds)

    cnt = 0
    cnt_false = 0
    hit_known = 0
    hit_top1 = 0

    index = int(option.locthr*100)

    if option.camrelu:

        dirname = os.path.join(
            'train_log',option.logdir,'result_camrelu',str(index))
    else:

        dirname = os.path.join(
            'train_log',option.logdir,'result_norelu',str(index))

    if not os.path.isdir(dirname):
        mkdir_p(dirname)

    for inp, outp in pred.get_result():
        images, labels, bbox = inp

        if gradcam:
            wrongs, top5, convmaps, grads_val = outp
            batch = wrongs.shape[0]
            if option.chlast:
                NUMBER,HEIGHT,WIDTH,CHANNEL = np.shape(convmaps)
            else:
                NUMBER,CHANNEL,HEIGHT,WIDTH = np.shape(convmaps)
            if not option.chlast:
                grads_val = np.transpose(grads_val, [0,2,3,1])
            W = np.mean(grads_val, axis=(1,2))
            if option.chlast:
                convmaps = np.transpose(convmaps, [0,3,1,2])
        else:
            wrongs, top5, convmaps, W = outp
            batch = wrongs.shape[0]
            NUMBER,CHANNEL,HEIGHT,WIDTH = np.shape(convmaps)

        for i in range(batch):
            gxa = int(bbox[i][0][0])
            gya = int(bbox[i][0][1])
            gxb = int(bbox[i][1][0])
            gyb = int(bbox[i][1][1])

            # generating heatmap
            weight = W[i]   # c x 1

            convmap = convmaps[i, :, :, :]  # c x h x w
            mergedmap = np.matmul(weight, convmap.reshape((CHANNEL, -1))). \
                            reshape(HEIGHT, WIDTH)
            if option.camrelu: mergedmap = np.maximum(mergedmap, 0)
            mergedmap = cv2.resize(mergedmap,
                            (option.final_size, option.final_size))
            heatmap = viz.intensity_to_rgb(mergedmap, normalize=True)
            blend = images[i] * 0.5 + heatmap * 0.5

            # initialization for boundary box
            bbox_img = images[i]
            bbox_img = bbox_img.astype('uint8')
            heatmap = heatmap.astype('uint8')
            blend = blend.astype('uint8')

            # thresholding heatmap
            # For computation efficiency, we revise this part by directly using mergedmap.
            gray_heatmap = cv2.cvtColor(heatmap,cv2.COLOR_RGB2GRAY)
            th_value = np.max(gray_heatmap)*option.locthr

            _, thred_gray_heatmap = \
                        cv2.threshold(gray_heatmap,int(th_value),
                                                255,cv2.THRESH_TOZERO)
            _, contours, _ = \
                        cv2.findContours(thred_gray_heatmap,
                                cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

            # calculate bbox coordinates
            rect = []
            for c in contours:
                x, y, w, h = cv2.boundingRect(c)
                rect.append([x,y,w,h])

            if rect == []:
                estimated_box = [0,0,1,1] #dummy
            else:
                x,y,w,h = large_rect(rect)
                estimated_box = [x,y,x+w,y+h]
                cv2.rectangle(bbox_img, (x, y), (x + w, y + h), (0, 255, 0), 2)

            cv2.rectangle(bbox_img, (gxa, gya), (gxb, gyb), (0, 0, 255), 2)
            gt_box = [gxa,gya,gxb,gyb]

            IOU_ = bb_IOU(estimated_box, gt_box)

            if IOU_ > 0.5 or IOU_ == 0.5:
                hit_known = hit_known + 1

            if (IOU_ > 0.5 or IOU_ == 0.5) and not wrongs[i]:
                hit_top1 = hit_top1 + 1

            if wrongs[i]:
                cnt_false += 1

            concat = np.concatenate((bbox_img, heatmap, blend), axis=1)
            classname = meta[meta_labels[labels[i]]].split(',')[0]

            if cnt < 500:
                if option.camrelu:
                    cv2.imwrite(
                        'train_log/{}/result_camrelu/{}/cam{}-{}.jpg'. \
                            format(option.logdir, index, cnt, classname),
                            concat)
                else:

                    cv2.imwrite(
                        'train_log/{}/result_norelu/{}/cam{}-{}.jpg'. \
                            format(option.logdir, index, cnt, classname),
                            concat)

            cnt += 1
            if cnt == valnum:
                if option.camrelu:

                    fname = 'train_log/{}/result_camrelu/{}/Loc.txt'. \
                            format(option.logdir, index)
                else:

                    fname = 'train_log/{}/result_norelu/{}/Loc.txt'. \
                            format(option.logdir, index)
                f = open(fname, 'w')
                acc_known = hit_known/cnt
                acc_top1 = hit_top1/cnt
                top1_acc = 1 - cnt_false / (cnt)
                if option.camrelu: print ("\nGRADCAM (use relu)")
                else: print ("\nCAM (do not use relu)")
                print ('Flag: {}\nCAM Threshold: {}\nGT-known Loc: {} \
                        \nTop-1 Loc: {}\nTop-1 Acc: {}' \
                        .format(flag,option.locthr,acc_known,acc_top1,top1_acc))
                line = 'GT-known Loc: {}\nTop-1 Loc: {}\nTop-1 Acc: {}'. \
                        format(acc_known,acc_top1,top1_acc)
                f.write(line)
                f.close()
                return

def bb_IOU(boxA, boxB):

    xA = max(boxA[0], boxB[0])
    yA = max(boxA[1], boxB[1])
    xB = min(boxA[2], boxB[2])
    yB = min(boxA[3], boxB[3])

    # compute the area of intersection rectangle
    interArea = (xB - xA + 1) * (yB - yA + 1)

    # compute the area of both the prediction and ground-truth
    # rectangles
    boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
    boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)

    # compute the intersection over union by taking the intersection
    # area and dividing it by the sum of prediction + ground-truth
    # areas - the interesection area
    iou = interArea / float(boxAArea + boxBArea - interArea)

    # return the intersection over union value
    return iou

def large_rect(rect):
    # find largest recteangles
    large_area = 0
    target = 0
    for i in range(len(rect)):
        area = rect[i][2]*rect[i][3]
        if large_area < area:
            large_area = area
            target = i

    x = rect[target][0]
    y = rect[target][1]
    w = rect[target][2]
    h = rect[target][3]

    return x, y, w, h

max_stars_repo_name: Qin-Folks/ADL

max_issues_repo_name: Qin-Folks/ADL

max_forks_repo_name: Qin-Folks/ADL