text:
"""Nuclide module.

Contains the per-nuclide components of a depletion chain.
"""

import bisect
from collections.abc import Mapping
from collections import namedtuple, defaultdict
from warnings import warn
from numbers import Real
try:
    import lxml.etree as ET
except ImportError:
    import xml.etree.ElementTree as ET

from numpy import empty, searchsorted

from openmc.checkvalue import check_type

__all__ = [
    "DecayTuple", "ReactionTuple", "Nuclide", "FissionYield",
    "FissionYieldDistribution"]

DecayTuple = namedtuple('DecayTuple', 'type target branching_ratio')
DecayTuple.__doc__ = """\
Decay mode information

Parameters
----------
type : str
    Type of the decay mode, e.g., 'beta-'
target : str or None
    Nuclide resulting from decay. A value of ``None`` implies the
    target does not exist in the currently configured depletion
    chain
branching_ratio : float
    Branching ratio of the decay mode

"""
try:
    DecayTuple.type.__doc__ = None
    DecayTuple.target.__doc__ = None
    DecayTuple.branching_ratio.__doc__ = None
except AttributeError:
    # Can't set __doc__ on properties on Python 3.4
    pass

ReactionTuple = namedtuple('ReactionTuple', 'type target Q branching_ratio')
ReactionTuple.__doc__ = """\
Transmutation reaction information

Parameters
----------
type : str
    Type of the reaction, e.g., 'fission'
target : str or None
    Nuclide resulting from reaction. A value of ``None``
    implies either no single target, e.g. from fission,
    or that the target nuclide is not considered
    in the current depletion chain
Q : float
    Q value of the reaction in [eV]
branching_ratio : float
    Branching ratio of the reaction

"""
try:
    ReactionTuple.type.__doc__ = None
    ReactionTuple.target.__doc__ = None
    ReactionTuple.Q.__doc__ = None
    ReactionTuple.branching_ratio.__doc__ = None
except AttributeError:
    pass

class Nuclide:
    """Decay modes, reactions, and fission yields for a single nuclide.

    Parameters
    ----------
    name : str, optional
        GND name of this nuclide, e.g. ``"He4"``, ``"Am242_m1"``

    Attributes
    ----------
    name : str or None
        Name of nuclide.
    half_life : float or None
        Half life of nuclide in [s].
    decay_energy : float
        Energy deposited from decay in [eV].
    n_decay_modes : int
        Number of decay pathways.
    decay_modes : list of openmc.deplete.DecayTuple
        Decay mode information. Each element of the list is a named tuple with
        attributes 'type', 'target', and 'branching_ratio'.
    n_reaction_paths : int
        Number of possible reaction pathways.
    reactions : list of openmc.deplete.ReactionTuple
        Reaction information. Each element of the list is a named tuple with
        attribute 'type', 'target', 'Q', and 'branching_ratio'.
    yield_data : FissionYieldDistribution or None
        Fission product yields at tabulated energies for this nuclide. Can be
        treated as a nested dictionary ``{energy: {product: yield}}``
    yield_energies : tuple of float or None
        Energies at which fission product yields exist
    """

    def __init__(self, name=None):
        # Information about the nuclide
        self.name = name
        self.half_life = None
        self.decay_energy = 0.0

        # Decay paths
        self.decay_modes = []

        # Reaction paths
        self.reactions = []

        # Neutron fission yields, if present
        self._yield_data = None

    @property
    def n_decay_modes(self):
        return len(self.decay_modes)

    @property
    def n_reaction_paths(self):
        return len(self.reactions)

    @property
    def yield_data(self):
        if self._yield_data is None:
            return None
        return self._yield_data

    @yield_data.setter
    def yield_data(self, fission_yields):
        if fission_yields is None:
            self._yield_data = None
        else:
            check_type("fission_yields", fission_yields, Mapping)
            if isinstance(fission_yields, FissionYieldDistribution):
                self._yield_data = fission_yields
            else:
                self._yield_data = FissionYieldDistribution(fission_yields)

    @property
    def yield_energies(self):
        if self._yield_data is None:
            return None
        return self.yield_data.energies

    def add_decay_mode(self, type, target, branching_ratio):
        """Add decay mode to the nuclide

        Parameters
        ----------
        type : str
            Type of the decay mode, e.g., 'beta-'
        target : str or None
            Nuclide resulting from decay. A value of ``None`` implies the
            target does not exist in the currently configured depletion
            chain
        branching_ratio : float
            Branching ratio of the decay mode

        """
        self.decay_modes.append(
            DecayTuple(type, target, branching_ratio)
        )

    def add_reaction(self, type, target, Q, branching_ratio):
        """Add transmutation reaction to the nuclide

        Parameters
        ----------
        type : str
            Type of the reaction, e.g., 'fission'
        target : str or None
            Nuclide resulting from reaction. A value of ``None``
            implies either no single target, e.g. from fission,
            or that the target nuclide is not considered
            in the current depletion chain
        Q : float
            Q value of the reaction in [eV]
        branching_ratio : float
            Branching ratio of the reaction

        """
        self.reactions.append(
            ReactionTuple(type, target, Q, branching_ratio)
        )

    @classmethod
    def from_xml(cls, element, root=None, fission_q=None):
        """Read nuclide from an XML element.

        Parameters
        ----------
        element : xml.etree.ElementTree.Element
            XML element to read nuclide data from
        root : xml.etree.ElementTree.Element, optional
            Root XML element for chain file (only used when fission product
            yields are borrowed from another parent)
        fission_q : None or float
            User-supplied fission Q value [eV].
            Will be read from the element if not given

        Returns
        -------
        nuc : openmc.deplete.Nuclide
            Instance of a nuclide

        """
        nuc = cls()
        nuc.name = element.get('name')

        # Check for half-life
        if 'half_life' in element.attrib:
            nuc.half_life = float(element.get('half_life'))
            nuc.decay_energy = float(element.get('decay_energy', '0'))

        # Check for decay paths
        for decay_elem in element.iter('decay'):
            d_type = decay_elem.get('type')
            target = decay_elem.get('target')
            if target is not None and target.lower() == "nothing":
                target = None
            branching_ratio = float(decay_elem.get('branching_ratio'))
            nuc.decay_modes.append(DecayTuple(d_type, target, branching_ratio))

        # Check for reaction paths
        for reaction_elem in element.iter('reaction'):
            r_type = reaction_elem.get('type')
            Q = float(reaction_elem.get('Q', '0'))
            branching_ratio = float(reaction_elem.get('branching_ratio', '1'))

            # If the type is not fission, get target and Q value, otherwise
            # just set null values
            if r_type != 'fission':
                target = reaction_elem.get('target')
                if target is not None and target.lower() == "nothing":
                    target = None
            else:
                target = None
                if fission_q is not None:
                    Q = fission_q

            # Append reaction
            nuc.reactions.append(ReactionTuple(
                r_type, target, Q, branching_ratio))

        fpy_elem = element.find('neutron_fission_yields')
        if fpy_elem is not None:
            # Check for use of FPY from other nuclide
            parent = fpy_elem.get('parent')
            if parent is not None:
                assert root is not None
                fpy_elem = root.find(
                    './/nuclide[@name="{}"]/neutron_fission_yields'.format(parent)
                )
                if fpy_elem is None:
                    raise ValueError(
                        "Fission product yields for {0} borrow from {1}, but {1} is"
                        " not present in the chain file or has no yields.".format(
                            nuc.name, parent
                        ))
                nuc._fpy = parent

            nuc.yield_data = FissionYieldDistribution.from_xml_element(fpy_elem)

        return nuc

    def to_xml_element(self):
        """Write nuclide to XML element.

        Returns
        -------
        elem : xml.etree.ElementTree.Element
            XML element to write nuclide data to

        """
        elem = ET.Element('nuclide')
        elem.set('name', self.name)

        if self.half_life is not None:
            elem.set('half_life', str(self.half_life))
            elem.set('decay_modes', str(len(self.decay_modes)))
            elem.set('decay_energy', str(self.decay_energy))
            for mode_type, daughter, br in self.decay_modes:
                mode_elem = ET.SubElement(elem, 'decay')
                mode_elem.set('type', mode_type)
                mode_elem.set('target', daughter or "Nothing")
                mode_elem.set('branching_ratio', str(br))

        elem.set('reactions', str(len(self.reactions)))
        for rx, daughter, Q, br in self.reactions:
            rx_elem = ET.SubElement(elem, 'reaction')
            rx_elem.set('type', rx)
            rx_elem.set('Q', str(Q))
            if daughter is not None:
                rx_elem.set('target', daughter)
            if br != 1.0:
                rx_elem.set('branching_ratio', str(br))

        if self.yield_data:
            fpy_elem = ET.SubElement(elem, 'neutron_fission_yields')

            if hasattr(self, '_fpy'):
                # Check for link to other nuclide data
                fpy_elem.set('parent', self._fpy)
            else:
                energy_elem = ET.SubElement(fpy_elem, 'energies')
                energy_elem.text = ' '.join(str(E) for E in self.yield_energies)
                self.yield_data.to_xml_element(fpy_elem)

        return elem

    def validate(self, strict=True, quiet=False, tolerance=1e-4):
        """Search for possible inconsistencies

        The following checks are performed:

            1) for all non-fission reactions and decay modes,
               does the sum of branching ratios equal about one?
            2) for fission reactions, does the sum of fission yield
               fractions equal about two?

        Parameters
        ----------
        strict : bool, optional
            Raise exceptions at the first inconsistency if true.
            Otherwise mark a warning
        quiet : bool, optional
            Flag to suppress warnings and return immediately at
            the first inconsistency. Used only if
            ``strict`` does not evaluate to ``True``.
        tolerance : float, optional
            Absolute tolerance for comparisons. Used to compare computed
            value ``x`` to intended value ``y`` as::

                valid = (y - tolerance <= x <= y + tolerance)

        Returns
        -------
        valid : bool
            True if no inconsistencies were found

        Raises
        ------
        ValueError
            If ``strict`` evaluates to ``True`` and an inconistency was
            found

        See Also
        --------
        openmc.deplete.Chain.validate
        """

        msg_func = ("Nuclide {name} has {prop} that sum to {actual} "
                    "instead of {expected} +/- {tol:7.4e}").format
        valid = True

        # check decay modes
        if self.decay_modes:
            sum_br = sum(m.branching_ratio for m in self.decay_modes)
            stat = 1.0 - tolerance <= sum_br <= 1.0 + tolerance
            if not stat:
                msg = msg_func(
                    name=self.name, actual=sum_br, expected=1.0, tol=tolerance,
                    prop="decay mode branch ratios")
                if strict:
                    raise ValueError(msg)
                elif quiet:
                    return False
                warn(msg)
                valid = False

        if self.reactions:
            type_map = defaultdict(set)
            for reaction in self.reactions:
                type_map[reaction.type].add(reaction)
            for rxn_type, reactions in type_map.items():
                sum_rxn = sum(rx.branching_ratio for rx in reactions)
                stat = 1.0 - tolerance <= sum_rxn <= 1.0 + tolerance
                if stat:
                    continue
                msg = msg_func(
                    name=self.name, actual=sum_br, expected=1.0, tol=tolerance,
                    prop="{} reaction branch ratios".format(rxn_type))
                if strict:
                    raise ValueError(msg)
                elif quiet:
                    return False
                warn(msg)
                valid = False

        if self.yield_data:
            for energy, fission_yield in self.yield_data.items():
                sum_yield = fission_yield.yields.sum()
                stat = 2.0 - tolerance <= sum_yield <= 2.0 + tolerance
                if stat:
                    continue
                msg = msg_func(
                    name=self.name, actual=sum_yield,
                    expected=2.0, tol=tolerance,
                    prop="fission yields (E = {:7.4e} eV)".format(energy))
                if strict:
                    raise ValueError(msg)
                elif quiet:
                    return False
                warn(msg)
                valid = False

        return valid

class FissionYieldDistribution(Mapping):
    """Energy-dependent fission product yields for a single nuclide

    Can be used as a dictionary mapping energies and products to fission
    yields::

        >>> fydist = FissionYieldDistribution(
        ...     {0.0253: {"Xe135": 0.021}})
        >>> fydist[0.0253]["Xe135"]
        0.021

    Parameters
    ----------
    fission_yields : dict
        Dictionary of energies and fission product yields for that energy.
        Expected to be of the form ``{float: {str: float}}``. The first
        float is the energy, typically in eV, that represents this
        distribution. The underlying dictionary maps fission products
        to their respective yields.

    Attributes
    ----------
    energies : tuple
        Energies for which fission yields exist. Sorted by
        increasing energy
    products : tuple
        Fission products produced at all energies. Sorted by name.
    yield_matrix : numpy.ndarray
        Array ``(n_energy, n_products)`` where
        ``yield_matrix[g, j]`` is the fission yield of product
        ``j`` for energy group ``g``.

    See Also
    --------
    * :meth:`from_xml_element` - Construction methods
    * :class:`FissionYield` - Class used for storing yields at a given energy
    """

    def __init__(self, fission_yields):
        # mapping {energy: {product: value}}
        energies = sorted(fission_yields)

        # Get a consistent set of products to produce a matrix of yields
        shared_prod = set.union(*(set(x) for x in fission_yields.values()))
        ordered_prod = sorted(shared_prod)

        yield_matrix = empty((len(energies), len(shared_prod)))

        for g_index, energy in enumerate(energies):
            prod_map = fission_yields[energy]
            for prod_ix, product in enumerate(ordered_prod):
                yield_matrix[g_index, prod_ix] = prod_map.get(product, 0.0)
        self.energies = tuple(energies)
        self.products = tuple(ordered_prod)
        self.yield_matrix = yield_matrix

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

    def __getitem__(self, energy):
        if energy not in self.energies:
            raise KeyError(energy)
        return FissionYield(
            self.products, self.yield_matrix[self.energies.index(energy)])

    def __iter__(self):
        return iter(self.energies)

    def __repr__(self):
        return "<{} with {} products at {} energies>".format(
            self.__class__.__name__, self.yield_matrix.shape[1],
            len(self.energies))

    @classmethod
    def from_xml_element(cls, element):
        """Construct a distribution from a depletion chain xml file

        Parameters
        ----------
        element : xml.etree.ElementTree.Element
            XML element to pull fission yield data from

        Returns
        -------
        FissionYieldDistribution
        """
        all_yields = {}
        for yield_elem in element.iter("fission_yields"):
            energy = float(yield_elem.get("energy"))
            products = yield_elem.find("products").text.split()
            yields = map(float, yield_elem.find("data").text.split())
            # Get a map of products to their corresponding yield
            all_yields[energy] = dict(zip(products, yields))

        return cls(all_yields)

    def to_xml_element(self, root):
        """Write fission yield data to an xml element

        Parameters
        ----------
        root : xml.etree.ElementTree.Element
            Element to write distribution data to
        """
        for energy, yield_obj in self.items():
            yield_element = ET.SubElement(root, "fission_yields")
            yield_element.set("energy", str(energy))
            product_elem = ET.SubElement(yield_element, "products")
            product_elem.text = " ".join(map(str, yield_obj.products))
            data_elem = ET.SubElement(yield_element, "data")
            data_elem.text = " ".join(map(str, yield_obj.yields))

    def restrict_products(self, possible_products):
        """Return a new distribution with select products

        .. versionadded:: 0.12

        Parameters
        ----------
        possible_products : iterable of str
            Candidate pool of fission products. Existing products
            not contained here will not exist in the new instance

        Returns
        -------
        FissionYieldDistribution or None
            A value of None indicates no values in
            ``possible_products`` exist in :attr:`products`

        """

        overlap = set(self.products).intersection(possible_products)
        if not overlap:
            return None

        products = sorted(overlap)
        indices = searchsorted(self.products, products)

        # coerce back to dictionary to pass back to __init__
        new_yields = {}
        for ene, yields in zip(self.energies, self.yield_matrix.copy()):
            new_yields[ene] = dict(zip(products, yields[indices]))

        return type(self)(new_yields)

class FissionYield(Mapping):
    """Mapping for fission yields of a parent at a specific energy

    Separated to support nested dictionary-like behavior for
    :class:`FissionYieldDistribution`, and allowing math operations
    on a single vector of yields. Can in turn be used like a
    dictionary to fetch fission yields.
    Supports multiplication of a scalar to scale the fission
    yields and addition of another set of yields.

    Does not support resizing / inserting new products that do
    not exist.

    Parameters
    ----------
    products : tuple of str
        Sorted products for this specific distribution
    yields : numpy.ndarray
        Fission product yields for each product in ``products``

    Attributes
    ----------
    products : tuple of str
        Products for this specific distribution
    yields : numpy.ndarray
        Fission product yields for each product in ``products``

    Examples
    --------
    >>> import numpy
    >>> fy_vector = FissionYield(
    ...     ("I129", "Sm149", "Xe135"),
    ...     numpy.array((0.001, 0.0003, 0.002)))
    >>> fy_vector["Xe135"]
    0.002
    >>> new = FissionYield(fy_vector.products, fy_vector.yields.copy())
    >>> fy_vector *= 2
    >>> fy_vector["Xe135"]
    0.004
    >>> new["Xe135"]
    0.002
    >>> (new + fy_vector)["Sm149"]
    0.0009
    >>> dict(new) == {"Xe135": 0.002, "I129": 0.001, "Sm149": 0.0003}
    True
    """

    def __init__(self, products, yields):
        self.products = products
        self.yields = yields

    def __contains__(self, product):
        ix = bisect.bisect_left(self.products, product)
        return ix != len(self.products) and self.products[ix] == product

    def __getitem__(self, product):
        ix = bisect.bisect_left(self.products, product)
        if ix == len(self.products) or self.products[ix] != product:
            raise KeyError(product)
        return self.yields[ix]

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

    def __iter__(self):
        return iter(self.products)

    def items(self):
        """Return pairs of product, yield"""
        return zip(self.products, self.yields)

    def __add__(self, other):
        """Add one set of fission yields to this set, return new yields"""
        if not isinstance(other, FissionYield):
            return NotImplemented
        new = FissionYield(self.products, self.yields.copy())
        new += other
        return new

    def __iadd__(self, other):
        """Increment value from other fission yield"""
        if not isinstance(other, FissionYield):
            return NotImplemented
        self.yields += other.yields
        return self

    def __radd__(self, other):
        return self + other

    def __imul__(self, scalar):
        """Scale these fission yields by a real scalar"""
        if not isinstance(scalar, Real):
            return NotImplemented
        self.yields *= scalar
        return self

    def __mul__(self, scalar):
        """Return a new set of yields scaled by a real scalar"""
        if not isinstance(scalar, Real):
            return NotImplemented
        new = FissionYield(self.products, self.yields.copy())
        new *= scalar
        return new

    def __rmul__(self, scalar):
        return self * scalar

    def __repr__(self):
        return "<{} containing {} products and yields>".format(
            self.__class__.__name__, len(self))

    # Avoid greedy numpy operations like np.float64 * fission_yield
    # converting this to an array on the fly. Force __rmul__ and
    # __radd__. See issue #1492
    __array_ufunc__ = None


text:
<script src="app-routing.module.ts"></script>
<div class="nav-space">
  <home></home>
</div>

redpajama_set_name: RedPajamaGithub


text:
<!--
================================================================================
== Mari Ideascale Procedural Library
== Copyright (c) 2013 Jens Kafitz. All Rights Reserved.
================================================================================
== File: JK_PolySurfaceCurvature.xml
== Description: Polygon Surface curvature detection node.
================================================================================
== Author: Jens Kafitz | Mari Ideascale
== Web: www.campi3d.com
== Web: www.mari.ideascale.com
== Email: MariIdeas@campi3d.com
================================================================================
== Modified Date: January 13, 2015
================================================================================
== Redistribution and use in source and binary forms, with or without
== modification, are permitted provided that the following conditions are met:
==
== 1. Redistributions of source code must retain the above copyright
== notice, this list of conditions and the following disclaimer.
==
== 2. Redistributions in binary form must reproduce the above copyright
== notice, this list of conditions and the following disclaimer in the
== documentation and/or other materials provided with the distribution.
==
== 3. Neither the name of the copyright holder nor the names of its
== contributors may be used to endorse or promote products derived from
== this software without specific prior written permission.
==
== THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
== IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
== THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
== PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
== CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
== EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
== PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
== OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
== WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
== OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
== ADVISED OF HE POSSIBILITY OF SUCH DAMAGE.
================================================================================
-->

<Node>
    <ID>PolySurface Curvature</ID>
    <DefaultName>PolySurface Curvature</DefaultName>
    <Category>Geometry/Custom/</Category>
    <Inputs>
        <Input Name="Position"></Input>
        <Input Name="Normal"></Input>
    </Inputs>
    <Attributes>
        <!--===============================================================================================================-->
        <Attribute Name="Adjust" PrettyName="Curvature" Group="" Type="double" Logarithmic="1" Min="0" Max="1">0.1</Attribute>
        <Attribute Name="Size" PrettyName="Intensity" Group="" Type="double" Logarithmic="1" Min="0" Max="2">0.1</Attribute>
        <Attribute Name="Invert" PrettyName="Invert" Group="" Type="bool" Min="false" Max="true">false</Attribute>
        <Attribute Name="absolute" PrettyName="Hard Edged" Group="Extra Attributes" Type="bool" Min="false" Max="true">false</Attribute>
        <Attribute Name="AO" PrettyName="Attenuate with AmbientOcclusion" Group="Extra Attributes" Type="bool" Min="false" Max="true">false</Attribute>

        <!--===============================================================================================================-->

    </Attributes>
    <Contexts>
        <Context Type="NodeGraphView">
            <Inputs>
                <Input Name="Position"><Pos>100,-20</Pos></Input>
                <Input Name="Normal"><Pos>100,+20</Pos></Input>
            </Inputs>
        </Context>
        <Context Type="GLSL">
            <Shader ShaderType='Fragment'>
                <Inputs>
                    <Input Name="Position"><Default>State.Position</Default></Input>
                    <Input Name="Normal"><Default>State.Normal</Default></Input>
                </Inputs>
            </Shader>
            <Shader ShaderType='TessEvaluation'>
                <Inputs>
                    <Input Name="Position"><Default>State.Position</Default></Input>
                    <Input Name="Normal"><Default>State.Normal</Default></Input>
                </Inputs>
            </Shader>
            <Shader>
                <Body><![CDATA[

                #if defined MRI_SHADER_FRAGMENT || defined MRI_SHADER_TESS_EVALUATION

                vec3 N = #Normal;
                vec3 P = #Position;
                float AO = mix(1.0,State.AmbientOcclusion,float($AO));

                float hardEdge = float($absolute);

                float Size = AO*$Size;
                float Adjust = AO*$Adjust;

                float size_pow = (pow(10000.0,Size*Size)-1.0) + 0.0001;

                float curvN = 0.0;
                float curvP = 0.0;

                float tuneCurvature = (Adjust*size_pow);
                curvN = length(fwidth(N)) ;
                curvP = length(fwidth(P)) ;

                float mixer = clamp(curvN,0,1) / curvP;

                float curvature = clamp((mixer*tuneCurvature),0.0,1.0);
                curvature = mix(curvature,(softThreshold(0.5,0.0,curvature)),hardEdge);
                float inv_curv = 1.0 - curvature;

                float result = mix(curvature,inv_curv,float($Invert));
                result = clamp(result,0.0,1.0);

                Output = vec4(result,result,result,1.0);

                #endif

                ]]></Body>
            </Shader>
        </Context>
    </Contexts>
</Node>


text:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1.1-b02-fcs
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2008.12.04 at 02:20:17 PM IST
//

package org.apache.wink.webdav.model;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

/**
 * The supportedlock Property per the WebDAV specification [RFC
 * 4918]
 *
 *

 *    Name:       supportedlock
 *    Namespace:  DAV:
 *    Purpose:    To provide a listing of the lock capabilities supported
 *    by the resource.
 *    Description: The supportedlock property of a resource returns a
 *    listing of the combinations of scope and access types which may be
 *    specified in a lock request on the resource.  Note that the actual
 *    contents are themselves controlled by access controls so a server is
 *    not required to provide information the client is not authorized to
 *    see.
 *
 *    <!ELEMENT supportedlock (lockentry)* >
 *
 *    Example - Retrieving the supportedlock Property
 *
 *    >>Request
 *
 *    PROPFIND  /container/ HTTP/1.1
 *    Host: www.foo.bar
 *    Content-Length: xxxx
 *    Content-Type: text/xml; charset="utf-8"
 *
 *    <?xml version="1.0" encoding="utf-8" ?>
 *    <D:propfind xmlns:D="DAV:">
 *      <D:prop><D:supportedlock/></D:prop>
 *    </D:propfind>
 *
 *    >>Response
 *
 *    HTTP/1.1 207 Multi-Status
 *    Content-Type: text/xml; charset="utf-8"
 *    Content-Length: xxxx
 *
 *    <?xml version="1.0" encoding="utf-8" ?>
 *    <D:multistatus xmlns:D="DAV:">
 *      <D:response>
 *           <D:href>http://www.foo.bar/container/</D:href>
 *           <D:propstat>
 *                <D:prop>
 *                     <D:supportedlock>
 *                          <D:lockentry>
 *                               <D:lockscope><D:exclusive/></D:lockscope>
 *                               <D:locktype><D:write/></D:locktype>
 *                          </D:lockentry>
 *                          <D:lockentry>
 *                               <D:lockscope><D:shared/></D:lockscope>
 *                               <D:locktype><D:write/></D:locktype>
 *                          </D:lockentry>
 *                     </D:supportedlock>
 *                </D:prop>
 *                <D:status>HTTP/1.1 200 OK</D:status>
 *           </D:propstat>
 *      </D:response>
 *    </D:multistatus>
 *

 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"lockentry"})
@XmlRootElement(name = "supportedlock")
public class Supportedlock {

    protected List<Lockentry> lockentry;

    /**
     * Gets the value of the lockentry property.
     *

     * This accessor method returns a reference to the live list, not a
     * snapshot. Therefore any modification you make to the returned list will
     * be present inside the JAXB object. This is why there is not a
     * set method for the lockentry property.
     *

     * For example, to add a new item, do as follows:
     *
     *

     * getLockentry().add(newItem);
     *

     *

     * Objects of the following type(s) are allowed in the list
     * {@link Lockentry }
     */
    public List<Lockentry> getLockentry() {
        if (lockentry == null) {
            lockentry = new ArrayList<Lockentry>();
        }
        return this.lockentry;
    }

}


text:
define([
	'utils/warn',
	'config/namespaces',
	'render/StringFragment/_StringFragment',
	'render/DomFragment/Element/shared/getMatchingStaticNodes',
	'circular'
], function (
	warn,
	namespaces,
	StringFragment,
	getMatchingStaticNodes,
	circular
) {

	'use strict';

	var DomFragment, updateCss, updateScript;

	circular.push( function () {
		DomFragment = circular.DomFragment;
	});

	updateCss = function () {
		var node = this.node, content = this.fragment.toString();

		if ( node.styleSheet ) {
		    node.styleSheet.cssText = content;
		} else {

		    while ( node.hasChildNodes() ) {
		        node.removeChild( node.firstChild );
		    }

		    node.appendChild( document.createTextNode(content) );
		}

	};

	updateScript = function () {
		if ( !this.node.type || this.node.type === 'text/javascript' ) {
			warn( 'Script tag was updated. This does not cause the code to be re-evaluated!' );
			// As it happens, we ARE in a position to re-evaluate the code if we wanted
			// to - we could eval() it, or insert it into a fresh (temporary) script tag.
			// But this would be a terrible idea with unpredictable results, so let's not.
		}

		this.node.text = this.fragment.toString();
	};

	return function appendElementChildren ( element, node, descriptor, docFrag ) {
		// Special case - script and style tags
		if ( element.lcName === 'script' || element.lcName === 'style' ) {
			element.fragment = new StringFragment({
				descriptor:   descriptor.f,
				root:         element.root,
				owner:        element
			});

			if ( docFrag ) {
				if ( element.lcName === 'script' ) {
					element.bubble = updateScript;
					element.node.text = element.fragment.toString(); // bypass warning initially
				} else {
					element.bubble = updateCss;
					element.bubble();
				}
			}

			return;
		}

		if ( typeof descriptor.f === 'string' && ( !node || ( !node.namespaceURI || node.namespaceURI === namespaces.html ) ) ) {
			// great! we can use innerHTML
			element.html = descriptor.f;

			if ( docFrag ) {
				node.innerHTML = element.html;

				// Update live queries, if applicable
				element.matchingStaticNodes = {}; // so we can remove matches made with querySelectorAll at teardown time
				updateLiveQueries( element );
			}
		}

		else {
			element.fragment = new DomFragment({
				descriptor:    descriptor.f,
				root:          element.root,
				pNode:         node,
				owner:         element,
				pElement:      element,
			});

			if ( docFrag ) {
				node.appendChild( element.fragment.docFrag );
			}
		}
	};

	function updateLiveQueries ( element ) {
		var instance, liveQueries, node, selector, query, matchingStaticNodes, i;

		node = element.node;
		instance = element.root;

		do {
			liveQueries = instance._liveQueries;

			i = liveQueries.length;
			while ( i-- ) {
				selector = liveQueries[i];
				query = liveQueries[ selector ];

				matchingStaticNodes = getMatchingStaticNodes( element, selector );
				query.push.apply( query, matchingStaticNodes );
			}
		} while ( instance = instance._parent );
	}

});


text:
/**
 * Created by ericwang on 20/06/2016.
 */
export default class fgpWidgetSpan {

    constructor() {
        this.restrict = 'E';
        this.scope = {};
    }

    template(scope, element) {
        return '

' +
            '
';
    }

    controller($scope, $element) {

        var element_id = $element.attr("id");
        var widgetData = null;
        $scope.$emit('fetchWidgetMetadataEvent', {
            id: element_id, callback: function (data) {
                if (data) {
                    widgetData = data;
                }
            }
        });

        $scope.showdata = widgetData.data;
        $scope.css = {
            width: "col-md-12",
            height: "400"
        };
        if ($scope.showdata.metadata.css) {
            $scope.css = $scope.showdata.metadata.css;
        }
    }

    static buildFactory() {
        fgpWidgetSpan.instance = new fgpWidgetSpan();
        return fgpWidgetSpan.instance;
    }

}


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

	<title>ASP integration Samples List — CKEditor</title>
	<link type="text/css" rel="stylesheet" href="../sample.css" />

		CKEditor Samples List for ASP — CKEditor Sample

		Overview

The ckeditor.asp file provides a wrapper to ease the work of creating CKEditor instances from classic Asp.

To use it, you must first include it into your page:

		<!-- #INCLUDE file="../../ckeditor.asp" -->

	Of course, you should adjust the path to make it point to the correct location, and maybe use a full path (with virtual="" instead of file="")

After that script is included, you can use it in different ways, based on the following pattern:

		Create an instance of the CKEditor class:

dim editor
set editor = New CKEditor

		Set the path to the folder where CKEditor has been installed, by default it will use /ckeditor/

editor.basePath = "../../"

	Now use one of the three main methods to create the CKEditor instances:

				Replace textarea with id (or name) "editor1".

editor.replaceInstance "editor1"

			Replace all textareas with CKEditor.

editor.replaceAll empty

			Create a textarea element and attach CKEditor to it.

editor.editor "editor1", initialValue

Before step 3 you can use a number of methods and properties to adjust the behavior of this class and the CKEditor instances
that will be created:

returnOutput : if set to true, the functions won't dump the code with response.write, but instead they will return it so
	you can do anything you want

basePath: location of the CKEditor scripts

initialized: if you set it to true, it means that you have already included the CKEditor.js file into the page and it
		doesn't have to be generated again.

textareaAttributes: You can set here a Dictionary object with the attributes that you want to output in the call to the "editor" method.

config: Allows to set config values for all the instances from now on.

instanceConfig: Allows to set config values just for the next instance.

addEventHandler: Adds an event handler for all the instances from now on.

addInstanceEventHandler: Adds an event handler just for the next instance.

addGlobalEventHandler: Adds an event handler for the global CKEDITOR object.

clearEventHandlers: Removes one or all the event handlers from all the instances from now on.

clearInstanceEventHandlers: Removes one or all the event handlers  from the next instance.

clearGlobalEventHandlers: Removes one or all the event handlers  from the global CKEDITOR object.

		Basic Samples

Replace existing textareas by code

Replace all textareas by code

Create instances in asp

		Advanced Samples

Advanced example

Listening to events

			CKEditor - The text editor for the Internet - http://ckeditor.com

			Copyright © 2003-2012, CKSource - Frederico Knabben. All rights reserved.


text:
package plank

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/bwmarrin/snowflake"
	uuid "github.com/satori/go.uuid"

	"k8s.io/test-infra/prow/config"
	"k8s.io/test-infra/prow/github"
	"k8s.io/test-infra/prow/kube"
	"k8s.io/test-infra/prow/npj"
	reportlib "k8s.io/test-infra/prow/report"
)

const (
	testInfra = "https://github.com/kubernetes/test-infra/issues"

	// maxSyncRoutines is the maximum number of goroutines
	// that will be active at any one time for the sync
	maxSyncRoutines = 20
)

type kubeClient interface {
	CreateProwJob(kube.ProwJob) (kube.ProwJob, error)
	ListProwJobs(map[string]string) ([]kube.ProwJob, error)
	ReplaceProwJob(string, kube.ProwJob) (kube.ProwJob, error)

	CreatePod(kube.Pod) (kube.Pod, error)
	ListPods(map[string]string) ([]kube.Pod, error)
	DeletePod(string) error
}

type githubClient interface {
	BotName() (string, error)
	CreateStatus(org, repo, ref string, s github.Status) error
	ListIssueComments(org, repo string, number int) ([]github.IssueComment, error)
	CreateComment(org, repo string, number int, comment string) error
	DeleteComment(org, repo string, ID int) error
	EditComment(org, repo string, ID int, comment string) error
}

type configAgent interface {
	Config() *config.Config
}

// Controller manages ProwJobs.
type Controller struct {
	kc     kubeClient
	pkc    kubeClient
	ghc    githubClient
	ca     configAgent
	node   *snowflake.Node
	totURL string

	pendingJobs map[string]int
	lock        sync.RWMutex
}

// getNumPendingJobs retrieves the number of pending
// ProwJobs for a given job identifier
func (c *Controller) getNumPendingJobs(key string) int {
	c.lock.RLock()
	defer c.lock.RUnlock()
	return c.pendingJobs[key]
}

// incrementNumPendingJobs increments the amount of
// pending ProwJobs for the given job identifier
func (c *Controller) incrementNumPendingJobs(job string) {
	c.lock.Lock()
	defer c.lock.Unlock()

	c.pendingJobs[job] = c.pendingJobs[job] + 1
}

// setPending sets the currently pending set of jobs.
// This is NOT thread safe and should only be used for
// initializing the controller during testing.
func (c *Controller) setPending(pendingJobs map[string]int) {
	if pendingJobs == nil {
		c.pendingJobs = make(map[string]int)
	} else {
		c.pendingJobs = pendingJobs
	}
}

// NewController creates a new Controller from the provided clients.
func NewController(kc, pkc *kube.Client, ghc *github.Client, ca *config.Agent, totURL string) (*Controller, error) {
	n, err := snowflake.NewNode(1)
	if err != nil {
		return nil, err
	}
	return &Controller{
		kc:          kc,
		pkc:         pkc,
		ghc:         ghc,
		ca:          ca,
		node:        n,
		pendingJobs: make(map[string]int),
		lock:        sync.RWMutex{},
		totURL:      totURL,
	}, nil
}

// Sync does one sync iteration.
func (c *Controller) Sync() error {
	pjs, err := c.kc.ListProwJobs(nil)
	if err != nil {
		return fmt.Errorf("error listing prow jobs: %v", err)
	}
	pods, err := c.pkc.ListPods(nil)
	if err != nil {
		return fmt.Errorf("error listing pods: %v", err)
	}
	pm := map[string]kube.Pod{}
	for _, pod := range pods {
		pm[pod.Metadata.Name] = pod
	}

	var k8sJobs []kube.ProwJob
	for _, pj := range pjs {
		if pj.Spec.Agent == kube.KubernetesAgent {
			k8sJobs = append(k8sJobs, pj)
		}
	}
	pjs = k8sJobs

	c.updatePendingJobs(pjs)
	var syncErrs []error
	if err := c.terminateDupes(pjs); err != nil {
		syncErrs = append(syncErrs, err)
	}

	pjCh := make(chan kube.ProwJob, len(pjs))
	for _, pj := range pjs {
		pjCh <- pj
	}
	close(pjCh)

	errCh := make(chan error, len(pjs))
	reportCh := make(chan kube.ProwJob, len(pjs))
	wg := &sync.WaitGroup{}
	wg.Add(maxSyncRoutines)
	for i := 0; i < maxSyncRoutines; i++ {
		go c.syncProwJob(wg, pjCh, errCh, reportCh, pm)
	}
	wg.Wait()
	close(errCh)
	close(reportCh)

	for err := range errCh {
		syncErrs = append(syncErrs, err)
	}

	var reportErrs []error
	for report := range reportCh {
		if err := reportlib.Report(c.ghc, c.ca, report); err != nil {
			reportErrs = append(reportErrs, err)
		}
	}

	if len(syncErrs) == 0 && len(reportErrs) == 0 {
		return nil
	}
	return fmt.Errorf("errors syncing: %v, errors reporting: %v", syncErrs, reportErrs)
}

func (c *Controller) syncProwJob(wg *sync.WaitGroup, jobs <-chan kube.ProwJob, syncErrors chan<- error, reports chan<- kube.ProwJob, pm map[string]kube.Pod) {
	defer wg.Done()
	for pj := range jobs {
		if pj.Spec.Agent == kube.KubernetesAgent {
			if err := c.syncKubernetesJob(pj, pm, reports); err != nil {
				syncErrors <- err
			}
		}
	}
}

// terminateDupes aborts presubmits that have a newer version. It modifies pjs
// in-place when it aborts.
func (c *Controller) terminateDupes(pjs []kube.ProwJob) error {
	// "job org/repo#number" -> newest job
	dupes := make(map[string]kube.ProwJob)
	for i, pj := range pjs {
		if pj.Complete() || pj.Spec.Type != kube.PresubmitJob {
			continue
		}
		n := fmt.Sprintf("%s %s/%s#%d", pj.Spec.Job, pj.Spec.Refs.Org, pj.Spec.Refs.Repo, pj.Spec.Refs.Pulls[0].Number)
		prev, ok := dupes[n]
		if !ok {
			dupes[n] = pj
			continue
		}
		toCancel := pj
		if prev.Status.StartTime.Before(pj.Status.StartTime) {
			toCancel = prev
			dupes[n] = pj
		}
		toCancel.Status.CompletionTime = time.Now()
		toCancel.Status.State = kube.AbortedState
		npj, err := c.kc.ReplaceProwJob(toCancel.Metadata.Name, toCancel)
		if err != nil {
			return err
		}
		pjs[i] = npj
	}
	return nil
}

func (c *Controller) syncKubernetesJob(pj kube.ProwJob, pm map[string]kube.Pod, reports chan<- kube.ProwJob) error {
	if pj.Complete() {
		if pj.Status.PodName == "" {
			// Completed ProwJob, already cleaned up the pod. Nothing to do.
			return nil
		} else if _, ok := pm[pj.Status.PodName]; ok {
			// Delete the old pod.
			if err := c.pkc.DeletePod(pj.Status.PodName); err != nil {
				return fmt.Errorf("error deleting pod %s: %v", pj.Status.PodName, err)
			}
		}
		pj.Status.PodName = ""
	} else if pj.Status.PodName == "" {
		// Do not start more jobs than specified.
		numPending := c.getNumPendingJobs(pj.Spec.Job)
		if pj.Spec.MaxConcurrency > 0 && numPending >= pj.Spec.MaxConcurrency {
			logrus.WithField("job", pj.Spec.Job).Infof("Not starting another instance of %s, already %d running.", pj.Spec.Job, numPending)
			return nil
		}

		// We haven't started the pod yet. Do so.
		pj.Status.State = kube.PendingState
		c.incrementNumPendingJobs(pj.Spec.Job)
		if id, pn, err := c.startPod(pj); err == nil {
			pj.Status.PodName = pn
			pj.Status.BuildID = id
			var b bytes.Buffer
			if err := c.ca.Config().Plank.JobURLTemplate.Execute(&b, &pj); err != nil {
				return fmt.Errorf("error executing URL template: %v", err)
			}
			url := b.String()
			pj.Status.URL = url
		} else {
			return fmt.Errorf("error starting pod: %v", err)
		}
		pj.Status.Description = "Job triggered."
		reports <- pj
	} else if pod, ok := pm[pj.Status.PodName]; !ok {
		// Pod is missing. This shouldn't happen normally, but if someone goes
		// in and manually deletes the pod then we'll hit it. Start a new pod.
		pj.Status.PodName = ""
		pj.Status.State = kube.PendingState
	} else if pod.Status.Phase == kube.PodUnknown {
		// Pod is in Unknown state. This can happen if there is a problem with
		// the node. Delete the old pod, we'll start a new one next loop.
		if err := c.pkc.DeletePod(pj.Status.PodName); err != nil {
			return fmt.Errorf("error deleting pod %s: %v", pj.Status.PodName, err)
		}
		pj.Status.PodName = ""
		pj.Status.State = kube.PendingState
	} else if pod.Status.Phase == kube.PodSucceeded {
		// Pod succeeded. Update ProwJob, talk to GitHub, and start next jobs.
		pj.Status.CompletionTime = time.Now()
		pj.Status.State = kube.SuccessState
		pj.Status.Description = "Job succeeded."
		var b bytes.Buffer
		if err := c.ca.Config().Plank.JobURLTemplate.Execute(&b, &pj); err != nil {
			return fmt.Errorf("error executing URL template: %v", err)
		}
		pj.Status.URL = b.String()
		reports <- pj
		for _, nj := range pj.Spec.RunAfterSuccess {
			if _, err := c.kc.CreateProwJob(npj.NewProwJob(nj)); err != nil {
				return fmt.Errorf("error starting next prowjob: %v", err)
			}
		}
	} else if pod.Status.Phase == kube.PodFailed {
		if pod.Status.Reason == kube.Evicted {
			// Pod was evicted. Restart it.
			pj.Status.PodName = ""
			pj.Status.State = kube.PendingState
		} else {
			// Pod failed. Update ProwJob, talk to GitHub.
			pj.Status.CompletionTime = time.Now()
			pj.Status.State = kube.FailureState
			pj.Status.Description = "Job failed."
			var b bytes.Buffer
			if err := c.ca.Config().Plank.JobURLTemplate.Execute(&b, &pj); err != nil {
				return fmt.Errorf("error executing URL template: %v", err)
			}
			pj.Status.URL = b.String()
			reports <- pj
		}
	} else {
		// Pod is running. Do nothing.
		return nil
	}
	_, err := c.kc.ReplaceProwJob(pj.Metadata.Name, pj)
	return err
}

func (c *Controller) startPod(pj kube.ProwJob) (string, string, error) {
	buildID, err := c.getBuildID(pj.Spec.Job)
	if err != nil {
		return "", "", fmt.Errorf("error getting build ID: %v", err)
	}
	env := npj.EnvForSpec(pj.Spec)
	env["BUILD_NUMBER"] = buildID
	kubeEnv := kubeEnv(env)

	spec := pj.Spec.PodSpec
	spec.RestartPolicy = "Never"
	podName := newPodName()

	// Set environment variables in each container in the pod spec. We don't
	// want to update the spec in place, since that will update the ProwJob
	// spec. Instead, create a copy.
	spec.Containers = []kube.Container{}
	for i := range pj.Spec.PodSpec.Containers {
		spec.Containers = append(spec.Containers, pj.Spec.PodSpec.Containers[i])
		spec.Containers[i].Name = fmt.Sprintf("%s-%d", podName, i)
		spec.Containers[i].Env = append(spec.Containers[i].Env, kubeEnv...)
	}
	p := kube.Pod{
		Metadata: kube.ObjectMeta{
			Name: podName,
		},
		Spec: spec,
	}
	actual, err := c.pkc.CreatePod(p)
	if err != nil {
		return "", "", fmt.Errorf("error creating pod: %v", err)
	}
	return buildID, actual.Metadata.Name, nil
}

// kubeEnv transforms a mapping of environment variables
// into their serialized form for a PodSpec
func kubeEnv(environment map[string]string) []kube.EnvVar {
	var kubeEnvironment []kube.EnvVar
	for key, value := range environment {
		kubeEnvironment = append(kubeEnvironment, kube.EnvVar{
			Name:  key,
			Value: value,
		})
	}

	return kubeEnvironment
}

func (c *Controller) getBuildID(name string) (string, error) {
	if c.totURL == "" {
		return c.node.Generate().String(), nil
	}
	var err error
	url := c.totURL + "/vend/" + name
	for retries := 0; retries < 60; retries++ {
		if retries > 0 {
			time.Sleep(2 * time.Second)
		}
		var resp *http.Response
		resp, err = http.Get(url)
		if err != nil {
			continue
		}
		defer resp.Body.Close()
		if resp.StatusCode != 200 {
			continue
		}
		if buf, err := ioutil.ReadAll(resp.Body); err == nil {
			return string(buf), nil
		}
		return "", err
	}
	return "", err
}

func (c *Controller) updatePendingJobs(pjs []kube.ProwJob) {
	for _, pj := range pjs {
		if pj.Status.State == kube.PendingState {
			c.incrementNumPendingJobs(pj.Spec.Job)
		}
	}
}

var newPodName = func() string {
	return uuid.NewV1().String()
}


text:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from matplotlib.pyplot import axes

import hickle as hkl
import numpy as np

np.random.seed(2 ** 10)
import tensorflow as tf
import itertools
from keras import backend as K
K.set_image_dim_ordering('tf')
import matplotlib.pyplot as plt
from keras import regularizers
from keras.layers import Dropout
from keras.models import Sequential
from keras.layers.core import Activation
from keras.utils.vis_utils import plot_model
from keras.initializers import RandomNormal
from keras.layers.wrappers import TimeDistributed
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import Conv2DTranspose
from keras.layers.convolutional import Conv3D
from keras.layers.convolutional import Conv3DTranspose
from keras.layers.convolutional import UpSampling3D
from keras.layers.convolutional_recurrent import ConvLSTM2D
from keras.layers.convolutional import MaxPooling3D
from keras.layers.convolutional import ZeroPadding3D
from keras.layers.merge import multiply
from keras.layers.merge import add
from keras.layers.merge import concatenate
from keras.layers.merge import average
from keras.layers.core import Permute
from keras.layers.core import RepeatVector
from keras.layers.core import Dense
from keras.layers.core import Lambda
from keras.layers.core import Reshape
from keras.layers.core import Flatten
from keras.utils import to_categorical
from keras.layers.recurrent import LSTM
from keras.layers.recurrent import GRU
from keras.layers.normalization import BatchNormalization
from keras.callbacks import LearningRateScheduler
from keras.layers.advanced_activations import LeakyReLU
from keras.losses import kullback_leibler_divergence
from keras.losses import mean_squared_error
from keras.layers import Input
from keras.models import Model
from keras.models import model_from_json
from keras.metrics import top_k_categorical_accuracy
from experience_memory import ExperienceMemory
from sklearn.metrics import classification_report
from sklearn.metrics import precision_recall_fscore_support
from sklearn.metrics import confusion_matrix
from image_utils import random_rotation
from image_utils import random_shift
from image_utils import random_zoom
from image_utils import flip_axis
from custom_layers import AttnLossLayer
from image_utils import random_brightness
from config_basec import *
from sys import stdout

import tb_callback
import lrs_callback
import argparse
import random
import math
import cv2
import os

def process_prec3d():
    json_file = open(PRETRAINED_C3D, 'r')
    loaded_model_json = json_file.read()
    json_file.close()
    model = model_from_json(loaded_model_json)

    model.load_weights(PRETRAINED_C3D_WEIGHTS)
    print("Loaded weights from disk")
    # for layer in model.layers[:13]:
    #     layer.trainable = RETRAIN_CLASSIFIER

    for layer in model.layers[:9]:
        layer.trainable = RETRAIN_CLASSIFIER

    # i = 0
    # for layer in model.layers:
    #     print(layer, i)
    #     i = i + 1

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

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

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    model.layers.pop()
    model.outputs = [model.layers[-1].output]
    model.layers[-1].outbound_nodes = []

    return model

def pretrained_c3d():
    c3d = process_prec3d()
    inputs = Input(shape=(16, 128, 208, 3))
    resized = TimeDistributed(Lambda(lambda image: tf.image.resize_images(image, (112, 112))))(inputs)

    # conv_1a = ConvLSTM2D(filters=16,
    #                  strides=(1, 1, 1),
    #                  dilation_rate=(2, 1, 1),
    #                  kernel_size=(2, 11, 11),
    #                  padding='same')(resized)
    # x = TimeDistributed(BatchNormalization())(conv_1a)
    # x = TimeDistributed(LeakyReLU(alpha=0.2))(x)
    # out_1a = TimeDistributed(Dropout(0.5))(x)
    #
    # conv_1b = ConvLSTM2D(filters=16,
    #                  strides=(1, 1, 1),
    #                  dilation_rate=(4, 1, 1),
    #                  kernel_size=(2, 5, 5),
    #                  padding='same')(out_1a)
    # x = TimeDistributed(BatchNormalization())(conv_1b)
    # x = TimeDistributed(LeakyReLU(alpha=0.2))(x)
    # out_1b = TimeDistributed(Dropout(0.5))(x)
    #
    # res_1 = add([out_1a, out_1b])
    #
    # conv_2 = ConvLSTM2D(filters=1,
    #                  strides=(1, 1, 1),
    #                  dilation_rate=(2, 1, 1),
    #                  kernel_size=(2, 3, 3),
    #                  padding='same')(res_1)
    # x = TimeDistributed(BatchNormalization())(conv_2)
    # a = TimeDistributed(Activation(activation='softmax'))(x)
    # a = AttnLossLayer()(a)
    #
    # scaled = multiply([resized, a])
    # c3d_out = c3d(scaled)
    features = c3d(resized)
    features_flat = TimeDistributed(Flatten())(features)

    lstm_1 = LSTM(units=256,
                  recurrent_dropout=0.2,
                  return_sequences=True,
                  activation='tanh')(features_flat)

    lstm_2 = LSTM(units=14*14,
                  recurrent_dropout=0.2,
                  return_sequences=True)(lstm_1)
    lstm_2 = Activation('softmax')(lstm_2)

    a_reshape = Reshape(target_shape=(4, 14, 14, 1))(lstm_2)
    a = AttnLossLayer()(a_reshape)
    scaled = multiply([features, a])

    def feature_cube(x):
        return K.mean(K.mean(x, axis=2, keepdims=False), axis=2, keepdims=False)

    x = Lambda(feature_cube)(scaled)

    x_flat = TimeDistributed(Flatten())(x)
    lstm_3 = LSTM(units=512,
                  recurrent_dropout=0.2,
                  return_sequences=True,
                  activation='tanh')(x_flat)

    lstm_4 = LSTM(units=512,
                  recurrent_dropout=0.2,
                  return_sequences=False,
                  activation='tanh')(lstm_3)

    dense = Dense(units=512, activation='relu', kernel_regularizer=regularizers.l2(0.01))(lstm_4)
    x = BatchNormalization()(dense)
    x = Dropout(0.5)(x)
    # x = Dense(units=512, activation='relu')(x)
    # x = BatchNormalization()(x)
    # x = Dropout(0.5)(x)
    actions = Dense(units=len(simple_ped_set), activation='sigmoid', kernel_regularizer=regularizers.l2(0.01))(x)

    model = Model(inputs=inputs, outputs=actions)

    # model = Model(inputs=inputs, outputs=c3d_out)

    # i = 0
    # for layer in model.layers:
    #     print(layer, i)
    #     i = i + 1
    #
    print (c3d.summary())
    # exit(0)
    return model

def ensemble_c3d():
    inputs = Input(shape=(16, 128, 208, 3))

    def sliceA(x):
        return x[:, :, :, 0:112, :]

    # def sliceB(x):
    #     return x[:, :, :, 48:160, :]

    # def sliceC(x):
    #     return x[:, :, :, 96:208, :]

    A = Lambda(sliceA)(inputs)
    # B = Lambda(sliceB)(inputs)
    # C = Lambda(sliceC)(inputs)

    c3d_A = pretrained_c3d()
    # c3d_B = pretrained_c3d()
    c3d_C = pretrained_c3d()
    c3d_A.compile(loss="binary_crossentropy",
                optimizer=OPTIM_C)
    # c3d_B.compile(loss="binary_crossentropy",
    #               optimizer=OPTIM_C)
    # c3d_C.compile(loss="binary_crossentropy",
    #               optimizer=OPTIM_C)

    A_out = c3d_A(A)
    # B_out = c3d_B(B)
    # C_out = c3d_C(C)

    # features = concatenate([A_out, C_out])
    dense = Dense(units=1024, activation='relu', kernel_regularizer=regularizers.l2(0.01))(A_out)
    x = BatchNormalization()(dense)
    x = Dropout(0.5)(x)
    x = Dense(units=512, activation='relu')(x)
    x = BatchNormalization()(x)
    x = Dropout(0.5)(x)
    actions = Dense(units=len(simple_ped_set), activation='sigmoid', kernel_regularizer=regularizers.l2(0.01))(x)

    model = Model(inputs=inputs, outputs=actions)

    # i=0
    # for layer in model.layers:
    #     print (layer, i)
    #     i = i+1
    # exit(0)

    return model

def set_trainability(model, trainable):
    model.trainable = trainable
    for layer in model.layers:
        layer.trainable = trainable

def arrange_images(video_stack):
    n_frames = video_stack.shape[0] * video_stack.shape[1]
    frames = np.zeros((n_frames,) + video_stack.shape[2:], dtype=video_stack.dtype)

    frame_index = 0
    for i in range(video_stack.shape[0]):
        for j in range(video_stack.shape[1]):
            frames[frame_index] = video_stack[i, j]
            frame_index += 1

    img_height = video_stack.shape[2]
    img_width = video_stack.shape[3]
    # width = img_size x video_length
    width = img_width * video_stack.shape[1]
    # height = img_size x batch_size
    height = img_height * video_stack.shape[0]
    shape = frames.shape[1:]
    image = np.zeros((height, width, shape[2]), dtype=video_stack.dtype)
    frame_number = 0
    for i in range(video_stack.shape[0]):
        for j in range(video_stack.shape[1]):
            image[(i * img_height):((i + 1) * img_height), (j * img_width):((j + 1) * img_width)] = frames[frame_number]
            frame_number = frame_number + 1

    return image

def load_weights(weights_file, model):
    model.load_weights(weights_file)

def run_utilities(classifier, CLA_WEIGHTS):
    if PRINT_MODEL_SUMMARY:
        if CLASSIFIER:
            print("Classifier:")
            print (classifier.summary())
        # exit(0)

    # Save model to file
    if SAVE_MODEL:
        if CLASSIFIER:
            model_json = classifier.to_json()
            with open(os.path.join(MODEL_DIR, "classifier.json"), "w") as json_file:
                json_file.write(model_json)

        if PLOT_MODEL:
            if CLASSIFIER:
                plot_model(classifier, to_file=os.path.join(MODEL_DIR, 'classifier.png'), show_shapes=True)

    if CLASSIFIER:
        if CLA_WEIGHTS != "None":
            print("Pre-loading classifier with weights.")
            load_weights(CLA_WEIGHTS, classifier)

def random_augmentation(video):
    # Toss a die
    k = np.random.randint(0, 5, dtype=int)
    if k == 0:
        for i in range(VIDEO_LENGTH):
            video[i] = (video[i].astype(np.float32) - 127.5) / 127.5
        return video

    elif k == 1:
        # Random Rotation
        theta = np.random.uniform(-ROT_MAX, ROT_MAX)
        for i in range (VIDEO_LENGTH):
            video[i] = random_rotation(video[i], (i*theta)/VIDEO_LENGTH, row_axis=0,
                            col_axis=1, channel_axis=2, fill_mode="nearest")
            video[i] = (video[i].astype(np.float32) - 127.5) / 127.5

    elif k == 2:
        # Random shift
        h, w = video.shape[1], video.shape[2]
        tx = np.random.uniform(-SFT_V_MAX, SFT_V_MAX) * h
        ty = np.random.uniform(-SFT_H_MAX, SFT_H_MAX) * w
        for i in range(VIDEO_LENGTH):
            video[i] = random_shift(video[i], tx, ty, row_axis=0,
                                    col_axis=1, channel_axis=2, fill_mode="nearest")
            video[i] = (video[i].astype(np.float32) - 127.5) / 127.5

    elif k == 3:
        # Horizontal Flip
        for i in range(VIDEO_LENGTH):
            video[i] = flip_axis(video[i], axis=1)
            video[i] = (video[i].astype(np.float32) - 127.5) / 127.5

    else:
        # Vary brightness
        u = np.random.uniform(BRIGHT_RANGE_L, BRIGHT_RANGE_H)
        for i in range(VIDEO_LENGTH):
            video[i] = random_brightness(video[i], u)
            video[i] = (video[i].astype(np.float32) - 127.5) / 127.5

    return video

def load_X_y_RAM(videos_list, index, frames, ped_action_cats):
    if RAM_DECIMATE:
        X = []
        y = []
        for i in range(BATCH_SIZE):
            video = np.take(frames, videos_list[(index*BATCH_SIZE + i)], axis=0)
            video = random_augmentation(video)
            X.append(video)
            if (len(ped_action_cats) != 0):
                y.append(np.take(ped_action_cats, videos_list[(index * BATCH_SIZE + i)], axis=0))

        X = np.asarray(X)
        y = np.asarray(y)
        return X, y
    else:
        print ("RAM usage flag not set. Are you sure you want to do this?")
        exit(0)

def load_X_y(videos_list, index, data_dir, ped_action_cats):
    X = np.zeros((BATCH_SIZE, VIDEO_LENGTH,) + IMG_SIZE)
    y = []
    for i in range(BATCH_SIZE):
        y_per_vid = []
        for j in range(VIDEO_LENGTH):
            frame_number = (videos_list[(index*BATCH_SIZE + i), j])
            filename = "frame_" + str(frame_number) + ".png"
            im_file = os.path.join(data_dir, filename)
            try:
                frame = cv2.imread(im_file, cv2.IMREAD_COLOR)
                X[i, j] = (frame.astype(np.float32) - 127.5) / 127.5
            except AttributeError as e:
                print (im_file)
                print (e)
            if (len(ped_action_cats) != 0):
                try:
                    y_per_vid.append(ped_action_cats[frame_number - 1])
                except IndexError as e:
                    print(frame_number)
                    print(e)
        if (len(ped_action_cats) != 0):
            y.append(y_per_vid)
    return X, np.asarray(y)

def map_to_simple(ped_action):
    if (ped_action == 0):
        return 0
    elif (ped_action == 1):
        return 1
    elif (ped_action == 2):
        return 1
    elif (ped_action == 5):
        return 2
    elif (ped_action == 6):
        return 2
    elif (ped_action == 7):
        return 2
    elif (ped_action == 8):
        return 0
    elif (ped_action == 9):
        return 1
    elif (ped_action == 12):
        return 3
    elif (ped_action == 13):
        return 4
    else:
        print ("Irrelevant ped_action found. Exiting.")
        print (ped_action)
        exit(0)

def get_action_classes(action_labels, mode='softmax'):
    # Load labels into per frame numerical indices from the action set
    print("Loading annotations.")

    ped_action_classes = []
    count = [0] * len(simple_ped_set)
    for i in range(len(action_labels)):
        action_dict = dict(ele.split(':') for ele in action_labels[i].split(', ')[2:])
        # Settle pedestrian classes
        a_clean = []
        for key, value in action_dict.iteritems():
            if 'pedestrian' in key:
                if ',' in value:
                    splits = value.split(',')
                    for k in range(len(splits)):
                        a_clean.append(splits[k])
                else:
                    a_clean.append(value)

        if len(a_clean) == 0:
            a_clean = ['no ped']

        ped_actions_per_frame = list(set([a.lower() for a in a_clean]))
        simple_ped_actions_per_frame = []
        encoded_ped_action = np.zeros(shape=(len(simple_ped_set)), dtype=np.float32)
        for action in ped_actions_per_frame:
            # Get ped action number and map it to simple set
            if action.lower() not in ped_actions:
                print ("Unknown action in labels. Exiting.")
                print (action)
                exit(0)
            if action.lower() == 'crossing':
                ped_action = simple_ped_set.index('crossing')
                simple_ped_actions_per_frame.append(ped_action)
            # if action.lower() == 'standing':
            #     ped_action = simple_ped_set.index('standing')
            #     simple_ped_actions_per_frame.append(ped_action)
            # if action.lower() == 'no ped':
            #     ped_action = simple_ped_set.index('no ped')
            #     simple_ped_actions_per_frame.append(ped_action)

        if mode=='softmax':
            if 2 in simple_ped_actions_per_frame:
                act = 2
            if 0 in simple_ped_actions_per_frame:
                act = 0
            if 1 in simple_ped_actions_per_frame:
                act = 1

            encoded_ped_action = to_categorical(act, len(simple_ped_set))
            count[act] = count[act] + 1

        elif mode=='sigmoid':
            for action in simple_ped_actions_per_frame:
                count[action] = count[action] + 1
                # Add all unique categorical one-hot vectors
                encoded_ped_action = encoded_ped_action + to_categorical(action, len(simple_ped_set))

        else:
            print ("No mode selected to determine action labels. Exiting.")
            exit(0)

        ped_action_classes.append(encoded_ped_action.T)

    ped_action_classes = np.asarray(ped_action_classes)
    ped_action_classes = np.reshape(ped_action_classes, newshape=(ped_action_classes.shape[0:2]))
    return ped_action_classes, count

def remove_zero_classes(videos_list, simple_ped_actions_per_frame):
    r_indices = []
    for i in range(len(videos_list)):
        # if (len(list(simple_ped_actions_per_frame[videos_list[i, CLASS_TARGET_INDEX]])) == 0):
        if sum(simple_ped_actions_per_frame[videos_list[i, CLASS_TARGET_INDEX]]) == 0:
            r_indices.append(i)

    for i in sorted(r_indices, reverse=True):
        videos_list = np.delete(videos_list, i, axis=0)

    return videos_list

def load_to_RAM(frames_source):
    frames = np.zeros(shape=((len(frames_source),) + IMG_SIZE))

    j = 1
    for i in range(1, len(frames_source)):
        filename = "frame_" + str(j) + ".png"
        im_file = os.path.join(DATA_DIR, filename)
        try:
            frame = cv2.imread(im_file, cv2.IMREAD_COLOR)
            frames[i] = frame.astype(np.float32)
            j = j + 1
        except AttributeError as e:
            print(im_file)
            print(e)

    return frames

def get_video_lists(frames_source, stride, frame_skip=0):
    # Build video progressions
    videos_list = []
    start_frame_index = 1
    end_frame_index = ((frame_skip + 1) * VIDEO_LENGTH) + 1 - frame_skip
    while (end_frame_index <= len(frames_source)):
        frame_list = frames_source[start_frame_index:end_frame_index]
        if (len(set(frame_list)) == 1):
            videos_list.append(range(start_frame_index, end_frame_index, frame_skip+1))
            start_frame_index = start_frame_index + stride
            end_frame_index = end_frame_index + stride
        else:
            start_frame_index = end_frame_index - 1
            end_frame_index = start_frame_index + (frame_skip+1)*VIDEO_LENGTH -frame_skip

    videos_list = np.asarray(videos_list, dtype=np.int32)

    return np.asarray(videos_list)

def get_classwise_data(videos_list, ped_action_labels):
    classwise_videos_list = [[] for _ in range(len(simple_ped_set))]
    count = [0] * len(simple_ped_set)
    for i in range(len(videos_list)):
        labels = np.where(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]] == 1)
        for j in labels[0]:
            count[j] += 1
            classwise_videos_list[j].append(np.asarray(videos_list[i]))

    print('Before subsampling')
    print(str(count))

    return classwise_videos_list, count

def prob_subsample(classwise_videos_list, count):
    train_videos_list = []
    sample_size = min(count)

    for i in range(len(classwise_videos_list)):
        indices = np.random.choice(count[i], sample_size, replace=False)
        videos_list = np.asarray(np.take(classwise_videos_list[i], indices, axis=0))
        train_videos_list.extend(np.asarray(videos_list))

    train_videos_list = np.random.permutation(train_videos_list)

    return np.asarray(train_videos_list)

def subsample_videos(videos_list, ped_action_labels):
    print (videos_list.shape)
    AP_MAX = 3
    CR_MAX = 10
    ST_MAX = 10
    NP_MAX = 3

    ap_count = 0
    cr_count = 0
    st_count = 0
    np_count = 0

    r_indices = []

    classwise_videos_list, count = get_classwise_data(videos_list, ped_action_labels)
    videos_list = prob_subsample(classwise_videos_list, count)

    exit(0)

    for i in range(len(videos_list)):
        # Approaching count
        if (list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1) == 1):
            ap_count = ap_count + 1
            if (ap_count < AP_MAX):
                r_indices.append(i)
            else:
                ap_count = 0

        # Crossing count
        if (list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1) == 2):
            cr_count = cr_count + 1
            if (cr_count < CR_MAX):
                r_indices.append(i)
            else:
                cr_count = 0

        # Stopped count
        if (list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1) == 3):
            st_count = st_count + 1
            if (st_count < ST_MAX):
                r_indices.append(i)
            else:
                st_count = 0

        # No ped count
        if (list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1) == 6):
            np_count = np_count + 1
            if (np_count < NP_MAX):
                r_indices.append(i)
            else:
                np_count = 0

        # if (list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1) ==
        #         list(ped_action_labels[videos_list[i, 8]]).index(1)):
        #     r_indices.append(i)

    for i in sorted(r_indices, reverse=True):
        videos_list = np.delete(videos_list, i, axis=0)

    count = [0] * len(simple_ped_set)
    for i in range(len(videos_list)):
        count[list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1)] = \
            count[list(ped_action_labels[videos_list[i, CLASS_TARGET_INDEX]]).index(1)] + 1

    print ('After subsampling')
    print (str(count))

    return videos_list

def get_sklearn_metrics(y_true, y_pred, avg=None):
    return precision_recall_fscore_support(y_true, np.round(y_pred), average=avg)

def get_classification_report(y_true, y_pred):
    return classification_report(y_true, np.round(y_pred), target_names=simple_ped_set)

def train(BATCH_SIZE, ENC_WEIGHTS, DEC_WEIGHTS, CLA_WEIGHTS):
    print("Loading data definitions.")

    frames_source = hkl.load(os.path.join(DATA_DIR, 'sources_train_208.hkl'))
    videos_list = get_video_lists(frames_source=frames_source, stride=1, frame_skip=0)
    # videos_list_2 = get_video_lists(frames_source=frames_source, stride=1, frame_skip=1)
    # videos_list_3 = get_video_lists(frames_source=frames_source, stride=1, frame_skip=2)
    # videos_list = np.concatenate((videos_list_1, videos_list_2), axis=0)

    # Load actions from annotations
    action_labels = hkl.load(os.path.join(DATA_DIR, 'annotations_train_208.hkl'))
    ped_action_classes, ped_class_count = get_action_classes(action_labels=action_labels, mode='sigmoid')
    print("Training Stats: " + str(ped_class_count))

    # videos_list = remove_zero_classes(videos_list, ped_action_classes)
    # classwise_videos_list, count = get_classwise_data(videos_list, ped_action_classes)
    # videos_list = prob_subsample(classwise_videos_list, count)

    if RAM_DECIMATE:
        frames = load_to_RAM(frames_source=frames_source)

    if SHUFFLE:
        # Shuffle images to aid generalization
        videos_list = np.random.permutation(videos_list)

    # Setup test
    test_frames_source = hkl.load(os.path.join(TEST_DATA_DIR, 'sources_test_208.hkl'))
    test_videos_list = get_video_lists(frames_source=test_frames_source, stride=4)
    # Load test action annotations
    test_action_labels = hkl.load(os.path.join(TEST_DATA_DIR, 'annotations_test_208.hkl'))
    test_ped_action_classes, test_ped_class_count = get_action_classes(test_action_labels, mode='sigmoid')
    # test_videos_list = remove_zero_classes(test_videos_list, test_ped_action_classes)
    print("Test Stats: " + str(test_ped_class_count))

    # Build the Spatio-temporal Autoencoder
    print ("Creating models.")
    # Build stacked classifier
    classifier = pretrained_c3d()
    # classifier = ensemble_c3d()
    # classifier = c3d_scratch()
    classifier.compile(loss="binary_crossentropy",
                       optimizer=OPTIM_C,
                       # metrics=[metric_precision, metric_recall, metric_mpca, 'accuracy'])
                       metrics=['accuracy'])

    # Build attention layer output
    intermediate_classifier = Model(inputs=classifier.layers[0].input, outputs=classifier.layers[7].output)
    mask_gen_1 = Sequential()
    # mask_gen_1.add(encoder)
    mask_gen_1.add(intermediate_classifier)
    mask_gen_1.compile(loss='binary_crossentropy', optimizer=OPTIM_C)

    run_utilities(classifier, CLA_WEIGHTS)

    n_videos = videos_list.shape[0]
    n_test_videos = test_videos_list.shape[0]

    NB_ITERATIONS = int(n_videos/BATCH_SIZE)
    # NB_ITERATIONS = 5
    NB_TEST_ITERATIONS = int(n_test_videos/BATCH_SIZE)
    # NB_TEST_ITERATIONS = 5

    # Setup TensorBoard Callback
    TC_cla = tb_callback.TensorBoard(log_dir=TF_LOG_CLA_DIR, histogram_freq=0, write_graph=False, write_images=False)
    LRS_clas = lrs_callback.LearningRateScheduler(schedule=schedule)
    LRS_clas.set_model(classifier)

    print ("Beginning Training.")
    # Begin Training
    # Train Classifier
    if CLASSIFIER:
        print("Training Classifier...")
        for epoch in range(NB_EPOCHS_CLASS):
            print("\n\nEpoch ", epoch)
            c_loss = []
            test_c_loss = []

            # # Set learning rate every epoch
            LRS_clas.on_epoch_begin(epoch=epoch)
            lr = K.get_value(classifier.optimizer.lr)
            print("Learning rate: " + str(lr))
            print("c_loss_metrics: " + str(classifier.metrics_names))

            y_train_pred = []
            y_train_true = []
            for index in range(NB_ITERATIONS):
                # Train Autoencoder
                if RAM_DECIMATE:
                    # videos_list = prob_subsample(classwise_videos_list, count)
                    X, y = load_X_y_RAM(videos_list, index, frames, ped_action_classes)
                else:
                    # videos_list = prob_subsample(classwise_videos_list, count)
                    X, y = load_X_y(videos_list, index, DATA_DIR, ped_action_classes)

                X_train = X
                y_true_class = y[:, CLASS_TARGET_INDEX]

                c_loss.append(classifier.train_on_batch(X_train, y_true_class))

                y_train_true.extend(y_true_class)
                y_train_pred.extend(classifier.predict(X_train, verbose=0))

                arrow = int(index / (NB_ITERATIONS / 30))
                stdout.write("\rIter: " + str(index) + "/" + str(NB_ITERATIONS - 1) + "  " +
                             "c_loss: " + str([ c_loss[len(c_loss) - 1][j]  for j in [0, 1]]) + "  " +
                             "\t    [" + "{0}>".format("=" * (arrow)))
                stdout.flush()

            if SAVE_GENERATED_IMAGES:
                # Save generated images to file
                ped_pred_class = classifier.predict(X_train, verbose=0)
                # pred_seq = arrange_images(np.concatenate((X_train, predicted_images), axis=1))
                pred_seq = arrange_images(X_train)
                pred_seq = pred_seq * 127.5 + 127.5

                font = cv2.FONT_HERSHEY_SIMPLEX
                y_orig_classes = y
                # Add labels as text to the image

                for k in range(BATCH_SIZE):
                    for j in range(int(VIDEO_LENGTH )):
                        class_num_past = np.argmax(y_orig_classes[k, j])
                        class_num_y = np.argmax(ped_pred_class[k])
                        # label_true = simple_ped_set[class_num_past]
                        # label_pred = simple_ped_set[class_num_y]

                        label_true = str(y_orig_classes[k, j])
                        label_pred = str([round(float(i), 2) for i in ped_pred_class[k]])

                        # if (y_orig_classes[k, j] > 0.5):
                        #     label_true = "crossing"
                        # else:
                        #     label_true = "not crossing"
                        #
                        # if (ped_pred_class[k] > 0.5):
                        #     label_pred = "crossing"
                        # else:
                        #     label_pred = "not crossing"

                        cv2.putText(pred_seq, 'truth: ' + label_true,
                                    (2 + j * (208), 94 + k * 128), font, 0.5, (255, 255, 255), 1,
                                    cv2.LINE_AA)
                        cv2.putText(pred_seq, label_pred,
                                    (2 + j * (208), 114 + k * 128), font, 0.5, (255, 255, 255), 1,
                                    cv2.LINE_AA)

                cv2.imwrite(os.path.join(CLA_GEN_IMAGES_DIR, str(epoch) + "_" + str(index) + "_cla_pred.png"), pred_seq)

                slices = mask_gen_1.predict(X_train)
                slices = slices.repeat(8, axis=2).repeat(8, axis=3)
                slice_images = arrange_images(slices)
                slice_images = slice_images * 127.5 + 127.5
                cv2.imwrite(os.path.join(CLA_GEN_IMAGES_DIR, str(epoch) + "_" + str(index) + "_slice_pred.png"), slice_images)

            # Run over test data
            print('')
            y_test_pred = []
            y_test_true = []
            for index in range(NB_TEST_ITERATIONS):
                X, y = load_X_y(test_videos_list, index, TEST_DATA_DIR, test_ped_action_classes)
                X_test = X
                y_true_class = y[:, CLASS_TARGET_INDEX]

                test_c_loss.append(classifier.test_on_batch(X_test, y_true_class))
                y_test_true.extend(y_true_class)
                y_test_pred.extend(classifier.predict(X_test, verbose=0))

                arrow = int(index / (NB_TEST_ITERATIONS / 40))
                stdout.write("\rIter: " + str(index) + "/" + str(NB_TEST_ITERATIONS - 1) + "  " +
                             "test_c_loss: " +  str([ test_c_loss[len(test_c_loss) - 1][j]  for j in [0, 1]]))
                stdout.flush()

            if SAVE_GENERATED_IMAGES:
                # Save generated images to file
                test_ped_pred_class = classifier.predict(X_test, verbose=0)
                # pred_seq = arrange_images(np.concatenate((X_train, predicted_images), axis=1))
                pred_seq = arrange_images(X_test)
                pred_seq = pred_seq * 127.5 + 127.5

                font = cv2.FONT_HERSHEY_SIMPLEX
                y_orig_classes = y
                # Add labels as text to the image

                for k in range(BATCH_SIZE):
                    for j in range(int(VIDEO_LENGTH)):
                        class_num_past = np.argmax(y_orig_classes[k, j])
                        class_num_y = np.argmax(test_ped_pred_class[k])

                        # label_true = simple_ped_set[class_num_past]
                        # label_pred = simple_ped_set[class_num_y]
                        label_true = str(y_orig_classes[k, j])
                        label_pred = str([round(float(i), 2) for i in ped_pred_class[k]])

                        #
                        # if (y_orig_classes[k, j] > 0.5):
                        #     label_true = "crossing"
                        # else:
                        #     label_true = "not crossing"
                        #
                        # if (test_ped_pred_class[k] > 0.5):
                        #     label_pred = "crossing"
                        # else:
                        #     label_pred = "not crossing"

                        cv2.putText(pred_seq, 'truth: ' + label_true,
                                    (2 + j * (208), 94 + k * 128), font, 0.5, (255, 255, 255), 1,
                                    cv2.LINE_AA)
                        cv2.putText(pred_seq, label_pred,
                                    (2 + j * (208), 114 + k * 128), font, 0.5, (255, 255, 255), 1,
                                    cv2.LINE_AA)

                cv2.imwrite(os.path.join(CLA_GEN_IMAGES_DIR, str(epoch) + "_" + str(index) + "_cla_test_pred.png"), pred_seq)

            # then after each epoch
            avg_c_loss = np.mean(np.asarray(c_loss, dtype=np.float32), axis=0)
            avg_test_c_loss = np.mean(np.asarray(test_c_loss, dtype=np.float32), axis=0)

            print (np.asarray(y_train_true))
            print (np.asarray(y_train_pred))

            train_prec, train_rec, train_fbeta, train_support = get_sklearn_metrics(np.asarray(y_train_true),
                                                                                np.asarray(y_train_pred),
                                                                                avg='micro')
            test_prec, test_rec, test_fbeta, test_support = get_sklearn_metrics(np.asarray(y_test_true),
                                                                                np.asarray(y_test_pred),
                                                                                avg='micro')

            loss_values = np.asarray(avg_c_loss.tolist() + [train_prec.tolist()] +
                                     [train_rec.tolist()] +
                                     avg_test_c_loss.tolist() + [test_prec.tolist()] +
                                     [test_rec.tolist()], dtype=np.float32)
            # loss_values = np.asarray(avg_c_loss.tolist() + train_prec.tolist() +
            #                          train_rec.tolist() +
            #                          avg_test_c_loss.tolist() + test_prec.tolist() +
            #                          test_rec.tolist(), dtype=np.float32)
            precs = ['prec_' + action for action in simple_ped_set]
            recs = ['rec_' + action for action in simple_ped_set]
            fbeta = ['fbeta_' + action for action in simple_ped_set]
            c_loss_keys = ['c_' + metric for metric in classifier.metrics_names+precs+recs]
            test_c_loss_keys = ['c_test_' + metric for metric in classifier.metrics_names+precs+recs]

            loss_keys = c_loss_keys + test_c_loss_keys
            logs = dict(zip(loss_keys, loss_values))

            TC_cla.on_epoch_end(epoch, logs)

            # Log the losses
            with open(os.path.join(LOG_DIR, 'losses_cla.json'), 'a') as log_file:
                log_file.write("{\"epoch\":%d, %s;\n" % (epoch, logs))

            print("\nAvg c_loss: " + str(avg_c_loss) +
                  " Avg test_c_loss: " + str(avg_test_c_loss))

            print ("Training Precision per class:" + str(train_prec))
            print ("Test Precision per class:" + str(test_prec))
            print ("Training Recall per class:" + str(train_rec))
            print ("Test Recall per class:" + str(test_rec))

            prec, recall, fbeta, support = get_sklearn_metrics(np.asarray(y_train_true),
                                                               np.asarray(y_train_pred),
                                                               avg='weighted')
            print ("Train Prec: %.2f, Recall: %.2f, Fbeta: %.2f" %(prec, recall, fbeta))
            prec, recall, fbeta, support = get_sklearn_metrics(np.asarray(y_test_true),
                                                               np.asarray(y_test_pred),
                                                               avg='weighted')
            print("Test Prec: %.2f, Recall: %.2f, Fbeta: %.2f" % (prec, recall, fbeta))

            # Save model weights per epoch to file
            # encoder.save_weights(os.path.join(CHECKPOINT_DIR, 'encoder_cla_epoch_' + str(epoch) + '.h5'), True)
            # decoder.save_weights(os.path.join(CHECKPOINT_DIR, 'decoder_cla_epoch_' + str(epoch) + '.h5'), True)
            classifier.save_weights(os.path.join(CHECKPOINT_DIR, 'classifier_cla_epoch_' + str(epoch) + '.h5'),
                                    True)

            # get_confusion_matrix(y_train_true, y_train_pred)
            # get_confusion_matrix(y_test_true, y_test_pred)

        print (get_classification_report(np.asarray(y_train_true), np.asarray(y_train_pred)))
        print (get_classification_report(np.asarray(y_test_true), np.asarray(y_test_pred)))

def test(ENC_WEIGHTS, DEC_WEIGHTS, CLA_WEIGHTS):

    # Create models
    print ("Creating models.")
    classifier = pretrained_c3d()
    classifier.compile(loss="binary_crossentropy",
                       optimizer=OPTIM_C,
                       metrics=[metric_precision, metric_recall, metric_mpca, 'accuracy'])

    run_utilities(classifier, CLA_WEIGHTS)

    # Setup test
    test_frames_source = hkl.load(os.path.join(TEST_DATA_DIR, 'sources_test_208.hkl'))
    test_videos_list = get_video_lists(frames_source=test_frames_source, stride=8)
    # Load test action annotations
    test_action_labels = hkl.load(os.path.join(TEST_DATA_DIR, 'annotations_test_208.hkl'))
    test_driver_action_classes, test_ped_action_classes, test_ped_class_count = get_action_classes(test_action_labels)
    print("Test Stats: " + str(test_ped_class_count))

    n_test_videos = test_videos_list.shape[0]

    # Test model by making predictions
    test_c_loss = []
    y_true_total = []
    y_pred_total = []
    NB_TEST_ITERATIONS = int(n_test_videos / BATCH_SIZE)
    for index in range(NB_TEST_ITERATIONS):
        X, y1, y2 = load_X_y(test_videos_list, index, TEST_DATA_DIR, [], test_ped_action_classes)
        X_test = X
        y2_true_class = y2[:, CLASS_TARGET_INDEX]

        test_c_loss.append(classifier.test_on_batch(X_test, y2_true_class))
        y_true_total.append(K.cast(y2_true_class, dtype='int32'))
        y_pred_total.append(K.cast(K.round(classifier.predict(X_test)), 'int32'))

        arrow = int(index / (NB_TEST_ITERATIONS / 40))
        stdout.write("\rIter: " + str(index) + "/" + str(NB_TEST_ITERATIONS - 1) + "  " +
                     "test_c_loss: " + str([test_c_loss[len(test_c_loss) - 1][j] for j in [0, 1, 2, 3, 4]]))
        stdout.flush()

        # Save generated images to file
        ped_pred_class = classifier.predict(X_test, verbose=0)
        orig_image = arrange_images(X_test)
        orig_image = orig_image * 127.5 + 127.5
        pred_image = np.copy(orig_image)
        font = cv2.FONT_HERSHEY_SIMPLEX
        y2_orig_classes = y2
        # Add labels as text to the image
        for k in range(BATCH_SIZE):
            for j in range(VIDEO_LENGTH):
                class_num_past_y2 = np.argmax(y2_orig_classes[k, j])
                cv2.putText(orig_image, "Ped: " + simple_ped_set[class_num_past_y2],
                            (2 + j * (112), 104 + k * 112), font, 0.5, (255, 255, 255), 1,
                            cv2.LINE_AA)
        cv2.imwrite(os.path.join(CLA_GEN_IMAGES_DIR, str(index) +
                                 "_cla_test_orig.png"), orig_image)

        # Add labels as text to the image
        for k in range(BATCH_SIZE):
            class_num_y2 = np.argmax(ped_pred_class[k])
            cv2.putText(pred_image, "Ped: " + simple_ped_set[class_num_y2],
                        (2, 104 + k * 112), font, 0.5, (255, 255, 255), 1,
                        cv2.LINE_AA)
        cv2.imwrite(os.path.join(CLA_GEN_IMAGES_DIR, str(index) + "_cla_test_pred.png"),
                    pred_image)

    # then after each epoch/iteration
    avg_test_c_loss = np.mean(np.asarray(test_c_loss, dtype=np.float32), axis=0)

    loss_values = np.asarray(avg_test_c_loss.tolist(), dtype=np.float32)
    test_c_loss_keys = ['c_test_' + metric for metric in classifier.metrics_names]

    loss_keys = test_c_loss_keys
    logs = dict(zip(loss_keys, loss_values))

    # Log the losses
    with open(os.path.join(LOG_DIR, 'losses_cla.json'), 'a') as log_file:
        log_file.write("{\"Iter\":%d, %s;\n" % (index, logs))

    print("\nAvg test_c_loss: " + str(avg_test_c_loss))

    np.save(os.path.join(CLA_GEN_IMAGES_DIR, 'y_true_total.npy'), np.asarray(y_true_total))
    np.save(os.path.join(CLA_GEN_IMAGES_DIR, 'y_pred_total.npy'), np.asarray(y_pred_total))

    precision, recall, f1 = score(np.asarray(y_true_total), np.asarray(y_pred_total))

    print('precision: {}'.format(precision))
    print('recall: {}'.format(recall))
    print('fscore: {}'.format(f1))

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--mode", type=str)
    parser.add_argument("--enc_weights", type=str, default="None")
    parser.add_argument("--dec_weights", type=str, default="None")
    parser.add_argument("--cla_weights", type=str, default="None")
    parser.add_argument("--batch_size", type=int, default=BATCH_SIZE)
    parser.add_argument("--nice", dest="nice", action="store_true")
    parser.set_defaults(nice=False)
    args = parser.parse_args()
    return args

if __name__ == "__main__":
    args = get_args()
    if args.mode == "train":
        train(BATCH_SIZE=args.batch_size,
              ENC_WEIGHTS=args.enc_weights,
              DEC_WEIGHTS=args.dec_weights,
              CLA_WEIGHTS=args.cla_weights)

    if args.mode == "test":
        test(ENC_WEIGHTS=args.enc_weights,
             DEC_WEIGHTS=args.dec_weights,
             CLA_WEIGHTS=args.cla_weights)


text:
using AeccBot.CommandHandling;
using AeccBot.MessageRouting;
using AeccBot.MessageRouting.DataStore;
using Aecc.Models;

namespace AeccBot
{
    public class AeccStrings
    {
        private const string REFERENCE_CHANNEL = "test";

        //COMMANDS
        public const string CommandKeyword = "aecc"; // Used if the channel does not support mentions
        public const string Command_AddAggregationChannel = "disponible";
        public const string Command_AcceptRequest = "acepta";
        public const string Command_RejectRequest = "ignora";
        public const string Command_EndEngagement = "termina";
        public const string Command_InitiateEngagement = "charla";
        public const string Command_DeleteAggregationChannel = "no disponible";

        // COMMAND RESPONSES
        public const string HandleCommand_NotFound = "No he entendio el comando \"{0}\".";

        public const string AddNoAgentAvailable_Text = "Lo sentimos, pero ahora mismo el voluntario ya no está disponible. Prueba más adelante o elige a otro voluntario.";
        public const string AddNoAgentsAvailable_Text = "Lo sentimos, pero ahora mismo no hay ningún voluntario disponible.";
        public const string AddNoAgentsAvailable_Text2 = "Por favor, mantente a la espera hasta que te notifiquemos y luego escribe un saludo para comenzar la conversación. ¡Gracias!";

        public const string AddAggregationChannel_Text = "En este canal es donde se añadirán solicitudes.";
        public const string AddAggregationChannel_NotifyText = "\"{0}\" ya está disponible.";
        public const string AddAggregationChannel_AlreadyExistsText = "Esta canal ya está recibiendo solicitudes.";

        public const string DeleteAggregationChannel_Text = "Ya no estás disponible para recibir solicitudes. Para volver a estar disponible, teclea: {0}.";
        public const string DeleteAggregationChannel_NotExistText = "No estás disponible. Si quieres estar disponible, teclea: {0}";
        public const string DeleteAggregationChannel_InEngagementText = "Estás en una conversación. Si quieres cancelarla, teclea: {0}";
        public const string DeleteAggregationChannel_InEngagementEventText = "Estás en una conversación. Si quieres cancelarla, pulsa el botón cancelar.";

        public const string EndEngagement_NotFoundText = "No he podido encontrar la conversación";
        public const string EndEngagement_ErrorText = "No se ha podido finalizar la conversación";

        public const string AcceptAndRejectRequest_PartyNotFound = "No puedo encontrar la petición pendiente del beneficiario \"{0}\"";
        public const string AcceptAndRejectRequest_UserNotFound = "Falta el nombre del beneficiario.";
        public const string AcceptAndRejectRequest_NoRequest = "No hay peticiones pendientes.";
        public const string AcceptAndRejectRequest_InOtherConversation = "Ya estás involucrado en una conversación con \"{0}\"";
        public const string AcceptAndRejectRequest_NoAggregation = "Antes de entablar una conversación tienes que estar disponible. Para ello, teclea: {0}";
        public const string AcceptAndRejectRequest_Error = "Ha ocurrido un error.";

        public const string SendText_AlreadyAggregation = "Tienes que esperar a que se te envíe una solicitud para hablar con un beneficiario.";

        // ENGAGEMENT RESPONSES
        public const string EngagementInitiated_ClientText = "Danos un momento para iniciar la conversación.";
        public const string EngagementInitiated_AggregationNotFoundClientText = "No podemos contactar con el voluntario. Puedes intentarlo con otros voluntarios.";

        public const string EngagementInitiated_AlreadyClientText = "Estamos intentando iniciar la conversación. Si quieres cancelarla, teclea: {0}";
        public const string EngagementInitiated_AlreadyClientEventText = "Estamos intentando iniciar la conversación. Si quieres cancelarla, pulsa el botón cancelar.";
        public const string EngagementInitiated_TimeoutClientText = "Lo sentimos, el voluntario que has seleccionado ahora no puede hablar. Prueba más adelante o elige a otro voluntario.";

        public const string RejectRequest_OwnerText = "Petición del beneficiario \"{0}\" rechazada.";
        public const string RejectRequest_ClientText = "Lo sentimos, el voluntario que has seleccionado ahora no puede hablar. Prueba más adelante o elige a otro voluntario.";
        public const string RejectRequest_AlreadyRejectClientText = "Conversación cancelada.";

        public const string EngagementAdded_OwnerEventText = "Estás conectado con el beneficiario \"{0}\". Cuando termines la conversación pulsa el botón cancelar.";
        public const string EngagementAdded_OwnerText = "Estás conectado con el beneficiario \"{0}\". Cuando termines la conversación teclea: {1}.";
        public const string EngagementAdded_ClientText = "ahora estás hablando con \"{0}\"";

        public const string EngagementRemoved_OwnerEventText = "Conversación con el usuario \"{0}\" terminada. Sigues estando disponible para comunicarte con otros beneficiarios.";
        public const string EngagementRemoved_OwnerText = "Conversación con el usuario \"{0}\" terminada. Sigues estando disponible para comunicarte con otros beneficiarios. Para dejar de estar disponible, teclea: {1}";
        public const string EngagementRemoved_ClientText = "La conversación con \"{0}\" ha terminado.";

        //PENDING ENGAGEMENT REQUEST CARD
        public const string RequestCard_Title = "Petición de asistencia";
        public const string RequestCard_Subtitle = "Usuario: {0}";
        public const string RequestCard_Text = "Utiliza los botones para aceptar o rechazar.";
        public const string RequestCard_AcceptTitle = "Aceptar";
        public const string RequestCard_RejectTitle = "Rechazar";

        public const double Timeout_PendingRequest_InSg = 30;
        public const double Timeout_Engagement_InSg = 60 * 15;
        public const double Timeout_AggregationChecked_InSg = 60;

        private static IRoutingDataManager _routingDataManager;

        static AeccStrings()
        {
            _routingDataManager = WebApiConfig.RoutingDataManager;
        }

        public static string GetCommandKeyword(Party pendingRequest, Party aggregationParty)
        {
            string botName = _routingDataManager.ResolveBotNameInConversation(aggregationParty);
            string commandKeyword = (string.IsNullOrEmpty(botName) || pendingRequest.ChannelId != REFERENCE_CHANNEL) ? Commands.CommandKeyword : $"@{botName}";
            return commandKeyword;
        }

        public static string GetCommandKeyword(Party party)
        {
            return GetCommandKeyword(party, party);
        }
    }
}