@staticmethod
def open_at_time(schedule, timestamp, include_close=False):
    """
        To determine if a given timestamp is during an open time for the market.

        :param schedule: schedule DataFrame
        :param timestamp: the timestamp to check for
        :param include_close: if False then the timestamp that equals the closing timestamp will return False and not be
            considered a valid open date and time. If True then it will be considered valid and return True. Use True
            if using bars and would like to include the last bar as a valid open date and time.
        :return: True if the timestamp is a valid open date and time, False if not
        """
    date = timestamp.date()
    if date in schedule.index:
        if include_close:
            return schedule.loc[date, 'market_open'
                ] <= timestamp <= schedule.loc[date, 'market_close']
        else:
            return schedule.loc[date, 'market_open'
                ] <= timestamp < schedule.loc[date, 'market_close']
    else:
        return False


def __iter__():
    """Returns an ordered set of versions for beeing looped over.

        The objects returned are of 'IVersionData'.
        """


def PLUS_DI(df, n):
    """
    Plus Directional Indicator
    """


def render_view_remove():
    """Remove the selected render view

    """
    pass


def validate_dataset(ds):
    """
    Check if all entries in this dataset have all the required fields
    Parameters
    ----------
    ds : dict
        Dictionary of datasets
    Raises
    ------
    ValueError: If a field is missing
    """
    req_fields = ['data_pattern', 'datadir', 'datatype', 'is_mc', 'notes',
        'run_list', 'run_number_prefix', 'system']
    for name, entry in list(ds.items()):
        for field in req_fields:
            if field not in list(entry.keys()):
                raise ValueError(
                    'Field `{}` missing in `{}` dataset definition'.format(
                    field, name))
        if isinstance(entry['run_list'], int):
            entry['run_list'] = str(entry['run_list'])


def Lorentz1d(x, *p):
    """
    function to calculate a general one dimensional Lorentzian

    Parameters
    ----------
    x :     array-like
        coordinate(s) where the function should be evaluated
    p :     list
        list of parameters of the Lorentz-function
        [XCEN, FWHM, AMP, BACKGROUND]

    Returns
    -------
    array-like
        the value of the Lorentian described by the parameters p
        at position (x, y)

    """
    g = p[3] + p[2] / (1 + (2 * (x - p[0]) / p[1]) ** 2)
    return g


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

    The ".dev0" means dirty.

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


def isProcessingAllowed(request, identifier):
    """Return True if processing is allowed or False if not. If identifier is provided
        the user represented by that identifier is used, otherwise it's the current request
        user"""
    NotImplemented


def check_types_compatible(*types: str) ->bool:
    """
    Check types have no conflicts (can be used in multiple inheritance)
    """
    cur_type = None
    cur_type_segments = None
    for data_type in types:
        segments = data_type.count(':')
        if cur_type is None or segments >= cur_type_segments:
            cur_type_segments = segments
            cur_type = data_type
    for data_type in types:
        if data_type not in cur_type:
            return False
    return True


def is_even(x):
    """Returns True if x is even, otherwise False."""
    return x % 2 == 0


def _parse_service_response_json(response):
    """Parse service response as JSON
    """
    return response.json()


def rename_collection(db, collection, new_name):
    """
    Renames a MongoDB collection.

    Arguments:

        db (Database): A pymongo ``Database`` object. Can be obtained
            with ``get_db``.

        collection (str): Name of the collection to be renamed.

        new_name (str, func): ``new_name`` can be one of two things::

            1. The new collection name, as a string.
            2. A function which, when passed the current collection name,
                returns the new collection name. If the function
                returns an empty string, the collection will not be
                renamed.
    """
    if hasattr(new_name, '__call__'):
        _new = new_name(collection)
        if _new == '':
            return
    else:
        _new = new_name
    c = db[collection]
    c.rename(_new)


def workid_from_url(url):
    """Get the workid from an archiveofourown.org website url"""
    split_url = url.split('/')
    try:
        index = split_url.index('works')
    except ValueError:
        return
    if len(split_url) >= index + 1:
        if split_url[index + 1].isdigit():
            return int(split_url[index + 1])
    return


@classmethod
def _get_pdi(cls, df, windows):
    """ +DI, positive directional moving index

        :param df: data
        :param windows: range
        :return:
        """
    window = cls.get_only_one_positive_int(windows)
    pdm_column = 'pdm_{}'.format(window)
    tr_column = 'atr_{}'.format(window)
    pdi_column = 'pdi_{}'.format(window)
    df[pdi_column] = df[pdm_column] / df[tr_column] * 100
    return df[pdi_column]


def delta13c_brand(r45sam, r46sam, d13cstd, r45std, r46std):
    """
    Linear simplification from Brand et al. 2010 Pure Appl Chem
    """
    raise NotImplementedError


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

        :param GenericErrorTag val:
        :rtype: LockingErrorTagUnion
        """
    return cls('generic_error', val)


def BoolProperty(name: str='', description: str='', default=False, options:
    set={'ANIMATABLE'}, tags: set={}, subtype: str='NONE', update=None, get
    =None, set=None):
    """Returns a new boolean property definition.

    :param name: Name used in the user interface.
    :type name: str
    :param description: Text used for the tooltip and api documentation.
    :type description: str
    :param options: Enumerator in [‘HIDDEN’, ‘SKIP_SAVE’, ‘ANIMATABLE’, ‘LIBRARY_EDITABLE’, ‘PROPORTIONAL’,’TEXTEDIT_UPDATE’].
    :type options: set
    :param tags: Enumerator of tags that are defined by parent class.
    :type tags: set
    :param subtype: Enumerator in [‘PIXEL’, ‘UNSIGNED’, ‘PERCENTAGE’, ‘FACTOR’, ‘ANGLE’, ‘TIME’, ‘DISTANCE’, ‘NONE’].
    :type subtype: str
    :param update: Function to be called when this value is modified, This function must take 2 values (self, context) and return None. Warning there are no safety checks to avoid infinite recursion.
    :param get: Function to be called when this value is ‘read’, This function must take 1 value (self) and return the value of the property.
    :param set: Function to be called when this value is ‘written’, This function must take 2 values (self, value) and return None.
    """
    pass


def _inv_impl(expr, op, **kw):
    """See :meth:`.ColumnOperators.__inv__`."""
    if hasattr(expr, 'negation_clause'):
        return expr.negation_clause
    else:
        return expr._negate()


def remove_tags(pipelineId=None, tagKeys=None):
    """
    Removes existing tags from the specified pipeline.
    See also: AWS API Documentation

    :example: response = client.remove_tags(
        pipelineId='string',
        tagKeys=[
            'string',
        ]
    )

    :type pipelineId: string
    :param pipelineId: [REQUIRED]
            The ID of the pipeline.

    :type tagKeys: list
    :param tagKeys: [REQUIRED]
            The keys of the tags to remove.
            (string) --

    :rtype: dict
    :return: {}

    """
    pass


def getFileSystemEncoding():
    """Return the name of the encoding used to convert
           Unicode filenames into system file names"""


def _unit_empty_map(value, empty):
    """
    Map unit values for CoNLL-U columns to a string or None if empty.

    Args:
        value: The value to map.
        empty: The empty representation for this unit.

    Returns:
        None if value is empty and value otherwise.
    """
    return None if value == empty else value


@classmethod
def start(cls, line: str) ->bool:
    """Takes a line from the document as argument, and
        returns a boolean representing whether that line marks the start
        of the current token. Every subclass of BlockToken must define a
        start function (see `block_tokenizer.tokenize_main`).
        """
    raise NotImplementedError


def color_rgb(r, g, b):
    """r,g,b are intensities of red, green, and blue in range(256)
    Returns color specifier string for the resulting color"""
    return '#%02x%02x%02x' % (r, g, b)


def guess_fileformat(aUri):
    """
    Simple file format guessing (using rdflib format types) based on the suffix

    see rdflib.parse [https://rdflib.readthedocs.org/en/latest/using_graphs.html]

    """
    if aUri.endswith('.xml'):
        return 'xml'
    elif aUri.endswith('.nt'):
        return 'nt'
    elif aUri.endswith('.n3') or aUri.endswith('.ttl'):
        return 'n3'
    elif aUri.endswith('.trix'):
        return 'trix'
    elif aUri.endswith('.rdfa'):
        return 'rdfa'
    else:
        return None


def array_split(iterable, n):
    """Split a list into chunks of ``n`` length."""
    for i in range(0, len(iterable), n):
        yield iterable[i:i + n]


def get_format(fmt, string):
    """Return a dictionary containing a format for each byte order."""
    return {'big': fmt('>' + string), 'little': fmt('<' + string)}


def reduce_path_widget(exclude_set, content):
    """
    Reduce the number of paths based on the exclude_set

    Arguments:
    exclude_set - Set of names to not consider
    content - Content of the widgets

    Return:
    None
    """
    for item in content:
        for sub_item in item:
            keys_to_delete = []
            for key in sub_item:
                if key in exclude_set:
                    keys_to_delete.append(key)
            for key in keys_to_delete:
                del sub_item[key]


def generate_url(url, *args, **kwargs):
    """Generate an url with input arguments.

    *args -> path parameter.
    *kwargs -> query parameter.
    """
    url = url.rstrip('/')
    if args:
        url = '/'.join([url, *args])
    if kwargs:
        for k, v in kwargs.items():
            if k == list(kwargs.keys())[0]:
                url += '?{}={}'.format(k, v)
                continue
            url += '&{}={}'.format(k, v)
    return url


@staticmethod
def __sanitize_requirements(requirements):
    """ @type requirements: dict """
    if requirements:
        if not isinstance(requirements, dict):
            raise Exception(
                'Invalid requirements format. They should be a dict')
        for key, value in requirements.items():
            requirements[key] = '(%s)' % value
    else:
        requirements = {}
    return requirements


def get_uri_parent(uri):
    """Return URI of parent collection with trailing '/', or None, if URI is top-level.

    This function simply strips the last segment. It does not test, if the
    target is a 'collection', or even exists.
    """
    if not uri or uri.strip() == '/':
        return None
    return uri.rstrip('/').rsplit('/', 1)[0] + '/'


def values():
    """ Return tuple of tuples (name, address) when isactive=True.  """


def ctime():
    """Return a string representing the date and time.

        datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
        d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
        platforms where the native C ctime() function (which time.ctime()
        invokes, but which datetime.ctime() does not invoke) conforms to the
        C standard.
        """


@classmethod
def is_valid(cls, elem):
    """ Check that the object elem is a field of the enum
            Example:
            >>> class MyEnum(EnumAutoName):
            ...     FIELD1 = "abc"
            ...     FIELD2 = 3
            ...
            >>> MyEnum.is_valid(MyEnum.FIELD1)
            True
            >>> MyEnum.is_valid("FIELD1")
            False
        """
    return elem in cls


def mangling_schemes():
    """
	Generate triplets for use with mangle_name
	(used in check_fortran_mangling)
	the order is tuned for gfortan
	"""
    for u in ('_', ''):
        for du in ('', '_'):
            for c in ('lower', 'upper'):
                yield u, du, c


def save_userpref():
    """Save user preferences separately, overrides startup file preferences

    """
    pass


def _roi_func(brain, roi, algorithm, cv_dict, **kwargs):
    """Brain_Data.predict_multi() helper function"""
    return brain.apply_mask(roi).predict(algorithm=algorithm, cv_dict=
        cv_dict, plot=False, **kwargs)


def create_cached_iscsi_volume(GatewayARN=None, VolumeSizeInBytes=None,
    SnapshotId=None, TargetName=None, SourceVolumeARN=None,
    NetworkInterfaceId=None, ClientToken=None):
    """
    Creates a cached volume on a specified cached volume gateway. This operation is only supported in the cached volume gateway architecture.
    In the request, you must specify the gateway, size of the volume in bytes, the iSCSI target name, an IP address on which to expose the target, and a unique client token. In response, the gateway creates the volume and returns information about it. This information includes the volume Amazon Resource Name (ARN), its size, and the iSCSI target ARN that initiators can use to connect to the volume target.
    Optionally, you can provide the ARN for an existing volume as the SourceVolumeARN for this cached volume, which creates an exact copy of the existing volumes latest recovery point. The VolumeSizeInBytes value must be equal to or larger than the size of the copied volume, in bytes.
    See also: AWS API Documentation

    Examples
    Creates a cached volume on a specified cached gateway.
    Expected Output:

    :example: response = client.create_cached_iscsi_volume(
        GatewayARN='string',
        VolumeSizeInBytes=123,
        SnapshotId='string',
        TargetName='string',
        SourceVolumeARN='string',
        NetworkInterfaceId='string',
        ClientToken='string'
    )

    :type GatewayARN: string
    :param GatewayARN: [REQUIRED]
            The Amazon Resource Name (ARN) of the gateway. Use the ListGateways operation to return a list of gateways for your account and region.

    :type VolumeSizeInBytes: integer
    :param VolumeSizeInBytes: [REQUIRED]

    :type SnapshotId: string
    :param SnapshotId:

    :type TargetName: string
    :param TargetName: [REQUIRED]

    :type SourceVolumeARN: string
    :param SourceVolumeARN: The ARN for an existing volume. Specifying this ARN makes the new volume into an exact copy of the specified existing volume's latest recovery point. The VolumeSizeInBytes value for this new volume must be equal to or larger than the size of the existing volume, in bytes.

    :type NetworkInterfaceId: string
    :param NetworkInterfaceId: [REQUIRED]

    :type ClientToken: string
    :param ClientToken: [REQUIRED]

    :rtype: dict
    :return: {
        'VolumeARN': 'string',
        'TargetARN': 'string'
    }

    :returns:
    (dict) --
    VolumeARN (string) --
    TargetARN (string) --

    """
    pass


def render_html(content: str) ->str:
    """
    Return a html fragment unchanged.

    Parameters
    ----------
    content : str
        Html text.

    Returns
    -------
    html : str
    """
    return content


def set_application(app):
    """Tells the server about the application to use."""


def _dTAI_UTC(time, leapsecond_to_time, leapseconds=leapseconds):
    """Get TAI-UTC difference in seconds for a given time.

    >>> from datetime import datetime, timedelta
    >>> _dTAI_UTC(datetime(1972, 1, 1), lambda ls: ls.utc)
    datetime.timedelta(0, 10)
    >>> tai = lambda ls: ls.utc + ls.dTAI_UTC
    >>> _dTAI_UTC(datetime(2015, 7, 1, 0, 0, 34), tai)
    datetime.timedelta(0, 35)
    >>> _dTAI_UTC(datetime(2015, 7, 1, 0, 0, 35), tai) # leap second
    datetime.timedelta(0, 35)
    >>> _dTAI_UTC(datetime(2015, 7, 1, 0, 0, 36), tai)
    datetime.timedelta(0, 36)

    Bulletin C 51 says "NO leap second will be introduced at the end
    of June 2016."[4] and therefore UTC-TAI is still 36
    at 27 June 2016:

    >>> _dTAI_UTC(datetime(2016, 6, 27), lambda ls: ls.utc)
    datetime.timedelta(0, 36)
    """
    leapseconds_list = leapseconds()
    transition_times = list(map(leapsecond_to_time, leapseconds_list))
    if time < transition_times[0]:
        raise ValueError('Dates before %s are not supported, got %r' % (
            transition_times[0], time))
    for i, (start, end) in enumerate(zip(transition_times, transition_times
        [1:])):
        if start <= time < end:
            return leapseconds_list[i].dTAI_UTC
    assert 0


def qtview(html, url=''):
    """View HTML in a Qt dialog"""
    try:
        from PyQt5.QtWebKitWidgets import QWebView
        from PyQt5.QtCore import QUrl
    except ImportError:
        from PyQt4.QtWebKit import QWebView
        from PyQt4.QtCore import QUrl
    helpView = QWebView()
    helpView.setHtml(html, QUrl(url))
    helpView.show()
    return helpView


@classmethod
def _check_mandatory_params(cls, params, mandatory):
    """
        Ensure that we have all mandatory parameters in the given parameters

        :param params: file parameters
        :param mandatory: required parameters
        :raises ValueError: if some of the required parameters are missing
        """
    for md in mandatory:
        if md not in params:
            raise ValueError('Mandatory parameter is missing: {0}'.format(md))


@classmethod
def load(cls, database, doc_id):
    """Load a specific document from the given database.

        :param database: the `Database` object to retrieve the document from
        :param doc_id: the document ID
        :return: the `Document` instance, or `None` if no document with the
                 given ID was found
        """
    doc = database.get(doc_id)
    if doc is None:
        return None
    return cls.wrap(doc)


def split_translated_columns(df, on='SCP_Title', sep='\\[', min_title=10,
    initialize=''):
    """
    Creates new columns with the splite results of translates titles in the format lang1 `sep`lang2]`sep`.
    The new colums are called `on`_0 (not translated) `on`_1, and `on`_2.
    """
    if sep == '\\[':
        trail = '\\]'
    elif sep == '\\(':
        trail = '\\)'
    else:
        trail = ''
    it0 = df[~df[on].str.contains('.* %s[A-Za-z0-0\\s]{%d}' % (sep, min_title))
        ][on].str.split('\\s%s' % sep).str[0]
    it1 = df[df[on].str.contains('.* %s[A-Za-z0-0\\s]{%d}' % (sep, min_title))
        ][on].str.split('\\s%s' % sep).str[0]
    it2 = df[df[on].str.contains('.* %s[A-Za-z0-0\\s]{%d}' % (sep, min_title))
        ][on].str.replace('%s$' % trail, '').str.split('\\s%s' % sep).str[1]
    df['%s_0' % on] = initialize
    df['%s_1' % on] = initialize
    df['%s_2' % on] = initialize
    df.loc[it0.index.values, '%s_0' % on] = it0
    df.loc[it1.index.values, '%s_1' % on] = it1
    df.loc[it2.index.values, '%s_2' % on] = it2
    return df


def convert_empty_string_to_none(str):
    """Returns None if given string is empty.

    Empty string is default for Django form empty HTML input.
    python-mistral-client does not handle empty strings, only "None" type.

    :param str: string variable
    """
    return str if len(str) != 0 else None


@staticmethod
def get_values(data):
    """Return median of bernoulli distributed layer
        calculated from expected values. """
    return (data > 0.5).astype(float)


def v2rel(v):
    """rewrites "be" lemma to "i"s, for more natural reading of relations"""
    if v == 'be':
        return 'is'
    return v


def parse_asset_code(value: bytes) ->str:
    """
    Decode a byte string an remove any extra bytes.

    Example: b'KIN\\x00' > 'KIN'
    """
    return value.decode().replace('\x00', '')


def dmerge(d1, d2, merge_func=None):
    """
        Create a new dictionary being the merge of the two passed as a
        parameter. If a key is in both dictionaries, the values are processed
        with the merge_func.

        By default the value in the second dictionary erases the value in the
        first one.
    """
    d = {}
    d.update(d1)
    if merge_func is None:
        d.update(d2)
        return d
    for k, v in d2.iteritems():
        if k in d:
            d[k] = merge_func(d[k], v)
        else:
            d[k] = v
    return d


def display_size(val):
    """
    return a human-readable count value for the provided byte count

    Accepts a byte count value and returns a string with a count value and
    binary prefix which describes the respective size.

    Args:
        val: the value (in bytes) to interpret

    Returns:
        the human-readable size
    """
    for unit in ['B', 'KiB', 'MiB', 'GiB']:
        if abs(val) < 1024.0:
            return '{:3.1f} {}'.format(val, unit)
        val /= 1024.0
    return '{:.1f} TiB'.format(val)


def single(val):
    """ Creates an iterator with a single value.

    Args:

        val(any):               Single value to add to the iterator.

    Returns:

        iterable:               An iterable yielding the single value.

    Examples:

        >>> list(single(1))
        [1]
    """
    yield val


def type_check_expr(value, kind):
    """ Type check the value of an expression.

    Parameters
    ----------
    value : object
        The value to type check.

    kind : type
        The allowed type of the value.

    """
    if not isinstance(kind, type):
        raise TypeError('%s is not a type' % kind)
    if not isinstance(value, kind):
        msg = "expression value has invalid type '%s'"
        raise TypeError(msg % type(value).__name__)


def landsat_c1_toa_cloud_mask(input_img, snow_flag=False, cirrus_flag=False,
    cloud_confidence=2, shadow_confidence=3, snow_confidence=3,
    cirrus_confidence=3):
    """Extract cloud mask from the Landsat Collection 1 TOA BQA band

    Parameters
    ----------
    input_img : ee.Image
        Image from a Landsat Collection 1 TOA collection with a BQA band
        (e.g. LANDSAT/LE07/C01/T1_TOA).
    snow_flag : bool
        If true, mask snow pixels (the default is False).
    cirrus_flag : bool
        If true, mask cirrus pixels (the default is False).
        Note, cirrus bits are only set for Landsat 8 (OLI) images.
    cloud_confidence : int
        Minimum cloud confidence value (the default is 2).
    shadow_confidence : int
        Minimum cloud confidence value (the default is 3).
    snow_confidence : int
        Minimum snow confidence value (the default is 3).  Only used if
        snow_flag is True.
    cirrus_confidence : int
        Minimum cirrus confidence value (the default is 3).  Only used if
        cirrus_flag is True.

    Returns
    -------
    ee.Image

    Notes
    -----
    Output image is structured to be applied directly with updateMask()
        i.e. 0 is cloud, 1 is cloud free

    Assuming Cloud must be set to check Cloud Confidence

    Bits
        0:     Designated Fill
        1:     Terrain Occlusion (OLI) / Dropped Pixel (TM, ETM+)
        2-3:   Radiometric Saturation
        4:     Cloud
        5-6:   Cloud Confidence
        7-8:   Cloud Shadow Confidence
        9-10:  Snow/Ice Confidence
        11-12: Cirrus Confidence (Landsat 8 only)

    Confidence values
        00: "Not Determined", algorithm did not determine the status of this
            condition
        01: "No", algorithm has low to no confidence that this condition exists
            (0-33 percent confidence)
        10: "Maybe", algorithm has medium confidence that this condition exists
            (34-66 percent confidence)
        11: "Yes", algorithm has high confidence that this condition exists
            (67-100 percent confidence)

    References
    ----------
    https://landsat.usgs.gov/collectionqualityband

    """
    qa_img = input_img.select(['BQA'])
    cloud_mask = qa_img.rightShift(4).bitwiseAnd(1).neq(0).And(qa_img.
        rightShift(5).bitwiseAnd(3).gte(cloud_confidence)).Or(qa_img.
        rightShift(7).bitwiseAnd(3).gte(shadow_confidence))
    if snow_flag:
        cloud_mask = cloud_mask.Or(qa_img.rightShift(9).bitwiseAnd(3).gte(
            snow_confidence))
    if cirrus_flag:
        cloud_mask = cloud_mask.Or(qa_img.rightShift(11).bitwiseAnd(3).gte(
            cirrus_confidence))
    return cloud_mask.Not()


def _convert_to_dataset_class(df, dataset_class, expectation_suite=None,
    profiler=None):
    """
    Convert a (pandas) dataframe to a great_expectations dataset, with (optional) expectation_suite

    Args:
        df: the DataFrame object to convert
        dataset_class: the class to which to convert the existing DataFrame
        expectation_suite: the expectation suite that should be attached to the resulting dataset
        profiler: the profiler to use to generate baseline expectations, if any

    Returns:
        A new Dataset object
    """
    if expectation_suite is not None:
        new_df = dataset_class.from_dataset(df)
        new_df._initialize_expectations(expectation_suite)
    else:
        new_df = dataset_class.from_dataset(df)
        if profiler is not None:
            new_df.profile(profiler)
    return new_df


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


@classmethod
def get_supported_resources_types(cls):
    """Returns a list of resource types this plugin supports

        :returns: a list of resource types
        """
    raise NotImplementedError


def from_iterable(iterables):
    """
    Backport of itertools.chain.from_iterable
    """
    for it in iterables:
        for element in it:
            yield element


def render_view_remove():
    """Remove the selected render view

    """
    pass


def Values2A(ibrav, values):
    """needs a doc string"""
    if ibrav in [0, 1, 2]:
        return [values[0], values[0], values[0], 0, 0, 0]
    elif ibrav in [3, 4]:
        return [values[0], values[0], values[1], values[0], 0, 0]
    elif ibrav in [5, 6]:
        return [values[0], values[0], values[1], 0, 0, 0]
    elif ibrav in [7, 8, 9, 10, 11, 12]:
        return [values[0], values[1], values[2], 0, 0, 0]
    elif ibrav in [13, 14, 15]:
        return [values[0], values[1], values[2], 0, values[3], 0]
    else:
        return list(values[:6])


def safe_int(value):
    """
    Attempt to convert the given value to an integer,
    returning None on failure.
    """
    try:
        return int(value)
    except (TypeError, ValueError):
        return None


def assign_metrics_to_assembly(mmcif_dict, assembly):
    """Takes an assembly dict, and goes through an mmcif dictionary looking for
    relevant energy etc. information to update it with.

    :param dict mmcif_dict: The dictionary to read.
    :param dict assembly: The assembly to update."""
    for a in mmcif_dict.get('pdbx_struct_assembly_prop', []):
        if a['biol_id'] == str(assembly['id']):
            if a['type'] == 'MORE':
                assembly['delta_energy'] = float(a['value'].split('/')[0])
            elif a['type'] == 'SSA (A^2)':
                assembly['surface_area'] = float(a['value'].split('/')[0])
            elif a['type'] == 'ABSA (A^2)':
                assembly['buried_surface_area'] = float(a['value'].split(
                    '/')[0])


def with_metaclass(meta, *bases):
    """Create a base class with a metaclass."""
    return meta('NewBase', bases, {})


def pendingparentchange():
    """Returns true if the dirstate is in the middle of a set of changes
        that modify the dirstate parent.
        """


def smart_map(func, i, *args, **kwargs):
    """
    将单个对象或列表中的每个项传入给定的函数，并返回单个结果或列表结果，类似于 map 函数

    :param func: 传入到的函数
    :param i: 列表或单个对象
    :param args: func 函数所需的 args
    :param kwargs: func 函数所需的 kwargs
    :return: 若传入的为列表，则以列表返回每个结果，反之为单个结果
    """
    if isinstance(i, (list, tuple, set)):
        return list(map(lambda x: func(x, *args, **kwargs), i))
    else:
        return func(i, *args, **kwargs)


def numeric_to_native(val):
    """
    Given a numeric string (as defined by fluent spec),
    return an int or float
    """
    if '.' in val:
        return float(val)
    else:
        return int(val)


@classmethod
def from_dict(cls, **keys) ->'Duration':
    """ initializes a `Duration` object from a dictionary using `**` notation."""
    return cls(**keys)


def position_distance(a, b, g_length):
    """
    Calculate the shortest distance between two positions on a circular genome.
    :param a: index of first position
    :param b: index of second position
    :param g_length: total genome length in basepairs
    :return: the calculated distance
    """
    diff = abs(a - b)
    return min(diff, g_length - diff)


def _resource_endpoint(object_uri):
    """Determine the resource name and whether it is the plural endpoint from
    the specified `object_uri`. Returns `(None, None)` for the root URL plural
    endpoint.
    """
    obj_parts = object_uri.split('/')
    plural_endpoint = len(obj_parts) % 2 == 0
    if plural_endpoint:
        obj_parts = obj_parts[:-1]
    if len(obj_parts) <= 2:
        return '', False
    resource_name = obj_parts[-2]
    resource_name = resource_name.rstrip('s')
    return resource_name, plural_endpoint


def _remove_pixels(masks, pixels_to_remove):
    """Remove pixels from all masks

    Parameters
    ----------
    masks : list of arrays
        List of masks
    pixels_to_remove : list of arrays
        List as [[rows], [cols]] that expands with zip(*pixels_to_remove) to
        iterate over pairs of (row, col) points to remove from all masks.

    Returns
    -------
    new_masks : list of arrays
        Returns original masks with overlapping pixels removed

    """
    new_masks = []
    for mask in masks:
        new_mask = mask.copy().todok()
        for row, col in zip(*pixels_to_remove):
            new_mask[row, col] = 0
        new_masks.append(new_mask.tocoo())
    return new_masks


@classmethod
def woba_npb(cls, bb, hbp, _1b, _2b, _3b, hr, ab, sf, ibb=0, e_bb=0):
    """
        Weighted on-base average for NPB(wOBA)
        http://1point02.jp/
        :param bb: base on ball
        :param hbp: hit by pitch
        :param _1b: single
        :param _2b: double
        :param _3b: triple
        :param hr: home run
        :param ab: at bat
        :param sf: sacrifice fly
        :param ibb: intentional base on balls(default:0)
        :param e_bb: base on ball for error(default:0)
        :return: (float) wOBA
        """
    _calc_params = {'const_u_bb': 0.692, 'const_u_hbp': 0.73,
        'const_u_e_bb': 0.966, 'const_u_1b': 0.865, 'const_u_2b': 1.334,
        'const_u_3b': 1.725, 'const_u_hr': 2.065}
    return cls.woba(bb, hbp, _1b, _2b, _3b, hr, ab, sf, ibb, e_bb, **
        _calc_params)


def factorial(num):
    """Returns the factorial of a nonnegative integer.

    This function is provided in math module starting with Python 2.6,
    but implement anyway for compatibility with older systems."""
    result = 1
    for i in range(2, num + 1):
        result = result * i
    return result


def extract_dict(fields, source, pop=1, noempty=1):
    """
    Extrahiere die angegebenen Felder aus dem Quell-Dictionary,
    um sie beispielsweise in eine andere Tabelle zu schreiben.
    Dabei werden die gefundenen Schlüssel normalerweise aus der Quelle
    gelöscht:

    >>> source={'tan': 123, 'status': 'new', 'owner_id': 'Willy'}
    >>> extract_dict(['status'], source)
    {'status': 'new'}
    >>> source
    {'tan': 123, 'owner_id': 'Willy'}

    Wird pop=0 übergeben, bleibt die Quelle unverändert erhalten:

    >>> extract_dict(['owner_id'], source, pop=0)
    {'owner_id': 'Willy'}
    >>> source
    {'tan': 123, 'owner_id': 'Willy'}

    In der Quelle nicht vorhandene Schlüssel werden übergangen,
    erzeugen also keinen Fehler:

    >>> extract_dict(['owner_id', 'group_id'], source, pop=0)
    {'owner_id': 'Willy'}
    >>> source
    {'tan': 123, 'owner_id': 'Willy'}

    Mit noempty=True (Standardwert) werden "leere" Werte (wie nach dem
    Absenden von Web-Formularen sehr häufig) weggelassen:

    >>> form={'group_id': 'group_abc', 'status': '', 'zahl': '0'}
    >>> all=['group_id', 'status', 'zahl']
    >>> extract_dict(all, form, pop=1, noempty=1)
    {'group_id': 'group_abc', 'zahl': '0'}

    Diese leeren Werte sind im Falle von pop=True dann trotzdem in der
    Quelle gelöscht:
    >>> form
    {}

    Siehe auch die allgemeinere Funktion visaplan.tools.dicts.subdict
    """
    get = pop and source.pop or source.get
    res = {}
    if noempty:
        for field in fields:
            if field in source:
                val = get(field)
                if val not in (None, ''):
                    res[field] = val
    else:
        for field in fields:
            if field in source:
                res[field] = get(field)
    return res


@classmethod
def can_create(cls, user_id):
    """
        Typically used in routes like `POST /widgets`

        :param user_id: The user on behalf of whom permission is being requested
        :return: A boolean value indicating whether or not the given user
        is allowed to create wholly new instances of this resource
        """
    return True


@classmethod
def getPlaybackRate(cls):
    """Gets the playback rate of the document timeline.
        """
    return cls.build_send_payload('getPlaybackRate', {}), cls.convert_payload({
        'playbackRate': {'class': float, 'optional': False}})


def view_selected():
    """Resize view so you can see selected nodes

    """
    pass


@staticmethod
def get_attribute_name(mlflow_attribute_name):
    """
        Resolves an MLflow attribute name to a `SqlRun` attribute name.
        """
    return mlflow_attribute_name


def iterargF2(dinp, size, scan):
    """an iterator used by the F2 processing to allow multiprocessing or MPI set-up"""
    for i in range(scan):
        r = dinp.row(i)
        yield r, size


def store_userid(request, reset=False, remove=False, invite=False):
    """Store user ID in the session."""
    request.session['social_auth_user'] = request.user.pk
    request.session['password_reset'] = reset
    request.session['account_remove'] = remove
    request.session['user_invite'] = invite


def image_from_view(filepath: str=''):
    """Make an image from the current 3D view for re-projection

    :param filepath: File Path, Name of the file
    :type filepath: str
    """
    pass


def _power2(n):
    """Find the next power of 2.
    """
    p2 = 16
    while n > p2:
        p2 += p2
    return p2


@classmethod
def from_exactlines(cls, transformed_lines):
    """Constructs a partially-computed LinesClassifier from ExactLines.

        This is useful, for example, if you need ExactLines for some other
        analysis and then want to determine classification regions. We use it
        to determine the class break-point when generating Figure 4 from [1]
        (experiments/linearity_hypothesis.py).
        """
    if not len(transformed_lines[0]) == 2:
        error = ('ExactLine must be called with include_post=True ' +
            'to use from_exactline.')
        if len(transformed_lines) == 2:
            error += ('\nIf you called exactline (singular), you must ' +
                'pass a singleton list instead.')
        raise TypeError(error)
    self = cls(None, None, None)
    self.transformed_lines = transformed_lines
    self.partially_computed = True
    return self


def Day_():
    """Compatibility: see pDay"""


def unauthenticated(func):
    """Adds 'unauthenticated' attribute to decorated function.

    Usage:

    >>> @unauthenticated
    ... def mymethod(f):
    ...     pass
    """
    func.unauthenticated = True
    return func


def trace(fn):
    """Decorator that marks a function to be traced."""
    fn.should_trace = True
    return fn


@classmethod
def load_provisioning(cls):
    """set up the provision.py module for this dialect.

        For dialects that include a provision.py module that sets up
        provisioning followers, this method should initiate that process.

        A typical implementation would be::

            @classmethod
            def load_provisioning(cls):
                __import__("mydialect.provision")

        The default method assumes a module named ``provision.py`` inside
        the owning package of the current dialect, based on the ``__module__``
        attribute::

            @classmethod
            def load_provisioning(cls):
                package = ".".join(cls.__module__.split(".")[0:-1])
                try:
                    __import__(package + ".provision")
                except ImportError:
                    pass

        .. versionadded:: 1.3.14

        """


def fail_if_missing(module, found, service, msg=''):
    """
    This function will return an error or exit gracefully depending on check mode status
    and if the service is missing or not.

    :arg module: is an  AnsibleModule object, used for it's utility methods
    :arg found: boolean indicating if services was found or not
    :arg service: name of service
    :kw msg: extra info to append to error/success msg when missing
    """
    if not found:
        if module.check_mode:
            module.exit_json(msg=
                'Service %s not found on %s, assuming it will exist on full run'
                 % (service, msg), changed=True)
        else:
            module.fail_json(msg=
                'Could not find the requested service %s: %s' % (service, msg))


def allocate_hosts(AutoPlacement=None, ClientToken=None, InstanceType=None,
    Quantity=None, AvailabilityZone=None):
    """
    Allocates a Dedicated Host to your account. At minimum you need to specify the instance size type, Availability Zone, and quantity of hosts you want to allocate.
    See also: AWS API Documentation

    :example: response = client.allocate_hosts(
        AutoPlacement='on'|'off',
        ClientToken='string',
        InstanceType='string',
        Quantity=123,
        AvailabilityZone='string'
    )

    :type AutoPlacement: string
    :param AutoPlacement: This is enabled by default. This property allows instances to be automatically placed onto available Dedicated Hosts, when you are launching instances without specifying a host ID.
            Default: Enabled

    :type ClientToken: string
    :param ClientToken: Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see How to Ensure Idempotency in the Amazon Elastic Compute Cloud User Guide .

    :type InstanceType: string
    :param InstanceType: [REQUIRED]
            Specify the instance type that you want your Dedicated Hosts to be configured for. When you specify the instance type, that is the only instance type that you can launch onto that host.

    :type Quantity: integer
    :param Quantity: [REQUIRED]
            The number of Dedicated Hosts you want to allocate to your account with these parameters.

    :type AvailabilityZone: string
    :param AvailabilityZone: [REQUIRED]
            The Availability Zone for the Dedicated Hosts.

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

    :returns:
    (string) --

    """
    pass


def invertStereo(smifragment):
    """
    >>> invertStereo("C")
    'C'
    >>> invertStereo("[C@@]")
    '[C@]'
    >>> invertStereo("[C@]")
    '[C@@]'
    >>> invertStereo("[C@H]")
    '[C@@H]'
    >>> invertStereo("[C@@H]")
    '[C@H]'
    """
    ans = []
    i = 0
    while i < len(smifragment):
        x = smifragment[i]
        ans.append(x)
        if x == '@':
            if smifragment[i + 1] == '@':
                i += 1
            else:
                ans.append('@')
        i += 1
    return ''.join(ans)


def extract_7z_singlefile(archive, compression, cmd, verbosity, interactive,
    outdir):
    """Extract a singlefile archive (eg. gzip or bzip2) with '7z e'.
    This makes sure a single file and no subdirectories are created,
    which would cause errors with patool repack."""
    cmdlist = [cmd, 'e']
    if not interactive:
        cmdlist.append('-y')
    cmdlist.extend(['-o%s' % outdir, '--', archive])
    return cmdlist


def empty_display_renderer(widget, data):
    """Display renderer which renders an empty string.
    """
    return data.rendered or u''


def is_content_xml(content_type):
    """Based on the Content-Type return True if the content is XML text."""
    if 'text/xml' in content_type:
        return True
    if 'application/vnd.paos+xml' in content_type:
        return True
    return False


def find_first(iterable, predicate):
    """ Return the first item in iterable that matches predicate, or None if no match """
    for item in iterable:
        if predicate(item):
            return item


def redir_dest_to_path(destination: str):
    """ Convert a redirection destination to a path fragment """
    if destination.startswith('/'):
        return destination[1:]
    return destination


def create_tags(ResourceId=None, Tags=None):
    """
    Creates tags for a WorkSpace.
    See also: AWS API Documentation

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

    :type ResourceId: string
    :param ResourceId: [REQUIRED]
            The resource ID of the request.

    :type Tags: list
    :param Tags: [REQUIRED]
            The tags of the request.
            (dict) --Describes the tag of the WorkSpace.
            Key (string) -- [REQUIRED]The key of the tag.
            Value (string) --The value of the tag.

    :rtype: dict
    :return: {}

    """
    pass


def _ta_append(list_of_tensors, value):
    """Append a value to the end of a list of PyTorch tensors."""
    list_of_tensors.append(value)
    return list_of_tensors


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


def bytescale(data, high=255, low=0, cmin=None, cmax=None):
    """Byte scales an array (image).

    Byte scaling converts the input image to uint8 dtype, and rescales
    the data range to ``(low, high)`` (default 0-255).
    If the input image already has dtype uint8, no scaling is done.
    Source code adapted from scipy.misc.bytescale (deprecated in scipy-1.0.0)

    Parameters
    ----------
    data : numpy array
        image data array.
    high : int (default=255)
        Scale max value to `high`.
    low : int (default=0)
        Scale min value to `low`.
    cmin : int (optional)
        Bias scaling of small values. Default is ``data.min()``.
    cmax : int (optional)
        Bias scaling of large values. Default is ``data.max()``.

    Returns
    -------
    img_array : uint8 numpy array
        The byte-scaled array.

    Examples
    --------
        >>> import numpy as np
        >>> from earthpy.spatial import bytescale
        >>> img = np.array([[ 91.06794177,   3.39058326,  84.4221549 ],
        ...                 [ 73.88003259,  80.91433048,   4.88878881],
        ...                 [ 51.53875334,  34.45808177,  27.5873488 ]])
        >>> bytescale(img)
        array([[255,   0, 236],
               [205, 225,   4],
               [140,  90,  70]], dtype=uint8)
        >>> bytescale(img, high=200, low=100)
        array([[200, 100, 192],
               [180, 188, 102],
               [155, 135, 128]], dtype=uint8)
        >>> bytescale(img, cmin=0, cmax=255)
        array([[255,   0, 236],
               [205, 225,   4],
               [140,  90,  70]], dtype=uint8)
    """
    if data.dtype == 'uint8':
        return data
    if high > 255:
        raise ValueError('`high` should be less than or equal to 255.')
    if low < 0:
        raise ValueError('`low` should be greater than or equal to 0.')
    if high < low:
        raise ValueError('`high` should be greater than or equal to `low`.')
    if cmin is None or cmin < data.min():
        cmin = float(data.min())
    if cmax is None or cmax > data.max():
        cmax = float(data.max())
    crange = cmax - cmin
    if crange < 0:
        raise ValueError('`cmax` should be larger than `cmin`.')
    elif crange == 0:
        raise ValueError(
            '`cmax` and `cmin` should not be the same value. Please specify `cmax` > `cmin`'
            )
    scale = float(high - low) / crange
    data[data > cmax] = cmax
    bytedata = (data - cmin) * scale + low
    return (bytedata.clip(low, high) + 0.5).astype('uint8')


def shape_key_retime():
    """Resets the timing for absolute shape keys

    """
    pass


def check_termination(dF, F, dx_norm, x_norm, ratio, ftol, xtol):
    """Check termination condition for nonlinear least squares."""
    ftol_satisfied = dF < ftol * F and ratio > 0.25
    xtol_satisfied = dx_norm < xtol * (xtol + x_norm)
    if ftol_satisfied and xtol_satisfied:
        return 4
    elif ftol_satisfied:
        return 2
    elif xtol_satisfied:
        return 3
    else:
        return None


def convert_to_wsgi(field):
    """Convert a field name from UPPER_CASE to Title-Case.
    """
    return field.lower().replace('_', ' ').title().replace(' ', '-')


@staticmethod
def units_to_latex(units):
    """
        Transform ASCII units to Latex

        Note: this function is not yet implemented.

        units (str):
            The units to transform.
        """
    return units


@classmethod
def _camel_case(cls, text, first_upper=False):
    """
        Transform text to camelCase or CamelCase

        :param text:
        :param first_upper: first symbol must be upper?
        :return:
        """
    result = ''
    need_upper = False
    for pos, symbol in enumerate(text):
        if symbol == '_' and pos > 0:
            need_upper = True
        else:
            if need_upper:
                result += symbol.upper()
            else:
                result += symbol.lower()
            need_upper = False
    if first_upper:
        result = result[0].upper() + result[1:]
    return result


def list2string(lista):
    """Covierte lista a string"""
    if len(lista) == 0:
        return ''
    if str(lista[0].__class__) in ["<class 'int'>", "<class 'float'>"]:
        resultado = ''
        for l in lista:
            resultado = resultado + str(l) + ', '
        return resultado[:-2]
    elif str(lista[0].__class__) in ["<class 'str'>"]:
        resultado = ''
        for l in lista:
            resultado = resultado + "'" + str(l) + "', "
        return resultado[:-2]


@classmethod
def header_hash(cls, header):
    """Given a header return the hash."""
    import quark_hash
    return quark_hash.getPoWHash(header)


def template_new_rxn(output):
    """
    Generate template file used as input of rxn_creator function

    Parameters
    ----------
    output: str
        path for the template new_rxn to create
    """
    with open(output, 'w') as f:
        line = '\t'.join(['reaction_id', 'my_rxn']) + '\n'
        f.write(line)
        line = '\t'.join(['comment', 'reaction added for X reason']) + '\n'
        f.write(line)
        line = '\t'.join(['reversible', 'false']) + '\n'
        f.write(line)
        line = '\t'.join(['linked_gene', '(gene_a or gene_b) and gene_c']
            ) + '\n'
        f.write(line)
        line = '\t'.join(['#reactant/product', '#stoichio:compound_id:compart']
            ) + '\n'
        f.write(line)
        line = '\t'.join(['reactant', '1.0:compound_a:c']) + '\n'
        f.write(line)
        line = '\t'.join(['reactant', '2.0:compound_b:c']) + '\n'
        f.write(line)
        line = '\t'.join(['product', '1.0:compound_c:c']) + '\n'
        f.write(line)
        f.write('\n')
        line = '\t'.join(['reaction_id', 'my_rxn_2']) + '\n'
        f.write(line)
        line = '\t'.join(['comment', 'reaction added for X reason']) + '\n'
        f.write(line)
        line = '\t'.join(['reversible', 'true']) + '\n'
        f.write(line)
        line = '\t'.join(['linked_gene', '']) + '\n'
        f.write(line)
        line = '\t'.join(['#reactant/product', '#stoichio:compound_id:compart']
            ) + '\n'
        f.write(line)
        line = '\t'.join(['reactant', '1.0:compound_a:c']) + '\n'
        f.write(line)
        line = '\t'.join(['reactant', '2.0:compound_d:c']) + '\n'
        f.write(line)
        line = '\t'.join(['product', '1.0:compound_c:c']) + '\n'
        f.write(line)


def mean(lis):
    """Always returns a floating-point number.
    """
    lis_len = len(lis)
    if lis_len == 0:
        return 0.0
    total = float(sum(lis))
    return total / lis_len


def vote_display(vote, arg=None):
    """
    Given a string mapping values for up and down votes, returns one
    of the strings according to the given ``Vote``:

    =========  =====================  =============
    Vote type   Argument               Outputs
    =========  =====================  =============
    ``+1``     ``"Bodacious,Bogus"``  ``Bodacious``
    ``-1``     ``"Bodacious,Bogus"``  ``Bogus``
    =========  =====================  =============

    If no string mapping is given, "Up" and "Down" will be used.

    Example usage::

        {{ vote|vote_display:"Bodacious,Bogus" }}
    """
    if arg is None:
        arg = 'Up,Down'
    bits = arg.split(',')
    if len(bits) != 2:
        return vote.vote
    up, down = bits
    if vote.vote == 1:
        return up
    return down


def convertFfoPpbToSkew(ffoPpb):
    """
    Convert frequency skew to Fraction Frequency Offset (FFO) in ppb.
    """
    return ffoPpb * 1e-09 + 1


def color_triple(color):
    """
    Convert a command line colour value to a RGB triple of integers.
    FIXME: Somewhere we need support for greyscale backgrounds etc.
    """
    if color.startswith('#') and len(color) == 4:
        return int(color[1], 16), int(color[2], 16), int(color[3], 16)
    if color.startswith('#') and len(color) == 7:
        return int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16)
    elif color.startswith('#') and len(color) == 13:
        return int(color[1:5], 16), int(color[5:9], 16), int(color[9:13], 16)


def simplex_size(d, m):
    """Count points in the d-m simplex."""
    n = 1
    p = 1
    for i in range(d):
        n *= m + i
        p *= i + 1
    return n // p


def rectangle_vol(length, width, height):
    """Usage: rectangle_vol(length rectangle, width of rectangle, height of rectangle)"""
    return length * width * height


def define(zelf, *args, **kwargs):
    """ set a attribute on this ding. """
    name = args[0]
    value = args[1]
    zelf[name] = value


def update_permission_names(apps, schema_editor):
    """
    Updates the wording of our three custom gym permissions
    """
    Permission = apps.get_model('auth', 'Permission')
    for name in ['Trainer, can see the users for a gym',
        'Admin, can manage users for a gym',
        'Admin, can administrate the different gyms']:
        permissions = Permission.objects.filter(name=name)
        if permissions.exists():
            permissions[0].name = name.replace(',', ':')
            permissions[0].save()


def m_i(i):
    """
    Compute one plus the "total degree of the interpolating
    polynoimals" (Kruger & Kubler, 2004). This shows up many times in
    Smolyak's algorithm. It is defined as:

    .. math::

        m_i = \\begin{cases}
        1 \\quad & \\text{if } i = 1 \\\\
        2^{i-1} + 1 \\quad & \\text{if } i \\geq 2
        \\end{cases}

    Parameters
    ----------
    i : int
        The integer i which the total degree should be evaluated

    Returns
    -------
    num : int
        Return the value given by the expression above

    """
    if i < 0:
        raise ValueError('i must be positive')
    elif i == 0:
        return 0
    elif i == 1:
        return 1
    else:
        return 2 ** (i - 1) + 1


def iter_slices(string, slice_length):
    """Iterate over slices of a string."""
    pos = 0
    while pos < len(string):
        yield string[pos:pos + slice_length]
        pos += slice_length


def view_all():
    """Resize view so you can see all nodes

    """
    pass


def lambda_eval(v):
    """
    If v is a callable, call it and return the value. Else, return it.
    Helpful when you want to preserve the ability to lazy-evaluate a
    value.
    """
    return v() if hasattr(v, '__call__') else v


def fill(strings, linelen=75):
    """Make one string from sequence of strings, with whitespace
    in between. The whitespace is chosen to form lines of at most
    linelen characters, if possible."""
    currpos = 0
    lasti = 0
    result = []
    for i, s in enumerate(strings):
        length = len(s)
        if currpos + length < linelen:
            currpos += length + 1
        else:
            result.append(b' '.join(strings[lasti:i]))
            lasti = i
            currpos = length
    result.append(b' '.join(strings[lasti:]))
    return b'\n'.join(result)


@classmethod
def load(cls, filename):
    """Load :class:'.Source' object from filename"""
    import pickle
    with open(filename, 'rb') as fp1:
        src = pickle.load(fp1)
    return src


def html_escape(string):
    """ Escape HTML special characters ``&<>`` and quotes ``'"``. """
    return string.replace('&', '&').replace('<', '<').replace('>',
        '>').replace('"', '"').replace("'", ''')


def non_darcy_drain_eta(re, iL, gamw, beta_function, *args, **kwargs):
    """For non-Darcy flow calculate the vertical drain eta parameter

    eta = 2 / (re**2 * beta**nflow * (rw * gamw)**(nflow-1) * nflow * iL**(nflow-1))

    nflow will be obtained from the **kwargs.  rw will be back calculated
    from the n parameter (n=re/rw) which is usually the first of the *arg parameters
    or one of the **kwargs

    Note that eta is used in radial consolidation equations:
    [strain rate] = (u - uw)**n * k / gamw * eta
    Compare with the Darcian case of (eta terms are calculated differerntly
    for Darcy and non-Darcy cases):
    [strain rate] = (u - uw) * k / gamw * eta

    Note that `non_darcy_drain_eta` only uses the exponential portion of the
    Non-Darcian flow relationship.  If hydraulic gradients are greater than
    iL then the flow rates will be overestimated.

    Parameters
    ----------
    re : float
        Drain influence radius.
    iL : float
        Limiting hydraulic gradient beyond which flow follows Darcy's law.
    gamw : float
        Unit weight of water. Usually gamw=10 kN/m**3 or gamw=9.807 kN/m**3.
    beta_function : obj or string
        The non_darcy_beta function to use. e.g. non_darcy_beta_ideal
        non_darcy_beat_constant, non_darcy_piecewise_constant.
        This can either be the function object itself
        or the name of the function e.g. 'non_darcy_beta_ideal'.
    *args, **kwargs : various
        The arguments to pass to the beta_function.

    Returns
    -------
    eta : float
        Value of eta parameter for non-Darcian flow

    Examples
    --------
    >>> non_darcy_drain_eta(re=1.5, iL=10, gamw=10,
    ... beta_function='non_darcy_beta_ideal', n=15, nflow=1.3, nterms=20)
    0.09807...
    >>> non_darcy_drain_eta(1.5, 10, 10,
    ... 'non_darcy_beta_ideal', 15, nflow=1.3, nterms=20)
    0.09807...

    >>> non_darcy_drain_eta(re=1.5, iL=10, gamw=10,
    ... beta_function='non_darcy_beta_ideal', n=np.array([20.0, 15.0]),
    ... nflow=np.array([1.000001, 1.3]), nterms=20)
    array([0.3943..., 0.0980...])

    """
    try:
        beta_fn = globals()[beta_function]
    except KeyError:
        beta_fn = beta_function
    try:
        n = kwargs['n']
    except:
        n = args[0]
    rw = re / n
    nflow = kwargs['nflow']
    beta = beta_fn(*args, **kwargs)
    eta = 2 / (re ** 2 * beta ** nflow * (rw * gamw) ** (nflow - 1) * nflow *
        iL ** (nflow - 1))
    return eta


def _make_runium_param(iterations, times):
    """
    Creates and returns a dict with runium specific stats and functions that
    can be accessed from within the task.
    """
    context = {'iterations': iterations, 'iterations_remaining': times -
        iterations}
    return context


@classmethod
def _serialize_tag(cls, value):
    """Tag values can only be one of the following types: string, numeric, or boolean
        Opentracing spec: https://github.com/opentracing/specification/blob/master/specification.md
        """
    return value if isinstance(value, (int, float, bool, str)) else str(value)


@classmethod
def command(cls, name):
    """ Get command class for name """
    return cls.commands().get(name)


def simple(y, x, N, beta, gamma, sigma, mu):
    """
    Defines the SEIR simple model.

    :param array y: Individuals at time step x
    :param array x: Time step
    :param int N: Population
    :param float beta: The parameter controlling how often a susceptible-infected contact results in a new infection.
    :param float gamma: The rate an infected recovers and moves into the resistant phase.
    :param float sigma: The rate at which an exposed person becomes infective.
    :param float mu: The parameter represents the average death rate

    :returns: S, E, I, R at time step n
    :rtype: tuple(int/float, int/float, int/float)
    """
    S = mu * (N - y[0]) - beta * y[0] * y[2] / N
    E = beta * y[0] * y[2] / N - (mu + sigma) * y[1]
    I = sigma * y[1] - (mu + gamma) * y[2]
    R = gamma * y[2] - mu * y[3]
    return S, E, I, R


def list_static():
    """Get URL and path of a particular mapping"""
    raise NotImplementedError


def hash_string(string_to_hash):
    """
    Hashes string using SHA-512

    :param string_to_hash: string to hash
    :type string_to_hash: str
    :return: hashed string
    """
    import crypt
    if hasattr(crypt, 'mksalt'):
        return crypt.crypt(string_to_hash, crypt.mksalt(crypt.METHOD_SHA512))
    else:
        import string
        import random
        rand = random.SystemRandom()
        salt = ''.join([rand.choice(string.ascii_letters + string.digits) for
            _ in range(8)])
        return crypt.crypt(string_to_hash, '$6$rounds={rounds}${salt}'.
            format(rounds=4096, salt=salt))


def suppress_context(exc):
    """Python 2 compatible version of raise from None"""
    exc.__context__ = None
    return exc


def nonzero_1d(input):
    """Return the nonzero index of the given 1D input.

    Parameters
    ----------
    input : Tensor
        Must be a 1D tensor.

    Returns
    -------
    Tensor
        A 1D integer tensor containing the nonzero indices.
    """
    pass


def _covered_spikes_criterion(occ_superset, size_superset, occ_subset,
    size_subset, l_covered_spikes):
    """
    evaluate covered spikes criterion
    (see pattern_set_reduction)
    """
    reject_superset = True
    reject_subset = True
    score_superset = (size_superset - l_covered_spikes) * occ_superset
    score_subset = (size_subset - l_covered_spikes) * occ_subset
    if score_superset >= score_subset:
        reject_superset = False
    else:
        reject_subset = False
    return reject_superset, reject_subset


def get_object_tagging(Bucket=None, Key=None, VersionId=None):
    """
    Returns the tag-set of an object.
    See also: AWS API Documentation

    :example: response = client.get_object_tagging(
        Bucket='string',
        Key='string',
        VersionId='string'
    )

    :type Bucket: string
    :param Bucket: [REQUIRED]

    :type Key: string
    :param Key: [REQUIRED]

    :type VersionId: string
    :param VersionId:

    :rtype: dict
    :return: {
        'VersionId': 'string',
        'TagSet': [
            {
                'Key': 'string',
                'Value': 'string'
            },
        ]
    }

    :returns:
    (dict) --
    VersionId (string) --
    TagSet (list) --
    (dict) --
    Key (string) -- Name of the tag.
    Value (string) -- Value of the tag.

    """
    pass


def _transfer_deprecated_param_vals(replacement_params, kwargs):
    """ For the decorator replace_parameters(), reassigns new parameters
    the values passed to their corresponding deprecated parameters.

    Parameters
    ----------
    replacement_params: Dict[str, str]
    Dictionary of old_parameters as keys with replacement parameters
    as their corresponding values.

    kwargs: Dict[str, any]
    Dictionary of all the keyword args passed on the decorated function.

    Returns
    -------
    kwargs: Dict[str, any]
    Dictionary of all the keyword args to be passed on
    to the decorated function, with old parameter names
    replaced by new parameters, with their values intact.
    """
    for old_param, new_param in replacement_params.items():
        old_param_val = kwargs.setdefault(old_param, None)
        if old_param_val is not None:
            kwargs[new_param] = old_param_val
        kwargs.pop(old_param)
    return kwargs


def trim_trailing_lines(lines):
    """
    Trim trailing blank lines.
    """
    lines = list(lines)
    while lines and not lines[-1]:
        lines.pop(-1)
    return lines


def rstrip_list(s):
    """
    Return list with empty items from end of list removed.
    """
    for i in range(len(s) - 1, -1, -1):
        if s[i]:
            break
    else:
        return []
    return s[:i + 1]


def is_dict(var):
    """
    is this a dict-like?
    """
    return isinstance(var, dict)


def scale(factory=None, **parameters):
    """ Find image scale data for the given parameters or create it if
            a factory was provided.  The parameters will be passed back to
            the factory method, which is expected to return a tuple
            containing a representation of the actual image scale data (i.e.
            a string or file-like object) as well as the image's format and
            dimensions.  For convenience, this happens to match the return
            value of `scaleImage`, but makes it possible to use different
            storages, i.e. ZODB blobs """


def max_rt(value: str) ->int:
    """
    Convert the name of the section to the number of seconds, and validate the range

    :param value: Config section name
    :return: Number of seconds
    """
    seconds = int(value)
    if not 60 <= seconds <= 86400:
        raise ValueError('MAX_RT must be between 60 and 86400 seconds')
    return seconds


def prior_wording(frequency_short):
    """Create the comparison wording for the prior period based
    off the frequency_short"""
    prior_wording = ''
    if frequency_short == 'A':
        prior_wording = 'Last yr'
    elif frequency_short == 'SA':
        prior_wording = '6 months ago'
    elif frequency_short == 'Q':
        prior_wording = 'Last quarter'
    elif frequency_short == 'M':
        prior_wording = 'Last month'
    elif frequency_short == 'BW':
        prior_wording = '2 wks ago'
    elif frequency_short == 'W':
        prior_wording = 'Last week'
    elif frequency_short == 'D':
        prior_wording = 'Previous day'
    return prior_wording


@classmethod
def get_keyring(cls):
    """Get current keyring backend.

        Returns the Keyring class, the `name` property will return the name
        of the keyring.
        """
    return cls.keyring.get_keyring()


@staticmethod
def _regr_test_fromcsv():
    """Test reading in from a CSV since that has a few differences.

    Using pandas.read_csv produces a DataFrame with the following potential
    issues:

       1. Booleans become numpy.bool_ which may not be serializable without
          some tricks.
       2. Column ordering may end up different.

>>> import tempfile, os, shutil, io, pandas, msgpack
>>> from oxtie.fronts import nums
>>> from oxtie.backs import simple
>>> backend = simple.FileBackend(root=tempfile.mkdtemp(suffix='.oxtie'))
>>> data = io.StringIO(('%c'%10).join([
...    'event_date,estimate,period_date,reported,confirmed',
...    '10/1/2017,,2017/9,,FALSE',
...    '7/1/2017,0.17,2017/6,0.15,TRUE']))
>>> p = pandas.read_csv(data, index_col=0, parse_dates=[0])
>>> f = nums.SimpleFrame({'name': 'test'}, backend, frame=p)
>>> f.more = '*' * 10  # Add some more data in a property to save.
>>> f.save()
>>> g = backend.load({'name': 'test'}, allow_load=True)
>>> all(g.frame == f.frame) and f.more == g.more
True

    As an aside, you can use the deserialize_body_csv method to create
    a nums.SimpleFrame instance directly from a CSV representation without
    having to call pandas.read_csv first:

>>> cbody = {'__csv': f.frame.to_csv()}
>>> h = nums.SimpleFrame.deserialize_body_csv({'name': 'test'}, cbody, None)
>>> all(h.frame == f.frame)
True

    Now clean up

>>> shutil.rmtree(backend.root)
"""


@staticmethod
def invert_y(z, y):
    """
        Inverts the Y tile value.

        Inputs:
        z -- the zoom level associated with the tile
        y -- the Y tile number

        Returns:
        The flipped tile value
        """
    raise NotImplementedError()


def get_main_package_directory(distribution):
    """
    Given a Distribution object, return the main package directory.
    """
    return min(distribution.packages, key=len)


def get_s3_key(prefix, suffix, date):
    """
    Get an AWS S3 key formatted with the date.

    :param str prefix: prefix of the S3 key
    :param str suffix: suffix of the S3 key
    :param str date: date
    :return str: AWS S3 key
    """
    key = f'{prefix}/{date}/{suffix}'
    return key


def join_channels(zelf, *args, **kwargs):
    """ join channels.  """
    for channel in zelf.channels:
        zelf.join(channel)


def receive_leave_group(group_state: 'GroupState'):
    """
    Received IGMP Leave packet regarding group GroupState
    """
    group_state.group_state_logger.debug(
        'NonQuerier MembersPresent: receive_leave_group')
    return


def make_values(params, point):
    """Return a dictionary with the values replaced by the values in point,
    where point is a list of the values corresponding to the sorted params."""
    values = {}
    for i, k in enumerate(sorted(params)):
        values[k] = point[i]
    return values


def waitUntilFinished():
    """Return a Deferred that fires (with this IBuildSetStatus object)
        when all builds have finished."""


@classmethod
def get_real_function(this, fn):
    """Returns the reference to the real function which was decorated
		and bypasses as fn argument to this method

		:param fn: function which was decorated
		:return: function - reference to the real function decorated with registered decorators
		"""
    return this._get_native_function(fn)


def _add_keys_to_request(request_field_pb, key_pbs):
    """
    Add protobuf keys to a request object.

    :type request_field_pb: `RepeatedCompositeFieldContainer`
    :param request_field_pb: A repeated proto field that contains keys.

    :type key_pbs: of :
    :param list key_pbs: The class:`~gcloudoem.datastore.datastore_v1_pb2.Key`s to add to a request.
    """
    for key_pb in key_pbs:
        request_field_pb.add().CopyFrom(key_pb)


def object_map(api):
    """get all relevant objects from the server and put it in a single dictionary"""
    uid_mapping = {}
    params1 = {'paging': False}
    resp1 = api.get(endpoint='indicatorTypes', params=params1).json()
    for elem in resp1['indicatorTypes']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['displayName'])}
    params2 = {'fields': 'id,name,value', 'paging': False}
    resp2 = api.get(endpoint='constants', params=params2).json()
    for elem in resp2['constants']:
        uid_mapping[elem['id']] = {u'desc': u'[Name: {} - Value: {}]'.
            format(elem['name'], elem['value'])}
    params3 = {'fields': 'id,name,organisationUnits', 'paging': False}
    resp3 = api.get(endpoint='organisationUnitGroups', params=params3).json()
    for elem in resp3['organisationUnitGroups']:
        uid_mapping[elem['id']] = {u'desc': u'[Name: {} - OUG Size: {}]'.
            format(elem['name'], len(elem['organisationUnits']))}
    params4 = {'fields': 'id,name', 'paging': False}
    resp4 = api.get(endpoint='dataElements', params=params4).json()
    for elem in resp4['dataElements']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['name'])}
    params5 = {'fields': 'id,name', 'paging': False}
    resp5 = api.get(endpoint='categoryOptionCombos', params=params5).json()
    for elem in resp5['categoryOptionCombos']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['name'])}
    params6 = {'fields': 'id,name', 'paging': False}
    resp6 = api.get(endpoint='programs', params=params6).json()
    for elem in resp6['programs']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['name'])}
    params7 = {'fields': 'id,name', 'paging': False}
    resp7 = api.get(endpoint='programIndicators', params=params7).json()
    for elem in resp7['programIndicators']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['name'])}
    params8 = {'fields': 'id,name', 'paging': False}
    resp8 = api.get(endpoint='trackedEntityAttributes', params=params8).json()
    for elem in resp8['trackedEntityAttributes']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['name'])}
    params9 = {'fields': 'id,name', 'paging': False}
    resp9 = api.get(endpoint='programStages', params=params9).json()
    for elem in resp9['programStages']:
        uid_mapping[elem['id']] = {u'desc': u'{}'.format(elem['name'])}
    return uid_mapping


def printmat(message, mat):
    """convenience method."""
    print(message)
    mat.neatprint()


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


@classmethod
def is_session_in_topic(cls) ->bool:
    """True if session id is in topic."""
    return True


def splitKeywordDict(dct):
    """Take a keyword dict and return a tuple of the form (userDict,
    reservedDict) """
    userDict = {}
    reservedDict = {}
    for key, value in dct.items():
        if key[0] == '_':
            reservedDict[key] = value
        else:
            userDict[key] = value
    return userDict, reservedDict


def note_adapter(obj, request):
    """
    Adapter for rendering a :class:`skosprovider.skos.Note` to json.

    :param skosprovider.skos.Note obj: The note to be rendered.
    :rtype: :class:`dict`
    """
    return {'note': obj.note, 'type': obj.type, 'language': obj.language,
        'markup': obj.markup}


def getPeer():
    """
        Get the remote address of this connection.

        Treat this method with caution.  It is the unfortunate result of the
        CGI and Jabber standards, but should not be considered reliable for
        the usual host of reasons; port forwarding, proxying, firewalls, IP
        masquerading, etc.

        @return: An L{IAddress} provider.
        """


def get_id(AccountId=None, IdentityPoolId=None, Logins=None):
    """
    Generates (or retrieves) a Cognito ID. Supplying multiple logins will create an implicit linked account.
    This is a public API. You do not need any credentials to call this API.
    See also: AWS API Documentation

    :example: response = client.get_id(
        AccountId='string',
        IdentityPoolId='string',
        Logins={
            'string': 'string'
        }
    )

    :type AccountId: string
    :param AccountId: A standard AWS account ID (9+ digits).

    :type IdentityPoolId: string
    :param IdentityPoolId: [REQUIRED]
            An identity pool ID in the format REGION:GUID.

    :type Logins: dict
    :param Logins: A set of optional name-value pairs that map provider names to provider tokens. The available provider names for Logins are as follows:
            Facebook: graph.facebook.com
            Amazon Cognito Identity Provider: cognito-idp.us-east-1.amazonaws.com/us-east-1_123456789
            Google: accounts.google.com
            Amazon: www.amazon.com
            Twitter: api.twitter.com
            Digits: www.digits.com
            (string) --
            (string) --

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

    """
    pass


def find_nb_for_cna(nb_wraps, client_adpt, vswitch_map):
    """Determines the NetworkBridge (if any) supporting a client adapter.

    :param nb_wraps: The network bridge wrappers on the system.
    :param client_adpt: The client adapter wrapper.
    :param vswitch_map: Maps the vSwitch IDs to URIs.
                        See 'get_vswitch_map'
    :return The Network Bridge wrapper that is hosting the client adapter.
            If there is not one, None is returned.
    """
    for nb_wrap in nb_wraps:
        if vswitch_map.get(nb_wrap.vswitch_id) != client_adpt.vswitch_uri:
            continue
        if not nb_wrap.supports_vlan(client_adpt.pvid):
            continue
        return nb_wrap
    return None


def _find_associated_colorbar(obj):
    """A rather poor way of telling whether an axis has a colorbar associated: Check the
    next axis environment, and see if it is de facto a color bar; if yes, return the
    color bar object.
    """
    for child in obj.get_children():
        try:
            cbar = child.colorbar
        except AttributeError:
            continue
        if cbar is not None:
            return cbar
    return None


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 run_in_thread(func, *args, **kwargs):
    """
    多线程工具函数，不涉及返回值等细节处理时使用
    :param func: 被线程委托的函数
    :return: 返回Thread线程对象
    """
    from threading import Thread
    thread = Thread(target=func, args=args, kwargs=kwargs)
    thread.daemon = True
    thread.start()
    return thread


@staticmethod
def record_to_str(record):
    """Returns the configured records into a list of string"""
    record = record.split(',')
    try:
        record.remove('')
    except ValueError:
        pass
    pk, record = record[0].split('}')
    return record


@classmethod
def dkron_run_hourly(cls):
    """Called by dkron to run all tasks that shal be run hourly."""
    for section, srv in cls._ocean._all_services():
        srvd = cls._get(srv)
        if 'dkron' in srvd and 'hourly' in srvd['dkron']:
            cmd = srvd['dkron']['hourly']
            cls.shell(srv, '-c', cmd)


def write_gmsh(msh_fname=None, mesh_dict=None):
    """Write gmsh .msh file."""
    with open(msh_fname, 'w') as mfid:
        mfid.write('$MeshFormat\n')
        mfid.write('{}'.format(mesh_dict['mesh_format']))
        mfid.write('$EndMeshFormat\n')
        mfid.write('$Nodes\n')
        mfid.write('{0:d}\n'.format(mesh_dict['nodes'].shape[0]))
        for inode, node_row in enumerate(mesh_dict['nodes'].tolist()):
            mfid.write('{0:d} {1:f} {2:f} {3:f}\n'.format(inode + 1,
                node_row[0], node_row[1], node_row[2]))
        mfid.write('$EndNodes\n')
        mfid.write('$Elements\n')
        mfid.write('{0:d}\n'.format(mesh_dict['elements'].shape[0]))
        for ielem, (elem_row, info_row) in enumerate(zip(mesh_dict[
            'elements'].astype(str), mesh_dict['elem_info'].astype(str))):
            mfid.write('{0} {1} {2}\n'.format(ielem + 1, ' '.join(info_row),
                ' '.join(elem_row[:-1])))
        mfid.write('$EndElements\n')


def get_namespace_from_name(name):
    """
    Get a fully-qualified name's namespace, if it has one.
    It's the sequence of characters after the last "." in the name.
    If there is no "." in the name, then it belongs to the null
    namespace (i.e. the empty string will be returned)

    >>> get_namespace_from_name('abcd.efgh')
    'efgh'
    >>> get_namespace_from_name('abc')
    ''
    >>> get_namespace_from_name('a.b.c')
    'c'
    """
    if '.' not in name:
        return ''
    return name.split('.')[-1]


def hel_to_chapter(el):
    """
    Transforms an parsel element into a chapter dict.

    :param el: sel element
    :return: chapter's name, href and title
    :rtype: dict
    """
    return dict(name=el.css('a::text').extract_first(), href=el.css(
        'a::attr(href)').extract_first(), title=el.css('span::text').
        extract_first())


def camel_to_underscore(name):
    """Convert camel case style naming to underscore style naming

    If there are existing underscores they will be collapsed with the
    to-be-added underscores. Multiple consecutive capital letters will not be
    split except for the last one.

    >>> camel_to_underscore('SpamEggsAndBacon')
    'spam_eggs_and_bacon'
    >>> camel_to_underscore('Spam_and_bacon')
    'spam_and_bacon'
    >>> camel_to_underscore('Spam_And_Bacon')
    'spam_and_bacon'
    >>> camel_to_underscore('__SpamAndBacon__')
    '__spam_and_bacon__'
    >>> camel_to_underscore('__SpamANDBacon__')
    '__spam_and_bacon__'
    """
    output = []
    for i, c in enumerate(name):
        if i > 0:
            pc = name[i - 1]
            if c.isupper() and not pc.isupper() and pc != '_':
                output.append('_')
            elif i > 3 and not c.isupper():
                previous = name[i - 3:i]
                if previous.isalpha() and previous.isupper():
                    output.insert(len(output) - 1, '_')
        output.append(c.lower())
    return ''.join(output)


def set_flags(obj, flag_field, flags):
    """Will process the flags and set attributes in the object accordingly.

    The object "obj" will gain attributes named after the flags provided in
    "flags" and valued True/False, matching the results of applying each
    flag value from "flags" to flag_field.
    """
    for flag in flags:
        if flag[1] & flag_field:
            obj.__dict__[flag[0]] = True
        else:
            obj.__dict__[flag[0]] = False


def __ne__(A, other):
    """Returns true if both objects are not equal"""
    return not A == other


def db2Amp(db_difference):
    """Receives difference in decibels, returns amplitude proportion"""
    return 10.0 ** (db_difference / 20.0)


def get_queues(app):
    """Get all active queues and workers for a celery application.

    Unlike get_running_queues, this goes through the application's server.
    Also returns a dictionary with entries for each worker attached to
    the given queues.

    :param `celery.Celery` app: the celery application

    :return: queues dictionary with connected workers, all workers
    :rtype: (dict of lists of strings, list of strings)

    :example:

    >>> from merlin.celery import app
    >>> queues, workers = get_queues(app)
    >>> queue_names = [*queues]
    >>> workers_on_q0 = queues[queue_names[0]]
    >>> workers_not_on_q0 = [worker for worker in workers
                             if worker not in workers_on_q0]
    """
    i = app.control.inspect()
    active_workers = i.active_queues()
    if active_workers is None:
        active_workers = {}
    queues = {}
    for worker in active_workers:
        for my_queue in active_workers[worker]:
            try:
                queues[my_queue['name']].append(worker)
            except KeyError:
                queues[my_queue['name']] = [worker]
    return queues, [*active_workers]


def split_encoded(data, encoding, max_split=None):
    """Split ID3v2 frame data according to encoding."""
    remainder = data
    values = []
    num_split = 0
    while True:
        try:
            if encoding in ['iso-8859-1', 'utf-8']:
                head, tail = remainder.split(b'\x00', 1)
            else:
                if len(remainder) % 2 != 0:
                    remainder += b'\x00'
                head, tail = remainder.split(b'\x00\x00', 1)
                if len(head) % 2 != 0:
                    head, tail = remainder.split(b'\x00\x00\x00', 1)
                    head += b'\x00'
        except ValueError:
            if remainder:
                values.append(remainder)
            break
        else:
            values.append(head)
            remainder = tail
            num_split += 1
            if max_split and num_split >= max_split:
                values.append(tail)
                break
    return values


def get_title(run):
    """
    form standard psi title
    """
    return '{} {} {} {}'.format(run.get_sample(), run.get_field(), run.
        get_orient(), run.get_temp())


@staticmethod
def p_cpu_type(p):
    """cpu_type : CPU_TYPE STRING"""
    p[0] = p[2]


def extract_suffixed_keys(dictionary, suffix):
    """Returns a dictionary with all keys from :obj:`dictionary` that are suffixed
  with :obj:`suffix`.
  """
    sub_dict = {}
    for key, value in dictionary.items():
        if key.endswith(suffix):
            original_key = key[:-len(suffix)]
            sub_dict[original_key] = value
    return sub_dict


def edit_word(word, pred, edit_id):
    """
    Edit a word, given edit and seq2seq predictions.
    """
    if edit_id == 1:
        return word
    elif edit_id == 2:
        return word.lower()
    elif edit_id == 0:
        return pred
    else:
        raise Exception('Unrecognized edit ID: {}'.format(edit_id))


def setExpression(expr):
    """Set the filter expression, e.g. 'context.meta_type=='...'"""


@classmethod
def fetch(cls, id, connection=None):
    """Fetches a persisted job from its corresponding Redis key and
        instantiates it.
        """
    job = cls(id, connection=connection)
    job.refresh()
    return job


def get_bot_channel_associations(botName=None, botAlias=None, nextToken=
    None, maxResults=None, nameContains=None):
    """
    Returns a list of all of the channels associated with the specified bot.
    The GetBotChannelAssociations operation requires permissions for the lex:GetBotChannelAssociations action.
    See also: AWS API Documentation

    :example: response = client.get_bot_channel_associations(
        botName='string',
        botAlias='string',
        nextToken='string',
        maxResults=123,
        nameContains='string'
    )

    :type botName: string
    :param botName: [REQUIRED]
            The name of the Amazon Lex bot in the association.

    :type botAlias: string
    :param botAlias: [REQUIRED]
            An alias pointing to the specific version of the Amazon Lex bot to which this association is being made.

    :type nextToken: string
    :param nextToken: A pagination token for fetching the next page of associations. If the response to this call is truncated, Amazon Lex returns a pagination token in the response. To fetch the next page of associations, specify the pagination token in the next request.

    :type maxResults: integer
    :param maxResults: The maximum number of associations to return in the response. The default is 50.

    :type nameContains: string
    :param nameContains: Substring to match in channel association names. An association will be returned if any part of its name matches the substring. For example, 'xyz' matches both 'xyzabc' and 'abcxyz.' To return all bot channel associations, use a hyphen ('-') as the nameContains parameter.

    :rtype: dict
    :return: {
        'botChannelAssociations': [
            {
                'name': 'string',
                'description': 'string',
                'botAlias': 'string',
                'botName': 'string',
                'createdDate': datetime(2015, 1, 1),
                'type': 'Facebook'|'Slack'|'Twilio-Sms',
                'botConfiguration': {
                    'string': 'string'
                }
            },
        ],
        'nextToken': 'string'
    }

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

    """
    pass


def channel_squeeze(x, groups):
    """
    Channel squeeze operation.

    Parameters:
    ----------
    x : Tensor
        Input tensor.
    groups : int
        Number of groups.

    Returns
    -------
    Tensor
        Resulted tensor.
    """
    batch, channels, height, width = x.size()
    channels_per_group = channels // groups
    x = x.view(batch, channels_per_group, groups, height, width).sum(dim=2)
    return x


def _str_or_false(x):
    """
    Returns a boolean False if x is the string "False" or similar.
    Returns the original string otherwise.
    """
    if x.lower() == 'false':
        x = False
    return x


def freestyle_lineset_remove():
    """Remove the active line set from the list of line sets

    """
    pass


def chi_eff(mass1, mass2, spin1z, spin2z):
    """Returns the effective spin from mass1, mass2, spin1z, and spin2z."""
    return (spin1z * mass1 + spin2z * mass2) / (mass1 + mass2)


@classmethod
def commit(cls, client=None):
    """Commit everything from datapoints via the client.

        :param client: InfluxDBClient instance for writing points to InfluxDB.
        :attention: any provided client will supersede the class client.
        :return: result of client.write_points.
        """
    if not client:
        client = cls._client
    rtn = client.write_points(cls._json_body_(), time_precision=cls.
        _time_precision, retention_policy=cls._retention_policy)
    cls._reset_()
    return rtn


def downsample_actor(actor, fact=0.5):
    """
    Reduce resolution of actor

    :param actor:
    :param fact:  (Default value = 0.5)

    """
    actor.decimate(fraction=fact)


def _status_as_tuple(status):
    """Translate a status into a tuple of user, context, state"""
    creator = status.get('creator')
    if not creator:
        user = 'Unknown'
    else:
        user = creator.get('login')
    context = status.get('context')
    state = status.get('state')
    return user, context, state


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 get_supported_lang():
    """Get a list of the model programming languages that are supported
    by yggdrasil.

    Returns:
        list: The names of programming languages supported by yggdrasil.

    """
    from yggdrasil import schema
    s = schema.get_schema()
    out = s['model'].subtypes
    if 'c++' in out:
        out[out.index('c++')] = 'cpp'
    if 'r' in out:
        out[out.index('r')] = 'R'
    return list(set(out))


def dag_s3_prefix(dag_id, timestamp):
    """Define the prefix that will be prepended to all files created by this dag run"""
    return '{}/{}'.format(dag_id, timestamp)


def _hashable(x):
    """ ensure that an point is hashable by a python dict """
    return tuple(map(float, x))


def p_group_non_capture(p):
    """character : group"""
    p[0] = [('non_capture', (p[1],))]


def choose_pack_transaction(pack_point):
    """Return the transaction before or at the specified pack time.

        Returns None if there is nothing to pack.
        """


def freestyle_module_open(filepath: str='', make_internal: bool=True):
    """Open a style module file

    :param filepath: filepath
    :type filepath: str
    :param make_internal: Make internal, Make module file internal after loading
    :type make_internal: bool
    """
    pass


def polynomial(voltage, order=50):
    """Generate the polynomial I-V curve model.

    From Kennedy (1999) [see full references in online docs].

    Args:
        voltage (ndarray): normalized bias voltage
        order (float): order of polynomial (usually between 30 and 50)

    Returns:
        ndarray: normalized current

    """
    current = voltage ** (2 * order + 1) / (1 + voltage ** (2 * order))
    return current


@staticmethod
def get_dayofweek(row):
    """Get day of the week from date"""
    x = row['date']
    try:
        return x.dayofweek
    except Exception as e:
        return 0


def mos_repr_int(i: int) ->str:
    """ Get the Mosel source code representation of an int, without type or bound checking. """
    return repr(i)


@staticmethod
def page_download_finish(bar, files, fs):
    """Callback functions for page_download_task futures, assigning the
        resulting filehandles to the right index in the array and updating
        the progress bar.
        """
    index, f = fs.result()
    files[index] = f
    bar.update(1)


def get_aws_describe_function(node):
    """Describe function for the node using python reflection mechanism"""
    describe_fn_str = None
    if node and 'type' in node and node['type']:
        describe_fn_str = 'describe_%s' % node['type']
    return describe_fn_str


def read_numpy(fh, byteorder, dtype, count, offsetsize):
    """Read tag data from file and return as numpy array."""
    dtype = 'b' if dtype[-1] == 's' else byteorder + dtype[-1]
    return fh.read_array(dtype, count)


@staticmethod
def is_valid_name_start(char):
    """
        Checks whether a character token is a valid start of a name
        """
    return char.isalpha() or char == '_'


def adapt_timedelta(value):
    """Convert datetime.timedelta to %H:%M:%S string."""
    hours, remainder = divmod(value.total_seconds(), 3600)
    minutes, seconds = divmod(remainder, 60)
    return '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))


def bvshl(a, b):
    """
    Shift left: a << b
    """
    return '(bvshl {} {})'.format(a, b)


def update(checksum=None):
    """Store checksum.  If not given, I will calculate() myself.
        """


@staticmethod
def lg2(x):
    """Second Legendre polynomial"""
    return (3 * x * x - 1) / 2


def broadcast_equal(lhs=None, rhs=None, out=None, name=None, **kwargs):
    """Returns the result of element-wise **equal to** (==) comparison operation with broadcasting.

    Example::

       x = [[ 1.,  1.,  1.],
            [ 1.,  1.,  1.]]

       y = [[ 0.],
            [ 1.]]

       broadcast_equal(x, y) = [[ 0.,  0.,  0.],
                                [ 1.,  1.,  1.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_logic.cc:L46

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

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

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


def needs_reversal(chain):
    """
    Determine if the chain needs to be reversed.

    This is to set the chains such that they are in a canonical ordering

    Parameters
    ----------
    chain : tuple
        A tuple of elements to treat as a chain

    Returns
    -------
    needs_flip : bool
        Whether or not the chain needs to be reversed
    """
    x = len(chain)
    if x == 1:
        first = 0
        second = 0
    else:
        q, r = divmod(x, 2)
        first = q - 1
        second = q + r
    while first >= 0 and second < len(chain):
        if chain[first] > chain[second]:
            return True
        elif chain[first] == chain[second]:
            first -= 1
            second += 1
        else:
            return False
    return False


def claim(offer_did=None, _data=None, **kwargs):
    """Claim a data access offer.

    Args:
        offer_did (str): DID of the offer that is being claimed.
        _data (dict): metadata proving the value exchange. Follows the format
            of the `OfferClaim` model.
    """
    pass


def lin_interpol(y12, x12, x):
    """
    Return linear interpolation between two support points.

    Args:
        :y12: (tuple) y1 and y2 value
        :x12: (tuple) x1 and x2 value
        :x: (float) position for which to return the interpolation

    Returns:
        :y_x: (float) linearly interpolated y(x)
    """
    return y12[0] + (y12[1] - y12[0]) / (x12[1] - x12[0]) * (x - x12[0])


def unique(items):
    """Yield items from *item* in order, skipping duplicates."""
    seen = set()
    for item in items:
        if item in seen:
            continue
        else:
            yield item
            seen.add(item)


def list_elasticsearch_instance_types(ElasticsearchVersion=None, DomainName
    =None, MaxResults=None, NextToken=None):
    """
    List all Elasticsearch instance types that are supported for given ElasticsearchVersion
    See also: AWS API Documentation

    :example: response = client.list_elasticsearch_instance_types(
        ElasticsearchVersion='string',
        DomainName='string',
        MaxResults=123,
        NextToken='string'
    )

    :type ElasticsearchVersion: string
    :param ElasticsearchVersion: [REQUIRED]
            Version of Elasticsearch for which list of supported elasticsearch instance types are needed.

    :type DomainName: string
    :param DomainName: DomainName represents the name of the Domain that we are trying to modify. This should be present only if we are querying for list of available Elasticsearch instance types when modifying existing domain.

    :type MaxResults: integer
    :param MaxResults: Set this value to limit the number of results returned. Value provided must be greater than 30 else it wont be honored.

    :type NextToken: string
    :param NextToken: NextToken should be sent in case if earlier API call produced result containing NextToken. It is used for pagination.

    :rtype: dict
    :return: {
        'ElasticsearchInstanceTypes': [
            'm3.medium.elasticsearch'|'m3.large.elasticsearch'|'m3.xlarge.elasticsearch'|'m3.2xlarge.elasticsearch'|'m4.large.elasticsearch'|'m4.xlarge.elasticsearch'|'m4.2xlarge.elasticsearch'|'m4.4xlarge.elasticsearch'|'m4.10xlarge.elasticsearch'|'t2.micro.elasticsearch'|'t2.small.elasticsearch'|'t2.medium.elasticsearch'|'r3.large.elasticsearch'|'r3.xlarge.elasticsearch'|'r3.2xlarge.elasticsearch'|'r3.4xlarge.elasticsearch'|'r3.8xlarge.elasticsearch'|'i2.xlarge.elasticsearch'|'i2.2xlarge.elasticsearch'|'d2.xlarge.elasticsearch'|'d2.2xlarge.elasticsearch'|'d2.4xlarge.elasticsearch'|'d2.8xlarge.elasticsearch'|'c4.large.elasticsearch'|'c4.xlarge.elasticsearch'|'c4.2xlarge.elasticsearch'|'c4.4xlarge.elasticsearch'|'c4.8xlarge.elasticsearch'|'r4.large.elasticsearch'|'r4.xlarge.elasticsearch'|'r4.2xlarge.elasticsearch'|'r4.4xlarge.elasticsearch'|'r4.8xlarge.elasticsearch'|'r4.16xlarge.elasticsearch',
        ],
        'NextToken': 'string'
    }

    :returns:
    (string) --

    """
    pass


@classmethod
def start_recording_skipped(cls):
    """
        Start collecting OptionErrors for all skipped options recorded
        with the record_skipped_option method
        """
    cls._errors_recorded = []


def get_topic_name(lambda_name):
    """ Topic name generation """
    return '%s-zappa-async' % lambda_name


def getArguments(parser):
    """Provides additional validation of the arguments collected by argparse."""
    return parser.parse_args()


def no_of_elements(mesh):
    """
    Calculate the number of elements contained in the given mesh.

    Parameters
    ----------
    mesh : dict
        mesh dict containing
        at least the following keyword
            elements : dict of ndarrays
                Contains array of nodes for elements sorted by element types.

    Returns
    -------
    result : int
        number of elements
    """
    no_elem = 0
    for elem in mesh['elements']:
        no_elem += mesh['elements'][elem].shape[0]
    return no_elem


def _fspath(path):
    """Return the path representation of a path-like object.

    If str or bytes is passed in, it is returned unchanged. Otherwise the
    os.PathLike interface is used to get the path representation. If the
    path representation is not str or bytes, TypeError is raised. If the
    provided path is not str, bytes, or os.PathLike, TypeError is raised.
    """
    if isinstance(path, (str, bytes)):
        return path
    path_type = type(path)
    try:
        path_repr = path_type.__fspath__(path)
    except AttributeError:
        if hasattr(path_type, '__fspath__'):
            raise
        else:
            raise TypeError(
                'expected str, bytes or os.PathLike object, not ' +
                path_type.__name__)
    if isinstance(path_repr, (str, bytes)):
        return path_repr
    else:
        raise TypeError(
            'expected {}.__fspath__() to return str or bytes, not {}'.
            format(path_type.__name__, type(path_repr).__name__))