def Lagrange(points):
    """**Lagrange**\\ (*points*)
    Renvoie le polynôme d'interpolation de Lagrange pour les points de coordonnées *points*

    Est prévue pour être utilisé avec :py:func:`choix_points`

    Associé à  :py:func:`pyromaths.outils.Priorites3.priorites`, permet d'obtenir sa version réduite.

    Associé à  :py:func:`pyromaths.outils.Priorites3.plotify`, permet d'obtenir sa version utilisable avec psplot.

    >>> from pyromaths.ex.troisiemes import notion_de_fonction
    >>> p = notion_de_fonction.Lagrange(((-4, -2), (-2, 0), (0,4), (2,-4), (4,2)))

    >>> from pyromaths.outils import Priorites3
    >>> Priorites3.priorites(p)[-1]
    ['Polynome([[Fraction(5, 48), 4], [Fraction(1, 8), 3], [Fraction(-23, 12), 2], [Fraction(-3, 2), 1], [Fraction(4, 1), 0]], "x", 0)']
    >>> Priorites3.plotify(Priorites3.priorites(p)[-1])
    5/48*x^4+1/8*x^3-23/12*x^2-3/2*x^1+4/1
    """
    PIL = []
    for i in range(len(points)):
        if points[i][1]:
            PIL.append('Fraction(%s, ' % points[i][1])
            produit = []
            for j in range(len(points)):
                if j != i:
                    produit.append(repr(points[i][0] - points[j][0]))
            produit = repr(eval('*'.join(produit)))
            PIL[i] += produit + ')*'
            produit = []
            for j in range(len(points)):
                if j != i and points[j][0] > 0:
                    produit.append('Polynome("x-%s", details = 0)' % points
                        [j][0])
                elif j != i and points[j][0] < 0:
                    produit.append('Polynome("x+%s", details = 0)' % -
                        points[j][0])
                elif j != i and points[j][0] == 0:
                    produit.append('Polynome("x", details = 0)')
            produit = '*'.join(produit)
            PIL[i] += produit
        else:
            PIL.append('0')
    return '+'.join(PIL)


def clear_hooks():
    """Clear all trace hooks."""
    global HOOKS
    HOOKS = []
    return


def setdefname(name):
    """Assign a default plot view name used by all plotters
    This default name starts as "Plot 1"
    """
    global _PVNAME
    _PVNAME = name


def fromOpenIDRequest(cls, request):
    """Instantiate a Request object from the arguments in a
        C{checkid_*} OpenID message
        """
    self = cls()
    args = request.message.getArgs(self.ns_uri)
    is_openid1 = request.message.isOpenID1()
    if args == {}:
        return None
    self.parseExtensionArgs(args, is_openid1)
    return self


def draw_tail_navigable(context):
    """
    Draw a normal arrow to indicate association end navigability at
    association tail.
    """
    cr = context.cairo
    cr.line_to(0, 0)
    cr.stroke()
    cr.move_to(15, -6)
    cr.line_to(0, 0)
    cr.line_to(15, 6)


def update(*args, **kwds):
    """od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        """
    if len(args) > 2:
        raise TypeError(
            'update() takes at most 2 positional arguments (%d given)' % (
            len(args),))
    elif not args:
        raise TypeError('update() takes at least 1 argument (0 given)')
    self = args[0]
    other = ()
    if len(args) == 2:
        other = args[1]
    if isinstance(other, dict):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, 'keys'):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value


def __ge__(ref):
    """KeyReferences must be totally orderable."""


def circularlerp(value, start, end):
    """
    Circular Lerp interpolation
    Wraps around to get closest path (0.0 = 1.0)
    """
    shortest_path = (end - start + 0.5) % 1.0 - 0.5
    result = (start + shortest_path * value) % 1.0
    return result


def find_channel_id(slack, name):
    """Allow a user to configure this system using a user-friendly channel name.
    The network handlers will use this method to map that to a channel ID.
    """
    result = slack.api_call('channels.list', exclude_members=True)
    for channel in result['channels']:
        if channel['name'] == name:
            return channel['id']
        prev_names = channel.get('previous_names')
        if prev_names is not None and name in prev_names:
            return channel['id']
    return None


@classmethod
def register(cls, name, klass, content_type='text/plain'):
    """
        Register an emitter.

        Parameters::
         - `name`: The name of the emitter ('json', 'xml', 'yaml', ...)
         - `klass`: The emitter class.
         - `content_type`: The content type to serve response as.
        """
    cls.EMITTERS[name] = klass, content_type


@classmethod
def iter_unique_field_combinations(cls, model_cls):
    """ Returns an iteratorable of unique constraints (set of
        field names) on the model.

        .. note::
            Relation considered to be unique if the set of columns used as
            foreign keys (can be multiple in case of composite key) has a
            unique constraint.

            *Relations can be unique together with other fields.*

        :param model_cls: ORM model class for which relations are going to be
            iterated.
        :returns: Returns an iteratorable of unique constraints.
        """
    raise NotImplementedError()


def config_positive_int_value(value):
    """
    Returns positive int value if it can be cast by int() and it's an
    integer > 0. (not including zero) Raises ValueError otherwise.
    """
    try:
        result = int(value)
        if result < 1:
            raise ValueError()
    except (TypeError, ValueError):
        raise ValueError(
            'Config option must be an positive int number, not "%s".' % value)
    return result


def is_non_empty_string(str_):
    """checks if a string is not an empty string, True if not empty"""
    return bool(str_ != '')


def _remove_html_comment_tags(html):
    """
    Returns the passed HTML contents with all comment tags removed while
    keeping the contents within the tags.

    Some pages embed the HTML contents in comments. Since the HTML contents are
    valid, removing the content tags (but not the actual code within the
    comments) will return the desired contents.

    Parameters
    ----------
    html : PyQuery object
        A PyQuery object which contains the requested HTML page contents.

    Returns
    -------
    string
        The passed HTML contents with all comment tags removed.
    """
    return str(html).replace('<!--', '').replace('-->', '')


@staticmethod
def get_elastic_mappings(es_major):
    """Get Elasticsearch mapping.

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "properties": {
                "revision_comment_analyzed": {
                    "type": "text",
                    "index": true
                },
                "title_analyzed": {
                    "type": "text",
                    "index": true
                }
           }
        } """
    return {'items': mapping}


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 '+'


def verifyJobTreeOptions(options):
    """ verifyJobTreeOptions() returns None if all necessary values
    are present in options, otherwise it raises an error.
    It can also serve to validate the values of the options.
    """
    required = ['logLevel', 'batchSystem', 'jobTree']
    for r in required:
        if r not in vars(options):
            raise RuntimeError(
                'Error, there is a missing option (%s) from the jobTree Stack, did you remember to call Stack.addJobTreeOptions()?'
                 % r)
    if options.jobTree is None:
        raise RuntimeError('Specify --jobTree')


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


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

    Like 'git describe --tags --dirty --always'.

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


def read_mask(dataset):
    """Get the dataset's mask

    Returns
    -------
    numpy.array

    Notes
    -----
    This function is no longer called by module code but we're going to
    continue to test it for a few future versions as insurance on the new
    implementation.

    """
    return dataset.dataset_mask()


def quasilexico_key(x):
    """Returns a key suitable for a quasi-lexicographic sort [1]_.

    Objects are sorted by length first, then lexicographically.

    Examples
    --------
    >>> L = ['a', 'aa', 'b']
    >>> sorted(L, key=quasilexico_key)
    ['a', 'b', 'aa']

    References
    ----------
    .. [1] Calude, Cristian (1994). Information and randomness. An algorithmic
           perspective. EATCS Monographs on Theoretical Computer Science.
           Springer-Verlag. p. 1.

    """
    return len(x), x


@staticmethod
def to_jwk(key_obj):
    """
        Serializes a given RSA key into a JWK
        """
    raise NotImplementedError


def getplaylistcontent():
    """
    @api {post} /music/playlist/getplaylistcontent 获取用户歌单内容
    @apiVersion 1.0.0
    @apiGroup Playlist
    @apiDescription 获取用户歌单内容

    @apiParam (Headers) {string} token 令牌
    @apiParam (Headers) {String} device_token 设备令牌
    @apiParam (Headers) {String} content_type 内容类型
    @apiParam (Headers) {String} timestamp 时间戳

    @apiSuccess (Success) {Object} itemid 单曲编号
    @apiSuccess (Success) {Object} translatename 翻译名称

    @apiSuccessExample {json} Success-Response:
    {
        "data": [
            {
                "itemid": 9546550,
                "translatename": "Be Your Light (电视剧「隧道」片尾曲)"
            }
        ]
    }

    @apiError (Error) 31006 No playlist id in the request params!

    @apiErrorExample {json} Error-Response:
    {
        "data": "No playlist id in the request params!"
    }

    """


def pyargsort(seq, cmp=None, key=lambda x: x):
    """Like numpy's argsort, but using the builtin Python sorting
    function.  Takes an optional cmp."""
    return sorted(list(range(len(seq))), key=lambda x: key(seq.__getitem__(
        x)), cmp=None)


@staticmethod
def get_example_structures(examples):
    """Get the list of example structures."""
    if not isinstance(examples, list):
        raise ValueError('parameter examples should be of type list, {} given'
            .format(type(examples)))
    return [('Select structure', False)] + examples


def vertices_smooth(factor: float=0.5, repeat: int=1, xaxis: bool=True,
    yaxis: bool=True, zaxis: bool=True):
    """Flatten angles of selected vertices

    :param factor: Smoothing, Smoothing factor
    :type factor: float
    :param repeat: Repeat, Number of times to smooth the mesh
    :type repeat: int
    :param xaxis: X-Axis, Smooth along the X axis
    :type xaxis: bool
    :param yaxis: Y-Axis, Smooth along the Y axis
    :type yaxis: bool
    :param zaxis: Z-Axis, Smooth along the Z axis
    :type zaxis: bool
    """
    pass


def _construct_vector(m, i):
    """Construct the vector for x_i of length 2^m, which has form:
    A string of 2^{m-i-1} 1s followed by 2^{m-i-1} 0s, repeated
    2^m / (2*2^{m-i-1}) = 2^{m-1}/2^{m-i-1} = 2^i times.
    NOTE: we must have 0 <= i < m."""
    return ([1] * 2 ** (m - i - 1) + [0] * 2 ** (m - i - 1)) * 2 ** i


def set_color(actor, color):
    """
    set an actor's look to a specific color

    :param actor:
    :param color:

    """
    actor.color(c=color)


def getSystemPlatform():
    """Return an unicode string containing the system platform name
        """


@classmethod
def check_success(cls, response, msg):
    """Raise CallFailure on problems.

        :param response: a requests.Response
        :param msg: the result of parse_response on response
        """
    pass


def ranaxis(dmin, dmax):
    """needs a doc string"""
    import random as rand
    return rand.random() * (dmax - dmin) + dmin


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 is_root(dmrs, nodeid):
    """
    Check if a node has no incoming links
    """
    return not any(dmrs.get_in(nodeid, itr=True))


def reveal():
    """Show all Grease Pencil layers

    """
    pass


def chunks(iterable, n):
    """Yield successive n-sized chunks from iterable"""
    for i in range(0, len(iterable), n):
        yield iterable[i:i + n]


def launch(url, wait=False, locate=False):
    """This function launches the given URL (or filename) in the default
    viewer application for this file type.  If this is an executable, it
    might launch the executable in a new session.  The return value is
    the exit code of the launched application.  Usually, ``0`` indicates
    success.

    Examples::

        click.launch('http://click.pocoo.org/')
        click.launch('/my/downloaded/file', locate=True)

    .. versionadded:: 2.0

    :param url: URL or filename of the thing to launch.
    :param wait: waits for the program to stop.
    :param locate: if this is set to `True` then instead of launching the
                   application associated with the URL it will attempt to
                   launch a file manager with the file located.  This
                   might have weird effects if the URL does not point to
                   the filesystem.
    """
    from ._termui_impl import open_url
    return open_url(url, wait=wait, locate=locate)


def _to_bytes(string):
    """
    Convert string to bytes.
    """
    if not isinstance(string, (str, bytes)):
        string = str(string)
    return string if isinstance(string, bytes) else string.encode('utf-8')


def is_supported_trait(trait):
    """ Returns true if the given trait is supported by this type This
        doesn't mean that the trait may be added to this page, it serves
        as a simple sanity check, returning True if the combination of the
        type and the trait make any sense at all.

        """
    raise NotImplementedError


def dig2phys(signal, dmin, dmax, pmin, pmax):
    """
    converts digital edf values to physical values

    Parameters
    ----------
    signal : np.ndarray or int
        A numpy array with int values (digital values) or an int.
    dmin : int
        digital minimum value of the edf file (eg -2048).
    dmax : int
        digital maximum value of the edf file (eg 2048).
    pmin : float
        physical maximum value of the edf file (eg -200.0).
    pmax : float
        physical maximum value of the edf file (eg 200.0).

    Returns
    -------
    physical : np.ndarray or float
        converted physical values

    """
    m = (pmax - pmin) / (dmax - dmin)
    physical = m * signal
    return physical


def __enter__():
    """enter execution context"""


def hdf_is_open(fid):
    """ Is an HDF file open via fid """
    try:
        status = fid.id.valid
    except AttributeError:
        status = fid.fid.valid
    if status == 0:
        return False
    elif status == 1:
        return True
    else:
        return None


def is_script(path):
    """
    Check if a given file starts with the magic sequence '#!'.
    """
    with open(path, 'rb') as f:
        return f.read(2) == b'#!'


def __contains__(changeid):
    """Whether a changeset exists."""


def do_intersect(bb1, bb2):
    """
    Helper function that returns True if two bounding boxes overlap.
    """
    if bb1[0] + bb1[2] < bb2[0] or bb2[0] + bb2[2] < bb1[0]:
        return False
    if bb1[1] + bb1[3] < bb2[1] or bb2[1] + bb2[3] < bb1[1]:
        return False
    return True


def _is_earlier(t1, t2):
    """Compares two timestamps."""
    if t1['secs'] > t2['secs']:
        return False
    elif t1['secs'] < t2['secs']:
        return True
    elif t1['nsecs'] < t2['nsecs']:
        return True
    return False


def digitsum_small(n):
    """ Use for numbers with less than 6 digits. """
    s = 0
    while n:
        s += n % 10
        n //= 10
    return s


def get_status_string():
    """Active or Inactive in the specific locale"""


def nodeattrfunc(args, node):
    """Node attributes function"""
    label = node.name.upper()
    if not args.minimal_labels and node.description:
        label = '%s:\n%s' % (label, node.description)
    words = label.split(' ')
    words_per_line = 3
    lines = []
    for idx in range(0, len(words), words_per_line):
        line = ' '.join(words[idx:min(len(words), idx + words_per_line)])
        lines.append(line)
    label = '\n'.join(lines)
    if not args.minimal_labels and node.effect_size:
        label = '%s\n%s: %0.3f' % (label, args.effect_name, node.effect_size)
    shape = ('rectangle' if args.rectangle_leaves and node.was_leaf else
        'ellipse')
    return (
        'fillcolor="/%s/%d" label="%s" style=filled fontname="helvetica bold" fontsize=15.0 fontcolor=%s shape = %s'
         % (args.color_scheme, node.color, label, node.fontcolor, shape))


def getProximityInWindow(geneWinT, geneProximityD):
    """Given a window of genes, calculate the distances between first gene
and the rest (in number of genes) and store in geneProximityD. Updates
geneProximityD in place, returning None.
    """
    gnA = geneWinT[0]
    for i in range(1, len(geneWinT)):
        gnB = geneWinT[i]
        if gnA < gnB:
            geneProximityD[gnA, gnB] = i
        else:
            geneProximityD[gnB, gnA] = i


@staticmethod
def _convert_entity_refs(text):
    """Converts entity refs to chars to handle etree auto conversions."""
    text = text.replace('<', '<')
    text = text.replace('>', '>')
    return text


def _print_pgfplot_libs_message(data):
    """Prints message to screen indicating the use of PGFPlots and its
    libraries."""
    pgfplotslibs = ','.join(list(data['pgfplots libs']))
    tikzlibs = ','.join(list(data['tikz libs']))
    print(70 * '=')
    print('Please add the following lines to your LaTeX preamble:\n')
    print('\\usepackage[utf8]{inputenc}')
    print('\\usepackage{fontspec}  % This line only for XeLaTeX and LuaLaTeX')
    print('\\usepackage{pgfplots}')
    if tikzlibs:
        print('\\usetikzlibrary{' + tikzlibs + '}')
    if pgfplotslibs:
        print('\\usepgfplotslibrary{' + pgfplotslibs + '}')
    print(70 * '=')
    return


def db2dbm(quality):
    """
    Converts the Radio (Received) Signal Strength Indicator (in db) to a dBm
    value.  Please see http://stackoverflow.com/a/15798024/1013960
    """
    dbm = int(quality / 2 - 100)
    return min(max(dbm, -100), -50)


def A_func(*, η_O, η_A, η_H, b_θ, b_r, b_φ, deriv_η_O, deriv_η_A, deriv_η_H,
    deriv_b_θ, deriv_b_r, deriv_b_φ):
    """
    Compute the value of the variable A
    """
    return (deriv_η_H * b_θ + η_H * deriv_b_θ - deriv_η_A * b_r * b_φ - η_A *
        deriv_b_r * b_φ - η_A * b_r * deriv_b_φ) / (η_O + η_A * (1 - b_φ ** 2)
        ) - (deriv_η_O + deriv_η_A * (1 - b_φ ** 2) - 2 * η_A * b_φ * deriv_b_φ
        ) * (η_H * b_θ - η_A * b_r * b_φ) / (η_O + η_A * (1 - b_φ ** 2)) ** 2


def list_ip_routes(DirectoryId=None, NextToken=None, Limit=None):
    """
    Lists the address blocks that you have added to a directory.
    See also: AWS API Documentation

    :example: response = client.list_ip_routes(
        DirectoryId='string',
        NextToken='string',
        Limit=123
    )

    :type DirectoryId: string
    :param DirectoryId: [REQUIRED]
            Identifier (ID) of the directory for which you want to retrieve the IP addresses.

    :type NextToken: string
    :param NextToken: The ListIpRoutes.NextToken value from a previous call to ListIpRoutes . Pass null if this is the first call.

    :type Limit: integer
    :param Limit: Maximum number of items to return. If this value is zero, the maximum number of items is specified by the limitations of the operation.

    :rtype: dict
    :return: {
        'IpRoutesInfo': [
            {
                'DirectoryId': 'string',
                'CidrIp': 'string',
                'IpRouteStatusMsg': 'Adding'|'Added'|'Removing'|'Removed'|'AddFailed'|'RemoveFailed',
                'AddedDateTime': datetime(2015, 1, 1),
                'IpRouteStatusReason': 'string',
                'Description': 'string'
            },
        ],
        'NextToken': 'string'
    }

    """
    pass


def can_paginate(operation_name=None):
    """
    Check if an operation can be paginated.

    :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').

    """
    pass


def convert_datetime(f):
    """Indicate that callback needs to receive datetime objects as strings"""
    setattr(f, 'convert_datetime', True)
    return f


def enum_source(descriptor):
    """Returns source code defining an enumeration type"""
    name = descriptor.name
    lines = ['// %s enum' % name, 'lua_newtable(L); // proxy table',
        'lua_newtable(L); // main table']
    for value in descriptor.value:
        k = value.name
        v = value.number
        lines.extend(['lua_pushnumber(L, %d);' % v,
            'lua_setfield(L, -2, "%s");' % k])
    lines.extend(['// define metatable on main table', 'lua_newtable(L);',
        'lua_pushcfunction(L, lua_protobuf_enum_index);',
        'lua_setfield(L, -2, "__index");', 'lua_setmetatable(L, -2);', '',
        '// define metatable on proxy table', 'lua_newtable(L);',
        'lua_pushvalue(L, -2);', 'lua_setfield(L, -2, "__index");',
        'lua_pushcfunction(L, lua_protobuf_enum_newindex);',
        'lua_setfield(L, -2, "__newindex");', 'lua_remove(L, -2);',
        'lua_setmetatable(L, -2);', 'lua_setfield(L, -2, "%s");' % name,
        '// end %s enum' % name])
    return lines


def removeUnwantedHeaders(allHeadersContent):
    """ remove unwanted headers, e.g. the ones used for dictionaries but not desirable in the pch
   """
    unwantedHeaders = []
    deprecatedHeaders = ['']
    unwantedHeaders.extend(deprecatedHeaders)
    for unwantedHeader in unwantedHeaders:
        allHeadersContent = allHeadersContent.replace('#include "%s"' %
            unwantedHeader, '')
    return allHeadersContent


def is_left(point0, point1, point2):
    """ Tests if a point is Left|On|Right of an infinite line.

    Ported from the C++ version: on http://geomalgorithms.com/a03-_inclusion.html

    .. note:: This implementation only works in 2-dimensional space.

    :param point0: Point P0
    :param point1: Point P1
    :param point2: Point P2
    :return:
        >0 for P2 left of the line through P0 and P1
        =0 for P2 on the line
        <0 for P2 right of the line
    """
    return (point1[0] - point0[0]) * (point2[1] - point0[1]) - (point2[0] -
        point0[0]) * (point1[1] - point0[1])


def filter_by_accuracy(points, cutoff=30):
    """
    Remove points that have worse reported accuracy than the cutoff value in meters.
    """
    for p in points:
        if p.h_accuracy <= cutoff:
            yield p


def zonesurfaces(ddtt):
    """return al list of surfaces that belong to the zone"""
    kwargs = {'fields': ['Zone_Name'], 'iddgroups': [
        'Thermal Zones and Surfaces']}
    return ddtt.getreferingobjs(**kwargs)


def to_bytes(s):
    """convert str to bytes for py 2/3 compat
    """
    if isinstance(s, bytes):
        return s
    return s.encode('utf-8', 'ignore')


def object_type_repr(obj):
    """Returns the name of the object's type.  For some recognized
    singletons the name of the object is returned instead. (For
    example for `None` and `Ellipsis`).
    """
    if obj is None:
        return 'None'
    elif obj is Ellipsis:
        return 'Ellipsis'
    cls = type(obj)
    if cls.__module__ in ('__builtin__', 'builtins'):
        name = cls.__name__
    else:
        name = cls.__module__ + '.' + cls.__name__
    return '%s object' % name


def __filter_greater_than(items, attr, value):
    """
        select from items list where the attribute is greater than 'value' as
        integers
    """
    filtered_items = []
    for item in items:
        if int(item[attr]) > int(value):
            filtered_items.append(item)
    return filtered_items


def uch_punwani(xy, d_pipe, gs, rhog, rhos, ut):
    """
    Provide functions to solve for voidage and choking velocity based on
    equations from Punwani 1976. Requires SciPy fsolve function.

    Parameters
    ----------
    xy
        Solves for ep and uch using SciPy fsolve where
        ep = voidage [-] and uch = choking velocity [m/s]
    d_pipe : float
        Internal pipe diameter [m]
    gs : float
        Solids flux [kg/(s m^2)]
    rhog : float
        Density of gas, must be in units of lb/ft^3
    rhos : float
        Density of particle [kg/m^3]
    ut : float
        Terminal velocity [m/s]

    Returns
    -------
    f1, f2 : functions
        Functions to solve for ep and uch

    References
    ----------
    Punwani, Modi, Tarman, 1976. A Generalized Correlation for Estimating
    Choking Velocity in Vertical Solids Transport. Institute of Gas Technology,
    Chicago, IL, 1-14.
    """
    ep, uc = xy
    g = 9.81
    f1 = 2 * g * d_pipe * (ep ** -4.7 - 1) - 0.074 * rhog ** 0.77 * (uc /
        ep - ut) ** 2
    f2 = gs / rhos / (1 - ep) - uc / ep + ut
    return f1, f2


def convert2boolean(arg):
    """convert2boolean is used for environmental variables that must be
    returned as boolean"""
    if not isinstance(arg, bool):
        return arg.lower() in ('yes', 'true', 't', '1', 'y')
    return arg


def _win_path_to_bytes(path):
    """Encode Windows paths to bytes. Only used on Python 2.

    Motivation is to be consistent with other operating systems where paths
    are also returned as bytes. This avoids problems mixing bytes and Unicode
    elsewhere in the codebase. For more details and discussion see
    <https://github.com/pypa/pip/issues/3463>.

    If encoding using ASCII and MBCS fails, return the original Unicode path.
    """
    for encoding in ('ASCII', 'MBCS'):
        try:
            return path.encode(encoding)
        except (UnicodeEncodeError, LookupError):
            pass
    return path


def clip(x, lowest, highest):
    """Return x clipped to the range [lowest..highest]."""
    return max(lowest, min(x, highest))


def boolean(s):
    """
    Convert JSON/Swagger boolean value to Python, raise ValueError otherwise

    >>> boolean('true')
    True

    >>> boolean('false')
    False
    """
    if isinstance(s, bool):
        return s
    elif not hasattr(s, 'lower'):
        raise ValueError('Invalid boolean value')
    elif s.lower() == 'true':
        return True
    elif s.lower() == 'false':
        return False
    else:
        raise ValueError('Invalid boolean value')


def _get_sysfs_netdev_path(pci_addr, pf_interface):
    """Get the sysfs path based on the PCI address of the device.

    Assumes a networking device - will not check for the existence of the path.
    """
    if pf_interface:
        return '/sys/bus/pci/devices/%s/physfn/net' % pci_addr
    return '/sys/bus/pci/devices/%s/net' % pci_addr


def ExecuteBashCommandMute(commandString):
    """Executes a bash command without printing it.

    Parameters
    ----------
    commandString : :obj:`str`
        command line

    """
    from os import system
    system(commandString)


def psi_Ca_Mg_Cl_PK74(T, P):
    """c-c'-a: calcium magnesium chloride [PK74]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def is_dictionary_subset(sub, super_dict):
    """
    This function checks if `sub` dictionary is a subset of `super` dictionary.
    :param sub: subset dictionary, for example user_provided_attr_value.
    :param super_dict: super dictionary, for example resources_attr_value.
    :return: True if sub is contained in super.
    """
    for key in sub:
        if sub[key] != super_dict[key]:
            return False
    return True


def is_latex_enabled():
    """
    Returns True if LaTeX is enabled in matplotlib's rcParams,
    False otherwise
    """
    import matplotlib as mpl
    return mpl.rcParams['text.usetex']


def get_key_def(key, config, default=None, msg=None, delete=False):
    """Returns a value given a dictionary key, or the default value if it cannot be found."""
    if isinstance(key, list):
        if len(key) <= 1:
            if msg is not None:
                raise AssertionError(msg)
            else:
                raise AssertionError(
                    'must provide at least two valid keys to test')
        for k in key:
            if k in config:
                val = config[k]
                if delete:
                    del config[k]
                return val
        return default
    elif key not in config:
        return default
    else:
        val = config[key]
        if delete:
            del config[key]
        return val


def makeFigFromFile(filename, *args, **kwargs):
    """
    Renders an image in a matplotlib figure, so it can be added to reports
    args and kwargs are passed to plt.subplots
    """
    import matplotlib.pyplot as plt
    img = plt.imread(filename)
    fig, ax = plt.subplots(*args, **kwargs)
    ax.axis('off')
    ax.imshow(img)
    return fig


def __check_completeness(transcript):
    """Private method that checks whether a transcript is complete
    or not based solely on the presence of CDS/UTR information."""
    if len(transcript.combined_utr) > 0:
        if transcript.combined_utr[0][0] < transcript.combined_cds[0][0]:
            if transcript.strand == '+':
                transcript.has_start_codon = True
            elif transcript.strand == '-':
                transcript.has_stop_codon = True
        if transcript.combined_utr[-1][1] > transcript.combined_cds[-1][1]:
            if transcript.strand == '+':
                transcript.has_stop_codon = True
            elif transcript.strand == '-':
                transcript.has_start_codon = True


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 scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def parse_attribute(attribute, lines, i, path):
    """
    Parse one attribute from the APKBUILD.

    It may be written across multiple lines, use a quoting sign and/or have
    a comment at the end. Some examples:

    pkgrel=3
    options="!check" # ignore this comment
    arch='all !armhf'
    depends="
        first-pkg
        second-pkg"

    :param attribute: from the APKBUILD, i.e. "pkgname"
    :param lines:
-terminated list of lines from the APKBUILD
    :param i: index of the line we are currently looking at
    :param path: full path to the APKBUILD (for error message)
    :returns: (found, value, i)
              found: True if the attribute was found in line i, False otherwise
              value: that was parsed from the line
              i: line that was parsed last
    """
    if not lines[i].startswith(attribute + '='):
        return False, None, i
    value = lines[i][len(attribute + '='):-1]
    end_char = None
    for char in ["'", '"']:
        if value.startswith(char):
            end_char = char
            value = value[1:]
            break
    if not end_char:
        return True, value, i
    if end_char in value:
        value = value.split(end_char, 1)[0]
        return True, value, i
    i += 1
    while i < len(lines):
        line = lines[i]
        value += ' '
        if end_char in line:
            value += line.split(end_char, 1)[0].strip()
            return True, value.strip(), i
        value += line.strip()
        i += 1
    raise RuntimeError("Can't find closing quote sign (" + end_char +
        ") for attribute '" + attribute + "' in: " + path)


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 items(cls):
    """
        All values for this enum
        :return: list of `pyowm.commons.enums.ImageType`

        """
    return [cls.PNG, cls.GEOTIFF]


def delete(k):
    """
        Call __delitem__ with key k.
        """


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

    Like 'git describe --tags --dirty --always'.

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


def _is_settable(field: 'dataclasses.Field[Any]') ->bool:
    """Determine if the given :class:`dataclasses.Field` is settable.

    :param field:
        Field to determine if it is settable.

    :return:
        True if the `field` is optional, otherwise False.
    """
    return field.init


@classmethod
def load_from_file(cls, filename):
    """Return a Css.root tree from filename, handling the encoding."""
    return cls.load_from_data(open(filename, 'rb').read())


def parse_http_datetime(datestring, utc_tzinfo=None, strict=False):
    """Returns a datetime object from an HTTP 1.1 Date/Time string.

    Note that HTTP dates are always in UTC, so the returned datetime
    object will also be in UTC.

    You can optionally pass in a tzinfo object which should represent
    the UTC timezone, and the returned datetime will then be
    timezone-aware (allowing you to more easly translate it into
    different timzeones later).

    If you set 'strict' to True, then only the RFC 1123 format
    is recognized.  Otherwise the backwards-compatible RFC 1036
    and Unix asctime(3) formats are also recognized.

    Please note that the day-of-the-week is not validated.
    Also two-digit years, although not HTTP 1.1 compliant, are
    treated according to recommended Y2K rules.

    """
    import re, datetime
    m = re.match(
        '(?P<DOW>[a-z]+), (?P<D>\\d+) (?P<MON>[a-z]+) (?P<Y>\\d+) (?P<H>\\d+):(?P<M>\\d+):(?P<S>\\d+(\\.\\d+)?) (?P<TZ>[a-zA-Z0-9_+]+)$'
        , datestring, re.IGNORECASE)
    if not m and not strict:
        m = re.match(
            '(?P<DOW>[a-z]+) (?P<MON>[a-z]+) (?P<D>\\d+) (?P<H>\\d+):(?P<M>\\d+):(?P<S>\\d+) (?P<Y>\\d+)$'
            , datestring, re.IGNORECASE)
        if not m:
            m = re.match(
                '(?P<DOW>[a-z]+), (?P<D>\\d+)-(?P<MON>[a-z]+)-(?P<Y>\\d+) (?P<H>\\d+):(?P<M>\\d+):(?P<S>\\d+(\\.\\d+)?) (?P<TZ>\\w+)$'
                , datestring, re.IGNORECASE)
    if not m:
        raise ValueError('HTTP date is not correctly formatted')
    try:
        tz = m.group('TZ').upper()
    except:
        tz = 'GMT'
    if tz not in ('GMT', 'UTC', '0000', '00:00'):
        raise ValueError('HTTP date is not in GMT timezone')
    monname = m.group('MON').upper()
    mdict = {'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6,
        'JUL': 7, 'AUG': 8, 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12}
    month = mdict.get(monname)
    if not month:
        raise ValueError('HTTP date has an unrecognizable month')
    y = int(m.group('Y'))
    if y < 100:
        century = datetime.datetime.utcnow().year / 100
        if y < 50:
            y = century * 100 + y
        else:
            y = (century - 1) * 100 + y
    d = int(m.group('D'))
    hour = int(m.group('H'))
    minute = int(m.group('M'))
    try:
        second = int(m.group('S'))
    except:
        second = float(m.group('S'))
    dt = datetime.datetime(y, month, d, hour, minute, second, tzinfo=utc_tzinfo
        )
    return dt


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


@staticmethod
def get_elastic_mappings(es_major):
    """Get Elasticsearch mapping.

        Different versions of Elasticsearch may need specific versions
        of the mapping, thus using es_major to potentially provide
        different mappings.

        When the mapping depends on the version of Kibiter/Kibana,
        we will use the Elasticsearch version anyway, since they should
        be paired (same major version for 5 and larger, ES major version 2
        for Kibiter/Kibana major version 4).

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = '{}'
    return {'items': mapping}


def _escape_for_regex(text):
    """Escape ``text`` to allow literal matching using egrep"""
    re_specials = '\\^$|(){}[]*+?.'
    sh_specials = '\\$`"'
    re_chars = []
    sh_chars = []
    for c in text:
        if c in re_specials:
            re_chars.append('\\')
        re_chars.append(c)
    for c in re_chars:
        if c in sh_specials:
            sh_chars.append('\\')
        sh_chars.append(c)
    return ''.join(sh_chars)


def to_list(value):
    """Convert `value` to a list."""
    if not isinstance(value, list) and value is not None:
        value = [value]
    return value


def p_path_expr_1(p):
    """PathExpr : LocationPath"""
    p[0] = p[1]


def convert_p(element, text):
    """
    Adds 2 newlines to the end of text
    """
    depth = -1
    while element:
        if not element.name == '[document]' and not element.parent.get('id'
            ) == '__RESTRUCTIFY_WRAPPER__':
            depth += 1
        element = element.parent
    if text:
        text = '    ' * depth + text
    return text


def dfs_tree(graph, start=0):
    """DFS, build DFS tree in unweighted graph

       :param graph: directed graph in listlist or listdict format
       :param int start: source vertex
       :returns: precedence table
       :complexity: `O(|V|+|E|)`
       """
    to_visit = [start]
    prec = [None] * len(graph)
    while to_visit:
        node = to_visit.pop()
        for neighbor in graph[node]:
            if prec[neighbor] is None:
                prec[neighbor] = node
                to_visit.append(neighbor)
    return prec


@staticmethod
def format_resource_name(name):
    """format resource name

        Util method to format resource names to make them compatible with BCF.

        Replaces special characters with its corresponding BCF compatible
        encoding.

        :param name non empty string which is the name of the resource
        :rtype string name with special characters replaced
        """
    return name.replace('_', '__').replace(' ', '_s').replace("'", '_a'
        ).replace('/', '_f').replace('[', '_l').replace(']', '_r')


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

        :param SharedLinkCopyDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_copy_details', val)


@staticmethod
def _sentence_tokenizer_merge_matches(match):
    """ Best way we found to deal with repeating groups"""
    start, end = match.span()
    return match.string[start:end] + '<SPLIT>'


def experimental(func):
    """
    Decorator for marking APIs experimental in the docstring.

    :param func: A function to mark
    :returns Decorated function.
    """
    notice = '.. Note:: Experimental: This method may change or ' + """be removed in a future release without warning.
"""
    func.__doc__ = notice + func.__doc__
    return func


@staticmethod
def __deleteQuote(quoted_string):
    """Delete first and last " or ' from {quoted_string}

    Keyword arguments:
      quoted_string -- (string) String to get rid of quotes

    return: (string) {quoted_string} without quotes
     """
    str_lengh = len(quoted_string)
    if str_lengh > 1:
        if quoted_string[0] == '"' or quoted_string[0] == "'":
            quoted_string = quoted_string[1:]
        str_lengh = len(quoted_string)
        if str_lengh >= 1:
            if quoted_string[str_lengh - 1] == '"' or quoted_string[
                str_lengh - 1] == "'":
                quoted_string = quoted_string[:str_lengh - 1]
    return quoted_string


def update_package_data(distribution):
    """update build_py options to get package_data changes"""
    build_py = distribution.get_command_obj('build_py')
    build_py.finalize_options()


@staticmethod
def get_card_not_enrolled_eci(card_type):
    """
        Get the card not enrolled ECI for the given card type.
        https://resourcecentre.realexpayments.com/pdf/RealControl%20Reporting%20-%20User%20Guide%20v1.0.pdf
        :param str card_type: The card type. e.g: VISA, MC, AMEX,...
        :return str: The ECI.
        """
    if card_type == 'VISA':
        return '6'
    if card_type == 'MC':
        return '1'
    raise Exception('Only VISA and MC support 3DSecure.')


def obv(df, price='close', volume='volume', col='obv'):
    """
    On Balance Volume (OBV) measures buying and selling pressure as a cumulative indicator, adding volume on up days and subtracting it on down days
    The On Balance Volume (OBV) line is simply a running total of positive and negative volume.
    A period's volume is positive when the close is above the prior close and is negative when the close is below the prior close.

    The On Balance Volume (OBV) is a cumulative total of the up and down volume.
    When the close is higher than the previous close, the volume is added to
    the running total, and when the close is lower than the previous close,
    the volume is subtracted from the running total.

    Parameters:
        df (pd.DataFrame): DataFrame which contain the asset price.
        price (string): the column name of the price of the asset.
        volume (string): the column name of the volume of the asset.
        obv (string): the column name for the on balance volume values.

    Returns:
        df (pd.DataFrame): Dataframe with obv of the asset calculated.

    Sample Strategy:
    Bullish:
        AND [Daily SMA(60,Daily Volume) > 100000]
        AND [Daily SMA(60,Daily Close) > 10]

        AND [Daily Close < Daily SMA(65,Daily Close)]
        AND [Daily AccDist > Daily AccDist Signal (65)]
        AND [Daily OBV > Daily OBV Signal(65)]
        AND [Daily Close < Daily SMA(20,Daily Close)]
        AND [Daily AccDist > Daily AccDist Signal (20)]
        AND [Daily OBV > Daily OBV Signal(20)]

    Bearish:

        AND [Daily SMA(60,Daily Volume) > 100000]
        AND [Daily SMA(60,Daily Close) > 10]

        AND [Daily Close > Daily SMA(65,Daily Close)]
        AND [Daily AccDist < Daily AccDist Signal (65)]
        AND [Daily OBV < Daily OBV Signal(65)]
        AND [Daily Close > Daily SMA(20,Daily Close)]
        AND [Daily AccDist < Daily AccDist Signal (20)]
        AND [Daily OBV < Daily OBV Signal(20)]

    Citation: https://school.stockcharts.com/doku.php?id=technical_indicators:on_balance_volume_obv

    """
    df['diff'] = df[price].diff()
    df = df.fillna(1)
    df.loc[df['diff'] > 0, col + '_sign'] = 1
    df.loc[df['diff'] < 0, col + '_sign'] = -1
    df.loc[df['diff'] == 0, col + '_sign'] = 0
    volume_sign = df[volume] * df[col + '_sign']
    df[col] = volume_sign.cumsum()
    df.drop(['diff', col + '_sign'], axis=1, inplace=True)
    return df


def add_matched_element(element, target_set, sep):
    """Append an element to the end of all elements in a set.

    Creates a new copy of target_set with an element appended to the end of all
    items in that target_set. Returns a union between the target_set and the
    newly created copy of target_set.

    @param element: The element to add.
    @param target_set: Collection of items to append element to.
    @type target_set: set
    @return: The union between a copy of target_set with element appended to
        all of its items and the original target_set.
    @rtype: set
    """
    new_elements = map(lambda x: x + sep + element, target_set)
    return target_set.union(new_elements)


def clear_render_border():
    """Clear the boundaries of the border render and disable border render

    """
    pass


def try_(func, default=None):
    """Try return the result of func, else return default."""
    try:
        return func()
    except Exception:
        return default


def preloaded_multi_mp_sgd_mom_update(*data, **kwargs):
    """Momentum update function for multi-precision Stochastic Gradient Descent (SGD) optimizer.

    Momentum update has better convergence rates on neural networks. Mathematically it looks
    like below:

    .. math::

      v_1 = \\alpha * \\nabla J(W_0)\\\\
      v_t = \\gamma v_{t-1} - \\alpha * \\nabla J(W_{t-1})\\\\
      W_t = W_{t-1} + v_t

    It updates the weights using::

      v = momentum * v - learning_rate * gradient
      weight += v

    Where the parameter ``momentum`` is the decay rate of momentum estimates at each epoch.

    Defined in src/operator/contrib/preloaded_multi_sgd.cc:L200

    Parameters
    ----------
    data : NDArray[]
        Weights, gradients, momentums, learning rates and weight decays
    momentum : float, optional, default=0
        The decay rate of momentum estimates at each epoch.
    rescale_grad : float, optional, default=1
        Rescale gradient to grad = rescale_grad*grad.
    clip_gradient : float, optional, default=-1
        Clip gradient to the range of [-clip_gradient, clip_gradient] If clip_gradient <= 0, gradient clipping is turned off. grad = max(min(grad, clip_gradient), -clip_gradient).
    num_weights : int, optional, default='1'
        Number of updated weights.

    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 equiangular_dimension_unpack(nodes, ratio):
    """Calculate the two underlying dimensions
    from the total number of nodes

    Args:
        nodes (int): combined dimensions
        ratio (float): ratio between the two dimensions

    Returns:
        int, int: separated dimensions
    """
    dim1 = int((nodes / ratio) ** 0.5)
    dim2 = int((nodes * ratio) ** 0.5)
    return dim1, dim2


def with_metaclass(meta, *bases):
    """Create a base class with a metaclass."""
    return meta('NewBase', bases, {})


def _write_gml(G, path):
    """
    Wrapper around nx.write_gml
    """
    import networkx as nx
    return nx.write_gml(G, path, stringizer=str)


def p_if_stmt(p):
    """if_stmt : IF OPEN_PAREN expression CLOSE_PAREN maybe_nline suite
               | if_stmt ELSEIF OPEN_PAREN expression CLOSE_PAREN maybe_nline suite """
    if len(p) == 7:
        p[0] = ['IF_EXPR']
        p[0].append(p[3])
        p[0].append(p[6])
        p[0].append([])
    else:
        p[0] = p[1]
        p[0][3].append([p[4], p[7]])


def _ensure_exceptable(errors):
    """Ensures that errors are passable to except clause.
       I.e. should be BaseException subclass or a tuple."""
    is_exception = isinstance(errors, type) and issubclass(errors,
        BaseException)
    return errors if is_exception else tuple(errors)


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

        :param PaperContentAddMemberDetails val:
        :rtype: EventDetails
        """
    return cls('paper_content_add_member_details', val)


def fib(x):
    """
    :returns an array of first x fib numbers
    :param x: length of to-be-found array
    :return: array of first x fib numbers
    """
    if type(x) != int:
        raise Exception('Input variable must be a positive int')
    if x < 0:
        raise Exception('Input variable must be a positive int')
    result = []
    a = 0
    b = 1
    c = 1
    while len(result) != x:
        result.append(a)
        a = b
        b = c
        c = a + b
    return result


def remove(key):
    """ remove from cache """


def within_delta(dt1, dt2, delta):
    """
    Useful for comparing two datetimes that may a negilible difference
    to be considered equal.
    """
    delta = abs(delta)
    difference = dt1 - dt2
    return -delta <= difference <= delta


def color(requestContext, seriesList, theColor):
    """
    Assigns the given color to the seriesList

    Example::

        &target=color(collectd.hostname.cpu.0.user, 'green')
        &target=color(collectd.hostname.cpu.0.system, 'ff0000')
        &target=color(collectd.hostname.cpu.0.idle, 'gray')
        &target=color(collectd.hostname.cpu.0.idle, '6464ffaa')

    """
    for series in seriesList:
        series.color = theColor
    return seriesList


def legend_strategy_always(scrollbar, legend):
    """
    A strategy for a legend, to make it visible always.
    """
    legend.show()


def plural(n):
    """Utility function to optionally pluralize words based on the value of n.
    """
    if n == 1:
        return ''
    else:
        return 's'


def preloaded_multi_sgd_mom_update(*data, **kwargs):
    """Momentum update function for Stochastic Gradient Descent (SGD) optimizer.

    Momentum update has better convergence rates on neural networks. Mathematically it looks
    like below:

    .. math::

      v_1 = \\alpha * \\nabla J(W_0)\\\\
      v_t = \\gamma v_{t-1} - \\alpha * \\nabla J(W_{t-1})\\\\
      W_t = W_{t-1} + v_t

    It updates the weights using::

      v = momentum * v - learning_rate * gradient
      weight += v

    Where the parameter ``momentum`` is the decay rate of momentum estimates at each epoch.

    Defined in src/operator/contrib/preloaded_multi_sgd.cc:L91

    Parameters
    ----------
    data : NDArray[]
        Weights, gradients, momentum, learning rates and weight decays
    momentum : float, optional, default=0
        The decay rate of momentum estimates at each epoch.
    rescale_grad : float, optional, default=1
        Rescale gradient to grad = rescale_grad*grad.
    clip_gradient : float, optional, default=-1
        Clip gradient to the range of [-clip_gradient, clip_gradient] If clip_gradient <= 0, gradient clipping is turned off. grad = max(min(grad, clip_gradient), -clip_gradient).
    num_weights : int, optional, default='1'
        Number of updated weights.

    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 string_is_yes(string, default=None):
    """
    Mapping of a given string to a boolean.

    If it is empty or None (evaluates to False), and `default` is set, `default` is returned.
    If the lowercase of the string is any of ['y', '1', 'yes', 'true', 'ja'], it will return `True`.
    Else it will return `False`

    :param string: The input
    :type  string: str

    :param default: default result for empty input
    :type  default: None | bool

    :return: result (True/False/default)
    :rtype:  bool
    """
    if not string and default is not None:
        return default
    return string.lower() in ['y', '1', 'yes', 'true', 'ja']


def minimum(value, index, exclude=False):
    """normalize a query value for minimum of a range; return the value for
        query"""


def bytes_to_str(input_bytes):
    """Convert bytes to string.
  """
    return input_bytes.decode()


def _aisc_table(metric, version):
    """
    Returns the name of the AISC table matching the criteria.

    Parameters
    ----------
    metric : bool
        If True, searches for the name in the metric shape database. Otherwise,
        searches for the name in the imperial shape database.
    version : {'15.0'}
        The version of the shape database to query. If None, the latest version
        will be used.
    """
    if version is None:
        version = '15.0'
    if version == '15.0':
        if metric:
            return 'aisc_metric_15_0'
        else:
            return 'aisc_imperial_15_0'
    else:
        raise ValueError('Version {!r} not found.'.format(version))


def get_dirs_and_files(key_list, prefix):
    """
    Return a 2-tuple of sets. The first set in the 2-tuple
    contains directory names and the second set contains files names.

    Example with an object_key of /static/. The leading slash from /
    get_dirs_and_files('/static/', ['static/css/ads.css', 'static/js/main.js', 'static/robots.txt'])
    {'css', 'js'} {'robots.txt'}
    """
    dirs = set()
    files = set()
    prefix = prefix.lstrip('/')
    prefix_len = len(prefix)
    for key in key_list:
        if key.startswith(prefix):
            key = key[prefix_len:]
        if '/' in key:
            dirs.add(key.split('/')[0])
        else:
            files.add(key)
    return dirs, files


def deep_copy_array(array_in):
    """
    Meant only for an array of scalars (no nesting):
    """
    array_out = []
    for i in range(len(array_in)):
        array_out.append(array_in[i])
    return array_out


@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 ext_mid(data):
    """
    Extract the middle of the spectrum.

    Parameters
    ----------
    data : ndarray
        Array of NMR data.

    Returns
    -------
    ndata : ndarray
        Middle half of spectrum.

    """
    return data[(...), int(data.shape[-1] * 1.0 / 4.0):int(data.shape[-1] *
        3.0 / 4.0)]


def suggestDType(x):
    """Return a suitable dtype for x"""
    if isinstance(x, list) or isinstance(x, tuple):
        if len(x) == 0:
            raise Exception('can not determine dtype for empty list')
        x = x[0]
    if hasattr(x, 'dtype'):
        return x.dtype
    elif isinstance(x, float):
        return float
    elif isinstance(x, int):
        return int
    else:
        return object


def bucket_to_tablename(prefix, bucket):
    """Convert bucket to SQLAlchemy tablename.
    """
    return prefix + bucket


def do_insertions(insertions, tokens):
    """
    Helper for lexers which must combine the results of several
    sublexers.

    ``insertions`` is a list of ``(index, itokens)`` pairs.
    Each ``itokens`` iterable should be inserted at position
    ``index`` into the token stream given by the ``tokens``
    argument.

    The result is a combined token stream.

    TODO: clean up the code here.
    """
    insertions = iter(insertions)
    try:
        index, itokens = next(insertions)
    except StopIteration:
        for item in tokens:
            yield item
        return
    realpos = None
    insleft = True
    for i, t, v in tokens:
        if realpos is None:
            realpos = i
        oldi = 0
        while insleft and i + len(v) >= index:
            tmpval = v[oldi:index - i]
            yield realpos, t, tmpval
            realpos += len(tmpval)
            for it_index, it_token, it_value in itokens:
                yield realpos, it_token, it_value
                realpos += len(it_value)
            oldi = index - i
            try:
                index, itokens = next(insertions)
            except StopIteration:
                insleft = False
                break
        yield realpos, t, v[oldi:]
        realpos += len(v) - oldi
    while insleft:
        realpos = realpos or 0
        for p, t, v in itokens:
            yield realpos, t, v
            realpos += len(v)
        try:
            index, itokens = next(insertions)
        except StopIteration:
            insleft = False
            break


def check_commutativity(op_1, op_2, anti=False):
    """
    Check the (anti-)commutativity between two operators.

    Args:
        op_1 (WeightedPauliOperator): operator
        op_2 (WeightedPauliOperator): operator
        anti (bool): if True, check anti-commutativity, otherwise check commutativity.

    Returns:
        bool: whether or not two operators are commuted or anti-commuted.
    """
    com = op_1 * op_2 - op_2 * op_1 if not anti else op_1 * op_2 + op_2 * op_1
    com.simplify()
    return bool(com.is_empty())


def dump_masked(obj, h5f, **kwargs):
    """ dumps an ndarray object to h5py file"""
    h5f.create_dataset('data', data=obj, **kwargs)
    h5f.create_dataset('mask', data=obj.mask, **kwargs)
    h5f.create_dataset('type', data=['masked'])


@classmethod
def fromASE(cls, aseg):
    """ Returns geometry from an ASE object.

        Parameters
        ----------
        aseg : ASE ``Atoms`` object which contains the following routines:
            ``get_atomic_numbers``, ``get_positions``, ``get_cell``.
            From those methods a `Geometry` object will be created.
        """
    Z = aseg.get_atomic_numbers()
    xyz = aseg.get_positions()
    cell = aseg.get_cell()
    return cls(xyz, atom=Z, sc=cell)


def assert_type_str_or_list(df, variable, name_arg):
    """This function asserts if variable is a string or a list dataType."""
    assert isinstance(variable, (str, list)
        ), 'Error: %s argument must be a string or a list.' % name_arg


def render_to_response(value, fields=None):
    """Render a member or list of members to an appropriate response.

        The request should include an indication of the client's preferred
        representation. This can be specified via the Accept header or by
        using the {.renderer} notation at the end of the URL path.

        """


def printRho(SGLaue, rho, rhoMax):
    """default doc string

    :param type name: description

    :returns: type name: description

    """
    dim = len(rho.shape)
    if dim == 2:
        ix, jy = rho.shape
        for j in range(jy):
            line = ''
            if SGLaue in ['3', '3m1', '31m', '6/m', '6/mmm']:
                line += (jy - j) * '  '
            for i in range(ix):
                r = int(100 * rho[i, j] / rhoMax)
                line += '%4d' % r
            print(line + '\n')
    else:
        ix, jy, kz = rho.shape
        for k in range(kz):
            print('k = %d' % k)
            for j in range(jy):
                line = ''
                if SGLaue in ['3', '3m1', '31m', '6/m', '6/mmm']:
                    line += (jy - j) * '  '
                for i in range(ix):
                    r = int(100 * rho[i, j, k] / rhoMax)
                    line += '%4d' % r
                print(line + '\n')


def fft_projections_convolution_image_filter(*args, **kwargs):
    """Procedural interface for FFTProjectionsConvolutionImageFilter"""
    import itk
    instance = itk.FFTProjectionsConvolutionImageFilter.New(*args, **kwargs)
    return instance.__internal_call__()


def get_full_object_name(obj):
    """
    Get full name of object
    :param obj:
    :return:
    """
    result = []
    if hasattr(obj, '__module__'):
        result.append(getattr(obj, '__module__'))
    if hasattr(obj, '__name__'):
        result.append(getattr(obj, '__name__'))
    return '.'.join(result)


def ex2err(ex):
    """Convert a Cinder Exception to a Nexenta Error."""
    return ex.msg


def search(df, column_name, search_string):
    """Search a data frame field for a string of choice"""
    tmp_df = df[df[column_name].isnull() == False]
    return tmp_df[tmp_df[column_name].str.contains(search_string)]


def build_relabel_dict(x):
    """Relabel the input ids to continuous ids that starts from zero.

    The new id follows the order of the given node id list.

    Parameters
    ----------
    x : list
      The input ids.

    Returns
    -------
    relabel_dict : dict
      Dict from old id to new id.
    """
    relabel_dict = {}
    for i, v in enumerate(x):
        relabel_dict[v] = i
    return relabel_dict


def pipe(value, *functions, funcs=None):
    """pipe(value, f, g, h) == h(g(f(value)))"""
    if funcs:
        functions = funcs
    for function in functions:
        value = function(value)
    return value


def memstr_to_bytes(text):
    """ Convert a memory text to its value in bytes.
    """
    kilo = 1024
    units = dict(K=kilo, M=kilo ** 2, G=kilo ** 3)
    try:
        size = int(units[text[-1]] * float(text[:-1]))
    except (KeyError, ValueError):
        raise ValueError(
            "Invalid literal for size give: %s (type %s) should be alike '10G', '500M', '50K'."
             % (text, type(text)))
    return size


def get_dataset_path(parsed_url):
    """
    The dataset path is different than the one in `_parsed_dataset_url` for some filesystems.
    For example s3fs expects the bucket name to be included in the path and doesn't support
    paths that start with a `/`
    """
    if parsed_url.scheme.lower() in ['s3', 'gs', 'gcs']:
        return parsed_url.netloc + parsed_url.path
    return parsed_url.path


def _parseTagName(tag, offset):
    """
    parse the packet to get the base tag name
    the offset is so that we can increment the array pointer if need be
    """
    bt = tag
    ind = 0
    try:
        if tag.endswith(']'):
            pos = len(tag) - tag.rindex('[')
            bt = tag[:-pos]
            temp = tag[-pos:]
            ind = temp[1:-1]
            s = ind.split(',')
            if len(s) == 1:
                ind = int(ind)
                newTagName = bt + '[' + str(ind + offset) + ']'
            else:
                ind = []
                for i in range(len(s)):
                    s[i] = int(s[i])
                    ind.append(s[i])
        else:
            pass
        return tag, bt, ind
    except Exception:
        return tag, bt, 0


def _equiv_refresh_interval():
    """Get smallest interval for which the browser should follow redirects.

    Redirection happens if the given interval is smaller than this.
    """
    from .commands import options
    return options.get('equiv_refresh_interval')


def _review(subs, shared):
    """Configure the `doorstop review` subparser."""
    info = 'absolve items of their unreviewed status'
    sub = subs.add_parser('review', description=info.capitalize() + '.',
        help=info, **shared)
    sub.add_argument('label', help="item UID, document prefix, or 'all'")
    group = sub.add_mutually_exclusive_group()
    group.add_argument('-i', '--item', action='store_true', help=
        "indicates the 'label' is an item UID")
    group.add_argument('-d', '--document', action='store_true', help=
        "indicates the 'label' is a document prefix")


def convertFile(inputfile, outputfile):
    """Convert an RML file to an ODT file.
        """


def decompress_amount(x):
    """    Undo the value compression performed by x=compress_amount(n). The input
    x matches one of the following patterns:
        x = n = 0
        x = 1+10*(9*n + d - 1) + e
        x = 1+10*(n - 1) + 9"""
    if not x:
        return 0
    x = x - 1
    x, e = divmod(x, 10)
    n = 0
    if e < 9:
        x, d = divmod(x, 9)
        d = d + 1
        n = x * 10 + d
    else:
        n = x + 1
    return n * 10 ** e


def _truncate_seq_pair(tokens_a, tokens_b, max_length):
    """Truncates a sequence pair in place to the maximum length."""
    while True:
        total_length = len(tokens_a) + len(tokens_b)
        if total_length <= max_length:
            break
        if len(tokens_a) > len(tokens_b):
            tokens_a.pop()
        else:
            tokens_b.pop()


def __len__():
    """returns number of relations in catalog."""


def validate_parameter(parameter, allowed_modes, default_value, basic_type=
    str, heritable=True):
    """
    Validates the parameter and wraps it into a tuple with the
    inheritance option (if parameter is not a tuple already).
    In this case the parameter will become a tuple (parameter, 'inherit'),
    which will indicate that the stream settings will override this parameter.
    In case if the parameter is already a tuple specified as parameter=(value, 'strict'), then the parameter
    will not be overrided.

    Parameters
    ----------
    parameter : object
        The value of the parameter
    allowed_modes : dict or set
        Allowed values for the parameter
    default_value : object
        Default value to substitute if the parameter is None
    basic_type : type
        Type of the parameter.
    heritable : bool
        Whether to check for heretability option.

    Returns
    -------
    out : tuple
        New parameter value wrapped into a tuple.

    """
    if parameter is None:
        parameter = default_value
    if isinstance(parameter, basic_type) and heritable:
        parameter = parameter, 'inherit'
    if isinstance(parameter, list):
        parameter = tuple(parameter)
    if isinstance(parameter, tuple) and heritable:
        if len(parameter) != 2:
            raise ValueError
        if not isinstance(parameter[0], basic_type):
            raise TypeError
        if parameter[0] not in allowed_modes:
            raise ValueError
        if parameter[1] not in {'inherit', 'strict'}:
            raise ValueError
    elif heritable:
        raise NotImplementedError
    return parameter


def CO2LOGSERVER_AUTH_CHECKER(x):
    """
    If authentication is required on a route, this function is called with a
    dictionary of checksum algorithm names mapped to matching salts as created
    in :any:`co2logserver.authentication.authentication` and returns a boolean
    value indicating whether authentication should be granted to this request.
    By default, at least one checksum should be given and all handed checksums
    should match.
    """
    return len(x) and all(x.values())


def get_name(friendly=False):
    """Get name of this resource

    :return: name of this resource
    :rtype: str
    """
    if friendly:
        return 'Check request'
    return 'actionforcecheck'


def OC_calc(TP, TOP, P):
    """
    Calculate OC (Overlap coefficient).

    :param TP: true positive
    :type TP : int
    :param TOP: test outcome positive
    :type TOP : int
    :param P:  condition positive
    :type P : int
    :return: overlap coefficient as float
    """
    try:
        overlap_coef = TP / min(TOP, P)
        return overlap_coef
    except (ZeroDivisionError, TypeError):
        return 'None'


def bake():
    """Bake fluid simulation

    """
    pass


@classmethod
def process_search_query(cls, search_params, regular_term_fields,
    regular_terms_fields, regular_date_fields, post_params, aggs, sort,
    page, limit, **kwds):
    """Common function to generate query, send to elastic and return the results dict.

    search_params: dict
    regular_term_fields: dict
    regular_terms_fields: dict
    regular_date_fields: dict
    post_params: dict
    aggs: dict
    sort: dict
    page: int
    limit: int
    kwds: dict (other params)
    - index_name: string
    - highlight: bool
    - id_key: string
    - render: ['raw', 'select', 'query', 'pager'] (default is map)
    - raw_aggs: if set it return the raw aggs
    - no_source: if set it will deactivate _source
    - fields: str or list (Source filtering) don't support dict like _source
    - raw_search: {'any_search'}, will be appended in the [bool][must]
    - page_len: int for the paginator render

      return dict
    """
    page = int(page)
    if kwds.get('index_name'):
        index_name = kwds.get('index_name')
    else:
        index_name = cls.get_index_name()
    if not search_params:
        search_params = {}
    if not post_params:
        post_params = {}
    ret = {index_name: {}, 'total': 0, 'aggs': {}}
    filters = cls.process_regular_fields(search_params, regular_term_fields,
        regular_terms_fields, regular_date_fields)
    query = cls.process_filters(query={}, filters=filters)
    post_filter = cls.process_regular_fields(post_params,
        regular_term_fields, regular_terms_fields, regular_date_fields)
    query, keyword_query = cls.process_keyword_query_filter(query,
        search_params)
    if kwds.get('raw_search'):
        if not query:
            query = {'bool': {'must': []}}
        query['bool']['must'].append(kwds.get('raw_search'))
    if not query:
        query = {'match_all': {}}
    my_query = {'query': query}
    if aggs:
        my_query['aggregations'] = aggs
    if kwds.get('no_source'):
        my_query['_source'] = False
        kwds['render'] = 'raw'
    elif kwds.get('fields'):
        my_query['_source'] = kwds.get('fields')
    my_query = cls.process_post_filters(post_filter, my_query)
    if sort is None:
        if keyword_query:
            sort = [{'_score': 'desc'}]
        else:
            sort = [{'created_at': 'asc'}, {cls.ID_KEY: 'asc'}]
    if sort not in cls.SKIP_SORT_LIST:
        my_query['sort'] = sort
    _from = page - 1
    if _from < 0:
        _from = 0
    my_query['from'] = _from * limit
    my_query['size'] = limit
    if kwds.get('highlight'):
        my_query['highlight'] = kwds['highlight']
    if cls.DEBUG_QUERY:
        print('\n' + '=' * len('= ELASTIC SEARCH QUERY +' * 5) + '\n' +
            '+ ELASTIC SEARCH QUERY +' * 5 + '\n' + '=' * len(
            '+ ELASTIC SEARCH QUERY =' * 5))
        print('Class name :', cls.__name__, ' index_name', index_name)
        import json
        print(json.dumps(my_query))
    id_key = kwds.get('id_key') or cls.ID_KEY
    if kwds.get('render') == 'query':
        return my_query
    result = cls.search(my_query, myindex=index_name)
    if kwds.get('render') == 'select':
        mapped_result = cls.render_select(result)
    elif kwds.get('render') == 'paginator':
        mapped_result = cls.render_paginator(result, page=page, limit=limit,
            page_len=kwds.get('page_len', 0))
    elif kwds.get('render') == 'raw':
        mapped_result = result
    elif kwds.get('render') == 'pager':
        mapped_result = cls.render_pager(result)
    else:
        mapped_result = cls.render_map(result, id_key=id_key)
    if aggs:
        aggs_result_tmp = result.get('aggregations') or {}
        aggs_result = {}
        if kwds.get('raw_aggs'):
            aggs_result = aggs_result_tmp
        elif aggs_result_tmp:
            from collections import OrderedDict
            aggs_result = {}
            for name in aggs.keys():
                if 'buckets' in result['aggregations'][name]:
                    aggs_field_ordered_dict = OrderedDict()
                    for item in result['aggregations'][name]['buckets']:
                        aggs_field_ordered_dict.update({item['key']: item[
                            'doc_count']})
                    aggs_result[name] = aggs_field_ordered_dict
                elif 'value' in result['aggregations'][name]:
                    aggs_result[name] = result['aggregations'][name]['value']
                else:
                    raise NotImplementedError
        ret[index_name] = mapped_result[0]
        ret['total'] = mapped_result[1]
        ret['aggs'] = aggs_result
    elif kwds.get('render') and kwds.get('render') in ('select', 'raw'):
        ret[index_name] = mapped_result
        if kwds.get('render') == 'raw':
            ret['total'] = mapped_result['hits']['total']
        elif kwds.get('render') == 'select':
            ret['total'] = len(mapped_result)
    else:
        ret[index_name] = mapped_result[0]
        ret['total'] = mapped_result[1]
    return ret


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


@classmethod
def required_climate(cls):
    """
        Returns the climate required by this animal, such as temperate,
        tropocal, artic etc.

        :return:
        """
    return 'unknown'


def _format_check(settings):
    """
    Check the format of a urbanaccess_config object.

    Parameters
    ----------
    settings : dict
        urbanaccess_config as a dictionary
    Returns
    -------
    Nothing
    """
    valid_keys = ['data_folder', 'logs_folder', 'log_file', 'log_console',
        'log_name', 'log_filename', 'gtfs_api']
    for key in settings.keys():
        if key not in valid_keys:
            raise ValueError('{} not found in list of valid configuation keys'
                .format(key))
        if not isinstance(key, str):
            raise ValueError('{} must be a string'.format(key))
        if key == 'log_file' or key == 'log_console':
            if not isinstance(settings[key], bool):
                raise ValueError('{} must be boolean'.format(key))


def seconds_to_hms(input_seconds):
    """Convert seconds to human-readable time."""
    minutes, seconds = divmod(input_seconds, 60)
    hours, minutes = divmod(minutes, 60)
    hours = int(hours)
    minutes = int(minutes)
    seconds = str(int(seconds)).zfill(2)
    return hours, minutes, seconds


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

        :param DeviceApprovalsChangeDesktopPolicyType val:
        :rtype: EventType
        """
    return cls('device_approvals_change_desktop_policy', val)


def _bisect_right(seq, tgt, key_func, lower_search_bound=0,
    upper_search_bound=None):
    """Return the index of the last item in seq such that all e in seq[:index]
    have key_func(e) <= tgt, and all e in seq[index:] have key_func(e) > tgt.

    Thus, seq.insert(index, value) will insert value after the rightmost item
    such that meets the above condition.

    lower_search_bound and upper_search_bound bound the slice to be searched.

    Assumes that seq is already sorted.
    """
    if lower_search_bound < 0:
        raise ValueError('lower_search_bound must be non-negative')
    if upper_search_bound is None:
        upper_search_bound = len(seq)
    while lower_search_bound < upper_search_bound:
        midpoint_index = (lower_search_bound + upper_search_bound) // 2
        if tgt < key_func(seq[midpoint_index]):
            upper_search_bound = midpoint_index
        else:
            lower_search_bound = midpoint_index + 1
    return lower_search_bound


def paths_clear(only_selected: bool=False):
    """Clear path caches for all bones, hold Shift key for selected bones only

    :param only_selected: Only Selected, Only clear paths from selected bones
    :type only_selected: bool
    """
    pass


def asint(text):
    """
    Safely converts a string to an integer, returning ``None`` if the string is ``None``.

    :type text: str
    :rtype: int

    """
    if text is not None:
        return int(text)


def get_root_package_name(name: str) ->str:
    """Get the root package name of a nested module one.

    Args:
      name (str): Full name of the module

    Returns:
      str: The root package name

    Examples:
      >>> get_root_package_name('weather.nested.file')
      'weather'
      >>> get_root_package_name('weather')
      'weather'

    """
    return name.split('.')[0] if name else name


def _match_message(key, value, event):
    """Return true if `key` and `value` exist within the given message."""
    if key == 'datapath_id' and value is None:
        return True
    val = str(value).upper()
    msg = event['msg']
    if key in msg:
        return str(msg[key]).upper() == val
    pkt = msg.get('pkt')
    if pkt is not None and key in pkt:
        return str(pkt[key]).upper() == val
    return False


def display_removed_ruleset(name):
    """display function for removing a ruleset"""
    print('Removed ruleset "%s"' % name)


def getpeaks_fromfit2d(filename):
    """
    read peaks list created by fit2d peak search

    #TODO: to remove function to read old data format, not used any longer
    """
    frou = open(filename, 'r')
    alllines = frou.readlines()
    frou.close()
    peaklist = alllines[1:]
    print(' %d peaks in %s' % (len(peaklist), filename))
    outputfilename = filename[:-6] + '.pik'
    fric = open(outputfilename, 'w')
    for line in peaklist:
        fric.write(line)
    fric.close()
    print('X,Y, int list in %s' % outputfilename)
    return len(peaklist)


def get_settings_config(session, return_type=None, **kwargs):
    """
    Get VPSAOS setting configuration

    :type session: zadarapy.session.Session
    :param session: A valid zadarapy.session.Session object.  Required.

    :type return_type: str
    :param return_type: If this is set to the string 'json', this function
        will return a JSON string.  Otherwise, it will return a Python
        dictionary.  Optional (will return a Python dictionary by default).

    :rtype: dict, str
    :returns: A dictionary or JSON data set as a string depending on
        return_type parameter.
    """
    path = '/api/settings_config.json'
    return session.get_api(path=path, return_type=return_type, **kwargs)


def get_file_extension(filename):
    """
    Return extension of given file name in lower case.
    """
    return filename.split('.')[-1].lower()


def rollingchecksum(removed, new, a, b, blocksize=4096):
    """
    Generates a new weak checksum when supplied with the internal state
    of the checksum calculation for the previous window, the removed
    byte, and the added byte.
    """
    a -= removed - new
    b -= removed * blocksize - a
    return b << 16 | a, a, b


def to_bytes(size, power=1024, sep=' '):
    """Converts human size to raw bytes."""
    if not size:
        return 0
    size, suffix = size.split(sep, 1)
    suffix = suffix[0]
    try:
        factor = {'K': power, 'M': power ** 2, 'G': power ** 3, 'T': power **
            4, 'P': power ** 5}[suffix]
    except KeyError:
        factor = 1
    return int(float(size) * factor)


def setpnumber_function(postnrid, poststedid):
    """Event handler to load poststed from postnr, through an ajax call."""
    return (
        """
        var setpnumber = function () {
          var jdoc = loadJSONDoc('http://cache.norsktest.no/ajax/poststed/' + $('%s').value + '/');
          jdoc.addCallback(function (result) {
             if (result != "")
                $('%s').value = result;
          });
        }"""
         % (postnrid, poststedid))


def get_relative_url(url):
    """
    Returns the relative URL from a URL. For example:

    'http://web.net' -> ''
    'http://web.net/' -> ''
    'http://web.net/1222' -> '/1222'
    'http://web.net/wsadas/asd' -> '/wsadas/asd'

    It will never return a trailing "/".

    @param url: A url to transform
    @type url: str

    @return: relative URL
    """
    stripped_site_url = url.replace('://', '')
    baseurl = '/' + '/'.join(stripped_site_url.split('/')[1:])
    if baseurl[-1] == '/':
        return baseurl[:-1]
    else:
        return baseurl


def penalty_function(nearness, buff=10 ** -6):
    """
    weak regime --> far from constraint violation
    strong regime --> close to but not doing constraint violation
    negative regime --> already in violation of constraints

    Penalty function must be continuous!
    """
    if nearness > 0:
        return 0
    else:
        return 10 ** 64 * (1 - nearness)


@staticmethod
def lazy_advance(old_normal, old_lazy):
    """
        This method takes int "old_lazy" (which corresponds to bit vector
        "old_normal"), and changes it to the next lazy int, "new_lazy" (
        which corresponds to "new_normal").

        example:

        lazy sequence: 000, 001, 011, 010, 110, 111, 101, 100

        old_lazy = 011
        old_normal = 2 = 010

        new_normal = 3 = 011
        mask = (new_normal & ~old_normal) = 011 & 101 = 001
        new_lazy = new_normal ^ mask = 011 ^ 001 = 010

        Parameters
        ----------
        old_normal : int
        old_lazy : int

        Returns
        -------
        int, int

        """
    new_normal = old_normal + 1
    new_lazy = old_lazy ^ new_normal & ~(new_normal - 1)
    return new_normal, new_lazy


def apply(df, remove_common=False, include_activity_timest_in_key=False):
    """
    Dataframe to grouped stream

    Parameters
    -------------
    df
        Dataframe

    Returns
    -------------
    grouped_stream
        Grouped stream of events
    """
    stream = df.to_dict('r')
    grouped_stream = {}
    i = 0
    while i < len(stream):
        keys = list(stream[i].keys())
        for key in keys:
            if str(stream[i][key]) == 'nan' or str(stream[i][key]) == 'None':
                del stream[i][key]
        if 'event_id' in stream[i] and 'event_activity' in stream[i
            ] and 'event_timestamp' in stream[i]:
            event_id = stream[i]['event_id']
            event_activity = stream[i]['event_activity']
            event_timestamp = stream[i]['event_timestamp']
            if include_activity_timest_in_key:
                if (event_id, event_activity, event_timestamp
                    ) not in grouped_stream:
                    grouped_stream[event_id, event_activity, event_timestamp
                        ] = []
            elif event_id not in grouped_stream:
                grouped_stream[event_id] = []
            if remove_common:
                del stream[i]['event_id']
                del stream[i]['event_activity']
                if 'event_timestamp' in stream[i]:
                    del stream[i]['event_timestamp']
            if include_activity_timest_in_key:
                grouped_stream[event_id, event_activity, event_timestamp
                    ].append(stream[i])
            else:
                grouped_stream[event_id].append(stream[i])
        i = i + 1
    return grouped_stream


def welcommessage(version):
    """Return welcome message."""
    message = ('Kaidoku - player, solver and creater of sudoku puzzles.\n' +
        """          https://sekika.github.io/kaidoku/
""" +
        'Type h for help, c for showing a problem, q for quit.')
    return message


def __new__(cls, colid, name, *args, **keywargs):
    """Initialize the String object with the given column name. Ignore the
        column identifier.

        Parameters
        ----------
        colid: int
            Unique column identifier
        name: string
            Column name
        """
    return str.__new__(cls, str(name))


def decode_response(client_message, to_object=None):
    """ Decode response from client message"""
    parameters = dict(response=None)
    if not client_message.read_bool():
        parameters['response'] = to_object(client_message.read_data())
    return parameters


def float_range(A, L=None, D=None):
    """float_range(stop) -> float_range object
    float_range(start, stop[, step]) -> float range object

    Return an object that produces a sequence of floating point numbers from
    start (inclusive) to stop (exclusive) by step.  float_range(i, j) produces
    i, i+1, i+2, ..., j-1.  start defaults to 0, and stop is omitted!
    float_range(4) produces 0, 1, 2, 3.  These are exactly the valid indices for a
    list of 4 elements.  When step is given, it specifies the increment (or
    decrement).
    """
    if L == None:
        L = A + 0.0
        A = 0.0
    if D == None:
        D = 1.0
    while True:
        if D > 0 and A >= L:
            break
        elif D < 0 and A <= L:
            break
        yield A
        A = A + D


def resize_by_factor(im, factor):
    """
    Resizes the image according to a factor. The image is pre-filtered
    with a Gaussian and then resampled with bilinear interpolation.

    This function uses scikit-image and essentially combines its
    `pyramid_reduce` with `pyramid_expand` into one function.

    Returns the same object if factor is 1, not a copy.

    Parameters
    ----------
    im : ndarray, ndim=2 or 3
        Image. Either 2D or 3D with 3 or 4 channels.
    factor : float
        Resize factor, e.g. a factor of 0.5 will halve both sides.
    """
    from skimage.transform.pyramids import pyramid_reduce, pyramid_expand
    if factor < 1:
        return pyramid_reduce(im, downscale=1 / factor)
    elif factor > 1:
        return pyramid_expand(im, upscale=factor)
    else:
        return im


def helpline(obj):
    """
    Yield an object's first docstring line, or an empty string.

    .. versionadded:: 1.0
    """
    docstring = obj.__doc__
    if not docstring or docstring == type(obj).__doc__:
        return None
    return docstring.lstrip().splitlines()[0]


def ensure_nest_alts_are_valid_alts(nest_spec, list_elements, all_ids):
    """
    Ensures that the alternative id's in `nest_spec` are all in the universal
    choice set for this dataset. Raises a helpful ValueError if they are not.

    Parameters
    ----------
    nest_spec : OrderedDict, or None, optional.
        Keys are strings that define the name of the nests. Values are lists of
        alternative ids, denoting which alternatives belong to which nests.
        Each alternative id must only be associated with a single nest!
        Default == None.
    list_elements : list of ints.
        Each element should correspond to one of the alternatives identified as
        belonging to a nest.
    all_ids : list of ints.
        Each element should correspond to one of the alternatives that is
        present in the universal choice set for this model.

    Returns
    -------
    None.
    """
    invalid_alt_ids = []
    for x in list_elements:
        if x not in all_ids:
            invalid_alt_ids.append(x)
    if invalid_alt_ids != []:
        msg = 'The following elements are not in df[alt_id_col]: {}'
        raise ValueError(msg.format(invalid_alt_ids))
    return None


def replace_template_path(path):
    """ replace original template path with new dict """
    segments = path.split('.')
    module = '.'.join(segments[0:-1])
    name = segments[-1]
    if module == 'ipypublish.html.ipypublish':
        return {'module': 'ipypublish.templates.segments', 'file':
            'ipy-{0}.html-tplx.json'.format(name)}
    elif module == 'ipypublish.html.standard':
        return {'module': 'ipypublish.templates.segments', 'file':
            'std-{0}.html-tplx.json'.format(name)}
    elif module == 'ipypublish.latex.standard':
        return {'module': 'ipypublish.templates.segments', 'file':
            'std-{0}.latex-tpl.json'.format(name)}
    elif module == 'ipypublish.latex.ipypublish':
        return {'module': 'ipypublish.templates.segments', 'file':
            'ipy-{0}.latex-tpl.json'.format(name)}
    else:
        print('Warning: unknown template path: {}'.format(path))
        return {'module': module, 'file': '{0}.json'.format(name)}


@classmethod
def from_fileobj(klass, fileobj, endianness=None, check=True):
    """ Return read structure with given or guessed endiancode

        Parameters
        ----------
        fileobj : file-like object
           Needs to implement ``read`` method
        endianness : None or endian code, optional
           Code specifying endianness of read data

        Returns
        -------
        wstr : WrapStruct object
           WrapStruct object initialized from data in fileobj
        """
    raw_str = fileobj.read(klass.template_dtype.itemsize)
    return klass(raw_str, endianness, check)


@classmethod
def is_compatible(cls, value):
    """
        Returns ``True`` if this model should be used to store ``value``.

        Checks if ``value`` is an instance of ``value_type``. Override this
        method if you need more advanced behaviour. For example, to distinguish
        between single and multi-line text.
        """
    if not hasattr(cls, 'value_type'):
        raise NotImplementedError(
            'You must define a `value_type` attribute or override the `is_compatible()` method on `SettingValueModel` subclasses.'
            )
    return isinstance(value, cls.value_type)


@classmethod
def from_string(cls, string):
    """
        Converts string "white" or "black" into
        corresponding color

        :type: string: str
        :rtype: Color
        """
    return cls(cls._color_dict[string])


def read_last_line(fh, offset=256):
    """ Read last line from a seekable file. Start reading
    from buff before end of file, and double backwards seek
    until line break is found. If reached beginning of file
    (no lines), just return whole file
    """
    fh.seek(0, 2)
    size = fh.tell()
    while offset < size:
        fh.seek(-offset, 2)
        lines = fh.readlines()
        if len(lines) > 1:
            return lines[-1]
        offset *= 2
    fh.seek(0, 0)
    return fh.readlines()[-1]


def get_filename_and_extension(path):
    """
    Returns a filename and the file extension. The filename cna
    be either a simlpe filename or a full path.

    :param path:
    :return:
    """
    filename = path.split('.')[:-1]
    extension = path.split('.')[-1]
    return filename, extension


@classmethod
def error_payload(cls, message, code, id_):
    """JSON v2 error payload.  result is not present."""
    return {'jsonrpc': '2.0', 'id': id_, 'error': {'message': message,
        'code': code}}


def permute(x, indices=(0, 0), rows=0, cols=1):
    """Swap two columns and (or) two rows of 'x', whose indices are specified
    in indices=[i,j].
    Note: permutations are done in-place. You'll lose your original matrix"""
    [i, j] = indices
    if rows:
        x[(i), :], x[(j), :] = x[(j), :], x[(i), :] + 0
    if cols:
        x[:, (i)], x[:, (j)] = x[:, (j)], x[:, (i)] + 0


def p_argument_string(p):
    """argument : string"""
    p[0] = [p[1]]


def weeks_to_seconds(weeks):
    """Convert weeks to seconds"""
    return int(weeks * 604800.0)


@staticmethod
def dmql(query):
    """Client supplied raw DMQL, ensure quote wrap."""
    if isinstance(query, dict):
        raise ValueError(
            'You supplied a dictionary to the dmql_query parameter, but a string is required. Did you mean to pass this to the search_filter parameter? '
            )
    if len(query) > 0 and query != '*' and query[0] != '(' and query[-1
        ] != ')':
        query = '({})'.format(query)
    return query


def iter_fragments(string, is_match=None):
    """Yield fragments of `string` that are of a desired form as dictated by `is_match`

    Parameters
    ----------
    string: String
        A string containing fragments, which, when passed to `is_match` return True
    is_match: Callable, or None, default=lambda _: False
        Callable given a single string input that is a fragment of `string`, starting at any index.
        Expected to return boolean, which is truthy when the given fragment is of the desired form

    Yields
    ------
    String
        Fragment of `string` starting at an index and continuing to the end, for which `is_match`
        returned a truthy value
    Int
        The index at which the aforementioned string fragment begins"""
    is_match = is_match or (lambda _: False)
    for i in range(len(string)):
        if is_match(string[i:]):
            yield string[i:], i


def arcsinh(data=None, out=None, name=None, **kwargs):
    """Returns the element-wise inverse hyperbolic sine of the input array, \\
    computed element-wise.

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

       - arcsinh(default) = default
       - arcsinh(row_sparse) = row_sparse
       - arcsinh(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L436

    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,


@classmethod
def get_datasource_url(cls, ds_name):
    """Get a connection URL for the datasource"""
    return 'sqlite:///%s' % cls.get_datasource_filename(ds_name)


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 eval_callbacks(callbacks, result):
    """Evaluate list of callbacks on result.

    The return values of the `callbacks` are ORed together to give the
    overall decision on whether or not the optimization procedure should
    continue.

    Parameters
    ----------
    callbacks : list of callables
        Callbacks to evaluate.

    result : `OptimizeResult`, scipy object
        Optimization result object to be stored.

    Returns
    -------
    decision : bool
        Decision of the callbacks whether or not to keep optimizing
    """
    stop = False
    if callbacks:
        for c in callbacks:
            decision = c(result)
            if decision is not None:
                stop = stop or decision
    return stop


def set_logger(l):
    """sets the current logger."""
    global logger
    logger = l


@staticmethod
def _questionmark_handler(date_pointer):
    """ Handles Cron Syntax parsing for `?` values. """
    parsed_date = date_pointer
    unit_boundary_reached = True
    return parsed_date, unit_boundary_reached


def print_footnotes(outputfile):
    """Add footnotes to the output file.

    Args:
        outputfile (file): The file to which the footnotes will be written.
    """
    outputfile.write(
        """Footnotes:

STATISTICS Section Legend:
N: Number of residues
Min: Minimum B-factor value
Max: Maximum B-factor value
Mean: Mean B-factor value
Mode: Mode B-factor value
Median: Median B-factor value
STDDev: Standard Deviation of the B-factor values
"""
        )
    outputfile.write(
        """
RMSF Plane Visualization:
Download plane.py file from https://pymolwiki.org/index.php/Plane_Wizard and place it in the PyMol working directory if the RMSF plane needs to be visualized.
"""
        )
    return True


@classmethod
def fromNameStr(cls, engine, name_str, type_str=None):
    """Create field object using stringified name"""
    return cls(engine, engine.getNameList(name_str)[1:], type_str=type_str)


def get_schema_filename(xml):
    """Return the filename of the schema file that corresponds to the given XML object.

    :param xml: the pre-parsed XML object
    :return: the XSD filename
    """
    xml_schema_location_key = (
        '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation')
    element_root = xml.getroot()
    if element_root is None:
        return None
    element_schema_location = element_root.get(xml_schema_location_key)
    if element_schema_location is None:
        return None
    schema_location = element_schema_location.split()[1]
    schema_filename = schema_location.rpartition('/')[2]
    return schema_filename


def callable(obj):
    """Return whether the object is callable (i.e., some kind of function).
       Note that classes are callable, as are instances with a __call__()
       method.
    """
    return hasattr(obj, '__call__')


def count_lines(filename):
    """ Counts the number of lines in the file.
	"""
    with open(filename, 'r') as fh:
        i = 0
        for i, _ in enumerate(fh, 1):
            pass
        return i


def theta_H_K_HMW84(T, P):
    """c-c': hydrogen potassium [HMW84]."""
    theta = 0.005
    valid = T == 298.15
    return theta, valid