@classmethod
def now(cls):
    """[!81zsw] Almost same as datetime.now(), except returning LocalDateTime object."""
    pass


def __sub_class_rename__(tab):
    """
    Changes the sub-class identification of SDSS DR12 in such a way, that for stars only the main identification
    (Kx, Fy, ...) is left. WD's are also only one sub-class and it won't be distingushed between
    hot and cool ones.
    The identification of galaxies and QSO's is untouched.

    :param tab: The input table with the data from the SDSS DR12
    :type tab: numpy.ndarray, astropy.table.Table
    :return: The input data with the changed sub-class identification
    :rtype: numpy.ndarray, astropy.table.Table
    """
    for i, t in enumerate(tab):
        sub_cl = t['subCl'].split(' ')
        if len(sub_cl) > 1:
            tab['subCl'][i] = sub_cl[0]
        sub_cl = sub_cl[0]
        if (len(sub_cl) == 3 or len(sub_cl) == 4) and sub_cl[-1] != 'N':
            if 'sd' in sub_cl:
                sub_cl = sub_cl[2:]
            else:
                sub_cl = sub_cl[:2]
            tab['subCl'][i] = sub_cl
        elif '/' in sub_cl:
            if 'Ib' in sub_cl:
                sub_cl = sub_cl.split('Ib')[0]
            else:
                sub_cl = sub_cl.split('/')[0]
            tab['subCl'][i] = sub_cl
        elif 'WD' in sub_cl:
            tab['subCl'][i] = 'WD'
        elif 'III' in sub_cl:
            sub_cl = sub_cl[:2]
            tab['subCl'][i] = sub_cl
        elif ':' in sub_cl:
            sub_cl = sub_cl.split(':')[-1]
            tab['subCl'][i] = sub_cl
        elif '.' in sub_cl:
            if 'Ib' in sub_cl:
                sub_cl = sub_cl.split('Ib')[0]
            elif 'V.' in sub_cl:
                sub_cl = sub_cl.split('V.')[0]
            sub_cl = sub_cl.split('.')[0]
            tab['subCl'][i] = sub_cl
        elif 'lb' in sub_cl:
            sub_cl = sub_cl.split('lb')[0]
            tab['subCl'][i] = sub_cl
        elif 'Ib' in sub_cl:
            sub_cl = sub_cl.split('Ib')[0]
            tab['subCl'][i] = sub_cl
        elif 'IV' in sub_cl:
            sub_cl = sub_cl.split('IV')[0]
            tab['subCl'][i] = sub_cl
        elif 'Ia' in sub_cl:
            sub_cl = sub_cl.split('Ia')[0]
            tab['subCl'][i] = sub_cl
        elif 'Vn' in sub_cl:
            sub_cl = sub_cl.split('Vn')[0]
            tab['subCl'][i] = sub_cl
    tab = tab[tab['subCl'] != '']
    return tab


def setup_tracking_scene():
    """Prepare scene for compositing 3D objects into this footage

    """
    pass


def hasTemplate(s):
    """ Return True if string s has string templates """
    return '{' in s and '}' in s


def _improve_answer_span(doc_tokens, input_start, input_end, tokenizer,
    orig_answer_text):
    """Returns tokenized answer spans that better match the annotated answer."""
    tok_answer_text = ' '.join(tokenizer.tokenize(orig_answer_text))
    for new_start in range(input_start, input_end + 1):
        for new_end in range(input_end, new_start - 1, -1):
            text_span = ' '.join(doc_tokens[new_start:new_end + 1])
            if text_span == tok_answer_text:
                return new_start, new_end
    return input_start, input_end


def grant_permission(username, action):
    """Grant a user permission to perform an action."""


@classmethod
def with_params(cls, xid, path, watch, data, offset, size, client, server):
    """
    Build a ClientMessage with the given params, possibly parsing some more.

    This must be overridden by subclasses so the specific parameters to each subclass
    can be extracted.

    :param xid: the transaction id associated with this ClientMessage
    :param path: the path associated with this ClientMessage, if any
    :param watch: a boolean indicating if watch on the path should be set
    :param data: the remaining data of the associated data packet
    :param offset: the offset from which the data should be read
    :param size: the total size of this ClientMessage
    :param client: the ip:port generating this ClientMessage

    :returns: Returns an instance of the specific ClientMessage subclass.
    :raises DeserializationError: if parsing the ClientMessage fails.
    """
    return cls(size, xid, path, client, watch, server)


def sum_fuel_across_sectors(fuels):
    """Sum fuel across sectors of an enduse if multiple sectors.
    Otherwise return unchanged `fuels`

    Arguments
    ---------
    fuels : dict or np.array
        Fuels of an enduse either for sectors or already aggregated

    Returns
    -------
    sum_array : np.array
        Sum of fuels of all sectors
    """
    if isinstance(fuels, dict):
        sum_array = sum(fuels.values())
        return sum_array
    else:
        return fuels


@classmethod
def convert_to_xml(cls, value):
    """
        Keep alpha hex numerals all uppercase just for consistency.
        """
    return '%02X%02X%02X' % value


@classmethod
def add_url_rules(cls, app, rule_prefix, endpoint_prefix=None):
    """
        A convenience method for hooking up the URLs.

        This automatically adds a list & a detail endpoint to your routes.

        :param app: The ``Flask`` object for your app.
        :type app: ``flask.Flask``

        :param rule_prefix: The start of the URL to handle.
        :type rule_prefix: string

        :param endpoint_prefix: (Optional) A prefix for the URL's name (for
            endpoints). The default is ``None``, which will autocreate a prefix
            based on the class name. Ex: ``BlogPostResource`` ->
            ``api_blog_post_list``
        :type endpoint_prefix: string

        :returns: Nothing
        """
    methods = ['GET', 'POST', 'PUT', 'DELETE']
    app.add_url_rule(rule_prefix, endpoint=cls.build_endpoint_name('list',
        endpoint_prefix), view_func=cls.as_list(), methods=methods)
    app.add_url_rule(rule_prefix + '<pk>/', endpoint=cls.
        build_endpoint_name('detail', endpoint_prefix), view_func=cls.
        as_detail(), methods=methods)


def dbh__movie(path, contenttype, extension, roottag, nsurl):
    """ Generic Web Page Handler - Returns image_generic for Web browser supported images """
    if extension.lower() in ['avi', 'mpg']:
        return 'db_movie_viewer'
    else:
        return False


def _recv_n_create_rq(event):
    """Logging handler when an N-CREATE-RQ is received.

    Parameters
    ----------
    event : events.Event
        The evt.EVT_DIMSE_RECV event that occurred.
    """
    pass


def say_hello(to):
    """Say hello to somebody"""
    return f'Hello {to}!'


def get_trail_by_arn(cloudtrail_client, trail_arn):
    """Gets trail information based on the trail's ARN"""
    trails = cloudtrail_client.describe_trails()['trailList']
    for trail in trails:
        if trail.get('TrailARN', None) == trail_arn:
            return trail
    raise ValueError('A trail could not be found for %s' % trail_arn)


def _get_resource(service, resources):
    """
    For multiple resources, give us the resource object associated with the
    last resource
    """
    resource = service
    for item in resources:
        resource = getattr(resource, item)()
    return resource


def _format_float(arg):
    """Formats a float value to be as short as possible.

    Trims extraneous trailing zeros and period to give API
    args the best possible chance of fitting within 2000 char
    URL length restrictions.

    For example:

    format_float(40) -> "40"
    format_float(40.0) -> "40"
    format_float(40.1) -> "40.1"
    format_float(40.001) -> "40.001"
    format_float(40.0010) -> "40.001"

    :param arg: The lat or lng float.
    :type arg: float

    :rtype: string
    """
    return '{}'.format(round(float(arg), 6)).rstrip('0').rstrip('.')


def render(id, template_path, input):
    """Render a template.

        id - the id for the collection
        template_path - the relative path (or filename) of the template
                        itself, under the path of the collection
        input - input data for the template

        If the template raises a CompileError or RenderError, the
        system will automatically fall back on the original
        non-customized template.
        """


def nearest_colour_index(colour_map, rgb, debug=0):
    """
    General purpose function. Uses Euclidean distance.
    So far used only for pre-BIFF8 ``WINDOW2`` record.
    Doesn't have to be fast.
    Doesn't have to be fancy.
    """
    best_metric = 3 * 256 * 256
    best_colourx = 0
    for colourx, cand_rgb in colour_map.items():
        if cand_rgb is None:
            continue
        metric = 0
        for v1, v2 in zip(rgb, cand_rgb):
            metric += (v1 - v2) * (v1 - v2)
        if metric < best_metric:
            best_metric = metric
            best_colourx = colourx
            if metric == 0:
                break
    if 0 and debug:
        print('nearest_colour_index for %r is %r -> %r; best_metric is %d' %
            (rgb, best_colourx, colour_map[best_colourx], best_metric))
    return best_colourx


@staticmethod
def _format_comments(comment, tcomment):
    """Formats the extracted and translator comments of the entry and
        returns them.
        """
    return '\n'.join([comment, tcomment])


def handle_error(msg, err_type, logger, raise_msg=None, log_msg=None):
    """handle an error, by logging it, then raising an exception"""
    if raise_msg is None:
        raise_msg = msg
    if log_msg is None:
        log_msg = msg
    logger.error(log_msg)
    raise err_type(raise_msg)


def convert_ywdhms_to_seconds(y, w, d, h, m, s):
    """The inverse of _divmod_time"""
    d += w * 7
    d += y * 365
    h += 24 * d
    m += 60 * h
    s += 60 * m
    return s


@classmethod
def get_non_optional_settings(cls):
    """
        This method has to determine which settings are needed by this bear.
        The user will be prompted for needed settings that are not available
        in the settings file so don't include settings where a default value
        would do.

        Note: This function also queries settings from bear dependencies in
        recursive manner. Though circular dependency chains are a challenge to
        achieve, this function would never return on them!

        :return: A dictionary of needed settings as keys and a tuple of help
                 text and annotation as values
        """
    non_optional_settings = {}
    for dependency in cls.BEAR_DEPS:
        non_optional_settings.update(dependency.get_non_optional_settings())
    non_optional_settings.update(cls.get_metadata().non_optional_params)
    return non_optional_settings


@staticmethod
def get_key(block_number, activation_delay):
    """
            activation_block_number is the block number after which config will be activated
            so an activation block number 10 means the config will be activated only after adding
            block number 10 into the block chain
        """
    activation_block_number = block_number + activation_delay
    return b'proposal_record_block_number_' + activation_block_number.to_bytes(
        8, byteorder='big', signed=False)


def get_enabled_plugins():
    """Returns a list of plugins that are enabled in the config."""


@classmethod
def coerce_float(cls, value):
    """ Coerce a Python value to a Cypher Float.

        :rtype: :py:class:`float`
        """
    return float(value)


@classmethod
def table_fullname(cls):
    """
        gets the table fullname that this entity represents in database.

        fullname is `schema.table_name` if schema is available, otherwise it
        defaults to `table_name`.

        :rtype: str
        """
    schema = cls.table_schema()
    name = cls.table_name()
    if schema is not None:
        return '{schema}.{name}'.format(schema=schema, name=name)
    else:
        return name


def create_constraint(AcceptLanguage=None, PortfolioId=None, ProductId=None,
    Parameters=None, Type=None, Description=None, IdempotencyToken=None):
    """
    Creates a new constraint.
    See also: AWS API Documentation

    :example: response = client.create_constraint(
        AcceptLanguage='string',
        PortfolioId='string',
        ProductId='string',
        Parameters='string',
        Type='string',
        Description='string',
        IdempotencyToken='string'
    )

    :type AcceptLanguage: string
    :param AcceptLanguage: The language code to use for this operation. Supported language codes are as follows:
            'en' (English)
            'jp' (Japanese)
            'zh' (Chinese)
            If no code is specified, 'en' is used as the default.

    :type PortfolioId: string
    :param PortfolioId: [REQUIRED]
            The portfolio identifier.

    :type ProductId: string
    :param ProductId: [REQUIRED]
            The product identifier.

    :type Parameters: string
    :param Parameters: [REQUIRED]
            The constraint parameters.

    :type Type: string
    :param Type: [REQUIRED]
            The type of the constraint.

    :type Description: string
    :param Description: The text description of the constraint.

    :type IdempotencyToken: string
    :param IdempotencyToken: [REQUIRED]
            A token to disambiguate duplicate requests. You can create multiple resources using the same input in multiple requests, provided that you also specify a different idempotency token for each request.
            This field is autopopulated if not provided.

    :rtype: dict
    :return: {
        'ConstraintDetail': {
            'ConstraintId': 'string',
            'Type': 'string',
            'Description': 'string',
            'Owner': 'string'
        },
        'ConstraintParameters': 'string',
        'Status': 'AVAILABLE'|'CREATING'|'FAILED'
    }

    """
    pass


def linear_equation(val1, val2, time1, time2, current_time):
    """Linear equation to get interpolated value.

    :param float val1: first keyframe value
    :param float val2: second keyframe value
    :param float time1: first keyframe local time
    :param float time2: second keyframe local time
    :param float current_time: current animation local time
    """
    return val1 + (val2 - val1) / (time2 - time1) * (current_time - time1)


def none_missing(df):
    """
    Asserts that there are no missing values (NaNs) in the DataFrame.
    """
    assert not df.isnull().any().any()
    return df


def is_function(x):
    """
    Checks if the provided expression x is a function term. i.e., a tuple
    where the first element is callable.
    """
    return isinstance(x, tuple) and len(x) > 0 and callable(x[0])


def prod(array):
    """array = list of lists"""
    ans = []
    for r in array:
        p = 1
        for i in r:
            p = p * i
        ans.append(p)
    return ans


def interpret(block: str):
    """
    Interprets an element block, breaking it into element and number of that element.

    :param block: string block describing an element
    :return: composition dictionary
    :rtype: dict
    """
    if block[0].isdigit() is True:
        return {block: 1}
    else:
        ele = block[0]
        i = 0
        num = ''
        while i < len(block) - 1:
            i += 1
            if block[i].isdigit() is True:
                num += block[i]
            elif block[i] == ' ':
                continue
            else:
                ele += block[i]
        if num == '':
            num = 1
        else:
            num = int(num)
        return {ele: num}


def reader(stream, errors='strict'):
    """Construct a StreamReader object for this codec."""


def goToNext():
    """Redirect to next step."""


def render_view_add():
    """Add a render view

    """
    pass


def slip(offset: int=0):
    """Trim the contents of the active strip

    :param offset: Offset, Offset to the data of the strip
    :type offset: int
    """
    pass


def sum_node_list(node_list):
    """Custom sum function in order to avoid create redundant nodes in Python sum implementation."""
    from operator import add
    from functools import reduce
    return reduce(add, node_list)


@classmethod
def setup(cls, url, **kw):
    """
        Constructs a global queue for all instances of me, returning a
        deferred that fires with it.
        """
    return cls.qFactory.setGlobal(url, **kw)


def hasSessionData():
    """Does a Session Data Object exist for the current browser id?

        o Do not create a Session Data Object if one does not exist.

        o Permission required: Access session data
        """


def ceil_div(num, div):
    """
    Returns the ceiling function of a division between `num` and `div`.

    Usage::

        >>> ceil_div(100, 7)
        15
        >>> ceil_div(100, 10)
        10
        >>> ceil_div(1, 4)
        1

    :param num: Division's numerator, a number
    :param div: Division's divisor, a number

    :return: Rounded up result of the division between the parameters.
    """
    quanta, mod = divmod(num, div)
    if mod:
        quanta += 1
    return quanta


def get_app_label(app):
    """
    Returns the _internal_ app label for the given app module.
    i.e. for <module django.contrib.auth.models> will return 'auth'
    """
    return app.__name__.split('.')[-2]


def getPassword():
    """Return password, or None if no login name found.

        If there's a login but no password, return empty string.
        """


def job_description(jobs):
    """Return description of jobs for usage string.
    """
    job_last = len(jobs) - 1
    if job_last <= 0:
        return '', -1
    job_list = 'Jobs:\n'
    for j, descr in enumerate(jobs):
        job_list += ' {:3d} {}\n'.format(j, descr)
    return job_list, job_last


def psi_K_MgOH_OH_HMW84(T, P):
    """c-c'-a: potassium magnesium-hydroxide hydroxide [HMW84]."""
    psi = 0
    valid = T == 298.15
    return psi, valid


def read_viewlayers():
    """Read all render layers of all used scenes

    """
    pass


def forceSquare(ax):
    """ Force axes to be square regardless of data limits """
    if ax is not None:
        x0, x1 = ax.get_xlim()
        y0, y1 = ax.get_ylim()
        ax.set_aspect((x1 - x0) / (y1 - y0))


def task_test():
    """run unit-tests using py.test"""
    return {'actions': ['py.test tests/']}


def label_key(label, padding=5):
    """Returns a padded key from a label representing a milestone number.
    All parts of a label that are numbers are padded so that alphabetical
    sorting can work as expected (e.g., '2.0' < '11.0').

    For example, this function will return 'v00001.00022e-00123b' if label =
    'v1.22e-123b'.

    :param label: the milestone label
    :param padding: the maximum number of characters for each numeric part.
           Default=5
    :return: a key that can be used in alphabetical sorting
    """
    key = prefix = ''
    components = []
    in_prefix = True
    current_number = current_suffix = ''
    for c in label:
        if not c.isdigit():
            if in_prefix:
                prefix += c
            else:
                current_suffix += c
        else:
            if in_prefix:
                in_prefix = False
            if current_suffix != '':
                components.append((current_number, current_suffix))
                current_number = current_suffix = ''
            current_number += c
    if not in_prefix and current_number != '':
        components.append((current_number, current_suffix))
    key = prefix
    for component in components:
        key += component[0].rjust(padding, '0') + component[1]
    return key


def view_show():
    """Toggle show render view

    """
    pass


def wrap_in_list(val, *append_these):
    """
    >>> wrap_in_list(1, 2)
    [1, 2]
    >>> wrap_in_list([1, 2], 3, 4)
    [1, 2, 3, 4]
    >>> wrap_in_list([1, 2], [3, 4])
    [1, 2, [3, 4]]
    """
    wrapped = val if isinstance(val, list) else [val]
    return wrapped + list(append_these)


def analyze_alignment(alignment, pdb_contact_idxs=[]):
    """Return scores describing the qualit of the alignment.

    Returns
    -------
    identity : float <= 1
        Core identity.
    coverage : float <= 1
        Core coverage.
    if_identity : float <= 1
        Interface identity.
    if_coverage : float <= 1
        Interface coverage.
    """
    pdb_aa_idx = -1
    sequence_1_length = 0
    sequence_1_identity = 0
    sequence_1_coverage = 0
    interface_1_identity = 0
    interface_1_coverage = 0
    for aa_1, aa_2 in zip(*alignment):
        is_interface = False
        if aa_1 == '-':
            continue
        sequence_1_length += 1
        if aa_2 == '-':
            continue
        pdb_aa_idx += 1
        if pdb_aa_idx in pdb_contact_idxs:
            is_interface = True
        sequence_1_coverage += 1
        if is_interface:
            interface_1_coverage += 1
        if aa_1 != aa_2:
            continue
        sequence_1_identity += 1
        if is_interface:
            interface_1_identity += 1
    identity = sequence_1_identity / float(sequence_1_length)
    coverage = sequence_1_coverage / float(sequence_1_length)
    assert identity <= 1
    assert coverage <= 1
    if pdb_contact_idxs:
        if_identity = sequence_1_identity / float(len(pdb_contact_idxs))
        if_coverage = interface_1_coverage / float(len(pdb_contact_idxs))
        assert if_identity <= 1
        assert if_coverage <= 1
    else:
        if_identity = None
        if_coverage = None
    return identity, coverage, if_identity, if_coverage


def not_none(value):
    """Sets a None value to "None" string"""
    return 'None' if value is None else str(value)


def generate_AES_key(bytes=32):
    """Generates a new AES key

    Parameters
    ----------
    bytes : int
        number of bytes in key

    Returns
    -------
    key : bytes
    """
    try:
        from Crypto import Random
        return Random.get_random_bytes(bytes)
    except ImportError:
        print('PyCrypto not install. Reading from /dev/random instead')
        with open('/dev/random', 'r') as rand:
            return rand.read(bytes)


@classmethod
def process(cls, *, context=None, parameter=None):
    """ Evaluate the MUL command. """
    lhs, rhs = context.stack.pop(), context.stack.pop()
    context.stack.append(lhs * rhs)


def convert_bytes_to_bit_str(byte_array):
    """Convert bytes to bits string for decoding purpose"""
    bin_format = '{0:08b}'
    bit_data = []
    for element in byte_array:
        data = bin_format.format(element)
        bit_data.append(data)
    return ''.join(bit_data)


@classmethod
def _get_msg_value(cls, msg, search_path, msg_id=None, **kwargs):
    """
        获取报文的内容（注意只获取第1个取到的节点值）

        @param {object} msg - 主报文对象（SimpleXml对象）
        @param {string} search_path - 需要获取值的搜索路径，符合xpath规范
        @param {string} msg_id=None - 报文id（用于标明该报文业务类型）
        @param {**kwargs} kwargs - 设置参数
            namespaces=None - 命名空间
                可传入值的示例如下：
                ns = {
                    'real_person': 'http://people.example.com',
                    'role': 'http://characters.example.com'
                }

        @returns {string} - 获取到的值

        @throws {NameError} - 对应标准错误码21002，当参数路径不存在时抛出

        """
    return msg.get_value(search_path, default=None, namespaces=None if
        'namespaces' not in kwargs.keys() else kwargs['namespaces'])


def provider_parser(subparser):
    """Configure provider parser for Namesilo"""
    subparser.add_argument('--auth-token', help=
        'specify key for authentication')


def get_numpy_include_path():
    """
    Gets the path to the numpy headers.
    """
    import builtins
    if hasattr(builtins, '__NUMPY_SETUP__'):
        del builtins.__NUMPY_SETUP__
    import imp
    import numpy
    imp.reload(numpy)
    try:
        numpy_include = numpy.get_include()
    except AttributeError:
        numpy_include = numpy.get_numpy_include()
    return numpy_include


def _index_if(collection, pred):
    """Find the index of the first item in a collection for which a predicate is true.

    Returns the index, or -1 if no such item exists.
    """
    for index, element in enumerate(collection):
        if pred(element):
            return index
    return -1


def series():
    """Return list of individual series to be reported on (think y)"""


def semanage_port_get_type(seport, port, proto):
    """ Get the SELinux type of the specified port.

    :param seport: Instance of seobject.portRecords

    :type port: str
    :param port: Port or port range (example: "8080", "8080-9090")

    :type proto: str
    :param proto: Protocol ('tcp' or 'udp')

    :rtype: tuple
    :return: Tuple containing the SELinux type and MLS/MCS level, or None if not found.
    """
    ports = port.split('-', 1)
    if len(ports) == 1:
        ports.extend(ports)
    key = int(ports[0]), int(ports[1]), proto
    records = seport.get_all()
    if key in records:
        return records[key]
    else:
        return None


def _get_session_auth_info(_helper_cfg):
    """This function parses session authentication information if found in the helper file.

    .. versionchanged:: 2.2.0
       Removed one of the preceding underscores in the function name
    """
    _session_auth = {}
    _session_info = ['username', 'password']
    for _key in _session_info:
        if _key in _helper_cfg['connection']['session_auth']:
            _session_auth[_key] = _helper_cfg['connection']['session_auth'][
                _key]
        else:
            _session_auth[_key] = None
    return _session_auth


@staticmethod
def _next_point(p, n):
    """
        Helper method that calculates next antipodal point
        :param p: previous point
        :param n: total number of points in a contour
        :return:
        """
    return p % n + 1


@classmethod
def _get_reserved_fieldnames(cls):
    """ Returns a list of fieldnames to hide when calling
            "to_view_dict" on view model

        :return:
        """
    return {'obj_type', 'doc_id', 'doc_ref'}


def check_marking(p, marking):
    """
    Tiny internal function that checks that ``marking`` is compatible with ``p``.

    OUTPUT:

        A 3-tuple.

    EXAMPLES::

        sage: import surface_dynamics.interval_exchanges.rauzy_class_cardinality as rcc
        sage: p = Partition([3,2,2])
        sage: rcc.check_marking(p, (1,3,1))
        (1, 3, 1)
        sage: rcc.check_marking(p, (1,3,2))
        (1, 3, 2)
        sage: rcc.check_marking(p, (1,3,3))
        Traceback (most recent call last):
        ...
        ValueError: marking[2] is not good
        sage: rcc.check_marking(p, (1,3,-1))
        Traceback (most recent call last):
        ...
        ValueError: marking[2] is not good
        sage: rcc.check_marking(p, (2,3,2))
        (2, 3, 2)
        sage: rcc.check_marking(p, (2,3,3))
        Traceback (most recent call last):
        ...
        ValueError: wrong marking type 2
    """
    if len(marking) != 3:
        raise ValueError('marking must be a 3-tuple (t,i,j)')
    if marking[0] == 1:
        if marking[1] not in p:
            raise ValueError('marking[1] not in p')
        if marking[2] < 0 or marking[2] > marking[1] - 1:
            raise ValueError('marking[2] is not good')
    elif marking[0] == 2:
        if marking[1] == marking[2]:
            if not p.to_exp()[marking[1] - 1] > 1:
                raise ValueError('wrong marking type 2')
        elif marking[1] not in p or marking[2] not in p:
            raise ValueError('marking not in p')
    else:
        raise ValueError('marking[0] must be 1 or 2')
    return tuple(marking)


def set_edge_attributes(G, values, name=None):
    """Sets edge attributes from a given value or dictionary of values.

    .. Warning:: The call order of arguments `values` and `name`
        switched between v1.x & v2.x.

    Parameters
    ----------
    G : NetworkX Graph

    values : scalar value, dict-like
        What the edge attribute should be set to.  If `values` is
        not a dictionary, then it is treated as a single attribute value
        that is then applied to every edge in `G`.  This means that if
        you provide a mutable object, like a list, updates to that object
        will be reflected in the edge attribute for each edge.  The attribute
        name will be `name`.

        If `values` is a dict or a dict of dict, it should be keyed
        by edge tuple to either an attribute value or a dict of attribute
        key/value pairs used to update the edge's attributes.
        For multigraphs, the edge tuples must be of the form ``(u, v, key)``,
        where `u` and `v` are nodes and `key` is the edge key.
        For non-multigraphs, the keys must be tuples of the form ``(u, v)``.

    name : string (optional, default=None)
        Name of the edge attribute to set if values is a scalar.

    Examples
    --------
    After computing some property of the edges of a graph, you may want
    to assign a edge attribute to store the value of that property for
    each edge::

        >>> G = nx.path_graph(3)
        >>> bb = nx.edge_betweenness_centrality(G, normalized=False)
        >>> nx.set_edge_attributes(G, bb, 'betweenness')
        >>> G.edges[1, 2]['betweenness']
        2.0

    If you provide a list as the second argument, updates to the list
    will be reflected in the edge attribute for each edge::

        >>> labels = []
        >>> nx.set_edge_attributes(G, labels, 'labels')
        >>> labels.append('foo')
        >>> G.edges[0, 1]['labels']
        ['foo']
        >>> G.edges[1, 2]['labels']
        ['foo']

    If you provide a dictionary of dictionaries as the second argument,
    the entire dictionary will be used to update edge attributes::

        >>> G = nx.path_graph(3)
        >>> attrs = {(0, 1): {'attr1': 20, 'attr2': 'nothing'},
        ...          (1, 2): {'attr2': 3}}
        >>> nx.set_edge_attributes(G, attrs)
        >>> G[0][1]['attr1']
        20
        >>> G[0][1]['attr2']
        'nothing'
        >>> G[1][2]['attr2']
        3

    """
    if name is not None:
        try:
            if G.is_multigraph():
                for (u, v, key), value in values.items():
                    try:
                        G[u][v][key][name] = value
                    except KeyError:
                        pass
            else:
                for (u, v), value in values.items():
                    try:
                        G[u][v][name] = value
                    except KeyError:
                        pass
        except AttributeError:
            for u, v, data in G.edges(data=True):
                data[name] = values
    elif G.is_multigraph():
        for (u, v, key), d in values.items():
            try:
                G[u][v][key].update(d)
            except KeyError:
                pass
    else:
        for (u, v), d in values.items():
            try:
                G[u][v].update(d)
            except KeyError:
                pass


@classmethod
def reset(cls):
    """Reset to default state."""
    return


def log1p(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise ``log(1 + x)`` value of the input.

    This function is more accurate than ``log(1 + x)``  for small ``x`` so that
    :math:`1+x\\approx 1`

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

       - log1p(default) = default
       - log1p(row_sparse) = row_sparse
       - log1p(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_logexp.cc:L206

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

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

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


def getServiceNamed(serviceName):
    """
        Retrieve the named service from this application.

        Raise a C{KeyError} if there is no such service name.
        """


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

    Mathematically this amounts to
    P_1 = x
    P_2 = 3/2 * P_1*P_1 - 1/2 .

    .. note::

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

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

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

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

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

    :returns: The index of the next element that will be computed in the
        recursion, the order of the next element, and the index of a special
        element. Is this case the first order Legendre polynomial of the
        current variable is the special element.
    :rtype: Tuple[int, int, int]
    """
    result[:, (pos)] = x[:, (cur_var)]
    result[:, (pos + 1)] = 3.0 / 2.0 * result[:, (pos)] * result[:, (pos)
        ] - 0.5
    return pos + 2, 3, pos


def get_doc():
    """Get documentation of this resource

    :return: rst string
    :rtype: str
    """
    return """
    The ``alignak_notifications`` model is a cache used internally by the backend to store the
    notifications that must be sent out to the Alignak arbiter.
    """


def disconnect(code, reason):
    """Return SockJS packet with code and close reason

    `code`
        Closing code
    `reason`
        Closing reason
    """
    return 'c[%d,"%s"]' % (code, reason)


def round(data=None, name=None, attr=None, out=None, **kwargs):
    """Returns element-wise rounded value to the nearest integer of the input.

    Example::

       round([-1.5, 1.5, -1.9, 1.9, 2.1]) = [-2.,  2., -2.,  2.,  2.]

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

      - round(default) = default
      - round(row_sparse) = row_sparse
      - round(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_basic.cc:L778

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

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

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


def capitalize(text):
    """
    Capitalize first non-whitespace character folling each period in string

    :param str text: text to capitalize
    :return: capitalized text
    :rtype: str
    """
    ret = list(text)
    i = 0
    while i < len(text) - 1 and text[i].isspace():
        i += 1
    if text[i].isalpha() and text[i].islower():
        ret[i] = ret[i].upper()
    p = 0
    while p < len(text) - 1:
        p = text.find('.', p)
        if p < 0:
            break
        p += 1
        w = p
        while w < len(text) - 1 and text[w].isspace():
            w += 1
        if text[w].isalpha() and text[w].islower():
            ret[w] = ret[w].upper()
    return ''.join(ret)


def bindprop(element_class, ogm_name, val, *, binding=None):
    """
    Helper function for binding ogm properties/values to corresponding db
    properties/values for traversals.

    :param goblin.element.Element element_class: User defined element class
    :param str ogm_name: Name of property as defined in the ogm
    :param val: The property value
    :param str binding: The binding for val (optional)

    :returns: tuple object ('db_property_name', ('binding(if passed)', val))
    """
    db_name = getattr(element_class, ogm_name, ogm_name)
    _, data_type = element_class.__mapping__.ogm_properties[ogm_name]
    val = data_type.to_db(val)
    if binding:
        val = binding, val
    return db_name, val


def is_dict(obj):
    """
        from edict.edict import *
        is_dict({1:2})
        is_dict(200)
    """
    if type(obj) == type({}):
        return True
    else:
        return False


def update_ml_model(MLModelId=None, MLModelName=None, ScoreThreshold=None):
    """
    Updates the MLModelName and the ScoreThreshold of an MLModel .
    You can use the GetMLModel operation to view the contents of the updated data element.
    See also: AWS API Documentation

    :example: response = client.update_ml_model(
        MLModelId='string',
        MLModelName='string',
        ScoreThreshold=...
    )

    :type MLModelId: string
    :param MLModelId: [REQUIRED]
            The ID assigned to the MLModel during creation.

    :type MLModelName: string
    :param MLModelName: A user-supplied name or description of the MLModel .

    :type ScoreThreshold: float
    :param ScoreThreshold: The ScoreThreshold used in binary classification MLModel that marks the boundary between a positive prediction and a negative prediction.
            Output values greater than or equal to the ScoreThreshold receive a positive result from the MLModel , such as true . Output values less than the ScoreThreshold receive a negative response from the MLModel , such as false .

    :rtype: dict
    :return: {
        'MLModelId': 'string'
    }

    """
    pass


@classmethod
def get_description(cls):
    """Friendly description for the API definition."""
    cls._assert_api_definition('DESCRIPTION')
    return cls.api_definition.DESCRIPTION


def simplify(units):
    """
    Cancel units that appear in both numerator and denominator, then attempt to replace
    groups of units with single units where possible (ie, J/s => W)
    """
    pass


@classmethod
def closed(cls, a, b):
    """
        Create a new closed Interval.

        :param float a: Left bound
        :param float b: Right bound
        """
    return cls((a, b), (True, True))


@classmethod
def sload(cls, filename):
    """
        Instantiate the detector description from a NeXus file, adapted from:
        http://download.nexusformat.org/sphinx/classes/base_classes/NXdetector.html

        :param filename: name of the file on the disk
        :return: Detector instance
        """
    obj = cls()
    cls.load(filename)
    return obj


def writeSamples(outfile1, outfile2, ncats, catsize, weird, weirdsize):
    """writes two files, differing only on the value of one category"""
    try:
        f = open(outfile1, 'w')
    except IOError:
        print('For some reason I cannot open ' + outfile1)
        print('Check directory permissions and/or file name')
        exit(-1)
    try:
        g = open(outfile2, 'w')
    except:
        print('For some reason I cannot open ' + outfile1)
        print('Check directory permissions and/or file name.')
        exit(-1)
    for i in range(ncats):
        f.write('cat_' + str(i) + '\t' + str(catsize) + '\n')
        g.write('cat_' + str(i) + '\t' + str(catsize) + '\n')
    f.write(weird + '\t0\n')
    g.write(weird + '\t' + str(weirdsize) + '\n')
    f.close()
    g.close()


@classmethod
def from_dict(cls, dictionary):
    """Creates a Vividict from a (possibly nested) python dict

        :param dict dictionary: Python dict to be converted to a Vividict
        :return: A Vividict with all key-values pairs from the given dict
        :rtype: Vividict
        """
    return cls(dictionary)


def format_time(t):
    """Format seconds into a human readable form.

    >>> format_time(10.4)
    '10.4s'
    >>> format_time(1000.4)
    '16min 40.4s'
    """
    m, s = divmod(t, 60)
    h, m = divmod(m, 60)
    if h:
        return '{0:2.0f}hr {1:2.0f}min {2:4.1f}s'.format(h, m, s)
    elif m:
        return '{0:2.0f}min {1:4.1f}s'.format(m, s)
    else:
        return '{0:4.1f}s'.format(s)


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

        :param SharedLinkSettingsAllowDownloadEnabledDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_settings_allow_download_enabled_details', val)


def _draw_circle(data, obj, draw_options):
    """Return the PGFPlots code for circles.
    """
    x, y = obj.center
    ff = data['float format']
    cont = ('\\draw[{}] (axis cs:' + ff + ',' + ff + ') circle (' + ff + ');\n'
        ).format(','.join(draw_options), x, y, obj.get_radius())
    return data, cont


def proc_default():
    """
    Default processor: return data in str/bytes, after strip
    :return: data
    """
    return lambda data: data.strip()


def translate_bbox(bbox, y_offset=0, x_offset=0):
    """Translate bounding boxes.

    This method is mainly used together with image transforms, such as padding
    and cropping, which translates the left top point of the image from
    coordinate :math:`(0, 0)` to coordinate
    :math:`(y, x) = (y\\_offset, x\\_offset)`.

    The bounding boxes are expected to be packed into a two dimensional
    tensor of shape :math:`(R, 4)`, where :math:`R` is the number of
    bounding boxes in the image. The second axis represents attributes of
    the bounding box. They are :math:`(y_{min}, x_{min}, y_{max}, x_{max})`,
    where the four attributes are coordinates of the top left and the
    bottom right vertices.

    Args:
        bbox (~numpy.ndarray): Bounding boxes to be transformed. The shape is
            :math:`(R, 4)`. :math:`R` is the number of bounding boxes.
        y_offset (int or float): The offset along y axis.
        x_offset (int or float): The offset along x axis.

    Returns:
        ~numpy.ndarray:
        Bounding boxes translated according to the given offsets.

    """
    out_bbox = bbox.copy()
    out_bbox[:, :2] += y_offset, x_offset
    out_bbox[:, 2:] += y_offset, x_offset
    return out_bbox


def list_object_parents(DirectoryArn=None, ObjectReference=None, NextToken=
    None, MaxResults=None, ConsistencyLevel=None):
    """
    Lists parent objects that are associated with a given object in pagination fashion.
    See also: AWS API Documentation

    :example: response = client.list_object_parents(
        DirectoryArn='string',
        ObjectReference={
            'Selector': 'string'
        },
        NextToken='string',
        MaxResults=123,
        ConsistencyLevel='SERIALIZABLE'|'EVENTUAL'
    )

    :type DirectoryArn: string
    :param DirectoryArn: [REQUIRED]
            The Amazon Resource Name (ARN) that is associated with the Directory where the object resides. For more information, see arns .

    :type ObjectReference: dict
    :param ObjectReference: [REQUIRED]
            The reference that identifies the object for which parent objects are being listed.
            Selector (string) --A path selector supports easy selection of an object by the parent/child links leading to it from the directory root. Use the link names from each parent/child link to construct the path. Path selectors start with a slash (/) and link names are separated by slashes. For more information about paths, see Accessing Objects . You can identify an object in one of the following ways:
            $ObjectIdentifier - An object identifier is an opaque string provided by Amazon Cloud Directory. When creating objects, the system will provide you with the identifier of the created object. An object s identifier is immutable and no two objects will ever share the same object identifier
            /some/path - Identifies the object based on path
            #SomeBatchReference - Identifies the object in a batch call

    :type NextToken: string
    :param NextToken: The pagination token.

    :type MaxResults: integer
    :param MaxResults: The maximum number of items to be retrieved in a single call. This is an approximate number.

    :type ConsistencyLevel: string
    :param ConsistencyLevel: Represents the manner and timing in which the successful write or update of an object is reflected in a subsequent read operation of that same object.

    :rtype: dict
    :return: {
        'Parents': {
            'string': 'string'
        },
        'NextToken': 'string'
    }

    :returns:
    (string) --
    (string) --

    """
    pass


def moveTo(target, new_name=None):
    """Move this object to the target given.

        Returns the new name within the target.
        """


def select_bookmark(dir: str=''):
    """Select a bookmarked directory

    :param dir: Dir
    :type dir: str
    """
    pass


def openForAppending():
    """
        Return a file object for appending.
        """


def join_summaries(*args):
    """
    Joins summaries. If summary value is not string, it will be ignored.

    :param str separator: Summary separator.
    :param list[str] args: List of summaries.
    :return: Joined strings.
    :rtype: str | None
    """
    summaries_strings = []
    """:type: list[str]"""
    for summary in args:
        if isinstance(summary, str) and len(summary) > 0:
            summaries_strings.append(summary)
    if len(summaries_strings) == 0:
        return None
    return ', '.join(summaries_strings)


@classmethod
def is_dask(cls):
    """
        This returns True if dask functions should be used
        """
    if cls.client is None:
        return False
    return cls.client.is_dask()


def get_style_fontsize(node):
    """Returns font size defined by this element.

    :Args:
      - node (:class:`ooxml.doc.Element`): Node element

    :Returns:
      Font size as int number or 0 if it is not defined

    """
    if hasattr(node, 'rpr'):
        if 'sz' in node.rpr:
            return int(node.rpr['sz']) / 2
    return 0


@classmethod
def seq_uid(cls, *args, **kwargs):
    """Set the id for this sequence, override to add other key.

    Mandatory keys: raw

    """
    return cls.__index_name__


def p_global_param_str(p):
    """ global_param_str : ABANDON_LEASE_TIME
                         | ADAPTIVE_LEASE_TIME_THRESHOLD
                         | DDNS_DOMAINNAME
                         | DDNS_REV_DOMAINNAME
                         | DEFAULT_LEASE_TIME
                         | DELAYED_ACK
                         | MAX_ACK_DELAYED
                         | DYNAMIC_BOOTP_LEASE_CUTOFF
                         | DYNAMIC_BOOTP_LEASE_LENGTH
                         | FILENAME
                         | LEASE_FILE_NAME
                         | LIMIT_ADDRS_PER_IA
                         | DHCPV6_LEASE_FILE_NAME
                         | LOCAL_PORT
                         | LOCAL_ADDRESS
                         | LOG_FACILITY
                         | MAX_LEASE_TIME
                         | MIN_LEASE_TIME
                         | MIN_SECS
                         | NEXT_SERVER
                         | OMAPI_PORT
                         | PID_FILE_NAME
                         | DHCPV6_PID_FILE_NAME
                         | PING_TIMEOUT
                         | PREFERRED_LIFETIME
                         | REMOTE_PORT
                         | SERVER_IDENTIFIER
                         | SERVER_DUID
                         | SERVER_NAME
                         | SITE_OPTION_SPACE
                         | VENDOR_OPTION_SPACE
    """
    p[0] = p[1]


def _build_diagram(module, builder, drawer, tree, type, code, fontmap=None,
    antialias=True, nodoctype=False, transparency=False, size=None):
    """
    Inspired from :epkg:`blockdiag` source file (*_bootstrap.py*).
    """
    ScreenNodeBuilder = builder.ScreenNodeBuilder
    diagram = ScreenNodeBuilder.build(tree, None)
    DiagramDraw = drawer.DiagramDraw
    drawer = DiagramDraw(type, diagram, fontmap=fontmap, code=code,
        antialias=antialias, nodoctype=nodoctype, transparency=transparency)
    drawer.draw()
    if size:
        return drawer.save(size=size)
    else:
        return drawer.save()


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 buildZooKeeperHosts(host_list):
    """
    Build the ZK cluster host list for client connections.

    :param list host_list: A list of
        :py:class:`~nodepool.zk.ZooKeeperConnectionConfig` objects (one
        per server) defining the ZooKeeper cluster servers.
    """
    if not isinstance(host_list, list):
        raise Exception("'host_list' must be a list")
    hosts = []
    for host_def in host_list:
        host = '%s:%s%s' % (host_def.host, host_def.port, host_def.chroot)
        hosts.append(host)
    return ','.join(hosts)


@classmethod
def deserialize_insert(cls, document: dict):
    """
        Update this document values to values that can be inserted in Mongo.
        Remove entries for unknown fields.
        Convert dot notation fields to corresponding dictionary as dot notation is not allowed on insert.

        :param document: Document that should be inserted.
        Each entry if composed of a field name associated to a value.
        """
    cls._remove_dot_notation(document)
    for field in cls.__fields__:
        field.deserialize_insert(document)
        if field.should_auto_increment:
            document[field.name] = cls._increment(*field.get_counter(document))


def get_request(request_id, request_type):
    """Get the data associated with the request id, or None.

        :param request_id: The unique id for the request.
        :type request_id: int
        :param request_type: Optional request type that the requested id must
            match, otherwise no match is returned.
        :type request_type: `RequestType`
        :return: A 2-tuple of the key and data originally held, or None if the
            `request_id` is not in the database.
        """


def clearOutputs(cell):
    """
    Replace list of outputs with an empty one.
    """
    cell['outputs'] = []


def set_title(title):
    """Change the title of the content object if possible.
        """


def parse_s2bs(s2bs):
    """
    convert s2b files to dictionary
    """
    s2b = {}
    for s in s2bs:
        for line in open(s):
            line = line.strip().split('\t')
            s, b = line[0], line[1]
            s2b[s] = b
    return s2b


def release_vcf_path(data_type: str, version: str, contig: str) ->str:
    """
    Publically released VCF. Provide specific contig, i.e. "20", to retrieve contig
    specific VCF

    :param data_type: One of "exomes" or "genomes"
    :param version: One of the release versions of gnomAD on GRCh37
    :param contig: Single contig "1" to "Y"
    :return: Path to VCF
    """
    contig = f'.{contig}' if contig else ''
    return (
        f'gs://gnomad-public/release/{version}/vcf/{data_type}/gnomad.{data_type}.r{version}.sites{contig}.vcf.bgz'
        )


def _valid_hull(geoms, points):
    """
    Sanity check within ``alpha_shape_auto()`` to verify the generated
    alpha shape actually contains the original set of points (xys).

    Parameters
    ----------

    geoms   : GeoSeries
              see alpha_geoms()
    points  : list
              xys parameter cast as shapely.geometry.Point objects

    Returns
    -------

    flag    : bool
              Valid hull for alpha shape [True] or not [False]

    """
    flag = True
    if geoms.shape[0] != 1:
        flag = False
    for point in points:
        if not point.intersects(geoms[0]):
            flag = False
    return flag


def get_tables():
    """
    Returns hardcoded list of tables which have ``tenant_id`` column.

    The list is hardcoded to match the state of the schema when this
    upgrade script is run.
    """
    tables = ['firewalls', 'firewall_policies', 'firewall_rules']
    return tables


@staticmethod
def getNonInstallableProducts():
    """Hide in the add-ons configlet."""
    return [u'archetypes.querywidget', u'brasil.gov.portal.upgrades.v10900',
        u'brasil.gov.portal.upgrades.v10901',
        u'brasil.gov.portal.upgrades.v10902',
        u'brasil.gov.portal.upgrades.v10903',
        u'brasil.gov.portal.upgrades.v10904',
        u'brasil.gov.portal.upgrades.v10905',
        u'brasil.gov.tiles.upgrades.v2000', u'brasil.gov.vcge.at',
        u'brasil.gov.vcge.dx', u'brasil.gov.vcge.upgrades.v2000',
        u'collective.googleanalytics', u'collective.js.cycle2',
        u'collective.js.galleria', u'collective.js.jqueryui',
        u'collective.upload', u'collective.z3cform.datagridfield',
        u'collective.z3cform.datetimewidget', u'ftw.upgrade',
        u'plone.app.blocks', u'plone.app.collection',
        u'plone.app.contenttypes', u'plone.app.dexterity',
        u'plone.app.drafts', u'plone.app.event', u'plone.app.event.at',
        u'plone.app.intid', u'plone.app.iterate', u'plone.app.jquery',
        u'plone.app.jquerytools', u'plone.app.querystring',
        u'plone.app.relationfield', u'plone.app.theming',
        u'plone.app.tiles', u'plone.app.versioningbehavior',
        u'plone.formwidget.autocomplete', u'plone.formwidget.contenttree',
        u'plone.formwidget.datetime', u'plone.formwidget.querystring',
        u'plone.formwidget.recurrence', u'plone.resource', u'plone.session',
        u'plonetheme.classic', u'Products.Doormat',
        u'Products.PloneFormGen', u'raptus.autocompletewidget']


@classmethod
def select_labelled(cls, label):
    """Returns an XPath to find an HTML <select> referred to by a <label> that contains the text in `label`."""
    return cls(
        '//select[@id=//label[normalize-space(node())=normalize-space("%s")]/@for]'
         % label)


def csv_list(l):
    """Format list to a string with comma-separated values.
    """
    if len(l) == 0:
        return ''
    return ', '.join(map(str, l))


def get_default_values(number_of_bands, values):
    """Return values for bands

    Utility function to get values (e.g., nodata) for bands.

    For n = number_of_bands:
    - If values is a single value, transform it into a list with n elements
    - If values is a list with size lower than n, extend the list to size n by repeating the last value (n=4, values=[1, 2], result=[1, 2, 2, 2]
    - If values is a list with size greater than n, slice values to values[:n]

    :param number_of_bands: number of bands
    :type number_of_bands: int
    :param values: value or list of values
    :type values: same as raster type
    :return: values
    :rtype: same as input values
    """
    try:
        if number_of_bands < len(values):
            values = values[:number_of_bands]
        elif number_of_bands > len(values):
            values = values[-1] * (number_of_bands - len(values))
    except TypeError:
        values = [values] * number_of_bands
    except:
        raise
    return values


def check_transforms(fw, bw, symbs):
    """ Verify validity of a pair of forward and backward transformations

    Parameters
    ----------
    fw: expression
        forward transformation
    bw: expression
        backward transformation
    symbs: iterable of symbols
        the variables that are transformed
    """
    for f, b, y in zip(fw, bw, symbs):
        if f.subs(y, b) - y != 0:
            raise ValueError('Incorrect (did you set real=True?) fw: %s' %
                str(f))
        if b.subs(y, f) - y != 0:
            raise ValueError('Incorrect (did you set real=True?) bw: %s' %
                str(b))


def SI(val):
    """SecondarySourceID"""
    return val


def algum(sequência):
    """
    Retorna Verdadeiro se algum dos objetos da sequência dada for
    verdadeiro e Falso caso contrário.

    Examples
    --------

    >>> algum([Verdadeiro, Verdadeiro])  # doctest: +SKIP
    Verdadeiro
    >>> algum([Verdadeiro, Falso])       # doctest: +SKIP
    Falso
    """
    return any(sequência)


def page_has_tag(page, tag):
    """
    Check if a Page object is associated with the given tag.

    :param page: a Page instance
    :param tag: a Tag instance or a slug string.

    :return: whether the Page instance has the given tag attached (False if no Page or no
             attached PageTags exists)
    :type: Boolean
    """
    from .models import PageTags
    if hasattr(tag, 'slug'):
        slug = tag.slug
    else:
        slug = tag
    try:
        return page.pagetags.tags.filter(slug=slug).exists()
    except PageTags.DoesNotExist:
        return False


def package_root(varmap):
    """Return correct directory for the root package.

    The "root" package is the one where modules which do not
    belong to a package are located (see the distutils docs).
    This function should not need to be called directly in
    your actual setup script, but it can be useful for testing.
    Note that it looks for a ``package_root`` setup var, which
    can be used as a shortcut if your "root" package is not in
    the standard place (which is your setup script directory),
    rather than having to declare a ``package_dir`` dictionary
    with a ``''`` key.
    """
    try:
        return varmap['package_dir']['']
    except KeyError:
        try:
            result = varmap['package_root']
        except KeyError:
            return '.'
        else:
            dirmap = varmap.setdefault('package_dir', {})
            if '' not in dirmap:
                dirmap[''] = result
            return result


def write(output):
    """Write XML representation to the file-like object output
        """


def generate_target_states_list(sweep, initial_state_labels):
    """Based on a bare state label (i1, i2, ...)  with i1 being the excitation level of subsystem 1, i2 the
    excitation level of subsystem 2 etc., generate a list of new bare state labels. These bare state labels
    correspond to target states reached from the given initial one by single-photon qubit transitions. These
    are transitions where one of the qubit excitation levels increases at a time. There are no changes in
    oscillator photon numbers.

    Parameters
    ----------
    sweep: ParameterSweep
    initial_state_labels: tuple(int1, int2, ...)
        bare-state labels of the initial state whose energy is supposed to be subtracted from the spectral data

    Returns
    -------
    list of tuple"""
    target_states_list = []
    for subsys_index, qbt_subsys in sweep.qbt_subsys_list:
        initial_qbt_state = initial_state_labels[subsys_index]
        for state_label in range(initial_qbt_state + 1, qbt_subsys.
            truncated_dim):
            target_labels = list(initial_state_labels)
            target_labels[subsys_index] = state_label
            target_states_list.append(tuple(target_labels))
    return target_states_list


def trim_leading_lines(lines):
    """
    Trim leading blank lines.
    """
    lines = list(lines)
    while lines and not lines[0]:
        lines.pop(0)
    return lines


def getColspan(item):
    """Colspan value based on the given item."""


def container_absent(api, container):
    """
    Ensure a container is absent.

    Container is an :class:`~lxdapi.api.APIResult` for the container, to be
    able to compare the configuration with.

    It is expected that the user manages the HTTP transactions, here's an
    example usage::

        container_absent(api, container_get('yourcontainer'))
    """
    if not container:
        return False
    if container.metadata['status'] == 'Running':
        api.put('containers/%s/state' % container.metadata['name'], json=
            dict(action='stop', timeout=api.default_timeout)).wait()
    api.delete('containers/%s' % container.metadata['name']).wait()
    return True


@classmethod
def get_table_names(cls, inspector, schema):
    """Need to consider foreign tables for PostgreSQL"""
    tables = inspector.get_table_names(schema)
    tables.extend(inspector.get_foreign_table_names(schema))
    return sorted(tables)


def get_target_ns(xml_tree):
    """Extract the target namespace for the XML doc.

    Returns:
        str: Extracted from the `targetNamespace` attribute of the root element.

        If the root element does not have a `targetNamespace` attribute, return an empty
        string, "".

     Examples:

         <xs:schema
             targetNamespace="http://www.w3.org/XML/1998/namespace"
             xmlns:xs="http://www.w3.org/2001/XMLSchema">

         -> http://www.w3.org/XML/1998/namespace

    """
    ns_list = xml_tree.xpath('/*/@targetNamespace')
    if len(ns_list):
        return ns_list[0]
    return ''


@classmethod
def clear(cls):
    """
        clear start and end timer_start
        """
    cls.timer_start.clear()
    cls.timer_end.clear()


@staticmethod
def parse_limits(limits):
    """
        Ignore a limits string--simply doesn't apply for the limit
        proxy.

        @return: Empty list.
        """
    return []


def _root_block(block):
    """
    Looks up the root of the stack of blocks containing the given ``block``.

    Example
    -------

    Parameters
    ----------
    block : Block
        The block of interest for which the root block will be obtained.

    Returns
    -------
    Block
        The block at the root of the block stack containing ``block``.
    """
    if not block:
        return block
    while block.logical_parent:
        block = block.logical_parent
    return block


def file_check(file):
    """
    Check a sample if it is supported on the SNDBOX enviroment
    Input:
    File - string name of File
    output:
    Boolen - True/False
    """
    supported_files = ['.raw', '.doc', '.dot', '.xls', '.csv', '.xlt',
        '.xlm', '.ppt', '.pot', '.pps', '.docx', '.docm', '.dotx', '.dotm',
        '.dotm', '.xlsx', '.xlsm', '.xltx', '.xltm', '.xlsb', '.xla',
        '.xlam', '.iqy', '.pptx', '.pptm', '.potx', '.ppsx', '.xml',
        '.pe32', '.rtf', '.pdf', '.vbs', '.vbe', '.ps1', '.js', '.lnk',
        '.html', '.bat', '.zip']
    supported_sample = False
    while supported_sample == False:
        if '.' not in file:
            supported_sample = True
            return True
        else:
            for file_ext in supported_files:
                if file_ext in file:
                    supported_sample = True
                    return True
                else:
                    return False


def _exhange(obj, key):
    """Exchange provided key for mapped version"""
    if hasattr(obj, 'attribute_map'):
        for k, v in obj.attribute_map.items():
            if v == key:
                return k
    return None


@classmethod
def normalize_email(cls, email):
    """
        Normalize the address by lowercasing the domain part of the email
        address.
        """
    email = email or ''
    try:
        email_name, domain_part = email.strip().rsplit('@', 1)
    except ValueError:
        pass
    else:
        email = '@'.join([email_name, domain_part.lower()])
    return email


def enn_ayy(quant):
    """
    Cheeky way to put a N/A placeholder for a string.

    :param quant: What to check if it's None.
    :type quant: str
    """
    return 'N/A' if quant is None else quant


def generate_presigned_url(ClientMethod=None, Params=None, ExpiresIn=None,
    HttpMethod=None):
    """
    Generate a presigned url given a client, its method, and arguments

    :type ClientMethod: string
    :param ClientMethod: The client method to presign for

    :type Params: dict
    :param Params: The parameters normally passed to
            ClientMethod.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned url is valid
            for. By default it expires in an hour (3600 seconds)

    :type HttpMethod: string
    :param HttpMethod: The http method to use on the generated url. By
            default, the http method is whatever is used in the method's model.

    """
    pass


@classmethod
def get_exchange_correlation_energy(cls, calc, **kwargs):
    """Return exchange correlation (XC) energy in eV."""
    return cls._get_pw_energy_value(calc, 'energy_xc')


def _and(queries):
    """
    Returns a query item matching the "and" of all query items.

    Args:
        queries (List[str]): A list of query terms to and.

    Returns:
        The query string.

    """
    if len(queries) == 1:
        return queries[0]
    return f"({' '.join(queries)})"


def unhandled_pragma(name, filename, lineno):
    """ Emit a warning for an unhandled pragma.

    Parameters
    ----------
    name : str
        The name of the unhandled pragma.

    filename : str
        The name of the file with the unhandled pragma.

    lineno : int
        The line number of the unhandled pragma.

    """
    import warnings
    msg = "unhandled pragma '%s'" % name
    warnings.warn_explicit(msg, SyntaxWarning, filename, lineno)


@staticmethod
def basic(instance, attrname, value, **_):
    """
        Sets the value on the instance using `setattr()`
        :param instance: instance to store the value on
        :param attrname: name of the attribute to store the value with
        :param value: value to store for the instance
        """
    setattr(instance, attrname, value)


def _diff_dow(dow1, dow2):
    """
    How many days we need to add to week day dow2 to reach dow1.
    For example, if dow2 is Monday and dow1 is Sunday, the result is 6.
    Monday is 1, Sunday is 7.
    """
    result = dow1 - dow2
    if result < 0:
        result = 7 + result
    return result


def coded_to_actual(coded_data, actual_lows, actual_highs):
    """Converts a pandas DataFrame from coded units to actuals.

    :param coded_data: A pandas.Dataframe that contains the runs to convert.
    :param actual_lows: A dictionary mapping factor names to factor lows.
    :param actual_highs: A dictionary mapping factor names to factor highs.
    :returns: A pandas.DataFrame containing factor settings in actual values.
	"""
    actual_data = coded_data.copy()
    for col in actual_data.columns:
        if not (col in actual_highs and col in actual_lows):
            continue
        try:
            actual_data[col] *= 0.5 * (float(actual_highs[col]) - float(
                actual_lows[col]))
            actual_data[col] += 0.5 * (actual_highs[col] + actual_lows[col])
        except ValueError:
            actual_data[col] = actual_data[col].map({(-1): actual_lows[col],
                (1): actual_highs[col]})
    return actual_data


def _encode_v2(value):
    """
    Encode all ':' substrings in a string (also encodes '$' so that it can
    be used to mark encoded characters). This way we can use :: to separate
    the two halves of an aside key.
    """
    simple = value.replace('$', '$$').replace(':', '$:')
    return simple


def _get_params(func, *args, **kwargs):
    """Turn an argument list into a dictionary.

    :arg function func: A function.
    :arg list *args: Positional arguments of `func`.
    :arg dict **kwargs: Keyword arguments of `func`.

    :returns dict: Dictionary representation of `args` and `kwargs`.
    """
    params = dict(zip(func.func_code.co_varnames[:len(args)], args))
    if func.func_defaults:
        params.update(dict(zip(func.func_code.co_varnames[-len(func.
            func_defaults):], func.func_defaults)))
    params.update(kwargs)
    return params


def convert_energy(Energy, Input_unit, Output_unit):
    """Description: ocnverts energy from Input_unit to Output_unit.
    Input  :- Energy to be converted
    		- Input unit. Can be:
    		'erg'   - ergs
    		'J'     - Jouls
    		'Hz'    - Frequency [1/s]
    		'A','Ang'- Wavelength [Ang]
    		'cm'    - Wavelength [cm]
    		'nm'    - Wavelength [nm]
    		'm'     - Wavelength [m]
    		'eV'    - Electron volts [h nu/q]
    		'keV'   - kilo Electron volts [h nu/q]
    		'MeV'   - Mega Electron volts [h nu/q]
    		'GeV'   - Giga Electron volts [h nu/q]
    		'T'     - Temperature [K]
    		'me'    - Electron mass [E/m_e]
    		'mp'    - Proton mass [E/m_p]
    		'cal'   - calorie (4.184 J)
    		'Btu'   - (1.055x10^3 J)
    		'kWh'   - kilowatt-hour (3.6x10^6 J)
    		'TNT'   - one ton of TNT (4.2x10^9 J)
    		'gr'    - Energy equivalent of 1 gram of matter (9x10^13 J)
    		- requested output unit. One of the above.
    Output :- Energy in output system
     Tested : ?
         By : Maayane T. Soumagnac Nov 2016
        URL :
     Example:
     Reliable:  """
    Erg2Erg = 1.0
    Erg2J = 1e-07
    Erg2eV = 624150000000.0
    Erg2T = 7243000000000000.0
    Erg2me = 1221400.0
    Erg2mp = 665.214577
    Erg2cal = Erg2J / 4.184
    Erg2Btu = Erg2J / 1055.0
    Erg2kWh = Erg2J / 3600000.0
    Erg2TNT = Erg2J / 4200000000.0
    relation = 'inv'
    if Input_unit.lower() == 'erg':
        ConvFactor = Erg2Erg
    elif Input_unit.lower() == 'j':
        ConvFactor = Erg2J
    elif Input_unit.lower() == 'ev':
        ConvFactor = Erg2eV
    elif Input_unit.lower() == 't':
        ConvFactor = Erg2T
    """
    elif Input_unit.lower()=='cm':
        relation='inv'
        ConvFactor=Erg2A*1e-8
    elif Input_unit.lower()=='nm':
        relation='inv'
        ConvFactor=Erg2A*1e-4
    #elif Input_unit.lower()=='m':
    #    relation='inv'
    #    ConvFactor=Erg2A*1e-10
    elif Input_unit.lower()=='ev':
        ConvFactor = Erg2eV
    elif Input_unit.lower()=='kev':
        ConvFactor = Erg2eV*1e-3
    elif Input_unit.lower()=='mev':
        ConvFactor = Erg2eV*1e-6
    elif Input_unit.lower()=='gev':
        ConvFactor = Erg2eV* 1e-9
    #elif Input_unit.lower()=='t':
    #    ConvFactor = Erg2T
    elif Input_unit.lower()=='me':
        ConvFactor = Erg2me
    elif Input_unit.lower()=='mp':
        ConvFactor = Erg2mp
    elif Input_unit.lower()=='cal':
        ConvFactor = Erg2cal
    elif Input_unit.lower()=='btu':
        ConvFactor = Erg2Btu
    elif Input_unit.lower()=='kwh':
        ConvFactor = Erg2kWh
    elif Input_unit.lower()=='tnt':
        ConvFactor = Erg2TNT
    #elif Input_unit =='gr':
    #    ConvFactor = Erg2gr
    else: print 'error: unknown InUnit option'
    """
    if relation == 'lin':
        ErgE = Energy * ConvFactor
    elif relation == 'inv':
        ErgE = Energy / ConvFactor
    else:
        print('unknown relation')
    relation = 'lin'
    if Output_unit.lower() == 'erg':
        ConvFactor = Erg2Erg
    elif Output_unit.lower() == 'j':
        ConvFactor = Erg2J
    elif Output_unit.lower() == 'ev':
        ConvFactor = Erg2eV
    elif Output_unit.lower() == 't':
        ConvFactor = Erg2T
    """

    elif Output_unit.lower()== 'kev':
        ConvFactor = Erg2eV*1e-3
    elif Output_unit.lower()== 'mev':
        ConvFactor = Erg2eV*1e-6
    elif Output_unit.lower()== 'gev':
        ConvFactor = Erg2eV*1e-9
    elif Output_unit.lower()== 'me':
        ConvFactor = Erg2me
    elif Output_unit.lower()== 'mp':
        ConvFactor = Erg2mp
    elif Output_unit.lower()== 'cal':
        ConvFactor = Erg2cal
    elif Output_unit.lower()== 'btu':
        ConvFactor = Erg2Btu
    elif Output_unit.lower()== 'kwh':
        ConvFactor = Erg2kWh
    elif Output_unit.lower()== 'tnt':
        ConvFactor = Erg2TNT
    #elif Output_unit.lower()== 'gr':
    #    ConvFactor = Erg2gr
    else: print 'Unknown InUnit Option'
"""
    if relation == 'lin':
        new_energy = ErgE * ConvFactor
    elif relation == 'inv':
        new_energy = ErgE / ConvFactor
    else:
        print('unknown relation')
    return new_energy


def plural(n, if_single, if_plural, *, add_n=True):
    """
	Return a string or another, depending on a number.

	Parameters
	----------
	n : int
		The number to test.

	if_single : str
		The string to return if `n` is lower or equal than 1.

	if_plural : str
		The string to return if `n` is greater than 1.

	add_n : bool
		`True` to prepend the string by the number, `False` to only get the string.

	Returns
	-------
	s : str
		The single or plural string, depending on the test.
	"""
    s = if_plural if n > 1 else if_single
    if add_n:
        s = f'{n} {s}'
    return s


@classmethod
def tokenize_with_lookahead(cls, tokenizer, input_str):
    """
        Yields (token, lookahead) one by one.
        Lookahead is None for the last token.
        """
    prev_token = None
    current_token = None
    for current_token in tokenizer(input_str):
        if prev_token is not None:
            yield prev_token, current_token
        prev_token = current_token
    if current_token is not None:
        yield current_token, None


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 _find_next_joint(root, current_link, next_joint_name):
    """
    Find the next joint in the URDF tree

    Parameters
    ----------
    root
    current_link: xml.etree.ElementTree
        The current URDF link
    next_joint_name: str
        Optional : The name of the next joint. If not provided, find it automatically as the first child of the link.
    """
    has_next = False
    next_joint = None
    search_by_name = True
    current_link_name = None
    if next_joint_name is None:
        search_by_name = False
        current_link_name = current_link.attrib['name']
    for joint in root.findall('joint'):
        if joint is not None:
            if search_by_name:
                if joint.attrib['name'] == next_joint_name:
                    has_next = True
                    next_joint = joint
            elif joint.find('parent').attrib['link'] == current_link_name:
                has_next = True
                next_joint = joint
                break
    return has_next, next_joint


def _INCPERIOD(x, p=1):
    """
    Forces an increase `p` in the minperiod of object `x`.

    Example: `ta-lib` calculates `+DM` a period of 1 too early, but calculates
    the depending `+DI` from the right starting point. Increasing the period,
    without changing the underlying already calculated `+DM` values, allows the
    `+DI` values to be right
    """
    x._minperiod += p


def assert_list_data(value: list) ->None:
    """Asserts value is list type."""
    assert isinstance(value, list
        ), f'Input value type must be a list. Actual type: {type(value)}, value: {value}'


@staticmethod
def round(val, digit: int=0):
    """Round specified digit of the val.

        Parameters
        ----------
        val : int
            An int value.
        digit : int, default 0
            The digit to be rounded at.

        Returns
        -------
        float
            Rounded value.

        """
    p = 10 ** digit
    return (val * p * 2 + 1) // 2 / p


def correct_label(df):
    """Label이 잘못된 부분을 수정하는 함수
    Args:
        - df : Dataframe [내용, 평가]
    Return:
        - df : Label이 수정된 DataFrame"""
    correct_label_dict = {'긍정': '옹호', '긍정/보도자료': '옹호', '보도자료.옹호': '옹호',
        '중입': '중립', ' 중립': '중립', '옹호 ': '옹호', '증립': '중립', '주읿': '중립', '중힙':
        '중립', '옹로': '옹호', '엉호': '옹호', '중랍': '중립', '융호': '옹호', '부부정': '부정',
        '옹ㅎ': '옹호', '부정 ': '부정', '웅호': '옹호', '올호': '옹호', '중립ㅂ': '중립', '부넝':
        '부정', '옹호옹호': '옹호', ' 부정': '부정', '부정정': '부정', '온호': '옹호', '즁립':
        '중립', '부덩': '부정', '부저ㅏㅇ': '부정', '옹ㅇ호': '옹호', '뷰종': '부정', '증ㄹ;ㅂ':
        '중립', 'ㅈ우': '중립', '중리': '중립', '엉허': '옹호', '붱': '부정', '오옿': '옹호',
        '중': '중립', '즁랍': '중립', '즁': '중립', '증': '중립', '중ㅂ': '중립', '부': '부정',
        '부저': '부정', '부장': '부정'}
    df['평가'] = df['평가'].replace(correct_label_dict)
    df = df.query("(평가 == '옹호') | (평가 == '부정') | (평가 == '중립')")
    return df


def splint(xa, ya, y2a, n, x, y):
    """
/*      CALCULATE CUBIC SPLINE INTERP VALUE
 *       ADAPTED FROM NUMERICAL RECIPES BY PRESS ET AL.
 *       XA,YA: ARRAYS OF TABULATED FUNCTION IN ASCENDING ORDER BY X
 *       Y2A: ARRAY OF SECOND DERIVATIVES
 *       N: SIZE OF ARRAYS XA,YA,Y2A
 *       X: ABSCISSA FOR INTERPOLATION
 *       Y: OUTPUT VALUE
 */
 """
    klo = 0
    khi = n - 1
    while khi - klo > 1:
        k = int((khi + klo) / 2)
        if xa[k] > x:
            khi = k
        else:
            klo = k
    h = xa[khi] - xa[klo]
    a = (xa[khi] - x) / h
    b = (x - xa[klo]) / h
    yi = a * ya[klo] + b * ya[khi] + ((a * a * a - a) * y2a[klo] + (b * b *
        b - b) * y2a[khi]) * h * h / 6.0
    y[0] = yi
    return


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

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

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


def retuple(p):
    """ convert point str back to tuple if necessary """
    if isinstance(p, tuple):
        return p
    elif isinstance(p, str):
        return tuple(p.split(','))


@classmethod
def fromdescriptor(cls, desc):
    """
        Create a :class:`~manticore.core.workspace.Store` instance depending on the descriptor.

        Valid descriptors:
          * fs:<path>
          * redis:<hostname>:<port>
          * mem:

        :param str desc: Store descriptor
        :return: Store instance
        """
    type_, uri = ('fs', None) if desc is None else desc.split(':', 1)
    for subclass in cls.__subclasses__():
        if subclass.store_type == type_:
            return subclass(uri)
    raise NotImplementedError(f"Storage type '{type_}' not supported.")


@classmethod
def SupportsPlugins(cls):
    """Determines if a parser supports plugins.

    Returns:
      bool: True if the parser supports plugins.
    """
    return cls._plugin_classes is not None


def psi_K_Na_SO4_PK74(T, P):
    """c-c'-a: potassium sodium sulfate [PK74]."""
    psi = -0.01
    valid = T == 298.15
    return psi, valid


def time_to_phase(time, period):
    """
    Convert time to phase.

    Parameters
    ----------
    time : ndarray
        An array which represents a time vector.
    period : float
        A value of period which phases the light curve with.

    Returns
    -------
    phase
        A phase vector.
    """
    time_min = time.min()
    time = time - time_min
    phase = time / period - time // period
    return phase


def _extract_columns(name, cube):
    """
    Workaround to extract data from a cube and create a dataframe
    following SOS boilerplate.

    """
    try:
        from HTMLParser import HTMLParser
    except ImportError:
        from html.parser import HTMLParser
    station = cube.attributes.get('abstract', None)
    if not station:
        station = name.replace('.', '_')
    parser = HTMLParser()
    station = parser.unescape(station)
    sensor = 'NA'
    lon = cube.coord(axis='X').points[0]
    lat = cube.coord(axis='Y').points[0]
    time = cube.coord(axis='T')
    time = time.units.num2date(cube.coord(axis='T').points)[0]
    date_time = time.strftime('%Y-%M-%dT%H:%M:%SZ')
    data = cube.data.mean()
    return station, sensor, lat, lon, date_time, data


def refresh_pyconstraints():
    """Refresh all pyconstraints

    """
    pass


def Kronecker(i, j):
    """Kronecker delta function.

    i : int
        First index of Kronecker delta.
    j : int
        Second index of Kronecker delta.

    Returns
    -------
    Kronecker delta : int
    """
    if i == j:
        return 1
    else:
        return 0


def next_player(player):
    """
    Returns the player that plays after the specified player.

    :param int player: player for which to calculate the
                       next player. Must be 0, 1, 2, or 3.
    :return: the next player
    """
    return (player + 1) % 4


def addeppykeys(idfmunch):
    """adds eppykeys needed by eppy3000"""
    for key, val in idfmunch.items():
        for key1, val1 in val.items():
            val1['eppykey'] = key
            val1['eppyname'] = key1


@staticmethod
def _suffix_for(req):
    """
        For a requirement, return the 'extras_require' suffix for
        that requirement.
        """
    return ':' + str(req.marker) if req.marker else ''


def obj_to_dic(obj):
    """
    将 obj 对象的属性封装成 dict
    :param obj: [obj]
    :return:
    """
    res = dict(obj.__dict__)
    res.pop('_sa_instance_state', None)
    return res


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

        :param SharingChangeLinkPolicyType val:
        :rtype: EventType
        """
    return cls('sharing_change_link_policy', val)


@classmethod
def instance(cls):
    """Return a reference to the singleton instance, or ``None`` if one
        does not exist.
        """
    return getattr(cls, '_{}_singleton'.format(cls.__name__), None)


def considered_immutable_error(clb_state, lb_id):
    """
    Return the error seen whenever the load balancer is not in an ACTIVE state,
    in which case it is immutable.  Any modifications to the load balancer
    (adding nodes, deleting nodes, changing nodes) will result in this
    message.

    Not sure if this message is applicable when deleting the load balancer.

    :param str clb_state: The states in which the CLB is considered immutable.
        The state should be one of (PENDING_DELETE, PENDING_UPDATE, ERROR).
        This state gets incorporated into the message.
    :param str lb_id: The load balancer ID, which gets incorporated into the
        message.

    :return: a `tuple` of (dict body message, 422 http status code)
    """
    return {'message':
        "Load Balancer '{0}' has a status of '{1}' and is considered immutable."
        .format(lb_id, clb_state), 'code': 422}, 422


def calculate_alternator_current(alternator_status, on_engine,
    gear_box_power_in, max_alternator_current, alternator_current_model,
    engine_start_current, prev_battery_state_of_charge, acceleration, time):
    """
    Calculates the alternator current [A].

    :param alternator_status:
        When the alternator is on due to 1:state of charge or 2:BERS [-].
    :type alternator_status: int

    :param on_engine:
        If the engine is on [-].
    :type on_engine: bool

    :param gear_box_power_in:
        Gear box power [kW].
    :type gear_box_power_in: float

    :param max_alternator_current:
        Max feasible alternator current [A].
    :type max_alternator_current: float

    :param alternator_current_model:
        Alternator current model.
    :type alternator_current_model: callable

    :param engine_start_current:
        Current demand to start the engine [A].
    :type engine_start_current: float

    :param prev_battery_state_of_charge:
        Previous state of charge of the battery [%].

        .. note::

            `prev_battery_state_of_charge` = 99 is equivalent to 99%.
    :type prev_battery_state_of_charge: float

    :param acceleration:
        Acceleration [m/s2].
    :type acceleration: float

    :param time:
        Time [s].
    :type time: float

    :return:
        Alternator current [A].
    :rtype: float
    """
    if alternator_status and on_engine and engine_start_current == 0:
        a_c = alternator_current_model(time, prev_battery_state_of_charge,
            alternator_status, gear_box_power_in, acceleration)
        a_c = max(a_c, -max_alternator_current)
    else:
        a_c = 0.0
    return a_c - engine_start_current


def gamma(data=None, name=None, attr=None, out=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 : Symbol
        The input array.

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

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


def p_enum_constant_list_2(t):
    """enum_constant_list : enum_constant COMMA enum_constant_list"""
    t[0] = t[1] + t[3]


def simple_moving_average(iterable, k=10):
    """ Returns an iterator over the simple moving average of the given list of values.
    """
    a = iterable if isinstance(iterable, list) else list(iterable)
    for m in range(len(a)):
        i = m - k
        j = m + k + 1
        w = a[max(0, i):j]
        yield float(sum(w)) / (len(w) or 1)


def createTagPath(node, tags):
    """create new child at the end of a tag chain starting from node
    no matter what"""
    if len(tags) == 0:
        return node
    dom = node.ownerDocument
    for tag in tags:
        node = node.appendChild(dom.createElement(tag))
    return node


def capital_first_transform(word: str, index: int):
    """
    Capital-case a single word

    Parameters
    ----------
    word : str
        Word to capital-case
    index : int
        Index of word in original string of words. If `index == 0`, the word
        will be capitalized, otherwise it will be lower-cased.

    Returns
    -------
    w : str
        Transformed word.
    """
    return word.capitalize() if index == 0 else word.lower()


@staticmethod
def parse_cap(string):
    """Parse a capability string."""
    cap, sep, param = string.partition('=')
    if not sep:
        return cap, []
    return cap, param.split(',')


def node_lang_class(node):
    """Extract a language specification from a node class names.

    :Parameters:
        node
            A docutils node

    :Returns:
        A string giving a language abbreviation (e.g. 'py') or None if no
        langauge is found.

    Some sourcecode containers can pass a (programming) language specification
    by passing it via a classname like 'lang-py'. This function searches a
    nodes classnames for those starting with 'lang-' and returns the trailing
    portion. Note that if more than one classname matches, only the first is
    seen.

    """
    for cname in node['classes']:
        if cname.startswith('lang-'):
            return cname[5:]
    return None


def split_normals():
    """Split custom normals of selected vertices

    """
    pass


def _bjoin(seq):
    """
    Convert the sequence `seq` into a string by joining with ', ' and
    surrounding with parentheses.
    """
    return '(' + ', '.join(seq) + ')'


def format_string_for_vistoms(string, prefix='', suffix=''):
    """
    Function to format a string such that it can be used in VISTOMS.

    :param string: string to be formatted
    :type string: str
    :param prefix: prefix to be placed in front of the string
    :type prefix: str
    :param suffix: suffix to be appended to the string
    :type suffix: str
    :return: formatted string
    :rtype: str
    """
    replacement_list = (' ', ''), ('_', '-'), ('[', ''), (']', ''), ('.', '-')
    for repl in replacement_list:
        string = string.replace(repl[0], repl[1])
    return str(prefix) + string + str(suffix)


@classmethod
def from_filename(cls, filename):
    """Creates a Thesaurus object from the given filename, which should
        contain the WordNet wn_s.pl file.

        >>> t = Thesaurus.from_filename("wn_s.pl")
        >>> t.synonyms("hail")
        ['acclaim', 'come', 'herald']
        """
    f = open(filename, 'rb')
    try:
        return cls.from_file(f)
    finally:
        f.close()


def name(obj):
    """ return name of an object (type). """
    t = str(type(obj))
    s = str(obj)
    if 'function' in t:
        pre, post = s.split(' at ', 1)
        pre, post = pre.split()
        name = "<function '" + post + "'>"
    elif 'module' in t:
        pre, post = s.split(' from ', 1)
        name = '<' + pre[1:] + '>'
    elif 'class' in t:
        if 'method' in t:
            pre, post = s.split(' of ', 1)
            name = "<method '" + pre.split()[-1] + "'>"
        else:
            pre, post = t.split('class ', 1)
            name = "<ding '" + post[:-1][1:-1] + "'>"
    elif 'built-in' in t:
        name = '<' + t + '>'
    return name


def extract_vtodos(calendars):
    """Filter out vtodos from an iterator over calendars.

    :param calendars: Iterator over (href, calendar) tuples
    :return: Iterator over Calendar subcomponents
    """
    for href, calendar in calendars:
        for component in calendar.subcomponents:
            if component.name == 'VTODO':
                yield component


def make_tuple(v):
    """ returns a tuple with v as unique element
    """
    return v,


def p_expression_types(t):
    """
    expression : FLOAT
               | INT
               | STRING
               | list
               | dict
               | querychain
               | query
               | scope
               | argskwargs
    """
    t[0] = t[1]


@classmethod
def get_by_id(cls, record_id):
    """Get record by ID."""
    if any((isinstance(record_id, (str, bytes)) and record_id.isdigit(),
        isinstance(record_id, (int, float)))):
        return cls.query.get(int(record_id))
    return None


@staticmethod
def commit(message):
    """Build and return full command to use with subprocess.Popen for 'git commit' command

        :param message:
        :return: list
        """
    cmd = ['git', 'commit', '-m', message]
    return cmd


def is_subclass(obj, cls):
    """
    判断某一个类或者对象是否是某一个类的子类
    :param obj: 类或对象
    :param cls: 类
    :return: True or False
    """
    try:
        for i in obj.__bases__:
            if i is cls or isinstance(i, cls):
                return True
        for i in obj.__bases__:
            if isinstance(i, cls):
                return True
    except AttributeError:
        return isinstance(obj.__class__, cls)
    return False


@classmethod
def from_dict(cls, params):
    """Create a RasterModelGrid from a dictionary.

        Parameters
        ----------
        params : dict_like
            Initialization parameters for a RasterModelGrid.

        Returns
        -------
        RasterModelGrid
            A newly-created grid.

        Examples
        --------
        >>> from landlab import RasterModelGrid
        >>> grid = RasterModelGrid.from_dict(
        ...     {'shape': (3, 4), 'bc': {'top': 'closed'}})
        >>> grid.number_of_nodes
        12

        LLCATS: GINF
        """
    shape = params.pop('shape', None)
    return cls(shape, **params)


def find_vertex(vertices, connection):
    """
    Find which vertex of *vertices* corresponds to *connection*.

    Parameters
    ----------
    vertices: DataFrame
        Dataframe of the vertices.
    connection: Series
        Row of the dataframe *connections* obtained with the function
        *dhd.connect.second_selection*.

    Returns
    -------
    Series
        Series of the dataframe *vertices* corresponding to *connection*.
    """
    vertex = vertices.loc[vertices['idE'] == connection['idE']].iloc[0]
    return vertex


def set_node_attributes(G, values, name=None):
    """Set node attributes from dictionary of nodes and values

        Parameters
        ----------
        G : DyNetx Graph

        name : string
           Attribute name

        values: dict
           Dictionary of attribute values keyed by node. If `values` is not a
           dictionary, then it is treated as a single attribute value that is then
           applied to every node in `G`.

        """
    if name is not None:
        try:
            for n, v in values.items():
                try:
                    G.node[n][name] = values[n]
                except KeyError:
                    pass
        except AttributeError:
            for n in G:
                G.node[n][name] = values
    else:
        for n, d in values.items():
            try:
                G.node[n].update(d)
            except KeyError:
                pass


def display_name_from_filepath(name):
    """Returns the path stripped of directory and extension, ensured to be utf8 compatible.

    """
    pass


def _getWordCount(start, length, bits):
    """
    Get the number of words that the requested
    bits would occupy.  We have to take into account
    how many bits are in a word and the fact that the
    number of requested bits can span multipe words.
    """
    newStart = start % bits
    newEnd = newStart + length
    totalWords = (newEnd - 1) / bits
    return totalWords + 1


def checkCommodities(esM, commodities):
    """ Check if the commodity is considered in the energy system model. """
    if not commodities.issubset(esM.commodities):
        raise ValueError(
            """Commodity does not match the ones of the specified energy system model.
"""
             + 'Commodity: ' + str(set(commodities)) + '\n' +
            'Energy system model commodities: ' + str(esM.commodities))


def is_folder_ignored(folder_name):
    """
    Defines pytable folders which should be ignored during concat.
    """
    if '_i_' in folder_name or 'bin_stats' in folder_name:
        return True
    else:
        return False


def read_file(filepath):
    """Read the contents of a file, returning a string variable"""
    with open(filepath, 'r') as file_to_read:
        content = file_to_read.read()
    return content


@staticmethod
def _get_cov_thresh_dict(cov_thresh, protected_attribute_names):
    """Return dict with covariance threshold for each protected attribute.

        Each attribute gets the same threshold (cov_thresh).

        Args:
            cov_thresh (float): the covariance threshold.
            protected_attribute_names (list(str)): list of protected attribute
                names.

        Returns:
            sensitive_attrs_to_cov_thresh (dict):
            dict of form {"sensitive_attribute_name_1":cov_thresh, ...}.
        """
    sensitive_attrs_to_cov_thresh = {}
    for sens_attr_name in protected_attribute_names:
        sensitive_attrs_to_cov_thresh[sens_attr_name] = cov_thresh
    return sensitive_attrs_to_cov_thresh


def _sync_onset(raw, onset, inverse=False):
    """Adjust onsets in relation to raw data."""
    offset = (-1 if inverse else 1) * raw._first_time
    assert raw.info['meas_date'] == raw.annotations.orig_time
    annot_start = onset - offset
    return annot_start


@classmethod
def _match(cls, url, **kwargs):
    """Return True if this handler can handle the input URL"""
    if cls.match_proto:
        return url.proto == cls.match_proto
    else:
        return True


def floor_from_str(src):
    """A more complex restriction on integer.  A comment in the XSD assures
    that the value 1 is valid in the schema only for legacy reasons.  In
    other words, we may encounter content with a value of 1 but we should
    not generate this value in our output.

    <xs:simpleType name="Floor">
            <xs:restriction base="xs:integer">
                    <xs:maxInclusive value="1"/>
                    <xs:minInclusive value="-100"/>
            </xs:restriction>
    </xs:simpleType>
    """
    value = int(src)
    if value < -100 or value > 1:
        raise ValueError('Value out of bounds defined for FLOOR: %i' % value)
    return value


def stencil_fit_image_aspect(use_repeat: bool=True, use_scale: bool=True,
    mask: bool=False):
    """When using an image texture, adjust the stencil size to fit the image aspect ratio

    :param use_repeat: Use Repeat, Use repeat mapping values
    :type use_repeat: bool
    :param use_scale: Use Scale, Use texture scale values
    :type use_scale: bool
    :param mask: Modify Mask Stencil, Modify either the primary or mask stencil
    :type mask: bool
    """
    pass


def _breakdown_point(n_samples, n_subsamples):
    """Approximation of the breakdown point.

    Parameters
    ----------
    n_samples : int
        Number of samples.

    n_subsamples : int
        Number of subsamples to consider.

    Returns
    -------
    breakdown_point : float
        Approximation of breakdown point.
    """
    return 1 - (0.5 ** (1 / n_subsamples) * (n_samples - n_subsamples + 1) +
        n_subsamples - 1) / n_samples


def merge_dicts(*dicts):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.

    Source: https://stackoverflow.com/q/38987
    """
    result = {}
    for dictionary in dicts:
        result.update(dictionary)
    return result


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


def to_string(option, value):
    """
    Converts any values to strings when appropriate
    """
    try:
        value = value.__str__()
    except AttributeError:
        pass
    return option, value


def dissolve_verts(use_face_split: bool=False, use_boundary_tear: bool=False):
    """Dissolve verts, merge edges and faces

    :param use_face_split: Face Split, Split off face corners to maintain surrounding geometry
    :type use_face_split: bool
    :param use_boundary_tear: Tear Boundary, Split off face corners instead of merging faces
    :type use_boundary_tear: bool
    """
    pass


def _nameof(obj, dflt=''):
    """Return the name of an object.
    """
    return getattr(obj, '__name__', dflt)


def is_int(string: str) ->bool:
    """Check whether string is integer.
    """
    try:
        int(string)
        return True
    except ValueError:
        return False


def byte_width(number):
    """Determine the smallest number of bytes that can encode a number.

    Parameters
    ----------
    number: int
        The number to be encoded

    Returns
    -------
    int
        The number of bytes required to encode this value.

    """
    abs_number = abs(number)
    if abs_number <= 127:
        return 1
    elif abs_number <= 32767:
        return 2
    elif abs_number <= 2147483647:
        return 4
    else:
        return 8


def _reg2int(reg):
    """Converts 32-bit register value to signed integer in Python.

    Parameters
    ----------
    reg: int
        A 32-bit register value read from the mailbox.

    Returns
    -------
    int
        A signed integer translated from the register value.

    """
    result = -(reg >> 31 & 1) * (1 << 31)
    for i in range(31):
        result += (reg >> i & 1) * (1 << i)
    return result