def itemat(iterable, index):
    """Try to get the item at index position in iterable after iterate on
    iterable items.

    :param iterable: object which provides the method __getitem__ or __iter__.
    :param int index: item position to get.
    """
    result = None
    handleindex = True
    if isinstance(iterable, dict):
        handleindex = False
    else:
        try:
            result = iterable[index]
        except TypeError:
            handleindex = False
    if not handleindex:
        iterator = iter(iterable)
        if index < 0:
            index += len(iterable)
        while index >= 0:
            try:
                value = next(iterator)
            except StopIteration:
                raise IndexError('{0} index {1} out of range'.format(
                    iterable.__class__, index))
            else:
                if index == 0:
                    result = value
                    break
                index -= 1
    return result


def _escape_latex(string):
    """Format normal string to be LaTeX compliant."""
    string = string.replace('\\', '\\\\')
    string = string.replace('&', '\\&')
    string = string.replace('%', '\\%')
    string = string.replace('$', '\\$')
    string = string.replace('#', '\\#')
    string = string.replace('_', '\\_')
    string = string.replace('{', '\\{')
    string = string.replace('}', '\\}')
    string = string.replace('~', '\\textasciitilde ')
    string = string.replace('^', '\\textasciicircum ')
    return string


def j01AutoSuggest(fieldName, searchString, page, batchSize):
    """Returns the auto suggest result on the search string."""


def is_integer_like(val):
    """Returns validation of a value as an integer."""
    try:
        int(val)
        return True
    except (TypeError, ValueError, AttributeError):
        return False


def wms100format(format):
    """
    >>> wms100format('image/png')
    'PNG'
    >>> wms100format('image/GeoTIFF')
    """
    _mime_class, sub_type = format.split('/')
    sub_type = sub_type.upper()
    if sub_type in ['PNG', 'TIFF', 'GIF', 'JPEG']:
        return sub_type
    else:
        return None


def _expand_task_collection(factory):
    """Parse task collection task factory object, and return task list.
    :param dict factory: A loaded JSON task factory object.
    """
    return factory.tasks


def hasMultValuesPerItem(listOfD):
    """returns true if the dictionary has a list with more than one element"""
    if len(listOfD) > 1:
        return True
    for d in listOfD:
        for value in d.values():
            if len(value) > 1:
                return True
    return False


def cycles_sampling_preset_add(name: str='', remove_name: bool=False,
    remove_active: bool=False):
    """Add a Sampling Preset

    :param name: Name, Name of the preset, used to make the path name
    :type name: str
    :param remove_name: remove_name
    :type remove_name: bool
    :param remove_active: remove_active
    :type remove_active: bool
    """
    pass


def getUser(name):
    """ Return the user object for the user "name". if the user
        cannot be found, None will be returned.

        Permission - *Manage users*
        """


def make_url(url, **kwargs):
    """Build an Appveyor API url."""
    return 'https://ci.appveyor.com/api' + url.format(**kwargs)


def get_default_action_sampling_strategy():
    """
    If true, then we try each allowed first action at the root of the tree, in which case:
     - we spend as much computing resources to value each board state obtained after a first action,
     - the total number of MC samples may slightly differ from 'num_tirages_MC'.

    Otherwise, we randomly sample the first actions at the root of the tree, in which case:
     - we might over-sample or under-sample a few of them,
     - we have a better control of the total number of MC samples.
    """
    deterministic_sampling_of_actions_at_root = True
    return deterministic_sampling_of_actions_at_root


def is_number(obj):
    """
    evalua si es objecto es un numero

    Arguments
    ---------
    obj: any type

    Returns
    -------
    bool
        True if the object is a number
    """
    return isinstance(obj, (int, float))


def str_path(s):
    """Make a string appropriate to be a path compnent"""
    return s.lower().replace(' ', '_').replace('/', '_')


def proxnormrast(Z, r, p, gamma, mode=None, search={'t': 1, 's': 1, 'k': 1},
    init={'t': 1, 's': 0, 'k': 1}, tol=1e-12):
    """
    Prox of low-rank inducing Frobenius and spectral norm for
    integer-valued r.

    X,final = PROXNORMRAST(Z,r,p,gamma) produces the prox of the low-rank
    inducing norm gamma*||.||_{ell_p,r*} evaluated in Z for
    integer-valued r > 0, i.e.,
    a) X is the solution to the optimization problem:

        minimize_X gamma*||X||_{ell_p,r*} + 0.5*||X-Z||_{ell_2}^2,

    where p=2 or p='inf'.
    b) final["t"] and final["s"] are the final values of parameters to the two
    nested search. For p = 'inf', final["k"] is the final value of the third inner
    search parameter.
    If ||Z||_{ell_p^D,r} <= gamma, then t = s = k = None.

    ... = PROXNORMRAST(Z,r,p,gamma,option) allows us to specify furhter options:
        1. ... = PROXNORMRAST(Z,r,p,...,mode = 'vec') is used to flag that the
        vector-valued problem is to be solved.
        2. ... = PROXNORMRAST(Z,r,p,gamma,tol = tol_val) sets the relative
        tolerance of the deciding about zeros e.g. if Z is matrix then
        for all i: sigma(X)_i = 0 if |sigma(X)_i| <= tol_val*||Z||_{ell_p,r).
        Default value: tol_val = 1e-12.
        3. ... = PROXNORMRAST(Z,r,p,gamma,...,search = search_val) changes
        from default binary search to linear search over
        a) t if search_val["t"] = 0.
        b) s if search_val["s"] = 0.
        c) k if search_val["k"] = 0 (only for p = 'inf').
        4. ... = PROXNORMRAST(Z,r,p,gamma,...,init = init_val) changes
        from default binary search start values t_0 = 1, k_0 = 1, s_0 = 0
        to
        a) t_0 if init_val["t"] = t_0.
        b) s_0 if init_val["s"] = s_0.
        c) k_0 if init_val["k"] = k_0 (only for p = 'inf').

    ---------------
    References:
    - C. Grussler and A. Rantzer and P. Giselsson (2018):
    "Low-Rank Optimization with Convex Constraints",
    IEEE Transactions on Automatic Control, DOI: 10.1109/TAC.2018.2813009.

    - C. Grussler and P. Giselsson (2016):
    "Low-Rank Inducing Norms With Optimality Interpreations",
    arXiv:1612.03186v1.

    - C. Grussler and P. Giselsson (2017):
    "Local convergence of proximal splitting methods for rank constrained
    problems", pp. 702-708, IEEE 56th Annual Conference on Decision and Control
    (CDC), DOI: 10.1109/CDC.2017.8263743.

    - C. Grussler (2017):
    "Rank reduction with convex constraints", PhD Thesis,
    Department of Automatic Control, Lund Institute of Technology,
    Lund University, ISBN 978-91-7753-081-7.
    """
    import numpy as np
    from lripy.projrnorm import projrnorm
    if p != 2 and p != 'inf':
        raise ValueError('p can only be equal to 2 or inf')
    dim = Z.shape
    max_mn = np.max(dim)
    min_mn = np.min(dim)
    if mode == 'vec':
        if r > max_mn:
            raise ValueError('r is larger than max(Z.shape)')
    elif r > min_mn:
        raise ValueError('r is larger than min(Z.shape)')
    if p == 'inf':
        p = 1
    if mode == 'vec':
        Y, _, final = projrnorm(Z, None, r, p, gamma, search, init, tol)
        X = Z - Y
    else:
        U, S, V = np.linalg.svd(Z, full_matrices=False)
        y, _, final = projrnorm(S, None, r, p, gamma, search, init, tol)
        S = S - y
        X = U.dot(np.diag(S)).dot(V)
    return X, final


def project_opened(project):
    """This function is called after opening the project"""


def make_slist(l, t_sizes):
    """
    Create a list of tuples of given sizes from a list

    Parameters
    ----------
    l : list or ndarray
        List or array to pack into shaped list.
    t_sizes : list of ints
        List of tuple sizes.

    Returns
    -------
    slist : list of tuples
        List of tuples of lengths given by t_sizes.

    """
    out = []
    start = 0
    for s in t_sizes:
        out.append(l[start:start + s])
        start = start + s
    return out


def tmap(*args, **kwargs):
    """Like map, but returns a tuple."""
    return tuple(map(*args, **kwargs))


def parse_rwl(response):
    """Parse the json response for a RWL Hue remote."""
    press = str(response.state['buttonevent'])
    if press[-1] in ['0', '2']:
        button = str(press)[0] + '_click'
    else:
        button = str(press)[0] + '_hold'
    data = {'model': 'RWL', 'name': response.name, 'state': button,
        'battery': response.config['battery'], 'last_updated': response.
        state['lastupdated'].split('T')}
    return data


def expose(func):
    """Decorator for RPC endpoint methods that are exposed to the RPC client.

    If the dispatcher's access_policy is set to ExplicitRPCAccessPolicy then
    endpoint methods need to be explicitly exposed.::

        # foo() cannot be invoked by an RPC client
        def foo(self):
            pass

        # bar() can be invoked by an RPC client
        @rpc.expose
        def bar(self):
            pass

    """
    func.exposed = True
    return func


def default_page_layout():
    """Define a set of default layouts. A new simplelayout page
        automatically renders the defined layouts.

        Example:
            return {
                "default": [
                    {"cols": [{"blocks": []}]}
                ]
            }

        Results in one layout with one.
        Return None, will trigger a fallback to on layout with one column.
        """


def duplicate_move(OBJECT_OT_duplicate=None, TRANSFORM_OT_translate=None):
    """Duplicate selected objects and move them

    :param OBJECT_OT_duplicate: Duplicate Objects, Duplicate selected objects
    :param TRANSFORM_OT_translate: Move, Move selected items
    """
    pass


def remove_quotes(string):
    """
    Remove quotes from string.

    Ex.:
      "foo" -> foo
      'foo' -> foo
      'foo  -> 'foo

    """
    quotes = '"', "'"
    if string.startswith(quotes) and string.endswith(quotes):
        return string[1:-1]
    return string


def _construct(s):
    """ We override _construct here to add method binding. Basically
    we do this after the class is constructed but before the construct()
    elaboration happens."""
    if not s._dsl.constructed:
        if s._dsl.param_tree is None:
            kwargs = s._dsl.kwargs
        elif s._dsl.param_tree.leaf is None:
            kwargs = s._dsl.kwargs
        else:
            kwargs = s._dsl.kwargs.copy()
            if 'construct' in s._dsl.param_tree.leaf:
                more_args = s._dsl.param_tree.leaf['construct']
                kwargs.update(more_args)
        s._handle_decorated_methods()
        s.construct(*s._dsl.args, **kwargs)
        if s._dsl.call_kwargs is not None:
            s._continue_call_connect()
        s._dsl.constructed = True


@classmethod
def create(cls, *args, **kwargs):
    """
        Return always a new instance of the backend class
        """
    return cls(*args, **kwargs)


def open_xyz(xyz_file):
    """
    Opens an xyz file and returns a list of lists

    Parameters
    ----------
    xyz_file: String
        File path

    Returns
    ----------
    List of lists: List of lists
        Outer list is whole xyz file, each inner list is a line of the file containing
        the symbol and x,y,z coordinates

    """
    file = open(xyz_file, 'r').read().splitlines()
    if len(file[0].split()) != 1:
        exit('Not a proper xyz file!')
    natoms = int(file[0])
    if natoms != len(file[2:]):
        exit(
            'Number of atoms in header does not match number of atoms in file!'
            )
    else:
        return file[2:]


def _fix_bias(op_name, attrs, num_inputs):
    """A workaround for 'use_bias' attribute since onnx don't provide this attribute,
    we have to check the number of inputs to decide it."""
    if num_inputs == 3:
        attrs['no_bias'] = False
    elif num_inputs == 2:
        attrs['no_bias'] = True
    else:
        raise ValueError('Unexpected number of inputs for: {}'.format(op_name))
    return attrs


def thumbstrip(arr, orientation='horizontal'):
    """Make a filmstrip from an array of images"""
    assert orientation in ['horizontal', 'vertical']
    arr_t = arr if orientation == 'vertical' else arr.swapaxes(1, 2)
    s = arr_t.shape
    arr_strip = arr_t.reshape((s[0] * s[1],) + s[2:])
    return arr_strip if orientation == 'vertical' else arr_strip.swapaxes(0, 1)


@classmethod
def _from_dict(cls, _dict):
    """Initialize a Translation object from a json dictionary."""
    args = {}
    if 'translation' in _dict or 'translation_output' in _dict:
        args['translation_output'] = _dict.get('translation') or _dict.get(
            'translation_output')
    else:
        raise ValueError(
            "Required property 'translation' not present in Translation JSON")
    return cls(**args)


def tfilter(*args, **kwargs):
    """Like filter, but returns a tuple."""
    return tuple(filter(*args, **kwargs))


def normalize(score, base=2048):
    """ Use 2048 as base score if the performance equals baseline  """
    return int(base * score)


def fCO2frompHCarb(pH, CARB, K0, K1, K2):
    """Calculate CO2 fugacity from pH and carbonate ion.

    Based on CalculatefCO2frompHCarb, version 01.0, 06-12-2019, by Denis Pierrot.
    """
    H = 10.0 ** -pH
    return CARB * H ** 2 / (K0 * K1 * K2)


@classmethod
def summary(cls, gid, excl_fpath, gen_fpath, tm_dset, gen_index, excl_dict=
    None, res_class_dset=None, res_class_bin=None, excl_area=0.0081,
    power_density=None, cf_dset='cf_mean-means', lcoe_dset='lcoe_fcr-means',
    resolution=64, exclusion_shape=None, close=False, offshore_flags=None,
    friction_layer=None, args=None, data_layers=None):
    """Get a summary dictionary of a single supply curve point.

        Parameters
        ----------
        gid : int
            gid for supply curve point to analyze.
        excl_fpath : str
            Filepath to exclusions h5.
        gen_fpath : str
            Filepath to .h5 reV generation output results.
        tm_dset : str
            Dataset name in the techmap file containing the
            exclusions-to-resource mapping data.
        gen_index : np.ndarray
            Array of generation gids with array index equal to resource gid.
            Array value is -1 if the resource index was not used in the
            generation run.
        excl_dict : dict | None
            Dictionary of exclusion LayerMask arugments {layer: {kwarg: value}}
            None if excl input is pre-initialized.
        res_class_dset : str | np.ndarray | None
            Dataset in the generation file dictating resource classes.
            Can be pre-extracted resource data in np.ndarray.
            None if no resource classes.
        res_class_bin : list | None
            Two-entry lists dictating the single resource class bin.
            None if no resource classes.
        excl_area : float
            Area of an exclusion cell (square km).
        power_density : float | None | pd.DataFrame
            Constant power density float, None, or opened dataframe with
            (resource) "gid" and "power_density columns".
        cf_dset : str | np.ndarray
            Dataset name from gen containing capacity factor mean values.
            Can be pre-extracted generation output data in np.ndarray.
        lcoe_dset : str | np.ndarray
            Dataset name from gen containing LCOE mean values.
            Can be pre-extracted generation output data in np.ndarray.
        resolution : int | None
            SC resolution, must be input in combination with gid.
        exclusion_shape : tuple
            Shape of the exclusions extent (rows, cols). Inputing this will
            speed things up considerably.
        close : bool
            Flag to close object file handlers on exit.
        offshore_flags : np.ndarray | None
            Array of offshore boolean flags if available from wind generation
            data. None if offshore flag is not available.
        friction_layer : None | FrictionMask
            Friction layer with scalar friction values if valid friction inputs
            were entered. Otherwise, None to not apply friction layer.
        args : tuple | list, optional
            List of summary arguments to include. None defaults to all
            available args defined in the class attr, by default None
        data_layers : dict, optional
            Aggregation data layers. Must be a dictionary keyed by data label
            name. Each value must be another dictionary with "dset", "method",
            and "fpath", by default None

        Returns
        -------
        summary : dict
            Dictionary of summary outputs for this sc point.
        """
    kwargs = {'excl_dict': excl_dict, 'res_class_dset': res_class_dset,
        'res_class_bin': res_class_bin, 'excl_area': excl_area,
        'power_density': power_density, 'cf_dset': cf_dset, 'lcoe_dset':
        lcoe_dset, 'resolution': resolution, 'exclusion_shape':
        exclusion_shape, 'close': close, 'offshore_flags': offshore_flags,
        'friction_layer': friction_layer}
    with cls(gid, excl_fpath, gen_fpath, tm_dset, gen_index, **kwargs
        ) as point:
        summary = point.summarize(args=args, data_layers=data_layers)
    return summary


def _escape_xref(xref_match):
    """Escape things that need to be escaped if they're in a cross-reference.
    """
    xref = xref_match.group()
    xref = xref.replace('/', '%2F')
    xref = xref.replace('?', '%3F')
    xref = xref.replace('#', '%23')
    return xref


def _lte(field, value, document):
    """
    Returns True if the value of a document field is less than or
    equal to a given value
    """
    try:
        return document.get(field, None) <= value
    except TypeError:
        return False


def cupgrowth(D, Do, Y, fitMax=0.0, fitMin=0.0, Dh=float('inf')):
    """Find the additional length accrued by a tapered roller bearing due
    the press fit of the bearing cup in a housing bore.

    Parameters
    ==========

    D : float
        outside diameter of the cup.

    Do : float
        mean inside diameter of the outer ring (at midpoint of roller).

.   Y : float
        Y factor

    fitMax : float
        Maximum diametral interference of the cup in the housing bore.

    fitMin: float
        Minimum diametral interference of the cup in the housing bore.

    Dh : float
        housing outside diameter.  default: infinity

    Cone growth calculation based on the equation provided in Timken's catalog.
    (K = Y * .9725)

    Returns
    =======

    out: tuple
        (cupgrowthMax, cupgrowthMin)... i.e., axial length increase
    """
    K = Y * 0.9725
    try:
        cupgrowthmin = 0.5 * (K / 0.39) * (Do / D * (1 - (D / Dh) ** 2) / (
            1 - (Do / Dh) ** 2)) * abs(fitMin)
        cupgrowthmax = 0.5 * (K / 0.39) * (Do / D * (1 - (D / Dh) ** 2) / (
            1 - (Do / Dh) ** 2)) * abs(fitMax)
        return cupgrowthmax, cupgrowthmin
    except ZeroDivisionError:
        return 0.0, 0.0


def rint(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise rounded value to the nearest integer of the input.

    .. note::
       - For input ``n.5`` ``rint`` returns ``n`` while ``round`` returns ``n+1``.
       - For input ``-n.5`` both ``rint`` and ``round`` returns ``-n-1``.

    Example::

       rint([-1.5, 1.5, -1.9, 1.9, 2.1]) = [-2.,  1., -2.,  2.,  2.]

    The storage type of ``rint`` output depends upon the input storage type:

       - rint(default) = default
       - rint(row_sparse) = row_sparse
       - rint(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_basic.cc:L799

    Parameters
    ----------
    data : Symbol
        The input array.

    name : string, optional.
        Name of the resulting symbol.

    Returns
    -------
    Symbol
        The result symbol.
    """
    return 0,


def getid(obj):
    """Get obj's id or object itself if no id
    Abstracts the common pattern of allowing both an object or
    an object's ID as a parameter when dealing with relationships.
    """
    try:
        return obj.id
    except AttributeError:
        return obj


def set_hide_expired_events(onoff):
    """If set to True, the expired events will not be displayed.
        """


@classmethod
def isnum(cls, nextchar):
    """ Whether the next character is part of a number """
    return nextchar.isdigit()


@classmethod
def no_password_link_view_report_failed(cls, val):
    """
        Create an instance of this class set to the
        ``no_password_link_view_report_failed`` tag with value ``val``.

        :param NoPasswordLinkViewReportFailedType val:
        :rtype: EventType
        """
    return cls('no_password_link_view_report_failed', val)


@classmethod
def parse(class_, f):
    """Parse a transaction Tx from the file-like object f."""
    raise NotImplemented()


@staticmethod
def _uri_parse_error(reason):
    """uri parsing helper -- creates preformatted error message"""
    return ValueError('Invalid otpauth uri: %s' % (reason,))


def binary_string(number: int) ->str:
    """Number to binary string

    :param number: some number (an integer) to turn into a binary string
    :return: Some string which is the binary string
    :rtype: str

    .. doctest:: python

        >>> binary_string(200)
        '11001000'
        >>> binary_string(10)
        '1010'

    """
    return bin(number)[2:]


def _expand_for_carryover(max_vol, plan, **kwargs):
    """
    Divide volumes larger than maximum volume into separate transfers
    """
    max_vol = float(max_vol)
    carryover = kwargs.get('carryover', True)
    if not carryover:
        return plan
    new_transfer_plan = []
    for p in plan:
        source = p['aspirate']['location']
        target = p['dispense']['location']
        volume = float(p['aspirate']['volume'])
        while volume > max_vol * 2:
            new_transfer_plan.append({'aspirate': {'location': source,
                'volume': max_vol}, 'dispense': {'location': target,
                'volume': max_vol}})
            volume -= max_vol
        if volume > max_vol:
            volume /= 2
            new_transfer_plan.append({'aspirate': {'location': source,
                'volume': float(volume)}, 'dispense': {'location': target,
                'volume': float(volume)}})
        new_transfer_plan.append({'aspirate': {'location': source, 'volume':
            float(volume)}, 'dispense': {'location': target, 'volume':
            float(volume)}})
    return new_transfer_plan


def rcbrt(data=None, out=None, name=None, **kwargs):
    """Returns element-wise inverse cube-root value of the input.

    .. math::
       rcbrt(x) = 1/\\sqrt[3]{x}

    Example::

       rcbrt([1,8,-125]) = [1.0, 0.5, -0.2]

    Defined in src/operator/tensor/elemwise_unary_op_pow.cc:L269

    Parameters
    ----------
    data : NDArray
        The input array.

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


def _get_to_field(field):
    """
    Extract remote field with which model had relation.
    """
    remote_side = getattr(field, 'remote_side', None)
    return list(remote_side)[0] if remote_side else None


def stringint(k, n):
    """ returns string of k by placing zeros before to have n characters
    ex: 1 -> '0001'
    15 -> '0015'

    # ugly way: better use  '%04d'%k  for n=4 for isntance
    """
    strint = str(k)
    res = '0' * (n - len(strint)) + strint
    return res


def create_streaming_distribution_with_tags(StreamingDistributionConfigWithTags
    =None):
    """
    Create a new streaming distribution with tags.
    See also: AWS API Documentation

    :example: response = client.create_streaming_distribution_with_tags(
        StreamingDistributionConfigWithTags={
            'StreamingDistributionConfig': {
                'CallerReference': 'string',
                'S3Origin': {
                    'DomainName': 'string',
                    'OriginAccessIdentity': 'string'
                },
                'Aliases': {
                    'Quantity': 123,
                    'Items': [
                        'string',
                    ]
                },
                'Comment': 'string',
                'Logging': {
                    'Enabled': True|False,
                    'Bucket': 'string',
                    'Prefix': 'string'
                },
                'TrustedSigners': {
                    'Enabled': True|False,
                    'Quantity': 123,
                    'Items': [
                        'string',
                    ]
                },
                'PriceClass': 'PriceClass_100'|'PriceClass_200'|'PriceClass_All',
                'Enabled': True|False
            },
            'Tags': {
                'Items': [
                    {
                        'Key': 'string',
                        'Value': 'string'
                    },
                ]
            }
        }
    )

    :type StreamingDistributionConfigWithTags: dict
    :param StreamingDistributionConfigWithTags: [REQUIRED]
            The streaming distribution's configuration information.
            StreamingDistributionConfig (dict) -- [REQUIRED]A streaming distribution Configuration.
            CallerReference (string) -- [REQUIRED]A unique number that ensures that the request can't be replayed. If the CallerReference is new (no matter the content of the StreamingDistributionConfig object), a new streaming distribution is created. If the CallerReference is a value that you already sent in a previous request to create a streaming distribution, and the content of the StreamingDistributionConfig is identical to the original request (ignoring white space), the response includes the same information returned to the original request. If the CallerReference is a value that you already sent in a previous request to create a streaming distribution but the content of the StreamingDistributionConfig is different from the original request, CloudFront returns a DistributionAlreadyExists error.
            S3Origin (dict) -- [REQUIRED]A complex type that contains information about the Amazon S3 bucket from which you want CloudFront to get your media files for distribution.
            DomainName (string) -- [REQUIRED]The DNS name of the Amazon S3 origin.
            OriginAccessIdentity (string) -- [REQUIRED]The CloudFront origin access identity to associate with the RTMP distribution. Use an origin access identity to configure the distribution so that end users can only access objects in an Amazon S3 bucket through CloudFront.
            If you want end users to be able to access objects using either the CloudFront URL or the Amazon S3 URL, specify an empty OriginAccessIdentity element.
            To delete the origin access identity from an existing distribution, update the distribution configuration and include an empty OriginAccessIdentity element.
            To replace the origin access identity, update the distribution configuration and specify the new origin access identity.
            For more information, see Using an Origin Access Identity to Restrict Access to Your Amazon S3 Content in the Amazon Amazon CloudFront Developer Guide .
            Aliases (dict) --A complex type that contains information about CNAMEs (alternate domain names), if any, for this streaming distribution.
            Quantity (integer) -- [REQUIRED]The number of CNAME aliases, if any, that you want to associate with this distribution.
            Items (list) --A complex type that contains the CNAME aliases, if any, that you want to associate with this distribution.
            (string) --

            Comment (string) -- [REQUIRED]Any comments you want to include about the streaming distribution.
            Logging (dict) --A complex type that controls whether access logs are written for the streaming distribution.
            Enabled (boolean) -- [REQUIRED]Specifies whether you want CloudFront to save access logs to an Amazon S3 bucket. If you do not want to enable logging when you create a streaming distribution or if you want to disable logging for an existing streaming distribution, specify false for Enabled , and specify empty Bucket and Prefix elements. If you specify false for Enabled but you specify values for Bucket and Prefix , the values are automatically deleted.
            Bucket (string) -- [REQUIRED]The Amazon S3 bucket to store the access logs in, for example, myawslogbucket.s3.amazonaws.com .
            Prefix (string) -- [REQUIRED]An optional string that you want CloudFront to prefix to the access log filenames for this streaming distribution, for example, myprefix/ . If you want to enable logging, but you do not want to specify a prefix, you still must include an empty Prefix element in the Logging element.
            TrustedSigners (dict) -- [REQUIRED]A complex type that specifies any AWS accounts that you want to permit to create signed URLs for private content. If you want the distribution to use signed URLs, include this element; if you want the distribution to use public URLs, remove this element. For more information, see Serving Private Content through CloudFront in the Amazon CloudFront Developer Guide .
            Enabled (boolean) -- [REQUIRED]Specifies whether you want to require viewers to use signed URLs to access the files specified by PathPattern and TargetOriginId .
            Quantity (integer) -- [REQUIRED]The number of trusted signers for this cache behavior.
            Items (list) --
            Optional : A complex type that contains trusted signers for this cache behavior. If Quantity is 0 , you can omit Items .
            (string) --

            PriceClass (string) --A complex type that contains information about price class for this streaming distribution.
            Enabled (boolean) -- [REQUIRED]Whether the streaming distribution is enabled to accept user requests for content.
            Tags (dict) -- [REQUIRED]A complex type that contains zero or more Tag elements.
            Items (list) --A complex type that contains Tag elements.
            (dict) --A complex type that contains Tag key and Tag value.
            Key (string) -- [REQUIRED]A string that contains Tag key.
            The string length should be between 1 and 128 characters. Valid characters include a-z , A-Z , 0-9 , space, and the special characters _ - . : / = + @ .
            Value (string) --A string that contains an optional Tag value.
            The string length should be between 0 and 256 characters. Valid characters include a-z , A-Z , 0-9 , space, and the special characters _ - . : / = + @ .

    :rtype: dict
    :return: {
        'StreamingDistribution': {
            'Id': 'string',
            'ARN': 'string',
            'Status': 'string',
            'LastModifiedTime': datetime(2015, 1, 1),
            'DomainName': 'string',
            'ActiveTrustedSigners': {
                'Enabled': True|False,
                'Quantity': 123,
                'Items': [
                    {
                        'AwsAccountNumber': 'string',
                        'KeyPairIds': {
                            'Quantity': 123,
                            'Items': [
                                'string',
                            ]
                        }
                    },
                ]
            },
            'StreamingDistributionConfig': {
                'CallerReference': 'string',
                'S3Origin': {
                    'DomainName': 'string',
                    'OriginAccessIdentity': 'string'
                },
                'Aliases': {
                    'Quantity': 123,
                    'Items': [
                        'string',
                    ]
                },
                'Comment': 'string',
                'Logging': {
                    'Enabled': True|False,
                    'Bucket': 'string',
                    'Prefix': 'string'
                },
                'TrustedSigners': {
                    'Enabled': True|False,
                    'Quantity': 123,
                    'Items': [
                        'string',
                    ]
                },
                'PriceClass': 'PriceClass_100'|'PriceClass_200'|'PriceClass_All',
                'Enabled': True|False
            }
        },
        'Location': 'string',
        'ETag': 'string'
    }

    :returns:
    (string) --

    """
    pass


@staticmethod
def _locate_entry(entries, key):
    """ Search the binary tree structure for the correct entry.

        :param key: the key to search the master pop table for a given entry
        :return: the entry for this given key
        :rtype: :py:class:`_MasterPopEntry`
        """
    imin = 0
    imax = len(entries)
    while imin < imax:
        imid = (imax + imin) // 2
        entry = entries[imid]
        if key & entry['mask'] == entry['key']:
            return entry
        if key > entry['key']:
            imin = imid + 1
        else:
            imax = imid
    return None


def get_keys(src, dst, keys):
    """
    Copies the value of keys from source object to dest object

    :param src:
    :param dst:
    :param keys:
    :return:
    """
    for key in keys:
        dst[key] = src[key] if key in src else None


@staticmethod
def _get_img_type(soup):
    """Return the file format for the images"""
    url = soup.find(property='og:image')['content']
    return url.split('.')[-1]


@classmethod
def member_add_external_id(cls, val):
    """
        Create an instance of this class set to the ``member_add_external_id``
        tag with value ``val``.

        :param MemberAddExternalIdType val:
        :rtype: EventType
        """
    return cls('member_add_external_id', val)


@staticmethod
def get_full_url(url, use_ssl, host):
    """Return the full URL to a DCOR resource

        Parameters
        ----------
        url: str
            Full URL or resource identifier; valid values are

            - https://dcor.mpl.mpg.de/api/3/action/dcserv?id=caab96f6-
              df12-4299-aa2e-089e390aafd5'
            - dcor.mpl.mpg.de/api/3/action/dcserv?id=caab96f6-df12-
              4299-aa2e-089e390aafd5
            - caab96f6-df12-4299-aa2e-089e390aafd5
        use_ssl: bool
            Set this to False to disable SSL (should only be used for
            testing). Defaults to None (does not force SSL if the URL
            starts with "http://").
        host: str
            Use this host if it is not specified in `url`
        """
    if use_ssl is None:
        if url.startswith('http://'):
            web = 'http'
        else:
            web = 'https'
    elif use_ssl:
        web = 'https'
    else:
        web = 'http'
    if url.count('://'):
        base = url.split('://', 1)[1]
    else:
        base = url
    if base.count('/'):
        host, api = base.split('/', 1)
    else:
        api = 'api/3/action/dcserv?id=' + base
    new_url = '{}://{}/{}'.format(web, host, api)
    return new_url


def _get_df_between_date_by_index(data_df, date_frm, date_to):
    """
    该函数仅用于 return_risk_analysis 中计算使用
    :param data_df:
    :param date_frm:
    :param date_to:
    :return:
    """
    if date_frm is not None and date_to is not None:
        new_data_df = data_df[(data_df.index >= date_frm) & (data_df.index <=
            date_to)]
    elif date_frm is not None:
        new_data_df = data_df[data_df.index >= date_frm]
    elif date_to is not None:
        new_data_df = data_df[data_df.index <= date_to]
    else:
        new_data_df = data_df
    return new_data_df


@classmethod
def from_excellon(cls, line, **kwargs):
    """ Create a ToolSelectionStmt from an excellon file line.

        Parameters
        ----------
        line : string
            Line from an Excellon file

        Returns
        -------
        tool_statement : ToolSelectionStmt
            ToolSelectionStmt representation of `line.`
        """
    line = line[1:]
    compensation_index = None
    if len(line) <= 3:
        tool = int(line)
    else:
        tool = int(line[:2])
        compensation_index = int(line[2:])
    return cls(tool, compensation_index, **kwargs)


def uniqify(l):
    """uniqify in place"""
    s = set()
    idxs = []
    for i, item in enumerate(l):
        if item in s:
            idxs.append(i)
        else:
            s.add(item)
    for i in reversed(idxs):
        l.pop(i)
    return l


def sub_dfs_by_num(df, num):
    """Get a generator yielding num consecutive sub-dataframes of the given df.

    Arguments
    ---------
    df : pandas.DataFrame
        The dataframe for which to get sub-dataframes.
    num : int
        The number of sub-dataframe to divide the given dataframe into.

    Returns
    -------
    generator
        A generator yielding n consecutive sub-dataframes of the given df.

    Example
    -------
    >>> import pandas as pd; import pdutil;
    >>> data = [[23, "Jen"], [42, "Ray"], [15, "Fin"]]
    >>> df = pd.DataFrame(data, columns=['age', 'name'])
    >>> for subdf in pdutil.iter.sub_dfs_by_num(df, 2): print(subdf)
       age name
    0   23  Jen
    1   42  Ray
       age name
    2   15  Fin
    """
    size = len(df) / float(num)
    for i in range(num):
        yield df.iloc[int(round(size * i)):int(round(size * (i + 1)))]


@staticmethod
def check_error(hresult):
    """Check a given HRESULT for errors.

        Throws an error for non-S_OK HRESULTs.

        """
    S_OK = 0
    E_NOINTERFACE = 2147500034
    E_POINTER = 2147500035
    E_OUTOFMEMORY = 2147942414
    E_INVALIDARG = 2147942487
    AUDCLNT_E_UNSUPPORTED_FORMAT = 2290679816
    if hresult == S_OK:
        return
    elif hresult + 2 ** 32 == E_NOINTERFACE:
        raise RuntimeError(
            'The specified class does not implement the requested interface, or the controlling IUnknown does not expose the requested interface.'
            )
    elif hresult + 2 ** 32 == E_POINTER:
        raise RuntimeError('An argument is NULL.')
    elif hresult + 2 ** 32 == E_INVALIDARG:
        raise RuntimeError('invalid argument')
    elif hresult + 2 ** 32 == E_OUTOFMEMORY:
        raise RuntimeError('out of memory')
    elif hresult + 2 ** 32 == AUDCLNT_E_UNSUPPORTED_FORMAT:
        raise RuntimeError('unsupported format')
    else:
        raise RuntimeError('Error {}'.format(hex(hresult + 2 ** 32)))


@classmethod
def AddArguments(cls, argument_group):
    """Adds command line arguments to an argument group.

    This function takes an argument parser or an argument group object and adds
    to it all the command line arguments this helper supports.

    Args:
      argument_group (argparse._ArgumentGroup|argparse.ArgumentParser):
          argparse group.
    """
    argument_group.add_argument('--artifact_filters', '--artifact-filters',
        dest='artifact_filter_string', type=str, default=None, metavar=
        'ARTIFACT_FILTERS', action='store', help=
        'Names of forensic artifact definitions, provided on the command command line (comma separated). Forensic artifacts are stored in .yaml files that are directly pulled from the artifact definitions project. You can also specify a custom artifacts yaml file (see --custom_artifact_definitions). Artifact definitions can be used to describe and quickly collect data of interest, such as specific files or Windows Registry keys.'
        )
    argument_group.add_argument('--artifact_filters_file',
        '--artifact-filters_file', dest='artifact_filters_file', type=str,
        default=None, metavar='PATH', action='store', help=
        'Names of forensic artifact definitions, provided in a file with one artifact name per line. Forensic artifacts are stored in .yaml files that are directly pulled from the artifact definitions project. You can also specify a custom artifacts yaml file (see --custom_artifact_definitions). Artifact definitions can be used to describe and quickly collect data of interest, such as specific files or Windows Registry keys.'
        )


def pytest_unconfigure(config):
    """ called before test process is exited.

    :param _pytest.config.Config config: pytest config object
    """


def on_node_saved(sender, instance, created, **kwargs):
    """
    Called whenever new record if observed tree inserted, or whenever
    is node updated. Instance is marked as moved when parent of instance
    was changed

    :param sender:
    :param instance:
    :param created:
    :param kwargs:
    :return:
    """
    if not getattr(instance, 'acl_propagation_stopped', False):
        instance.acl.insert(created=created)


@classmethod
def create(cls, root, schema):
    """
        Create an object based on the root tag name.
        @param root: An XML root element.
        @type root: L{Element}
        @param schema: A schema object.
        @type schema: L{schema.Schema}
        @return: The created object.
        @rtype: L{SchemaObject}
        """
    fn = cls.tags.get(root.name)
    if fn is not None:
        return fn(schema, root)
    else:
        return None


def _range_rule(lbound, ubound) ->float:
    """
    Uses a modified version (dividing by 10 instead of 4) of
    the range rule heuristic to provide a very rough estimate
    of what a good standard deviation could be for a normal
    distribution to sample genetic mutations from for a
    hyperparameter having the range (lbound, ubound).
    """
    return (ubound - lbound) / 10


@staticmethod
def get_state_type():
    """
        This is needed so the service framework knows the
        state type of the current state.
        return::str The state and update type of this state.
        """
    return 'full_update_in'


@classmethod
def add_hook(cls, hook_type, hook_func):
    """Add a new hook of specified type.

        :param cls: class that registers hooks
        :param hook_type: hook type, e.g., '__pre_parse_args__'
        :param hook_func: hook function
        """
    if hook_type not in cls._hooks_map:
        cls._hooks_map[hook_type] = []
    cls._hooks_map[hook_type].append(hook_func)


def file_loc():
    """Return file and line number"""
    import sys
    import inspect
    try:
        raise Exception
    except:
        file_ = '.../' + '/'.join(inspect.currentframe().f_code.co_filename
            .split('/')[-3:])
        line_ = sys.exc_info()[2].tb_frame.f_back.f_lineno
        return '{}:{}'.format(file_, line_)


def check_permissions(permissions, context):
    """
    Check if it's permitted.
    Raises an appropriate exception if it's is not permitted.
    """
    for permission in permissions:
        if not permission.has_permission(context):
            return False
    return True


def resolve_name(name):
    """Resolve a name like ``module.object`` to an object and return it.

    Raise `ImportError` if the module or name is not found.
    """
    parts = name.split('.')
    cursor = len(parts) - 1
    module_name = parts[:cursor]
    attr_name = parts[-1]
    while cursor > 0:
        try:
            ret = __import__('.'.join(module_name), fromlist=[attr_name])
            break
        except ImportError:
            if cursor == 0:
                raise
            cursor -= 1
            module_name = parts[:cursor]
            attr_name = parts[cursor]
            ret = ''
    for part in parts[cursor:]:
        try:
            ret = getattr(ret, part)
        except AttributeError:
            raise ImportError(name)
    return ret


@classmethod
def has_archiving(cls):
    """Returns whether it supports archiving items on the fetch process.

        :returns: this backend supports items archive
        """
    return True


def render_git_describe_long(pieces):
    """TAG-DISTANCE-gHEX[-dirty].

    Like 'git describe --tags --dirty --always -long'.
    The distance/hash is unconditional.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


def midpoint_point_point(a, b):
    """Compute the midpoint of two points lying in the XY-plane.

    Parameters
    ----------
    a : sequence of float
        XYZ coordinates of the first point.
    b : sequence of float
        XYZ coordinates of the second point.

    Returns
    -------
    list
        XYZ coordinates of the midpoint.

    """
    return [0.5 * (a[0] + b[0]), 0.5 * (a[1] + b[1]), 0.5 * (a[2] + b[2])]


def save_df(df, name, engine='pickle', key='df', **kwargs):
    """Save a dataframe to disk.
    """
    meth = 'to_{}'.format(engine)
    if engine == 'hdf':
        kwargs['key'] = key
    if engine == 'csv':
        kwargs.setdefault('index', False)
    getattr(df, meth)(name, **kwargs)


def _mask_first_axes(x, mask, c_contig=None):
    """Fast application of the mask for both C or Fortran-ordered x.
    """
    if c_contig is None:
        c_contig = x.flags.c_contiguous
    if c_contig:
        y = x[mask]
    else:
        shape = (mask.size,) + x.shape[mask.ndim:]
        y = x.reshape(shape, order='F')[mask.ravel('F')]
    return y, c_contig


def hamming_distance(left_bytes, right_bytes):
    """Get the binary Hamming distance between two sequences of bytes."""
    if len(left_bytes) != len(right_bytes):
        raise ValueError('Length of both sequences must match')
    result = 0
    for left, right in zip(left_bytes, right_bytes):
        diff = left ^ right
        for j in range(8):
            result += diff >> j & 1
    return result


def _get_unique_smem_id(name):
    """Due to bug with NVVM invalid internalizing of shared memory in the
    PTX output.  We can't mark shared memory to be internal. We have to
    ensure unique name is generated for shared memory symbol.
    """
    global _unique_smem_id
    _unique_smem_id += 1
    return '{0}_{1}'.format(name, _unique_smem_id)


def size(roi):
    """Return the number of elements in roi"""
    return roi.size


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


@classmethod
def get_args(cls, dist, header=None):
    """
        Yield write_script() argument tuples for a distribution's
        console_scripts and gui_scripts entry points.
        """
    if header is None:
        header = cls.get_header()
    spec = str(dist.as_requirement())
    for type_ in ('console', 'gui'):
        group = type_ + '_scripts'
        for name, ep in dist.get_entry_map(group).items():
            cls._ensure_safe_name(name)
            script_text = cls.template % locals()
            args = cls._get_script_args(type_, name, header, script_text)
            for res in args:
                yield res


def to_iterable(value, allow_none=True):
    """
    Tries to convert the given value to an iterable, if necessary.
    If the given value is a list, a list is returned; if it is a string, a list
    containing one string is returned, ...

    :param value: Any object
    :param allow_none: If True, the method returns None if value is None, else
                       it returns an empty list
    :return: A list containing the given string, or the given value
    """
    if value is None:
        if allow_none:
            return None
        return []
    elif isinstance(value, (list, tuple, set, frozenset)):
        return value
    return [value]


@staticmethod
def getJavaPackage():
    """ Returns package name String. """
    return 'com.microsoft.ml.spark.stages.DynamicMiniBatchTransformer'


def detectAnd(sensors, obj):
    """Returns True if all sensors detect the object"""
    result = True
    for s in sensors:
        result = result and s.detect(obj)
        if not result:
            return result
    return result


def jaccard_similarity(list1, list2):
    """Jaccard score between two lists.

    Parameters
    ----------
    list1
    list2

    Returns
    -------
    float
        Jaccard similarity between elements in list.

    """
    s1 = set(list1)
    s2 = set(list2)
    return len(s1.intersection(s2)) / len(s1.union(s2))


def survey_cadence_arrays(log, surveyCadenceSettings, pathToOutputDirectory,
    pathToOutputPlotDirectory, plot=False):
    """
    *Generate the survey cadence arrays for each filter*

    **Key Arguments:**
        - ``log`` -- logger
        - ``surveyCadenceSettings`` -- the survey cadence parameters as set in the simulation settings file
        - ``pathToOutputDirectory`` -- path to the output directory (provided by the user)
        - ``pathToOutputPlotDirectory`` -- path to add plots to
        - ``plot`` -- generate plot?

    **Return:**
        - ``cadenceDictionary`` -- a dictionary of { band : observedDayList }
    """
    import numpy as np
    import matplotlib.pyplot as plt
    lunarMonth = 29.3
    surveyYear = 12.0 * lunarMonth
    cadenceDictionary = {}
    obsFraction = surveyCadenceSettings['Observable Fraction of Year']
    lossFraction = surveyCadenceSettings['Fraction of Year Lost to Weather etc'
        ]
    for thisFilter in surveyCadenceSettings['Filters']:
        band = thisFilter['band']
        firstDay = thisFilter['day of year of first scheduled observation']
        repeatEvery = thisFilter['repeat every ? days']
        moonFraction = thisFilter['Fraction of Lunar Month Lost to Moon']
        finalObsDayOfMonth = lunarMonth * (1.0 - moonFraction)
        monthCount = 0
        day = 1
        monthDay = 1
        moonDayList = []
        while day < surveyYear:
            while monthDay < int(lunarMonth):
                if monthDay <= finalObsDayOfMonth:
                    moonDayList.append(day)
                monthDay += 1
                day += 1
            monthCount += 1
            day = int(lunarMonth * monthCount)
            monthDay = 0
        day = firstDay
        nextObs = firstDay
        obsDaysList = []
        finalObsDayOfYear = obsFraction * surveyYear
        while day <= finalObsDayOfYear:
            randNum = np.random.rand()
            if day == nextObs:
                if day in moonDayList and randNum > lossFraction:
                    obsDaysList.append(day)
                nextObs = day + repeatEvery
            day += 1
        cadenceDictionary[band] = obsDaysList
    if plot:
        fig = plt.figure(num=None, figsize=(8, 8), dpi=600, facecolor=None,
            edgecolor=None, frameon=True)
        ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True, frameon=False)
        ax.set_ylim(0, 12)
        for k, v in cadenceDictionary.iteritems():
            x = 2 * np.pi * np.array(v) / surveyYear
            y = np.ones(len(x)) * 10.0
            if k in ['g', 'B']:
                color = '#268bd2'
            elif k in ['r', 'V']:
                color = '#859900'
            elif k in ['R', 'i']:
                color = '#cb4b16'
            elif k in ['I', 'z']:
                color = '#dc322f'
            else:
                color = '#b58900'
            plt.scatter(x, y, s=50, c=color, marker='o', cmap=None, norm=
                None, vmin=None, vmax=None, alpha=0.5, linewidths=None,
                edgecolor='w', verts=None, hold=True)
        circleTicks = np.arange(0, 350, 30)
        tickLabels = []
        for tick in circleTicks:
            tickLabels.append('%s days' % (tick,))
        plt.xticks(2 * np.pi * circleTicks / surveyYear, tickLabels)
        plt.yticks([])
        title = 'Cadence Wheel for Simulated Survey'
        plt.title(title)
        fileName = pathToOutputPlotDirectory + title.replace(' ', '_') + '.png'
        plt.savefig(fileName)
        plt.clf()
    return cadenceDictionary


@classmethod
def paper_as_files(cls, val):
    """
        Create an instance of this class set to the ``paper_as_files`` tag with
        value ``val``.

        :param PaperAsFilesValue val:
        :rtype: UserFeatureValue
        """
    return cls('paper_as_files', val)


def psi_K_Mg_HCO3_HMW84(T, P):
    """c-c'-a: potassium magnesium bicarbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


@classmethod
def _form_media_range(cls, type_subtype, media_type_params):
    """
        Combine `type_subtype` and `media_type_params` to form a media range.

        `type_subtype` is a ``str``, and `media_type_params` is an iterable of
        (parameter name, parameter value) tuples.
        """
    media_type_params_segment = ''
    for param_name, param_value in media_type_params:
        param_value = cls._escape_and_quote_parameter_value(param_value=
            param_value)
        media_type_params_segment += ';' + param_name + '=' + param_value
    return type_subtype + media_type_params_segment


def _dict_mod_replace(to_dict, attrs_dict):
    """Replaces attribute values in to_dict with those from attrs_dict.

    :param to_dict: The dictionary to modify
    :type to_dict: dict(str, list[str]) or AttrsDict
    :param attrs_dict: Dictionary of attributes to set in ``to_dict``
    :type attrs_dict: dict(str, list[str]) or AttrsDict
    :return: None, modifies ``to_dict`` in place.
    :rtype: None
    """
    to_dict.update(attrs_dict)


def move_back(fh):
    """
    move file ptr one step back
    :param fh: file object
    :return:
    """
    fh.seek(fh.tell() - 1)


def init_helper(obj, kw):
    """
  Helper for classes with attributes initialized by keyword arguments.

  Inside a class's __init__, this will copy keyword arguments to fields
  of the same name.  See libopenflow for an example.
  """
    for k, v in kw.items():
        if not hasattr(obj, k):
            raise TypeError(obj.__class__.__name__ + ' constructor got ' +
                "unexpected keyword argument '" + k + "'")
        setattr(obj, k, v)


def uninstall(context):
    """Uninstall script"""


def df_to_ca(df):
    """Extract only alpha carbons from dataframe."""
    ca = df[df['atom_name'] == 'CA']
    ca.index.name = 'df_index'
    ca = ca.reset_index()
    return ca


def getRenderingFor(iprops):
    """Return a deferred that fires with interpolation with the given properties

        @param iprops: the L{IProperties} provider supplying the properties.
        """


def detach_static_ip(staticIpName=None):
    """
    Detaches a static IP from the Amazon Lightsail instance to which it is attached.
    See also: AWS API Documentation

    :example: response = client.detach_static_ip(
        staticIpName='string'
    )

    :type staticIpName: string
    :param staticIpName: [REQUIRED]
            The name of the static IP to detach from the instance.

    :rtype: dict
    :return: {
        'operations': [
            {
                'id': 'string',
                'resourceName': 'string',
                'resourceType': 'Instance'|'StaticIp'|'KeyPair'|'InstanceSnapshot'|'Domain'|'PeeredVpc',
                'createdAt': datetime(2015, 1, 1),
                'location': {
                    'availabilityZone': 'string',
                    'regionName': 'us-east-1'|'us-west-1'|'us-west-2'|'eu-west-1'|'eu-central-1'|'ap-south-1'|'ap-southeast-1'|'ap-southeast-2'|'ap-northeast-1'|'ap-northeast-2'
                },
                'isTerminal': True|False,
                'operationDetails': 'string',
                'operationType': 'DeleteInstance'|'CreateInstance'|'StopInstance'|'StartInstance'|'RebootInstance'|'OpenInstancePublicPorts'|'PutInstancePublicPorts'|'CloseInstancePublicPorts'|'AllocateStaticIp'|'ReleaseStaticIp'|'AttachStaticIp'|'DetachStaticIp'|'UpdateDomainEntry'|'DeleteDomainEntry'|'CreateDomain'|'DeleteDomain'|'CreateInstanceSnapshot'|'DeleteInstanceSnapshot'|'CreateInstancesFromSnapshot',
                'status': 'NotStarted'|'Started'|'Failed'|'Completed',
                'statusChangedAt': datetime(2015, 1, 1),
                'errorCode': 'string',
                'errorDetails': 'string'
            },
        ]
    }

    """
    pass


@classmethod
def register_converter(cls, name, converter):
    """
        Register a preset pattern for later use in URL patterns.

        Example usage::

            >>> from datetime import date
            >>> from time import strptime
            >>> class DateConverter(Converter):
            ...     pattern = r'\\d{8}'
            ...     def from_string(self, s):
            ...         return date(*strptime(s, '%d%m%Y')[:3])
            ...
            >>> ExtensiblePattern.register_converter('date', DateConverter)
            >>> ExtensiblePattern('/<:date>')\\
            ...      .match('/01011970')  # doctest:+ELLIPSIS
            PathMatch(..., args=(datetime.date(1970, 1, 1),), kwargs={})
        """
    cls.preset_patterns[name] = converter


def get_dimord(measure, calc=None, community=None):
    """
    Get the dimension order of a network measure.

    Parameters
    ----------

    measure : str
        Name of funciton in teneto.networkmeasures.
    calc : str, default=None
        Calc parameter for the function
    community : bool, default=None
        If not null, then community property is assumed to be believed.

    Returns
    -------

    dimord : str
        Dimension order. So "node,node,time" would define the dimensions of the network measure.

    """
    if not calc:
        calc = ''
    else:
        calc = '_' + calc
    if not community:
        community = ''
    else:
        community = 'community'
    if 'community' in calc and 'community' in community:
        community = ''
    if calc == 'community_avg' or calc == 'community_pairs':
        community = ''
    dimord_dict = {'temporal_closeness_centrality': 'node',
        'temporal_degree_centrality': 'node',
        'temporal_degree_centralit_avg': 'node',
        'temporal_degree_centrality_time': 'node,time',
        'temporal_efficiency': 'global', 'temporal_efficiency_global':
        'global', 'temporal_efficiency_node': 'node',
        'temporal_efficiency_to': 'node', 'sid_global': 'global,time',
        'community_pairs': 'community,community,time', 'community_avg':
        'community,time', 'sid': 'community,community,time',
        'reachability_latency_global': 'global', 'reachability_latency':
        'global', 'reachability_latency_node': 'node', 'fluctuability':
        'node', 'fluctuability_global': 'global', 'bursty_coeff':
        'edge,edge', 'bursty_coeff_edge': 'edge,edge', 'bursty_coeff_node':
        'node', 'bursty_coeff_meanEdgePerNode': 'node', 'volatility_global':
        'time'}
    if measure + calc + community in dimord_dict:
        return dimord_dict[measure + calc + community]
    else:
        print('WARNINGL: get_dimord() returned unknown dimension labels')
        return 'unknown'


def _int_to_slice(idx):
    """Return a slice that indexes the same entries as a single int."""
    if idx == -1:
        return slice(-1, None)
    else:
        return slice(idx, idx + 1)


def get_model_field(schema, field):
    """Get the model field of a schema field

    :param Schema schema: a marshmallow schema
    :param str field: the name of the schema field
    :return str: the name of the field in the model
    """
    if schema._declared_fields.get(field) is None:
        raise Exception('{} has no attribute {}'.format(schema.__name__, field)
            )
    if schema._declared_fields[field].attribute is not None:
        return schema._declared_fields[field].attribute
    return field


def SizeReserveUernPremEnd(t):
    """Unearned reserve per policy: End of period"""
    return 0


def rm(ctx, target, force=True):
    """Removes target file or directory recursively."""
    ctx.sudo('rm -r%s %s' % ('f' if force else '', target))


def screw(steps: int=9, turns: int=1, center: float=(0.0, 0.0, 0.0), axis:
    float=(0.0, 0.0, 0.0)):
    """Extrude selected vertices in screw-shaped rotation around the cursor in indicated viewport

    :param steps: Steps, Steps
    :type steps: int
    :param turns: Turns, Turns
    :type turns: int
    :param center: Center, Center in global view space
    :type center: float
    :param axis: Axis, Axis in global view space
    :type axis: float
    """
    pass


def userpref_autoexec_path_remove(index: int=0):
    """Remove path to exclude from autoexecution

    :param index: Index
    :type index: int
    """
    pass


def _identify_fs_from_path(path, mounts):
    """
    Scan a list of mount points and try to identify the one that matches the
    given path

    """
    max_match = 0
    matching_mount = None
    for mount in mounts:
        if path.startswith(mount) and len(mount) > max_match:
            max_match = len(mount)
            matching_mount = mount
    return matching_mount


@classmethod
def create(cls, **kwargs):
    """
        Create a new model instance and save it to the database.
        Values are passed in as keyword arguments.

        Example::

            user = User.create(first_name='Charlie', last_name='Leifer')
        """
    instance = cls(**kwargs)
    instance.save(_is_create=True)
    return instance


def render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

    Eexceptions:
    1: no tags. 0.postDISTANCE[.dev0]
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance'] or pieces['dirty']:
            rendered += '.post%d' % pieces['distance']
            if pieces['dirty']:
                rendered += '.dev0'
    else:
        rendered = '0.post%d' % pieces['distance']
        if pieces['dirty']:
            rendered += '.dev0'
    return rendered


def bytestring(s, encoding='utf-8', fallback='iso-8859-1'):
    """Convert a given string into a bytestring."""
    if isinstance(s, bytes):
        return s
    try:
        return s.encode(encoding)
    except UnicodeError:
        return s.encode(fallback)


@classmethod
def access_error(cls, val):
    """
        Create an instance of this class set to the ``access_error`` tag with
        value ``val``.

        :param SharedFolderAccessError val:
        :rtype: UnshareFolderError
        """
    return cls('access_error', val)


def list_tenant_endpoints(tenant_id):
    """
        List the tenant specific endpoints.

        :param six.text_type tenant_id: tenant id to operate on
        :returns: an iterable of the endpoints available for the specified
            tenant id
        :rtype: iterable
        """


def __repr__(cls):
    """The representation for tokens.  Tokens are commonly used in the
        code but, being classes, have an ugly default `__repr__` when printed out.
        In this metaclass we can define a better `__repr__` for tokens."""
    string = 'TokenClass_{0}'.format(cls.token_label)
    return string


def _map_reactions_to_kinetic_parameters(reactions, enzrxns):
    """Get mapping of enzyme reactions to kinetic parameters."""
    for reaction in reactions.values():
        try:
            for enzrxn in reaction['enzymes']:
                try:
                    enzrxn_dict = enzrxns[enzrxn]
                except KeyError:
                    pass
                else:
                    for k, v in enzrxn_dict.items():
                        if k != 'enzyme':
                            reaction.setdefault('enzrxns', {}).setdefault(
                                enzrxn, {}).setdefault(k, v)
        except KeyError:
            pass


def str_to_bool_with_none(value):
    """
    Convert given string value to boolean or ``None``.
    """
    if str(value).lower() == 'true':
        return True
    if str(value).lower() == 'false':
        return False
    if str(value).lower() == 'none':
        return None
    raise ValueError('Invalid string value {} to be converted to boolean'.
        format(str(value)))


@staticmethod
def from_bytes(key_bytes):
    """ Generates a public key object from a byte (or hex) string.

        Args:
            key_bytes (bytes or str): A byte stream.

        Returns:
            PublicKey: A PublicKey object.
        """
    raise NotImplementedError


def and_or():
    """Returns a list of the supported logical operators"""
    return ['AND', 'OR']


def assert_consistent_reg_options(exec_type, json_spec,
    executable_builder_exeception):
    """
    Validates the "regionalOptions" field and verifies all the regions used
    in "regionalOptions" have the same options.
    """
    reg_options_spec = json_spec.get('regionalOptions')
    json_fn = 'dxapp.json' if exec_type == 'app' else 'dxworkflow.json'
    if not isinstance(reg_options_spec, dict):
        raise executable_builder_exeception(
            "The field 'regionalOptions' in  must be a mapping")
    if not reg_options_spec:
        raise executable_builder_exeception(
            "The field 'regionalOptions' in " + json_fn +
            ' must be a non-empty mapping')
    regional_options_list = list(reg_options_spec.items())
    for region, opts_for_region in regional_options_list:
        if not isinstance(opts_for_region, dict):
            raise executable_builder_exeception(
                "The field 'regionalOptions['" + region + "']' in " +
                json_fn + ' must be a mapping')
        if set(opts_for_region.keys()) != set(regional_options_list[0][1].
            keys()):
            if set(opts_for_region.keys()) - set(regional_options_list[0][1
                ].keys()):
                with_key, without_key = region, regional_options_list[0][0]
                key_name = next(iter(set(opts_for_region.keys()) - set(
                    regional_options_list[0][1].keys())))
            else:
                with_key, without_key = regional_options_list[0][0], region
                key_name = next(iter(set(regional_options_list[0][1].keys()
                    ) - set(opts_for_region.keys())))
            raise executable_builder_exeception(
                'All regions in regionalOptions must specify the same options; '
                 + '%s was given for %s but not for %s' % (key_name,
                with_key, without_key))
        if exec_type == 'app':
            for key in opts_for_region:
                if key in json_spec.get('runSpec', {}):
                    raise executable_builder_exeception(key +
                        ' cannot be given in both runSpec and in regional options for '
                         + region)


def convert_yn_to_bool(yn, yes=True, no=False):
    """Convert a y/yes or n/no to a boolean value."""
    if yn.lower().startswith('y'):
        return yes
    else:
        return no


def getPreviousBuild():
    """Convenience method. Returns None if the previous build is
        unavailable."""


def getHomeFolder(principalId):
    """Get the home folder instance of the specified principal.

        If a assignment does not exist and `autoCreateAssignment` is set to
        `True`, then create the assignment and the homefolder. The homefolder
        will always be created regardless of the value of createHomeFolder.
        The folder will be given the same name like the principalId.

        During creation, the principal should get the rights specified in
        homeFolderRole inside the folder.

        If the home folder does not exist and `autoCreateAssignment` is set to
        `False`, then return `None`.
        """


def find_nearest(array, value):
    """
    Smart and small function to find the index of the nearest value, in an array, of some other value

    Parameters
    -----------
    array: array
        list or array
    value: float
        value to look for in the array
    """
    import numpy as np
    idx = np.abs(array - value).argmin()
    return idx


def _is_valid_glob(glob):
    """Check whether a glob pattern is valid.

    It does so by making sure it has no dots (path separator) inside groups,
    and that the grouping braces are not mismatched. This helps doing useless
    (or worse, wrong) work on queries.

    Args:
      glob: Graphite glob pattern.

    Returns:
      True if the glob is valid.
    """
    depth = 0
    for c in glob:
        if c == '{':
            depth += 1
        elif c == '}':
            depth -= 1
            if depth < 0:
                return False
        elif c == '.':
            if depth > 0:
                return False
    return depth == 0


def _Mul(lhs=None, rhs=None, out=None, name=None, **kwargs):
    """Multiplies arguments element-wise.

    The storage type of ``elemwise_mul`` output depends on storage types of inputs

       - elemwise_mul(default, default) = default
       - elemwise_mul(row_sparse, row_sparse) = row_sparse
       - elemwise_mul(default, row_sparse) = row_sparse
       - elemwise_mul(row_sparse, default) = row_sparse
       - elemwise_mul(csr, csr) = csr
       - otherwise, ``elemwise_mul`` generates output with default storage

    Parameters
    ----------
    lhs : NDArray
        first input
    rhs : NDArray
        second input

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


def next():
    """Iterator protocol. See Python documentation for :class:`io.IOBase` for
        details.
        """


def get_paginator(operation_name=None):
    """
    Create a paginator for an operation.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    :rtype: L{botocore.paginate.Paginator}
    """
    pass


def SetDefaultDData(dType, histoName, NShkl=0, NDij=0):
    """Create an initial Histogram dictionary

    Author: Jackson O'Donnell (jacksonhodonnell .at. gmail.com)
    """
    if dType in ['SXC', 'SNC']:
        return {'Histogram': histoName, 'Show': False, 'Scale': [1.0, True],
            'Babinet': {'BabA': [0.0, False], 'BabU': [0.0, False]},
            'Extinction': ['Lorentzian', 'None', {'Tbar': 0.1, 'Cos2TM':
            0.955, 'Eg': [1e-10, False], 'Es': [1e-10, False], 'Ep': [1e-10,
            False]}], 'Flack': [0.0, False]}
    elif dType == 'SNT':
        return {'Histogram': histoName, 'Show': False, 'Scale': [1.0, True],
            'Babinet': {'BabA': [0.0, False], 'BabU': [0.0, False]},
            'Extinction': ['Lorentzian', 'None', {'Eg': [1e-10, False],
            'Es': [1e-10, False], 'Ep': [1e-10, False]}]}
    elif 'P' in dType:
        return {'Histogram': histoName, 'Show': False, 'Scale': [1.0, False
            ], 'Pref.Ori.': ['MD', 1.0, False, [0, 0, 1], 0, {}, [], 0.1],
            'Size': ['isotropic', [1.0, 1.0, 1.0], [False, False, False], [
            0, 0, 1], [1.0, 1.0, 1.0, 0.0, 0.0, 0.0], 6 * [False]],
            'Mustrain': ['isotropic', [1000.0, 1000.0, 1.0], [False, False,
            False], [0, 0, 1], NShkl * [0.01], NShkl * [False]], 'HStrain':
            [NDij * [0.0], NDij * [False]], 'Extinction': [0.0, False],
            'Babinet': {'BabA': [0.0, False], 'BabU': [0.0, False]}}


def list_zpaq(archive, compression, cmd, verbosity, interactive):
    """List a ZPAQ archive."""
    return [cmd, 'l', archive]


def unshift_token(text):
    """Remove a token from the front of a string.

    :param str text:
    :returns: {'text': str, 'separator': str, 'remainder': str}
    """
    if len(text) == 0:
        return {'text': text, 'separator': '', 'remainder': ''}
    token = ''
    for i in range(0, len(text)):
        char = text[i]
        if char == ' ' and (len(token) >= 1 and token[i - 1] == ' '):
            token += char
        elif char == ' ' and len(token) == 0:
            token += char
        elif char == ' ':
            return {'text': token, 'separator': ' ', 'remainder': text[i + 1:]}
        elif char == '\n':
            return {'text': token, 'separator': '\n', 'remainder': text[i + 1:]
                }
        elif len(token) >= 1 and token[i - 1] == ' ':
            return {'text': token, 'separator': '', 'remainder': text[len(
                token):]}
        else:
            token += char
    return {'text': token, 'separator': '', 'remainder': ''}


def get_metadata_lines(name):
    """Yield named metadata resource as list of non-blank non-comment lines

       Leading and trailing whitespace is stripped from each line, and lines
       with ``#`` as the first non-blank character are omitted."""


def get_axis_limits(ax, scale=0.85, position='upper-right'):
    """Used to position the identifier labels in the corner of images.
    e.g. '(a)' etc.

    An example use with this definition is as follows:

        ax1.annotate("("+d[i+1-10]+")", xy=get_axis_limits(ax1))

    This will place an annotation in the top right corner of our subplot,
    ax1. Specifically this is used for labelling multiple plots using
    letters. The function d[i] is a dictionary function which converts
    numbers to letters.

    Parameters
    ----------
    ax : plot/subplot function
        The plot or subplot that you want to scale accordingly
    scale : float, optional
        A scale function that determines as a fractional percentage the
        position from the edge of the plot (e.g. scale = 1 is at the
        edge and scale = 0.5 is centred).
    position : string, optional
        Determines the prefered location of interest releative to the
        four corners of the plot. string selections are ('upper-right',
        'upper-left', 'lower-right', 'lower-left')

    Returns
    -------
    x : float
        coordinate reference relative to the input plot ax in the x axis
    y: float
        coordinate reference relative to the input plot ax in the y axis

    """
    if position == 'upper-right':
        try:
            return ax.get_xlim()[1] * 0.95 * scale, ax.get_ylim()[1] * 0.9
        except AttributeError:
            return ax.xlim()[1] * 0.95 * scale, ax.ylim()[1] * 0.9
    elif position == 'upper-left':
        try:
            return ax.get_xlim()[1] * 0.95 * (1 - scale), ax.get_ylim()[1
                ] * 0.9
        except AttributeError:
            return ax.xlim()[1] * 0.95 * (1 - scale), ax.ylim()[1] * 0.9
    elif position == 'lower-right':
        try:
            return ax.get_xlim()[1] * 0.95, ax.get_ylim()[1] * (1 - scale)
        except AttributeError:
            return ax.xlim()[1] * 0.95, ax.ylim()[1] * (1 - scale)
    elif position == 'lower-left':
        try:
            return ax.get_xlim()[1] * 0.95, ax.get_ylim()[1] * 0.95 * (1 -
                scale)
        except AttributeError:
            return ax.xlim()[1] * 0.95, ax.ylim()[1] * 0.95 * (1 - scale)


def p_block(p):
    """block : BRACE_OPEN content BRACE_CLOSE"""
    p[0] = p[2]


def check_okay(status):
    """Check if the status is something wrong."""
    return status['state'] == 'OK'


def sanitize(s) ->str:
    """
    Returns string decoded from utf-8 with leading/trailing whitespace
    character removed
    """
    return s.decode('utf-8').strip()


def contains_whitespace(s):
    """True if there are any whitespace characters in s."""
    if isinstance(s, str):
        ws = ' \t\n\r\x0b\x0c'
    else:
        ws = b' ', b'\t', b'\n', b'\r', b'\x0b', b'\x0c'
    for ch in ws:
        if ch in s:
            return True
    else:
        return False


def weight_by_order_type(phase_type, order):
    """ Calculate the new weight for the order using the perc of orders with this order type for the given phase
        as calculated in the dataset. (e.g. 20% of orders in a movement phase are H)
        :param phase_type: The current phase type ('M', 'R', 'A')
        :param order: The order to evaluate
        :return: The new weight for the order
    """
    probs = {'M': {'H': 0.19798, '-': 0.49738, 'S': 0.28929, 'C': 0.01535,
        'R': 0.0, 'B': 0.0, 'D': 0.0}, 'R': {'H': 0.9436, '-': 0.0, 'S':
        0.0, 'C': 0.0, 'R': 0.03213, 'B': 0.0, 'D': 0.02427}, 'A': {'H':
        0.8495, '-': 0.0, 'S': 0.0, 'C': 0.0, 'R': 0.0, 'B': 0.11252, 'D':
        0.03798}}
    parts = order.split()
    if len(parts) < 3:
        return 1e-05
    order_type = parts[2]
    if phase_type in probs and order_type in probs[phase_type]:
        return probs[phase_type][order_type]
    return 1e-05


def incr(key, value=1):
    """
        Увеличить значение ключа на единицу (тип значения - целое число).
        Работает только над  существующими ключами, если ключ
        не существует, будет возвращена ошибка C{KeyError}.

        @param key: ключ
        @type key: C{str}
        @param value: величина инкремента
        @type value: C{int}
        @return: Deferred с новым значением ключа, C{int}
        @rtype: C{twisted.internet.Deferred}
        """


def log(text, array=None):
    """Prints a text message. And, optionally, if a Numpy array is provided it
    prints it's shape, min, and max values.
    """
    if array is not None:
        text = text.ljust(25)
        text += 'shape: {:20}  '.format(str(array.shape))
        if array.size:
            text += 'min: {:10.5f}  max: {:10.5f}'.format(array.min(),
                array.max())
        else:
            text += 'min: {:10}  max: {:10}'.format('', '')
        text += '  {}'.format(array.dtype)
    print(text)


@classmethod
def load(cls, data):
    """Create an object from JSON data.

        Parameters
        ----------
        data : `dict`
            JSON data.

        Returns
        ----------
        `object`
            Created object.

        Raises
        ------
        KeyError
            If `data` does not have the '__class__' key
            or the necessary class is not in the class group.
        """
    ret = cls.classes[data['__class__']]
    data_cls = data['__class__']
    del data['__class__']
    try:
        ret = ret(**data)
    finally:
        data['__class__'] = data_cls
    return ret


def derive_section_root(page):
    """
    Returns the 'section root' for the provided ``page``, or ``None``
    if no such page can be identified. Results are dependant on the
    value of the ``WAGTAILMENUS_SECTION_ROOT_DEPTH`` setting.
    """
    from wagtailmenus.conf import settings
    desired_depth = settings.SECTION_ROOT_DEPTH
    if page.depth == desired_depth:
        return page.specific
    if page.depth > desired_depth:
        return page.get_ancestors().get(depth=desired_depth).specific


def _syscal_write_quadpoles(fid, quadpoles):
    """helper function that writes the actual measurement configurations to a
    file descriptor.

    Parameters
    ----------
    fid: file descriptor
        data is written here
    quadpoles: numpy.ndarray
        measurement configurations

    """
    fid.write('# A B M N\n')
    for nr, quadpole in enumerate(quadpoles):
        fid.write('{0} {1} {2} {3} {4}\n'.format(nr, quadpole[0], quadpole[
            1], quadpole[2], quadpole[3]))


def build_graph_mapping_collection(from_ff, to_ff, mappings):
    """
    Function that produces a collection of :class:`vermouth.map_parser.Mapping`
    objects.
    Hereby deprecated.

    Parameters
    ----------
    from_ff: vermouth.forcefield.ForceField
        Origin force field.
    to_ff: vermouth.forcefield.ForceField
        Destination force field.
    mappings: dict[str, dict[str, vermouth.map_parser.Mapping]]
        All known mappings

    Returns
    -------
    collections.abc.Iterable
        A collection of mappings that map from `from_ff` to `to_ff`.
    """
    return mappings[from_ff.name][to_ff.name].values()


def make_url(url, **kwargs):
    """Build an Appveyor API url."""
    return 'https://ci.appveyor.com/api' + url.format(**kwargs)


def get_bsse_section(natoms_a, natoms_b, mult_a=1, mult_b=1, charge_a=0,
    charge_b=0):
    """Get the &FORCE_EVAL/&BSSE section."""
    bsse_section = {'FORCE_EVAL': {'BSSE': {'FRAGMENT': [{'LIST': '1..{}'.
        format(natoms_a)}, {'LIST': '{}..{}'.format(natoms_a + 1, natoms_a +
        natoms_b)}], 'CONFIGURATION': [{'MULTIPLICITY': mult_a, 'CHARGE':
        charge_a, 'GLB_CONF': '1 0', 'SUB_CONF': '1 0'}, {'MULTIPLICITY':
        mult_b, 'CHARGE': charge_b, 'GLB_CONF': '0 1', 'SUB_CONF': '0 1'},
        {'MULTIPLICITY': mult_a, 'CHARGE': charge_a, 'GLB_CONF': '1 1',
        'SUB_CONF': '1 0'}, {'MULTIPLICITY': mult_b, 'CHARGE': charge_b,
        'GLB_CONF': '1 1', 'SUB_CONF': '0 1'}, {'MULTIPLICITY': mult_a +
        mult_b - 1, 'CHARGE': charge_a + charge_b, 'GLB_CONF': '1 1',
        'SUB_CONF': '1 1'}]}}}
    return bsse_section


def write_msbt(msbt_info: tuple):
    """Writes an MSBT file"""
    msbt_path, msbt_data = msbt_info
    msbt_path.parent.mkdir(parents=True, exist_ok=True)
    with msbt_path.open(mode='wb') as f_msbt:
        f_msbt.write(msbt_data)
    return None


def is_collapse_legal(mesh, u, v, allow_boundary=False):
    """Verify if the requested collapse is legal for a triangle mesh.

    Parameters
    ----------
    mesh : compas.datastructures.Mesh
        The mesh.
    u : str
        The vertex to collapse towards.
    v : str
        The vertex to collapse.

    Returns
    -------
    bool
        `True` if the collapse is legal.
        `False` otherwise.

    """
    u_on = mesh.is_vertex_on_boundary(u)
    v_on = mesh.is_vertex_on_boundary(v)
    if v_on and not u_on:
        return False
    if not allow_boundary:
        if u_on or v_on:
            return False
    fkey_uv = mesh.halfedge[u][v]
    fkey_vu = mesh.halfedge[v][u]
    for nbr in mesh.halfedge[u]:
        if nbr in mesh.halfedge[v]:
            fkey_nbr_v = mesh.halfedge[nbr][v]
            fkey_u_nbr = mesh.halfedge[u][nbr]
            if fkey_nbr_v is None and fkey_u_nbr is None:
                return False
            if mesh.halfedge[v][nbr] == fkey_uv and mesh.halfedge[nbr][u
                ] != fkey_uv:
                return False
            if mesh.halfedge[u][nbr] == fkey_vu and mesh.halfedge[nbr][v
                ] != fkey_vu:
                return False
    for nbr in mesh.halfedge[v]:
        if nbr in mesh.halfedge[u]:
            if mesh.halfedge[v][nbr] == fkey_uv and mesh.halfedge[nbr][u
                ] != fkey_uv:
                return False
            if mesh.halfedge[u][nbr] == fkey_vu and mesh.halfedge[nbr][v
                ] != fkey_vu:
                return False
    return True


def pdp(ice_data):
    """
    Calculate a partial dependence plot from ICE data

    :param ice_data: the ICE data generated by :func:`pycebox.ice.ice`
    :type ice_data: ``pandas`` ``DataFrame``

    :return: the partial dependence plot curve
    :rtype: ``pandas`` ``Series``
    """
    return ice_data.mean(axis=1)


def make_pathable_string(s, replacewith='_'):
    """
    Removes symbols from a string to be compatible with directory structure.

    :param s: string
    """
    import re
    return re.sub('\\W+', replacewith, s)


def select_border(gesture_mode: int=0, xmin: int=0, xmax: int=0, ymin: int=
    0, ymax: int=0, extend: bool=True):
    """Select strips using border selection

    :param gesture_mode: Gesture Mode
    :type gesture_mode: int
    :param xmin: X Min
    :type xmin: int
    :param xmax: X Max
    :type xmax: int
    :param ymin: Y Min
    :type ymin: int
    :param ymax: Y Max
    :type ymax: int
    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    """
    pass


def write_only_property(f):
    """
    @write_only_property decorator. Creates a property (descriptor attribute)
    that accepts assignment, but not getattr (use in an expression).
    """
    docstring = f.__doc__
    return property(fset=f, doc=docstring)


@classmethod
def _read_instruction_from_relative_instructions(cls, relative_instructions):
    """Returns ReadInstruction obj initialized with relative_instructions."""
    result = cls.__new__(cls)
    result._init(relative_instructions)
    return result


@staticmethod
def __looks_like_html(response):
    """Guesses entity type when Content-Type header is missing.
        Since Content-Type is not strictly required, some servers leave it out.
        """
    text = response.text.lstrip().lower()
    return text.startswith('<html') or text.startswith('<!doctype')


def rowcol_to_index(row, col, width):
    """Convert row major coordinates to 1-D index."""
    return width * row + col


@classmethod
def condition(cls, previous_value, value, has_changed=False, first_save=
    False, graph_property=None):
    """ Only save this value if it is increasing

        :rtype: bool
        """
    if previous_value is not None:
        return value > previous_value
    else:
        return True


def read_renderlayers():
    """Read all render layers of all used scenes

    """
    pass


def items():
    """
        Return list of tuples containing user login names and user object
        each.  Do not use this for large groups, prefer to use
        iteritems(), or iterate over each key from keys() or iterkeys()
        and obtain user object Lazily.
        """


def get_outbucket_name(bucket):
    """chop up bucket name and have a play"""
    return bucket.replace('files', 'wfoutput')


def ifloordiv(a, b):
    """Same as a //= b."""
    a //= b
    return a


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def dump_array(the_array, write, array_name):
    """dumps a given encoding"""
    write('  static const unsigned char  ' + array_name + '[' + repr(len(
        the_array)) + 'L] =\n')
    write('  {\n')
    line = ''
    comma = '    '
    col = 0
    for value in the_array:
        line += comma
        line += '%3d' % ord(value)
        comma = ','
        col += 1
        if col == 16:
            col = 0
            comma = ',\n    '
        if len(line) > 1024:
            write(line)
            line = ''
    write(line + '\n  };\n\n\n')


@classmethod
def description(cls):
    """Return a field->data type dictionary describing this model
        as reported by the database.

        :rtype: dict
        """
    description = {}
    for column in cls.__table__.columns:
        column_description = str(column.type)
        if not column.nullable:
            column_description += ' (required)'
        description[column.name] = column_description
    return description


def duplicate(mode: int=1):
    """Duplicate selected vertices, edges or faces

    :param mode: Mode
    :type mode: int
    """
    pass


def int_or_str(text):
    """Helper function for argument parsing."""
    try:
        return int(text)
    except ValueError:
        return text


def argsort(a):
    """return index list to get `a` in order, ie
    ``a[argsort(a)[i]] == sorted(a)[i]``
    """
    return sorted(range(len(a)), key=a.__getitem__)


def inverseDict(data):
    """
    Inverse a dictionary.

    >>> inverseDict({"0x10": 16, "0x20": 32}) == {32: '0x20', 16: '0x10'}
    True
    """
    result = {}
    for key, value in data.items():
        result[value] = key
    return result


def render_pep440_pre(pieces):
    """TAG[.post.devDISTANCE] -- No -dirty.

    Exceptions:
    1: no tags. 0.post.devDISTANCE
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '.post.dev%d' % pieces['distance']
    else:
        rendered = '0.post.dev%d' % pieces['distance']
    return rendered


def Squash(val, cap):
    """Use a sigmoidal squashing function to squash to 100."""
    if val < 1:
        return val
    return cap * val / (cap - 1.0 + val)


def split_string0(buf):
    """split a list of zero-terminated strings into python not-zero-terminated bytes"""
    return buf.split(b'\x00')[:-1]


def normalize_table_name(name):
    """Check if the table name is obviously invalid."""
    if not isinstance(name, str):
        raise ValueError('Invalid table name: %r' % name)
    name = name.strip()[:63]
    if not len(name):
        raise ValueError('Invalid table name: %r' % name)
    return name


def convert_IMProperty(model, prop, kwargs):
    """Returns a form field for a ``db.IMProperty``."""
    return None


def get_listOfReactants(reaction):
    """
    return list of reactants of a reaction
    """
    listOfReactants = None
    for e in reaction:
        if e.tag[0] == '{':
            uri, tag = e.tag[1:].split('}')
        else:
            tag = e.tag
        if tag == 'listOfReactants':
            listOfReactants = e
            break
    return listOfReactants


def validate_args(arg_d):
    """
  Validate that the user passed input args properly
  """
    if not arg_d.get('input_glob'):
        raise Exception(
            'Please provide an input_glob named argument to crop_faces')


@staticmethod
def split_by_new_lines(table_data):
    """
        Splits data by newline symbols.

        :param list[mixed] table_data:

        :rtype: list[mixed]
        """
    splitted_data = []
    for data in table_data:
        if isinstance(data, str):
            splitted_data.append(data.split('\n'))
        else:
            splitted_data.append(data)
    for data in splitted_data:
        if isinstance(data, list):
            for element in data:
                if element.isspace() or element == '':
                    data.remove(element)
    return splitted_data


@classmethod
def manager_name(cls) ->str:
    """returns the name of the property manager"""
    return 'master'


def eqexpr(key, value):
    """for automatic x is null vs x=value stmts"""
    return key + (' is %s' if value is None else '=%s')


def driver_button_edit():
    """Edit the drivers for the property connected represented by the highlighted button

    """
    pass


@classmethod
def ensure_indexes(cls):
    """
        No index support for datastore
        """
    return
    yield


def copy():
    """Copy selected Grease Pencil points and strokes

    """
    pass


def sparkml_installed():
    """
    Checks that *spark* is available.
    """
    try:
        import pyspark
        return True
    except ImportError:
        return False


def remove_security_group(nova, vm, security_group):
    """
    Removes a security group from an existing VM
    :param nova: the nova client
    :param vm: the OpenStack server object (VM) to alter
    :param security_group: the SNAPS SecurityGroup domain object to add
    """
    nova.servers.remove_security_group(str(vm.id), security_group.name)


@classmethod
def current(cls):
    """ Return the most recently created AzureDLFileSystem
        """
    if not cls._singleton[0]:
        return cls()
    else:
        return cls._singleton[0]


def reciprocalhdg(heading_deg):
    """The reciprocal of a heading in degrees"""
    if heading_deg + 180 > 360:
        return heading_deg - 180
    return heading_deg + 180


def get_line_indent_num(line_str):
    """
    Get the number of indents of the target line.

    Parameters
    ----------
    line_str : str
        String of target line.

    Returns
    -------
    line_indent_num : int
        Number of indents.
    """
    space_num = 0
    for line_char in line_str:
        if line_char != ' ':
            break
        space_num += 1
    line_indent_num = space_num // 4
    return line_indent_num


def get_html_tag(preview=False, request=None, hires=False, thumbnail=False,
    **extra_attributes):
    """Generate a image tag to render either the original version
        (if ``hires`` set to True), or the thumbnail (if ``thumbnail``
        set to True) or the web version (by default).

        If some ``extra_attributes`` are given, they will be added to
        the image tag as HTML attributes.
        """


def generic_find_fk_constraint_name(table, columns, referenced, insp):
    """Utility to find a foreign-key constraint name in alembic migrations"""
    for fk in insp.get_foreign_keys(table):
        if fk['referred_table'] == referenced and set(fk['referred_columns']
            ) == columns:
            return fk['name']


def droop(votes, seats):
    """Calculate the Droop quota.

    :math:`\\frac{votes}{seats + 1} + 1`

    :param int votes: the number of votes
    :param int seats: the number of seats
    """
    return int(1.0 * votes / (seats + 1) + 1)


@classmethod
def from_comp(cls, xx=0, xy=0, xz=0, yx=0, yy=0, yz=0, zx=0, zy=0, zz=0):
    """
        Return ``VelGrad`` tensor. Default is zero tensor.

        Keyword Args:
          xx, xy, xz, yx, yy, yz, zx, zy, zz (float): tensor components

        Example:
          >>> L = VelGrad.from_comp(xx=0.1, zz=-0.1)
          >>> L
          VelGrad:
          [[ 0.1  0.   0. ]
           [ 0.   0.   0. ]
           [ 0.   0.  -0.1]]

        """
    return cls([[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]])


def untokenize_without_newlines(tokens):
    """Return source code based on tokens."""
    text = ''
    last_row = 0
    last_column = -1
    for t in tokens:
        token_string = t[1]
        start_row, start_column = t[2]
        end_row, end_column = t[3]
        if start_row > last_row:
            last_column = 0
        if (start_column > last_column or token_string == '\n'
            ) and not text.endswith(' '):
            text += ' '
        if token_string != '\n':
            text += token_string
        last_row = end_row
        last_column = end_column
    return text.rstrip()


def mutate_string(string, pos, change_to):
    """
    Fastest way I've found to mutate a string
    @ 736 ns

    >>> mutate_string('anthony', 0, 'A')
    'Anthony'

    :param string:
    :param pos:
    :param change_to:
    :return:
    """
    string_array = list(string)
    string_array[pos] = change_to
    return ''.join(string_array)


def grokkers(name, obj):
    """Iterable of all grokkers that apply to obj.
        """


def _generate_csv_header_line(*, header_names, header_prefix='', header=
    True, sep=',', newline='\n'):
    """
    Helper function to generate a CSV header line depending on
    the combination of arguments provided.
    """
    if isinstance(header, str):
        header_line = header + newline
    elif not (header is None or isinstance(header, bool)):
        raise ValueError(f'Invalid value for argument `header`: {header}')
    elif header:
        header_line = header_prefix + sep.join(header_names) + newline
    else:
        header_line = ''
    return header_line


def ccw(p, q, r):
    """Checks if points in a triangle are ordered counter clockwise. When using R2,
    mesh nodes should be given in a counter clockwise order otherwise you'll
    get nonsensical results.

    Parameters
    ----------
    p - tuple, list,
        The x y coordinates of the point/vertex ie. (x,y) in desired order
    q - "
    r - "

    Returns
    ----------
    0 if colinear points, 1 if clockwise order, 2 if points are ordered counter clockwise
    """
    val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1])
    if val == 0:
        return 0
    elif val > 0:
        return 1
    elif val < 0:
        return 2


def set_login_view(app, login_view, blueprint=None):
    """
    Sets the login view for the app or blueprint. If a blueprint is passed,
    the login view is set for this blueprint on ``blueprint_login_views``.

    :param login_view: The user object to log in.
    :type login_view: str
    :param blueprint: The blueprint which this login view should be set on.
        Defaults to ``None``.
    :type blueprint: object
    """
    num_login_views = len(app.login_manager.blueprint_login_views)
    if blueprint is not None or num_login_views != 0:
        app.login_manager.blueprint_login_views[blueprint.name] = login_view
        if (app.login_manager.login_view is not None and None not in app.
            login_manager.blueprint_login_views):
            app.login_manager.blueprint_login_views[None
                ] = app.login_manager.login_view
        app.login_manager.login_view = None
    else:
        app.login_manager.login_view = login_view


def getIndexValue():
    """Return the value to passe the Catalog Index for the query.
        """


def write_xyz_tm4(ofile, c):
    """ Write the Crys in .xyz tilor-made 4 file format for Well's program"""
    print('****PRINTING .xyz TAILOR-MADE4 FOR Qeq program by B.Wells***',
        file=ofile)
    print('      FRAC       %.5f  %.5f  %.5f  %.3f  %.3f  %.3f  ' % (c.
        length[0], c.length[1], c.length[2], c.angle_deg[0], c.angle_deg[1],
        c.angle_deg[2]), file=ofile)
    print('%d' % c.natom, file=ofile)
    for i in range(c.natom):
        print('%3s %9.5f %9.5f %9.5f ' % (c.atom_element[i], c.atom_fract[i
            ][0], c.atom_fract[i][1], c.atom_fract[i][2]), file=ofile)


def reshaped(data):
    """
    check if data is 1d and if so reshape to a column vector
    """
    import pandas as pd
    import numpy as np
    if isinstance(data, (pd.Series, pd.DataFrame)):
        if len(data.shape) == 1:
            data = data.values.reshape(-1, 1)
        elif len(data.shape) == 2 and data.shape[1] == 1:
            data = data.values.reshape(-1, 1)
    elif isinstance(data, np.ndarray):
        if len(data.shape) == 1:
            data = data.reshape(-1, 1)
    elif isinstance(data, list):
        data = np.array(data)
        if len(data.shape) == 1:
            data = data.reshape(-1, 1)
    return data


@classmethod
def from_dict(cls, d):
    """
        Construct a new `UpdateByQuery` instance from a raw dict containing the search
        body. Useful when migrating from raw dictionaries.

        Example::

            ubq = UpdateByQuery.from_dict({
                "query": {
                    "bool": {
                        "must": [...]
                    }
                },
                "script": {...}
            })
            ubq = ubq.filter('term', published=True)
        """
    u = cls()
    u.update_from_dict(d)
    return u