def drawv(f, data, value, geometry):
    """
    y = drawv(f, data, value, geometry)

    Superpose points, rectangles and lines on an image.

    `drawv` creates the image `y` by a superposition of points,
    rectangles and lines of gray-level `value` on the image `f`. The
    parameters for each geometrical primitive are defined by each line
    in the `data` parameter. For points, they are represented by 2-D
    coordinates.  For lines, they are drawn with the same convention
    used by points, with a straight line connecting them in the order
    given by the data matrix. For rectangles and filled rectangles,
    data should be an array of 2 x 2D points.

    Parameters
    ----------
    f :        Gray-scale (uint8 or uint16) or binary image.
    data :     Vector of coordinates.
    value :    Gray value(s) for drawing.
                  If it's a single value, then it will be used for all objects,
                  otherwise, it should be an array of same length as `data`.
    geometry :  { 'point', 'line', 'rect', 'frect' (filled rectangles)}

    Returns
    -------
    y : Image of same type as `f`
    """
    """
        - Examples
            #
            #   example 1
            #
            f=to_uint8(zeros((3,5)))
            pcoords=to_uint16([[0,2,4],
                            [0,0,2]])
            pvalue=to_uint16([1,2,3])
            print drawv(f,pcoords,pvalue,'point')
            print drawv(f,pcoords,pvalue,'line')
            rectcoords=to_uint16([[0],
                               [0],
                               [3],
                               [2]])
            print drawv(f,rectcoords, to_uint16(5), 'rect')
            #
            #   example 2
            #
            f=readgray('blob3.tif')
            pc=blob(label(f),'centroid','data')
            lines=drawv(intersec(f,0),transpose(pc),to_uint8(1),'line')
            show(f,lines)
    """
    from numpy import array, newaxis, zeros, put, ravel, arange, floor, int32, zeros_like
    import itertools
    geometry = geometry.lower()
    if len(f.shape) == 1:
        f = f[(newaxis), :]
    value = array(value)
    if value.shape == ():
        value = itertools.repeat(value)
    else:
        assert len(data) == len(value
            ) or geometry == 'line', 'pymorph.drawv: Length of data does not match length of values'
        assert len(data) == len(value
            ) + 1 or geometry != 'line', 'pymorph.drawv: Length of data does not match length of values -1 (for line option)'
    res = zeros_like(f)
    if geometry == 'point':
        for (y, x), val in zip(data, value):
            res[y, x] = val
    elif geometry == 'line':
        for val, (x0, y0), (x1, y1) in itertools.izip(value, data[:-1],
            data[1:]):
            steep = abs(y1 - y0) > abs(x1 - x0)
            if steep:
                y0, x0 = x0, y0
                y1, x1 = x1, y1
            if x0 > x1:
                x0, x1 = x1, x0
                y0, y1 = y1, y0
            deltax = x1 - x0
            deltay = abs(y1 - y0)
            error = deltax // 2
            y = y0
            ystep = 1 if y0 < y1 else -1
            for x in range(x0, x1 + 1):
                if steep:
                    res[y, x] = val
                else:
                    res[x, y] = val
                error -= deltay
                if error < 0:
                    y += ystep
                    error += deltax
    elif geometry in ('frect', 'rect'):
        for (y0, x0, y1, x1), val in zip(data, value):
            assert y1 >= y0, 'pymorph.drawv: bad arguments'
            assert x1 >= x0, 'pymorph.drawv: bad arguments'
            if geometry == 'rect':
                res[y0:y1 + 1, (x0)] = val
                res[y0:y1 + 1, (x1)] = val
                res[(y0), x0:x1 + 1] = val
                res[(y1), x0:x1 + 1] = val
            else:
                res[y0:y1 + 1, x0:x1 + 1] = val
    else:
        assert False, "pymorph.drawv: geometry should be 'point', 'line', 'rect', or 'frect'."
    return res


def is_int(var):
    """
    is this an integer (ie, not a float)?
    """
    return isinstance(var, int)


def make_list(option, opt_str, value, parser):
    """
    This function is used when certain commandline options are used when running turboSETI (-c). It is used to convert
    the inputted option, which should be a comma separated string, into a list. Stores this in the inputted OptionParser
    object's values field, under the inputted option. This is only called for the coarse_chans option currently,
    essentially to parse the inputted coarse channels into a usable format.
    :param option:      Option,         whose value should be set to the new list
    :param opt_str:     string,         (unused) command line option inputted when main was run
    :param value:       string,         in comma separated format which must be converted to list format
    :param parser:      OptionParser,   instance whose option we are setting to the new list
    :return: void
    """
    v = value.replace('[', '').replace(']', '').split(',')
    v = list(map(int, v))
    setattr(parser.values, option.dest, v)


def _common_parser():
    """Returns a parser with common command-line options for all the scripts
    in the matdb suite.
    """
    import argparse
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('--examples', action='store_true', help=
        'See detailed help and examples for this script.')
    parser.add_argument('--verbose', default=0, type=int, help=
        'See verbose output as the script runs.')
    parser.add_argument('--debug', action='store_true', help=
        'Print verbose calculation information for debugging.')
    return parser


def get_location(http_info):
    """Extract the redirect URL from a pysaml2 http_info object"""
    assert 'headers' in http_info
    headers = http_info['headers']
    assert len(headers) == 1
    header_name, header_value = headers[0]
    assert header_name == 'Location'
    return header_value


def is_hex(s):
    """

    Explicit name, used to detect errors in to be sent hashes

    """
    try:
        int(s, 16)
        return True
    except ValueError:
        return False


def dow():
    """Return the integer day of the week, where sunday is 0"""


def get_model_attr(instance, attr):
    """Example usage: get_model_attr(instance, 'category__slug')"""
    for field in attr.split('__'):
        instance = getattr(instance, field)
    return instance


def split_irc_line(s):
    """Breaks a message from an IRC server into its prefix, command, and arguments.
    """
    prefix = ''
    trailing = []
    if not s:
        pass
    if s[0] == ':':
        prefix, s = s[1:].split(' ', 1)
    if s.find(' :') != -1:
        s, trailing = s.split(' :', 1)
        args = s.split()
        args.append(trailing)
    else:
        args = s.split()
    command = args.pop(0)
    return prefix, command, args


def strip(string, suffix):
    """Strip a suffix from a string if it exists:

        >>> strip('go bar a foobar', 'bar')
        'go bar a foo'
        >>> strip('go bar a foobar', 'baz')
        'go bar a foobar'
        >>> strip('allofit', 'allofit')
        ''

    """
    if string.endswith(suffix):
        string = string[:-len(suffix)]
    return string


@classmethod
def crash(cls):
    """Crashes browser on the main thread.
        """
    return cls.build_send_payload('crash', {}), None


@staticmethod
def setup_subparser(parser, cmd=None):
    """
        Set up a subparser for 'config'
        """
    parser.add_argument('key', nargs='?', help=
        'Configuration key to query or set')
    parser.add_argument('value', nargs='?', help='New value')
    parser.add_argument('-c', '--config-file', help=
        'Specify the config file to update')
    parser.add_argument('-o', '--config-only', action='store_true', help=
        'If specified, only consider options from this one file. Default: Consider all config options'
        )
    parser.add_argument('-P', '--package', help=
        'If specified, set options for this package instead of the global configs'
        )
    parser.add_argument('-C', '--category', help=
        'If specified, set options for this category instead of the global configs'
        )
    parser.add_argument('-E', '--env', action='store_true', default=None,
        help=
        'If specified, set an environment variable instead of the global configs'
        )


@classmethod
def write_bin(cls, context: str) ->'IoTransferEventArgs':
    """Creates new IoTransferEventArgs of read binary data

		:param context: SCPI command. It is truncated to maximum of 100 characters.
		:return: IoTransferEventArgs object of a write binary data operation."""
    obj = cls(False, False, None, context.rstrip())
    obj.binary = True
    return obj


def clear_username(string):
    """ because mongo usernames have special requirements """
    string = string.strip()
    if string.startswith('$'):
        string = string[1:]
    try:
        string = string[:string.index('@')]
    except ValueError:
        pass
    return string.replace('.', '')


def best_time(timestamp):
    """Specify a date to send the push at the best time per-device.
    Only YYYY_MM_DD are needed. Hour/minute/second information is discarded.

    :param timestamp: A ``datetime.datetime object.
    """
    return {'best_time': {'send_date': timestamp.strftime('%Y-%m-%d')}}


@classmethod
def getsizes(cls, k, min, defaults):
    """Helper function to provide sizes for splitter elements."""
    try:
        elem = len(defaults)
        for i in range(elem):
            if cls.conf['dims'][k][i] < min[i]:
                cls.conf['dims'][k] = min[i]
    except Exception:
        cls.conf['dims'][k] = defaults
    return cls.conf['dims'][k]


def find_end(s):
    """
    Given a string, s, find the position of the last character which is not a gap "-" hyphen.

    :param s: String to search for the last non gap character in

    :return: position of last non-gap character
    """
    import re
    s = s[::-1]
    s = s.upper()
    end = len(s) - re.search('[^-]', s).start()
    return end


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 authGSSServerUserName(context):
    """
    Get the user name of the principal trying to authenticate to the server.
    This method must only be called after authGSSServerStep returns a complete or continue response code.

    @param context: the context object returned from authGSSServerInit.
    @return: a string containing the user name.
    """


def HT_TRENDMODE(df, price='Close'):
    """
    Hilbert Transform - Trend vs Cycle Mode
    """


def multigraph_paths(G, source, cutoff=None):
    """
    For a networkx MultiDiGraph, find all paths from a source node
    to leaf nodes. This function returns edge instance numbers
    in addition to nodes, unlike networkx.all_simple_paths.

    Parameters
    ---------------
    G : networkx.MultiDiGraph
      Graph to evaluate
    source : hashable
      Node to start traversal at
    cutoff : int
      Number of nodes to visit
      If None will visit all nodes

    Returns
    ----------
    traversals : (n,) list of [(node, edge instance index), ] paths
      Traversals of the multigraph
    """
    if cutoff is None:
        cutoff = len(G.edges()) * len(G.nodes()) + 1
    current = [(source, 0)]
    queue = []
    traversals = []
    for i in range(cutoff):
        current_node = current[-1][0]
        child = G[current_node]
        if len(child) == 0:
            traversals.append(current)
            if len(queue) == 0:
                break
            current = queue.pop()
        else:
            start = True
            for node in child.keys():
                for instance in child[node].keys():
                    if start:
                        current.append((node, instance))
                        start = False
                    else:
                        queue.append(current[:-1] + [(node, instance)])
    return traversals


def is_positive_int_compatible(val):
    """
        True if val can be converted to int which would
        be posisitve
        """
    try:
        i = int(val)
        return i > 0
    except ValueError:
        return False


def error_red(err_str):
    """
    for printing errors in red in pycharm.
    :param err_str:
    :return:
    """
    CRED = '\x1b[91m'
    CEND = '\x1b[0m'
    return CRED + err_str + CEND


def flash(msg, queue='', allow_duplicate=True):
    """ Push a flash message onto the end of the flash queue represented
        by ``queue``.  An alternate flash message queue can used by passing
        an optional ``queue``, which must be a string.  If
        ``allow_duplicate`` is false, if the ``msg`` already exists in the
        queue, it will not be re-added."""


def beta_from_As(As):
    """
    Find beta given the stopband attenuation (in dB)

    Parameters
    ----------
    As : float
        Stopband attenuation in dB

    Returns
    -------
    beta : float
        The computed beta

    This is a standard formula from Kaiser."""
    if As > 50:
        return 0.1102 * (As - 8.7)
    elif As > 21:
        return 0.5842 * (As - 21) ** 0.4 + 0.07886 * (As - 21)
    else:
        return 0.0


def _depgrep_parens_action(_s, _l, tokens):
    """
    Builds a lambda function representing a predicate on a tree node
    from a parenthetical notation.
    """
    assert len(tokens) == 3
    assert tokens[0] == '('
    assert tokens[2] == ')'
    return tokens[1]


def add_keys(apps, schema_editor):
    """
    We can't import the Post model directly as it may be a newer
    version than this migration expects. We use the historical version.
    """
    Setting = apps.get_model('settings', 'Setting')
    key = ''
    try:
        key = 'WALLET_CHARGING_MESSAGE'
        Setting.objects.get(key=key)
    except Exception:
        Setting.objects.create(title='پیام شارژ کیف پول', key=key, value=
            'کیف پول شما شارژ ندارد. لطفا ابتدا کیف پول خود را شارژ بفرمایید.',
            value_type='s', is_show=False, is_variable_in_home=False)


def parameters_ui(layout, params):
    """ Create the ui for the rig parameters.
    """
    r = layout.row()
    r.label(text='Bend rotation axis:')
    r.prop(params, 'primary_rotation_axis', text='')


def zigzag2(i, curr=0.45, upper=0.48, lower=0.13):
    """
    Generalized version of the zig-zag function.
    Returns points oscillating between two bounds
    linearly.
    """
    if abs(i) <= upper - curr:
        return curr + i
    else:
        i = i - (upper - curr)
        i = i % (2 * (upper - lower))
        if i < upper - lower:
            return upper - i
        else:
            return 2 * lower - upper + i


def list_of_installed_packages():
    """
    calls ``pip list`` to retrieve the list of packages

    .. faqref::
        :tag: module
        :title: Obtenir des informations sur les packages installés

        Le module `pip <https://pip.pypa.io/en/stable/>`_ retourne des informations
        sur n'importe quel module installé, sa version, sa license ::

            pip show pandas

        On peut également l'obtenir depuis l'interpréteur python ::

            import pip
            pip.main(["show", "pandas"])

        Exemple ::

            Name: pandas
            Version: 0.16.0
            Summary: Powerful data structures for data analysis, time series,and statistics
            Home-page: http://pandas.pydata.org
            Author: The PyData Development Team
            Author-email: pydata@googlegroups.com
            License: BSD
            Location: c:\\python35_x64\\lib\\site-packages
            Requires: python-dateutil, pytz, numpy

        On utilise également ``pip freeze`` pour répliquer l'environnement
        dans lequel on a développé un programme. `pip freeze <https://pip.pypa.io/en/latest/reference/pip_freeze.html>`_
        produit la liste des modules avec la version utilisée ::

            docutils==0.11
            Jinja2==2.7.2
            MarkupSafe==0.19
            Pygments==1.6
            Sphinx==1.2.2

        Ce qu'on utilise pour répliquer l'environnement de la manière suivante ::

            pip freeze > requirements.txt
            pip install -r requirements.txt

        Cette façon de faire fonctionne très bien sous Linux mais n'est pas encore
        opérationnelle sous Windows à moins d'installer le compilateur C++ utilisée pour compiler
        Python.
    """
    from pyquickhelper.pycode.pip_helper import get_packages_list
    return get_packages_list()


def convertbits(data, frombits, tobits, pad=True):
    """General power-of-2 base conversion."""
    acc = 0
    bits = 0
    ret = []
    maxv = (1 << tobits) - 1
    max_acc = (1 << frombits + tobits - 1) - 1
    for value in data:
        if value < 0 or value >> frombits:
            return None
        acc = (acc << frombits | value) & max_acc
        bits += frombits
        while bits >= tobits:
            bits -= tobits
            ret.append(acc >> bits & maxv)
    if pad:
        if bits:
            ret.append(acc << tobits - bits & maxv)
    elif bits >= frombits or acc << tobits - bits & maxv:
        return None
    return ret


def add_client_order_item(id):
    """add client order item identified by *id*."""


def pop_post(user_email, postid):
    """
        removes the post with post index 'postid'
        from the list of posts from 'user_email'
        """


def process_constraints(data, constraint_fields):
    """
    Callback to move constrained fields from incoming data into a 'constraints'
    key.

    :param data:
        Incoming argument dict

    :param constraint_fields:
        Constrained fields to move into 'constraints' dict
    """
    objects = data if isinstance(data, list) else [data]
    if data['pattern'] is None:
        data['pattern'] = ''
    for obj in objects:
        constraints = {}
        for c_field in constraint_fields:
            try:
                c_value = obj.pop(c_field)
            except KeyError:
                continue
            else:
                if c_value is None:
                    c_value = False
                constraints[c_field] = c_value
        obj['constraints'] = constraints
    return data


def TSKVolumeGetBytesPerSector(tsk_volume):
    """Retrieves the number of bytes per sector from a TSK volume object.

  Args:
    tsk_volume (pytsk3.Volume_Info): TSK volume information.

  Returns:
    int: number of bytes per sector or 512 by default.
  """
    if hasattr(tsk_volume, 'info') and tsk_volume.info is not None:
        block_size = getattr(tsk_volume.info, 'block_size', 512)
    else:
        block_size = 512
    return block_size


@classmethod
def fullname(cls, sCanonical):
    """Translate a canonical name into a full name.
           """
    raise NotImplementedError


def get_path(D, path):
    """Get a path from a dictionary

    :param dict D: a dictionary
    :param list path: an iterable of hashables
    :return: the item at the path from the dictionary
    """
    assert isinstance(D, dict)
    try:
        assert map(hash, path)
    except TypeError:
        raise TypeError(u'path should be an iterable of hashables')
    item = D
    for p in path:
        try:
            item = item[p]
        except KeyError:
            item = None
            break
    return item


def cm_to_EMU(value):
    """1 cm = 360000 EMUs"""
    return int(value * 360000)


def keyframe_jump(next: bool=True):
    """Jump to previous/next keyframe

    :param next: Next Keyframe
    :type next: bool
    """
    pass


def as_attr(s):
    """ Replaces dashes with underscores, so `s` can be a python attribute :) """
    return s.replace('-', '_')


def getHeader(name, default=None):
    """Gets a header value

        Returns the value associated with a HTTP return header, or
        'default' if no such header has been set in the response
        yet.
        """


def document_iters_to_multipart_byteranges(ranges_iter, boundary):
    """
    Takes an iterator of range iters and yields a multipart/byteranges MIME
    document suitable for sending as the body of a multi-range 206 response.

    See document_iters_to_http_response_body for parameter descriptions.
    """
    if not isinstance(boundary, bytes):
        boundary = boundary.encode('ascii')
    divider = b'--' + boundary + b'\r\n'
    terminator = b'--' + boundary + b'--'
    for range_spec in ranges_iter:
        start_byte = range_spec['start_byte']
        end_byte = range_spec['end_byte']
        entity_length = range_spec.get('entity_length', '*')
        content_type = range_spec['content_type']
        part_iter = range_spec['part_iter']
        if not isinstance(content_type, bytes):
            content_type = str(content_type).encode('utf-8')
        if not isinstance(entity_length, bytes):
            entity_length = str(entity_length).encode('utf-8')
        part_header = b''.join((divider, b'Content-Type: ', content_type,
            b'\r\n', b'Content-Range: ', b'bytes %d-%d/%s\r\n' % (
            start_byte, end_byte, entity_length), b'\r\n'))
        yield part_header
        for chunk in part_iter:
            yield chunk
        yield b'\r\n'
    yield terminator


@classmethod
def from_dict_or_instance(cls, data, **kwargs):
    """
        check if ``data`` is already a :class:`ZoopObject` or
        ``subclass``.

        If not call :meth:`from_dict`.

        Args:
            data: dict of data or instance
            **kwargs: kwargs

        Returns:
            instance initialized of ``cls``
        """
    if isinstance(data, cls):
        return data
    else:
        return cls.from_dict(data, **kwargs)


def is_none(value):
    """ Checks if the value is a None """
    return value.lower() == str(None).lower()


@staticmethod
def update_parameters_with_cli_parameters(parameters, cli_parameters,
    stack_name):
    """
        Overwrite parameters from stack_config with those provided by user by cli
        :param parameters: dict
        :param cli_parameters: dict
        :param stack_name: string
        :return: dict

        """
    if stack_name in cli_parameters.keys():
        for new_key, new_value in cli_parameters[stack_name].items():
            parameters[new_key] = new_value
    return parameters


@staticmethod
def _mutate_label(label: str) ->str:
    """
        Athena only supports lowercase column names and aliases.

        :param label: Expected expression label
        :return: Conditionally mutated label
        """
    return label.lower()


def quit_app():
    """
    Quits application (callback)
    """
    global running
    running = False
    return 0


def cellFill(pfx, SGData, parmDict, sigDict):
    """Returns the filled-out reciprocal cell (A) terms and their uncertainties
    from the parameter and sig dictionaries.

    :param str pfx: parameter prefix ("n::", where n is a phase number)
    :param dict SGdata: a symmetry object
    :param dict parmDict: a dictionary of parameters
    :param dict sigDict:  a dictionary of uncertainties on parameters

    :returns: A,sigA where each is a list of six terms with the A terms
    """
    if SGData['SGLaue'] in ['-1']:
        A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A1'], parmDict[pfx +
            'A2'], parmDict[pfx + 'A3'], parmDict[pfx + 'A4'], parmDict[pfx +
            'A5']]
    elif SGData['SGLaue'] in ['2/m']:
        if SGData['SGUniq'] == 'a':
            A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A1'], parmDict[pfx +
                'A2'], 0, 0, parmDict[pfx + 'A5']]
        elif SGData['SGUniq'] == 'b':
            A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A1'], parmDict[pfx +
                'A2'], 0, parmDict[pfx + 'A4'], 0]
        else:
            A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A1'], parmDict[pfx +
                'A2'], parmDict[pfx + 'A3'], 0, 0]
    elif SGData['SGLaue'] in ['mmm']:
        A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A1'], parmDict[pfx +
            'A2'], 0, 0, 0]
    elif SGData['SGLaue'] in ['4/m', '4/mmm']:
        A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A0'], parmDict[pfx +
            'A2'], 0, 0, 0]
    elif SGData['SGLaue'] in ['6/m', '6/mmm', '3m1', '31m', '3']:
        A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A0'], parmDict[pfx +
            'A2'], parmDict[pfx + 'A0'], 0, 0]
    elif SGData['SGLaue'] in ['3R', '3mR']:
        A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A0'], parmDict[pfx +
            'A0'], parmDict[pfx + 'A3'], parmDict[pfx + 'A3'], parmDict[pfx +
            'A3']]
    elif SGData['SGLaue'] in ['m3m', 'm3']:
        A = [parmDict[pfx + 'A0'], parmDict[pfx + 'A0'], parmDict[pfx +
            'A0'], 0, 0, 0]
    try:
        if SGData['SGLaue'] in ['-1']:
            sigA = [sigDict[pfx + 'A0'], sigDict[pfx + 'A1'], sigDict[pfx +
                'A2'], sigDict[pfx + 'A3'], sigDict[pfx + 'A4'], sigDict[
                pfx + 'A5']]
        elif SGData['SGLaue'] in ['2/m']:
            if SGData['SGUniq'] == 'a':
                sigA = [sigDict[pfx + 'A0'], sigDict[pfx + 'A1'], sigDict[
                    pfx + 'A2'], 0, 0, sigDict[pfx + 'A5']]
            elif SGData['SGUniq'] == 'b':
                sigA = [sigDict[pfx + 'A0'], sigDict[pfx + 'A1'], sigDict[
                    pfx + 'A2'], 0, sigDict[pfx + 'A4'], 0]
            else:
                sigA = [sigDict[pfx + 'A0'], sigDict[pfx + 'A1'], sigDict[
                    pfx + 'A2'], sigDict[pfx + 'A3'], 0, 0]
        elif SGData['SGLaue'] in ['mmm']:
            sigA = [sigDict[pfx + 'A0'], sigDict[pfx + 'A1'], sigDict[pfx +
                'A2'], 0, 0, 0]
        elif SGData['SGLaue'] in ['4/m', '4/mmm']:
            sigA = [sigDict[pfx + 'A0'], 0, sigDict[pfx + 'A2'], 0, 0, 0]
        elif SGData['SGLaue'] in ['6/m', '6/mmm', '3m1', '31m', '3']:
            sigA = [sigDict[pfx + 'A0'], 0, sigDict[pfx + 'A2'], 0, 0, 0]
        elif SGData['SGLaue'] in ['3R', '3mR']:
            sigA = [sigDict[pfx + 'A0'], 0, 0, sigDict[pfx + 'A3'], 0, 0]
        elif SGData['SGLaue'] in ['m3m', 'm3']:
            sigA = [sigDict[pfx + 'A0'], 0, 0, 0, 0, 0]
    except KeyError:
        sigA = [0, 0, 0, 0, 0, 0]
    return A, sigA


def extract_arj(archive, compression, cmd, verbosity, interactive, outdir):
    """Extract an ARJ archive."""
    cmdlist = [cmd, 'x', '-r']
    if not interactive:
        cmdlist.append('-y')
    cmdlist.extend([archive, outdir])
    return cmdlist


def ontstop_stop(*args):
    """
    Always stop after finding tstop
    """
    return 1


def is_string(ins):
    """Convenience wrapper"""
    if ins.is_cstr():
        return True
    return False


@staticmethod
def fee_for_tx(message=''):
    """Returns fee for the matching message"""
    return 0.01 + len(message) / 100000


@classmethod
def _request_args(cls, request):
    """Validate the existence and type of the arguments passed
        in the request dictionary."""
    raise NotImplementedError


def create_graph(zettels, graph, include_self_references=True, only_listed=
    False):
    """
    Create of graph of the zettels linking to each other.

    Parameters
    ----------
    zettels : list of dictionaries
    include_self_references : bool, optional
        Include links to the source document. Defaults to True.
    only_listed : bool, optional
        Only include nodes in the graph it's actually one of the zettels.
        Default is False.

    Returns
    -------
    graph : nx.Graph

    """
    zettel_ids = set()
    link_ids = set()
    for zettel in zettels:
        zettel_ids.add(zettel['id'])
        link_ids.update(zettel['links'])
    if only_listed:
        ids_to_include = zettel_ids
    else:
        ids_to_include = zettel_ids | link_ids
    for zettel in zettels:
        graph.add_node(zettel['id'], title=zettel['title'])
        for link in zettel['links']:
            if link not in ids_to_include:
                continue
            if include_self_references or zettel['id'] != link:
                graph.add_edge(zettel['id'], link)
    return graph


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


def baseTransform(val):
    """ back-conversion: modules are encoded by their name
    and classes by the classname """
    from pybrain.structure.modules.module import Module
    from inspect import isclass
    if isinstance(val, Module):
        return val.name
    elif isclass(val):
        return val.__name__
    else:
        return str(val)


def get_value_stepwise(x, f):
    """
    Returns the value of a stepwise constant
    function defined by the right extrems
    of its interval
    Functions are assumed to be defined
    in (0, inf).

    Parameters
    ----------
    x: float
        Value in which the function is to be
        evaluated
    f: np.ndarray
        Stepwise function represented as a 2 column
        matrix. Each row is the rightmost extreme
        point of each constant interval. The first column
        contains the x coordinate and is sorted increasingly.
        f is assumed to be defined only in the interval
        :math: (0, \\infty)
    Returns
    --------
    float or None
        The image of x under f: `f(x)`. If `x` is negative,
        then None is returned instead. If x is outside
        the range of the function (greater than `f[-1, 0]`),
        then the method returns None.

    Examples
    ---------
    >>> f = np.array([
    ...     [1, 1],
    ...     [3, 4]])
    >>> [pm.get_value_stepwise(x, f)
    ...     for x in [-1, 0, 0.5, 1, 2, 3, 4]]
    [None, 1, 1, 1, 4, 4, None]

    """
    if x < 0:
        return None
    for step in f:
        if x <= step[0]:
            return step[1]


def runExtensionFunction(extensions, name, *args):
    """
  run extension functions by name
  name must in extensionFuntionNames
  """
    res = False
    for ext in extensions:
        func = ext.__dict__.get(name)
        hanldedByPrevious = False
        if not func is None:
            hanldedByPrevious = func(*args, res)
        res = res or hanldedByPrevious
    return res


def unpack(value):
    """Return a three tuple of data, code, and headers"""
    if not isinstance(value, tuple):
        return value, 200, {}
    try:
        data, code, headers = value
        return data, code, headers
    except ValueError:
        pass
    try:
        data, code = value
        return data, code, {}
    except ValueError:
        pass
    return value, 200, {}


def color_term(string, color='blue', bold=True):
    u"""Linux客户端彩色输出，适配py2，py3."""
    colors = {'grey': '\x1b[0;30m', 'red': '\x1b[0;31m', 'green':
        '\x1b[0;32m', 'yellow': '\x1b[0;33m', 'blue': '\x1b[0;34m',
        'megenta': '\x1b[0;35m', 'cyan': '\x1b[0;36m', 'white':
        '\x1b[0;37m', 'bold': '\x1b[1m', 'end': '\x1b[0m'}
    color_format = colors[color].replace('[0', '[1') if bold else colors[color]
    return color_format + str(string) + colors['end']


def validate_matrix_shape(name, shape, nrows, ncols, nobs):
    """
    Validate the shape of a possibly time-varying matrix, or raise an exception

    Parameters
    ----------
    name : str
        The name of the matrix being validated (used in exception messages)
    shape : array_like
        The shape of the matrix to be validated. May be of size 2 or (if
        the matrix is time-varying) 3.
    nrows : int
        The expected number of rows.
    ncols : int
        The expected number of columns.
    nobs : int
        The number of observations (used to validate the last dimension of a
        time-varying matrix)

    Raises
    ------
    ValueError
        If the matrix is not of the desired shape.
    """
    ndim = len(shape)
    if ndim not in [2, 3]:
        raise ValueError(
            'Invalid value for %s matrix. Requires a 2- or 3-dimensional array, got %d dimensions'
             % (name, ndim))
    if not shape[0] == nrows:
        raise ValueError(
            'Invalid dimensions for %s matrix: requires %d rows, got %d' %
            (name, nrows, shape[0]))
    if not shape[1] == ncols:
        raise ValueError(
            'Invalid dimensions for %s matrix: requires %d columns, got %d' %
            (name, ncols, shape[1]))
    if nobs is None and not (ndim == 2 or shape[-1] == 1):
        raise ValueError(
            'Invalid dimensions for %s matrix: time-varying matrices cannot be given unless `nobs` is specified (implicitly when a dataset is bound or else set explicity)'
             % name)
    if ndim == 3 and nobs is not None and not shape[-1] in [1, nobs]:
        raise ValueError(
            'Invalid dimensions for time-varying %s matrix. Requires shape (*,*,%d), got %s'
             % (name, nobs, str(shape)))


def t_start_triple_quoted_q1_string(t):
    """([bB]|[uU])?[rR]?'''"""
    t.lexer.push_state('TRIPLEQ1')
    t.type = 'STRING_START_TRIPLE'
    if 'r' in t.value or 'R' in t.value:
        t.lexer.is_raw = True
    t.value = t.value.split("'", 1)[0]
    return t


def get_vht_oper(type_, data):
    """http://git.kernel.org/cgit/linux/kernel/git/jberg/iw.git/tree/scan.c?id=v3.17#n897

    Positional arguments:
    type_ -- corresponding `ieprinters` dictionary key for the instance.
    data -- bytearray data to read.
    """
    raise NotImplementedError


def p_method_body(p):
    """method_body : LBRACE inner_statement_list RBRACE
                   | SEMI"""
    if len(p) == 4:
        p[0] = p[2]
    else:
        p[0] = []


def exit_spread_price(data, value, _idx):
    """
    Exit the trade when the trade price falls below the min or rises above the max.

    For example, it would exit if below 0.4 min or above $0.90 max price.
    """
    pass


def make_zoom_window(bounding_box, region_size, padding=2, invert=False):
    """
    Computes a zoom window around a target bounding box.

    Parameters
    ----------
    bounding_box : dict of ints
        This dict represents the target bounding box and should have the form::

            {
                'x_min': int,
                'x_max': int,
                'y_min': int,
                'y_max': int
            }

        where the ints describe the maximal and minimal indices of pixels along
        the x- and y-axes included within the bounding box, respectively.
    region_size : int
        The side length of the square region within which the target bounding
        box lies, in pixels.
    padding : int
        The number of pixels to include within the zoom window around the
        bounding box. If the zoom window is at the edge of the region, it may be
        impossible to pad by the specified number of pixels, in which case the
        zoom window will be shifted away from the edge of the region.
    invert : bool
        If True, the zoom window will be reflected across the diagonal.

    Returns
    -------
    dict of int
        This dict represents the computed zoom window and has the following
        structure::

            {
                'x_start': int,
                'y_start': int,
                'size': int
            }

        where x_start and y_start refer to the indices of the lowest-indexed
        pixel to be included in the zoom window along each axis, and size
        indicates the side length of the square zoom window in pixels.
    """
    zoom_window_size = max(bounding_box['x_max'] - bounding_box['x_min'],
        bounding_box['y_max'] - bounding_box['y_min']) + 1 + 2 * padding
    zoom_window = {'x_start': bounding_box['x_min'] - padding, 'y_start':
        bounding_box['y_min'] - padding, 'size': zoom_window_size}
    if invert:
        zoom_window = {'x_start': bounding_box['y_min'] - padding,
            'y_start': bounding_box['x_min'] - padding, 'size':
            zoom_window_size}
    if zoom_window['x_start'] + zoom_window['size'] - 1 >= region_size:
        zoom_window['x_start'] -= zoom_window['x_start'] + zoom_window['size'
            ] - region_size
    if zoom_window['y_start'] + zoom_window['size'] - 1 >= region_size:
        zoom_window['y_start'] -= zoom_window['y_start'] + zoom_window['size'
            ] - region_size
    if zoom_window['x_start'] < 0:
        zoom_window['x_start'] -= zoom_window['x_start']
    if zoom_window['y_start'] < 0:
        zoom_window['y_start'] -= zoom_window['y_start']
    return zoom_window


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


@staticmethod
def null_fn():
    """NO OP null function for filler task."""
    return True


def setDefaults(configObj={}):
    """ Return a dictionary of the default parameters
        which also been updated with the user overrides.
    """
    paramDict = {'gain': 7, 'grow': 1, 'ctegrow': 0, 'rn': 5, 'snr':
        '4.0 3.0', 'scale': '0.5 0.4', 'backg': 0, 'expkey': 'exptime'}
    if len(configObj) > 0:
        for key in configObj:
            paramDict[key] = configObj[key]
    return paramDict


def p_list_one(p):
    """asconfig    : asconfig_item
       string_list : STRING
       asg_list    : asg_item
       rule_list   : rule_item
    """
    p[0] = [p[1]]


def try_key(dictionary, default, *keys):
    """
    Tries to get all keys in a nested dictionary.
    """
    try:
        res = dictionary
        for k in keys:
            res = res[k]
        return res
    except (KeyError, IndexError) as e:
        return default


def ask_bool(question, default=True):
    """Asks a question yes no style"""
    default_q = 'Y/n' if default else 'y/N'
    answer = input('{0} [{1}]: '.format(question, default_q))
    lower = answer.lower()
    if not lower:
        return default
    return lower == 'y'


def groupbys(df1, df2, by=None, left_by=None, right_by=None,
    allow_right_empty=False):
    """
    df1: Left pandas.DataFrame
    df2: Right pandas.DataFrame
    by: "by" of groupby. Use intersection of each columns, if it is None.
    left_by: This or "by" is used as "by" of df1.groupby.
    right_by: This or "by" is used as "by" of df2.groupby.
    allow_right_empty: Output right, if it is empty.
    """
    if by is None:
        by = df1.columns.intersection(df2.columns).tolist()
    g1 = df1.groupby(left_by if left_by else by)
    g2 = df2.groupby(right_by if right_by else by)
    for k, v1 in g1:
        v2 = df2.iloc[g2.indices.get(k, [])]
        if allow_right_empty or len(v2):
            yield k, v1, v2


@classmethod
def register_variable_provider(cls, provider):
    """Plugin point to allow functions to manipulate the context
        passed to *all* templates for *all* widgets.

        def provider(context): ...

        TemplateEngine.register_variable_provider(provider)
        """
    cls.variable_providers.append(provider)


def duplicate_move(MBALL_OT_duplicate_metaelems=None,
    TRANSFORM_OT_translate=None):
    """Make copies of the selected metaelements and move them

    :param MBALL_OT_duplicate_metaelems: Duplicate Metaelements, Duplicate selected metaelement(s)
    :param TRANSFORM_OT_translate: Move, Move selected items
    """
    pass


@classmethod
def to_os_independent_path(cls, path):
    """Replaces the part of the given path with repository environment
        variable which makes the given path OS independent.

        :param path: path to make OS independent
        :return:
        """
    repo = cls.find_repo(path)
    if repo:
        return '$%s/%s' % (repo.env_var, repo.make_relative(path))
    else:
        return path


def _loop_once():
    """Run the main loop once
    """
    pass


def calculate_heartbeats(shb, chb):
    """
    Given a heartbeat string from the server, and a heartbeat tuple from the client,
    calculate what the actual heartbeat settings should be.

    :param (str,str) shb: server heartbeat numbers
    :param (int,int) chb: client heartbeat numbers

    :rtype: (int,int)
    """
    sx, sy = shb
    cx, cy = chb
    x = 0
    y = 0
    if cx != 0 and sy != '0':
        x = max(cx, int(sy))
    if cy != 0 and sx != '0':
        y = max(cy, int(sx))
    return x, y


def _add_codes(inv):
    """ add network, station, location, channel codes where applicable """
    for network in inv:
        net_code = network.code
        network.network_code = net_code
        for station in network:
            sta_code = station.code
            station.station_code = sta_code
            station.network_code = net_code
            for channel in station:
                channel.station_code = sta_code
                channel.network_code = net_code
                channel.channel_code = channel.code


def disable_availability_zones_for_load_balancer(LoadBalancerName=None,
    AvailabilityZones=None):
    """
    Removes the specified Availability Zones from the set of Availability Zones for the specified load balancer.
    There must be at least one Availability Zone registered with a load balancer at all times. After an Availability Zone is removed, all instances registered with the load balancer that are in the removed Availability Zone go into the OutOfService state. Then, the load balancer attempts to equally balance the traffic among its remaining Availability Zones.
    For more information, see Add or Remove Availability Zones in the Classic Load Balancer Guide .
    See also: AWS API Documentation

    Examples
    This example removes the specified Availability Zone from the set of Availability Zones for the specified load balancer.
    Expected Output:

    :example: response = client.disable_availability_zones_for_load_balancer(
        LoadBalancerName='string',
        AvailabilityZones=[
            'string',
        ]
    )

    :type LoadBalancerName: string
    :param LoadBalancerName: [REQUIRED]
            The name of the load balancer.

    :type AvailabilityZones: list
    :param AvailabilityZones: [REQUIRED]
            The Availability Zones.
            (string) --

    :rtype: dict
    :return: {
        'AvailabilityZones': [
            'string',
        ]
    }

    :returns:
    (string) --

    """
    pass


def register(module_name: str, translations_dict: dict):
    """Registers an addon’s UI translations.

    :param module_name: The name identifying the addon.
    :type module_name: str
    :param translations_dict: A dictionary built like that: {locale: {msg_key: msg_translation, ...}, ...}
    :type translations_dict: dict
    """
    pass


def macro_calc(item):
    """
    Calculate PPV_Macro and TPR_Macro.

    :param item: PPV or TPR
    :type item:dict
    :return: PPV_Macro or TPR_Macro as float
    """
    try:
        item_sum = sum(item.values())
        item_len = len(item.values())
        return item_sum / item_len
    except Exception:
        return 'None'


def Pretty(family, v1=None, v2=None, v3=None):
    """ backwards compatible. use PrettyUserAgent instead! """
    if v3:
        if v3[0].isdigit():
            return '%s %s.%s.%s' % (family, v1, v2, v3)
        else:
            return '%s %s.%s%s' % (family, v1, v2, v3)
    elif v2:
        return '%s %s.%s' % (family, v1, v2)
    elif v1:
        return '%s %s' % (family, v1)
    return family


def srm_to_ebc(srm):
    """
    Convert the EBC value to SRM
    https://en.wikipedia.org/wiki/Standard_Reference_Method
    """
    return srm / 0.508


def add_folder_counts(c):
    """Aggregate subfolder counts from folder_x_folder."""
    sql = """
        SELECT COUNT(*) as count, parent_id
        FROM folder_x_folder
        GROUP BY parent_id
    """
    c.execute(sql)
    data = c.fetchall()
    sql = """
        UPDATE folders
        SET subfolder_count = ?
        WHERE folder_id = ?
    """
    c.executemany(sql, data)


def tokenizepi(string):
    """
	Tokenize the string object ``string`` according to the processing
	instructions in the string. :func:`tokenize` will generate tuples with the
	first item being the processing instruction target and the second being the
	PI data. "Text" content (i.e. anything other than PIs) will be returned as
	``(None, data)``.
	"""
    pos = 0
    while True:
        pos1 = string.find('<?', pos)
        if pos1 < 0:
            part = string[pos:]
            if part:
                yield None, part
            return
        pos2 = string.find('?>', pos1)
        if pos2 < 0:
            part = string[pos:]
            if part:
                yield None, part
            return
        part = string[pos:pos1]
        if part:
            yield None, part
        part = string[pos1 + 2:pos2].strip()
        parts = part.split(None, 1)
        target = parts[0]
        if len(parts) > 1:
            data = parts[1]
        else:
            data = ''
        yield target, data
        pos = pos2 + 2


def validate_parameters(value, ctx=None):
    """Validate 'parameters' dict."""
    parameters = value.get_dict()
    try:
        plot_num = parameters['INPUTPP']['plot_num']
    except KeyError:
        return 'parameter `INPUTPP.plot_num` must be explicitly set'
    if plot_num in range(23) and plot_num not in [14, 15, 16]:
        parameters['INPUTPP']['plot_num'] = int(plot_num)
    else:
        return (
            '`INTPUTPP.plot_num` must be an integer in the range 0-23 excluding [14, 15, 16]'
            )
    try:
        dimension = parameters['PLOT']['iflag']
    except KeyError:
        return 'parameter `PLOT.iflag` must be explicitly set'
    if dimension in range(5):
        parameters['PLOT']['iflag'] = int(dimension)
    else:
        return '`PLOT.iflag` must be an integer in the range 0-4'


@staticmethod
def _get_vhba_value(metric, data):
    """
        function that returns the data from the managed object
        :param metric:
        :param data:
        :return:
        """
    if metric == 'network.vhba.tx.rate':
        return float(float(data.bytes_tx_delta) / 60 * 8 / 1000000000)
    elif metric == 'network.vhba.rx.rate':
        return float(float(data.bytes_rx_delta) / 60 * 8 / 1000000000)
    elif metric == 'network.vhba.rx.drop':
        return float(data.dropped_rx_delta)
    elif metric == 'network.vhba.tx.drop':
        return float(data.dropped_tx_delta)
    elif metric == 'network.vhba.rx.error':
        return float(data.errors_rx_delta)
    elif metric == 'network.vhba.tx.error':
        return float(data.errors_tx_delta)
    else:
        return None


def fib(n):
    """Fibonacci example function

    Args:
      n (int): integer

    Returns:
      int: n-th Fibonacci number
    """
    assert n > 0
    a, b = 1, 1
    for i in range(n - 1):
        a, b = b, a + b
    return a


@classmethod
def save_data(cls, data_set, mongo_collection, file_name=None):
    """
        save data to a mongodb database or to a file
        :param data_set : array()
        :param mongo_collection : mongodb collection
        :param file_name : str()
        :return Mongodb InsertOneResult or InsertManyResult
        todo: enable file_name option
        """
    if len(data_set) == 1:
        res = mongo_collection.insert_one(data_set[0])
        return res
    else:
        res = mongo_collection.insert_many(data_set)
        return res


def getcwd():
    """Return the path from which a canonical path is calculated.

        This path should be used to resolve file patterns or to convert
        canonical paths back to file paths for display. It shouldn't be
        used to get real file paths. Use vfs functions instead.
        """


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

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

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


def is_parsed_result_successful(parsed_result):
    """Returns True if a parsed result is successful"""
    return parsed_result['ResponseMetadata']['HTTPStatusCode'] < 300


def T2RP(T):
    """
    convert transform matrix into rotation matrix and translation vector

    Parameters
    ----------
    T : np.array(4,4)
        homogeneous transform matrix

    Returns
    -------
    R : np.array(3,3)
        rotation matrix
    P : np.array(3,1)
        translation vector

    Raises
    ------
    """
    R = T[:3, :3]
    P = T[:3, (3)].reshape(3, 1)
    return R, P


@staticmethod
def write_sorted_int(buf, offset, value):
    """
        Writes a packed sorted integer starting at the given buffer offset and
        returns the next offset to be written.

        :param buf: the buffer to write to.
        :type buf: bytearray
        :param offset: the offset in the buffer at which to start writing.
        :type offset: int
        :param value: the integer to be written.
        :type value: int
        :returns: the offset past the bytes written.
        :rtype: int

        Values in the inclusive range [-119,120] are stored in a single byte.
        For values outside that range, the first byte stores the number of
        additional bytes. The additional bytes store (value + 119 for negative
        and value - 121 for positive) as an unsigned big endian integer.
        """
    b1 = offset
    offset += 1
    if value < -119:
        """
            If the value < -119, then first adjust the value by adding 119. Then
            the adjusted value is stored as an unsigned big endian integer.
            """
        value += 119
        """
            Store the adjusted value as an unsigned big endian integer. For an
            negative integer, from left to right, the first significant byte is
            the byte which is not equal to 0xFF. Also please note that, because
            the adjusted value is stored in big endian integer, we extract the
            significant byte from left to right.

            In the left to right order, if the first byte of the adjusted value
            is a significant byte, it will be stored in the 2nd byte of the buf.
            Then we will look at the 2nd byte of the adjusted value to see if
            this byte is the significant byte, if yes, this byte will be stored
            in the 3rd byte of the buf, and the like.
            """
        if value | 16777215 != 4294967295:
            buf[offset] = value >> 24 & 255
            offset += 1
        if value | 65535 != 4294967295:
            buf[offset] = value >> 16 & 255
            offset += 1
        if value | 255 != 4294967295:
            buf[offset] = value >> 8 & 255
            offset += 1
        buf[offset] = value & 255
        offset += 1
        """
            value_len is the length of the value part stored in buf. Because
            the first byte of buf is used to stored the length, we need to
            subtract one.
            """
        value_len = offset - b1 - 1
        """
            The first byte stores the number of additional bytes. Here we store
            the result of 0x08 - value_len, rather than directly store
            value_len. The reason is to implement natural sort order for
            byte-by-byte comparison.
            """
        buf[b1] = 8 - value_len & 255
    elif value > 120:
        """
            If the value > 120, then first adjust the value by subtracting 121.
            Then the adjusted value is stored as an unsigned big endian integer.
            """
        value -= 121
        """
            Store the adjusted value as an unsigned big endian integer. For a
            positive integer, from left to right, the first significant byte is
            the byte which is not equal to 0x00.

            In the left to right order, if the first byte of the adjusted value
            is a significant byte, it will be stored in the 2nd byte of the buf.
            Then we will look at the 2nd byte of the adjusted value to see if
            this byte is the significant byte, if yes, this byte will be stored
            in the 3rd byte of the buf, and the like.
            """
        if value & 4278190080 != 0:
            buf[offset] = value >> 24 & 255
            offset += 1
        if value & 4294901760 != 0:
            buf[offset] = value >> 16 & 255
            offset += 1
        if value & 4294967040 != 0:
            buf[offset] = value >> 8 & 255
            offset += 1
        buf[offset] = value & 255
        offset += 1
        """
            value_len is the length of the value part stored in buf. Because the
            first byte of buf is used to stored the length, we need to subtract
            one.
            """
        value_len = offset - b1 - 1
        """
            The first byte stores the number of additional bytes. Here we store
            the result of 0xF7 + value_len, rather than directly store
            value_len. The reason is to implement natural sort order for
            byte-by-byte comparison.
            """
        buf[b1] = 247 + value_len & 255
    else:
        """
            If -119 <= value <= 120, only one byte is needed to store the value.
            The stored value is the original value plus 127.
            """
        buf[b1] = value + 127 & 255
    return offset


def asFloatOrNone(val):
    """Converts floats, integers and string representations of either to floats.
    If val is "NaN" (case irrelevant) or "?" returns None.

    Raises ValueError or TypeError for all other values

    """
    if hasattr(val, 'lower') and val.lower() in ('nan', '?'):
        return None
    else:
        return float(val)


def chunkizator(iterable, size=1000):
    """Creates chunks from an iterable"""
    s = 0
    chunk = []
    for i in iterable:
        if s == size:
            yield chunk
            chunk = []
            s = 0
        chunk.append(i)
        s += 1
    yield chunk


def get_test_permutations():
    """Return the permutations to be used in testing."""
    return []


def flagged_return(flags, objects):
    """Return only objects with corresponding True flags. Useful for functions with multiple possible return items."""
    if sum(flags) == 1:
        return objects[0]
    elif sum(flags) > 1:
        return tuple([object for flag, object in zip(flags, objects) if flag])
    else:
        return ()


@property
def rules_count(cls):
    """
        Get count of rules defined in the class
        :return: Count of rules
        :raise RuleNotDefinedException: If the rule is not defined.
        :raise CantCreateSingleRuleException: If the rule consists of more rules.
        :raise NotASingleSymbolException: If number of symbols on the left is more.
        """
    return cls.count


@staticmethod
def to_celsius(delisle):
    """ Convert delisle to celsius """
    return 100 - delisle * 2 / 3


def catV(mat1, mat2):
    """Concatenate 2 matrices (vertical concatenation)"""
    return mat1.catV(mat2)


@classmethod
def create_from_region(cls, chrom, start, end, strand, binsize, stepsize,
    flank=0, zero_padding=True):
    """Creates a GenomicIndexer object.

        This method constructs a GenomicIndexer from
        a given genomic interval.

        Parameters
        ----------
        chrom : str
            Chromosome name.
        start : int
            Interval start
        end : int
            Interval end
        binsize : int or None
            Binsize in base pairs. If None, the binsize is obtained from
            the interval lengths in the bed file, which requires intervals
            to be of equal length.
        stepsize : int or None
            Stepsize in base pairs. If stepsize is None,
            stepsize is set to equal to binsize.
        flank : int
            flank size in bp to be attached to
            both ends of a region. Default: 0.
        zero_padding : boolean
            zero_padding indicate if variable sequence
            lengths are used in conjunction with zero-padding.
            If zero_padding is True, a binsize must be specified.
            Default: True.
        """
    if binsize is None:
        binsize = end - start
    if stepsize is None:
        stepsize = binsize
    gind = cls(binsize, stepsize, flank, zero_padding=zero_padding)
    gind.add_interval(chrom, start, end, strand)
    return gind


def vehicleTypes2flt(outSTRM, vtIDm):
    """
    Currently, rather a stub than an implementation. Writes the vehicle ids stored
    in the given "vtIDm" map formatted as a .flt file readable by PHEM.

    The following may be a matter of changes:
    - A default map is assigned to all vehicle types with the same probability
    """
    for q in sorted(vtIDm._m):
        print('%s,%s,%s' % (vtIDm.g(q), '<VEHDIR>\\PC\\PC_%s.GEN' % q, 1.0),
            file=outSTRM)


def build_precedence_mapping(precedence_list):
    """Given a precedence list, build a dict with class->int mappings.
    Utility function used by some external code.
    """
    from ufl.classes import Expr, all_ufl_classes, abstract_classes
    pm = {}
    missing = set()
    k = 0
    for p in precedence_list:
        for c in p:
            pm[c] = k
        k += 1
    for c in all_ufl_classes:
        if c not in abstract_classes and c not in pm:
            b = c.__bases__[0]
            while b is not Expr:
                if b in pm:
                    pm[c] = pm[b]
                    break
                b = b.__bases__[0]
            if c not in pm:
                missing.add(c)
    return pm, missing


def get_spaced_line(line, depth=0):
    """
    Prepend a line with certain space
    :param line: the line to edit
    :param depth: the number of spaces to insert
    :return: the prepended line
    """
    if type(line) == str:
        return ' ' * depth + str(line)
    return line


def load_url(driver, content, wait_for_it=False):
    """given a url as `content`, opens the url"""
    driver.get(content)


def setdefault(key, d):
    """D.setdefault(k, d) -> D.get(k, d), also set D[k]=d if k not in D.

        Return the value like :meth:`~BTrees.Interfaces.IMinimalDictionary.get` except that if key is missing, d is both
        returned and inserted into the dictionary as the value of k.

        Note that, unlike as for Python's :meth:`dict.setdefault`, d is not
        optional.  Python defaults d to None, but that doesn't make sense
        for mappings that can't have None as a value (for example, an
        :class:`~BTrees.IIBTree.IIBTree` can have only integers as values).
        """


def resolve_json_response(json_response):
    """
    Resolves the json response for success or failure status and returns the correct
    response based on the outcome of said resolution

    :param json_response:       The json response gotten from a remote host, an overzealous typist
                                or some loosely available file
                                :type <type, 'str'>

    :return status:             The status of the json message which could be one of `success` or `failure`
                                :type <type, 'str'>
    """
    pass


def get(key, default=None):
    """ Get value for the given key

        If no value is found or the value is invalid, the default value
        will be returned.
        """


def cAddVec():
    """
    Return the kernel source for cAddVec.
    """
    R = """
        KERNEL void cAddVec(
        GLOBAL_MEM float2 *a,
        GLOBAL_MEM float2 *b,
        GLOBAL_MEM float2 *dest)
        {const int i = get_global_id(0);
        dest[i]= a[i]+b[i];
        };"""
    return R


def find(*, advertised=None, mail_host=None):
    """Search for mailing lists matching some criteria.

        The keyword arguments are mailing list properties that will be
        filtered upon.

        :return: The list of filtered mailing lists.
        :rtype: list of `IMailingList`
        """


@classmethod
def SaveProject(cctx, proj):
    """Save all changes"""
    book = cctx.frame.docBook
    for i in range(0, book.GetPageCount()):
        pane = book.GetPage(i)
        if hasattr(pane, '_object'):
            if pane._object.project == proj:
                pane.Commit()
    cctx.app.SaveProject(proj)


def create_rar(archive, compression, cmd, verbosity, interactive, filenames):
    """Create a RAR archive."""
    cmdlist = [cmd, 'a']
    if not interactive:
        cmdlist.append('-y')
    cmdlist.extend(['-r', '-m5', '--', archive])
    cmdlist.extend(filenames)
    return cmdlist


def sublocations():
    """Return an iterable of the object's sublocations."""


def read_fasta(fasta_file):
    """
    Read fasta file and return list.

    The retuned list (named data) has the following structure::

        fasta = [
            [header1, sequence1],
            [header2, sequence2],
            [header2, sequence2],
            ...
        ]

    """
    data = []
    with open(fasta_file) as ffile:
        for line in ffile:
            line = line.strip()
            if line.startswith('>'):
                data.append([line])
            elif len(data[-1]) == 1:
                data[-1].append(line)
            else:
                data[-1][1] = data[-1][1] + line
    return data


def __new__(cls, packoffset, type, size, stream, *args):
    """Helps with the initialization of subclasses"""
    return tuple.__new__(cls, (packoffset, type, size, stream))


@staticmethod
def storeDB(conn, domains):
    """Overwrite the domains in the table with the specified domains (string) in the database."""
    c = conn.cursor()
    vals = []
    for domain in domains:
        vals.append((domain,))
    c.execute('delete from domain')
    c.executemany('insert into domain(domain) values (?)', iter(vals))
    c.close()


def extract_request_details(request_object, session_object=None):
    """
        a method for extracting request details from request and session objects

        NOTE:   method is also a placeholder funnel for future validation
                processes, request logging, request context building and
                counter-measures for the nasty web

    :param request_object: request object generated by flask from request route
    :param session_object: session object generated by flask from client cookie
    :return: dictionary with request details
    """
    request_details = {'error': '', 'status': 'ok', 'code': 200, 'method':
        request_object.method, 'session': {}, 'root': request_object.
        url_root, 'route': request_object.path, 'headers': {}, 'form': {},
        'params': {}, 'json': {}, 'data': ''}
    request_details['headers'].update(**request_object.headers)
    for key in request_object.args.keys():
        request_details['params'][key] = request_object.args.get(key)
    if session_object:
        request_details['session'].update(**session_object)
    if request_object.is_json:
        try:
            json_details = request_object.get_json(silent=True)
            if isinstance(json_details, dict):
                request_details['json'] = json_details
        except:
            pass
    else:
        try:
            from base64 import b64encode
            request_details['data'] = b64encode(request_object.data).decode()
        except:
            pass
        try:
            for key, value in request_object.form.items():
                request_details['form'][key] = value
        except:
            pass
    return request_details


def _none_dict(val, name, defaults={}):
    """

    False/None  ===>  None
    True/dict   ===>  dict
    otherwise   ===>  error

    """
    if val is False or val is None:
        return None
    if val is True:
        val = dict()
    if not isinstance(val, dict):
        raise ValueError("Unrecognized type '{}' for `{}`!".format(type(val
            ), name))
    for kk, vv in defaults.items():
        val.setdefault(kk, vv)
    return val


def change_to_id(obj):
    """Change key named 'uuid' to 'id'

    Magnum returns objects with a field called 'uuid' many of Horizons
    directives however expect objects to have a field called 'id'.
    """
    obj['id'] = obj.pop('uuid')
    return obj


@staticmethod
def tokens_end_update(tokens, end=None):
    """Update the end of tokens accordinly to the start of the next one into the tokens list.

    Paramaters
    ----------
    tokens: list

    Returns
    -------
    tokens: list
    """
    if len(tokens) > 0:
        for k, tok in enumerate(tokens[:-1]):
            tok['end_next'] = tokens[k + 1]['start']
        if end is not None:
            tokens[-1]['end_next'] = end
    return tokens


def create_table(db, schema_name, table_name, columns):
    """
    Create a table, schema_name.table_name, in given database with given list of column names.
    """
    table = '{}.{}'.format(schema_name, table_name
        ) if schema_name else table_name
    db.execute('DROP TABLE IF EXISTS {}'.format(table))
    columns_list = ', '.join(columns)
    db.execute('CREATE TABLE {} ({})'.format(table, columns_list))


def get_parametrizations():
    """ returns a list of all implemented parametrizations """
    return ['ZHS1992', 'Alvarez2000', 'Alvarez2009', 'Alvarez2012']


def is_date(word):
    """ Function that returns 'FEC' if a shipo word is a date or False if not

        :param word: a word to be evaluated
        :type word: str
        :returns: 'FEC' if a shipo word is a date or False if not
        :rtype: str

        :Example:

        >>> import chana.ner
        >>> chana.ner.is_date('Agosto')
        'FEC'

    """
    months = ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
        'julio', 'agosto', 'setiembre', 'octubre', 'noviembre', 'diciembre']
    if word.lower() in months:
        return 'FEC'


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

        :param GroupAddExternalIdDetails val:
        :rtype: EventDetails
        """
    return cls('group_add_external_id_details', val)


@classmethod
def extract_error_message(cls, e):
    """Extract error message for queries"""
    message = str(e)
    try:
        if isinstance(e.args, tuple) and len(e.args) > 1:
            message = e.args[1]
    except Exception:
        pass
    return message


def SFANode_reduce_output_dim(sfa_node, new_output_dim, verbose=False):
    """ This function modifies an already trained SFA node (or GSFA node),
    reducing the number of preserved SFA features to new_output_dim features.
    The modification is done in place
    """
    if verbose:
        print('Updating the output dimensionality of SFA node')
    if new_output_dim > sfa_node.output_dim:
        er = 'Cannot increase the output dimensionality of the SFA node'
        raise ValueError(er)
    sfa_node.d = sfa_node.d[:new_output_dim]
    sfa_node.sf = sfa_node.sf[:, :new_output_dim]
    sfa_node._bias = sfa_node._bias[:new_output_dim]
    sfa_node._output_dim = new_output_dim


def binary_check(classes):
    """
    Check if the problem is a binary classification.

    :param classes:  all classes name
    :type classes : list
    :return: is_binary as bool
    """
    num_classes = len(classes)
    is_binary = False
    if num_classes == 2:
        is_binary = True
    return is_binary


@classmethod
def find(cls, db, name):
    """Find a user by name.
        Returns None if not found.
        """
    return db.query(cls).filter(cls.name == name).first()


def is_pubkey(p: str) ->bool:
    """
    determines if a string can be interpreted as btc hex formatted pubkey
    """
    prefix = p[0:2]
    try:
        bytes.fromhex(p)
    except ValueError:
        return False
    if len(p) == 66:
        return prefix in ['02', '03']
    if len(p) == 130:
        return prefix == '04'
    return False


def fix_caps(word):
    """Used to compare words, irrespective of their capitalisation

    :param word: the word to be fixed
    :type word: <str>
    :return: <str>
    """
    if word.isupper() and word != 'I':
        """eg: word -> 'AAA', result -> 'aaa'
        """
        word = word.lower()
    elif word[0].isupper():
        """eg: word -> 'AvA', result -> 'Ava'
        """
        word = word.lower().capitalize()
    else:
        """eg: word -> 'aVA', result -> 'ava'
        """
        word = word.lower()
    return word


def count_collisions(Collisions):
    """
    Counts the number of unique collisions and gets the collision index.

    Parameters
    ----------
    Collisions : array_like
        Array of booleans, containing true if during a collision event, false otherwise.

    Returns
    -------
    CollisionCount : int
        Number of unique collisions
    CollisionIndicies : list
        Indicies of collision occurance
    """
    CollisionCount = 0
    CollisionIndicies = []
    lastval = True
    for i, val in enumerate(Collisions):
        if val == True and lastval == False:
            CollisionIndicies.append(i)
            CollisionCount += 1
        lastval = val
    return CollisionCount, CollisionIndicies


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 is_number(s):
    """Tests if string "s" is a number."""
    try:
        float(s)
    except ValueError:
        return False
    return True


def metric_inc(key, value=1):
    """Increments the specified metric key value by the specified value.

    :param str|unicode key:

    :param int value:

    :rtype: bool
    """
    return False


def isdecimal(text):
    """
    Check if all characters in ``text`` are decimal characters and there is at least one character.

    Decimal characters are those that can be used to form integer numbers in base 10.
    For example, '10' has all decimals, but '1.0' does not (since the period is not a
    decimal). Formally a decimal character is in the Unicode General Category "Nd".

    :param text: The string to check
    :type text:  ``str``

    :return: True if all characters in ``text`` are decimal characters and there is at least one character, False otherwise.
    :rtype:  ``bool``
    """
    assert isinstance(text, str), '%s is not a string' % text
    return text.isdecimal()


def _zimbraAnnotatedTaskKey(username):
    """Returns the key for zimbra tasks annotations associated with a
    username."""
    return 'vnccollab.zimbra.related_zimbra_task.{0}'.format(username)


@classmethod
def get_backend(cls, backend=None):
    """Choose a backend instance.

        :param backend=None:  If provided, use this.

        ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

        :return:  Return backend if it is not None, otherwise try
                  to choose a reasonable bakend somehow.

        ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

        PURPOSE:  Sub-clases can override this to provide a default backend.
        """
    return backend


def main():
    """
    Just runs help if necessary
    """
    import __main__
    help(__main__)


def _while_loop(*data, **kwargs):
    """Run a while loop over with user-defined condition and computation

    From:src/operator/control_flow.cc:1151
    This function support variable length of positional input.

    Parameters
    ----------
    cond : Symbol
        Input graph for the loop condition.
    func : Symbol
        Input graph for the loop body.
    data : Symbol[]
        The input arrays that include data arrays and states.
    num_outputs : int, required
        The number of outputs of the subgraph.
    num_out_data : int, required
        The number of outputs from the function body.
    max_iterations : int, required
        Maximum number of iterations.
    cond_input_locs : tuple of <long>, required
        The locations of cond's inputs in the given inputs.
    func_input_locs : tuple of <long>, required
        The locations of func's inputs in the given inputs.
    func_var_locs : tuple of <long>, required
        The locations of loop_vars among func's inputs.

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

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


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


@classmethod
def supports_is_smartnic(cls):
    """Return whether is_smartnic field is supported.

        :returns: Whether is_smartnic field is supported
        :raises: ovo_exception.IncompatibleObjectVersion
        """
    return cls.supports_version((1, 9))


def strdict_to_dict(value):
    """
    Convert libcomps StrDict type object to standard dict.

    Args:
        value: a libcomps StrDict

    Returns:
        lang_dict: a dict

    """
    lang_dict = {}
    if len(value):
        for i, j in value.items():
            lang_dict[i] = j
    return lang_dict


def process_srv_record(template_record, zone_records):
    """
    Will process an srv record from a template.

    This results in marking zone_records for deletion, and returning the new record

    An srv record in the template will delete all existing srv records of the
    same name in the zone.
    """
    new_record = {'type': 'SRV', 'name': template_record['name'], 'data':
        template_record['target'], 'ttl': int(template_record['ttl']),
        'protocol': template_record['protocol'], 'service': template_record
        ['service'], 'priority': int(template_record['priority']), 'weight':
        int(template_record['weight']), 'port': int(template_record['port'])}
    for zone_record in zone_records:
        if zone_record['type'].upper() == 'SRV' and zone_record['name'].lower(
            ) == template_record['name'].lower(
            ) and '_replace' not in zone_record:
            zone_record['_delete'] = 1
    return new_record


def formatToAddressLength(format: str) ->int:
    """Return the length -in characters- that an address must have,
    according to a format"""
    if format == 'S19':
        return 4
    elif format == 'S28':
        return 6
    elif format == 'S37':
        return 8
    else:
        raise ValueError(
            'Invalid parameter in method formatToAddressLength: %s' % format)


def _poslist2wkt(poslist, axisorder):
    """Repurpose gml:posList into WKT aware list"""
    tmp = poslist.split()
    poslist2 = []
    xlist = tmp[1::2]
    ylist = tmp[::2]
    if axisorder == 'yx':
        for i, j in zip(ylist, xlist):
            poslist2.append('%s %s' % (i, j))
    else:
        for i, j in zip(xlist, ylist):
            poslist2.append('%s %s' % (i, j))
    return ', '.join(poslist2)


def tokenizeQuery(query):
    """Given a dictionary of {indexName: value} returns a dictionary of
        {indexname: token} appropriate for the search methods"""


def lcv(var, assignment, csp):
    """Least-constraining-values heuristic."""
    return sorted(csp.choices(var), key=lambda val: csp.nconflicts(var, val,
        assignment))


def encode(i: int) ->bytes:
    """Return the varint bytes encoding of an integer."""
    if i <= 252:
        return bytes([i])
    elif i <= 65535:
        return b'\xfd' + i.to_bytes(2, byteorder='little')
    elif i <= 4294967295:
        return b'\xfe' + i.to_bytes(4, byteorder='little')
    elif i <= 18446744073709551615:
        return b'\xff' + i.to_bytes(8, byteorder='little')
    else:
        raise ValueError(f'integer too large ({hex(i)}) for varint encoding')


def _copy_without_ignore_items(the_dict, ignored_keys=['ignore']):
    """
    get a copy of *the_dict* without entries having substring
    'ignore' in key
    """
    new_dict = {}
    for key, val in list(the_dict.items()):
        if key not in ignored_keys:
            new_dict[key] = val
    return new_dict


def delta3(a, b, c):
    """Delta function (3 variables)
    """
    if (a == b) & (b == c):
        return 1
    else:
        return 0


def is_url(url: str) ->bool:
    """Return True if a string is a URL.

    >>> is_url("")
    False
    >>> is_url("  ")
    False
    >>> is_url("http://example.com")
    True
    """
    return url.startswith('http')


def main():
    """health check for Monasca-notification"""
    return 0


@staticmethod
def custom_terminal_condition(old_info, new_info, oob) ->bool:
    """Calculate a new terminal condition using the info data."""
    return False


def _parse_testcase_record(testcase_record):
    """Parse testcase record and return it's info."""
    verdict = None
    verdict_found = False
    comment = ''
    properties = {}
    for element in testcase_record:
        if not verdict_found:
            if element.tag == 'error':
                verdict = 'failed'
                comment = element.get('message')
            elif element.tag == 'failure':
                verdict = 'failed'
                comment = element.get('message')
                verdict_found = True
            elif element.tag == 'skipped':
                verdict = 'skipped'
                comment = element.get('message')
                verdict_found = True
        if element.tag == 'properties':
            for prop in element:
                properties[prop.get('name')] = prop.get('value')
    if not verdict:
        verdict = 'passed'
    return verdict, comment, properties


def load_handlers(name):
    """Load the (URL pattern, handler) tuples for each component."""
    mod = __import__(name, fromlist=['default_handlers'])
    return mod.default_handlers


def avail_mem_sat(gpu, mem):
    """ Return true if there is at least mem available memory """
    avail_mem = float(gpu.entry['memory.total']) - float(gpu.entry[
        'memory.used'])
    return mem <= avail_mem


def get_fields(realm):
    """ Returns fields (table columns)
            Format: ( {Field:Label, Field:Label, ...}, (DEFAULT list) )
        """
    pass


def get_reciprocal_hits():
    """Checks if candidate is reciprocal best blast hit with gene

    returns: list with reciprocal hits"""
    reciprocal = {}
    proccesed = set()
    for line in open('tmp/dataset_diamond.res'):
        sline = line.split('\t')
        full_name = sline[0]
        sequence, gene = full_name.split('@')
        sequence = sequence[:-4]
        if sequence not in proccesed:
            proccesed.add(sequence)
            hit_gene = sline[1]
            reciprocal[sequence] = hit_gene
    return reciprocal


def is_index(board, location):
    """
    Check whether a location is a valid index of the board

    Parameters:
    ----
    board : np.array
    location : np.array

    Returns
    ----
    is_index : bool
    """
    if len(location) != 2:
        return False
    x, y = location
    return x in range(board.shape[0]) and y in range(board.shape[1])


@staticmethod
def item(index):
    """Provides a reference to an item"""
    if not index.isValid():
        return None
    return index.internalPointer()


@staticmethod
def create():
    """ Creates a specific built-in call. Currently just an
            empty stub. """
    return None


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

        :param TeamMergeRequestCanceledShownToSecondaryTeamDetails val:
        :rtype: EventDetails
        """
    return cls('team_merge_request_canceled_shown_to_secondary_team_details',
        val)


def calculateKey(cls, target):
    """Calculate the reference key for this reference

        Currently this is a two-tuple of the id()'s of the
        target object and the target function respectively.
        """
    return id(target.__self__), id(target.__func__)


def combine(iterable, separator):
    """Join ``iterable`` (filtering out its items that evaluate to
    ``Ǹone``) using ``separator``

    :argument iterable: Iterable to filter and join
    :type iterable: iterable

    :argument separator: Separator to join with
    :type separator: str

    :returns: Joined string
    :rtype: str

    >>> combine(['Foo', '', 'Bar', None, 'Xyz', 0], '/')
    'Foo/Bar/Xyz'

    """
    return separator.join(filter(None, iterable))


def calculate_interval(start_time, end_time, deltas=None):
    """Calculates wanted data series interval according to start and end times

    Returns interval in seconds
    :param start_time: Start time in seconds from epoch
    :param end_time: End time in seconds from epoch
    :type start_time: int
    :type end_time: int
    :param deltas: Delta configuration to use. Defaults hardcoded if no
      configuration is provided
    :type deltas: dict(max time range of query in seconds: interval to use
      in seconds)

    :rtype: int - *Interval in seconds*
    """
    time_delta = end_time - start_time
    deltas = deltas if deltas else {(900): 10, (1800): 30, (259200): 60, (
        604800): 300, (1209600): 600, (2419200): 900, (4838400): 1800, (
        9676800): 3600, (31536000): 7200, (126144000): 43200}
    for delta in sorted(deltas.keys()):
        if time_delta <= delta:
            return deltas[delta]
    return 86400


def format_search_key(key):
    """Currency names are unfortunately not all directly mappable."""
    key = key.lower()
    key = key.replace('(the)', '')
    key = key.strip()
    return key


def _modified_shepp_logan_ellipsoids(ellipsoids):
    """Modify ellipsoids to give the modified Shepp-Logan phantom.

    Works for both 2d and 3d.
    """
    intensities = [1.0, -0.8, -0.2, -0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
    intensities[2] += 5e-17
    intensities[3] += 5e-17
    assert len(ellipsoids) == len(intensities)
    for ellipsoid, intensity in zip(ellipsoids, intensities):
        ellipsoid[0] = intensity


def lambd_tris_Mg_GT17simopt(T, P):
    """n-c: tris magnesium [GT17simopt]."""
    lambd = -0.14505
    valid = T == 298.15
    return lambd, valid


def vertex_group_assign_new():
    """Assign the selected vertices to a new vertex group

    """
    pass


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 quick_stats(x, digits=3):
    """Quick wrapper to get mean and standard deviation of a tensor.

    Parameters
    ----------
    x: torch.Tensor
    digits: int
        Number of digits to round mean and standard deviation to.

    Returns
    -------
    tuple[float]
    """
    return round(x.mean().item(), digits), round(x.std().item(), digits)


def SetRecommendedRenderSettings(view):
    """
    Set view settings to enable smooth interaction with the rendering widget.
    Disables interactor-based render calls and forces server-side rendering.

    Parameters
    ----------
    view: paraview.servermanager.RenderView
    """
    view.EnableRenderOnInteraction = 0
    view.RemoteRenderThreshold = 0


def publish(nodeIdentifier, items, requestor):
    """ Publish items to a pubsub node.

        @return: a deferred that fires when the items have been published.
        @rtype: L{Deferred<twisted.internet.defer.Deferred>}
        """


def get_input(question, response_format, error_message):
    """ loops until a response that is in response_format is met"""
    while True:
        res = input(question)
        if res in response_format:
            return res
        print(error_message)


def dict_dropdown(dict_to_display, title='Dictionary Contents'):
    """Display the model_params dictionary as a dropdown menu."""
    from ipywidgets import interact
    from IPython.display import display
    from pprint import pprint
    dash = '---'
    print(f'{dash * 4} {title} {dash * 4}')

    @interact(dict_to_display=dict_to_display)
    def display_params(dict_to_display=dict_to_display):
        display(pprint(dict_to_display))
        return


def fetch_data():
    """
        Fetches a table from the Export API.
        """
    raise NotImplementedError()


@classmethod
def format_block(cls, block_desc):
    """Check block type and delegate to correct formatter"""
    if block_desc['block_type'] is 'file':
        return cls.format_file_header(block_desc)
    raise ValueError('Undefined block type:', block_desc['block_type'])


def recf_legendre_poly(result, x, special, n, cur_var, pos):
    """Implementation of the recursion formula for Legendre polynomials.
    The recursion formula is Bonnet's recursion formula
    P_n = (2n-1)/n * x * P_ {n-1}  - (n-1)* P_{n-2}.

        .. note::

        The procedure on how an recursion function is built can be found in the
        docstring of the recursion function for
        standard polynomials *recf_standard_poly*.

    :param result: Contains the observations along the first dimension
        and the function values of expansion w.r.t. an observation
        along the second dimension.
    :type result: numpy.ndarray

    :param x: The data to be expanded.
    :type x: numpy.ndarray

    :param special: Index of a special element to be considered in the
        recursion formula. In this case the special element is the
        first order Legendre polynomial of the current variable.
    :type special: int

    :param n: The order of the function to be computed at this step.
    :type n: int

    :param cur_var: The index of the current variable to be considered in the
        recursion. This value will have to be lower than x.shape[1].
    :type cur_var: int

    :param pos: The index of the element to be computed, along the second
        dimension of result.
    :type int: int

    :returns: The vectorized result (along the observations) of the
        n-th recursion step of the cur_var-th variable.
    :rtype: numpy.ndarray

    .. admonition:: Reference

        https://en.wikipedia.org/wiki/Legendre_polynomials
    """
    return (2.0 * n - 1.0) / n * result[:, (special)] * result[:, (pos - 1)
        ] - (n - 1.0) / n * result[:, (pos - 2)]


def _to_ndimage_mode(mode):
    """Convert from `numpy.pad` mode name to the corresponding ndimage mode."""
    mode_translation_dict = dict(edge='nearest', symmetric='reflect',
        reflect='mirror')
    if mode in mode_translation_dict:
        mode = mode_translation_dict[mode]
    return mode


def rev(node):
    """Obtain the revision number given a binary node.

        Raises ``error.LookupError`` if the node is not known.
        """


@classmethod
def update(cls, domain, source, dest_add, dest_del):
    """Update a domain mail forward destinations."""
    result = None
    if dest_add or dest_del:
        current_destinations = cls.get_destinations(domain, source)
        fwds = current_destinations[:]
        if dest_add:
            for dest in dest_add:
                if dest not in fwds:
                    fwds.append(dest)
        if dest_del:
            for dest in dest_del:
                if dest in fwds:
                    fwds.remove(dest)
        if len(current_destinations) != len(fwds
            ) or current_destinations != fwds:
            cls.echo('Updating mail forward %s@%s' % (source, domain))
            options = {'destinations': fwds}
            result = cls.call('domain.forward.update', domain, source, options)
    return result


def assert_utility_signal(library, session, line):
    """Asserts or deasserts the specified utility bus signal.

    Corresponds to viAssertUtilSignal function of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :param line: specifies the utility bus signal to assert. (Constants.UTIL_ASSERT*)
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    return library.viAssertUtilSignal(session, line)


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

    The ".dev0" means dirty.

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


def weekday():
    """Return the day of the week as an integer.

        Monday is 0 and Sunday is 6. The same as self.date().weekday().
        See also isoweekday().
        """


def where(query):
    """
    Simply returns the given query to the scope builder. Useful when you need
    to combine arbritary query elements with other scopes.
    """
    return query


@staticmethod
def _verify(start, end):
    """Throws ValueError if the range is not consistent."""
    if start > end:
        raise ValueError('start %s must not be greater than end %s' % (
            start, end))


def ucfirst(msg):
    """Return altered msg where only first letter was forced to uppercase."""
    return msg[0].upper() + msg[1:]


@classmethod
def get_file_types(cls, request=None):
    """
        Return a list of all registered data providers' codes and titles
        :param request: The current HttpRequest
        :return: list
        """
    return cls.get(request, f'/sources/api/file/type')


@staticmethod
def from_private_key(private_key):
    """ Generates a public key object from a PrivateKey object.

        Args:
            private_key (PrivateKey): The private key object from
               which to derive this object.

        Returns:
            PublicKey: A PublicKey object.
        """
    return private_key.public_key


def s3_build_path(bucket, key):
    """ Build the full path to the file """
    return 's3://{}/{}'.format(bucket, key)


def load(dbref):
    """Load the object from PostGreSQL/JSONB by using its DBRef.

        Note: The returned object is in the ghost state.
        """


def __init__(context, request, field):
    """
        adapts context/request and field because query params might affect how we render
        """


def get_requires_for_build_sdist(config_settings=None):
    """Returns a list of requirements for building, as strings"""
    return []


@classmethod
def get_all_connected_probes(cls):
    """! @brief Returns a list of DebugProbe instances."""
    raise NotImplementedError()


def convert_permalink_sign(doc, repl=''):
    """Change permalink sign to some text (``'repl'``).

    Most python documents use this (``U+00B6`` or ``pilcrow sign`` or '¶').
    On pdf, these marks are always visible, rather noisy.

    cf. in sample css, 'headerlink' is already made invisible ('display:none;').

    >>> el = fromstring(r'

tosixinch¶

')  # noqa: E501
    >>> convert_permalink_sign(el, '\\u2026')
    >>> tostring(el)
    '

tosixinch…

'
    """
    for el in doc.xpath('//a[@class="headerlink"]'):
        if el.text == '¶':
            el.text = repl


def _create_dummy_frequencies(trips):
    """Create station stop frequencies."""
    for trip in trips:
        yield {'trip_id': trip['trip_id'], 'start_time': '04:30:00',
            'end_time': '08:30:00', 'headway_secs': '1200'}
        yield {'trip_id': trip['trip_id'], 'start_time': '08:30:00',
            'end_time': '20:30:00', 'headway_secs': '1800'}
        yield {'trip_id': trip['trip_id'], 'start_time': '20:30:00',
            'end_time': '25:30:00', 'headway_secs': '2800'}


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 iformat(i):
    """
    Format an integer with commas deliminating every factor of 1000
    """
    import locale
    locale.setlocale(locale.LC_ALL, 'en_US')
    return locale.format('%d', i, grouping=True)


def create_api_routing(config, api):
    """
    Central method to create the routing per api. This way a independent routing is created which takes even
    the route prefix into account.

    Args:
        config (pyramid.config.Configurator): The pyramid apps config object
        api (pyramid_georest.lib.rest.Api): The Api which the routing is bound to.
    """
    config.add_route('{api_name}/read'.format(api_name=api.name), '/' + api
        .pure_name + '/{schema_name}/{table_name}/read/{format}')
    config.add_view(api, route_name='{api_name}/read'.format(api_name=api.
        name), attr='read', request_method=(api.read_method, api.
        read_filter_method))
    config.add_route('{api_name}/count'.format(api_name=api.name), '/' +
        api.pure_name + '/{schema_name}/{table_name}/count')
    config.add_view(api, route_name='{api_name}/count'.format(api_name=api.
        name), attr='count', request_method=(api.read_method, api.
        read_filter_method), renderer='string')
    config.add_route('{api_name}/show'.format(api_name=api.name), '/' + api
        .pure_name + '/{schema_name}/{table_name}/read/{format}/*primary_keys')
    config.add_view(api, route_name='{api_name}/show'.format(api_name=api.
        name), attr='show', request_method=api.read_method)
    config.add_route('{api_name}/create'.format(api_name=api.name), '/' +
        api.pure_name + '/{schema_name}/{table_name}/create/{format}')
    config.add_view(api, route_name='{api_name}/create'.format(api_name=api
        .name), attr='create', request_method=api.create_method)
    config.add_route('{api_name}/update'.format(api_name=api.name), '/' +
        api.pure_name +
        '/{schema_name}/{table_name}/update/{format}/*primary_keys')
    config.add_view(api, route_name='{api_name}/update'.format(api_name=api
        .name), attr='update', request_method=api.update_method)
    config.add_route('{api_name}/delete'.format(api_name=api.name), '/' +
        api.pure_name +
        '/{schema_name}/{table_name}/delete/{format}/*primary_keys')
    config.add_view(api, route_name='{api_name}/delete'.format(api_name=api
        .name), attr='delete', request_method=api.delete_method)
    config.add_route('{api_name}/model'.format(api_name=api.name), '/' +
        api.pure_name + '/{schema_name}/{table_name}/model/{format}')
    config.add_view(api, route_name='{api_name}/model'.format(api_name=api.
        name), attr='model', request_method=api.read_method)
    config.add_route('{api_name}/adapter'.format(api_name=api.name), '/' +
        api.pure_name + '/{schema_name}/{table_name}/adapter/{format}')
    config.add_view(api, route_name='{api_name}/adapter'.format(api_name=
        api.name), attr='adapter', request_method=api.read_method)
    config.commit()


def _clean_win_chars(string):
    """Windows cannot encode some characters in filename."""
    import urllib
    if hasattr(urllib, 'quote'):
        quote = urllib.quote
    else:
        import urllib.parse
        quote = urllib.parse.quote
    for char in ('<', '>', '!', ':', '\\'):
        string = string.replace(char, quote(char))
    return string


def p_cdtextfile(t):
    """cdtextfile : CDTEXTFILE STRING"""
    t[0] = 'cdtextfile', t[2]


@classmethod
def shorten_id(cls, internal_id):
    """
        Returns the shortcode for a numeric media PK

        :param internal_id: numeric ID value
        :return:
        """
    return cls._encode(internal_id)


def set_gdcmconv_path(path):
    """
    Set where the filepath to the gdcmconv executable (needed is it is not found in your PATH)

    :param path: the file path to the gdcmconv executable
    """
    global gdcmconv_path
    gdcmconv_path = path