def parse_warning_code(warning_code, quiet=False, return_dict=False):
    """Parses warning code from `check_all_diagnostics()` into
    individual failures and prints results.

    Parameters
    ----------
    warning_code : int
        When converted to binary, each digit in the code stands for
        whether or not a test passed. A digit of zero indicates the test
        passed. The ordering of the tests goes:
            ESS
            r_hat
            divergences
            tree depth
            E-BFMI
        For example, a warning code of 12 has a binary representation
        of 01100, which means that R-hat and divergences tests failed.
    quiet : bool, default False
        If True, suppress print results to the screen.
    return_dict : bool, default False
        If True, return a dictionary of containing test passage info.

    Returns
    -------
    output : dict
        If `return_dict` is True, returns a dictionary where each entry
        is True is the respective diagnostic check was passed and False
        if it was not.
    """
    if quiet and not return_dict:
        raise RuntimeError('`quiet` is True and `return_dict` is False, ' +
            'so there is nothing to do.')
    passed_tests = dict(neff=True, rhat=True, divergence=True, treedepth=
        True, energy=True)
    if warning_code & 1 << 0:
        passed_tests['neff'] = False
        if not quiet:
            print('ESS warning')
    if warning_code & 1 << 1:
        passed_tests['rhat'] = False
        if not quiet:
            print('Rhat warning')
    if warning_code & 1 << 2:
        passed_tests['divergence'] = False
        if not quiet:
            print('divergence warning')
    if warning_code & 1 << 3:
        passed_tests['treedepth'] = False
        if not quiet:
            print('treedepth warning')
    if warning_code & 1 << 4:
        passed_tests['energy'] = False
        if not quiet:
            print('energy warning')
    if warning_code == 0:
        if not quiet:
            print('No diagnostic warnings')
    if return_dict:
        return passed_tests


def _prepare_input(message, default=None):
    """
	Used to prepare input string
	"""
    if default is not None:
        message = message + ' [' + str(default) + ']: '
        return message
    return message + ' : '


@staticmethod
def import_module(module):
    """
		Imports module by name
		"""
    d = module.rfind('.')
    modulename = module[d + 1:len(module)]
    mod = __import__(module, globals(), locals(), [modulename])
    return mod


def obsfateverb(successorset, markers):
    """ Return the verb summarizing the successorset and potentially using
    information from the markers
    """
    if not successorset:
        verb = b'pruned'
    elif len(successorset) == 1:
        verb = b'rewritten'
    else:
        verb = b'split'
    return verb


def transmute(schema, **kw):
    """
        translates the schema and returns the translation.

        translations and kw are specific to the translation being performed.
        """


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

        :param UserLogInfo val:
        :rtype: ActorLogInfo
        """
    return cls('admin', val)


def _make_sentinel(name, reprstring, docstring, truthy=True):
    """Return a new object instance to use as a sentinel to represent
    an entity that cannot be used directly because of some logical
    reason or implementation detail.

    * Query uses a sentinel for the result data when optimizing
      queries because the result does not exist until the query
      is actually executed.
    * _get_error() uses a sentinel to build an appropriate error
      when objects normally required for processing are not found.
    * DataError uses a sentinel to compare float('nan') objects
      because they are not considered to be equal when directly
      compared.
    """
    cls_dict = {'__repr__': lambda self: reprstring, '__doc__': docstring}
    if not truthy:
        cls_dict['__bool__'] = lambda self: False
        cls_dict['__nonzero__'] = lambda self: False
    return type(name, (object,), cls_dict)()


def Nu_cylinder_Churchill_Bernstein(Re, Pr):
    """Calculates Nusselt number for crossflow across a single tube
    at a specified `Re` and `Pr`, both evaluated at the film temperature. No
    other wall correction is necessary for this formulation. Method is
    shown without modification in [2]_ and many other texts.

    .. math::
        Nu_D = 0.3 + \\frac{0.62 Re_D^{0.5} Pr^{1/3}}{[1 + (0.4/Pr)^{2/3}
        ]^{0.25}}\\left[1 + \\left(\\frac{Re_D}{282000}\\right)^{5/8}\\right]^{0.8}

    Parameters
    ----------
    Re : float
        Reynolds number with respect to cylinder diameter, [-]
    Pr : float
        Prandtl number at film temperature, [-]

    Returns
    -------
    Nu : float
        Nusselt number with respect to cylinder diameter, [-]

    Notes
    -----
    May underestimate heat transfer in some cases, as it the formula is
    described in [1]_ as "appears to provide a lower bound for RePr > 0.4".
    An alternate exponent for a smaller range is also presented in [1]_.

    This method applies to both the laminar and turbulent regimes.

    Examples
    --------
    Example 7.3 in [2]_, matches.

    >>> Nu_cylinder_Churchill_Bernstein(6071, 0.7)
    40.63708594124974

    References
    ----------
    .. [1] Churchill, S. W., and M. Bernstein. "A Correlating Equation for
       Forced Convection From Gases and Liquids to a Circular Cylinder in
       Crossflow." Journal of Heat Transfer 99, no. 2 (May 1, 1977):
       300-306. doi:10.1115/1.3450685.
    .. [2] Bergman, Theodore L., Adrienne S. Lavine, Frank P. Incropera, and
       David P. DeWitt. Introduction to Heat Transfer. 6E. Hoboken, NJ:
       Wiley, 2011.
    """
    return 0.3 + 0.62 * Re ** 0.5 * Pr ** (1 / 3.0) / (1 + (0.4 / Pr) ** (2 /
        3.0)) ** 0.25 * (1 + (Re / 282000.0) ** 0.625) ** 0.8


@classmethod
def get(cls, iterable, **kwargs) ->list:
    """Gets items from the list with the attributes specified.

        Parameters
        ----------
        iterable : list
            The iterable to loop over
        """
    output = []
    for i in iterable:
        for attr in kwargs:
            if not hasattr(i, attr) or getattr(i, attr) != kwargs[attr]:
                i = False
                break
        if i is not False:
            output.append(i)
    return output


def G_matrix(q, r, contrast, FFfxn, Volfxn, args=()):
    """Calculates the response matrix :math:`G(Q,r)`

    :param float q: :math:`Q`
    :param float r: :math:`r`
    :param float contrast: :math:`|\\Delta\\rho|^2`, the scattering contrast
    :param function FFfxn: form factor function FF(q,r,args)
    :param function Volfxn: volume function Vol(r,args)
    :returns float: G(Q,r)
    """
    FF = FFfxn(q, r, args)
    Vol = Volfxn(r, args)
    return 0.0001 * (contrast * Vol * FF ** 2).T


def subst_quoted_strings(sql, params):
    """Reverse operation to mark_quoted_strings - substitutes '@' by params.
    """
    parts = sql.split('@')
    params_dont_match = (
        "number of parameters doesn' match the transformed query")
    assert len(parts) == len(params) + 1, params_dont_match
    out = []
    for i, param in enumerate(params):
        out.append(parts[i])
        out.append("'%s'" % param.replace('\\', '\\\\').replace("'", "\\'"))
    out.append(parts[-1])
    return ''.join(out)


def owner_info():
    """Get ownership info for display
        """


def connectSSL(host, port, factory, contextFactory, timeout=30, bindAddress
    =None):
    """
        Connect a client Protocol to a remote SSL socket.

        @param host: a host name

        @param port: a port number

        @param factory: a L{twisted.internet.protocol.ClientFactory} instance

        @param contextFactory: a L{twisted.internet.ssl.ClientContextFactory} object.

        @param timeout: number of seconds to wait before assuming the
                        connection has failed.

        @param bindAddress: a (host, port) tuple of local address to bind to,
                            or C{None}.

        @return: An object which provides L{IConnector}.
        """


@classmethod
def from_api_data(cls, data):
    """Convert data from the API into a native object.

        Args:
            data (dict): API data describing a currency.

        Returns:
            :class:`Currency <pyticketswitch.currency.Currency>`: the currency.

        """
    kwargs = {'factor': data.get('currency_factor'), 'places': data.get(
        'currency_places'), 'number': data.get('currency_number'),
        'pre_symbol': data.get('currency_pre_symbol'), 'post_symbol': data.
        get('currency_post_symbol')}
    return cls(data.get('currency_code'), **kwargs)


def _displayExerciseDetails(response, namespace):
    """Write the exercise details to the console.

    """
    title = response['title']
    line = '=' * len(title)
    header = '\n'.join([line, title, line])
    content = '\n\n' + header + '\n\n' + response['description']
    namespace['manhole'].overwriteLine(content.encode('utf-8'))


@classmethod
def configure(cls, **kwargs):
    """ This function gets called with the per-provider configuration
        defined in onegov.yml. Authentication providers may optionally
        access these values.

        The return value is either a provider instance, or none if the
        provider is not available.

        """
    return cls()


def equal(seq):
    """Determine whether a sequence holds identical elements.
    """
    return len(set(seq)) <= 1


def sync_table_options(from_table, to_table, sync_auto_inc=False,
    sync_comments=False):
    """Generate the SQL statements needed to modify the Table options
       of the target table (patch), and restore them to their previous
       definition (revert)

    Args:
       from_table: A SchemaObject TableSchema Instance.
       to_table: A SchemaObject TableSchema Instance.
       sync_auto_inc: Bool, sync the tables auto increment value?
       sync_comments: Bool, sync the tbales comment field?

    Returns:
       A tuple (patch, revert) containing the SQL statements.
       A tuple of empty strings will be returned if no changes were found
    """
    p = []
    r = []
    for opt in from_table.options:
        if (opt == 'auto_increment' and not sync_auto_inc or opt ==
            'comment' and not sync_comments):
            continue
        if from_table.options[opt] != to_table.options[opt]:
            p.append(from_table.options[opt].create())
            r.append(to_table.options[opt].create())
    if p:
        return ' '.join(p), ' '.join(r)
    else:
        return '', ''


def _format_servers_list_networks(networks):
    """Return a formatted string of a server's networks

    :param networks: a Server.networks field
    :rtype: a string of formatted network addresses
    """
    output = []
    for network, addresses in networks.items():
        if not addresses:
            continue
        addresses_csv = ', '.join(addresses)
        group = '%s=%s' % (network, addresses_csv)
        output.append(group)
    return '; '.join(output)


def to_polar(RAa, RAb, Deca, Decb):
    """ Converts RA/Dec [deg] of two binary components into separation and position angle of B relative
        to A [mas, deg]
    """
    import numpy as np
    import astropy.units as u
    dRA = (RAb - RAa) * np.cos(np.radians(np.mean([Deca, Decb])))
    dRA = (dRA * u.deg).to(u.mas)
    dDec = Decb - Deca
    dDec = (dDec * u.deg).to(u.mas)
    r = np.sqrt(dRA ** 2 + dDec ** 2)
    p = (np.degrees(np.arctan2(dDec.value, -dRA.value)) + 270.0) % 360.0
    p = p * u.deg
    return r, p


def first(iterable, default=None):
    """Return the first element of an iterable or the next element of a generator; or default."""
    try:
        return iterable[0]
    except IndexError:
        return default
    except TypeError:
        return next(iterable, default)


def p_param_byval_definition(p):
    """ param_definition : BYVAL param_def
    """
    p[0] = p[2]
    if p[0] is not None:
        p[0].byref = False


def drift_forecast(submodel, horizon):
    """Computing the forecast for the drift model

    """
    points = []
    for h in range(horizon):
        points.append(submodel['value'] + submodel['slope'] * (h + 1))
    return points


@classmethod
def _parse_db_lib(cls, library):
    """
        Returns the canonical (database_name, library) for the passed in
        string 'library'.
        """
    database_name = library.split('.', 2)
    if len(database_name) == 2:
        library = database_name[1]
        if database_name[0].startswith(cls.DB_PREFIX):
            database_name = database_name[0]
        else:
            database_name = cls.DB_PREFIX + '_' + database_name[0]
    else:
        database_name = cls.DB_PREFIX
    return database_name, library


def setLocallyAllowedTypes(types):
    """
        Set a list of type ids which should be allowed. This must be a
        subset of the type's FTI-set allowable types. This list only comes
        into effect when the restrictions mode is 1 (enabled).
        """


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 select_link_viewer(NODE_OT_select=None, NODE_OT_link_viewer=None):
    """Select node and link it to a viewer node

    :param NODE_OT_select: Select, Select the node under the cursor
    :param NODE_OT_link_viewer: Link to Viewer Node, Link to viewer node
    """
    pass


def manhattan_distance(point_a, point_b):
    """
    return Manhattan distance between to points

    :param point_a:
    :param point_b:
    :return: Manhattan distance between to points
    """
    x1, y1 = point_a
    x2, y2 = point_b
    return float(abs(x1 - x2) + abs(y1 - y2))


@classmethod
def should_notify(cls, instance, action):
    """ Should the given instance send out a change notification. This can be used to limit publishes to only specific instances.

        :param instance: Model instance
        :param action:   Action that triggered the notification (created, saved, deleted)
        :rtype: bool
        """
    return True


def efit_transform(object, data):
    """Fit-Transform an object on data."""
    return object.fit_transform(data)


def get_optarg(arglist, *opts, default=False):
    """Gets an optional command line argument and returns its value.

    If default is not set, the flag is treated as boolean. Note that
    that setting default to None or '' will still take an argument
    after the flag.

    Parameters
    ----------
    arglist : array_like
        The command line argument list to be parsed.
    opts : list
        The arguments searched for in arglist.
    default : str or bool
        The default value if opts are not found in arglist. If default
        is False (default), then True is returned if opts are found.

    Returns
    -------
    str or bool
        The argument value in arglist or its default value.
    """
    for op in opts:
        if op in arglist:
            ind = arglist.index(op)
            arglist.remove(op)
            if default is False:
                return True
            else:
                return arglist.pop(ind)
    return default


def asbool(value, true=(b'true', u'true'), false=(b'false', u'false')):
    """Return string as bool if possible, else raise TypeError.

    >>> asbool(b' False ')
    False

    """
    value = value.strip().lower()
    if value in true:
        return True
    if value in false:
        return False
    raise TypeError()


def _add_doc(func, doc):
    """Add documentation to a function."""
    func.__doc__ = doc


def options(configuration):
    """ A single place to add program options """
    configuration.add_option('host', env_variable='MBOOT_HOST', default=
        '127.0.0.1', help_string='The host address to bind to')
    configuration.add_option('port', env_variable='MBOOT_PORT', default=
        5000, special_type=int, help_string='The port to bind to')
    configuration.add_option('inventory.inventory_router',
        '--inventory-router', default='tcp://127.0.0.1:9000', help_string=
        'The inventory router url')
    configuration.add_option('logging.log_file', default='mercury-boot.log',
        help_string='The log file path')
    configuration.add_option('logging.level', default='DEBUG', help_string=
        'The app log level')
    configuration.add_option('agent.file_server_url', required=True,
        help_string='The file server path containing agent boot files')
    configuration.add_option('agent.kernel', default='vmlinuz', help_string
        ='The agent kernel')
    configuration.add_option('agent.initrd', default='initrd', help_string=
        'The agent initial ram file system')
    configuration.add_option('agent.rootfs_option', help_string=
        'The kernel command line option used by the initrd to find the root file system'
        , required=True)
    configuration.add_option('agent.file_system', default=
        'mercury-agent.sqfs', help_string='The agent file system')
    configuration.add_option('agent.kernel_options', default='',
        help_string='Kernel options for the agent environment')
    configuration.add_option('agent.backend_url_cmdline', help_string=
        'Provide an alternative backend url. This will be appended to the agent kernel command line, overriding the configuration baked into the image'
        )
    configuration.add_option('agent.log_service_cmdline', help_string=
        'Provide an alternative log service url. This will be appended to the agent kernel command line, overriding the configuration baked into the image'
        )


def set_node(evaluate, set_name, context):
    """A node that sets a parameter in the context."""
    set_name(context, evaluate(context))


def generate_fluctuations_resample_filter(fs_desired, fs, ntaps, speed,
    correlation_length, state, window=None):
    """Generate fluctuations.

    .. note:: This function applies change of relative speed by updating the impulse response of the filter by resampling the initial frequency response.
    """
    return NotImplemented


def create_choice_attribute(creator_type, value, choice_entry):
    """Create an instance of a subclass of ChoiceAttributeMixin for the given value.

    Parameters
    ----------
    creator_type : type
        ``ChoiceAttributeMixin`` or a subclass, from which we'll call the ``get_class_for_value``
        class-method.
    value : ?
        The value for which we want to create an instance of a new subclass of ``creator_type``.
    choice_entry: ChoiceEntry
        The ``ChoiceEntry`` instance that hold the current value, used to access its constant,
        value and display name.

    Returns
    -------
    ChoiceAttributeMixin
        An instance of a subclass of ``creator_type`` for the given value

    """
    klass = creator_type.get_class_for_value(value)
    return klass(value, choice_entry)


def intent_not_recognized(method):
    """Apply this decorator to a method of class :class:`.HermesSnipsComponent`
    to register it as a callback to be triggered when the dialogue manager
    doesn't recognize an intent.
    """
    method.intent_not_recognized = True
    return method


def add_operator(_index, _operator):
    """Adds a an operator if index > 0, used in loops when making conditions."""
    if _index > 0:
        return ' ' + _operator + ' '
    else:
        return ''


def _create_json(name, description, locked, connection):
    """
    Create a JSON to be used for the REST API call
    """
    json = {'connection': connection, 'type': 'ws', 'name': name,
        'description': description, 'locked': locked}
    return json


def dict_from_items_with_values(*dictionaries, **items):
    """Creates a dict with the inputted items; pruning any that are `None`.

    Args:
        *dictionaries(dict): Dictionaries of items to be pruned and included.
        **items: Items to be pruned and included.

    Returns:
        dict: A dictionary containing all of the items with a 'non-None' value.

    """
    dict_list = list(dictionaries)
    dict_list.append(items)
    result = {}
    for d in dict_list:
        for key, value in d.items():
            if value is not None:
                result[key] = value
    return result


def __leader(d, reclen):
    """ Unpack the leader into its separate values. """
    return reclen, d[0], d[1], d[2], d[3], d[4], int(d[5]), int(d[6]), int(d
        [7:12]), d[12], d[13], d[14], int(d[15]), int(d[16]), int(d[17]), int(d
        [18])


def get_all_peerids():
    """Return a frozenset of all peerids to whom we have a connection (to
        one or more services) established. Mostly useful for unit tests."""


def _local_parse_args(args):
    """Parse arguments for forked processes using multiprocessing."""
    nworkers = args.nworkers or 4
    libE_specs = {'nworkers': nworkers, 'comms': 'local'}
    return nworkers, True, libE_specs, args.tester_args


@staticmethod
def save(filename):
    """
        ``save <file_name>``

        saves the history of typed commands
        dummy way to save/load workspace state

        e.g.::

            save my_setup

        .. note::

            Not implemented yet
        """
    return 'save {}'.format(filename)


@classmethod
def _make_username(cls, username):
    """
        Slugify the username and replace - with _ to meet username requirements
        """
    from django.template.defaultfilters import slugify
    from unidecode import unidecode
    slugified_name = slugify(unidecode(username)).replace('-', '_')
    slugified_name = slugified_name[:30]
    if len(username) < 4:
        slugified_name = None
    return slugified_name


def multires_base_apply(modifier: str=''):
    """Modify the base mesh to conform to the displaced mesh

    :param modifier: Modifier, Name of the modifier to edit
    :type modifier: str
    """
    pass


def print_topic_words(topic_model):
    """ Print words corresponding to topic modelling

    Parameters
    ----------
    topic_model : :obj:`gensim model`
            topic model

    Returns
    -------
        None
    """
    for idx, topic in topic_model.print_topics(-1):
        print('Topic: {} \n Words: {}'.format(idx, topic))
    return None


def extract_ids(id_dict):
    """Extract the inner `ids` dict out of trakt JSON responses and insert them
    into the containing `dict`. Then return the input `dict`
    """
    id_dict.update(id_dict.pop('ids', {}))
    return id_dict


def get_bbox(geo_pd):
    """Gets the bounding box of a geopandas dataframe

    Args:
        geo_pd (geopandas): shape from which we can get the bounding box as a basis for the extend of the meshgrid

    Return:
        (tuple of floats): bbox (x_min, y_min, x_max, y_max)
    """
    return geo_pd.total_bounds[0], geo_pd.total_bounds[1], geo_pd.total_bounds[
        2], geo_pd.total_bounds[3]


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

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

    """
    pass


def close_and_commit(session):
    """
    Commit changes to the DB and close out DB cursor.
    """
    session.commit()
    session.close()


def apply_matrix_norm(m, v):
    """Equivalent to apply_matrix_pt(M, (p,q)) - apply_matrix_pt(M, (0,0))"""
    a, b, c, d, e, f = m
    p, q = v
    return a * p + c * q, b * p + d * q


def with_leading_upper(example):
    """
    Changes the leading letter of the text of example `example` to uppercase.
    """
    text = example.text
    for i, c in enumerate(text):
        if not c.isspace():
            text = text[:i] + text[i].upper() + text[i + 1:]
            break
    example.text = text
    return example


def find_section(section, lines):
    """
    Find a named section in a ``numpy``-formatted docstring.

    Parameters
    ----------
    section : string
        The name of the section to find

    lines : array of string
        The docstring, split into lines

    Returns
    -------
    int, int
        The indices of the first and last lines of the section.
    """
    first_line = None
    for i, line in enumerate(lines):
        if '----' in line and i > 0 and section in lines[i - 1]:
            first_line = i + 1
            break
    if first_line is None:
        return None, None
    last_line = None
    for i in range(first_line, len(lines)):
        if '---' in lines[i]:
            last_line = i - 2
            break
    if last_line is None:
        last_line = len(lines) - 1
    return first_line, last_line


def select_first(only_selected_strokes: bool=False, extend: bool=False):
    """Select first point in Grease Pencil strokes

    :param only_selected_strokes: Selected Strokes Only, Only select the first point of strokes that already have points selected
    :type only_selected_strokes: bool
    :param extend: Extend, Extend selection instead of deselecting all other selected points
    :type extend: bool
    """
    pass


def limit(vmin, vmax, npeaks):
    """
    Fixed limits, vmin to vmax for all peaks.
    """
    return [(vmin, vmax)] * npeaks


def subset():
    """incoming things that are subsets of incoming things"""


def save_repeat_stockholm(tandem_repeat, file):
    """ save <tandem_repeat> in STOCKHOLM format in specified <file>

        Parameters: Tandem repeat MSA.
            e.g. ["ACDEF-", "ACCDEF"]

            More information in
            ftp://selab.janelia.org/pub/software/hmmer3/3.0/Userguide.pdf
            STOCKHOLM Format Example:

            # STOCKHOLM 1.0
            seq1 ACDEF...GHIKL
            seq2 ACDEF...GHIKL
            seq3 ...EFMNRGHIKL

            seq1 MNPQTVWY
            seq2 MNPQTVWY
            seq3 MNPQT...
            //

    """
    with open(file, 'w', newline='\n') as fh:
        fh.write('# STOCKHOLM 1.0\n')
        for i, iMSA in enumerate(tandem_repeat):
            fh.write('{} {}\n'.format(str(i), iMSA))
        fh.write('//')


def reverse_code(apps, schema_editor):
    """Reversing the inference of the process type is not possible and not necessary."""


def unlistify(n, depth=1, typ=list, get=None):
    """Return the desired element in a list ignoring the rest.

    >>> unlistify([1,2,3])
    1
    >>> unlistify([1,[4, 5, 6],3], get=1)
    [4, 5, 6]
    >>> unlistify([1,[4, 5, 6],3], depth=2, get=1)
    5
    >>> unlistify([1,(4, 5, 6),3], depth=2, get=1)
    (4, 5, 6)
    >>> unlistify([1,2,(4, 5, 6)], depth=2, get=2)
    (4, 5, 6)
    >>> unlistify([1,2,(4, 5, 6)], depth=2, typ=(list, tuple), get=2)
    6
    """
    i = 0
    if depth is None:
        depth = 1
    index_desired = get or 0
    while i < depth and isinstance(n, typ):
        if len(n):
            if len(n) > index_desired:
                n = n[index_desired]
                i += 1
        else:
            return n
    return n


def substituteVariables(command, level, name, value, target=None, **kwargs):
    """Substitute variables in command fragments by values e.g. ${level} => 'warning'."""
    rule = kwargs.get('rule', {})
    rule_value = rule.get('value', '') if rule else ''
    substitutes = {'${level}': str(level), '${target}': str(target),
        '${name}': '"' + str(name) + '"', '${value}': str(value),
        '${limit_value}': str(rule_value)}
    result = command
    for pattern, value in substitutes.items():
        result = result.replace(pattern, value)
    return result


def text_align(cr, x, y, text, align_x=0, align_y=0, padding_x=0, padding_y=0):
    """
    Draw text relative to (x, y).
    x, y - coordinates
    text - text to print (utf8)
    align_x - -1 (top), 0 (middle), 1 (bottom)
    align_y - -1 (left), 0 (center), 1 (right)
    padding_x - padding (extra offset), always > 0
    padding_y - padding (extra offset), always > 0
    """
    if not text:
        return
    x_bear, y_bear, w, h, x_adv, y_adv = cr.text_extents(text)
    if align_x == 0:
        x = 0.5 - (w / 2 + x_bear) + x
    elif align_x < 0:
        x = -(w + x_bear) + x - padding_x
    else:
        x = x + padding_x
    if align_y == 0:
        y = 0.5 - (h / 2 + y_bear) + y
    elif align_y < 0:
        y = -(h + y_bear) + y - padding_y
    else:
        y = -y_bear + y + padding_y
    cr.move_to(x, y)
    cr.show_text(text)


def create(mlist):
    """Tell the MTA that the mailing list was created."""


def delete(isamAppliance, check_mode=False, force=False):
    """
    Execute an operation (start, stop or restart) on packet tracing
    """
    warnings = ['No idempotency check coded yet.']
    if force is True:
        if check_mode is True:
            return isamAppliance.create_return_object(changed=True,
                warnings=warnings)
        else:
            return isamAppliance.invoke_delete(
                'Executing  delete operation on packet trace',
                '/isam/packet_tracing/', warnings=warnings)
    return isamAppliance.create_return_object(warnings=warnings)


def get_elk_command(line):
    """Return the 2 character command in the message."""
    if len(line) < 4:
        return ''
    return line[2:4]


def getParticle(value):
    """
    Returns one of ['none', 'photon', 'positron', 'electron'] following
    the convention:
            0 = no particle
            7 = photon
            8 = positron
            9 = electron)
    """
    if value == 7:
        return 'photon'
    if value == 0:
        return 'none'
    if value == 9:
        return 'electron'
    if value == 8:
        return 'positron'
    raise ValueError('Invalid particle code')


def valid_icon_size(size):
    """Icons must be power of 2 within [16, 2048]."""
    return not size & size - 1 and size in range(16, 2049)


@classmethod
def from_str(cls, s):
    """ e.g. Moderator/1 """
    n, v = s.split('/')
    return cls(n, v)


def SG(rho, rho_ref=999.0170824078306):
    """
    Calculates the specific gravity of a substance with respect to another
    substance; by default, this is water at 15.6 °C (60 °F). For gases,
    normally the reference density is 1.2 kg/m^3, that of dry air. However, in
    general specific gravity should always be specified with respect to the
    temperature and pressure of its reference fluid. This can vary widely.

    .. math::
        SG = \\frac{\\rho}{\\rho_{ref}}

    Parameters
    ----------
    rho : float
        Density of the substance, [kg/m^3]
    rho_ref : float, optional
        Density of the reference substance, [kg/m^3]

    Returns
    -------
    SG : float
        Specific gravity of the substance with respect to the reference
        density, [-]

    Notes
    -----
    Another common reference point is water at 4°C (rho_ref=999.9748691393087).
    Specific gravity is often used by consumers instead of density.
    The reference for solids is normally the same as for liquids - water.

    Examples
    --------
    >>> SG(860)
    0.8608461408159591

    """
    return rho / rho_ref


def _convert_to_slice(string):
    """Convert slice-str to slice

    Examples:
        >>> _convert_to_slice('0:51')
        (slice(0, 52),)
        >>> _convert_to_slice('0:51,6:10')
        (slice(0, 52), slice(6, 11))
        >>> _convert_to_slice(',6:10')
        (slice(None), slice(6, 11))

    """
    slices = []
    for ele in string.split(','):
        if ele == '' or ele == ':':
            slices.append(slice(None))
        else:
            sps = []
            for sp in ele.split(':'):
                try:
                    sps.append(int(sp))
                except ValueError:
                    raise ValueError('Format error: {}'.format(string))
            if len(sps) == 1:
                sl = slice(sps[0], sps[0] + 1)
            elif len(sps) == 2:
                sl = slice(sps[0], sps[1] + 1)
            elif len(sps) == 3:
                sl = slice(sps[0], sps[1] + 1, sps[2])
            else:
                raise RuntimeError('Too many : {}'.format(string))
            slices.append(sl)
    return tuple(slices)


def one_to_many(df, unitcol, manycol):
    """Asserts that a many-to-one relationship is preserved between two columns.

    For example, a retail store will have have distinct departments, each with several employees.
    If each employee may only work in a single department, then the relationship of the
    department to the employees is one to many.

    Args:
        df (pd.DataFrame): Any pd.DataFrame.
        unitcol (str): The column that encapulates the groups in ``manycol``.
        manycol (str): The column that must remain unique in the distict pairs
                       between ``manycol`` and ``unitcol``.

    Returns:
        Original `df`.

    """
    subset = df[[manycol, unitcol]].drop_duplicates()
    for many in subset[manycol].unique():
        if subset[subset[manycol] == many].shape[0] > 1:
            msg = '{} in {} has multiple values for {}'.format(many,
                manycol, unitcol)
            raise AssertionError(msg)
    return df


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

        :param FileLockingValue val:
        :rtype: UserFeatureValue
        """
    return cls('file_locking', val)


def compare_arrays(left, right):
    """Eq check with a short-circuit for identical objects."""
    return left is right or left.shape == right.shape and (left == right).all()


def theta_B3O3OH4_HCO3_FW86(T, P):
    """a-a': triborate bicarbonate [FW86]."""
    theta = -0.1
    valid = T == 298.15
    return theta, valid


def process_event(event):
    """Process a single bounce event.

        :param event: The bounce event to process.
        :type event: IBounceEvent
        """


def p_ReadOnly_true(p):
    """ReadOnly : readonly"""
    p[0] = True


def WichmannHill1982():
    """
    Algorithm AS 183 Appl. Statist. (1982) vol.31, no.2

    Returns a pseudo-random number rectangularly distributed
    between 0 and 1.   The cycle length is 6.95E+12 (See page 123
    of Applied Statistics (1984) vol.33), not as claimed in the
    original article.

    ix, iy and iz should be set to integer values between 1 and
    30000 before the first entry.

    Integer arithmetic up to 5212632 is required.
    """
    import numpy as np
    global ix, iy, iz
    ix = 171 * ix % 30269
    iy = 172 * iy % 30307
    iz = 170 * iz % 30323
    """
    If integer arithmetic only up to 30323 (!) is available, the preceding
    3 statements may be replaced by:

    ix = 171 * (ix % 177) -  2 * (ix / 177)
    iy = 172 * (iy % 176) - 35 * (iy / 176)
    iz = 170 * (iz % 178) - 63 * (iz / 178)

    if ix < 0:
        ix = ix + 30269
    if iy < 0:
        iy = iy + 30307
    if iz < 0:
        iz = iz + 30323
    """
    return np.remainder(np.float(ix) / 30269.0 + np.float(iy) / 30307.0 +
        np.float(iz) / 30323.0, 1.0)


@staticmethod
def generate_line(line):
    """
        Returns an an HTML line.
        :param str line: Line to be converted.
        :return str: Line.
        """
    return '<br>{}'.format(line)


@staticmethod
def parse_id(name):
    """
        Resolves an id from a binary XML file in the form "@[package:]DEADBEEF"
        and returns a tuple of package name and resource id.
        If no package name was given, i.e. the ID has the form "@DEADBEEF",
        the package name is set to None.

        Raises a ValueError if the id is malformed.

        :param name: the string of the resource, as in the binary XML file
        :return: a tuple of (resource_id, package_name).
        """
    if not name.startswith('@'):
        raise ValueError("Not a valid resource ID, must start with @: '{}'"
            .format(name))
    name = name[1:]
    package = None
    if ':' in name:
        package, res_id = name.split(':', 1)
    else:
        res_id = name
    if len(res_id) != 8:
        raise ValueError("Numerical ID is not 8 characters long: '{}'".
            format(res_id))
    try:
        return int(res_id, 16), package
    except ValueError:
        raise ValueError("ID is not a hex ID: '{}'".format(res_id))


def sort_by_pitch(sounding_notes):
    """
    Sort a list of notes by pitch

    Parameters
    ----------
    sounding_notes : list
        List of `VSNote` instances

    Returns
    -------
    list
        List of sounding notes sorted by pitch
    """
    return sorted(sounding_notes, key=lambda x: x.pitch)


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

        :param AccessLevel val:
        :rtype: FileMemberActionIndividualResult
        """
    return cls('success', val)


def update_pos(pos_dict, start_key, nbr=2):
    """Update the `pos_dict` by moving all positions after `start_key` by `nbr`."""
    for key, idx in pos_dict.items():
        if str.lower(key) >= str.lower(start_key):
            pos_dict[key] += nbr
    return pos_dict


def compose(stream, Loader=Loader):
    """
    Parse the first YAML document in a stream
    and produce the corresponding representation tree.
    """
    loader = Loader(stream)
    try:
        return loader.get_single_node()
    finally:
        loader.dispose()


def generate_script(group, entry_point, header, template):
    """Generate the script based on the template.

    :param str group:
        The entry-point group name, e.g., "console_scripts".
    :param str header:
        The first line of the script, e.g., "!#/usr/bin/env python".
    :param str template:
        The script template.
    :returns:
        The templated script content
    :rtype:
        str
    """
    if not entry_point.attrs or len(entry_point.attrs) > 2:
        raise ValueError(
            "Script targets must be of the form 'func' or 'Class.class_method'."
            )
    script_text = template % dict(group=group, module_name=entry_point.
        module_name, import_target=entry_point.attrs[0], invoke_target='.'.
        join(entry_point.attrs))
    return header + script_text


def qbytearray_to_str(qba):
    """Convert QByteArray object to str in a way compatible with Python 2/3"""
    return str(bytes(qba.toHex().data()).decode())


def get_cols_ratio_equal_val(df, val, ratio=1):
    """
    Useful for finding cols where a certain proportion of rows are equal
    to a particular value.
    """
    check = (df == val).sum()
    return check[check == ratio * len(df)]


@staticmethod
def split_df_into_subsets(df, fraction=0.5, random_state=1234):
    """Return a random sample of items from an axis of object.

        Parameters
        ----------
        df : pandas.core.frame.DataFrame
            Two-dimensional size-mutable,
            potentially heterogeneous tabular data
        fraction : float, optional
            Fraction of axis items to return.
            Cannot be used with `n`.
        random_state : int or numpy.random.RandomState, optional
            Seed for the random number generator (if int),
            or numpy RandomState object.

        Returns
        -------
        List
            List of data frame
        """
    df_1 = df.sample(frac=fraction, random_state=random_state)
    df_2 = df.drop(df_1.index)
    return df_1, df_2


def _get_words(data_dir):
    """Get list of words from history file.

    Parameters
    ----------
    data_dir : pathlib.Path
        Directory where data is saved.

    Returns
    -------
    word_list : list of str
        List of words.
    """
    words_file = data_dir.joinpath('words.txt')
    word_list = []
    if not words_file.is_file():
        return word_list
    with open(words_file, mode='r') as f:
        for l in f:
            line = l.rstrip()
            word_list.append(line)
    return word_list


def feather_weight_clear():
    """Reset the feather weight to zero

    """
    pass


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

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

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


def split_string_around_stars(string):
    """It splits the provided string around every star in it
    and returns the result in the form of a list

    Input:
    ------
    string : string

    Output:
    -------
    splitted_string : list
    """
    splitted_string = []
    word = ''
    for char in string:
        if char == '*':
            if word:
                splitted_string.append(word)
                word = ''
            splitted_string.append('*')
        else:
            word += char
    if word:
        splitted_string.append(word)
    return splitted_string


def p_value(t):
    """value : constant
             | ID"""
    t[0] = t[1]


def _get_key(key, scopes):
    """Get a key from the current scope"""
    if key == '.':
        return scopes[0]
    for scope in scopes:
        try:
            for child in key.split('.'):
                try:
                    scope = scope[child]
                except (TypeError, AttributeError):
                    scope = scope.__dict__[child]
            if scope is 0:
                return 0
            if scope is False:
                return False
            try:
                if scope._CHEVRON_return_scope_when_falsy:
                    return scope
            except AttributeError:
                return scope or ''
        except (AttributeError, KeyError):
            pass
    return ''


def xyz2zyx(dic, data):
    """
    3D Matrix transpose
    """
    raise NotImplementedError


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

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

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


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


def _generateSpecial_VectorOpts_orientFlip(overlayList, displayCtx, source,
    longArg):
    """Generates the ``VectorOpts.orientFlip`` option. """
    flip = source.overlay.isNeurological() != source.orientFlip
    if flip:
        return [longArg]
    else:
        return []


def get_calculation_annotation(calculation_field, calculation_method):
    """
    Returns the default django annotation
    @param calculation_field: the field to calculate ex 'value'
    @param calculation_method: the aggregation method ex: Sum
    @return: the annotation ex value__sum
    """
    return '__'.join([calculation_field.lower(), calculation_method.name.
        lower()])


@classmethod
def from_dict(cls, client, soap_dict):
    """
        Alternative constructor, builds entity object from a dictionary representation of
        a SOAP response created by the SOAP client.
        """
    return cls(client=client, courier_id=soap_dict.get('CourierID', None),
        name=soap_dict.get('CourierName', None))


def path_list_is_ancestor(ances_pl, des_pl):
    """
        from xdict.utils import *
        path_list_is_ancestor(['a','b'],['a','b'])
        path_list_is_ancestor(['a','b'],['a','b',''])
        path_list_is_ancestor(['a','b'],['a','b','c'])
        path_list_is_ancestor(['a','b'],['a','b','c','d'])
        path_list_is_ancestor(['a','b'],['a','b','c','d',''])
    """
    dl_len = des_pl.__len__()
    al_len = ances_pl.__len__()
    if dl_len > al_len:
        for i in range(0, al_len):
            if ances_pl[i] == des_pl[i]:
                pass
            else:
                return False
        return True
    else:
        return False


def rotatable_count(mol):
    """Rotatable bond count """
    mol.require('Rotatable')
    return sum(1 for _, _, b in mol.bonds_iter() if b.rotatable)


def dbes2dbes_strands(dBEs):
    """
    add reverse strand editing methods in the dBEs dataframe

    :param dBEs: pandas dataframe with BE methods
    """
    from beditor.lib.global_vars import nt2complement
    dBEs_ = dBEs.copy()
    dBEs_['strand'] = '-'
    for col_nt in ['nucleotide', 'nucleotide mutation']:
        dBEs_[col_nt] = dBEs_[col_nt].apply(lambda x: nt2complement[x])
    dBEs = dBEs.append(dBEs_, sort=True)
    return dBEs


def absolute_range_name(sheet_name, range_name=None):
    """Return an absolutized path of a range.

    >>> absolute_range_name("Sheet1", "A1:B1")
    "'Sheet1'!A1:B1"

    >>> absolute_range_name("Sheet1", "A1")
    "'Sheet1'!A1"

    >>> absolute_range_name("Sheet1")
    "'Sheet1'"

    >>> absolute_range_name("Sheet'1")
    "'Sheet''1'"

    >>> absolute_range_name("Sheet''1")
    "'Sheet''''1'"

    >>> absolute_range_name("''sheet12''", "A1:B2")
    "'''''sheet12'''''!A1:B2"
    """
    sheet_name = "'{}'".format(sheet_name.replace("'", "''"))
    if range_name:
        return '{}!{}'.format(sheet_name, range_name)
    else:
        return sheet_name


def create():
    """
    @api {post} /music/playlist/create 创建用户歌单
    @apiVersion 1.0.0
    @apiGroup Playlist
    @apiDescription 创建用户歌单

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

    @apiParam (Body) {String} playlistname 播放列表名称

    @apiSuccess (Success) {Object} playlistid 播放列表编号

    @apiSuccessExample {json} Success-Response:
    {
        "data": {
            "playlistid": 230
        }
    }

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

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

    """


def rect_to_coords(rect):
    """Converts a rect in the [x1, y1, x2, y2] format to coordinates."""
    return [[rect[0], rect[1]], [rect[2], rect[1]], [rect[2], rect[3]], [
        rect[0], rect[3]]]


def update_sequence(s, n, x):
    """Return a tuple copy of s with the nth element replaced by x."""
    t = tuple(s)
    if -len(t) <= n < len(t):
        return t[0:n] + (x,) + t[n + 1:0 if n == -1 else None]
    else:
        raise IndexError('sequence index out of range')


def higher(f, c, o=1):
    """Determine whether or not a series value is higher than
    the value ``o`` periods back.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe containing the column ``c``.
    c : str
        Name of the column in the dataframe ``f``.
    o : int, optional
        Offset value for shifting the series.

    Returns
    -------
    new_column : pandas.Series (bool)
        The array containing the new feature.

    """
    new_column = f[c] > f[c].shift(o)
    return new_column


def __iter__():
    """ Return an iterator over the results of ``self.all()``"""


def set_error_model(raise_api_errors: bool=True) ->None:
    """Set the error model for the library.

    By default, operations (GET, POST, PATCH, DELETE) will raise an exception if
    the response code from the host is >= 400. The exception object will contain
    the response so that it can be handled in the client code.

    Optionally, settings raise_api_errors to False will return the response and
    the client will be responsible for checking and handling any errors.

    Args:
        raise_api_errors: If set to true, the library will raise errors back to the
            application. If set to faise, errors will not be raised and the
            application must verify the responses itself.
    """
    global RAISE_API_ERRORS
    RAISE_API_ERRORS = raise_api_errors


def vertices_vector_to_matrix(vertices):
    """vertices_vector_to_matrix(vertices) -> List[List[float]]
    PyPRT outputs the GeneratedModel vertex coordinates as a list. The list
    contains the x, y, z coordinates of all the vertices. This function converts the
    vertex list into a list of N vertex coordinates lists (with N, the number
    of geometry vertices).

    Parameters:
        vertices: List[float]

    Returns:
        List[List[float]]

    Example:
        ``[[-10.0, 0.0, 10.0], [-10.0, 0.0, 0.0], [10.0, 0.0, 0.0], [10.0, 0.0, 10.0]]
        = vertices_vector_to_matrix([-10.0, 0.0, 10.0, -10.0, 0.0, 0.0, 10.0, 0.0, 0.0,
        10.0, 0.0, 10.0])``
    """
    vertices_as_matrix = []
    for count in range(0, int(len(vertices) / 3)):
        vector_per_pt = [vertices[count * 3], vertices[count * 3 + 1],
            vertices[count * 3 + 2]]
        vertices_as_matrix.append(vector_per_pt)
    return vertices_as_matrix


def init_legendre_rational(result, x, pos, cur_var):
    """Initialize the first and second order before starting the recursion.

    Mathematically this amounts to
    R_1 = (x-1)/(x+1)
    R_2 = 3/2 * (x-1)/(x+1)*P_1 - 1/2.

    .. note::

        The procedure on how an init function is built can be found in the
        docstring of the init function for
        standard polynomials *init_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 pos: The index of the element to be computed, along the second
        dimension of result.
    :type int: 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

    :returns: The index of the next element that will be computed in the
        recursion, the order of the next element, and the index of a special
        member. As we do not need a special element in Legendre rational
        functions, the index of the special element is set to None.
    :rtype: Tuple[int, int, int]
    """
    result[:, (pos)] = (x[:, (cur_var)] - 1.0) / (x[:, (cur_var)] + 1.0)
    result[:, (pos + 1)] = 3.0 / 2.0 * (x[:, (cur_var)] - 1.0) / (x[:, (
        cur_var)] + 1.0) * result[:, (pos)] - 1.0 / 2.0
    return pos + 2, 3, None


@classmethod
def filter(cls, **kwargs):
    """Фильтрация таблицы.

        Стандартная фильтрация с указание полей и значений

        Args:
            **kwargs: параметры фильтрации

        Returns:
            Возвращает результат фильтрации
            object

        """
    return cls.query().filter(**kwargs)


def pprint(to_be_printed):
    """nicely formated print"""
    try:
        import pprint as pp
        pp.pprint(to_be_printed)
    except ImportError:
        if isinstance(to_be_printed, dict):
            print('{')
            for k, v in to_be_printed.items():
                print("'" + k + "'" if str(k) == k else k, ': ', "'" + v +
                    "'" if str(v) == v else v, sep='')
            print('}')
        else:
            print('could not import pprint module, appling regular print')
            print(to_be_printed)


def calculate(hours, start, worktime, absence=None, initial_entries=[],
    min_length=0.0, max_week_hours=None, fetch_entries=True):
    """ Iterator of ITimeEntry objects
        """


def noop_make_key(key, *args, **kwargs):
    """
    For use with KEY_FUNCTION, to not alter the key name at all.
    """
    return key


def build_splat_el(transmitter):
    """
    Return the text (string) content of a SPLAT! elevation file (EL file) corresponding to the given transmitter.

    INPUT:
        - ``transmitter``: dictionary of the same form as any one of the elements in the list output by :func:`read_transmitters`

    OUTPUT:
        String

    NOTES:
        A transmitter with no ``'bearing'`` or ``'antenna_downtilt'`` or ``'vertical_beamwidth'`` data will produce the string ``'0  0'``.
    """
    t = transmitter
    try:
        bearing = float(t['bearing'])
        ad = float(t['antenna_downtilt'])
        vb = float(t['vertical_beamwidth'])
        s = '{!s}  {!s}\n'.format(ad, bearing)
        counter = 0
        for x in range(-10, 91):
            if counter < vb:
                s += '{!s}  0.9\n'.format(x)
            else:
                s += '{!s}  0.1\n'.format(x)
            counter += 1
    except:
        s = '0  0\n'
    return s[:-1]


def bulksetattr(obj, **kwargs):
    """
    Safely assign attributes in bulk.

    For each keyword argument kw, the function checks that kw is the name of
    one of the object's attributes.
    If kw is not the name of an attribute, the function raises an
    AttributeError. Otherwise, the function assigns the value of the keyword
    argument to the attribute, provided the object allows it.
    """
    for attr in kwargs:
        getattr(obj, attr)
        setattr(obj, attr, kwargs[attr])


def groupkey_to_pairs(groupkey, term):
    """
    Convert a 'groupkey', a structure defined below in 'lookup_grouped_by_feature',
    to a list of pairs representing the parameters that query for just the
    edges in that feature group.
    """
    direction, rel = groupkey
    if direction == 1:
        return [('rel', rel), ('start', term)]
    elif direction == -1:
        return [('rel', rel), ('end', term)]
    else:
        return [('rel', rel), ('node', term)]


def from_fdef(fdef):
    """
    Returns a function and its initialising parameters' values from a string
    containing them, typically 'fdef ; (param)'

    Parameters
    ----------

    fdef : str, optional
        String of type 'fdef ; (param)'

    Returns
    ----------
    f: function
    p: tuple
        initialising parameters' values

    """
    fstr, pstr = fdef.split(';')
    return eval(fstr), eval(pstr)


def get_website_from_host(http_host):
    """Try to find the website name from the HTTP_HOST name"""
    return http_host.split(':')[0]


def start_parallel_region():
    """Starts a parallel region

    This is a clean solution without having to explicitely invoke Manager
    and DistributedConfiguration class

    """
    from .managers import Manager
    dc = Manager().get_DistributedConfiguration()
    if dc.rank != 0:
        Manager().log_conf.verbosity -= 2
        Manager().log_conf.fverbosity -= 2


def ant2bl(i, j=None):
    """Returns baseline index for given antenna pair.  Will accept
    two args, or a list/tuple/etc.  Uses 0-based indexing"""
    if j is None:
        a1, a2 = sorted(i[:2])
    else:
        a1, a2 = sorted((i, j))
    return a2 * (a2 - 1) // 2 + a1


def reports_display_update():
    """Update the display of reports in Blender UI (internal use)

    """
    pass


@staticmethod
def representer(dumper, data):
    """Return a custom dumper that formats str in the literal style."""
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|' if
        data else '')


def ndof_orbit_zoom():
    """Orbit and zoom the view using the 3D mouse

    """
    pass


def listkeys(namespace):
    """Obtain all keys in a pushkey namespace.

        Returns an iterable of key names.
        """


def is_readonly_property(cls, name):
    """Tell whether a attribute can't be setattr'ed."""
    attr = getattr(cls, name, None)
    return attr and isinstance(attr, property) and not attr.fset


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 getNibbles(byte):
    """
    Returns hi and lo bits in a byte as a tuple
    >>> getNibbles(142)
    (8, 14)

    Asserts byte value in byte range
    >>> getNibbles(256)
    Traceback (most recent call last):
        ...
    ValueError: Byte value out of range 0-255: 256
    """
    if not 0 <= byte <= 255:
        raise ValueError('Byte value out of range 0-255: %s' % byte)
    return byte >> 4 & 15, byte & 15


def attenuation(originalGravity: float, finalGravity: float) ->float:
    """
    Determines Attenuation of yeast.

    Parameters
    ----------
    originalGravity : float
        Original gravity of wort.
    finalGravity : float
        Final gravity of beer.

    Returns
    -------
    float or None
        Attenuation.
    """
    if originalGravity > finalGravity:
        return (originalGravity - finalGravity) / (originalGravity - 1)
    else:
        return


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


@staticmethod
def get_matrix_size(zoom):
    """
        Returns tile matrix size of the world bounds at the given level. used for NSG profile calculations
        Args:
            zoom: zoom level to return the tile matrix size of

        Returns:
            x - tile matrix width
            y - tile matrix height
        """
    x = 2 ** (zoom + 1)
    y = 2 ** zoom
    return x, y


def keyingset_remove_selected():
    """Remove selected items (blue-gray rows) from active Keying Set

    """
    pass


def name_2_id(str_name_id):
    """Returns the number of a numbered object. For example: "Frame 3" returns 3"""
    words = str_name_id.split()
    number = words.pop()
    if number.isdigit():
        return float(number)
    return -1


def surrogate(text):
    """Returns unicode for a given RPM header.
    This is a layer to support both RPM 4.14 and 4.15.
    RPM 4.14 always returns bytes.
    RPM 4.15 always returns unicode strings with surrogateescaped errors.
    """
    if isinstance(text, bytes):
        return text.decode('utf-8', errors='surrogateescape')
    return text


def call_with_context(ctx, func, *args, _context_callable=False, **kwargs):
    """
    Returns the value of func(*args, **kwargs) within the context
    Set '_context_callable=True' if your contextmanager needs to be called first
    """
    if _context_callable:
        ctx = ctx()
    with ctx:
        return func(*args, **kwargs)


@staticmethod
def _readMeta(fd):
    """Read meta array from the top of a file. Read lines until a blank line is reached.
        This function should ideally work for ALL versions of MetaArray.
        """
    meta = ''
    while True:
        line = fd.readline().strip()
        if line == '':
            break
        meta += line
    ret = eval(meta)
    return ret


def safe_eval(source):
    """
    Protected string evaluation.

    Evaluate a string containing a Python literal expression without
    allowing the execution of arbitrary non-literal code.

    Parameters
    ----------
    source : str
        The string to evaluate.

    Returns
    -------
    obj : object
       The result of evaluating `source`.

    Raises
    ------
    SyntaxError
        If the code has invalid Python syntax, or if it contains
        non-literal code.

    Examples
    --------
    >>> np.safe_eval('1')
    1
    >>> np.safe_eval('[1, 2, 3]')
    [1, 2, 3]
    >>> np.safe_eval('{"foo": ("bar", 10.0)}')
    {'foo': ('bar', 10.0)}

    >>> np.safe_eval('import os')
    Traceback (most recent call last):
      ...
    SyntaxError: invalid syntax

    >>> np.safe_eval('open("/home/user/.ssh/id_dsa").read()')
    Traceback (most recent call last):
      ...
    ValueError: malformed node or string: <_ast.Call object at 0x...>

    """
    import ast
    return ast.literal_eval(source)


@classmethod
def get_all_hd_thermal_elements(cls, session, server_key):
    """Retrieve all storage components that support temperature sensors"""
    query = []
    query.extend([
        'MATCH (:ServerWithBMC {{ key: {} }})-[:HAS_CONTROLLER]->(controller:Controller)'
        .format(server_key),
        'MATCH (controller)-[:HAS_CACHEVAULT|:HAS_PHYSICAL_DRIVE]->(hd_component)'
        , 'WHERE hd_component:PhysicalDrive or hd_component:CacheVault',
        'RETURN controller, hd_component'])
    results = session.run('\n'.join(query))
    hd_thermal_elements = []
    for record in results:
        hd_thermal_elements.append({'controller': dict(record.get(
            'controller')), 'component': dict(record.get('hd_component'))})
    return hd_thermal_elements


def generate_inverse(conversions):
    """Generate all simple inverse conversions.

    A simple inverse conversion is something we can obtain by doing
    a ``1 / unit`` type of conversion.

    Parameters
    ----------
    conversions : dictionary
        The unit conversions, assumed to be of type `convert[quantity]`.
        Note that this variable will be updated by this function.

    Returns
    -------
    out : None
        Will not return anything, but will update the given parameter
        `conversions`.
    """
    newconvert = {}
    for unit in conversions:
        unit_from, unit_to = unit
        newunit = unit_to, unit_from
        if newunit not in conversions:
            newconvert[newunit] = 1.0 / conversions[unit]
    for newunit in newconvert:
        conversions[newunit] = newconvert[newunit]


def sync():
    """Synchronize with portal_catalog."""


def gentable(n):
    """
    Generate Any Number Table 1-10 or > 10
  """
    print('_' * 3 + '[ Table Of %s ]' % n + '_' * 3 + '\n')
    for i in range(1, 10 + 1):
        print('{} × {} = {}'.format(n, i, n * i))
    print('\n')


def num_cpus_in_mask(mask):
    """Return the number of cpus in a cpumask"""
    mask = mask.replace(',', '')
    value = int(mask, 16)
    return bin(value).count('1')


def make_default_short_help(help, max_length=45):
    """Return a condensed version of help string."""
    words = help.split()
    total_length = 0
    result = []
    done = False
    for word in words:
        if word[-1:] == '.':
            done = True
        new_length = result and 1 + len(word) or len(word)
        if total_length + new_length > max_length:
            result.append('...')
            done = True
        else:
            if result:
                result.append(' ')
            result.append(word)
        if done:
            break
        total_length += new_length
    return ''.join(result)


@staticmethod
def from_io_control(fobj):
    """
        Call TIOCGWINSZ (Terminal I/O Control to Get the WINdow SiZe)
        where ``fobj`` is a file object (e.g. ``sys.stdout``),
        returning the terminal width assigned to that file.

        See the ``ioctl``, ``ioctl_list`` and tty_ioctl`` man pages
        for more information.
        """
    import fcntl, termios, array
    winsize = array.array('H', [0] * 4)
    if not fcntl.ioctl(fobj.fileno(), termios.TIOCGWINSZ, winsize, True):
        return winsize[1]


def __contains__(key):
    """Return True if 'key' is in the container, else False.
        """


def bake_animation():
    """Update the audio animation cache

    """
    pass


def flatten_fieldsets(fieldsets):
    """Returns a list of field names from an admin fieldsets structure."""
    field_names = []
    for name, opts in fieldsets:
        for field in opts['fields']:
            if type(field) == tuple:
                field_names.extend(field)
            else:
                field_names.append(field)
    return field_names


def reset_instance(instance, *args, **kwargs):
    """
    Called on the post_save signal. Calls the instance's _reset_state method
    """
    instance._reset_state()


def unicode_sorter(input):
    """ This function implements sort keys for the german language according to
    DIN 5007."""
    key1 = input.lower()
    key1 = key1.replace(u'ä', u'a')
    key1 = key1.replace(u'ö', u'o')
    key1 = key1.replace(u'ü', u'u')
    key1 = key1.replace(u'ß', u'ss')
    return key1


def Ix(x, y, z, Hx, Hy, Hz, G):
    """Calculates the x-component of current at a grid position.

    Args:
        x, y, z (float): Coordinates of position in grid.
        Hx, Hy, Hz (memory view): numpy array of magnetic field values.
        G (class): Grid class instance - holds essential parameters describing the model.
    """
    if y == 0 or z == 0:
        Ix = 0
    else:
        Ix = G.dy * (Hy[x, y, z - 1] - Hy[x, y, z]) + G.dz * (Hz[x, y, z] -
            Hz[x, y - 1, z])
    return Ix


def _has_parent_of_type(node, node_type, statement):
    """Check if the given node has a parent of the given type."""
    parent = node.parent
    while not isinstance(parent, node_type) and statement.parent_of(parent):
        parent = parent.parent
    return isinstance(parent, node_type)


@classmethod
def localhost(cls, application_id):
    """
        The default Redis provider
        """
    return cls(host='localhost:{port}'.format(port=cls.DEFAULT_PORT))


def extract_aaf(var):
    """
    Extract the AAF directly from the INFO field.
    """
    return var.INFO.get('AF')


def SizeBenefitSurg(t):
    """Surgery benefit per policy"""
    return 0


def fail(error):
    """ Raises a RuntimeError with the given error Message

        >>> fail("This failed badly")
        Traceback (most recent call last):
        ...
        RuntimeError: This failed badly
    """
    raise RuntimeError(error)


def get_md_cell(source, metadata=None):
    """Markdown cell containing `source` with `metadata`."""
    return {'cell_type': 'markdown', 'metadata': {} if metadata is None else
        metadata, 'source': source}


def any_keys_not_none(d: dict, required: list):
    """
    Check although 1 element is not None but not all required
    :param d:
    :param required:
    :return:
    """
    passed = 0
    for r in required:
        v = d.get(r)
        if v is not None:
            passed += 1
    if len(required) == 1 and passed == len(required):
        return True
    return 0 < passed < len(required)


def literal(text):
    """" Returns the given value, ignoring the tokens alltogether. """
    return lambda tokens: text


def do_ids_match(oWarning, oSuppression):
    """
    Checks if the suppression ID matches the warning ID.

    Parameters:

      oWarning : (warning object)

      oSuppression : (suppression object)

    Returns: (boolean)
    """
    if oWarning.get_id() == oSuppression.get_warning_id():
        return True
    return False


def iso_format(datetime):
    """
    Generates an ISO formatted datetime based on what the LaunchKey API
    expects. This is a standard ISO datetime without microseconds.
    :param datetime: datetime.datetime object
    :return: ISO formatted string IE: 2017-10-03T22:50:15Z
    """
    return datetime.strftime('%Y-%m-%dT%H:%M:%SZ'
        ) if datetime is not None else None


def new():
    """Add new palette

    """
    pass


def trim(s):
    """Trim string to fit on terminal (assuming 80-column display)"""
    return s if len(s) <= 80 else s[:77] + '...'


def get_absolute_uri(request):
    """
	Get full URL with domain and protocol
	e.g.: 'http://example.com/someview/?query="test"'
	"""
    return request.build_absolute_uri()


def get(yaml_config, key_path, default_value=None):
    """ Get a value in a yaml_config, or return a default value.

    :param yaml_config: the YAML config.
    :param key: a key to look for. This can also be a list, looking at
                more depth.
    :param default_value: a default value to return in case the key is
                          not found.
    :return: the value at the given key path, or default_value if not found.
    """
    if len(key_path) == 0:
        return default_value
    node = yaml_config
    for key in key_path:
        try:
            node = node[key]
        except Exception:
            return default_value
    return node


def num_ascend(df):
    """Total number of track ascend."""
    return df.extra.Type.isin(['ASCEND']).sum()


def xauth(auth):
    """Expand authentication token

    >>> xauth(None)
    >>> xauth(('user', 'pass'))
    ('user', 'pass')
    >>> xauth('user:pass')
    ('user', 'pass')
    >>> xauth('apikey')
    ('apikey', '')

    """
    if auth is None or isinstance(auth, tuple):
        return auth
    else:
        u, _, p = auth.partition(':')
        return u, p


@classmethod
def parse(cls, nessus_data, data_type='XML', strict=False):
    """
        Parses a Nessus data file
        :param nessus_data The datafile to be parsed
        :param data_type File format (XML by default)
        :param strict Forces strict parsing of report objects which may be invalid
        """
    nessusobj = None
    if not isinstance(nessus_data, str):
        raise Exception(
            'Wrong nessus_data type given as argument: Nessus data should be provided as strings'
            )
    if nessus_data and data_type == 'XML':
        nessusobj = cls._parse_xml(nessus_data, strict)
    else:
        raise Exception(
            'No or unknown data type provided. Please check documentation for supported data types.'
            )
    return nessusobj


def load_from_file(module_path):
    """
    Load a python module from its absolute filesystem path
    """
    from imp import load_module, PY_SOURCE
    imported = None
    if module_path:
        with open(module_path, 'r') as openfile:
            imported = load_module('mod', openfile, module_path, (
                'imported', 'r', PY_SOURCE))
    return imported


def build_usb_control_request_type(direction, usb_type, recipient):
    """Build USB control request type for USB communication.

    Parameters:
        direction (int):
        usb_type (int):
        recipient (int):

    Returns:
        request type (int):
    """
    return direction | usb_type | recipient


def lambd_tris_K_GT17simopt(T, P):
    """n-c: tris potassium [GT17simopt]."""
    lambd = 0.02895
    valid = T == 298.15
    return lambd, valid


def _google_drive():
    """
    Returns a query item matching messages that have Google Drive attachments.

    """
    return f'has:drive'


def notifications_enabled(conf):
    """Check if oslo notifications are enabled."""
    notifications_driver = set(conf.oslo_messaging_notifications.driver)
    return notifications_driver and notifications_driver != {'noop'}


def _get_action(view):
    """ Return the string action name of the view """
    action = view.action
    if action == 'partial_update':
        action = 'update'
    return action


def _format_links(link_x):
    """
    Format links part
    :param link_x: list, which has several dicts in it
    :return: formatted string
    """
    try:
        pairs = ''
        for _dict in link_x:
            pairs += _dict['rel'] + '-> ' + _dict['href'] + '\n'
        return pairs[:-1]
    except Exception:
        return link_x


@classmethod
def __format_comparison_segments(cls, name, private, common):
    """
        Method to create the string that will be printed out to screen for the stats file.
        :return:
        """
    if common > 0:
        perc = 100 * (private - common) / private
    else:
        perc = 0
    string = '{0} {1}/{2}  ({3:.2f}%)'.format(cls.__format_rowname(name),
        private - common, private, perc)
    return string


def assert_type(item, *item_types):
    """Assert the given item is a particular type."""
    assert isinstance(item, item_types
        ), 'Item type {0} not in types: {1}'.format(type(item), item_types)


def convert_php_dateformat(php_format_string):
    """Convert a date/datetime using a php format string
    as used by settings.SHORT_DATE_FORMAT.

    For example:
        obj.report_datetime.strftime(
            convert_php_dateformat(settings.SHORT_DATE_FORMAT)
        )
    """
    php_to_python = {'A': '%p', 'D': '%a', 'F': '%B', 'H': '%H', 'M': '%b',
        'N': '%b', 'W': '%W', 'Y': '%Y', 'd': '%d', 'e': '%Z', 'h': '%I',
        'i': '%M', 'l': '%A', 'm': '%m', 's': '%S', 'w': '%w', 'y': '%y',
        'z': '%j', 'j': '%d', 'P': '%I:%M %p'}
    python_format_string = php_format_string
    for php, py in php_to_python.items():
        python_format_string = python_format_string.replace(php, py)
    return python_format_string


def getFullName(userid):
    """ Convert an internal userid to a "formal" name.

        o Convert only if possible, perhaps using the 'portal_membership'
          tool;  otherwise, return 'userid'.

        o Used to map userid's for Creator, Contributor DCMI queries.
        """


@classmethod
def items(cls):
    """
        All values for this enum
        :return: list of str

        """
    return [cls.GREATER_THAN, cls.GREATER_THAN_EQUAL, cls.LESS_THAN, cls.
        LESS_THAN_EQUAL, cls.EQUAL, cls.NOT_EQUAL]


def psh_fire_msg_action_if_new(sender, instance, created, **kwargs):
    """ Post save hook to fire message send task
    """
    if created:
        from message_sender.tasks import send_message
        send_message.apply_async(kwargs={'message_id': str(instance.id)})


@classmethod
def project_path(cls, project):
    """Returns a fully-qualified project resource name string."""
    return cls._PROJECT_PATH_TEMPLATE.render({'project': project})


def filter_keyphrases_brat(raw_ann):
    """Receive raw content in brat format and return keyphrases"""
    filter_keyphrases = map(lambda t: t.split('\t'), filter(lambda t: t[:1] ==
        'T', raw_ann.split('\n')))
    keyphrases = {}
    for keyphrase in filter_keyphrases:
        keyphrase_key = keyphrase[0]
        if ';' in keyphrase[1]:
            label_span = keyphrase[1].replace(';', ' ').split()
            span_str = [min(label_span[1:]), max(label_span[1:])]
        else:
            label_span = keyphrase[1].split()
            span_str = label_span[1:]
        label = label_span[0]
        span = int(span_str[0]), int(span_str[1])
        text = keyphrase[2]
        keyphrases[keyphrase_key] = {'keyphrase-label': label,
            'keyphrase-span': span, 'keyphrase-text': text,
            'tokens-indices': []}
    return keyphrases


def wf_group():
    """
    It returns the group/ACL for the current workflow job.

    In Airflow, I believe it uses RBAC vs ACL, need to discuss.
    """


def DeleteClusterTags(r, tags, dry_run=False):
    """
    Deletes tags from the cluster.

    @type tags: list of str
    @param tags: tags to delete
    @type dry_run: bool
    @param dry_run: whether to perform a dry run
    """
    query = {'dry-run': dry_run, 'tag': tags}
    return r.request('delete', '/2/tags', query=query)


@classmethod
def request_privileges(cls, *privileges):
    """
        Requests privileges.

        @type  privileges: int...
        @param privileges: Privileges to request.

        @raise WindowsError: Raises an exception on error.
        """
    cls.adjust_privileges(True, privileges)


@classmethod
def get_hosts(cls):
    """
        The fully-qualified hostnames that correspond to this service.
        These are often determined by asking a load balancer or service discovery mechanism.

        :return:
            The hostname strings corresponding to this service
        :rtype:
            list
        """
    return [cls.domain]


def metadata_entry_to_tuple(metadata_entry):
    """Converts a lxml.objectify.ObjectifiedElement metadata entry to a tuple.

    The metadata entry object is converted into a simple (key, value) tuple.

    :param lxml.objectify.ObjectifiedElement metadata_entry: an object
        containing MetadataEntry XML data. This tag is a child tag of
        EntityType.Metadata XML.

    :return: a key-value tuple respresnting the metadata entry. Both key and
        value will be strings.

    :rtype: tuple
    """
    key = metadata_entry.Key.text
    value = metadata_entry.TypedValue.Value.text
    return key, value


@classmethod
def _get_apic_classes(cls):
    """
        Get the APIC classes used by the acitoolkit class.
        Meant to be overridden by inheriting classes.
        Raises exception if not overridden.

        :returns: list of strings containing APIC class names
        """
    raise NotImplementedError


@classmethod
def format(cls):
    """Return git format argument."""
    return '%n'.join(cls.FORMAT) + '%n%n%n'


@classmethod
def is_ray(cls, geom):
    """Return whether ``geom`` is a ray-like object or not.

		:param geom:
		:type geom: type of :attr:`Geom.inner_object`
		:return: True if ``geom`` is an instance of the class representing a
			ray in the adapted library
		:rtype: bool

		"""
    raise NotImplementedError()


@classmethod
def create(cls, rev_table, resource_classes, region_map='reeds_region',
    cap_bins=5, sort_bins_by='trans_cap_cost', pre_filter=None,
    trg_by_region=False):
    """
        Identify ReEDS regions and classes and dump and updated table

        Parameters
        ----------
        rev_table : str | pandas.DataFrame
            reV supply curve or aggregation table,
            or path to file containing table
        resource_classes : str | pandas.DataFrame
            Resource classes, either provided in a .csv, .json or a DataFrame
            Allowable columns:
            - 'class' -> class labels to use
            - 'TRG_cap' -> TRG capacity bins to use to create TRG classes
            - any column in 'rev_table' -> Used for categorical bins
            - '*_min' and '*_max' where * is a numberical column in 'rev_table'
              -> used for range binning
            NOTE: 'TRG_cap' can only be combined with categorical bins
        region_map : str | pandas.DataFrame
            Mapping of supply curve points to region to create classes for
        cap_bins : int
            Number of equal capacity bins to create for each
            region-class
        sort_bins_by : str | list, optional
            Column(s) to sort by before capacity binning,
            by default 'trans_cap_cost'
        pre_filter : dict | NoneType
            Column value pair(s) to filter on. If None don't filter
        trg_by_region : bool
            Groupby on region when computing TRGs

        Returns
        -------
        .table : pandas.DataFrame
            Updated table with region_id and class_bin columns
            added. Includes all columns.
        .table_slim : pandas.DataFrame
            Updated table with region_id and class_bin columns
            added. Only includes columns in TABLE_OUT_COLS.
        .aggregate_table : pandas.DataFrame
            Region, class, bin aggregate table. Includes all columns.
        .aggregate_table_slim : pandas.DataFrame
            Region, class, bin aggregate table. Only inlcudes columns in
            AGG_TABLE_OUT_COLS.
        """
    classes = cls(rev_table, resource_classes, region_map=region_map,
        cap_bins=cap_bins, sort_bins_by=sort_bins_by, pre_filter=pre_filter,
        trg_by_region=trg_by_region)
    out = (classes.table, classes.table_slim, classes.aggregate_table,
        classes.aggregate_table_slim)
    return out


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 mhdReadHeader(fname):
    """Return a dictionary of meta data from meta header file"""
    fileIN = open(fname, 'r')
    line = fileIN.readline()
    meta_dict = {}
    tag_set1 = ['ObjectType', 'NDims', 'DimSize', 'ElementType',
        'ElementDataFile']
    tag_set2 = ['BinaryData', 'BinaryDataByteOrderMSB', 'CompressedData',
        'CompressedDataSize']
    tag_set3 = ['Offset', 'CenterOfRotation', 'AnatomicalOrientation',
        'ElementSpacing', 'TransformMatrix']
    tag_set4 = ['Comment', 'SeriesDescription', 'AcquisitionDate',
        'AcquisitionTime', 'StudyDate', 'StudyTime']
    tag_set = []
    tag_set.extend(tag_set1)
    tag_set.extend(tag_set2)
    tag_set.extend(tag_set3)
    tag_set.extend(tag_set4)
    tag_flag = [False] * len(tag_set)
    while line:
        tags = str.split(line, '=')
        for i in range(len(tag_set)):
            tag = tag_set[i]
            if str.strip(tags[0]) == tag and not tag_flag[i]:
                meta_dict[tag] = str.strip(tags[1])
                tag_flag[i] = True
        line = fileIN.readline()
    fileIN.close()
    return meta_dict


def theta_Cl_SO4_PK74(T, P):
    """a-a': chloride sulfate [PK74]."""
    theta = -0.035
    valid = T == 298.15
    return theta, valid


def PolsOther(t):
    """Number of policies: Other benefits"""
    return 0


def exc_info(exception):
    """
    Get exc_info tuple from exception.

    See also
    --------
    sys.exc_info
    """
    return type(exception), exception, exception.__traceback__


def Ad(phi, v):
    """
    This is Ad(phi,v), the big adjoint action of a deformation phi on a
    velocity w.

        Ad(phi,v) = (Dphi \\circ phi^{-1}) v\\circ phi^{-1}

    This is a tricky computation, is not commonly needed in practice and
    will not be implemented until needed.

    Given phi^{-1}, Ad(phi, v) can be computed by first multiplying v by
    Dphi^{-1} then splatting the components of the resulting vector field.
    """
    raise NotImplementedError


def is_incomplete(class_object):
    """
    Test whether the template class @p class_object has any unbound parameters.

    @return    @c False if the template class is fully specialized; @c True
               otheriwse (that is, if it has unbound parameters).
    """
    return getattr(class_object.__class__, '__unbound_parameters__', False)


def write(file):
    """Write the entry to the file
        """


def bin2de(x):
    """convert binary to decimal
    input: 11110000
    output: 15
    """
    n = 7
    de = 0
    while n >= 0:
        de = de + int(x[n]) * 2 ** (7 - n)
        n = n - 1
    return de


def add_tags(ResourceArns=None, Tags=None):
    """
    Adds the specified tags to the specified resource. You can tag your Application Load Balancers and your target groups.
    Each tag consists of a key and an optional value. If a resource already has a tag with the same key, AddTags updates its value.
    To list the current tags for your resources, use  DescribeTags . To remove tags from your resources, use  RemoveTags .
    See also: AWS API Documentation

    Examples
    This example adds the specified tags to the specified load balancer.
    Expected Output:

    :example: response = client.add_tags(
        ResourceArns=[
            'string',
        ],
        Tags=[
            {
                'Key': 'string',
                'Value': 'string'
            },
        ]
    )

    :type ResourceArns: list
    :param ResourceArns: [REQUIRED]
            The Amazon Resource Name (ARN) of the resource.
            (string) --

    :type Tags: list
    :param Tags: [REQUIRED]
            The tags. Each resource can have a maximum of 10 tags.
            (dict) --Information about a tag.
            Key (string) -- [REQUIRED]The key of the tag.
            Value (string) --The value of the tag.

    :rtype: dict
    :return: {}

    :returns:
    (dict) --

    """
    pass


def _is_stop(member_id, member_role, nodes):
    """Check wether the given member designates a public transport stop."""
    return member_role in ('stop', 'platform') or nodes[member_id].tags.get(
        'public_transport') == 'stop_position'


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


@staticmethod
def non_wrap_subtract(a, b):
    """ prevent wrap-around for np.ndarray """
    x = a - b
    x[b > a] = 0
    return x


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

        :param ExtendedVersionHistoryChangePolicyType val:
        :rtype: EventType
        """
    return cls('extended_version_history_change_policy', val)


@staticmethod
def _maybe_encode(value):
    """If the value passed in is a str, encode it as UTF-8 bytes for
        Python 3

        :param str|bytes value: The value to maybe encode
        :rtype: bytes

        """
    try:
        return value.encode('utf-8')
    except AttributeError:
        return value


def start(st_reg_number):
    """Checks the number valiaty for the Acre state"""
    weights = [4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
    digits = st_reg_number[:len(st_reg_number) - 2]
    check_digits = st_reg_number[-2:]
    divisor = 11
    if len(st_reg_number) > 13:
        return False
    sum_total = 0
    for i in range(len(digits)):
        sum_total = sum_total + int(digits[i]) * weights[i]
    rest_division = sum_total % divisor
    first_digit = divisor - rest_division
    if first_digit == 10 or first_digit == 11:
        first_digit = 0
    if str(first_digit) != check_digits[0]:
        return False
    digits = digits + str(first_digit)
    weights = [5] + weights
    sum_total = 0
    for i in range(len(digits)):
        sum_total = sum_total + int(digits[i]) * weights[i]
    rest_division = sum_total % divisor
    second_digit = divisor - rest_division
    if second_digit == 10 or second_digit == 11:
        second_digit = 0
    return str(first_digit) + str(second_digit) == check_digits


def lenRange(start, stop, step=1):
    """
    Get the length of values for a given range

    Args:
        start (int):
        stop (int):
        step (int):
    """
    return (stop - start + step - 1 + 2 * (step < 0)) // step


def detect_encoding(csvfile):
    """ Since encoding detection is hard to get right (and work correctly
    every time), we limit ourselves here to UTF-8 or CP1252, whichever works
    first. CP1252 is basically the csv format you get if you use windows and
    excel and it is a superset of ISO-8859-1/LATIN1.

    """
    csvfile.seek(0)
    try:
        for line in csvfile.readlines():
            line.decode('utf-8')
        return 'utf-8'
    except UnicodeDecodeError:
        return 'cp1252'


def independent_freq_count(frequencies, times, conservative=True):
    """This estimates the number of independent frequencies in a periodogram.

    This follows the terminology on page 3 of Zechmeister & Kurster (2009)::

        M = DELTA_f / delta_f

    where::

        DELTA_f = freq.max() - freq.min()
        delta_f = 1.0/(times.max() - times.min())

    Parameters
    ----------

    frequencies : np.array
        The frequencies array used for the calculation of the GLS periodogram.

    times : np.array
        The array of input times used for the calculation of the GLS
        periodogram.

    conservative : bool
        If True, will follow the prescription given in Schwarzenberg-Czerny
        (2003):

        http://adsabs.harvard.edu/abs/2003ASPC..292..383S

        and estimate the number of independent frequences as::

            min(N_obs, N_freq, DELTA_f/delta_f)

    Returns
    -------

    M : int
        The number of independent frequencies.

    """
    M = frequencies.ptp() * times.ptp()
    if conservative:
        M_eff = min([times.size, frequencies.size, M])
    else:
        M_eff = M
    return M_eff


def p_paste(p):
    """
    steps : steps step
    """
    p[0] = p[1] + p[2]


def LTE(x=None, y=None):
    """
    Compares two values and returns:
        true when the first value is less than or equivalent to the second value.
        false when the first value is greater than the second value.
    See https://docs.mongodb.com/manual/reference/operator/aggregation/lte/
    for more details
    :param x: first value or expression
    :param y: second value or expression
    :return: Aggregation operator
    """
    if x is None and y is None:
        return {'$lte': []}
    return {'$lte': [x, y]}


def escape_commit_message(message):
    """Replace xml-incompatible control characters."""
    import re
    message, _ = re.subn(u'[^\t\n\r -\ud7ff\ue000-�]+', lambda match: match
        .group(0).encode('unicode_escape'), message)
    return message


@classmethod
def get_VRS_model(cls, model):
    """ Decorates a given model with VRS constraints or variables.

            Args:
                model (ModelBase): model to decorate.

            Returns:
                ModelBase: decorated VRS DEA model.
        """
    raise NotImplementedError()


@classmethod
def _usage(cls):
    """
        Command line usage string for this class
        """
    return 'usage: python [script path|executable path|--help]'


def minmax(a, b):
    """ `default` argument cannot be used, because the C level function doesn't have a default value
		but an overload.
	"""
    if a <= b:
        return a, b
    else:
        return b, a


@classmethod
def getRecord(cls, node):
    """ fetches record name or query from datasource node

        :param node: datasource node
        :type node: :class:`lxml.etree.Element`
        :returns: record name or query
        :rtype: :obj:`str`
        """
    withRec = ['CLIENT', 'TANGO']
    withQuery = ['DB']
    if node.tag == 'datasource':
        dsource = node
    else:
        dsource = node.find('.//datasource')
    dstype = dsource.attrib['type']
    res = ''
    if dstype and dstype in withRec:
        host = None
        port = None
        dname = None
        rname = None
        member = None
        device = dsource.findall('device')
        if device is not None and len(device) > 0:
            host = device[0].get('hostname')
            port = device[0].get('port')
            dname = device[0].get('name')
            member = device[0].get('member')
        surfix = ''
        prefix = ''
        if member or member != 'attribute':
            if member == 'property':
                prefix = '@'
            elif member == 'command':
                surfix = '()'
        record = dsource.findall('record')
        if record is not None and len(record) > 0:
            rname = record[0].get('name')
            if rname:
                if dname:
                    if host:
                        if not port:
                            port = '10000'
                        res = '%s:%s/%s/%s%s%s' % (host, port, dname,
                            prefix, rname, surfix)
                    else:
                        res = '%s/%s%s%s' % (dname, prefix, rname, surfix)
                else:
                    res = rname
            return res
    elif dstype and dstype in withQuery:
        query = dsource.find('.//query')
        if len(query) and query.strip():
            return query.strip() or ''
    return res


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


@classmethod
def unitSize(cls, value, typeCode=None):
    """Determine unit size of an array (if possible)"""
    try:
        return value.__class__.__min_dimension__
    except AttributeError as err:
        dim = cls.dims(value)[-1]
        value.__class__.__min_dimension__ = dim
        return dim


def get_gdalReadInputs_from_boxImYX(boxImYX):
    """Return row_start,col_start,rows_count,cols_count and assumes boxImYX as [UL_YX,UR_YX,LR_YX,LL_YX)."""
    rS, cS = boxImYX[0]
    clip_sz_x = abs(boxImYX[1][1] - boxImYX[0][1])
    clip_sz_y = abs(boxImYX[0][0] - boxImYX[3][0])
    return cS, rS, clip_sz_x, clip_sz_y


def jsonify(comment_lower: str) ->str:
    """pyNastran: SPOINT={'id':10, 'xyz':[10.,10.,10.]}"""
    sline = comment_lower.split('=')
    rhs = sline[1].rstrip()
    return rhs.replace("'", '"').replace('}', ',}').replace(',,}', ',}')


def p_spec(p):
    """
    spec : spec class
         | spec enum
         | empty
    """
    if len(p) == 2:
        p[0] = []
    else:
        p[0] = p[1] + [p[2]]


def program_name_from_declaration(declaration):
    """
    Determine a program name from a given declaration

    Looks for::

        PROGRAM <program_name>
    """
    for line in declaration.splitlines():
        line = line.strip()
        if line.lower().startswith('program '):
            return line.split(' ')[1]


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 prod(iterable, ignore=False):
    """Takes the product sum of iterable. If ignore=True all elements except those that are None are multiplied.
	If ignore=False, None is returned if any element is None. """
    x = None
    for i in iterable:
        if not i is None:
            if x is None:
                x = i
            else:
                x = x * i
        elif not ignore:
            return None
    return x


def repeat(input, repeats, dim):
    """Repeats elements of an array.

    Parameters
    ----------
    input : Tensor
        Input data array
    repeats : int
        The number of repetitions for each element
    dim : int
        The dim along which to repeat values.

    Returns
    -------
    Tensor
        The obtained tensor.
    """
    pass


def byte_display(size):
    """
    Returns a string with the correct unit (KB, MB), given the size in bytes.
    """
    if size == 0:
        return '0 KB'
    if size <= 1024:
        return '%s bytes' % size
    if size > 1048576:
        return '%0.02f MB' % (size / 1048576.0)
    return '%0.02f KB' % (size / 1024.0)


def is_agent_token_valid(node, token):
    """Validates if a supplied token is valid for the node.

    :param node: Node object
    :token: A token value to validate against the driver_internal_info field
            agent_sercret_token.
    :returns: True if the supplied token matches the token recorded in the
              supplied node object.
    """
    if token is None:
        return False
    known_token = node.driver_internal_info.get('agent_secret_token', None)
    return known_token == token


def __repr__(cls):
    """Generate textual representation for an object of this class"""
    return cls.get_format()


def line_to_js_command_reference(from_point, to_point, curve_name):
    """
    Returning a js script based on reference modelling.
    :param from_point:
    :param to_point:
    :param curve_name:
    :return:
    """
    return curve_name + ' = CreateLineTwoPoints(' + 'point' + str(from_point
        ) + ',' + ' point' + str(to_point) + ');\n'


def to_unicode(s, encoding='utf-8'):
    """Convert to `unicode` string.

    :param s: String to convert.
    :param str encoding: Encoding codec.
    :return: `unicode` string, it's `unicode` in Python 2.x, `str` or `unicode` in Python 3.x.
    :rtype: unicode

    * In Python 2, convert `s` to `unicode` if it's `str` or `bytes`.
    * In Python 2, return original `s` if it's neither `str` or `bytes`.
    * In Python 3, convert `s` to `str` or `unicode` if it's `bytes`.
    * In Python 3, return original `s` if it's not `bytes`.
    * In Python 3, it equals to :func:`to_str`.
    """
    if isinstance(s, bytes):
        return s.decode(encoding)
    else:
        return s