def _a_decode_set(stream, offset, count, mapping):
    """
    'a1L3i123',3,1 --> 8,set(123)
    'a2L1i41i2',3,1 --> 8,set(4,2)
    """
    container = set()
    for _ in range(count):
        index = offset
        while 48 <= ord(stream[index:index + 1]) <= 57:
            index += 1
        offset, value = mapping[stream[index:index + 1]](stream, index + 1,
            int(stream[offset:index]), mapping)
        container.add(value)
    return offset, container


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


def compute_texptime(imageObjectList):
    """
    Add up the exposure time for all the members in
    the pattern, since 'drizzle' doesn't have the necessary
    information to correctly set this itself.
    """
    expnames = []
    exptimes = []
    start = []
    end = []
    for img in imageObjectList:
        expnames += img.getKeywordList('_expname')
        exptimes += img.getKeywordList('_exptime')
        start += img.getKeywordList('_expstart')
        end += img.getKeywordList('_expend')
    exptime = 0.0
    expstart = min(start)
    expend = max(end)
    exposure = None
    for n in range(len(expnames)):
        if expnames[n] != exposure:
            exposure = expnames[n]
            exptime += exptimes[n]
    return exptime, expstart, expend


def describe_workspaces_connection_status(WorkspaceIds=None, NextToken=None):
    """
    Describes the connection status of a specified WorkSpace.
    See also: AWS API Documentation

    :example: response = client.describe_workspaces_connection_status(
        WorkspaceIds=[
            'string',
        ],
        NextToken='string'
    )

    :type WorkspaceIds: list
    :param WorkspaceIds: An array of strings that contain the identifiers of the WorkSpaces.
            (string) --

    :type NextToken: string
    :param NextToken: The next token of the request.

    :rtype: dict
    :return: {
        'WorkspacesConnectionStatus': [
            {
                'WorkspaceId': 'string',
                'ConnectionState': 'CONNECTED'|'DISCONNECTED'|'UNKNOWN',
                'ConnectionStateCheckTimestamp': datetime(2015, 1, 1),
                'LastKnownUserConnectionTimestamp': datetime(2015, 1, 1)
            },
        ],
        'NextToken': 'string'
    }

    """
    pass


def _get_registry(db_name):
    """Helper method to get the registry for a `db_name`."""
    from odoo.modules.registry import Registry
    if isinstance(db_name, str):
        db = Registry(db_name)
    elif isinstance(db_name, Registry):
        db = db_name
    else:
        import sys
        caller = sys.getframe(1).f_code.co_name
        raise TypeError('"%s" requires a string or a Registry' % caller)
    return db


def yesno(prompt):
    """Returns True if user answers 'y' """
    prompt += ' [y/n]'
    a = ''
    while a not in ['y', 'n']:
        a = input(prompt).lower()
    return a == 'y'


def setenv(environ, key, value, enc='UTF-8'):
    """
    Set the named ``key`` to ``value`` in the WSGI environ dict ``environ``.
    Value must be a byte ``str`` and will be encoded according
    to the rules in PEP-3333.
    """
    environ[key] = value.decode('ISO-8859-1')


def gamma(data=None, out=None, name=None, **kwargs):
    """Returns the gamma function (extension of the factorial function \\
    to the reals), computed element-wise on the input array.

    The storage type of ``gamma`` output is always dense

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

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

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


def _unprotected_volume_from_shape(z):
    """
    Computes the Bloch-Wigner dilogarithm for z assuming z is of a type that
    properly supports polylog.
    """
    return (1 - z).arg() * z.abs().log() + z.polylog(2).imag()


def list_assessment_run_agents(assessmentRunArn=None, filter=None,
    nextToken=None, maxResults=None):
    """
    Lists the agents of the assessment runs that are specified by the ARNs of the assessment runs.
    See also: AWS API Documentation

    Examples
    Lists the agents of the assessment runs that are specified by the ARNs of the assessment runs.
    Expected Output:

    :example: response = client.list_assessment_run_agents(
        assessmentRunArn='string',
        filter={
            'agentHealths': [
                'HEALTHY'|'UNHEALTHY',
            ],
            'agentHealthCodes': [
                'IDLE'|'RUNNING'|'SHUTDOWN'|'UNHEALTHY'|'THROTTLED'|'UNKNOWN',
            ]
        },
        nextToken='string',
        maxResults=123
    )

    :type assessmentRunArn: string
    :param assessmentRunArn: [REQUIRED]
            The ARN that specifies the assessment run whose agents you want to list.

    :type filter: dict
    :param filter: You can use this parameter to specify a subset of data to be included in the action's response.
            For a record to match a filter, all specified filter attributes must match. When multiple values are specified for a filter attribute, any of the values can match.
            agentHealths (list) -- [REQUIRED]The current health state of the agent. Values can be set to HEALTHY or UNHEALTHY .
            (string) --
            agentHealthCodes (list) -- [REQUIRED]The detailed health state of the agent. Values can be set to IDLE , RUNNING , SHUTDOWN , UNHEALTHY , THROTTLED , and UNKNOWN .
            (string) --

    :type nextToken: string
    :param nextToken: You can use this parameter when paginating results. Set the value of this parameter to null on your first call to the ListAssessmentRunAgents action. Subsequent calls to the action fill nextToken in the request with the value of NextToken from the previous response to continue listing data.

    :type maxResults: integer
    :param maxResults: You can use this parameter to indicate the maximum number of items that you want in the response. The default value is 10. The maximum value is 500.

    :rtype: dict
    :return: {
        'assessmentRunAgents': [
            {
                'agentId': 'string',
                'assessmentRunArn': 'string',
                'agentHealth': 'HEALTHY'|'UNHEALTHY',
                'agentHealthCode': 'IDLE'|'RUNNING'|'SHUTDOWN'|'UNHEALTHY'|'THROTTLED'|'UNKNOWN',
                'agentHealthDetails': 'string',
                'autoScalingGroup': 'string',
                'telemetryMetadata': [
                    {
                        'messageType': 'string',
                        'count': 123,
                        'dataSize': 123
                    },
                ]
            },
        ],
        'nextToken': 'string'
    }

    """
    pass


@classmethod
def _get_apic_classes(cls):
    """
        Get the APIC classes used by this acitoolkit class.

        :returns: list of strings containing APIC class names
        """
    return ['l3extDomP']


def section(itr, size):
    """
    Goes through @itr and splits it up into chunks of @size. @itr must be
    subscriptable.

    >>> section('quantum_junk10', 3)
    ['qua', 'ntu', 'm_j', 'unk', '10']

    AUTHORS:
    v0.3.1+             --> pydsigner
    """
    res = []
    while itr:
        res.append(itr[:size])
        itr = itr[size:]
    return res


def pad_box(canvas_size=(100, 100), padding=(0, 0, 0, 0)):
    """
    Pad the box (cut the size and pad coords) and return new dimensions
    and coords as tuple of tuples
    """
    canvas_width, canvas_height = canvas_size
    padding_top, padding_right, padding_bottom, padding_left = padding
    padded_box_dim = (canvas_width - padding_right - padding_left,
        canvas_height - padding_top - padding_bottom)
    return padded_box_dim, (padding_left, padding_top)


def as_int(n):
    """
    Convert the argument to a builtin integer.

    The return value is guaranteed to be equal to the input. ValueError is
    raised if the input has a non-integral value.

    Examples
    ========

    >>> 3.0
    3.0
    >>> as_int(3.0)  # convert to int and test for equality
    3
    >>> int(sqrt(10))
    3
    >>> as_int(sqrt(10))
    Traceback (most recent call last):
    ...
    ValueError: ... is not an integer

    """
    try:
        result = int(n)
        if result != n:
            raise TypeError
    except TypeError:
        raise ValueError(f'{n} is not an integer')
    return result


@classmethod
def verify(cls):
    """Check the storage for errors."""
    return True


def initRepeat(container, func, n):
    """Call the function *container* with a generator function corresponding
    to the calling *n* times the function *func*.

    :param container: The type to put in the data from func.
    :param func: The function that will be called n times to fill the
                 container.
    :param n: The number of times to repeat func.
    :returns: An instance of the container filled with data from func.

    This helper function can be used in conjunction with a Toolbox
    to register a generator of filled containers, as individuals or
    population.

        >>> import random
        >>> random.seed(42)
        >>> initRepeat(list, random.random, 2) # doctest: +ELLIPSIS,
        ...                                    # doctest: +NORMALIZE_WHITESPACE
        [0.6394..., 0.0250...]

    See the :ref:`list-of-floats` and :ref:`population` tutorials for more examples.
    """
    return container(func() for _ in range(n))


def analyze_module(project, resource):
    """Perform static object analysis on a python file in the project

    Note that this might be really time consuming.
    """
    project.pycore.analyze_module(resource)


@staticmethod
def get_degradation_help_description(degradation):
    """ Generate help description given a degradation

        Args:
            degradation (Degradation): Input degradation
        Returns:
            (string): Degradation description
        """
    return degradation.description


def serialize(msg):
    """
    Prepare message for serialization

    :param msg: Message to serialize
    :type msg: BasicRequest
    :return: Message as dict
    :rtype: dict
    """
    return msg.to_dict()


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


def enforce(request):
    """
        Handles message posts.  Expects an HTTP request object
        from which the post info will be extracted.  Returns
        a return code to represent the results.
        """


def _import_show_doc_cell(mod=None, name=None):
    """Add an import show_doc cell + deal with the __file__ hack if necessary."""
    source = f'#export\nfrom local.notebook.showdoc import show_doc'
    if mod:
        source += f'\nfrom local.{mod} import *'
    if name:
        source += f'\nfrom pathlib import Path\n__file__ = {name}'
    return {'cell_type': 'code', 'execution_count': None, 'metadata': {
        'hide_input': True}, 'outputs': [], 'source': source}


def _string_literal_to_string(string_literal_token):
    """Converts the StringLiteral token to a plain string: get text content,
    removes quote characters, and unescapes it.

    :param string_literal_token: The string literal
    :return:
    """
    token_text = string_literal_token.getText()
    return token_text[1:-1].replace(u"\\'", u"'").replace(u'\\\\', u'\\')


def qtile(a, ir):
    """
    This routine returns the ith entry of vector after sorting in
    descending order.

    Parameters
    ----------
    a : list
        Input data distribution
    ir : int
        Quartile value

    Returns
    -------
    qtile : ???
        ???

    """
    as_sorted = sorted(a, reverse=True)
    qtile1 = as_sorted[ir]
    return qtile1


@classmethod
def from_spec(cls, name, properties):
    """
        Create browser object based on limits database data.

        :param name: browser identifier (name:platform:version)
        :param properties:
        :returns: browser object
        """
    name, platform, version = name.split(':')[:3]
    return cls(name, platform or '', cls.parse_version(version), int(
        properties['maxcookies']), int(properties['maxsize']), int(
        properties['maxtotal']))


def _mergeparallel(inputfiles=None, outputfile=None):
    """ This merges Procar files seperated between k-point ranges.
    Happens with parallel Abinit runs.
    """
    print('Merging parallel files...')
    filenames = sorted(inputfiles)
    with open(outputfile, 'w') as outfile:
        for fname in filenames:
            with open(fname) as infile:
                for line in infile:
                    outfile.write(line)


@staticmethod
def short_name_type():
    """
        Returns the short name type for this port.

        :returns: string
        """
    return 'g'


@classmethod
def _get_mstd(cls, df, column, windows):
    """ get moving standard deviation

        :param df: data
        :param column: column to calculate
        :param windows: collection of window of moving standard deviation
        :return: None
        """
    window = cls.get_only_one_positive_int(windows)
    column_name = '{}_{}_mstd'.format(column, window)
    df[column_name] = df[column].rolling(min_periods=1, window=window,
        center=False).std()


def logging_format(verbose=2, style='txt'):
    """returns a format
    :parameter:
        - str style: defines style of output format (defaults to txt)
            - txt plain text
            - dict like text which can be casted to dict
    """
    frmt = "'dt':'%(asctime)s', 'lv':'%(levelname)-7s', 'ln':'%(name)s'"
    if verbose > 1:
        frmt += (
            ",\t'Func': '%(funcName)-12s','line':%(lineno)5d, 'module':'%(module)s'"
            )
    if verbose > 2:
        frmt += """,
	'file':'%(filename)s',	'Process':['%(processName)s', %(process)d],                 'thread':['%(threadName)s', %(thread)d], 'ms':%(relativeCreated)d"""
    frmt += ",\n\t'msg':'%(message)s'"
    if style == 'dict':
        frmt = '{' + frmt + '}'
        frmt = frmt.replace(' ', '').replace('\n', '').replace('\t', '')
    if style == 'txt':
        frmt = frmt.replace("'", '').replace(',', '')
    return frmt


def _throw_invalid_doc_id():
    """Throws an error.

    """
    raise TypeError('Invalid document uid (must be an instance of uuid.UUID).')


def float_xrange(start, end, step=1.0, exceed=False):
    """Like range() but for floats"""
    i = start
    if exceed:
        more = step
    else:
        more = 0.0
    while i < end + more:
        yield i
        i += step


def _isQObjectAlive(obj):
    """An approximation of PyQt's isQObjectAlive().
    """
    try:
        if hasattr(obj, 'parent'):
            obj.parent()
        elif hasattr(obj, 'parentItem'):
            obj.parentItem()
        else:
            raise Exception(
                'Cannot determine whether Qt object %s is still alive.' % obj)
    except RuntimeError:
        return False
    else:
        return True


@staticmethod
def _normalized_vcf(chrom, pos, ref, alt):
    """If both ref/alt are > 1 base, and there are overlapping from the left,
           we need to trim off the overlapping bases.
           In the case that ref/alt is like this:
               CTTTT/CT    # with >1 overlapping bases from the left
           ref/alt should be normalized as TTTT/T, more examples:
                TC/TG --> C/G
           and pos should be fixed as well.
        """
    for i in range(max(len(ref), len(alt))):
        _ref = ref[i] if i < len(ref) else None
        _alt = alt[i] if i < len(alt) else None
        if _ref is None or _alt is None or _ref != _alt:
            break
    if _ref is None and _alt is None:
        raise ValueError('"ref" and "alt" cannot be the same: {}'.format((
            chrom, pos, ref, alt)))
    _pos = int(pos)
    if _ref is None or _alt is None:
        _pos = _pos + i - 1
        _ref = ref[i - 1:]
        _alt = alt[i - 1:]
    else:
        _pos = _pos + i
        _ref = ref[i:]
        _alt = alt[i:]
    return chrom, _pos, _ref, _alt


def int_n(v):
    """Cast to int, or on failure, return a default Value"""
    try:
        return int(float(v))
    except:
        return None


def set_theme(themeName, themeObj):
    """Update the theme cache."""


@classmethod
def from_index(cls, index):
    """Return the Enum value at a given index."""
    return cls.ALL[index]


def real_name(magic_func):
    """ Find the real name of the magic.
    """
    magic_name = magic_func.__name__
    if magic_name.startswith('magic_'):
        magic_name = magic_name[len('magic_'):]
    return getattr(magic_func, 'argcmd_name', magic_name)


@classmethod
def __copy__(cls, the_filter):
    """
        Creates a shallow copy of the object.
        """
    new_filter = type(the_filter)()
    new_filter._parent = the_filter._parent
    new_filter._key = the_filter._key
    new_filter._handler = the_filter._handler
    return new_filter


@classmethod
def reset(cls):
    """Reset the global application.  Only useful for testing."""
    cls._GLOBAL = cls()


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

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


def calculate_dtype(app_name) ->str:
    """
    For generic extractors try to return a more
    specific type we can be if reasonably sure.
    """
    app_name_lower = app_name.lower()
    for name, dtype in (('update', 'desktop app'), ('mail', 'pim'), ('api',
        'library'), ('sdk', 'library'), ('webview', 'browser')):
        if name in app_name_lower:
            return dtype
    return 'generic'


def convert_constant(node, params, layers, lambda_func, node_name, keras_name):
    """
    Convert Constant layer
    :param node: current operation node
    :param params: operation attributes
    :param layers: available keras layers
    :param lambda_func: function for keras Lambda layer
    :param node_name: internal converter name
    :param keras_name: resulting layer name
    :return: None
    """
    layers[node_name] = params['value']


def _is_typing_type(field_type: type) ->bool:
    """Determine whether a type is a typing class."""
    return hasattr(field_type, '_subs_tree')


def string(token):
    """
        Converts a raw string to a Python string

        "this string" -> this string
        """
    return token[1:-1]


def upsert(query):
    """Saves or uploads query

    Args:
        query:

    Returns:

    """
    return query.save()


def create_part_xml(part_msg_list=None):
    """
    get information from part_msg_list and covert it to xml.
    part_msg_list has special format.
    """
    if not part_msg_list:
        part_msg_list = []
    xml_string = '<CompleteMultipartUpload>'
    for part in part_msg_list:
        if len(part) >= 3:
            xml_string += '<Part>'
            xml_string += '<PartNumber>' + str(part[0]) + '</PartNumber>'
            xml_string += '<ETag>"' + str(part[2]).upper() + '"</ETag>'
            xml_string += '</Part>'
        else:
            print('the ', part, ' in part_msg_list is not as expected!')
            return ''
    xml_string += '</CompleteMultipartUpload>'
    return xml_string


def getDocString():
    """Return the doc string of the module."""


@classmethod
def validate(cls, output_destination):
    """Validate destination of report.

        :param output_destination: Destination of report
        """
    pass


def register(cls, test, factory, datatype):
    """
        Registers a filter control against a specific datatype.  The filter controller is added to
        filter_controls.

        Depending on whether create_from_modelfield or create_from_datatype (below) is used, the test or datatype will
        be used to create FilterControls in the future.

        :param test: A function to test whether the filtercontrol should be displayed (?)
        :param factory:  The filter control class.  When called, you will get a subclass of FilterControl.
        :param datatype:  The field type that is filtered by this control (?)
        """
    cls.filter_controls.append((test, factory, datatype))


@staticmethod
def sort(df, column, ascending=False):
    """
        Returns a new :class:`DataFrame` sorted by the specified column(s).

        :param cols: list of :class:`Column` or column names to sort by.
        :param ascending: boolean or list of boolean (default True).
            Sort ascending vs. descending. Specify list for multiple sort orders.
            If a list is specified, length of the list must equal length of the `cols`.
        """
    return df.sort(column, ascending=ascending)


def header2extent(header):
    """ convert a header dict to a 4-element tuple (left, right, bottom, top)
    all four elements shows the coordinates at the edge of a cell, not center
    """
    left = header['xllcorner']
    right = header['xllcorner'] + header['ncols'] * header['cellsize']
    bottom = header['yllcorner']
    top = header['yllcorner'] + header['nrows'] * header['cellsize']
    extent = left, right, bottom, top
    return extent


@staticmethod
def _generate_id(nfa_name: str, start_event_id: str) ->str:
    """
        Generates a run ID.

        :param nfa_name: The run NFA name.
        :type nfa_name: str

        :param start_event_id: The ID of the first event in the run,
        :type start_event_id: str

        :return: A run ID.
        """
    return '{}-{}'.format(nfa_name, start_event_id)


def ordinal(n: int) ->str:
    """
    Converts an int to it spoken ordinal representation
    """
    if n < 0:
        return
    return str(n) + 'tsnrhtdd'[(n / 10 % 10 != 1) * (n % 10 < 4) * n % 10::4]


def parse_duration(s: str) ->int:
    """
    >>> parse_duration('00:01')
    1
    >>> parse_duration('03:33')
    213
    >>> parse_duration('01:14:00')
    4440
    """
    parts = s.split(':')
    seconds = int(parts[-1])
    if len(parts) > 1:
        seconds += int(parts[-2]) * 60
    if len(parts) == 3:
        seconds += int(parts[0]) * 3600
    return seconds


def search_ontology_name(ontology_splited):
    """
    Find the 'name' of the ontology.
    """
    names = []
    for i in range(ontology_splited.__len__()):
        if ontology_splited[i][0] == '!--':
            try:
                variable = ontology_splited[i][1].split('_')[0]
                name = str(variable.split('/')[-1]) + '_'
                try:
                    name = str(name.split('#')[1])
                    names.append(name)
                except:
                    names.append(name)
            except:
                continue
    repetitions = {}
    for j in range(len(names)):
        if names[j] not in repetitions:
            repetitions[names[j]] = 1
        elif names[j] in repetitions:
            value = repetitions[names[j]]
            repetitions[names[j]] = value + 1
    current_value = 0
    for key, value in repetitions.items():
        if value > current_value:
            current_value = value
            ontologyname = key
    return ontologyname


def getid(obj):
    """Get obj's id or object itself if no id

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


def any_(obj):
    """Return True if any item in obj is true. If obj is empty, return False."""
    return any(obj)


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 toStringArray(name, a, width=0):
    """
    Returns an array (any sequence of floats, really) as a string.
    """
    string = name + ': '
    cnt = 0
    for i in a:
        string += '%4.2f  ' % i
        if width > 0 and (cnt + 1) % width == 0:
            string += '\n'
        cnt += 1
    return string


@staticmethod
def _clean_city_name(city):
    """
        remove "area", "region" words from city names
        :param city: city name
        :return: clean city name
        """
    for word in [' Bay Area', ' area', ' Area', 'Greater ', 'und Umgebung',
        'e Região', 'Région de']:
        city = city.replace(word, '')
    mapping = {'zurich': 'Zürich'}
    return mapping.get(city.strip().lower(), city.strip())


def sint(S):
    """convert a string to an integer, treating an all-blank string as zero"""
    if S.strip():
        return int(S)
    else:
        return 0


def BasinOrderToBasinRenameList(basin_order_list):
    """When we take data from the basins they will be numbered accoring to their junction rank, which is controlled by flow routing.

    The result is often numbered basins that have something that appears random to human eyes.
    We have developed a routine to renumber these basins.
    However, the way this works is to find a basin number and rename in the profile plots,
    such that when it finds a basin number it will rename that.
    So if you want to rename the seventh basin 0, you need to give a list where the seventh element is 0.

    This is a pain because how one would normally order basins would be to look at the image of the basin numbers,
    and then write the order in which you want those basins to appear.

    This function converts between these two lists. You give the function the order you want the basins to appear,
    and it gives a renaming list.

    Args:
        basin_order_list (int): the list of basins in which you want them to appear in the numbering scheme

    Return:
        The index into the returned basins

    Author: SMM
    """
    max_basin = max(basin_order_list)
    basin_rename_list = [0] * max_basin
    basin_rename_list.append(0)
    print('length is: ' + str(len(basin_rename_list)))
    for idx, basin in enumerate(basin_order_list):
        print('Index: ' + str(idx) + ', basin: ' + str(basin))
        basin_rename_list[basin] = idx
    return basin_rename_list


def LP_surface(genus, boundary, make_prefix_unique=True):
    """ Returns the contents of a surface file for the surface S_{genus, boundary}.
	We generally follow the naming convention given in Figure 13
	of the Labruere and Paris paper "Presentations for the punctured
	mapping class groups in terms of Artin groups".

	When genus == 1, the loop a_n is dropped as it is isotopic to the
	loop a_0.

	The case of genus == 0, given here, is a small modification of
	Figure 11 in [LP].

	You should not use this function directly, rather just call
	Surface((genus, boundary)). """
    contents = ['# A Twister surface file produced by LP_surface.']
    contents.append(
        '# with generating set for MCG(S_{%d,%d}) following Figure 13 of Labruere and'
         % (genus, boundary))
    contents.append(
        '# Paris paper "Presentations for the punctured mapping class groups')
    contents.append('# in terms of Artin groups".')
    contents.append('#')
    padded_length = len(str(max(2 * genus, boundary))
        ) if make_prefix_unique else 0
    square_count = 0
    if genus == 0:
        if boundary == 0:
            square_count += 1
            contents.append('annulus,a1,A1,-0,+1#')
            contents.append('annulus,a2,A2,-1,+0#')
        else:
            for i in range(boundary):
                square_count += 1
                start = 'rectangle,t' + str(i + 1).zfill(padded_length
                    ) + ',T' + str(i + 1).zfill(padded_length)
                connections = ',-' + str(square_count - 1) + ',+' + str(
                    square_count)
                contents.append(start + connections + '#')
                if i == boundary - 1:
                    start = 'annulus,a' + str(i + 1).zfill(padded_length
                        ) + ',A' + str(i + 1).zfill(padded_length)
                    connections = ',-' + str(square_count) + ',+' + '0'
                    contents.append(start + connections + '#')
                else:
                    square_count += 1
                    start = 'annulus,a' + str(i + 1).zfill(padded_length
                        ) + ',A' + str(i + 1).zfill(padded_length)
                    connections = ',-' + str(square_count - 1) + ',+' + str(
                        square_count)
                    contents.append(start + connections + '#')
    else:
        c_loop = -1
        next_line = 'annulus,a' + '0'.zfill(padded_length) + ',A' + '0'.zfill(
            padded_length) + ',+0'
        contents.append(next_line + '#')
        start = 'annulus,b' + '1'.zfill(padded_length) + ',B' + '1'.zfill(
            padded_length)
        connections = ',-0'
        if boundary > 1:
            for i in range(boundary - 1):
                square_count += 1
                connections = connections + ',-' + str(square_count)
                square_count += 1
                start2 = 'annulus,a' + str(i + 1).zfill(padded_length
                    ) + ',A' + str(i + 1).zfill(padded_length)
                connections2 = ',+' + str(square_count - 1) + ',+' + str(
                    square_count)
                contents.append(start2 + connections2 + '#')
                start3 = 'rectangle,t' + str(i + 1).zfill(padded_length
                    ) + ',T' + str(i + 1).zfill(padded_length)
                connections3 = ',-' + str(square_count)
                contents.append(start3 + connections3 + '#')
        elif boundary == 1:
            square_count += 1
            connections = connections + ',-' + str(square_count)
            start2 = 'rectangle,t' + '1'.zfill(padded_length
                ) + ',T' + '1'.zfill(padded_length)
            connections2 = ',+' + str(square_count)
            contents.append(start2 + connections2 + '#')
        elif boundary == 0 and genus > 1:
            square_count += 1
            connections = connections + ',+' + str(square_count)
        if genus > 1 and boundary > 0:
            square_count += 1
            connections = connections + ',-' + str(square_count)
            start2 = 'annulus,a' + str(boundary).zfill(padded_length
                ) + ',A' + str(boundary).zfill(padded_length)
            connections2 = ',+' + str(square_count)
            contents.append(start2 + connections2 + '#')
            square_count += 1
            connections = connections + ',+' + str(square_count)
        contents.append(start + connections + '#')
        for i in range(2, 2 * genus - 1):
            square_count += 1
            start = 'annulus,b' + str(i).zfill(padded_length) + ',B' + str(i
                ).zfill(padded_length)
            connections = ',-' + str(square_count - 1) + ',+' + str(
                square_count)
            contents.append(start + connections + '#')
            if i == 2:
                c_loop = len(contents)
        if genus > 1:
            square_count += 1
            start = 'annulus,b' + str(2 * genus - 1).zfill(padded_length
                ) + ',B' + str(2 * genus - 1).zfill(padded_length)
            connections = ',-' + str(square_count - 1)
            contents.append(start + connections + '#')
        if c_loop > -1:
            next_line = 'annulus,c,C,-' + str(square_count)
            contents.append(next_line + '#')
            contents[c_loop] = contents[c_loop][:-1] + ',+' + str(square_count
                ) + '#'
    return '\n'.join(contents)


def hub_prevent_multiple_readers(state=True):
    """Toggle prevention of multiple greenlets reading from a socket

    When multiple greenlets read from the same socket it is often hard
    to predict which greenlet will receive what data.  To achieve
    resource sharing consider using ``eventlet.pools.Pool`` instead.

    But if you really know what you are doing you can change the state
    to ``False`` to stop the hub from protecting against this mistake.
    """
    from eventlet.hubs import hub
    hub.g_prevent_multiple_readers = state


def format_lsn(lsn):
    """
    Transform a numeric XLOG location, in the corresponding %X/%X string
    representation

    :param int lsn: numeric XLOG location
    :rtype: str
    """
    return '%X/%X' % (lsn >> 32, lsn & 4294967295)


def str_banner(txt=None, c='-', prefix='#', debug=True, label=None, color=None
    ):
    """
    prints a banner of the form with a frame of # around the txt::

    # --------------------------
    # txt
    # --------------------------

    :param color: prints in the given color
    :param label: adds a label
    :param debug: prints only if debug is true
    :param txt: a text message to be printed
    :type txt: string
    :param c: the character used instead of c
    :type c: character
    """
    output = ''
    if debug:
        output = '\n'
        output += prefix + ' ' + 70 * c + '\n'
        if label is not None:
            output += prefix + ' ' + label + '\n'
            output += prefix + ' ' + 70 * c + '\n'
        if txt is not None:
            for line in txt.splitlines():
                output += prefix + ' ' + line + '\n'
            output += prefix + ' ' + 70 * c + '\n'
    if color is None:
        color = 'BLUE'
    return output


def collect_build_logs():
    """
    Collect the build logs produced by lbn-wrapcmd and write the content grouped by
    subdir and target.
    """
    from LbNightlyTools.Scripts.CollectBuildLogs import Script
    return Script().run()


def _item_from(container, index):
    """Attempts to fetch a index/key from a given container."""
    if index is None:
        return container
    return container[index]


def resolve(reference):
    """
        Resolve the external reference and return it.
        """


def islocked():
    """
        Is the current context locked or not. Return True, otherwise False.
        """


def _popget(d, key, default=None):
    """
    Pop the key if found (else return default)
    """
    if key in d:
        return d.pop(key)
    return default


def tokenize(expr):
    """
    Parse a string expression into a set of tokens that can be used as a path
    into a Python datastructure.
    """
    tokens = []
    escape = False
    cur_token = ''
    for c in expr:
        if escape == True:
            cur_token += c
            escape = False
        elif c == '\\':
            escape = True
            continue
        elif c == '[':
            if len(cur_token) > 0:
                tokens.append(cur_token)
                cur_token = ''
        elif c == ']':
            if len(cur_token) > 0:
                tokens.append(int(cur_token))
                cur_token = ''
        elif c == '.':
            if len(cur_token) > 0:
                tokens.append(cur_token)
                cur_token = ''
        else:
            cur_token += c
    if len(cur_token) > 0:
        tokens.append(cur_token)
    return tokens


def send_arduino(msg, serial_connection):
    """
    Send the *msg* over the *serial_connection*

    Adds a hexadecimal number of 6 bytes to the start of the message before
    sending it. "hello there" -> "0x000bhello there"

    Parameters
    ----------
    msg : str or bytes
        the message you want to send
    serial_connection : object
        the :code:`serial.Serial` object you want to use for sending
    """
    if not isinstance(msg, bytes):
        msg = str(msg).encode()
    length = '{0:#0{1}x}'.format(len(msg), 6).encode()
    data = length + msg
    serial_connection.write(data)


def range_value(val, limit):
    """
    验证给定值是否在范围内,先转换为数值比较，如果转换不成功，则转换为字符串比较
    :param val:
    :param limit:
    :return:
    """
    if (isinstance(limit, tuple) or isinstance(limit, list)) and len(limit
        ) == 2:
        try:
            a, b, c = int(limit[0]), int(val), int(limit[1])
        except ValueError:
            a, b, c = str(limit[0]), str(val), str(limit[1])
        return a <= b <= c
    return False


def view_all():
    """View all the strips in the sequencer

    """
    pass


def extends(other, strict=True):
    """Test whether a specification extends another

        The specification extends other if it has other as a base
        interface or if one of it's bases extends other.

        If strict is false, then the specification extends itself.
        """


def _fix_paths(envs, pathvars=('PATH', 'PERLLIB', 'PERL5LIB', 'PYTHONPATH',
    'LD_LIBRARY_PATH', 'MANPATH', 'INFOPATH')):
    """For the specified env vars that represent a search path, make sure that the
    paths are unique.  This allows the environment setting script to be lazy
    and not worry about it.  This routine gives the right-most path precedence
    and modifies C{envs} in place.

    :param envs: Dict of environment vars
    :param pathvars: List of path vars that will be fixed
    :rtype: None (envs is modified in-place)
    """
    for key in (set(envs.keys()) & set(pathvars)):
        path_ins = envs[key].split(':')
        pathset = set()
        path_outs = []
        for path in reversed(path_ins):
            if path not in pathset:
                pathset.add(path)
                path_outs.append(path)
        envs[key] = ':'.join(reversed(path_outs))


def vertex_color_smooth():
    """Smooth colors across vertices

    """
    pass


def rebuild():
    """This method is called, everytime a document is updated.
        """


@staticmethod
def stateMap():
    """
        Empty state map to allow instantiation of base class
        """
    stateDict = {}
    return stateDict


def torrent_availability(seeds, leeches):
    """Returns a rating based on seeds and leeches for a given torrent.
    :param seeds: Number of seeds on the torrent
    :param leeches: Number of leeches on the torrent
    :return: A numeric rating
    """
    return seeds * 2 + leeches


def bayes_posterior(prior, likelihood_df):
    """Calculate posterior given likelihoods and prior."""
    p_1 = prior * likelihood_df.iloc[:, (0)]
    p_2 = (1.0 - prior) * likelihood_df.iloc[:, (1)]
    return p_1 / (p_1 + p_2)


def decode(byte_data):
    """
    Decode the byte data to a string - in the case of this Py2 version, we can't really do anything (Py3 differs).
    """
    return byte_data


def traverse_dict(obj, query):
    """
        Get elements inside a nested dict, based on a dict query. The query is defined by a
        string separated by '__'. traverse_dict(foo, 'a__b__c') is roughly equivalent to foo[a][b][c] but
        will short circuit to return None if something on the query is None.
    """
    query = query.split('__')
    for name in query:
        obj = obj.get(name, None)
        if obj is None:
            return None
    return obj


def fmt_str(val):
    """Returns the peculiar formats of data expected by most of the Opsview
    API
    """
    if isinstance(val, bool):
        return '%d' % val
    elif isinstance(val, int):
        return '%d' % val
    elif isinstance(val, str):
        return val
    elif val:
        return '%s' % val
    return None


def run_script(script_name, namespace):
    """Execute the named script in the supplied namespace dictionary"""


def select_all_toggle(invert: bool=False):
    """Toggle selection of all keyframes

    :param invert: Invert
    :type invert: bool
    """
    pass


def _get_output_filename(dataset_dir, split_name):
    """Creates the output filename.

  Args:
    dataset_dir: The directory where the temporary files are stored.
    split_name: The name of the train/test split.

  Returns:
    An absolute file path.
  """
    return '%s/mnist_%s.tfrecord' % (dataset_dir, split_name)


def unregister_cms_apps(app):
    """
    Django CMS doesn't offer a function to unregister a cms app
    Allows overriding cms apps in allink_apps
    """
    from cms.apphook_pool import apphook_pool
    if app.__name__ in apphook_pool.apps:
        del apphook_pool.apps[app.__name__]


@staticmethod
def p_tp_blob(p):
    """tp_blob : TP_BLOB"""
    p[0] = p[1]


def to_list(obj):
    """Convert a list-like object to a list.

    >>> to_list([1, 2, 3])
    [1, 2, 3]

    >>> to_list("a,b,c")
    ['a', 'b', 'c']

    >>> to_list("item")
    ['item']

    >>> to_list(None)
    []

    """
    if isinstance(obj, (list, tuple)):
        return obj
    elif isinstance(obj, str):
        text = obj.strip()
        if ',' in text and ' ' not in text:
            return text.split(',')
        else:
            return text.split()
    elif obj is not None:
        return [obj]
    else:
        return []


def zeros_like(input):
    """Create a zero tensor with the same shape, dtype and context of the
    given tensor.

    Parameters
    ----------
    input : Tensor
        The input

    Returns
    -------
    Tensor
        The result
    """
    pass


@classmethod
def _select_machine(cls, choise, dataframe):
    """Select machine from data frame."""
    machine = list(dataframe.mach_name)[int(choise)]
    select_mach = dataframe['mach_name'] == machine
    print('\n', '\x1b[92m', machine, '\x1b[0m')
    return select_mach


def get_schema():
    """Schema structure of this resource

    :return: schema dictionary
    :rtype: dict
    """
    return {'mongo_indexes': {'index_updated': [('_updated', 1)],
        'index_name': [('name', 1)]}, 'schema': {'schema_version': {'type':
        'integer', 'default': 1}, 'imported_from': {'schema_version': 1,
        'title': 'Imported from', 'comment':
        'Item importation source (alignak-backend-import, ...)', 'type':
        'string', 'default': 'unknown'}, 'definition_order': {
        'schema_version': 1, 'title': 'Definition order', 'comment':
        'Priority level if several elements have the same name', 'type':
        'integer', 'default': 100}, 'name': {'schema_version': 1, 'title':
        'Time period name', 'comment': 'Unique time period name', 'type':
        'string', 'required': True, 'empty': False, 'unique': True},
        'alias': {'schema_version': 1, 'title': 'Alias', 'comment':
        'Element friendly name used by the Web User Interface.', 'type':
        'string', 'default': ''}, 'notes': {'schema_version': 1, 'title':
        'Notes', 'comment':
        'Element notes. Free text to store element information.', 'type':
        'string', 'default': ''}, 'dateranges': {'schema_version': 1,
        'title': 'Date ranges', 'comment': 'List of date ranges', 'type':
        'list', 'default': []}, 'exclude': {'schema_version': 1, 'title':
        'Exclusions', 'comment': 'List of excluded ranges.', 'type': 'list',
        'default': []}, 'is_active': {'schema_version': 1, 'title':
        'Active', 'comment':
        'The timeperiod is currently active or inactive.', 'type':
        'boolean', 'default': False}, '_realm': {'schema_version': 1,
        'title': 'Realm', 'comment': 'Realm this element belongs to.',
        'type': 'objectid', 'data_relation': {'resource': 'realm',
        'embeddable': True}, 'required': True}, '_sub_realm': {
        'schema_version': 1, 'title': 'Sub-realms', 'comment':
        'Is this element visible in the sub-realms of its realm?', 'type':
        'boolean', 'default': True}, '_users_read': {'schema_version': 1,
        'type': 'list', 'schema': {'type': 'objectid', 'data_relation': {
        'resource': 'user', 'embeddable': True}}}, '_users_update': {
        'schema_version': 1, 'type': 'list', 'schema': {'type': 'objectid',
        'data_relation': {'resource': 'user', 'embeddable': True}}},
        '_users_delete': {'schema_version': 1, 'type': 'list', 'schema': {
        'type': 'objectid', 'data_relation': {'resource': 'user',
        'embeddable': True}}}}, 'schema_deleted': {}}


def before_parenthesis_lowercased(value):
    """Returns all the content of a string before a parenthesis
    opening character it's found.

    :param value: Source value.
    :type value: str
    """
    value = value.lower()
    if '(' in value:
        value = value.split('(')[0]
    return value.strip(' ')


def _get_representation_attrs(frame, units, kwargs):
    """
    Find instances of the "representation attributes" for specifying data
    for this frame.  Pop them off of kwargs, run through the appropriate class
    constructor (to validate and apply unit), and put into the output
    valid_kwargs.  "Representation attributes" are the frame-specific aliases
    for the underlying data values in the representation, e.g. "ra" for "lon"
    for many equatorial spherical representations, or "w" for "x" in the
    cartesian representation of Galactic.

    This also gets any *differential* kwargs, because they go into the same
    frame initializer later on.
    """
    frame_attr_names = frame.representation_component_names.keys()
    repr_attr_classes = frame.representation_type.attr_classes.values()
    valid_kwargs = {}
    for frame_attr_name, repr_attr_class, unit in zip(frame_attr_names,
        repr_attr_classes, units):
        value = kwargs.pop(frame_attr_name, None)
        if value is not None:
            valid_kwargs[frame_attr_name] = repr_attr_class(value, unit=unit)
    differential_type = frame.differential_type
    if differential_type is not None:
        for frame_name, repr_name in frame.get_representation_component_names(
            's').items():
            diff_attr_class = differential_type.attr_classes[repr_name]
            value = kwargs.pop(frame_name, None)
            if value is not None:
                valid_kwargs[frame_name] = diff_attr_class(value)
    return valid_kwargs


def clean_fields(fields, ignored_value_indices, transforms):
    """
    Sometimes, NetMHC* has fields that are only populated sometimes, which results
    in different count/indexing of the fields when that happens.

    We handle this by looking for particular strings at particular indices, and
    deleting them.

    Warning: this may result in unexpected behavior sometimes. For example, we
    ignore "SB" and "WB" for NetMHC 3.x output; which also means that any line
    with a key called SB or WB will be ignored.

    Also, sometimes NetMHC* will have fields that we want to modify in some
    consistent way, e.g. NetMHCpan3 has 1-based offsets and all other predictors
    have 0-based offsets (and we rely on 0-based offsets). We handle this using
    a map from field index to transform function.
    """
    cleaned_fields = []
    for i, field in enumerate(fields):
        if field in ignored_value_indices:
            ignored_index = ignored_value_indices[field]
            if ignored_index == i:
                continue
        cleaned_field = transforms[i](field) if i in transforms else field
        cleaned_fields.append(cleaned_field)
    return cleaned_fields


def _literal(nonnumeric):
    """Convert a non-numeric blackbird literal to a Python literal.

    Args:
        nonnumeric (blackbirdParser.NonnumericContext): nonnumeric context
    Returns:
        str or bool
    """
    if nonnumeric.STR():
        return str(nonnumeric.getText().replace('"', ''))
    if nonnumeric.BOOL():
        val = nonnumeric.getText()
        if val == 'True':
            return True
        if val == 'False':
            return False
        raise ValueError('Unknown boolean value ' + nonnumeric.getText())
    raise ValueError('Unknown value ' + nonnumeric.getText())


def escape(string):
    """ Returns the string with control characters for Pattern syntax escaped.
        For example: "hello!" => "hello\\!".
    """
    for ch in ('{', '}', '[', ']', '(', ')', '_', '|', '!', '*', '+', '^'):
        string = string.replace(ch, '\\' + ch)
    return string


def get_image_id(filename):
    """ Gets id of an image. The id is constructed using the date of the
    typhoon. Note that typhoons from different sequences might have the
    same ID since they were recorded at the same time. Therefore, the final
    id is constructed using both the date and the typhoon ID together.
    To build the image id, the name of the original HDF file is used,
    which have the following structure:
    *YYYYMMDDHH-<typhoon id>-<satellite model>.h5*
    We can then parse it to the id, namely
    *<typhoon id>_YYYYMMDDHH*

    :param filename: Name of the HDF image file.
    :type filename: str
    :return: Image frame id
    :rtype: int
    """
    return filename.split('-')[1] + '_' + filename.split('-')[0]


@classmethod
def package_name(cls):
    """Python package name (at PyPI)."""
    return 'safewise-agent'


def get_folder_id(drive):
    """Determines the folder id of cfs-m's root folder"""
    folder_id = None
    file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}
        ).GetList()
    for f in file_list:
        if f['title'] == 'CFS_Manager':
            folder_id = f['id']
            return folder_id
    else:
        folder = drive.CreateFile({'title': 'CFS_Manager', 'mimeType':
            'application/vnd.google-apps.folder'})
        folder.Upload()
        return folder['id']


def binomial(n, k):
    """
    A fast way to calculate binomial coefficients by Andrew Dalke.
    See http://stackoverflow.com/questions/3025162/statistics-combinations-in-python

    By Andrew Dalke.
    """
    if 0 <= k <= n:
        ntok = 1
        ktok = 1
        for t in range(1, min(k, n - k) + 1):
            ntok *= n
            ktok *= t
            n -= 1
        return ntok // ktok
    else:
        return 0


def one(iterable, too_short=None, too_long=None):
    """Return the first item from *iterable*, which is expected to contain only
    that item. Raise an exception if *iterable* is empty or has more than one
    item.
    :func:`one` is useful for ensuring that an iterable contains only one item.
    For example, it can be used to retrieve the result of a database query
    that is expected to return a single row.
    If *iterable* is empty, ``ValueError`` will be raised. You may specify a
    different exception with the *too_short* keyword:

    >>> it = []
    >>> one(it)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    ValueError: too many items in iterable (expected 1)'
    >>> too_short = IndexError('too few items')
    >>> one(it, too_short=too_short)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    IndexError: too few items

    Similarly, if *iterable* contains more than one item, ``ValueError`` will
    be raised. You may specify a different exception with the *too_long*
    keyword:

    >>> it = ['too', 'many']
    >>> one(it)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    ValueError: too many items in iterable (expected 1)'
    >>> too_long = RuntimeError
    >>> one(it, too_long=too_long)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ...
    RuntimeError

    Note that :func:`one` attempts to advance *iterable* twice to ensure there
    is only one item. If there is more than one, both items will be discarded.
    See :func:`spy` or :func:`peekable` to check iterable contents less
    destructively.
    """
    it = iter(iterable)
    try:
        value = next(it)
    except StopIteration:
        raise (too_short or ValueError(
            'too few items in iterable (expected 1)'))
    try:
        next(it)
    except StopIteration:
        pass
    else:
        raise (too_long or ValueError(
            'too many items in iterable (expected 1)'))
    return value


@staticmethod
def save(file_path, model):
    """
        Save the model onto the file identified by file_path.

        Parameters
        ----------
        file_path : str
            The path to the filename where the model has to be saved
        model : RTEnsemble
            The model RTEnsemble model to save on file

        Returns
        -------
        status : bool
            Returns true if the save is successful, false otherwise
        """
    raise NotImplementedError('Feature not implemented!')


def attach_subscriptions(obj, dispatcher):
    """
    Attach subscriptions to an actual event dispatcher.

    :param object obj:
    :param EventDispatcher dispatcher:
    :return:
    """
    for k in dir(obj):
        f = getattr(obj, k)
        if k[0] != '_' and callable(f) and hasattr(f, '__subscriptions__'):
            for event_id, priority in f.__subscriptions__.items():
                dispatcher.add_listener(event_id, f, priority=priority)


def as_scalar(data):
    """Returns a scalar whose value is copied from this array.

    Parameters
    ----------
    data : Tensor
        The input data

    Returns
    -------
    scalar
        The scalar value in the tensor.
    """
    pass


def most_common(lst: list):
    """Used by consensus"""
    return max(set(lst), key=lst.count)


@classmethod
def get_number_of_runs(cls, subject_id):
    """Return the number of runs for the given subject.

        Parameters
        ----------
        subject_id : str
            The subject id

        Returns
        -------
        n_runs : int
            The number of runs for the subject.
        """
    n_runs = 1
    while cls.get_fif_filename(subject_id, n_runs) is not None:
        n_runs += 1
    return n_runs - 1


def fprod(ctx, factors):
    """
        Calculates a product containing a finite number of factors (for
        infinite products, see :func:`~mpmath.nprod`). The factors will be
        converted to mpmath numbers.

            >>> from mpmath import *
            >>> mp.dps = 15; mp.pretty = False
            >>> fprod([1, 2, 0.5, 7])
            mpf('7.0')

        """
    orig = ctx.prec
    try:
        v = ctx.one
        for p in factors:
            v *= p
    finally:
        ctx.prec = orig
    return +v


def get_min_distance(coord, target_array) ->float:
    """Calculate minimum distance between `coord` and `target_array`."""
    return (((target_array - coord) ** 2).sum(axis=1) ** 0.5).min()


def get_digitalization_links(newrecord):
    """
    Given a marc record, just return all links (from 856.u).
    """
    for field_856 in newrecord.get_fields('856'):
        is_digitalization = False
        for x in field_856.get_subfields('x'):
            if 'Digitalization' == x:
                is_digitalization = True
        if not is_digitalization:
            for z in field_856.get_subfields('z'):
                if 'digit' in z or 'Digit' in z and not ('Bach digital' in
                    z or 'Bach Digital' in z):
                    is_digitalization = True
                elif 'exemplar' in z or 'Exemplar' in z:
                    is_digitalization = True
        if is_digitalization:
            for url in field_856.get_subfields('u'):
                yield url


def ignore_private(elem):
    """Ignore rule for `MetaExtractor` to skip private DICOM elements (odd
    group number)."""
    if elem.tag.group % 2 == 1:
        return True
    return False


def comptage(L):
    """ Trie la liste avec la méthode du tri par comptage

    :param l: Un tableau de nombre
    :return: une copie de la liste triée

    >>> comptage([1, 2, 6, 5])
    [1, 2, 5, 6]
    """
    vmin = min(L)
    vmax = max(L)
    hist = [(0) for _ in range(vmin, vmax + 1)]
    for l in L:
        hist[l - vmin] += 1
    ans = []
    for i, v in enumerate(hist):
        ans += [i + vmin] * v
    return ans


@staticmethod
def _get_new_obj(model_cls, id_gen, field, tag):
    """Generate a new model object for associated data for
        an audio tag.
        """
    val = getattr(tag, field, None)
    if val is None:
        raise AttributeError('Invalid tag field {0} for {1}'.format(field,
            tag.path))
    obj = model_cls()
    obj.id = id_gen(val)
    obj.name = val
    return obj


def assert_kwargs(kwargs):
    """Raise an exception if extra keys are present."""
    if len(kwargs) > 0:
        extra = 's' if len(kwargs) > 1 else ''
        raise TypeError('Unexpected argument%s: %s' % (extra, ', '.join(
            kwargs)))


@classmethod
def from_pairs(cls, pairs):
    """ Create message from an iterable of ``(tag, value, is_header)`` tuples.

        :param pairs: An iterable of 3-tuple's ``(tag, value, is_header)``.
            `is_header` specifies whether the pair should be appended to the
            standard header or not.
        :return:
        """
    msg = cls()
    for tag, val, is_header in pairs:
        msg.append_pair(tag, val, header=is_header)
    return msg


def get_fw_by_task_index(wf, task_tag, index=1):
    """
    Given a workflow object (with connection to the db) returns the wf corresponding to the task_type.

    Args:
        wf: a fireworks Workflow object.
        task_tag: the task tag associated with the task as defined in abinit_workflows. Should not include the index.
        index: the numerical or text index of the task. If negative the the last fw corresponding to task_tag will
            be selected. If None, no index will be considered and the first match will be returned.

    Returns:
        a fireworks Firework object. None if no match is found.
    """
    task_index = None
    if index is not None and index >= 0:
        task_index = '{}_{}'.format(task_tag, index)
    selected_fw = None
    max_ind = -1
    for fw in wf.fws:
        fw_task_index = fw.spec.get('wf_task_index', '')
        if task_index:
            if fw_task_index == task_index:
                return fw
        elif task_tag in fw_task_index:
            if index is None:
                return fw
            try:
                fw_ind = int(fw_task_index.split('_')[-1])
                if fw_ind > max_ind:
                    selected_fw = fw
                    max_ind = fw_ind
            except:
                if selected_fw is None:
                    selected_fw = fw
    return selected_fw


@classmethod
def get_field_name_to_field(cls):
    """
        Returns dictionary with fieldnames defined in searchset class and field instances
        """
    if cls._field_name_to_search_field_instance is None:
        cls._field_name_to_search_field_instance = dict()
        cls._field_source_to_search_field_instance = dict()
        for name, _cls in cls.__dict__.items():
            if isinstance(_cls, cls._field_base_class):
                cls._field_name_to_search_field_instance[name] = _cls
                if (_cls.use_field_class_for_sources and not _cls.
                    exclude_sources_from_mapping and _cls.sources):
                    for field_source in _cls.sources:
                        cls.append_field_source_to_search_field_instance(source
                            =field_source, instance=_cls.__class__())
    return cls._field_name_to_search_field_instance


def managers_for_display():
    """Get the tracker managers.
        """


def is_hashable(obj) ->bool:
    """
    Return True if hash(obj) will succeed, False otherwise.

    Some types will pass a test against collections.abc.Hashable but fail when
    they are actually hashed with hash().

    Distinguish between these and other types by trying the call to hash() and
    seeing if they raise TypeError.

    Returns
    -------
    bool

    Examples
    --------
    >>> a = ([],)
    >>> isinstance(a, collections.abc.Hashable)
    True
    >>> is_hashable(a)
    False
    """
    try:
        hash(obj)
    except TypeError:
        return False
    else:
        return True


@classmethod
def unset_connection_resolver(cls):
    """
        Unset the connection resolver instance.
        """
    cls._resolver = None


def build_default_cache(user, obj1, obj2, obj3, data):
    """ build cache for default log types """
    return {'object1_str': str(obj1)}


def rasterFromDataset(dataset):
    """
	Reads all raster bands from a dataset and returns them as a NumPy ndarray of shape (h,w[,c])
	"""
    raster = dataset.ReadAsArray()
    if len(raster.shape) > 2:
        raster = raster.transpose((1, 2, 0))
    return raster


def create_grid(bm: 'bmesh.types.BMesh', x_segments: int, y_segments: int,
    size: float, matrix: 'mathutils.Matrix', calc_uvs: bool) ->dict:
    """Creates a grid with a variable number of subdivisions

    :param bm: The bmesh to operate on.
    :type bm: 'bmesh.types.BMesh'
    :param x_segments: number of x segments
    :type x_segments: int
    :param y_segments: number of y segments
    :type y_segments: int
    :param size: size of the grid
    :type size: float
    :param matrix: matrix to multiply the new geometry with
    :type matrix: 'mathutils.Matrix'
    :param calc_uvs: calculate default UVs
    :type calc_uvs: bool
    :return:  verts: output vertstype list of (bmesh.types.BMVert)
    """
    pass


def dedup(l, suffix='__'):
    """De-duplicates a list of string by suffixing a counter

    Always returns the same number of entries as provided, and always returns
    unique values.

    >>> print(','.join(dedup(['foo', 'bar', 'bar', 'bar'])))
    foo,bar,bar__1,bar__2
    """
    new_l = []
    seen = {}
    for s in l:
        if s in seen:
            seen[s] += 1
            s += suffix + str(seen[s])
        else:
            seen[s] = 0
        new_l.append(s)
    return new_l


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 health_after_attacks(n, h_0, m, a, method):
    """ Calculates the health of an opponent after a certain number of attacks.
		@param n The number of turns to attack for.
		@param h_0 The initial health of the opponent.
		@param m The max hit of the attacker.
		@param a The accuracy of the attacker.
		@param method The calculation method. @see successful_hits.py. """
    assert 0 <= a <= 1, a
    return method.h(n * a, h_0, m)


def writeFasta(sequence, sequence_name, output_file):
    """
    Writes a fasta sequence into a file.

    :param sequence: a string with the sequence to be written
    :param sequence_name: name of the the fasta sequence
    :param output_file: /path/to/file.fa to be written

    :returns: nothing
    """
    i = 0
    f = open(output_file, 'w')
    f.write('>' + str(sequence_name) + '\n')
    while i <= len(sequence):
        f.write(sequence[i:i + 60] + '\n')
        i = i + 60
    f.close()


@staticmethod
def _tagged_contexts(contexts):
    """Reduce the contexts to the latest, and tag them as changed/unchanged since the last save."""
    tagged_contexts = {}
    for tool, current_context in contexts['current_state'].items():
        last_context = contexts['last_saved'].get(tool, None)
        this_tagged_context = current_context.copy()
        changed = last_context != current_context
        this_tagged_context['affected files'] = []
        if last_context and changed and last_context['trigger files'
            ] == this_tagged_context['trigger files'] and last_context['config'
            ] == this_tagged_context['config'] and last_context['preconditions'
            ] == this_tagged_context['preconditions']:
            for file_name, file_hash in list(this_tagged_context[
                'target files'].items()):
                if last_context['target files'].get(file_name, None
                    ) != file_hash:
                    this_tagged_context['affected files'].append(file_name)
        else:
            this_tagged_context['affected files'] = this_tagged_context[
                'target files']
        tagged = {'context': this_tagged_context, 'changed': changed}
        tagged_contexts[tool] = tagged
    return tagged_contexts


def name():
    """
        Имя домена (относительно пути).

        Если домен корневой или не содержится в пути,
        имя может быть C{None}.

        @return: имя домена
        @rtype: C{str}
        """


@classmethod
def handle_file(cls, pathname='./', filename='*', first=True):
    """Return a string of the content of the file.

        :param str pathname: Path to the report directory.
        :param str filename: Regex matching the report file.
        :param bool first: Stop the search as soon as a file has been matched.

        :raises IOError: when the report file cannot be found or an error occurs when opening/reading.
        :raises OSError: when an error occurs when opening/reading the report file.

        :return: data from the file.
        :rtype: str

        """
    fullpath = cls._recursive_find(pathname, filename, first=first)
    if not len(fullpath):
        raise IOError("Report matching '%s' cannot be found." % filename)
    fullpath = fullpath[0]
    data = ''
    with open(fullpath, 'r') as f:
        data = f.read()
    return data


@classmethod
def enforce_unitscheck(cls, val):
    """If `val` is True, adjust Quantity objects to correct units. If *val* is False, ignore units."""
    if val:
        cls.unitscheck = cls._unitscheck
    else:
        cls.unitscheck = cls._unitsignore


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

        :param TeamMergeRequestCanceledShownToPrimaryTeamType val:
        :rtype: EventType
        """
    return cls('team_merge_request_canceled_shown_to_primary_team', val)


@classmethod
def make_mask_outside(cls, mask, size, buffer=0):
    """Return labeled mask of area around bead."""
    if buffer > 0:
        mask_min = cls._morph_mask_step(buffer, mask)
    else:
        mask_min = mask
    mask_outside = cls._morph_mask_step(size, mask)
    mask_outside[mask_min > 0] = 0
    return mask_outside


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


def provider_parser(subparser):
    """Generate subparser for nfsn"""
    subparser.add_argument('--auth-username', help=
        'specify username used to authenticate')
    subparser.add_argument('--auth-token', help=
        'specify token used to authenticate')


def highlander(iterable):
    """check only single True value in iterable"""
    i = iter(iterable)
    return any(i) and not any(i)


def longest_prefix(prefix_l, s):
    """Among the list of strings ``prefix_l``, find the longest prefix match
    for string ``s``."""
    result = None
    for p in prefix_l:
        if s.startswith(p):
            result = p if result == None or len(p) > len(result) else result
    return result


def getDebugInfo():
    """Returns a tuple with different items for debugging the connection.

        Debug information can be added to a connection by using setDebugInfo.
        """


def _get_dpi_ratio(fig):
    """Get DPI ratio (to handle hi-DPI screens)."""
    dpi_ratio = 1.0
    for key in ('_dpi_ratio', '_device_scale'):
        dpi_ratio = getattr(fig.canvas, key, dpi_ratio)
    return dpi_ratio


@classmethod
def execute(cls, inputs, files=None, **kwargs):
    """
        Function to be called from the outside to kick off the Service
        functionality.

        :param dictionary inputs: data parameters for Service, checked
            against the fields defined on the Service class.

        :param dictionary files: usually request's FILES dictionary or
            None.

        :param dictionary **kwargs: any additional parameters Service may
            need, can be an empty dictionary
        """
    instance = cls(inputs, files, **kwargs)
    instance.service_clean()
    with instance._process_context():
        return instance.process()


def list_replace(a_list, old, new):
    """
    Replaces every `old` item in `a_list` with `new` item
    """
    for i, item in enumerate(a_list):
        if item == old:
            a_list[i] = new


def _objective_func(f, x_full, k_params, alpha, *args):
    """
    The regularized objective function
    """
    x_params = x_full[:k_params]
    x_added = x_full[k_params:]
    return f(x_params, *args) + (alpha * x_added).sum()


@classmethod
def upcoming(cls, api_key=None, stripe_account=None, **params):
    """Return a deferred."""
    url = cls.class_url() + '/upcoming'
    return cls.request('get', url, params)


def compute_atom_fractions(atoms):
    """
    Return the atomic fractions of each element in a compound,
    given a dictionary of its atoms and their counts, in the format
    {symbol: count}.

    .. math::
        a_i =  \\frac{n_i}{\\sum_i n_i}

    Parameters
    ----------
    atoms : dict
        dictionary of counts of individual atoms, indexed by symbol with
        proper capitalization, [-]

    Returns
    -------
    afracs : dict
        dictionary of atomic fractions of individual atoms, indexed by symbol
        with proper capitalization, [-]

    Notes
    -----
    No actual data on the elements is used, so incorrect or custom compounds
    would not raise an error.

    Examples
    --------
    >>> compute_atom_fractions({'H': 12, 'C': 20, 'O': 5})
    {'H': 0.32432432432432434, 'C': 0.5405405405405406, 'O': 0.13513513513513514}

    """
    count = sum(atoms.values())
    afracs = {}
    for i in atoms:
        afracs[i] = atoms[i] / count
    return afracs


def create_hsm_client_certificate(HsmClientCertificateIdentifier=None, Tags
    =None):
    """
    Creates an HSM client certificate that an Amazon Redshift cluster will use to connect to the client's HSM in order to store and retrieve the keys used to encrypt the cluster databases.
    The command returns a public key, which you must store in the HSM. In addition to creating the HSM certificate, you must create an Amazon Redshift HSM configuration that provides a cluster the information needed to store and use encryption keys in the HSM. For more information, go to Hardware Security Modules in the Amazon Redshift Cluster Management Guide.
    See also: AWS API Documentation

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

    :type HsmClientCertificateIdentifier: string
    :param HsmClientCertificateIdentifier: [REQUIRED]
            The identifier to be assigned to the new HSM client certificate that the cluster will use to connect to the HSM to use the database encryption keys.

    :type Tags: list
    :param Tags: A list of tag instances.
            (dict) --A tag consisting of a name/value pair for a resource.
            Key (string) --The key, or name, for the resource tag.
            Value (string) --The value for the resource tag.

    :rtype: dict
    :return: {
        'HsmClientCertificate': {
            'HsmClientCertificateIdentifier': 'string',
            'HsmClientCertificatePublicKey': 'string',
            'Tags': [
                {
                    'Key': 'string',
                    'Value': 'string'
                },
            ]
        }
    }

    """
    pass


def validate_params(request):
    """Validate request params."""
    if 'params' in request:
        correct_params = isinstance(request['params'], (list, dict))
        error = 'Incorrect parameter values'
        assert correct_params, error


def bool_to_str(value: bool) ->str:
    """Converts boolean to 'ON' or 'OFF' string."""
    if type(value) is bool:
        return 'ON' if value is True else 'OFF'
    else:
        raise Exception(
            f"bool_to_str: unsupported variable type '{type(value)}', value '{value}'. Only boolean values are supported."
            )