def HTML_Desc(Title, Description, file):
    """
    Write model description in html file.

    :param Title: simulation title (analysis model)
    :type Title : str
    :param Description: model description
    :type Description : str
    :param file: html file object
    :type file : file object
    :return: None
    """
    file.write('
What is ' + Title + ' ?
\n')
    file.write('
' +
        Description + '
\n')


def cut_workload(workload_df, begin_time, end_time):
    """
    Extract any workload dataframe between begin_time and end_time.
    Datafram must contain 'submission_time', 'waiting_time' and
    'execution_time' + 'jobID'  columns.

    Jobs that are queued (submitted but not running) before `begin_time`
    and jobs that are running before `begin_time` and/or after `end_time`
    are cut to fit in this time slice.

    Example with :py:class:`evalys.Workload`:

    >>> from evalys.workload import Workload
    >>> w = Workload.from_csv("./examples/UniLu-Gaia-2014-2.swf")
    >>> cut_w = cut_workload(w.df, 500000, 600000)

    Example with :py:class:`evalys.JobSet`:

    >>> from evalys.jobset import JobSet
    >>> js = JobSet.from_csv("./examples/jobs.csv")
    >>> cut_js = cut_workload(js.df, 1000, 2000)

    """
    assert begin_time < end_time
    df = workload_df.copy()
    contains_starting_time = 'starting_time' in df
    df['starting_time'] = df['submission_time'] + df['waiting_time']
    df = df.sort_values(by='submission_time').set_index(['submission_time'],
        drop=False)
    begin = df.index.searchsorted(begin_time)
    end = df.index.searchsorted(end_time)
    to_export = df.iloc[begin:end]
    queued_jobs = df[(df['submission_time'] < begin_time) & (df[
        'starting_time'] >= begin_time)]
    running_jobs = df[(df['starting_time'] < begin_time) & (df[
        'starting_time'] + df['execution_time'] > begin_time)]
    if not contains_starting_time:
        to_export.drop('starting_time', inplace=True, axis=1)
        queued_jobs.drop('starting_time', inplace=True, axis=1)
        running_jobs.drop('starting_time', inplace=True, axis=1)
    return {'workload': to_export.sort_values(by='jobID').reset_index(drop=
        True), 'queue': queued_jobs.sort_values(by='jobID').reset_index(
        drop=True), 'running': running_jobs.sort_values(by='jobID').
        reset_index(drop=True)}


def get_streak(series, start_index, window):
    """Calculate the current streak.

    Parameters
    ----------
    series : pandas.Series
        A Boolean series for calculating streaks.
    start_index : int
        The offset of the series to start counting.
    window : int
        The period over which to count.

    Returns
    -------
    streak : int
        The count value for the current streak.

    """
    if window <= 0:
        window = len(series)
    i = start_index
    streak = 0
    while i >= 0 and start_index - i + 1 < window and series[i]:
        streak += 1
        i -= 1
    return streak


def edge_loops_from_edges(mesh, edges=None):
    """closed loops have matching start and end values.

    """
    pass


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

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


def uri_to_api_uri(uri):
    """Convert any uri to api uri.

    Provided uri as
    https://10.150.198.98/api/vdc/93b5fa47-d571-4d71-9caf-7af6ed4fab1f will be
    converted to https://10.150.198.98/api.

    :param uri
    :return api_uri
    :rtype str
    """
    uri_components = uri.split('/')
    api_uri = '/'.join(uri_components[:4])
    return api_uri


@classmethod
def from_text(cls, text):
    """Create a QColor from specified string"""
    color = cls()
    text = str(text)
    if text.startswith('#') and len(text) == 7:
        correct = '#0123456789abcdef'
        for char in text:
            if char.lower() not in correct:
                return color
    elif text not in list(cls.colorNames()):
        return color
    color.setNamedColor(text)
    return color


def _get_blank_value_19(field):
    """Get the value for blank fields in Django 1.9 and later."""
    if field.null:
        return None
    else:
        return ''


def safeget(dct, *keys):
    """ Recursive function to safely access nested dicts or return None.
    param dict dct: dictionary to process
    param string keys: one or more keys"""
    for key in keys:
        try:
            dct = dct[key]
        except KeyError:
            return None
    return dct


def is_exact(needle, haystack, start, end, matchnot):
    """Check exact occurrence of needle in haystack"""
    return (start >= 0 and end < len(haystack) and haystack[start:end] ==
        needle) ^ matchnot


@classmethod
def _formata_trace_back(cls, trace_back):
    """
        Formata o trace back como uma lista de dicionários no seguinte formato:
        {
            'codigo': '    a = 1 / 0',
            'local': '..unitarios/padroes/test_serializacao.py, line 318, in test_deve_retornar_resposta_para_erro_500_com_trace_back_passado'
        }
        :param trace_back: O traceback da exceção
        :type trace_back: list
        :return: A lista de traceback formatada
        :rtype: list
        """
    resultado = []
    for stack in trace_back[-4:-1]:
        linhas = stack.split('\n')
        local = linhas[0].split(', ')
        local[0] = local[0].strip()
        local[0] = local[0].replace('File "', '').replace('"', '')
        local[0] = '..{}'.format('/'.join(local[0].split('/')[-3:]))
        local = ', '.join(local)
        if not local.startswith('..Traceback '):
            resultado.append({'local': local, 'codigo': linhas[1]})
    return resultado


def write_xyz(crystal, fname, comment=None):
    """
    Generate an atomic coordinates .xyz file from a crystal structure.

    Parameters
    ----------
    crystal : crystals.Crystal
        Crystal to be converted.
    fname : path-like
        The XYZ file will be written to this file. If the file already exists,
        it will be overwritten.
    comment : str or None, optional
        Comment to include at the second line of ``fname``.
    """
    comment = comment or ''
    with open(fname, 'wt', encoding='ascii') as file:
        file.write(str(len(crystal)) + '\n')
        file.write(comment + '\n')
        for atom in crystal.itersorted():
            x, y, z = atom.coords_cartesian
            row = (
                f'  {atom.element:<2}       {x:10.5f}       {y:10.5f}       {z:10.5f}'
                )
            file.write(row + '\n')


def checkuniqueid(myserie):
    """
    check if each value in a pandas.Series is unique
    :param myserie: pandas.Series to be checked
    :return: boolean
    """
    if myserie.unique().shape[0] == myserie.shape[0]:
        return True
    else:
        print('{:.0%}'.format(myserie.unique().shape[0] / myserie.shape[0]),
            ' of values unique')
        return False


def gen_neighborhood(data, row, col):
    """
    Generate 3x3 neighborhood of selected pixel
    If near the edge generate the truncated neighborhood
    to avoid index out-of-bounds errors
    :param data: 2d numpy array
    :param row: integer row index
    :param col: integer col index
    :return data: sub-slice of original data array
    """
    min_row = 0
    min_col = 0
    max_row = data.shape[0] - 1
    max_col = data.shape[1] - 1
    if min_row < row < max_row and min_col < col < max_col:
        return data[row - 1:row + 2, col - 1:col + 2]
    elif (row, col) == (min_row, min_col):
        return data[row:row + 2, col:col + 2]
    elif (row, col) == (min_row, max_col):
        return data[row:row + 2, col - 1:col + 1]
    elif (row, col) == (max_row, max_col):
        return data[row - 1:row + 1, col - 1:col + 1]
    elif (row, col) == (max_row, min_col):
        return data[row - 1:row + 1, col:col + 2]
    elif row == min_row:
        return data[row:row + 2, col - 1:col + 2]
    elif col == max_col:
        return data[row - 1:row + 2, col - 1:col + 1]
    elif row == max_row:
        return data[row - 1:row + 1, col - 1:col + 2]
    else:
        return data[row - 1:row + 2, col:col + 2]


def gff2to3_parser(subparsers):
    """
    Parser for the gff2to3 tool.
    """
    parser = subparsers.add_parser('gff2to3', help=
        'convert a GFF2 file to the GFF3 format', description=
        'Convert a GFF2 file to the GFF3 format')
    parser.add_argument('gff2_file', help='a GFF2 file')
    parser.add_argument('output_file', help='the output GFF3 file')
    parser.add_argument('-i', '--ignore_incorrect_records', action=
        'store_true', help=
        'ignore incorrect records in the specified input GFF2 file')


def bytes_to_text(s, encoding):
    """
    Convert bytes objects to strings, using the given encoding. Illegally
    encoded input characters are replaced with Unicode "unknown" codepoint
    (�).

    Return any non-bytes objects without change.
    """
    if isinstance(s, bytes):
        return str(s, encoding, 'replace')
    else:
        return s


def count_variables(expr):
    """Count variables with the same value.

        >>> count_variables('xxy')
        {
            'x': 2,
            'y': 1
        }
    """
    result = {}
    variables = []
    for x in list(expr):
        if x not in variables:
            variables.append(x)
    for x in variables:
        result[x] = expr.count(x)
    return result


def clsinit_copy(cls):
    """ Initializes template information (i.e. attributes and traces)
    on classes derived from the ResourceManager class.
    It differs from the clsinit method in that it forces inheritance
    of attributes and traces from the parent class.

    It is used as a decorator in the class declaration as follows:

        @clsinit
        class MyResourceManager(ResourceManager):

            ...

    clsinit_copy should be prefered to clsinit when creating new
    ResourceManager child classes.

    """
    cls._clsinit_copy()
    return cls


@classmethod
def get_BZ_integration_grid_shift_Z(cls, calc, **kwargs):
    """Return the shift of the Brillouin zone points along reciprocal lattice vector Z."""
    array = cls._get_BZ_integration_grid_shift(calc, **kwargs)
    if array is not None:
        return array[2]


def Joule_Thomson(T, V, Cp, dV_dT=None, beta=None):
    """
    Calculate a real fluid's Joule Thomson coefficient. The required
    derivative should be calculated with an equation of state, and `Cp` is the
    real fluid versions. This can either be calculated with `dV_dT` directly,
    or with `beta` if it is already known.

    .. math::
        \\mu_{JT} = \\left(\\frac{\\partial T}{\\partial P}\\right)_H = \\frac{1}{C_p}
        \\left[T \\left(\\frac{\\partial V}{\\partial T}\\right)_P - V\\right]
        = \\frac{V}{C_p}\\left(\\beta T-1\\right)

    Parameters
    ----------
    T : float
        Temperature of fluid, [K]
    V : float
        Molar volume of fluid, [m^3/mol]
    Cp : float
        Real fluid heat capacity at constant pressure, [J/mol/K]
    dV_dT : float, optional
        Derivative of `V` with respect to `T`, [m^3/mol/K]
    beta : float, optional
        Isobaric coefficient of a thermal expansion, [1/K]

    Returns
    -------
    mu_JT : float
        Joule-Thomson coefficient [K/Pa]

    Examples
    --------
    Example from [2]_:

    >>> Joule_Thomson(T=390, V=0.00229754, Cp=153.235, dV_dT=1.226396e-05)
    1.621956080529905e-05

    References
    ----------
    .. [1] Walas, Stanley M. Phase Equilibria in Chemical Engineering.
       Butterworth-Heinemann, 1985.
    .. [2] Pratt, R. M. "Thermodynamic Properties Involving Derivatives: Using
       the Peng-Robinson Equation of State." Chemical Engineering Education 35,
       no. 2 (March 1, 2001): 112-115.

    """
    if dV_dT:
        return (T * dV_dT - V) / Cp
    elif beta:
        return V / Cp * (beta * T - 1.0)
    else:
        raise Exception('Either dV_dT or beta is needed')


def get_slice_coord(bounds, n):
    """
    Given the bounds of an actor, return the point that
    corresponds to the n% of the bounds range

    :param bounds: should be a list of two floats
    :param n: n should be a float in range 0, 1

    """
    if not isinstance(bounds, (list, tuple)) or not isinstance(bounds[0], float
        ) or not isinstance(bounds[1], float):
        raise ValueError('bounds should be a list or tuple of floats: {}'.
            format(bounds))
    if not isinstance(n, (int, float)):
        raise ValueError('n should be a float')
    if n < 0 or n > 1:
        raise ValueError('n should be in range [0, 1]')
    b0, b1 = bounds
    delta = b1 - b0
    return b0 + delta * n


@classmethod
def send_all(cls, force=False):
    """Send all pending documents to the recipients."""
    if force:
        documents = cls.query
    else:
        documents = cls.query.filter(cls.to_be_send)
    documents = documents.order_by(cls.priority)
    for document in documents:
        fragments = document.send(force=force)
        try:
            for fragment in fragments:
                yield fragment
        except GeneratorExit:
            fragments.close()
            raise


@staticmethod
def __yes_no_only(s):
    """Helper for parameters expecting ['yes', 'no', 'only']"""
    s = str(s).lower()
    if s in ['true', 'yes']:
        s = 'yes'
    elif s in ['false', 'no']:
        s = 'no'
    return s


@classmethod
def request_from(cls, ar, *args, **kwargs):
    """
        Return an action request on this actor which inherits from the
        given parent request.
        """
    sar = cls.request(*args, **kwargs)
    sar.setup_from(ar)
    return sar


@staticmethod
def search_file_pattern(path, pattern, start_address=0, chunk_size=0,
    chunk_limit=0, find_all=True):
    """
        Yields addresses of matching byte patterns inside a file.

        Supports wildcard bytes, a starting address, reading in chunks, and
        read limits.

        Args:
            path (str): A file path.
            pattern (str): A sequence of bytes, e.g. 'FF ?? E8 26 23 D7'.
                '??' represents a single byte wildcard. Spaces between bytes
                are optional.
            start_address (int, optional): Search start address.
            chunk_size (int, optional): The read length per chunk. By default,
                chunks are not used and the entire file is read into memory.
            chunk_limit (int, optional): The maximum number of chunks to read.
                By default, all chunks are read.
            find_all (bool, optional): If True, all found instances are
                yielded. If False, only the first found instance is yielded
                and searching stops.

        Yields:
            int: Found address.

        Example:
            import invade
            found_addresses = []
            for found_address in tool.search_file_pattern(
                    r'C:	arget.exe',
                    '?? 01 55 ?? ?? 4B 20 1E 1D ?? 15',
                    start_address=0x1000,
                    chunk_size=1024,
                    chunk_limit=10,
                    find_all=False):
                found_addresses.append(found_address)
            for address in found_addresses:
                print(hex(address))
        """
    pattern = ''.join(pattern.split())
    if not path or len(pattern) < 2 or len(pattern) % 2 != 0 or pattern.count(
        '?') == len(pattern):
        return
    if chunk_size == 0:
        chunk_size = -1
    if chunk_limit == 0:
        chunk_limit = -1
    pattern_largest_segment = list(filter(None, pattern.split('??')))
    pattern_largest_segment.sort(key=len, reverse=True)
    pattern_largest_segment = pattern_largest_segment[0]
    pattern_largest_segment_position = pattern.index(pattern_largest_segment
        ) // 2
    pattern_largest_segment = bytes.fromhex(pattern_largest_segment)
    if pattern.count('?') == 0:
        pattern_bytes = bytes.fromhex(pattern)
        chunk_position = 0
        with open(path, 'rb') as f:
            if start_address > 0:
                f.seek(start_address)
            while True:
                if chunk_limit > 0:
                    if chunk_position / chunk_size >= chunk_limit:
                        return
                try:
                    data = f.read(chunk_size)
                except MemoryError:
                    return
                if not data:
                    return
                i = 0
                found_position = 0
                while True:
                    try:
                        found_position = data.index(pattern_bytes,
                            found_position + i)
                        if chunk_size > 0:
                            yield chunk_position + found_position + start_address
                        else:
                            yield found_position + start_address
                        if find_all is False:
                            return
                    except ValueError:
                        break
                    i += 1
                chunk_position += chunk_size
                continue
    pattern_wildcard_positions = []
    for i in range(0, len(pattern), 2):
        pattern_byte = pattern[i:i + 2]
        if pattern_byte == '??':
            pattern_wildcard_positions.append(i // 2)
    pattern_len = len(pattern) // 2
    pattern_bytes = pattern.replace('?', '')
    pattern_bytes = bytes.fromhex(pattern_bytes)
    possible_positions = []
    end_of_file = False
    first_result = True
    chunk_position = 0
    with open(path, 'rb') as f:
        if start_address > 0:
            f.seek(start_address)
        while not end_of_file:
            if chunk_limit > 0:
                if chunk_position / chunk_size >= chunk_limit:
                    return
            try:
                data = f.read(chunk_size)
            except MemoryError:
                return
            if not data:
                end_of_file = True
            chunk_search = True
            while chunk_search:
                try:
                    if first_result is True:
                        possible_positions.append(data.index(
                            pattern_largest_segment))
                        first_result = False
                    else:
                        possible_positions.append(data.index(
                            pattern_largest_segment, possible_positions[-1] +
                            1))
                except ValueError:
                    if chunk_size > 0:
                        chunk_position += chunk_size
                    chunk_search = False
            for possible_position in possible_positions:
                possible_position -= pattern_largest_segment_position
                match_count = 0
                pattern_bytes_pos = 0
                data_offset_pos = 0
                i = 0
                while i < pattern_len:
                    if i in pattern_wildcard_positions:
                        match_count += 1
                        data_offset_pos += 1
                        i += 1
                        continue
                    if possible_position < 0:
                        possible_position = 0
                    if pattern_bytes[pattern_bytes_pos] == data[
                        possible_position + data_offset_pos]:
                        match_count += 1
                        data_offset_pos += 1
                        pattern_bytes_pos += 1
                        i += 1
                        continue
                    i += 1
                if match_count == pattern_len:
                    if find_all is True:
                        if chunk_size > 0:
                            yield chunk_position + possible_position + start_address - chunk_size
                        else:
                            yield possible_position + start_address
                    else:
                        yield possible_position + chunk_position + start_address - chunk_size
                        return
            possible_positions = []
            first_result = True
        return


def _form_response(role, origin, response, timestamp):
    """Form a VOEvent Transport Protocol packet suitable for sending an `ack`
    or `iamalive` response."""
    return (
        '<?xml version=\'1.0\' encoding=\'UTF-8\'?><trn:Transport role="' +
        role +
        '" version="1.0" xmlns:trn="http://telescope-networks.org/schema/Transport/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://telescope-networks.org/schema/Transport/v1.1 http://telescope-networks.org/schema/Transport-v1.1.xsd"><Origin>'
         + origin + '</Origin><Response>' + response +
        '</Response><TimeStamp>' + timestamp + '</TimeStamp></trn:Transport>'
        ).encode('UTF-8')


def resource_isdir(resource_name):
    """Is the named resource a directory?  (like ``os.path.isdir()``)"""


def cancel_schema_extension(DirectoryId=None, SchemaExtensionId=None):
    """
    Cancels an in-progress schema extension to a Microsoft AD directory. Once a schema extension has started replicating to all domain controllers, the task can no longer be canceled. A schema extension can be canceled during any of the following states; Initializing , CreatingSnapshot , and UpdatingSchema .
    See also: AWS API Documentation

    :example: response = client.cancel_schema_extension(
        DirectoryId='string',
        SchemaExtensionId='string'
    )

    :type DirectoryId: string
    :param DirectoryId: [REQUIRED]
            The identifier of the directory whose schema extension will be canceled.

    :type SchemaExtensionId: string
    :param SchemaExtensionId: [REQUIRED]
            The identifier of the schema extension that will be canceled.

    :rtype: dict
    :return: {}

    :returns:
    (dict) --

    """
    pass


def phase_structure(phase_a, phase_b, axis=-1):
    """Structure function for phase fluctuations.

    See Daigle, equation 18.

    The last term accounts for the fact that the mean phase difference of the signals may be nonzero.
    """
    return ((phase_a - phase_b) ** 2.0).mean(axis=axis) - (phase_a - phase_b
        ).mean(axis=axis) ** 2.0


def options(opt):
    """
	Load the :py:mod:`waflib.Tools.gnu_dirs` tool and add the ``--vala-target-glib`` command-line option
	"""
    opt.load('gnu_dirs')
    valaopts = opt.add_option_group('Vala Compiler Options')
    valaopts.add_option('--vala-target-glib', default=None, dest=
        'vala_target_glib', metavar='MAJOR.MINOR', help=
        'Target version of glib for Vala GObject code generation')


def proc_depends_setter(this, value):
    """Try to convert all possible dependencies to processes"""
    from .pyppl import _anything2procs
    depends = _anything2procs(value, procset='ends')
    try:
        prev_depends = this._depends
    except KeyError:
        prev_depends = []
    for prevdep in prev_depends:
        prevdep.nexts.remove(this)
    for depend in depends:
        depend.nexts.append(this)
    return depends


def fill_model_instance(instance, data):
    """
    Fill whatever fields possible in `instance` using the data dict.
    :param instance:
    :param data:
    """
    for field in instance._meta.fields:
        if not field.editable or field.name not in data:
            continue
        field.save_form_data(instance, data[field.name])
    return instance


@classmethod
def is_router_api_root(cls, callback):
    """
        If URL's callback is rest_framework.routers.APIRoot returns True
        """
    if callback.__module__ == 'rest_framework.routers':
        return True


def get_motif(seq_full, motif, mode='counts'):
    """get the counts of motif in a sequence"""
    cnt = 0
    if len(seq_full) < len(motif):
        return cnt
    for i in range(len(seq_full) - len(motif) + 1):
        if seq_full[i:i + len(motif)] == motif:
            cnt += 1
    if mode == 'counts':
        return cnt
    elif mode == 'frequency':
        return cnt / (len(seq_full) - len(motif) + 1.0)
    elif mode == 'normalized':
        return cnt / (len(seq_full) - len(motif) + 1.0) / 0.25 ** len(motif)
    else:
        return None


@staticmethod
def uncompress_public_key(public_key):
    """
        Converts compressed public keys to uncompressed public keys

        Compressed public key:
                   ┌ 0x02 + x, if y mod 2 = 0
         f(x, y) = │
                   └ 0x03 + x, if y mod 2 = 1
        Uncompressed public key:
         f(x,y) = x + y

        https://bitcointalk.org/index.php?topic=644919
        :param public_key: compressed public key (string)
        :return: uncompressed public key (string)
        """
    p = (
        115792089237316195423570985008687907853269984665640564039457584007908834671663
        )
    y_parity = int(public_key[:2]) - 2
    x = int(public_key[2:], 16)
    a = (pow(x, 3, p) + 7) % p
    y = pow(a, (p + 1) // 4, p)
    y = -y % p if y % 2 != y_parity else y
    return '{:x}{:x}'.format(x, y)


def setBit(val: int, bitNo: int):
    """
    Set a specified bit to '1'
    """
    return val | 1 << bitNo


def remove_null_values(dictionary):
    """
    Removed values that are None

    :param dictionary: The dictionary in which to remove None values
    """
    keys = list(dictionary.keys())
    for key in keys:
        if dictionary[key] is None:
            del dictionary[key]


def preloaded_multi_sgd_update(*data, **kwargs):
    """Update function for Stochastic Gradient Descent (SDG) optimizer.

    It updates the weights using::

     weight = weight - learning_rate * (gradient + wd * weight)

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

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

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

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


@classmethod
def clean_env(cls, content: dict) ->dict:
    """
        Given the content of the Travis CI configuration file,
        we clean the env entries.
        """
    to_delete = ['matrix']
    if 'env' in content:
        for env_var in to_delete:
            if env_var in content['env']:
                del content['env'][env_var]
    return content


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


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

    This ends up working like ``from module import object`` but is easier
    to deal with than the `__import__` builtin and supports digging into
    submodules.

    Parameters
    ----------

    name : `str`
        A dotted path to a Python object--that is, the name of a function,
        class, or other object in a module with the full path to that module,
        including parent modules, separated by dots.  Also known as the fully
        qualified name of the object.

    additional_parts : iterable, optional
        If more than one positional arguments are given, those arguments are
        automatically dotted together with ``name``.

    Examples
    --------

    >>> resolve_name('astropy.utils.introspection.resolve_name')
    <function resolve_name at 0x...>
    >>> resolve_name('astropy', 'utils', 'introspection', 'resolve_name')
    <function resolve_name at 0x...>

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


def rangify(number_list):
    """Assumes the list is sorted."""
    if not number_list:
        return number_list
    ranges = []
    range_start = prev_num = number_list[0]
    for num in number_list[1:]:
        if num != prev_num + 1:
            ranges.append((range_start, prev_num))
            range_start = num
        prev_num = num
    ranges.append((range_start, prev_num))
    return ranges


def rotate(use_cursor_init: bool=True):
    """Rotate the view

    :param use_cursor_init: Use Mouse Position, Allow the initial mouse position to be used
    :type use_cursor_init: bool
    """
    pass


def undo_history(item: int=0):
    """Redo specific action in history

    :param item: Item
    :type item: int
    """
    pass


def parse_url_querystring(querystring_dict):
    """
    Parse URL query strings dictionaries like {'a': ['123'], 'b[]': ['one', 'two']}
    to appropriate dictionaries ({'a': '123', 'b': ['one', 'two']})

    :param querystring_dict: querystring dictionary
    :type querystring_dict: dict
    :return: dict -- parsed and flatted querystring dictionary
    """
    result = {}
    for k in querystring_dict:
        if k.endswith('[]'):
            key = k[:-2]
            result[key] = querystring_dict[k]
        else:
            result[k] = querystring_dict[k][0]
    return result


def startup():
    """ dummy function populate the process pool """
    return 'Starting.'


def bindmount(s, recursive=False, readonly=False):
    """Argparse argument type for bind mount variants."""
    opts = {'recursive': recursive, 'readonly': readonly}
    return {s: opts}


def copy_to(target):
    """
        Copies the context object to the target.
        Submits copy for review.

        :param target: Target folder to copy to.
        :type target: ILibraryFolder.
        :returns: The newly created copy object.
        :rtype: IDexterityContent (same as self.context)
        """


@classmethod
def enabled(cls):
    u"""
        Returns: True always!
        """
    return True


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

        :param GroupChangeExternalIdType val:
        :rtype: EventType
        """
    return cls('group_change_external_id', val)


def available_formats():
    """Returns a list of all supported file-types"""
    return ['fasta-dna', 'fasta-aa', 'fastq']


def get_component_registry(context=None):
    """Get the nearest site manager in the given context.

        If `context` is `None`, return the global site manager.

        If the `context` is not `None`, it is expected that an adapter
        from the `context` to `IComponentLookup` can be found. If no
        adapter is found, a `ComponentLookupError` is raised.

        """


def typename(x):
    """
    <type 'list'>(16),file_St:<type 'str'>(38),RSbm:<type 'float'>(0.163),St:<type 'list'>(1540),nSf:<type 'int'>(2),RSbt:<type 'float'>(0.999),nP:<type 'int'>(944),Sb:<type 'list'>(1538),d_FSs:<type 'collections.defaultdict'>(16),Sf:<type 'list'>(2),cjName:<type 'str'>(2),nSm:<type 'int'>(9440),d_SF:<class 'collections.Counter'>(1538),nSb:<type 'int'>(1538),file_d_StFP:<type 'str'>(47),file_d_SF:<type 'str'>(40),RSmt:<type 'float'>(6.13),file_S:<type 'str'>(37),nSt:<type 'int'>(1540),iS:<type 'int'>(2),file_d_StFP_c:<type 'str'>(47)}
    """
    return str(type(x)).replace("'", '').split(' ')[-1][:-1]


def count_digits(value):
    """
    Count of digits of given number.

    :param value: integer value (can also be negative)
    :returns: count of digits of given number

    >>> count_digits(0)
    1
    >>> count_digits(1024)
    4
    >>> count_digits(1234567890)
    10
    >>> count_digits(-1234567890)
    10
    """
    if 0 == value:
        return 1
    value = abs(value)
    result = 0
    while value > 0:
        result += 1
        value //= 10
    return result


@staticmethod
def from_moments2d(mom):
    """Creates an ellipse whose moments match with the given moments.

        :Parameters:
            mom : moments2d
                a collection of moments up to 2nd order in 2D

        :Returns:
            retval : ellipse
                an ellipse whose interior generates moments that match with the given collection of moments
        """
    return None


def get_track_id_from_json(item):
    """ Try to extract video Id from various response types """
    fields = ['contentDetails/videoId', 'snippet/resourceId/videoId',
        'id/videoId', 'id']
    for field in fields:
        node = item
        for p in field.split('/'):
            if node and isinstance(node, dict):
                node = node.get(p)
        if node:
            return node
    return ''


def _is_url_without_path_query_or_fragment(url_parts):
    """
    Determines if a URL has a blank path, query string and fragment.

    :param url_parts: A URL.
    :type url_parts:  :class:`urlparse.ParseResult`
    """
    return url_parts.path.strip('/'
        ) == '' and url_parts.query == '' and url_parts.fragment == ''


def set_sym_y_labels(axis, mean=None):
    """
    Set symmetric y-limits for the specified axis.
    """
    low, upp = axis.get_ylim()
    if mean is None:
        mean = (upp - low) / 2
    if mean - low <= upp - mean:
        upp_ = upp
        low_ = mean - (upp - mean)
    else:
        upp_ = mean + (mean - low)
        low_ = low
    axis.set_ylim(low_, upp_)


def changeAdded(change):
    """A new Change was added to the ChangeMaster.  By the time this event
        is received, all schedulers have already received the change."""


def frameReceived(opcode, data, fin):
    """
        Callback when a frame is received.
        """


def process_variable_band(report, element):
    """
    Process jrxml variable element.
    :param report: dictionary holding report information
    :param element:
    """
    pass


@staticmethod
def parse(name):
    """
        Parse a name with the given convention into a tuple of "words".

        For example, an input of 'OnNavigationPanel_LeftDown' would result in
        an output of `('navigation_panel', 'left_down')`.

        Returns `None` if there is no match.
        """
    if not name.startswith('On'):
        return None
    cleaned_name = name[2:]
    words = tuple(cleaned_name.split('_'))
    return words


def set(key, value):
    """ Store value for 'key'.

        o Return a boolean to indicate success.
        """


def type_object_attrgetter(obj, attr, *defargs):
    """
    This implements an improved attrgetter for type objects (i.e. classes)
    that can handle class attributes that are implemented as properties on
    a metaclass.

    Normally `getattr` on a class with a `property` (say, "foo"), would return
    the `property` object itself.  However, if the class has a metaclass which
    *also* defines a `property` named "foo", ``getattr(cls, 'foo')`` will find
    the "foo" property on the metaclass and resolve it.  For the purposes of
    autodoc we just want to document the "foo" property defined on the class,
    not on the metaclass.

    For example::

        >>> class Meta(type):
        ...     @property
        ...     def foo(cls):
        ...         return 'foo'
        ...
        >>> class MyClass(metaclass=Meta):
        ...     @property
        ...     def foo(self):
        ...         ""\"Docstring for MyClass.foo property.""\"
        ...         return 'myfoo'
        ...
        >>> getattr(MyClass, 'foo')
        'foo'
        >>> type_object_attrgetter(MyClass, 'foo')
        <property at 0x...>
        >>> type_object_attrgetter(MyClass, 'foo').__doc__
        'Docstring for MyClass.foo property.'

    The last line of the example shows the desired behavior for the purposes
    of autodoc.
    """
    for base in obj.__mro__:
        if attr in base.__dict__:
            if isinstance(base.__dict__[attr], property):
                return base.__dict__[attr]
            break
    return getattr(obj, attr, *defargs)


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


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


def select_circle(x: int=0, y: int=0, radius: int=1, gesture_mode: int=0):
    """Select items using circle selection

    :param x: X
    :type x: int
    :param y: Y
    :type y: int
    :param radius: Radius
    :type radius: int
    :param gesture_mode: Event Type
    :type gesture_mode: int
    """
    pass


def hatodot(A, B):
    """ should be implemented in C """
    import scipy as sp
    A1 = sp.kron(A, sp.ones((1, B.shape[1])))
    B1 = sp.kron(sp.ones((1, A.shape[1])), B)
    return A1 * B1


def cellname(cell, delim=' '):
    """Consistent ``str`` representation for cells.

    * for Factor cells: the cell (str)
    * for Interaction cell: delim.join(cell).

    """
    if isinstance(cell, str):
        return cell
    elif isinstance(cell, (list, tuple)):
        return delim.join(cell)
    elif cell is None:
        return ''
    else:
        return str(cell)


def addrevision(revisiondata, transaction, linkrev, p1, p2, node=None,
    flags=0, cachedelta=None):
    """Add a new revision to the store.

        This is similar to ``add()`` except it operates at a lower level.

        The data passed in already contains a metadata header, if any.

        ``node`` and ``flags`` can be used to define the expected node and
        the flags to use with storage. ``flags`` is a bitwise value composed
        of the various ``REVISION_FLAG_*`` constants.

        ``add()`` is usually called when adding files from e.g. the working
        directory. ``addrevision()`` is often called by ``add()`` and for
        scenarios where revision data has already been computed, such as when
        applying raw data from a peer repo.
        """


def my_range(num_values):
    """Generate numbers from 0..num_values-1"""
    value = 0
    while value < num_values:
        yield value
        value += 1


def graph_key_from_tag(tag, entity_index):
    """Returns a key from a tag entity

    Args:
        tag (tag) : this is the tag selected to get the key from
        entity_index (int) : this is the index of the tagged entity

    Returns:
        str : String representing the key for the given tagged entity.
    """
    start_token = tag.get('start_token')
    entity = tag.get('entities', [])[entity_index]
    return str(start_token) + '-' + entity.get('key') + '-' + str(entity.
        get('confidence'))


@classmethod
def get_field(cls, stream, name, context=None):
    """Return the value of a single field.

        If the field is at a fixed byte offset from the beginning of the struct,
        it'll be read directly.

        If the field isn't at a fixed offset from the beginning of the struct
        (e.g. a variable-length field occurs before it) then the entire struct
        up to and including this field must be read. Unfortunately, this means
        that unrelated validation errors can be thrown if other fields have
        problems.

        :param io.BufferedIOBase stream:
            The stream to read from. It's assumed that the stream pointer is
            positioned at the start of a struct. The stream pointer is returned
            to its original position even if an exception occurred.
        :param str name:
            The name of the field to retrieve.
        :param context:
            Optional. Any object containing extra information to pass to the
            :meth:`~binobj.fields.base.Field.from_stream` method of the field.
            For fields located at a variable offset, this will be passed to the
            :meth:`~binobj.fields.base.Field.from_stream` method of *each* field
            read.

        :return: The value of the field in the struct data.

        :raise UnexpectedEOFError:
            The end of the stream was reached before the requested field could
            be completely read.
        """
    if name not in cls.__binobj_struct__.components:
        raise ValueError("%s doesn't have a field named %r." % (cls.
            __name__, name))
    field = cls.__binobj_struct__.components[name]
    original_offset = stream.tell()
    if field.offset is not None:
        try:
            stream.seek(original_offset + field.offset)
            return field.from_stream(stream, context, {})
        finally:
            stream.seek(original_offset)
    try:
        loaded_data = cls.partial_load(stream, name, context)
    finally:
        stream.seek(original_offset)
    return loaded_data[name]


def delete_orientation():
    """Delete transformation orientation

    """
    pass


def edge_id(data=None, u=None, v=None, name=None, attr=None, out=None, **kwargs
    ):
    """This operator implements the edge_id function for a graph
    stored in a CSR matrix (the value of the CSR stores the edge Id of the graph).
    output[i] = input[u[i], v[i]] if there is an edge between u[i] and v[i]],
    otherwise output[i] will be -1. Both u and v should be 1D vectors.

    Example:

       .. code:: python

          x = [[ 1, 0, 0 ],
               [ 0, 2, 0 ],
               [ 0, 0, 3 ]]
          u = [ 0, 0, 1, 1, 2, 2 ]
          v = [ 0, 1, 1, 2, 0, 2 ]
          edge_id(x, u, v) = [ 1, -1, 2, -1, -1, 3 ]

    The storage type of ``edge_id`` output depends on storage types of inputs
      - edge_id(csr, default, default) = default
      - default and rsp inputs are not supported

    Defined in src/operator/contrib/dgl_graph.cc:L1321

    Parameters
    ----------
    data : Symbol
        Input ndarray
    u : Symbol
        u ndarray
    v : Symbol
        v ndarray

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

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


def set_level(request, level):
    """
    Sets the minimum level of messages to be recorded, returning ``True`` if
    the level was recorded successfully.

    If set to ``None``, the default level will be used (see the ``get_level``
    method).
    """
    if not hasattr(request, '_messages'):
        return False
    request._messages.level = level
    return True


def get_nominal_integer_dict(nominal_vals):
    """
    Takes a set of nominal values (non-numeric)
    and returns a dictionary that maps each value
    to a unique integer
    """
    d = {}
    for val in nominal_vals:
        if val not in d:
            current_max = max(d.values()) if len(d) > 0 else -1
            d[val] = current_max + 1
    return d


def iter_nearest_neighbours(umis, substr_idx):
    """
    Added by Matt 06/05/17
    use substring dict to get (approximately) all the nearest neighbours to
    each in a set of umis.
    """
    for i, u in enumerate(umis, 1):
        neighbours = set()
        for idx, substr_map in substr_idx.items():
            u_sub = u[slice(*idx)]
            neighbours = neighbours.union(substr_map[u_sub])
        neighbours.difference_update(umis[:i])
        for nbr in neighbours:
            yield u, nbr


def google_list_style(style):
    """
    Finds out whether this is an ordered or unordered list

    :type style: dict

    :rtype: str
    """
    if 'list-style-type' in style:
        list_style = style['list-style-type']
        if list_style in ['disc', 'circle', 'square', 'none']:
            return 'ul'
    return 'ol'


def recv_end(the_socket, SOCKET_END_TAG):
    """通过寻找接收的协议数据中的尾标识字符串，获取完整的数据的数据报文"""
    total_data = []
    while True:
        data = the_socket.recv(8192)
        if SOCKET_END_TAG in data:
            total_data.append(data[:data.find(SOCKET_END_TAG)])
            break
        total_data.append(data)
        if len(total_data) > 1:
            last_pair = total_data[-2] + total_data[-1]
            if SOCKET_END_TAG in last_pair:
                total_data[-2] = last_pair[:last_pair.find(SOCKET_END_TAG)]
                total_data.pop()
                break
    if len(total_data) == 0:
        return None
    return b''.join(total_data)


def activate_foreign_keys(sender, connection, **kwargs):
    """Enable integrity constraint with sqlite."""
    if connection.vendor == 'sqlite':
        cursor = connection.cursor()
        cursor.execute('PRAGMA foreign_keys = ON;')


def get_package_class_name(name):
    """
    Return package and class name in a java variant from a typed variant name.

    If no package could be found, the package is an empty string.

    example::

        >>> get_package_class_name('Ljava/lang/Object;')
        ('java.lang', 'Object')

    :param name: the name
    :rtype: tuple
    :return:
    """
    if name[0] != 'L' and name[-1] != ';':
        raise ValueError("The name '{}' does not look like a typed name!".
            format(name))
    name = name[1:-1]
    if '/' not in name:
        return '', name
    package, clsname = name.rsplit('/', 1)
    package = package.replace('/', '.')
    return package, clsname


def get_enduse_from_array_nr(enduse_array_yr_to_get, lookup_enduse):
    """Get enduse string of enduse array number

    Arguments
    ---------
    enduse_array_yr_to_get : int
        Array positoin
    lookup_enduse : dict
        dictionary with enduse and enduse nr

    Returns
    -------
    enduse_str_to_get : str
        Enduse string name
    """
    for enduse_str, enduse_arry_nr in lookup_enduse.items():
        if enduse_arry_nr == enduse_array_yr_to_get:
            enduse_str_to_get = enduse_str
            break
    return enduse_str_to_get


def run_benchmark_test():
    """Run the benchmark test to identify the fastest provider."""


def process_plugins_for(config, options):
    """
    Given a `Coherence` configuration and an object of parsed options, returns
    the configuration based on the supplied options for the plugins.
    """
    plugins = config.get('plugin')
    if isinstance(plugins, dict):
        config['plugin'] = [plugins]
    if not plugins:
        plugins = config.get('plugins', None)
    if not plugins:
        config['plugin'] = []
        plugins = config['plugin']
    while len(options.plugins) > 0:
        p = options.plugins.pop()
        plugin = {}
        plugin_conf = p.split(',')
        for pair in plugin_conf:
            pair = pair.split(':', 1)
            if len(pair) == 2:
                pair[0] = pair[0].strip()
                if pair[0] in plugin:
                    if not isinstance(plugin[pair[0]], list):
                        new_list = [plugin[pair[0]]]
                        plugin[pair[0]] = new_list
                    plugin[pair[0]].append(pair[1])
                else:
                    plugin[pair[0]] = pair[1]
        try:
            plugins.append(plugin)
        except AttributeError:
            print(
                'mixing commandline plugins and configfile does not work with the old config file format'
                )
    return config


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

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


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


def verify_email_address(EmailAddress=None):
    """
    Verifies an email address. This action causes a confirmation email message to be sent to the specified address.
    This action is throttled at one request per second.
    See also: AWS API Documentation

    Examples
    The following example starts the email address verification process with Amazon SES:
    Expected Output:

    :example: response = client.verify_email_address(
        EmailAddress='string'
    )

    :type EmailAddress: string
    :param EmailAddress: [REQUIRED]
            The email address to be verified.

    :return: response = client.verify_email_address(
        EmailAddress='user@example.com',
    )

    print(response)

    """
    pass


def broadcast_mod(lhs=None, rhs=None, name=None, attr=None, out=None, **kwargs
    ):
    """Returns element-wise modulo of the input arrays with broadcasting.

    Example::

       x = [[ 8.,  8.,  8.],
            [ 8.,  8.,  8.]]

       y = [[ 2.],
            [ 3.]]

       broadcast_mod(x, y) = [[ 0.,  0.,  0.],
                              [ 2.,  2.,  2.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_basic.cc:L222

    Parameters
    ----------
    lhs : Symbol
        First input to the function
    rhs : Symbol
        Second input to the function

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

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


def check_int(s):
    """Sourced from helpful post from SO
    https://stackoverflow.com/questions/1265665/how-can-i-check-if-a-string-represents-an-int-without-using-try-except"""
    if s[0] in ('-', '+'):
        return s[1:].isdigit()
    return s.isdigit()


def _polygon_coords(nodes, mesh_polygons):
    """
    Determine each polygons node (x,y) coordinates from _extract_all_polygons()
    """
    poly_coords = []
    for p in mesh_polygons:
        poly_coords.append(nodes[(p - 1), :2])
    return poly_coords


def __len__():
    """Return the number of points.

        Returns
        -------
        positive int
            Number of objects within the file.

        """
    raise NotImplementedError()


def get_user(isamAppliance, user):
    """
    Get permitted features for user
    NOTE: Getting an unexplained error for this function, URL maybe wrong
    """
    return isamAppliance.invoke_get('Get permitted features for user',
        '/authorization/features/users/{0}/v1'.format(user))


def get_con(n, c, attr, pop=False):
    """
    Retrieves constraint references for a given static or time-depending
    attribute of a give component.

    Parameters
    ----------
    n : pypsa.Network
    c : str
        component name to which the constraint belongs
    attr: str
        attribute name of the constraints

    Example
    -------
    get_con(n, 'Generator', 'mu_upper')
    """
    cons = n.cons[c].pnl if n.constraints.pnl[c, attr] else n.cons[c].df
    return cons.pop(attr) if pop else cons[attr]


def active(config):
    """
    Verifies that the signature of a configuration has not timed out.

    :param config:
    :return: True/False
    """
    return True


def _dispatcher_helper(*args, **kwargs):
    """alias for clize.help.DispatcherHelper, avoiding circular import"""
    from clize.help import ClizeHelp, HelpForSubcommands
    return ClizeHelp(*args, builder=HelpForSubcommands.from_subject, **kwargs)


def _round_to_closest(val, res, decimals=None):
    """ round to closest resolution """
    if decimals is None and '.' in str(res):
        decimals = len(str(res).split('.')[1])
    return round(round(val / res) * res, decimals)


def getTrajNum(trajFilename):
    """
        Gets the trajectory number

        :param trajFilename: Trajectory filename
        :type trajFilename: str

        :returns: int -- Trajectory number
    """
    return int(trajFilename.split('_')[-1][:-4])


def _update_bounds_attributes(variables):
    """Adds time attributes to time bounds variables.

    Variables handling time bounds ("Cell boundaries" in the CF
    conventions) do not necessarily carry the necessary attributes to be
    decoded. This copies the attributes from the time variable to the
    associated boundaries.

    See Also:

    http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/
         cf-conventions.html#cell-boundaries

    https://github.com/pydata/xarray/issues/2565
    """
    for v in variables.values():
        attrs = v.attrs
        has_date_units = 'units' in attrs and 'since' in attrs['units']
        if has_date_units and 'bounds' in attrs:
            if attrs['bounds'] in variables:
                bounds_attrs = variables[attrs['bounds']].attrs
                bounds_attrs.setdefault('units', attrs['units'])
                if 'calendar' in attrs:
                    bounds_attrs.setdefault('calendar', attrs['calendar'])


@classmethod
def _images_failed(cls, session, previous_transaction):
    """Deletes the files of :attr:`_stored_images` back and clears
        the :attr:`_stored_images` and :attr:`_deleted_images` set
        when the ongoing transaction has done rollback.

        """
    for image, store in cls._stored_images:
        store.delete(image)
    cls._stored_images.clear()
    cls._deleted_images.clear()


def p_sliceop_2(p):
    """sliceop : COLON test"""
    p[0] = p[2]


def get_colorscale_lut(vis_widget):
    """Retrieve the LUT (lookup table) of a mayavi widget

    not sure this is valid for all mayavi things...

    """
    return vis_widget.module_manager.scalar_lut_manager.lut


@classmethod
def grant(cls, user, database):
    """Query to grant user access to a database."""
    return 'GRANT ALL ON DATABASE "{database}" TO "{user}"'.format(database
        =database, user=user)


def load_class_assets(calling_object, assets_dict):
    """Load class assets. Only call if class_assets_loaded is False."""
    calling_class = type(calling_object)
    for attribute_name in assets_dict:
        setattr(calling_class, attribute_name, assets_dict[attribute_name])
    setattr(calling_class, 'class_assets_loaded', True)


@classmethod
def fromkeys(cls, keys, value=None):
    """ create a new RevisionDict with keys from seq and given value """
    self = cls()
    for key in keys:
        self[key] = value
    return self


def _format_md_label_links(label, links, linkify):
    """Join a string of label and links with formatting."""
    if linkify:
        return '*{lb}* {ls}'.format(lb=label, ls=links)
    else:
        return '*{lb} {ls}*'.format(lb=label, ls=links)


def clear_notebook_parameters(library_db):
    """empties the notebook parameter table"""
    from src.praxxis.sqlite import connection
    conn = connection.create_connection(library_db)
    cur = conn.cursor()
    clear_parameter = 'DELETE FROM "NotebookDefaultParam"'
    cur.execute(clear_parameter)
    conn.commit()
    conn.close()


def getGroupId():
    """ Return the string id of this group, WITHOUT group prefix."""


@classmethod
def _get_backend_owner(cls):
    """
        return class that set_backend() should actually be modifying.
        for SubclassBackendMixin, this may not always be the class that was invoked.
        """
    return cls


def randomize_unitofwork():
    """Use random-ordering sets within the unit of work in order
    to detect unit of work sorting issues.

    This is a utility function that can be used to help reproduce
    inconsistent unit of work sorting issues.   For example,
    if two kinds of objects A and B are being inserted, and
    B has a foreign key reference to A - the A must be inserted first.
    However, if there is no relationship between A and B, the unit of work
    won't know to perform this sorting, and an operation may or may not
    fail, depending on how the ordering works out.   Since Python sets
    and dictionaries have non-deterministic ordering, such an issue may
    occur on some runs and not on others, and in practice it tends to
    have a great dependence on the state of the interpreter.  This leads
    to so-called "heisenbugs" where changing entirely irrelevant aspects
    of the test program still cause the failure behavior to change.

    By calling ``randomize_unitofwork()`` when a script first runs, the
    ordering of a key series of sets within the unit of work implementation
    are randomized, so that the script can be minimized down to the
    fundamental mapping and operation that's failing, while still reproducing
    the issue on at least some runs.

    This utility is also available when running the test suite via the
    ``--reversetop`` flag.

    """
    from sqlalchemy.orm import unitofwork, session, mapper, dependency
    from sqlalchemy.util import topological
    from sqlalchemy.testing.util import RandomSet
    (topological.set) = (unitofwork.set) = (session.set) = (mapper.set) = (
        dependency.set) = RandomSet


def _time_above_threshold(data, thresh, sampling_rate):
    """Return the number of ms that a given time series is above a threshold."""
    max_count = 0
    curr_count = 0
    above = False
    last_sample = 0.0
    for sample in data:
        if above is False and abs(sample) >= thresh:
            above = True
            curr_count = 0
        elif above:
            curr_count += 1
            if abs(sample) < thresh or last_sample * sample < 0.0:
                above = False
                if curr_count > max_count:
                    max_count = curr_count
        last_sample = sample
    if above and curr_count > max_count:
        max_count = curr_count
    return max_count / sampling_rate * 1000.0


def console_here():
    """
    Start debug console.
    """
    import code
    import inspect
    frame = inspect.currentframe().f_back
    ns = dict(frame.f_globals)
    ns.update(frame.f_locals)
    console = code.InteractiveConsole(ns)
    console.interact()


def __new__(mcs, name, bases, dct):
    """Create Command class.

        Add command_name as __module__:__name__
        Collect parameters
        """
    cls = type.__new__(mcs, name, bases, dct)
    if mcs.__event_base__ is None:
        mcs.__event_base__ = cls
    else:
        default_type = dct.get('__type__', name.lower())
        mcs.__events__[default_type] = cls
    return cls


def list_max_show_all(changelist):
    """
    Returns the maximum amount of results a changelist can have for the
    "Show all" link to be displayed in a manner compatible with both Django
    1.4 and 1.3. See Django ticket #15997 for details.
    """
    try:
        from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED
        return MAX_SHOW_ALL_ALLOWED
    except ImportError:
        return changelist.list_max_show_all


def area(segmap, source):
    """
    Number of pixels in segmap.

    Parameters
    ----------

    Returns
    -------

    """
    return {'N100': (segmap[source.slc] == source.segID).sum()}


def __call__(cls, *args, **kwargs):
    """
        Construct a new `Form` instance.

        Creates the `_unbound_fields` list and the internal `_wtforms_meta`
        subclass of the class Meta in order to allow a proper inheritance
        hierarchy.
        """
    if cls._unbound_fields is None:
        fields = []
        for name in dir(cls):
            if not name.startswith('_'):
                unbound_field = getattr(cls, name)
                if hasattr(unbound_field, '_formfield'):
                    fields.append((name, unbound_field))
        fields.sort(key=lambda x: (x[1].creation_counter, x[0]))
        cls._unbound_fields = fields
    if cls._wtforms_meta is None:
        bases = []
        for mro_class in cls.__mro__:
            if 'Meta' in mro_class.__dict__:
                bases.append(mro_class.Meta)
        cls._wtforms_meta = type('Meta', tuple(bases), {})
    return type.__call__(cls, *args, **kwargs)


@staticmethod
def check_params(task_id_list, custom_server_output_path):
    """Check the parameters.

        Task_id_list and custom_server_output_path must have one.
        """
    if not task_id_list and not custom_server_output_path:
        raise Exception(
            'One of the task_id_list and custom_server_output_path must exist')


def longestCommonPrefix(s1, s2):
    """Find the longest prefix common to strings s1 and s2."""
    prefix = ''
    for ch in s1:
        if s2.startswith(prefix + ch):
            prefix = prefix + ch
        else:
            return prefix
    return prefix


def __init__(opener, ui, root, validate, sparsematchfn):
    """Create a new dirstate object.

        opener is an open()-like callable that can be used to open the
        dirstate file; root is the root of the directory tracked by
        the dirstate.
        """


@classmethod
def build(cls):
    """ Recover all the map building the things"""
    for thing in cls.things:
        thing.build()


def isSignatureValid(expected, received):
    """
    Verifies that the received signature matches the expected value
    """
    if expected:
        if not received or expected != received:
            return False
    elif received:
        return False
    return True


def dbh__image(path, contenttype, extension, roottag, nsurl):
    """ Generic Web Page Handler - Returns image_generic for Web browser supported images """
    if extension.lower() in ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tif', 'tiff'
        ]:
        return 'db_image_viewer'
    else:
        return False


@staticmethod
def rename_attributes(**kwds):
    """Rename layout attributes.

        In the style dictionary multiple keywords can be used to address
        attributes. These keywords will be converted to an unique key word,
        used in the remaining code.

        ========= =================================
        keys      other valid keys
        ========= =================================
        fixed     fixed_nodes, fixed_vertices,
                  fixed_n, fixed_v
        positions initial_positions, node_positions
                  vertex_positions, n_positions,
                  v_positions
        ========= =================================

        """
    names = {'fixed': ['fixed_nodes', 'fixed_vertices', 'fixed_v',
        'fixed_n'], 'positions': ['initial_positions', 'node_positions',
        'vertex_positions', 'n_positions', 'v_positions'], 'layout_': [
        'layout_']}
    _kwds = {}
    del_keys = []
    for key, value in kwds.items():
        for attr, name_list in names.items():
            for name in name_list:
                if name in key and name[0] == key[0]:
                    _kwds[key.replace(name, attr).replace('layout_', '')
                        ] = value
                    del_keys.append(key)
                    break
    for key in del_keys:
        del kwds[key]
    return {**_kwds, **kwds}


def unsafe(f):
    """Marks a function or method as unsafe.

    ::

        @unsafe
        def delete(self):
            pass
    """
    f.unsafe_callable = True
    return f


def assign_ipv6_addresses(NetworkInterfaceId=None, Ipv6Addresses=None,
    Ipv6AddressCount=None):
    """
    Assigns one or more IPv6 addresses to the specified network interface. You can specify one or more specific IPv6 addresses, or you can specify the number of IPv6 addresses to be automatically assigned from within the subnet's IPv6 CIDR block range. You can assign as many IPv6 addresses to a network interface as you can assign private IPv4 addresses, and the limit varies per instance type. For information, see IP Addresses Per Network Interface Per Instance Type in the Amazon Elastic Compute Cloud User Guide .
    See also: AWS API Documentation

    :example: response = client.assign_ipv6_addresses(
        NetworkInterfaceId='string',
        Ipv6Addresses=[
            'string',
        ],
        Ipv6AddressCount=123
    )

    :type NetworkInterfaceId: string
    :param NetworkInterfaceId: [REQUIRED]
            The ID of the network interface.

    :type Ipv6Addresses: list
    :param Ipv6Addresses: One or more specific IPv6 addresses to be assigned to the network interface. You can't use this option if you're specifying a number of IPv6 addresses.
            (string) --

    :type Ipv6AddressCount: integer
    :param Ipv6AddressCount: The number of IPv6 addresses to assign to the network interface. Amazon EC2 automatically selects the IPv6 addresses from the subnet range. You can't use this option if specifying specific IPv6 addresses.

    :rtype: dict
    :return: {
        'NetworkInterfaceId': 'string',
        'AssignedIpv6Addresses': [
            'string',
        ]
    }

    :returns:
    (string) --

    """
    pass


def hms2deg(x):
    """Transform *hours:minutes:seconds* strings to degrees.

    Parameters
    ----------
    x : str
        The input angle, written in the form, hours:minutes:seconds

    Returns
    -------
    out : float
        The angle as a number of degrees.

    """
    from astropy.coordinates import Angle
    ac = Angle(x, unit='hour')
    deg = float(ac.to_string(unit='degree', decimal=True))
    return deg


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 _getformat(val):
    """
    Get the output format for a floating point number.

    The general format is used with 16 places of accuracy, except for when
    the floating point value is an integer, in which case a decimal point
    followed by a single zero is used.

    Parameters
    ----------
    val : float or int
        the number which needs formatted.

    Returns
    -------
    string
        the format string.
    """
    if int(val) == val:
        return '%.1f'
    else:
        return '%.16g'


def ae_4(provider):
    """Issue A-ASSOCIATE confirmation (reject) primitive and close transport
    connection.
    """
    provider.to_service_user.put(provider.primitive)
    provider.dul_socket.close()
    provider.dul_socket = None
    return 'Sta1'


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


def split_virtual_offset(virtual_offset):
    """Divides a 64-bit BGZF virtual offset into block start & within block offsets.

    >>> (100000, 0) == split_virtual_offset(6553600000)
    True
    >>> (100000, 10) == split_virtual_offset(6553600010)
    True

    """
    start = virtual_offset >> 16
    return start, virtual_offset ^ start << 16


def get_param_arg(param, idx, klass, arg, attr='id'):
    """Return the correct value for a fabric from `arg`."""
    if isinstance(arg, klass):
        return getattr(arg, attr)
    elif isinstance(arg, (int, str)):
        return arg
    else:
        raise TypeError('%s[%d] must be int, str, or %s, not %s' % (param,
            idx, klass.__name__, type(arg).__name__))


def _splice(value, n):
    """Splice `value` at its center, retaining a total of `n` characters.

    Parameters
    ----------
    value : str
    n : int
        The total length of the returned ends will not be greater than this
        value.  Characters will be dropped from the center to reach this limit.

    Returns
    -------
    A tuple of str: (head, tail).
    """
    if n <= 0:
        raise ValueError('n must be positive')
    value_len = len(value)
    center = value_len // 2
    left, right = value[:center], value[center:]
    if n >= value_len:
        return left, right
    n_todrop = value_len - n
    right_idx = n_todrop // 2
    left_idx = right_idx + n_todrop % 2
    return left[:-left_idx], right[right_idx:]


def stoopid(word, extra=None):
    """
        Return a 'StUpId' rendition of word. Optional, `extra`
        argument to randomly flip case of a small proportion of letters
        after the first pass, for an 'EXtRa sTupID' final form.
    """
    if not isinstance(word, str):
        raise TypeError(f'argument not recognized as string: {word}')
    new_word = ''
    for i, item in enumerate(word):
        if i % 2 == 0:
            new_word += item.upper()
        else:
            new_word += item.lower()
    if extra:
        pass
    return new_word


def get_environ(environ):
    """
    Returns our whitelisted environment variables.
    """
    for key in ('REMOTE_ADDR', 'SERVER_NAME', 'SERVER_PORT'):
        if key in environ:
            yield key, environ[key]


def plot_parts(parts, figsize=(10, 4), view_angles=(40, 90)):
    """Create a simple 3D plot to show the location of loaded parts in space

    Parameters
    ----------
    parts : list of `Mesh` or `Part`
        The parts to plot
    figsize : tuple, optional
        The figsize (in inches) which will be passed to matplotlib
    viewangles : tuple, optional
        The viewing angle of the 3D plot in degrees, will be passed to
        matplotlib

    Requires that matplotlib is installed
    """
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    fig = plt.figure(figsize=figsize)
    ax = fig.add_subplot(111, projection='3d')
    for part in parts.iter_single():
        mesh = part.mesh
        for edge in mesh.get_edges():
            nodes = part.nodes[edge]
            ax.plot(nodes[:, (0)], nodes[:, (1)], nodes[:, (2)], 'k')
    ax.view_init(*view_angles)
    ax.autoscale()
    plt.show()


def deserialize_date(string):
    """Deserializes string to date.

    :param string: str.
    :type string: str
    :return: date.
    :rtype: date
    """
    try:
        from dateutil.parser import parse
        return parse(string).date()
    except ImportError:
        return string


def add_str_to_keys(dct, key_str):
    """ convert dictionary keys by adding key_str"""
    new_dct = {}
    for key, value in dct.iteritems():
        if key_str in key:
            new_dct[key] = value
        else:
            new_dct[key + key_str] = value
    return new_dct


def unlock_all():
    """Unlock all Grease Pencil layers so that they can be edited

    """
    pass


@staticmethod
def depart(spht, _):
    """Append closing tags to document body list.

        :param sphinx.writers.html.SmartyPantsHTMLTranslator spht: Object to modify.
        :param _: Not used.
        """
    spht.body.append('</script>')


def unload_ipython_extension(ipython):
    """ Unload the IPython extension
    """
    pass


def maybe_add_ellipses(s, maxlen=72, instead_of_ellipses_add_this_text=None):
    """
    If string s is longer than maxlen, truncate it and add on ... to
    the end.

    If you want something else, use the instead_of_ellipses_add_this_text

    >>> maybe_add_ellipses('abcdef')
    'abcdef'
    >>> maybe_add_ellipses('abcdef', 3)
    'abc...'
    """
    if len(s) <= maxlen:
        return s
    elif instead_of_ellipses_add_this_text:
        return '{0}{1}'.format(s[:maxlen], instead_of_ellipses_add_this_text)
    else:
        return '%s...' % s[:maxlen]


def _format_node(e):
    """
    Internal function to format a node element into a dictionary.
    """
    ignored_tags = ['source', 'source_ref', 'source:ref', 'history',
        'attribution', 'created_by', 'tiger:tlid', 'tiger:upload_uuid']
    node = {'id': e['id'], 'lat': e['lat'], 'lon': e['lon']}
    if 'tags' in e:
        for t, v in list(e['tags'].items()):
            if t not in ignored_tags:
                node[t] = v
    return node


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


@staticmethod
def from_primitive(primitive):
    """Setup the current PDU using an A-RELEASE (request) primitive.

        Parameters
        ----------
        primitive : pdu_primitives.A_RELEASE
            The primitive to use to set the current PDU field values.
        """
    pass


def mode_type_from_header(h: str) ->str:
    """
    Extract scan mode from the header of filter string

    :param h: header or filter string
    :return: Scan type (e.g. p = profile, c = centroid)
    """
    if ' p ' in h.lower():
        return 'p'
    elif ' c ' in h.lower():
        return 'c'
    else:
        return None


def main(args):
    """
    Running the device test here
    """
    pass


def in_ipython_frontend():
    """
    Helper function which is variation of :meth:`pandas:pandas.io.formats.console.in_ipython_frontend` which
    checks to see if we are inside an IPython zmq frontend

    :return: `True` if D-Tale is being invoked within ipython notebook, `False` otherwise
    """
    try:
        from IPython import get_ipython
        ip = get_ipython()
        return 'zmq' in str(type(ip)).lower()
    except BaseException:
        pass
    return False


def readcb_fh(count, hook):
    """A callback for data.  hook should be a Python file-like object."""
    if count:
        return hook.read(count)
    else:
        if not hasattr(hook, 'seek'):
            return None
        hook.seek(0, 0)
        return None


def set_writeable(writeable_):
    """Sets whether the database is being written to disk, or just organized in
    memory.

    Args:

        writeable_ (bool): when True, calling :meth:`acorn.database.record` will
          eventually result in an entry being saved to disk; otherwise, records are
          organized in memory, but the disk write is disabled.
    """
    global writeable
    writeable = writeable_


def iter_fields(node):
    """Iterate over all fields of a node, only yielding existing fields."""
    if not hasattr(node, '_fields') or not node._fields:
        return
    for field in node._fields:
        try:
            yield field, getattr(node, field)
        except AttributeError:
            pass


def pack_bits(bits):
    """convert a bit (bool or int) tuple into a int"""
    packed = 0
    level = 0
    for bit in bits:
        if bit:
            packed += 2 ** level
        level += 1
    return packed


def _format_warning(message, category, filename, lineno, line=None):
    """Simple format for warnings issued by ProPlot. See the
    `internal warning call signature <https://docs.python.org/3/library/warnings.html#warnings.showwarning>`__
    and the `default warning source code <https://github.com/python/cpython/blob/master/Lib/warnings.py>`__."""
    return f'{filename}:{lineno}: ProPlotWarning: {message}\n'


def _is_data_center_line(line):
    """Determines if line introduces nodes from a Datacenter."""
    return line.startswith('Datacenter: ')


def parse_header(header_lines):
    """Return Info object from header information.

    header_lines -- list of lines or anything that behaves like it.

    Parses only the first three header lines with Filename, Organism, and
    Accession number. In general lines that contain a colon will be parsed.
    There's no error checking in here. If it fails to split on ':', the
    information is simply not added to the dictionary. The expected format
    for header lines is "key: value". The citation lane is parsed differently.
    """
    info = {}
    for line in header_lines:
        if line.startswith('Citation'):
            info['Citation'] = line.split()[-1].strip()
        elif ':' in line:
            try:
                field, value = map(str.strip, line.split(':', 1))
                info[field] = value
            except ValueError:
                continue
        else:
            continue
    return info


def clear():
    """ the whole cached (namespace) """


def linear_coeff(x1, y1, x2, y2):
    """return paramters that fit y = a*x+b"""
    a = (y2 - y1) / (x2 - x1)
    b = y2 - a * x2
    return a, b


def read_lammps_input(filename):
    """Read a LAMMPS input file.

    This will read in a LAMMPS input file and can be used to read
    the value of particular settings, for instance the time step.

    Parameters
    ----------
    filename : string
        The path to the LAMMPS input file.

    Returns
    -------
    out : list of tuples
        The settings found in the LAMMPS input file. The tuples are
        on the form `(keyword, setting)`.

    """
    settings = []
    with open(filename, 'r') as infile:
        for lines in infile:
            current_line, _, _ = lines.strip().partition('#')
            split = current_line.split()
            if split:
                keyword, setting = split[0], split[1:]
                settings.append((keyword, ' '.join(setting)))
    return settings


@staticmethod
def __join_lista_particiones(particiones):
    """
        Dada la lista de listas de particiones representadas con todas sus opciones, devuelve una lista con las particiones representadas como cadenas ya unidas.
        """
    res = []
    for i in range(len(particiones)):
        linea = str.format('{0}\t{1}\t{2}\t{3}\t{4}\t{5}', particiones[i][0
            ], particiones[i][1], particiones[i][2], particiones[i][3],
            particiones[i][4], particiones[i][5])
        linea = linea.replace('\t', '    ')
        res.append(linea)
    return res


@staticmethod
def merge_extinfo(host, extinfo):
    """Merge extended host information into a host

        :param host: the host to edit
        :type host: alignak.objects.host.Host
        :param extinfo: the external info we get data from
        :type extinfo: alignak.objects.hostextinfo.HostExtInfo
        :return: None
        """
    properties = ['notes', 'notes_url', 'icon_image', 'icon_image_alt',
        'vrml_image', 'statusmap_image']
    for prop in properties:
        if getattr(host, prop) == '' and getattr(extinfo, prop) != '':
            setattr(host, prop, getattr(extinfo, prop))


def Get_epsg(g):
    """
    This function reads the projection of a GEOGCS file or tiff file

    Keyword arguments:
    g -- string
        Filename to the file that must be read
    extension -- tiff or GEOGCS
        Define the extension of the dataset (default is tiff)
    """
    try:
        g_proj = g.GetProjection()
        Projection = g_proj.split('EPSG","')
        epsg_to = int(str(Projection[-1]).split(']')[0][0:-1])
    except:
        epsg_to = 4326
    return epsg_to


def _limb_darkened_profile(limb_dark_law, LDCs, mu):
    """Returns limb-darkened flux

    Args:
        limb_dark_law (str): 'quadratic'
        LDCs (numpy array): limb-darkening coefficients
            Must have two elements for 'quadratic'
        mu (numpy array): cos of the angle between the line-of-sight and the
            normal to a grid element of the host's surface

    Returns:
        numpy array: normalized flux profile

    """
    if limb_dark_law == 'quadratic' and len(LDCs) == 2:
        return 1.0 - LDCs[0] * (1.0 - mu) - LDCs[1] * (1.0 - mu) * (1.0 - mu)
    else:
        raise ValueError('Only quadratic limb-darkening law allowed, ' +
            'which requires two coefficients!')


def getKnownGroupEffects(fulldata, batchfilename):
    """ Check the input file for KNOWN possible group effects
    Exclude those that may not exist such as TREATMENT. Make no
    assumptions about order or sorting. Return list in arbitrary
    order. Independent of list provided by the user
    """
    foundColumns = list()
    listOneHotEncoded = list()
    if batchfilename == False:
        print('Using prechosen batch effect names')
        currentPossibleColumnEffects = ['TREATMENT', 'MOUSE', 'SEX', 'DATE',
            'NODEID']
        allColumns = fulldata.columns.values
        listOneHotEncoded = ['MOUSE']
        foundColumns = list(set(allColumns) & set(currentPossibleColumnEffects)
            )
    else:
        foundColumnsCombined = list()
        with open(batchfilename) as f:
            tempColumns = f.read().splitlines()
            for effect in tempColumns:
                foundColumnsCombined.append(effect)
            for ipair in foundColumnsCombined:
                name, typeEnc = ipair.strip().split(' ')
                foundColumns.append(name)
                if typeEnc == 'ONEHOT':
                    listOneHotEncoded.append(name)
    print('Number of Possible batch effects found/specified is ' + str(len(
        foundColumns)))
    print('Number of groupeffect columns in data is ' + str(foundColumns))
    return foundColumns, listOneHotEncoded


def convertKeyStringToMusic21KeyString(textString):
    """
    Utility function to change strings in the form of "Eb" to
    "E-" (for E-flat major) and leaves alone proper music21 strings
    (like "E-" or "f#").  A little bit complex because of parsing
    bb as B-flat minor and Bb as B-flat major.

    >>> key.convertKeyStringToMusic21KeyString('Eb')
    'E-'
    >>> key.convertKeyStringToMusic21KeyString('f#')
    'f#'
    >>> key.convertKeyStringToMusic21KeyString('bb')
    'b-'
    >>> key.convertKeyStringToMusic21KeyString('Bb')
    'B-'
    >>> key.convertKeyStringToMusic21KeyString('b#')
    'b#'
    >>> key.convertKeyStringToMusic21KeyString('c')
    'c'
    """
    if textString == 'bb':
        textString = 'b-'
    elif textString == 'Bb':
        textString = 'B-'
    elif textString.endswith('b') and not textString.startswith('b'):
        textString = textString.rstrip('b') + '-'
    return textString


def write_selected_sln_setting(cmake_file, settings,
    sln_setting_2_project_setting, sln_setting, has_property_value,
    command_indent, sln_conf, config_expressions,
    max_config_condition_width, **kwargs):
    """ Routine that writes main info of setting block """
    begin_text = kwargs['begin_text']
    property_name = kwargs['property_name']
    indent = kwargs['indent']
    write_setting_property_func = kwargs['write_setting_property_func']
    mapped_setting = settings[sln_setting_2_project_setting[sln_setting]]
    if property_name in mapped_setting:
        if mapped_setting[property_name]:
            if not has_property_value:
                begin_text = begin_text.replace('\n', '\n' + indent +
                    command_indent)
                if begin_text:
                    cmake_file.write('{}{}\n'.format(indent +
                        command_indent, begin_text))
                has_property_value = True
            config_condition_expr = None
            if sln_conf is not None:
                config_condition_expr = '$<CONFIG:{}>'.format(sln_conf)
                config_expressions.append(config_condition_expr)
            write_setting_property_func(cmake_file, indent + command_indent,
                config_condition_expr, mapped_setting[property_name],
                max_config_condition_width, **kwargs)
    return has_property_value


@staticmethod
def camera_stream_configurations():
    """Applicable only to CameraStreamController."""
    return None


def keyingset_button_remove():
    """Remove current UI-active property from current keying set

    """
    pass


def getOrder(orderid):
    """ returns a order by its id
        """


def set_print_timing(v: bool):
    """
        Set whether to print time measurements or not.
    """
    global print_timing
    print_timing = v


def parse_counts_and_flavors(counts, overcloud_roles):
    """Helper for parsing the OvercloudRoleCount object

    Given a list of OvercloudRoleCount and dict of OverlcoudRole objects
    return a dict of (image_name, count) and (image_name, flavor_id) in a
    format used for building a template.

    :param counts: List of tuskar.api.controllers.v1.models.OvercloudRoleCount
    :type  counts: list

    :param overcloud_roles: Dict of (overcloud_role_id, overcloud_role) so
                            we can access image_name and flavor_id of roles
    :type  overcloud_roles: dict

    :return: Tuple of dicts {(image_name, count)}, {(image_name, flavor_id)}
    :rtype:  two dict objects
    """
    parsed_counts = {}
    parsed_flavors = {}
    for count_obj in counts:
        image_name = overcloud_roles[count_obj.overcloud_role_id].image_name
        flavor_id = overcloud_roles[count_obj.overcloud_role_id].flavor_id
        count = count_obj.num_nodes
        parsed_counts[image_name] = count
        parsed_flavors[image_name] = flavor_id
    return parsed_counts, parsed_flavors


@property
def name(cls):
    """
        The name of this model class--equivalent to ``cls.__name__``.

        This attribute is provided for symmetry with the `Model.name` attribute
        of model instances.
        """
    return cls.__name__


def calculate_aspect_ratios(apps, schema_editor):
    """
    Assignes every projector one aspect ratio of the ones, that OS
    supported until this migration. If no matching ratio was found, the
    default of 16:9 is assigned.
    """
    Projector = apps.get_model('core', 'Projector')
    ratio_environment = 0.05
    aspect_ratios = {(4 / 3): (4, 3), (16 / 9): (16, 9), (16 / 10): (16, 10
        ), (30 / 9): (30, 9)}
    for projector in Projector.objects.all():
        projector_ratio = projector.width / projector.height
        ratio = 16, 9
        for value, _ratio in aspect_ratios.items():
            if (value >= projector_ratio - ratio_environment and value <=
                projector_ratio + ratio_environment):
                ratio = _ratio
                break
        projector.aspect_ratio_numerator = ratio[0]
        projector.aspect_ratio_denominator = ratio[1]
        projector.save(skip_autoupdate=True)


@classmethod
def from_doc(cls, doc, aliases={}):
    """
        Constructs a namespace object from a namespace doc returned by the API
        site_info call.
        """
    return cls(doc['id'], doc['*'], canonical=doc.get('canonical'), aliases
        =set(aliases.get(doc['id'], [])), case=doc['case'], content=
        'content' in doc)


def to_sanitized_path(path: str):
    """ Ensure path starts with / """
    return path if path.startswith(('/', './')) else f'./{path}'


def branch_tip(repo, branch):
    """HG has a lovely branch_tip method, but it requires mercurial 2.4
    This function provides backwards compatibility. If we ever get to
    drop older versions, we can drop this function."""
    if hasattr(repo, 'branchtip'):
        return repo.branchtip(branch)
    else:
        return repo.branchtags()[branch]


def struct_from_buffer(cls, buf, offset, data_size, ptrs_size):
    """
    Same as cls.from_buffer, but since Cython does not support classmethod,
    at least this can be called from C
    """
    self = cls.__new__(cls)
    self._init_from_buffer(buf, offset, data_size, ptrs_size)
    return self


def generate_state_name_id():
    """Generates an id for a state

    It simply uses a global counter that is increased each time. It is intended for the name of a new state.

    :return: a new state machine id
    """
    global state_name_counter
    state_name_counter += 1
    return state_name_counter


def cum_percentile(series, q):
    """ Takes a series of ordered frequencies and returns the value at a specified quantile
    Parameters:
    series - Series
        The series to analyze
    q - number
        Quantile to get the value of
    """
    total = series.sum()
    cum_sum = series.cumsum()
    return sum(cum_sum < total * q)


@staticmethod
def properties_non_controllable():
    """Return True if non controllable."""
    return None


def dq_has_flag(dqf, flag_to_check):
    """
    Returns true/false if the given DQ value has a specific flag value set after
    unpacked into a 16-bit string.  For example:

    .. code-block:: python

         print dq_has_flag(48,16)
         True
         print dq_has_flag(40, 16)
         False

    :param dqf: The DQ value.

    :type dqf: int

    :param flag_to_check: The flag value to check if it's set to True.

    :type flag_to_check: int

    :returns: bool -- Returns True if `flag_to_check` is `True` inside `dqf`.

    :raises: ValueError
    """
    if flag_to_check & flag_to_check - 1 == 0 and flag_to_check != 0:
        dq_16bit_str = '{0:b}'.format(dqf)
        flag_16bit_str = '{0:b}'.format(flag_to_check)
        return len(flag_16bit_str) <= len(dq_16bit_str) and dq_16bit_str[-1 *
            len(flag_16bit_str)] == '1'
    else:
        raise ValueError(
            'Flag to check must be a power of 2.  Asked to check whether flag '
             + str(flag_to_check) + ' is set to True in bitmask value ' +
            str(dqf) + ', but ' + str(flag_to_check) + ' is not a power of 2.')


def scan_robots_txt(lines, logger):
    """Tokenizes the contents of a `robots.txt` file.

    lines
        Contents of a `robots.txt` file.
    logger
        Problems found while scanning are logged here.

    Yields:

    record: (lineno, token, value)*
        Records, where each record is a sequence of triples.
    """
    record = []
    for lineno, line in enumerate(lines, 1):
        stripped_line = line.lstrip()
        if stripped_line.startswith('#'):
            continue
        if not stripped_line:
            if record:
                yield record
                record = []
            continue
        if len(stripped_line) != len(line):
            logger.warning('Line %d has whitespace before field', lineno)
        nocomment_line = stripped_line.split('#', 1)[0]
        try:
            field, value = nocomment_line.split(':', 1)
        except ValueError:
            logger.error('Line %d contains no ":"; ignoring line', lineno)
        else:
            record.append((lineno, field.casefold(), value.strip()))
    if record:
        yield record


def eccentricity_anomaly(E, e, M):
    """Eccentric anomaly function"""
    import numpy as np
    return E - e * np.sin(E) - M


def fromBytes(value):
    """Convert a byte string to a value.
        """


def tstress(calc, val):
    """https://www.quantum-espresso.org/Doc/INPUT_PW.html#tstress
    """
    assert isinstance(val, bool)
    if not calc.get_param('tprnfor'):
        calc.parameters['tprnfor'] = True


def bpm2bcl(bpm, m=0.001):
    """
    Converts a beats-per-minute number to a basic cycle length in ms. For
    example a bpm of 60 equals a bcl of 1000ms.

    >>> import myokit
    >>> print(myokit.pacing.bpm2bcl(60))
    1000.0

    To use a different unit scaling, change the optional parameter ``m``. For
    example, with m set to 1 the returned units are seconds:

    >>> print(myokit.pacing.bpm2bcl(120, 1))
    0.5
    """
    return 60.0 / m / bpm


@classmethod
def from_dataframe(cls, df, geom_col='geometry', **kwargs):
    """
        Construct a weights object from a pandas dataframe with a geometry
        column. This will cast the polygons to PySAL polygons, then build the W
        using ids from the dataframe.

        Parameters
        ----------
        df          : DataFrame
                      a :class: `pandas.DataFrame` containing geometries to use
                      for spatial weights
        geom_col    : string
                      the name of the column in `df` that contains the
                      geometries. Defaults to `geometry`
        idVariable  : string
                      the name of the column to use as IDs. If nothing is
                      provided, the dataframe index is used
        ids         : list
                      a list of ids to use to index the spatial weights object.
                      Order is not respected from this list.
        id_order    : list
                      an ordered list of ids to use to index the spatial weights
                      object. If used, the resulting weights object will iterate
                      over results in the order of the names provided in this
                      argument.

        See Also
        --------
        :class:`libpysal.weights.weights.W`
        :class:`libpysal.weights.contiguity.Queen`
        """
    idVariable = kwargs.pop('idVariable', None)
    ids = kwargs.pop('ids', None)
    id_order = kwargs.pop('id_order', None)
    if id_order is not None:
        if id_order is True and (idVariable is not None or ids is not None):
            ids = list(df.get(idVariable, ids))
            id_order = ids
        elif isinstance(id_order, str):
            ids = df.get(id_order, ids)
            id_order = ids
    elif idVariable is not None:
        ids = df.get(idVariable).tolist()
    elif isinstance(ids, str):
        ids = df.get(ids).tolist()
    w = cls.from_iterable(df[geom_col].tolist(), ids=ids, id_order=id_order,
        **kwargs)
    return w


def max_ones(coral):
    """
    Description: Returns the percentage of 1's in the coral. This function assumes 'coral' is a list,
    it could be further improved if it was a numpy array

    Input:
        - coral
    Output:
        - fitness
    """
    return 100 * (sum(coral) / len(coral))


def whitespace_tokenize(text):
    """Runs basic whitespace cleaning and splitting on a piece of text."""
    text = text.strip()
    if not text:
        return []
    tokens = text.split()
    return tokens


@classmethod
def install_parser(cls, parser_type, *tags):
    """Installs an URDF parser type for a defined tag.

        Parameters
        ----------
        parser_type : type
            Python class handling URDF parsing of the tag.
        tags : str
            One or more URDF string tag that the parser can parse.
        """
    if len(tags) == 0:
        raise ValueError('Must define at least one tag')
    for tag in tags:
        cls._parsers[tag] = parser_type


@classmethod
def triggers_by_table(cls, triggers):
    """Return dictionary from tables to triggers."""
    d = {}
    for trigger in triggers:
        table = trigger.tablename, trigger.policy, trigger.modal
        if table not in d:
            d[table] = [trigger]
        else:
            d[table].append(trigger)
    return d


def shoji_catalog_wrapper(index, **kwargs):
    """
    receives a dictionary and wraps its content on a body keyed dictionary
    with the appropiate shoji:<class> attribute
    """
    payload = {'element': 'shoji:catalog', 'index': index}
    payload.update(**kwargs)
    return payload


def make_sure_tables_exist(table_classes: list):
    """Makes sure tables exist before continuing.

    If they don't runs parser to create them. This is just in
    case certain tables are not filled already like ASes and
    AS_Connectivity need peers and customers
    """
    try:
        for Table_Class in table_classes:
            with Table_Class() as _db:
                assert _db.get_count() > 0
    except AssertionError:
        from ..relationships_parser import Relationships_Parser
        Relationships_Parser().run()


def __contains__(date):
    """Return whether the `date` is in the month."""


def normalize_bool_option(option_value):
    """
    Convert option value to Python's boolean.

    ``option_value`` is what all those internal option processing return,
    which may be a default value set for an option, or what user passed in.

    As switches, options with values can be used:

    .. code-block:: bash

       --foo=yes|no
       --foo=true|false
       --foo=1|0
       --foo=Y|N
       --foo=on|off

    With combination of ``store_true``/``store_false`` and a default value module developer
    sets for the option, simple form without value is evaluated as easily. With ``store_true``
    and ``False`` default, following option turn the feature `foo` on:

    .. code-block:: bash

       --enable-foo

    With ``store_false`` and ``True`` default, following simple option turn the feature `foo` off:

    .. code-block:: bash

       --disable-foo
    """
    if str(option_value).strip().lower() in ('yes', 'true', '1', 'y', 'on'):
        return True
    return False


def mock_publish_from_s3_exception(work_dict):
    """mock_publish_from_s3_exception

    :param work_dict: dictionary for driving the task
    """
    raise Exception('test mock_publish_from_s3_exception')


@staticmethod
def get_serial():
    """
        getter for the serial number

        :return: None
        """
    return None


def obj_type_serialize(obj: object):
    """ Returns class name. To be used with Schema.obj_type field.

    :param obj:
    :return:
    """
    return obj.__class__.__name__


def get_station_last_update(station_dataframe):
    """ Get a dict of the last weather conditions for a station.

    :param station_dataframe: The dataframe of the data for a station as returned by get_station_dataframe.
    :return: A dict of the last weather conditions for a station.
    """
    return dict(station_dataframe.ix[0])


def create(cls, *args, **kw):
    """Create an immutable object.

    This is a helper method for ``IImmutable.__im_create__(*args, **kw)``.
    """
    return cls.__im_create__(*args, **kw)


def showNtHeadersData(peInstance):
    """ Prints IMAGE_NT_HEADERS signature. """
    print('[+] IMAGE_NT_HEADERS signature:\n')
    print('--> NT_HEADERS signature: 0x%08x' % peInstance.ntHeaders.
        signature.value)


@staticmethod
def get_option(option, default=None, cast=None):
    """Returns the option value for the specified acorn database option.
        """
    from acorn.config import settings
    config = settings('acorn')
    if config.has_section('database') and config.has_option('database', option
        ):
        result = config.get('database', option)
        if cast is not None:
            result = cast(result)
    else:
        result = default
    return result


@classmethod
def encrypted_string(cls, plaintext):
    """Sends a string to DataRobot to be encrypted

        This is used for passwords that DataRobot uses to access external data sources

        Parameters
        ----------
        plaintext : str
            The string to encrypt

        Returns
        -------
        ciphertext : str
            The encrypted string
        """
    endpoint = 'stringEncryptions/'
    response = cls._client.post(endpoint, data={'plain_text': plaintext})
    return response.json()['cipherText']


def UernPremRate():
    """Unearned Premium Rate"""
    return None


@staticmethod
def has_battery():
    """Return whether the device has a battery."""
    return False


def get_magic(name):
    """Get a magic function by name or None if not exists."""
    return globals().get('do_' + name)


def eval():
    """
            Run eval to update the gate's outputs whenever you change the inputs.
        """
    raise NotImplementedError('Abstract method tick called.')