def fromBasicServiceEndpoint(cls, endpoint):
    """Create a new instance of this class from the endpoint
        object passed in.

        @return: None or OpenIDServiceEndpoint for this endpoint object"""
    type_uris = endpoint.matchTypes(cls.openid_type_uris)
    if type_uris and endpoint.uri is not None:
        openid_endpoint = cls()
        openid_endpoint.parseService(endpoint.yadis_url, endpoint.uri,
            endpoint.type_uris, endpoint.service_element)
    else:
        openid_endpoint = None
    return openid_endpoint


def two_level_split(line, sep=' ', quote='"'):
    """Split a line by sep.

    The line may optionally contains fields that are quoted by the quote sign.
    """
    in_quotes = False
    results = []
    temp = []
    for field in line.split(sep):
        if not field:
            temp.append(field) if in_quotes else results.append(field)
            continue
        if in_quotes:
            if field[0] == quote:
                raise ValueError(f"Non-matching `{quote}' quote: {line}")
            elif field[-1] == quote:
                temp.append(field.strip(quote))
                results.append(sep.join(temp))
                temp = []
                in_quotes = False
            else:
                temp.append(field)
        elif field[0] == quote:
            if field[-1] == quote:
                results.append(field.strip(quote))
            else:
                in_quotes = True
                temp.append(field.strip(quote))
        elif field[-1] == quote:
            raise ValueError(f"Non-matching `{quote}' quote: {line}")
        else:
            results.append(field)
    return results


@classmethod
def getcwd(cls):
    """Returns an instance representing the working directory."""
    if cls._wd is None:
        cls._wd = cls('/')
    return cls._wd


def isPow2(val):
    """
    Returns True if val is a power of 2
    val     - Integer
    """
    return val & val - 1 == 0


def compare_strings(old_string, new_string):
    """Splits a string by spaces, and compares the lists. Then, returns a dictionary containing the following results:

    `equal` is a list of words in common.

    `removed` is a list of words that ARE in old_string, but ARE NOT in new_string.

    `added` is a list of words that ARE NOT in old_string, but ARE in new_string.
    """
    old_string = old_string.split(' ')
    new_string = new_string.split(' ')
    equal_words = list(set(old_string).intersection(new_string))
    removed_words = list(set(old_string) - set(new_string))
    added_words = list(set(new_string) - set(old_string))
    return {'equal': equal_words, 'removed': removed_words, 'added':
        added_words}


def is_categorical(s, column=None):
    """Check if a pandas Series or a column in a DataFrame is categorical.

    s (pandas.Series or pandas.DataFrame): Series to check or dataframe with
        column to check.
    column (str): Column name. If a column name is given it is assumed that
        `s` is a `pandas.DataFrame`.
    """
    if column is not None:
        s = s[column]
    return s.dtype.name == 'category'


def expand_board(b):
    """
    Converts a 1D list to 2D.
    """
    assert len(b) == 9
    return [b[0:3], b[3:6], b[6:9]]


@classmethod
def run_hooks(cls, hook_type, *args, **kwargs):
    """Run all hooks of specified type.

        :param cls: class that registers hooks
        :param hook_type: hook type, e.g., '__pre_parse_args__'
        :param args: args to be passed to every hook function
        :param kwargs: kwargs to be passed to every hook function
        """
    hook_funcs = cls._hooks_map.get(hook_type) or []
    for hook_func in hook_funcs:
        hook_func(*args, **kwargs)


def delocalize_uncompressed_verts(uncomp_verts, local_nodes):
    """TODO: Update this function to also work on parsed vert data."""
    local_node_ct = len(local_nodes)
    for i in range(57, len(uncomp_verts), 68):
        if uncomp_verts[i] < local_node_ct:
            uncomp_verts[i] = local_nodes[uncomp_verts[i]]
        i += 2
        if uncomp_verts[i] < local_node_ct:
            uncomp_verts[i] = local_nodes[uncomp_verts[i]]


def _move_project_display_message_prelude(project_name, old_path, new_path):
    """ Summary for moving project

    :param old_path: (str)
    :param new_path: (str)
    :return:
    """
    print('MOVE:\tMove project to new location')
    print(' Old project root directory:\t%s' % old_path.replace(
        project_name, ''))
    print(' New project root directory:\t%s' % new_path)


@staticmethod
def normalize_locale(locale):
    """
        Normalize locale
        Extracts language code from passed in locale string to be used later
        for dictionaries loading.

        :param locale:          string, locale (en, en_US)
        :return:                string, language code
        """
    import re
    match = re.match('^[a-z]+', locale.lower())
    if match:
        return match.group()


def monitor_worker_ok(**kw):
    """监控系统监测worker status
    """
    if not kw.get('web_ip', ''):
        raise ValueError(950, u'请求ip不能为空')


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

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

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


def select_more():
    """Select keys linked to boundary selected keys of each particle

    """
    pass


def remove_security_group(nova, vm, security_group):
    """
    Removes a security group from an existing VM
    :param nova: the nova client
    :param vm: the OpenStack server object (VM) to alter
    :param security_group: the SNAPS SecurityGroup domain object to add
    """
    nova.servers.remove_security_group(str(vm.id), security_group.name)


def minmax(dates):
    """Returns an iso8601 daterange string that represents the
       min and max datemap.values().

    Args:
        datestrings: [d1, d2, d3,]

    Returns:
        ['min_date/max_date',]

    Example:
        >>> minmax(['2008-01-01', '2010-01-01', '2009-01-01'])
        "2008-01-01/2010-01-01"
    """
    return '{}/{}'.format(min(dates), max(dates)) if dates else '/'


@classmethod
def for_frame(cls, frame):
    """
        Returns the `Source` object corresponding to the file the frame is executing in.
        """
    return cls.for_filename(frame.f_code.co_filename, frame.f_globals or {})


def compound_interest(capital, iterations, interest_rate):
    """Computes compound interest
    >>> print(compound_interest(100, 3, 9.1))
    [109.1, 228.1281, 357.9877571]
    """
    results = []
    cummulative_total = 0
    for i in range(0, iterations):
        cummulative_total += capital
        cummulative_total *= interest_rate / 100 + 1
        results.append(cummulative_total)
    return results


@classmethod
def make_public(cls, public_value, application):
    """Construct a U2F Ed25519 public key"""
    return cls(public_value, application)


def to_bytes(value, encoding='utf8'):
    """
    cast string to bytes() like object, but for python2 support it's bytearray copy
    """
    if isinstance(value, bytes):
        return value
    if isinstance(value, str):
        return value.encode(encoding)
    elif isinstance(value, bytearray):
        return bytes(value)
    else:
        raise TypeError('Not a string or bytes like object')


def CRI(val):
    """CorrectedRepublishedIn"""
    return val


def p_track_flag_pre_emphasis(t):
    """track_flag : PRE_EMPHASIS"""
    from audiotools.toc import TOCFlag_PRE_EMPHASIS
    t[0] = TOCFlag_PRE_EMPHASIS(True)


@staticmethod
def _mutate_label(label: str) ->str:
    """
        Most engines support mixed case aliases that can include numbers
        and special characters, like commas, parentheses etc. For engines that
        have restrictions on what types of aliases are supported, this method
        can be overridden to ensure that labels conform to the engine's
        limitations. Mutated labels should be deterministic (input label A always
        yields output label X) and unique (input labels A and B don't yield the same
        output label X).

        :param label: Preferred expression label
        :return: Conditionally mutated label
        """
    return label


def _suffix_rules(token, tag='NN'):
    """ Default morphological tagging rules for English, based on word suffixes.
    """
    if isinstance(token, (list, tuple)):
        token, tag = token
    if token.endswith('ing'):
        tag = 'VBG'
    if token.endswith('ly'):
        tag = 'RB'
    if token.endswith('s') and not token.endswith(('is', 'ous', 'ss')):
        tag = 'NNS'
    if token.endswith(('able', 'al', 'ful', 'ible', 'ient', 'ish', 'ive',
        'less', 'tic', 'ous')) or '-' in token:
        tag = 'JJ'
    if token.endswith('ed'):
        tag = 'VBN'
    if token.endswith(('ate', 'ify', 'ise', 'ize')):
        tag = 'VBP'
    return [token, tag]


@classmethod
def getTablesByName(cls, elem, name):
    """
		Return a list of Table elements named name under elem.  See
		also .get_table().
		"""
    name = cls.TableName(name)
    return elem.getElements(lambda e: e.tagName == cls.tagName and e.Name ==
        name)


@classmethod
def get_real_child_model(cls, data):
    """Returns the real base class specified by the discriminator"""
    discriminator_value = data[cls.json_discriminator_key]
    return cls.discriminator_value_class_map.get(discriminator_value)


@staticmethod
def binary_edits_update_single(blendfile_abs, binary_edits, remap_filepath_cb):
    """
        After committing a blend file, we need to re-create the binary edits.
        """
    from bam.blend import blendfile_path_walker
    for fp, (rootdir, fp_blend_basename
        ) in blendfile_path_walker.FilePath.visit_from_blend(blendfile_abs,
        readonly=True, recursive=False):
        f_rel_orig = fp.filepath
        f_rel = remap_filepath_cb(f_rel_orig)
        fp.filepath_assign_edits(f_rel, binary_edits)


def explode_refresh(modifier: str=''):
    """Refresh data in the Explode modifier

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


@classmethod
def protocolHandlerManager(cls):
    """
        Class method to get a reference to the protocol handler manager.

        @return reference to the protocol handler manager
        @rtype ProtocolHandlerManager
        """
    if cls._protocolHandlerManager is None:
        from .Network.ProtocolHandlerManager import ProtocolHandlerManager
        cls._protocolHandlerManager = ProtocolHandlerManager()
    return cls._protocolHandlerManager


@classmethod
def from_dict(cls, dictionary):
    """
        Method for populating a SimObject from a dictionary.

        :param cls: Class to be instantiated.
        :param dict: Dictionary containing attribute data.
        :return: Instance of cls.
        """
    instance = cls()
    for key, value in dictionary.items():
        instance.__dict__[key] = value
    return instance


def ARGMAX(agg_column, out_column):
    """
  Builtin arg maximum aggregator for groupby

  Example: Get the movie with maximum rating per user.

  >>> sf.groupby("user",
  ...            {'best_movie':gl.aggregate.ARGMAX('rating','movie')})
  """
    return '__builtin__argmax__', [agg_column, out_column]


def get_roster(game_json):
    """
    Parse the roster info in the game json

    :param game_json: Json of all the info for a game

    :return: Dict: Key = Player id, Value = Name
    """
    players = {}
    for player in game_json['roster_player']:
        players[player['id']] = ' '.join([player['first_name'].strip(),
            player['last_name'].strip()])
    return players


def codestream_base(name):
    """
    Returns base of a codestream, without servicepack info.
    """
    if not (name.startswith('SLE-') or name.startswith('OES-')):
        return name
    separator = name.find('-', 4)
    if separator == -1:
        return name
    return name[:separator]


def update(seq):
    """Add the items from the given sequence to the set."""


def split_command_from_target(bot_username: str, command: (str or None)) ->(str
    , str):
    """
    Determines the command target bot username
    :param bot_username: the username of this bot
    :param command: the command to check
    :return: (the command, the username of the targeted bot)
    """
    target = bot_username
    if command is None or len(command) <= 0:
        return command, target
    if '@' in command:
        command, target = command.split('@', 1)
    return command, target


def remote(fn, name=None, types=None):
    """Decorator that adds a remote attribute to a function.

    fn -- function being decorated
    name -- aliased name of the function, used for remote proxies
    types -- a argument type specifier, can be used to ensure
             arguments are of the correct type
    """
    if not name:
        name = fn.__name__
    fn.remote = {'name': name, 'types': types}
    return fn


def _union(sets):
    """
    Returns a union of sets.
    """
    union = set()
    for s in sets:
        union |= s
    return union


def modifiedaminoacids(df):
    """
    Calculate the number of modified amino acids in supplied ``DataFrame``.

    Returns the total of all modifications and the total for each amino acid individually, as an ``int`` and a
    ``dict`` of ``int``, keyed by amino acid, respectively.

    :param df: Pandas ``DataFrame`` containing processed data.
    :return: total_aas ``int`` the total number of all modified amino acids
             quants ``dict`` of ``int`` keyed by amino acid, giving individual counts for each aa.
    """
    amino_acids = list(df['Amino acid'].values)
    aas = set(amino_acids)
    quants = {}
    for aa in aas:
        quants[aa] = amino_acids.count(aa)
    total_aas = len(amino_acids)
    return total_aas, quants


def subtreeFilter(node):
    """Return True or False to determine whether to expand the given
        (folderish) node
        """


def endswithoneof(inputstr, seq):
    """
    Check if *inputstr* ends with one of the items in seq. If it does, return
        the item that it ends with. If it doe not, return ``None``.

    :param inputstr: input string

    :param seq: sequences of items to check

    :return: the item the the input string ends with (``None`` if not found)

    :rtype: str or None
    """
    seq = set(seq)
    for item in seq:
        if inputstr.endswith(item):
            return item
    else:
        return None


def FormatDescriptorToPython(i):
    """
    Format a descriptor into a form which can be used as a python attribute

    example::

        >>> FormatDescriptorToPython('(Ljava/lang/Long; Ljava/lang/Long; Z Z)V')
        'Ljava_lang_LongLjava_lang_LongZZV

    :param i: name to transform
    :rtype: str
    """
    i = i.replace('/', '_')
    i = i.replace(';', '')
    i = i.replace('[', '')
    i = i.replace('(', '')
    i = i.replace(')', '')
    i = i.replace(' ', '')
    i = i.replace('$', '')
    return i


def _migrate_same_as_structure(data, client):
    """Changes sameAs string to schema:URL object."""
    same_as = data.get('same_as')
    if same_as and isinstance(same_as, str):
        data['same_as'] = {'@type': ['schema:URL'], 'url': same_as}
        if data.get('@context'):
            data['@context'].setdefault('same_as', {'@id': 'schema:sameAs',
                '@type': 'schema:URL', '@context': {'@version': '1.1',
                'url': 'schema:url', 'schema': 'http://schema.org/'}})
    return data


def _rfc822_escape(header):
    """Return a version of the string escaped for inclusion in an
    RFC-822 header, by ensuring there are 8 spaces space after each newline.
    """
    lines = header.split('\n')
    header = ('\n' + 8 * ' ').join(lines)
    return header


def key_description(character):
    """generate a readable description for a key"""
    ascii_code = ord(character)
    if ascii_code < 32:
        return 'Ctrl+{:c}'.format(ord('@') + ascii_code)
    else:
        return repr(character)


def get_setup(job=None):
    """
    Return the resource specific setup.

    :param job: optional job object.
    :return: setup commands (list).
    """
    return []


def get_startmenu():
    """get start menu location"""
    return ''


def log_this_request():
    """Instructs uWSGI to log current request data.

    :rtype: None
    """


def get_all(isdsAppliance, check_mode=False, force=False):
    """
    Retrieving all interfaces
    :rtype: (str, dict)
    """
    return isdsAppliance.invoke_get('Retrieving all interfaces',
        '/widgets/mgmtinterface')


def _pandas_sort_post_017(df, by, *args, **kwargs):
    """
    Use sort_values() to sort a DataFrame
    This raises a ValueError if the given value is both
    a column and an index label, i.e.:
    ValueError: 'frame' is both an index level and a column
    label, which is ambiguous.
    Because we usually sort by columns, we can rename
    the index to supress the ValueError.
    """
    if df.index.name is not None and df.index.name in by:
        df.index.name += '_index'
    return df.sort_values(*args, by=by, **kwargs)


def server_url(server_name, download=False):
    """Determine the server URL to download packages from."""
    server_name = server_name.lower()
    if server_name in ['testpypi', 'pypitest']:
        if download:
            return 'https://test.pypi.org/simple'
        else:
            return 'https://test.pypi.org/legacy/'
    elif server_name in ['pypi']:
        return 'https://pypi.org/pypi'


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 function_supporting_step(step):
    """function_supporting_step

    This function demonstrate the use of steps within function APIs. This
    enables smaller breakdown of functions into smaller steps, and thus provides
    finer granuality in your testscript logs.

    Arguments
    ---------
        steps   (obj): the step object to be passed in from the testscript

    """
    with step.start('function step one'):
        pass
    with step.start('function step two'):
        pass
    with step.start('function step three'):
        pass
    return


@classmethod
def concat(cls, tables):
    """Returns new Table object with data from list of Table objects.
		Columns are the same as in the first table.
		Other table must have at least the same columns."""
    res = tables[0].copy()
    for el in tables[1:]:
        for i in range(el.rowcnt):
            res.add_row(el.row_named(i))
    res.title = 'Concat'
    return res


@staticmethod
def _get_status(image):
    """Update the status field to standardize format."""
    return {'active': 'ACTIVE', 'queued': 'SAVING', 'saving': 'SAVING',
        'deleted': 'DELETED', 'pending_delete': 'DELETED', 'killed': 'ERROR'
        }.get(image.get('status'), 'UNKNOWN')


def describe_cache(GatewayARN=None):
    """
    Returns information about the cache of a gateway. This operation is only supported in the cached volume,tape and file gateway architectures.
    The response includes disk IDs that are configured as cache, and it includes the amount of cache allocated and used.
    See also: AWS API Documentation

    Examples
    Returns information about the cache of a gateway.
    Expected Output:

    :example: response = client.describe_cache(
        GatewayARN='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.

    :rtype: dict
    :return: {
        'GatewayARN': 'string',
        'DiskIds': [
            'string',
        ],
        'CacheAllocatedInBytes': 123,
        'CacheUsedPercentage': 123.0,
        'CacheDirtyPercentage': 123.0,
        'CacheHitPercentage': 123.0,
        'CacheMissPercentage': 123.0
    }

    """
    pass


@staticmethod
def _reduce(res, result_single_frame):
    """ 'add' action for an accumulator"""
    if isinstance(res, list) and len(res) == 0:
        res = result_single_frame
    else:
        res += result_single_frame
    return res


def palettecolor_lock_all():
    """Lock all Grease Pencil colors to prevent them from being accidentally modified

    """
    pass


def get_numbers(scards):
    """
    Return dictionary with keys -- number types and values -- list of numbers
    used in the input file.
    """
    r = {}
    for c in scards:
        for v, t in c.values:
            if t not in r:
                r[t] = []
            r[t].append(v)
    return r


@classmethod
def from_dict(cls, database_dict):
    """
        Given a dict, which contains the database config, this method will create and return a new DatabaseConfig
        object from it.
        The dict can contain any subset of the following keys, every key not used it substituted with the default item:
        - engine
        - host
        - database
        - port
        - user
        - password

        CHANGELOG

        Added 09.06.2019

        :param database_dict:
        :return:
        """
    argument_dict = cls.DEFAULT_DICT
    argument_dict.update(database_dict)
    return cls(**argument_dict)


def probs(pct):
    """
    Return a human-readable string representing the probabilities.

    This scheme is shamelessly ripped from CIA's Words of Estimative
    Probability.

    https://www.cia.gov/library/center-for-the-study-of-intelligence/csi-publications/books-and-monographs/sherman-kent-and-the-board-of-national-estimates-collected-essays/6words.html

    100%                Certainty
    93%     +/- ~6%     Almost certain
    75%     +/- ~12%    Probable
    50%     +/- ~10%    Chances about even
    30%     +/- ~10%    Probably not
    7%      +/- ~5%     Almost certainly not
    0%                  Impossibility
    """
    pct = int(pct * 100)
    if pct == 100:
        return 'certain'
    if pct > 87:
        return 'almost certain'
    if pct > 63:
        return 'probable'
    if pct > 40:
        return 'about even'
    if pct > 20:
        return 'probably not'
    if pct > 2:
        return 'almost certainly not'
    return 'an impossibility'


def detail_flood_fill():
    """Flood fill the mesh with the selected detail setting

    """
    pass


def wavelength(frequency, speed=343.2):
    """Calculate the wavelength l of frequency f given the speed (of sound)"""
    l = speed / frequency
    return l


def material_slot_remove():
    """Remove the selected material slot

    """
    pass


def _excel2num(x):
    """
    Convert Excel column name like 'AB' to 0-based column index.

    Parameters
    ----------
    x : str
        The Excel column name to convert to a 0-based column index.

    Returns
    -------
    num : int
        The column index corresponding to the name.

    Raises
    ------
    ValueError
        Part of the Excel column name was invalid.
    """
    index = 0
    for c in x.upper().strip():
        cp = ord(c)
        if cp < ord('A') or cp > ord('Z'):
            raise ValueError(f'Invalid column name: {x}')
        index = index * 26 + cp - ord('A') + 1
    return index - 1


def BayesianGaussianMixture(V, **kwargs):
    """Performs clustering on *V* by using Gaussian mixture models with variational inference. The function uses :func:`sklearn.micture.GaussianMixture`. See sklearn documents
    for details.

    :arg V: row-normalized eigenvectors for the purpose of clustering.
    :type V: :class:`numpy.ndarray`

    :arg n_clusters: specifies the number of clusters.
    :type n_clusters: int
    """
    try:
        from sklearn.mixture import BayesianGaussianMixture
    except ImportError:
        raise ImportError(
            'Use of this function (BayesianGaussianMixture) requires the installation of sklearn.'
            )
    n_components = kwargs.pop('n_components', None)
    if n_components == None:
        n_components = kwargs.pop('n_clusters', None)
        if n_components == None:
            n_components = 1
    n_init = kwargs.pop('n_init', 1)
    mixture = BayesianGaussianMixture(n_init=n_init, **kwargs).fit(V)
    return mixture.fit_predict(V)


def insert_commands() ->dict:
    """Lists the available sub-commands of the 'chado insert' command with corresponding descriptions"""
    return {'organism': 'insert an organism into the CHADO database'}


def man_escape(string):
    """Escapes strings for man page compatibility"""
    result = string.replace('\\', '\\\\')
    result = result.replace('`', "\\'")
    result = result.replace("'", '\\*(Aq')
    result = result.replace('-', '\\-')
    return result


def parse_line(data):
    """ Takes an IRC line and breaks it into the three main parts; the prefix,
    command, and parameters. It gets returned in the form of
    ``(prefix, command, params)``.
    This follows :rfc:`2812#section-2.3.1`, section 2.3.1 regarding message
    format.

        >>> message = ":nickname!myuser@myhost.net PRIVMSG #gerty :Hello!"
        >>> parse_line(message)
        ('nickname!myuser@myhost.net', 'PRIVMSG', ['#gerty', 'Hello!'])
    """
    if data[0] == ':':
        prefix, data = data[1:].split(' ', 1)
    else:
        prefix = None
    if ' :' in data:
        data, trailing = data.split(' :', 1)
        params = data.split()
        params.append(trailing)
    else:
        params = data.split()
    return prefix, params[0], params[1:]


def _datetime_to_str(dt):
    """Convert datetime object to camtasia lastMod format.

    <year><month><day>T<hour><minute><second>, e.g. 20190606T103830
    """
    return (
        f'{dt.year}{dt.month:02}{dt.day:02}T{dt.hour:02}{dt.minute:02}{dt.second:02}'
        )


def register_home(route):
    """Registers UI home page"""
    global _home
    _home = route


def find_overlap_tx(read_block, bed_df, ignore_strand=True):
    """
    The function use read_block to find which transcripts in bed_df overlaps with the range of introns in the read.
    Return the overlapped transcript index.
    """
    bed_df = bed_df[bed_df['chrom'] == read_block.chrom]
    if not ignore_strand:
        bed_df = bed_df[bed_df['strand'] == read_block.strand]
    left_flag = bed_df['end'] > min(read_block.introns['intron_starts'])
    right_flag = bed_df['start'] < max(read_block.introns['intron_ends'])
    tx_i = bed_df[left_flag & right_flag].index
    return tx_i


def add_mixin_to_class(basecls, mixins):
    """
    Given a class, adds the provided mixin classes as base classes and gives a new class

    :param Type basecls: An initial class to generate a new class from
    :param List[Type] mixins: A list of mixins to add as base classes
    :return: A new class with the provided mixins as base classes
    :rtype: Type[basecls, *mixins]
    """
    if not any(mixins):
        return basecls
    base_dict = basecls.__dict__.copy()
    class_tuple = basecls,
    for mixin in mixins:
        if not mixin:
            continue
        mixin_dict = mixin.__dict__.copy()
        base_dict.update(mixin_dict)
        class_tuple = class_tuple + (mixin,)
    base_dict.update(basecls.__dict__)
    return type(basecls.__name__, class_tuple, base_dict)


def starmap(function, argument_list):
    """Apply a univariate function to a list of arguments in a serial fashion.

    Uses the starmap() function from itertools in Python's standard library and
    Python's built-in zip() function.

    Args:
        function: A callable object that accepts one argument
        argument_list: An iterable object of input arguments

    Returns:
        List of output results

    Example:
        >>> def square(x):
        ...     return x**2
        ...
        >>> starmap(square, [1, 2, 3, 4, 5])
        [1, 4, 9, 16, 25]

    References:
        - https://docs.python.org/3/library/itertools.html#itertools.starmap
    """
    from itertools import starmap as _starmap
    iterator = _starmap(function, zip(argument_list))
    result_list = list(iterator)
    return result_list


def unix_time_from_uuid1(uuid_arg):
    """
    Converts a version 1 :class:`uuid.UUID` to a timestamp with the same precision
    as :meth:`time.time()` returns.  This is useful for examining the
    results of queries returning a v1 :class:`~uuid.UUID`.

    :param uuid_arg: a version 1 :class:`~uuid.UUID`
    """
    return (uuid_arg.time - 122192928000000000) / 10000000.0


def customdata_custom_splitnormals_clear():
    """Remove the custom split normals layer, if it exists

    """
    pass


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

        :param SfAllowNonMembersToViewSharedLinksDetails val:
        :rtype: EventDetails
        """
    return cls('sf_allow_non_members_to_view_shared_links_details', val)


@staticmethod
def _get_subject_mapping(subject):
    """
        Get the Jira value mapping for the subject field.

        :param subject: Issue subject
        :return: Jira value mapping for the subject
        """
    return subject


def _empty_2d_array(shape, initial_value=0):
    """
    Return a (list of rows) array of given shape, filled with some value.

    Args:
        shape (tuple): A (n_rows, n_cols) tuple.
        initial_value: The same value will be used in all cells.

    Returns:
        a (list): Array of given shape filled with the same value. Can index with z[row][col].
    """
    n_rows, n_cols = shape[0], shape[1]
    a = [[initial_value for _ in range(n_cols)] for _ in range(n_rows)]
    return a


@staticmethod
def _TransformResponseDict(resp_dict):
    """Transform the response from stats.nba.com
            The response from stats.nba.com is a JSON object. However,
            for efficiency the fields are not encoded as key-value pairs
            but rather separated as header and rowSets, which is not
            convenient for querying the attributes of the resultSets.
        """
    from .utils import convert_resultset
    resultSets = map(convert_resultset, resp_dict['resultSets'])
    resp_dict['resultSets'] = {}
    for name, data in resultSets:
        resp_dict['resultSets'][name] = data
    return resp_dict


def get_filename(url):
    """ Get the filename of a url """
    return url[url.rfind('/') + 1:]


def is_descriptor_schema(data):
    """Return ``True`` if passed object is DescriptorSchema and ``False`` otherwise."""
    return type(data).__name__ == 'DescriptorSchema'


def _parse_name(name, _standard_names=None):
    """
    Parses a column/row name.

    :param name:
        Name to be parsed.
    :type name: str

    :return:
        The parsed name.
    :rtype: str
    """
    if _standard_names and name in _standard_names:
        return _standard_names[name]
    return name.replace('_', ' ').capitalize()


def arrowRight(*argv):
    """
    Will print out to terminal using right arrows between each segment
    Example:
        arrowRight("hello", "world")

    Output:
        hello -> world
    """
    line = ''
    for arg in argv:
        line += f'{arg} -> '
    line = line[:-4]
    print(line)


def pre_submit(topology_name, env_name, env_config, options):
    """Override this function to perform custom actions prior to topology
    submission. No SSH tunnels will be active when this function is called."""
    pass


def create_miriam_json():
    """ Parses the latest miriam information.

    :return:
    """
    import xmlschema
    import json
    from pprint import pprint
    xs = xmlschema.XMLSchema('./resources/MiriamXML.xsd')
    d = xs.to_dict('./resources/IdentifiersOrg-Registry.xml')
    datatypes = {}
    for entry in d['datatype']:
        datatypes[entry['namespace']] = {'id': entry['@id'], 'pattern':
            entry['@pattern'], 'name': entry['name'], 'namespace': entry[
            'namespace'], 'definition': entry['definition']}
    with open('./resources/IdentifiersOrg-Registry.json', 'w') as fp:
        json.dump(datatypes, fp)


def __init(func):
    """Implements the equivalent of the GNU C __init initializer function.

    https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

    Decorator used to call functions upon importing the module.

    Positional arguments:
    func -- the decorated function object.

    Returns:
    The same function.
    """
    func()
    return func


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 unlink():
    """Unlink active font data-block

    """
    pass


def false_if_equal_filter(*value):
    """
    Returns 'false' if all values are equal, otherwise 'true'.
    """
    first = True
    eq = None
    for v in value:
        if first:
            eq = v
            first = False
            continue
        if eq != v:
            return True
    return False


def get_duration(name, instance):
    """
    Getter for Duration Property field.

    Handles correctly the conversion of of negative running duration (for more refer to the Toggl API doc).
    """
    if instance.is_running:
        return instance.start.int_timestamp * -1
    return int((instance.stop - instance.start).in_seconds())


def list_subtract(a, b):
    """Return a list ``a`` without the elements of ``b``.

    If a particular value is in ``a`` twice and ``b`` once then the returned
    list then that value will appear once in the returned list.
    """
    a_only = list(a)
    for x in b:
        if x in a_only:
            a_only.remove(x)
    return a_only


def brush_select(index: int=0):
    """Select a Grease Pencil drawing brush

    :param index: Index, Index of Drawing Brush
    :type index: int
    """
    pass


def add_n(*args, **kwargs):
    """Adds all input arguments element-wise.

    .. math::
       add\\_n(a_1, a_2, ..., a_n) = a_1 + a_2 + ... + a_n

    ``add_n`` is potentially more efficient than calling ``add`` by `n` times.

    The storage type of ``add_n`` output depends on storage types of inputs

    - add_n(row_sparse, row_sparse, ..) = row_sparse
    - add_n(default, csr, default) = default
    - add_n(any input combinations longer than 4 (>4) with at least one default type) = default
    - otherwise, ``add_n`` falls all inputs back to default storage and generates default storage

    Defined in src/operator/tensor/elemwise_sum.cc:L155

    Parameters
    ----------
    args : NDArray[]
        Positional input arguments

    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 rank_permutation(r, n):
    """Given r and n find the permutation of {0,..,n-1} with rank according to lexicographical order equal to r

       :param r n: integers with 0 ≤ r < n!
       :returns: permutation p as a list of n integers
       :beware: computation with big numbers
       :complexity: `O(n^2)`
    """
    fact = 1
    for i in range(2, n):
        fact *= i
    digits = list(range(n))
    p = []
    for i in range(n):
        q = r // fact
        r %= fact
        p.append(digits[q])
        del digits[q]
        if i != n - 1:
            fact //= n - 1 - i
    return p


def graph_statistics(node_frame, result=None):
    """
    Adds some information about the graph to the results.

    :param node_frame:
    :param result:
    :return:

    >>> pf = PixelFrame(np.array([[0, 0, 0],
    ...                           [1, 1, 1],
    ...                           [0, 0, 0]]), calibration=15.0)
    >>> sorted(graph_statistics(NodeFrame(pf)).items())
    [('graph_edge_count', 1.0), ('graph_edge_length', 30.0), ('graph_endpoint_count', 2), ('graph_junction_count', 0), ('graph_node_count', 2)]
    """
    graph_edge_length = node_frame.adjacency.sum() / 2
    graph_edge_count = node_frame.adjacency.nnz / 2
    graph_node_count = node_frame.adjacency.shape[0]
    graph_junction_count = len(node_frame.every_junction)
    graph_endpoint_count = len(node_frame.every_endpoint)
    return {'graph_edge_length': graph_edge_length * node_frame.calibration,
        'graph_edge_count': graph_edge_count, 'graph_node_count':
        graph_node_count, 'graph_junction_count': graph_junction_count,
        'graph_endpoint_count': graph_endpoint_count}


def msg_from_file(fp, fullParse=False, isBytes=False):
    """Read a file and parse its contents into a Message object model.
    Replacement for email.message_from_file().

    We use the HeaderParser subclass instead of Parser to avoid trying
    to parse the message body, instead setting the payload to the raw
    body as a string.  This is faster, and also helps us avoid
    problems trying to parse spam with broken MIME bodies."""
    from email.parser import Parser, HeaderParser, BytesParser, BytesHeaderParser
    parsers = (HeaderParser, Parser), (BytesHeaderParser, BytesParser)
    parser = parsers[int(isBytes)][int(fullParse)]
    return parser().parse(fp)


@classmethod
def next_conv_block(cls, inputs, layout, filters, bottleneck,
    resnext_factor, **kwargs):
    """ ResNeXt convolution block

        Parameters
        ----------
        inputs
            input tensor
        filters : int
            number of output filters
        bottleneck : bool
            whether to use a simple or a bottleneck block
        resnext_factor : int
            cardinality for ResNeXt model
        kwargs : dict
            `ConvBlock` parameters

        Returns
        -------
        nn.Module
        """
    if bottleneck:
        filters = filters * kwargs['bottleneck_factor']
        filters = [filters // 2, filters // 2, filters]
        kwargs['groups'] = [1, resnext_factor, 1]
    else:
        filters = [resnext_factor * 4, filters]
    x = cls.conv_block(inputs, layout, filters=filters, bottleneck=
        bottleneck, **kwargs)
    return x


def getObjects(request, conn=None):
    """
    Prepare objects for use in the annotation forms.
    These objects are required by the form superclass to populate hidden
    fields, so we know what we're annotating on submission
    """
    r = request.GET or request.POST
    images = len(r.getlist('image')) > 0 and list(conn.getObjects('Image',
        r.getlist('image'))) or list()
    datasets = len(r.getlist('dataset')) > 0 and list(conn.getObjects(
        'Dataset', r.getlist('dataset'))) or list()
    projects = len(r.getlist('project')) > 0 and list(conn.getObjects(
        'Project', r.getlist('project'))) or list()
    screens = len(r.getlist('screen')) > 0 and list(conn.getObjects(
        'Screen', r.getlist('screen'))) or list()
    plates = len(r.getlist('plate')) > 0 and list(conn.getObjects('Plate',
        r.getlist('plate'))) or list()
    acquisitions = len(r.getlist('acquisition')) > 0 and list(conn.
        getObjects('PlateAcquisition', r.getlist('acquisition'))) or list()
    shares = len(r.getlist('share')) > 0 and [conn.getShare(r.getlist(
        'share')[0])] or list()
    wells = len(r.getlist('well')) > 0 and list(conn.getObjects('Well', r.
        getlist('well'))) or list()
    return {'image': images, 'dataset': datasets, 'project': projects,
        'screen': screens, 'plate': plates, 'acquisition': acquisitions,
        'well': wells, 'share': shares}


def buffered_read(fh, lock, offsets, bytecounts, buffersize=2 ** 26):
    """Return iterator over blocks read from file."""
    length = len(offsets)
    i = 0
    while i < length:
        data = []
        with lock:
            size = 0
            while size < buffersize and i < length:
                fh.seek(offsets[i])
                bytecount = bytecounts[i]
                data.append(fh.read(bytecount))
                size += bytecount
                i += 1
        for block in data:
            yield block


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


@classmethod
def from_db(cls, db, zone_id=None):
    """ Create a schedule class instance from the database. """
    cursor = db.cursor()
    if zone_id is None:
        cursor.execute(
            'select day, starttime, zone, temp from schedule order by day, starttime, zone'
            )
    else:
        cursor.execute(
            'select day, starttime, zone, temp from schedule where zone=%s order by day, starttime, zone'
            , (zone_id,))
    entries = []
    for record in cursor:
        entries.append(record)
    return cls(entries)


def _is_4d(grouped_dicoms):
    """
    Use this function to detect if a dicom series is a ge 4d dataset
    NOTE: Only the first slice will be checked so you can only provide an already sorted dicom directory
    (containing one series)
    """
    header = grouped_dicoms[0][0]
    if len(grouped_dicoms) > 1:
        return True
    return False


def mysql_large_prefix_check(engine):
    """Check mysql has innodb_large_prefix set"""
    if not str(engine.url).startswith('mysql'):
        return False
    variables = dict(engine.execute(
        'show variables where variable_name like "innodb_large_prefix" or variable_name like "innodb_file_format";'
        ).fetchall())
    if variables['innodb_file_format'] == 'Barracuda' and variables[
        'innodb_large_prefix'] == 'ON':
        return True
    else:
        return False


def filter_req(req, extra):
    """Apply an extra using a requirements markers and return True if this requirement is kept"""
    if extra and not req.marker:
        return False
    keep_req = True
    if req.marker:
        if not extra:
            extra = None
        keep_req = req.marker.evaluate({'extra': extra})
    return keep_req


def analyze_cigar_indel(tuples, min_length):
    """Parses CIGAR tuples (op, len) and returns Indels with a length > minLength"""
    pos_ref = 0
    pos_read = 0
    indels = []
    for operation, length in tuples:
        if operation == 0:
            pos_ref += length
            pos_read += length
        elif operation == 1:
            if length >= min_length:
                indels.append((pos_ref, pos_read, length, 'INS'))
            pos_read += length
        elif operation == 2:
            if length >= min_length:
                indels.append((pos_ref, pos_read, length, 'DEL'))
            pos_ref += length
        elif operation == 4:
            pos_read += length
        elif operation == 7 or operation == 8:
            pos_ref += length
            pos_read += length
    return indels


def get_object_children(cmis_id):
    """Return a list of objects directly contained in the one
        specified by its id.
        """


def delete_slot_type(name=None):
    """
    Deletes all versions of the slot type, including the $LATEST version. To delete a specific version of the slot type, use the operation.
    You can delete a version of a slot type only if it is not referenced. To delete a slot type that is referred to in one or more intents, you must remove those references first.
    This operation requires permission for the lex:DeleteSlotType action.
    See also: AWS API Documentation

    :example: response = client.delete_slot_type(
        name='string'
    )

    :type name: string
    :param name: [REQUIRED]
            The name of the slot type. The name is case sensitive.

    """
    pass


def th_c_flatten(x):
    """
    Flatten tensor, leaving channel intact.
    Assumes CHW format.
    """
    return x.contiguous().view(x.size(0), -1)


@staticmethod
def replaceEmail(match):
    """Replace email strings with mailto: links
        """
    url = match.groups()[0]
    url = url.replace('@', '@')
    return '%s' % (url, url)


def set_name_w(name_w, w):
    """Return generic name if user passes None to the robust parameter in a
    regression. Note: already verified that the name is valid in
    check_robust() if the user passed anything besides None to robust.

    Parameters
    ----------
    name_w      : string
                  Name passed in by user. Default is None.
    w           : W object
                  pysal W object passed in by user

    Returns
    -------
    name_w      : string

    """
    if w != None:
        if name_w != None:
            return name_w
        else:
            return 'unknown'
    return None


@classmethod
def class_key(cls):
    """Nice order of classes. """
    return 5, 0, cls.__name__


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


def 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


@classmethod
def rollback(cls, resource, background=False):
    """ Rollback a disk from a snapshot. """
    disk_id = cls.usable_id(resource)
    result = cls.call('hosting.disk.rollback_from', disk_id)
    if background:
        return result
    cls.echo('Disk rollback in progress.')
    cls.display_progress(result)
    return result


@staticmethod
def evaluate(x, amplitude, x_0, fwhm):
    """One dimensional Lorentzian model function"""
    return amplitude * (fwhm / 2.0) ** 2 / ((x - x_0) ** 2 + (fwhm / 2.0) ** 2)


def get_upf_version(upf):
    """Get UPF version."""
    line = upf.split('\n')[0]
    if '<PP_INFO>' in line:
        return 1
    if 'UPF version' in line:
        return 2
    return 0


@classmethod
def from_api_data(cls, data):
    """Creates a new Offer object from API data from ticketswitch.

        Args:
            data (dict): the part of the response from a ticketswitch API call
                that concerns an offer.

        Returns:
            :class:`Offer <pyticketswitch.offer.Offer>`: a new
            :class:`Offer <pyticketswitch.offer.Offer>` object
            populated with the data from the api.

        """
    kwargs = {'seatprice': data.get('offer_seatprice'), 'surcharge': data.
        get('offer_surcharge'), 'original_seatprice': data.get(
        'full_seatprice'), 'original_surcharge': data.get('full_surcharge'),
        'absolute_saving': data.get('absolute_saving'), 'percentage_saving':
        data.get('percentage_saving')}
    return cls(**kwargs)


def is_html(response):
    """ Check if Flask response if of HTML type.

    Parameters
    ----------
        response: Flask response

    Returns
    -------
        True if valid False if not.
    """
    content_type = getattr(response, 'content_type', '')
    return 'text/html' in content_type.lower()


def window_historical_load(historical_load, window_begin, window_end):
    """Filter historical_load down to just the datapoints lying between times window_begin and window_end, inclusive."""
    filtered = []
    for timestamp, value in historical_load:
        if timestamp >= window_begin and timestamp <= window_end:
            filtered.append((timestamp, value))
    return filtered


@classmethod
def get_format_string(cls):
    """See RepositoryFormat.get_format_string()."""
    return b'Bazaar Knit Repository Format 3 (bzr 0.15)\n'


def calculate_correlation_lengths(semimajor, semiminor):
    """Calculate the Condon correlation length

    In order to derive the error bars from Gauss fitting from the
    Condon (1997, PASP 109, 116C) formulae, one needs the so called
    correlation length. The Condon formulae assumes a circular area
    with diameter theta_N (in pixels) for the correlation. This was
    later generalized by Hopkins et al. (2003, AJ 125, 465) for
    correlation areas which are not axisymmetric.

    Basically one has theta_N^2 = theta_B*theta_b.

    Good estimates in general are:

    + theta_B = 2.0 * semimajar

    + theta_b = 2.0 * semiminor
    """
    return 2.0 * semimajor, 2.0 * semiminor


def put_bucket_lifecycle(Bucket=None, LifecycleConfiguration=None):
    """
    Deprecated, see the PutBucketLifecycleConfiguration operation.
    See also: AWS API Documentation

    :example: response = client.put_bucket_lifecycle(
        Bucket='string',
        LifecycleConfiguration={
            'Rules': [
                {
                    'Expiration': {
                        'Date': datetime(2015, 1, 1),
                        'Days': 123,
                        'ExpiredObjectDeleteMarker': True|False
                    },
                    'ID': 'string',
                    'Prefix': 'string',
                    'Status': 'Enabled'|'Disabled',
                    'Transition': {
                        'Date': datetime(2015, 1, 1),
                        'Days': 123,
                        'StorageClass': 'GLACIER'|'STANDARD_IA'
                    },
                    'NoncurrentVersionTransition': {
                        'NoncurrentDays': 123,
                        'StorageClass': 'GLACIER'|'STANDARD_IA'
                    },
                    'NoncurrentVersionExpiration': {
                        'NoncurrentDays': 123
                    },
                    'AbortIncompleteMultipartUpload': {
                        'DaysAfterInitiation': 123
                    }
                },
            ]
        }
    )

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

    :type LifecycleConfiguration: dict
    :param LifecycleConfiguration:
            Rules (list) -- [REQUIRED]
            (dict) --
            Expiration (dict) --
            Date (datetime) -- Indicates at what date the object is to be moved or deleted. Should be in GMT ISO 8601 Format.
            Days (integer) -- Indicates the lifetime, in days, of the objects that are subject to the rule. The value must be a non-zero positive integer.
            ExpiredObjectDeleteMarker (boolean) -- Indicates whether Amazon S3 will remove a delete marker with no noncurrent versions. If set to true, the delete marker will be expired; if set to false the policy takes no action. This cannot be specified with Days or Date in a Lifecycle Expiration Policy.
            ID (string) -- Unique identifier for the rule. The value cannot be longer than 255 characters.
            Prefix (string) -- [REQUIRED] Prefix identifying one or more objects to which the rule applies.
            Status (string) -- [REQUIRED] If 'Enabled', the rule is currently being applied. If 'Disabled', the rule is not currently being applied.
            Transition (dict) --
            Date (datetime) -- Indicates at what date the object is to be moved or deleted. Should be in GMT ISO 8601 Format.
            Days (integer) -- Indicates the lifetime, in days, of the objects that are subject to the rule. The value must be a non-zero positive integer.
            StorageClass (string) -- The class of storage used to store the object.
            NoncurrentVersionTransition (dict) -- Container for the transition rule that describes when noncurrent objects transition to the STANDARD_IA or GLACIER storage class. If your bucket is versioning-enabled (or versioning is suspended), you can set this action to request that Amazon S3 transition noncurrent object versions to the STANDARD_IA or GLACIER storage class at a specific period in the object's lifetime.
            NoncurrentDays (integer) -- Specifies the number of days an object is noncurrent before Amazon S3 can perform the associated action. For information about the noncurrent days calculations, see How Amazon S3 Calculates When an Object Became Noncurrent in the Amazon Simple Storage Service Developer Guide.
            StorageClass (string) -- The class of storage used to store the object.
            NoncurrentVersionExpiration (dict) -- Specifies when noncurrent object versions expire. Upon expiration, Amazon S3 permanently deletes the noncurrent object versions. You set this lifecycle configuration action on a bucket that has versioning enabled (or suspended) to request that Amazon S3 delete noncurrent object versions at a specific period in the object's lifetime.
            NoncurrentDays (integer) -- Specifies the number of days an object is noncurrent before Amazon S3 can perform the associated action. For information about the noncurrent days calculations, see How Amazon S3 Calculates When an Object Became Noncurrent in the Amazon Simple Storage Service Developer Guide.
            AbortIncompleteMultipartUpload (dict) -- Specifies the days since the initiation of an Incomplete Multipart Upload that Lifecycle will wait before permanently removing all parts of the upload.
            DaysAfterInitiation (integer) -- Indicates the number of days that must pass since initiation for Lifecycle to abort an Incomplete Multipart Upload.

    """
    pass


def get_ipr_dtype_list(endianess='<', version=333):
    """
    Get the data type list for an IPR image description file.
    Further information about the file format is available `here
    <https://github.com/hyperspy/hyperspy/files/29507/ImageIPR.pdf>`__.

    Table of header tags:
        -  version: 2 byte unsigned short; *Current version number: 334*
        -  imageType: 2 byte unsigned short; *0=empty; 1=electron; 2=xmap; 3=disk; 4=overlay*
        -  label: 8 byte char array; *Image label*
        -  sMin: 2 byte unsigned short; *Min collected signal*
        -  sMax: 2 byte unsigned short; *Max collected signal*
        -  color: 2 byte unsigned short; *color: 0=gray; 1=R; 2=G; 3=B; 4=Y; 5=M; 6=C; 8=overlay*
        -  presetMode: 2 byte unsigned short; *0=clock; 1=live*
        -  presetTime: 4 byte unsigned long; *Dwell time for x-ray (millisec)*
        -  dataType: 2 byte unsigned short; *0=ROI;  1=Net intensity; 2=K ratio; 3=Wt%;  4=Mthin2*
        -  timeConstantOld: 2 byte unsigned short; *Amplifier pulse processing time [usec]*
        -  reserved1: 2 byte short; *Not used*
        -  roiStartChan: 2 byte unsigned short; *ROI starting channel*
        -  roiEndChan: 2 byte unsigned short; *ROI ending channel*
        -  userMin: 2 byte short; *User Defined Min signal range*
        -  userMax: 2 byte short; *User Defined Max signal range*
        -  iADC: 2 byte unsigned short; *Electron detector number: 1; 2; 3; 4*
        -  reserved2: 2 byte short; *Not used*
        -  iBits: 2 byte unsigned short; *conversion type: 8; 12 (not used)*
        -  nReads: 2 byte unsigned short; *No. of reads per point*
        -  nFrames: 2 byte unsigned short; *No. of frames averaged (not used)*
        -  fDwell: 4 byte float; *Dwell time (not used)*
        -  accV: 2 byte unsigned short; *V_acc in units of 100V*
        -  tilt: 2 byte short; *Sample tilt [deg]*
        -  takeoff: 2 byte short; *Takeoff angle [deg]*
        -  mag: 4 byte unsigned long; *Magnification*
        -  wd: 2 byte unsigned short; *Working distance [mm]*
        -  mppX: 4 byte float; *Microns per pixel in X direction*
        -  mppY: 4 byte float; *Microns per pixel in Y direction*
        -  nTextLines: 2 byte unsigned short; *No. of comment lines *
        -  charText: (4 x 32) byte character array; *Comment text*
        -  reserved3: 4 byte float; *Not used*
        -  nOverlayElements: 2 byte unsigned short; *No. of overlay elements*
        -  overlayColors: 16 array of 2 byte unsigned short; *Overlay colors*

        # These two are specific to V334 of the file format, and are omitted
        # for compatibility with V333 of the IPR format
        -  timeConstantNew: 4 byte float; *Amplifier time constant [usec]*
        -  reserved4: 2 array of 4 byte float; *Not used*

    Parameters
    ----------
    endianess : char
        byte-order used to read the data
    version : float
        version of .ipr file to read (only 333 and 334 have been tested)
        Default is 333 to be as backwards-compatible as possible, but the
        file version can be read from the file anyway, so this parameter
        should always be set programmatically

    Returns
    -------
    dtype_list : list
        List of the data tags and data types that will be used by numpy to
        read an IPR file.
    """
    end = endianess
    dtype_list = [('version', end + 'u2'), ('imageType', end + 'u2'), (
        'label', end + 'a8'), ('sMin', end + 'u2'), ('sMax', end + 'u2'), (
        'color', end + 'u2'), ('presetMode', end + 'u2'), ('presetTime',
        end + 'u4'), ('dataType', end + 'u2'), ('timeConstantOld', end +
        'u2'), ('reserved1', end + 'i2'), ('roiStartChan', end + 'u2'), (
        'roiEndChan', end + 'u2'), ('userMin', end + 'i2'), ('userMax', end +
        'i2'), ('iADC', end + 'u2'), ('reserved2', end + 'i2'), ('iBits',
        end + 'u2'), ('nReads', end + 'u2'), ('nFrames', end + 'u2'), (
        'fDwell', end + 'f4'), ('accV', end + 'u2'), ('tilt', end + 'i2'),
        ('takeoff', end + 'i2'), ('mag', end + 'u4'), ('wd', end + 'u2'), (
        'mppX', end + 'f4'), ('mppY', end + 'f4'), ('nTextLines', end +
        'u2'), ('charText', end + '4a32'), ('reserved3', end + '4f4'), (
        'nOverlayElements', end + 'u2'), ('overlayColors', end + '16u2')]
    if version >= 334:
        dtype_list.extend([('timeConstantNew', end + 'f4'), ('reserved4',
            end + '2f4')])
    return dtype_list


@staticmethod
def is_important_change(before, curr, *args):
    """Non important changes such as update_timestamp shouldn't be stored

        :param args: list of keys that should be ignored
        :return: True if this change should be stored
        """
    if not curr:
        return False
    if curr and not before:
        return True
    for key, content in curr.properties.items():
        if key in args:
            continue
        elif isinstance(content, dict) or isinstance(content, list):
            return True
        elif before.properties.get(key) != content:
            return True
    return False


def _is_long_running_process(command):
    """
    Try to determine if the process should be long-running or not
    """
    is_long_running_process = False
    if 'runserver' in command.name or 'runserver' in command.execute:
        is_long_running_process = True
    if command.long_running is not None:
        is_long_running_process = command.long_running
    return is_long_running_process


@staticmethod
def from_pandas(df, index=True):
    """Return a reader object which will iterate over records in
        the pandas.DataFrame *df*.

        .. note::

            This constructor requires the optional, third-party
            library pandas.
        """
    if index:
        yield list(df.index.names) + list(df.columns)
    else:
        yield list(df.columns)
    records = df.to_records(index=index)
    for record in records:
        yield list(record)


@classmethod
def get_outdated_docs(cls, app, env, added, changed, removed):
    """Handler for Sphinx's env-get-outdated event.

        This handler gives a Sphinx extension a chance to indicate that some
        set of documents are out of date and need to be re-rendered. The
        implementation here is stupid, for now, and always says that anything
        that uses the directive needs to be re-rendered.

        We should make it smarter, at some point, and have it figure out which
        modules are used by the associated handlers, and whether they have
        actually been updated since the last time the given document was
        rendered.
        """
    state = getattr(env, cls.directive_name, None)
    if state and state.doc_names:
        return sorted(state.doc_names)
    else:
        return []


def set_debug_console(value):
    """Set debug console enable."""
    global DEBUG_CONSOLE
    DEBUG_CONSOLE = bool(value)


def action_refactoring(file):
    """
    NOT IMPLEMENTED,
    call to import externally generated models (eg. in KNIME or R)
    """
    print('refactoring')
    return True, 'OK'


def _swap_pars(pars, a, b):
    """
    Swap polydispersity and magnetism when swapping parameters.

    Assume the parameters are of the same basic type (volume, sld, or other),
    so that if, for example, radius_pd is in pars but radius_bell_pd is not,
    then after the swap radius_bell_pd will be the old radius_pd and radius_pd
    will be removed.
    """
    for ext in ('', '_pd', '_pd_n', '_pd_nsigma', '_pd_type', '_M0',
        '_mphi', '_mtheta'):
        ax, bx = a + ext, b + ext
        if ax in pars and bx in pars:
            pars[ax], pars[bx] = pars[bx], pars[ax]
        elif ax in pars:
            pars[bx] = pars[ax]
            del pars[ax]
        elif bx in pars:
            pars[ax] = pars[bx]
            del pars[bx]


def ferm_pct(fermentables):
    """Adds a 'pct' to each fermentable in fermentables.

    'pct' represents the total percentage a fermentable makes up of the grist.
    """
    total = 0
    for ferm in fermentables:
        total += float(ferm['amount'])
    for ferm in fermentables:
        ferm['pct'] = 100 * float(ferm['amount']) / total
    return fermentables


def mp_switch_to_content(driver, frame='TargetContent'):
    """Passively try to switch to the content frame"""
    try:
        driver.switch_to.frame(frame)
    except:
        pass


@staticmethod
def to_percent(raw):
    """Create percent intensity value out of raw."""
    return int(raw[0] / 2)


def to_timestamp(datetime_timestamp):
    """Convert UTC datetime to microsecond timestamp used by Hangouts."""
    return int(datetime_timestamp.timestamp() * 1000000)


def get_linear_regression_options(defaults=None):
    """Adding arguments for the linear regression subcommand

    """
    if defaults is None:
        defaults = {}
    options = {'--inear-fields': {'action': 'store', 'dest':
        'linear_fields', 'default': defaults.get('linear_fields', None),
        'help':
        'Comma-separated list of input fields (predictors) to create the linear regression.'
        }, '--linear-regression': {'action': 'store', 'dest':
        'linear_regression', 'default': defaults.get('linear_regression',
        None), 'help': 'BigML linear regression Id.'},
        '--linear-regressions': {'action': 'store', 'dest':
        'linear_regressions', 'default': defaults.get('linear_regressions',
        None), 'help':
        'Path to a file containing linearregression/ids. One linearregression per line (e.g., linearregression/50a206a8035d0706dc000376).'
        }, '--linear-file': {'action': 'store', 'dest': 'linear_file',
        'default': defaults.get('linear_file', None), 'help':
        'BigML linear regression JSON structure file.'},
        '--no-linear-regression': {'action': 'store_true', 'dest':
        'no_linear_regression', 'default': defaults.get(
        'no_linear_regression', False), 'help':
        'Do not create a linear regression.'},
        '--linear-regression-attributes': {'action': 'store', 'dest':
        'linear_regression_attributes', 'default': defaults.get(
        'linear_regression_attributes', None), 'help':
        'Path to a json file describing linear regression attributes.'},
        '--no-no-linear-regression': {'action': 'store_false', 'dest':
        'no_linear_regression', 'default': defaults.get(
        'no_linear_regression', False), 'help': 'Create a linear regression.'}}
    return options


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

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

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


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


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

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


def get(username, default=None):
    """
        Get a user by user login name, or return default.
        Non-default result should provide IPropertiedUser.
        """


def name(item):
    """Return an item's name."""
    return item.__name__


def _no_self_loops(array, return_test=False):
    """
    Remove self-loops
    """
    test = array[:, (0)] != array[:, (1)]
    if return_test:
        return array[(test), :].astype(int), test
    return array[(test), :].astype(int)


@staticmethod
def check_args(args):
    """
        Validate mode args

        :param args: parsed arguments object
        :return: bool
        """
    del args
    return True


@classmethod
def clearDeviceOrientationOverride(cls):
    """Clears the overridden Device Orientation.
        """
    return cls.build_send_payload('clearDeviceOrientationOverride', {}), None


def get_topic_name(prefix, table, operation, host=None):
    """Create a topic name.

    The topic name needs to be synced between the agent and the
    plugin. The plugin will send a fanout message to all of the
    listening agents so that the agents in turn can perform their
    updates accordingly.

    :param prefix: Common prefix for the plugin/agent message queues.
    :param table: The table in question (NETWORK, SUBNET, PORT).
    :param operation: The operation that invokes notification (CREATE,
                      DELETE, UPDATE)
    :param host: Add host to the topic
    :returns: The topic name.
    """
    if host:
        return '%s-%s-%s.%s' % (prefix, table, operation, host)
    return '%s-%s-%s' % (prefix, table, operation)


def get_music_url(array):
    """
    get music url from list
    :param array:
    :return:
    """
    if isinstance(array, list) and len(array) >= 1:
        return array[-1]
    return None


def update_radius(DirectoryId=None, RadiusSettings=None):
    """
    Updates the Remote Authentication Dial In User Service (RADIUS) server information for an AD Connector directory.
    See also: AWS API Documentation

    :example: response = client.update_radius(
        DirectoryId='string',
        RadiusSettings={
            'RadiusServers': [
                'string',
            ],
            'RadiusPort': 123,
            'RadiusTimeout': 123,
            'RadiusRetries': 123,
            'SharedSecret': 'string',
            'AuthenticationProtocol': 'PAP'|'CHAP'|'MS-CHAPv1'|'MS-CHAPv2',
            'DisplayLabel': 'string',
            'UseSameUsername': True|False
        }
    )

    :type DirectoryId: string
    :param DirectoryId: [REQUIRED]
            The identifier of the directory for which to update the RADIUS server information.

    :type RadiusSettings: dict
    :param RadiusSettings: [REQUIRED]
            A RadiusSettings object that contains information about the RADIUS server.
            RadiusServers (list) --An array of strings that contains the IP addresses of the RADIUS server endpoints, or the IP addresses of your RADIUS server load balancer.
            (string) --
            RadiusPort (integer) --The port that your RADIUS server is using for communications. Your on-premises network must allow inbound traffic over this port from the AWS Directory Service servers.
            RadiusTimeout (integer) --The amount of time, in seconds, to wait for the RADIUS server to respond.
            RadiusRetries (integer) --The maximum number of times that communication with the RADIUS server is attempted.
            SharedSecret (string) --Not currently used.
            AuthenticationProtocol (string) --The protocol specified for your RADIUS endpoints.
            DisplayLabel (string) --Not currently used.
            UseSameUsername (boolean) --Not currently used.

    :rtype: dict
    :return: {}

    """
    pass


def modifier_move_up(modifier: str=''):
    """Move modifier up in the stack

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


@classmethod
def info(cls, id):
    """Display information about a PaaS instance."""
    return cls.call('paas.info', cls.usable_id(id))


@classmethod
def msearch(cls, body, keys, header=None):
    """Make a multi search.

    body: list of dict query
    keys: list of key I need to set to put the data behind

    """
    conn = cls.get_connection()
    new_body = []
    index_name = None
    assert len(body) == len(keys)
    if not header:
        index_name = cls.get_index_name()
    else:
        assert len(header) == len(body)
        if not index_name:
            index_name = header[0]['index_name']
    for idx, row in enumerate(body):
        if header and header[idx]:
            new_header = {'index': header[idx].get('index_name')}
            new_body.append(new_header)
        else:
            new_body.append({})
        new_body.append(row)
    result = conn.msearch(index=index_name, body=new_body)
    standard_result = {}
    for idx, one_response in enumerate(result['responses']):
        one_key = keys[idx]
        idx_name = index_name
        if header and header[idx]:
            idx_name = header[idx].get('index_name')
        mapped_result, total = cls.render_map(one_response, mindex=True)
        if one_response.get('aggregations'):
            mapped_result['aggs'] = one_response.get('aggregations')
        standard_result.update({one_key: {'total': total, idx_name:
            mapped_result}})
    return standard_result


def _ex(fsm, alpha, phi):
    """_ex(a, p) is pre of p through transitions satisfying a"""
    return fsm.pre(phi, alpha)


def __permitted__(context, request):
    """ Return True if view execution will be permitted using the
        context and request, False otherwise"""


@classmethod
def load(cls, filename):
    """
        Load a staj file, returning an MlayerModel object
        """
    fin = open(filename, 'r')
    lines = fin.readlines()
    fin.close()
    self = cls()
    self._parse(lines)
    return self


def drop(iterable, n=1):
    """
    Drop `n` values from `iterable`
    """
    iterator = iter(iterable)
    try:
        for _ in range(n):
            next(iterator)
    except StopIteration:
        pass
    return iterator


def java_version():
    """Show Java version

    Returns:
        str: Result of ``java -version``
    """
    import subprocess
    try:
        res = subprocess.check_output(['java', '-version'], stderr=
            subprocess.STDOUT)
        res = res.decode()
    except FileNotFoundError:
        res = (
            '`java -version` faild. `java` command is not found from this Pythonprocess. Please ensure Java is installed and PATH is set for `java`'
            )
    return res


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

        :param GroupChangeExternalIdDetails val:
        :rtype: EventDetails
        """
    return cls('group_change_external_id_details', val)


def diff(a: list, b: list):
    """Returns values from 'a' not found in 'b'"""
    return list(set(a) - set(b))


def combine_intervals(I1, I2):
    """ Return a 2-tuple of timestamps (I1[0], I2[1]). """
    return I1[0], I2[1]


def _is_my_ticket(user, ticket):
    """Check to see if the user has permission to access
    a ticket. If not then deny access."""
    if user.is_superuser or user.is_staff or user.id == ticket.assigned_to.id:
        return True
    else:
        return False


def GetAtomsById(atomData, atomLookUp, IdList):
    """gets a list of atoms from Atom table that match a set of atom IDs

    :param list atomData: Atom table to be used
    :param dict atomLookUp: dictionary of atom indexes with atom IDs as keys
    :param list IdList: atom IDs to be found

    :returns: list atoms: list of atoms found

    """
    atoms = []
    for Id in IdList:
        atoms.append(atomData[atomLookUp[Id]])
    return atoms


def state_scripts(state):
    """
    returns all the scripts in the state
    """
    json_data = state.data.get('json')
    scripts = []
    if json_data != None:
        scripts.extend(json_data.get('scripts', []))
        for child in json_data.get('children'):
            scripts.extend(child.get('scripts', []))
    return scripts


def _call_fit(fit_method, X, y=None, **kwargs):
    """
    helper function, calls the fit or fit_transform method with the correct
    number of parameters

    fit_method: fit or fit_transform method of the transformer
    X: the data to fit
    y: the target vector relative to X, optional
    kwargs: any keyword arguments to the fit method

    return: the result of the fit or fit_transform method

    WARNING: if this function raises a TypeError exception, test the fit
    or fit_transform method passed to it in isolation as _call_fit will not
    distinguish TypeError due to incorrect number of arguments from
    other TypeError
    """
    try:
        return fit_method(X, y, **kwargs)
    except TypeError:
        return fit_method(X, **kwargs)


@classmethod
def get_all(cls):
    """
        returns all subclasses inherited from Formatter

        >>> formatters = Formatter.get_all()
        >>> Extractor.from_yaml_file('a.yaml', formatters=formatters)
        """
    return cls.__subclasses__()


def electrons2adu(electrons, ccd_gain):
    """
    converts electron counts into analog-to-digital unit

    :param electrons:
    :return: adu value corresponding to electron count
    """
    return electrons / ccd_gain


@classmethod
def Zero(cls, *args):
    """Creates a matrix filled with zeros.

        @keyword shape: the shape of the matrix. Can be a single integer,
          two integers or a tuple. If a single integer is
          given here, the matrix is assumed to be square-shaped.
        """
    result = cls.Fill(0, *args)
    return result


@staticmethod
def decompress(data):
    """Get one parameter data, which returns."""
    return data


def selectData(data, featureSet):
    """
    Selects a part of your data according to a feature set

    Args:
      data : dict of str: numpy.ndarray
        dictionary that contains your full data to be partitioned
        featureSet: A list that contains the feature set that you want to select

    Returns:
      selectedData : dict of str: numpy.ndarray
       dictionary that contains the selected data according to the feature set
  """
    partialData = {'features': {}, 'response': {}}
    for feature in featureSet:
        currKey = 'X' + str(int(feature))
        partialData['features'][currKey] = data['features'][currKey]
    return partialData


def minute():
    """Return the minute"""


def bool_to_byte(value: bool) ->bytes:
    """Converts a bool into a byte"""
    return b'0x01' if value else b'0x00'


def num_unique_objects(df, obj_frequencies):
    """Total number of unique object ids encountered."""
    del df
    return len(obj_frequencies)


def mult3(v, d):
    """Multiplies a 3D vector to a scalar"""
    return [v[0] * d, v[1] * d, v[2] * d]


def get_detail_view_name(model):
    """
    Given a model class, return the view name to use for URL relationships
    that rever to instances of the model.
    """
    return '{}-detail'.format(model.__name__.lower())


def psi_K_Mg_CO3_HMW84(T, P):
    """c-c'-a: potassium magnesium carbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def next():
    """Move to next folder

    """
    pass


def media(statuses):
    """
    Count media attachments in statuses
    """
    i = 0
    for item in statuses:
        i += len(item['media_attachments'])
    return i


def __getitem__(key):
    """Return object by key or None if not exists.
        """


def clone(cls, original):
    """Return an exact copy of an object."""
    """The original object must have an empty constructor."""
    return cls.create(original.__class__)


@classmethod
def from_comp(cls, xx=1, xy=0, xz=0, yy=1, yz=0, zz=1, **kwargs) ->'Tensor':
    """
        Return tensor. Default is identity tensor.

        Note that tensor must be symmetrical.
        """
    return cls([[xx, xy, xz], [xy, yy, yz], [xz, yz, zz]], **kwargs)


@classmethod
def delete_by_id(cls, id_param):
    """
        removes the object by id
        :param id_param: entidade
        """
    obj = cls.find_by_id(id_param=id_param)
    cls.alchemy_db().session.delete(obj)


def load(word, reload=False):
    """ load from cache if not found read from anywhere"""


def filter_servers(servers, features=None):
    """
    Filter a list of servers by feature.

    :param servers: List of servers as parsed from nordvpn api in json format
    :param features: List of features to filter the server list. If None or
                     empty the default 'openvpn_udp' is applied.
    :returns: The filtered list
    """
    if features is None or not features:
        features = ['openvpn_udp']
    filtered_servers = []
    servers = servers.copy()
    for server in servers:
        append = True
        for feature in features:
            if not server['features'][feature]:
                append = False
                break
        if append:
            filtered_servers.append(server)
    return filtered_servers


def read_binary(filename):
    """
        Write binary data to a file on disk
    """
    import struct
    data = []
    f = open(filename, 'rb')
    byte = f.read(1)
    while byte != b'':
        data.append(ord(byte))
        byte = f.read(1)
    f.close()
    return data


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


def read_n_altitude_lvls(fn):
    """Read number of altitude levels from WF / BAMF output"""
    with open(fn, 'r') as fd:
        while True:
            ln = fd.readline()
            tmp = ln.split('The number of altitude levels:')
            if len(tmp) > 1:
                return int(tmp[-1])
    raise ValueError('Number of altitude levels not found in {}'.format(fn))


def selected_objects_add():
    """Make selected objects appear in NLA Editor by adding Animation Data

    """
    pass


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


def heatmap(column_rel, **kwargs):
    """Plot a heatmap of data, probably from a column association call.

    This may be useful for other data frames, but most of the time you will
    want to call this like `edpanalyst.heatmap(popmod.mutual_information())`.
    """
    try:
        import seaborn as sns
    except ImportError:
        raise RuntimeError(
            'edpanalyst.heatmap requires that the "seaborn" python package be installed.'
            )
    plot_df = column_rel.fillna(0).reset_index()
    hmap = sns.clustermap(plot_df, linewidths=0.2, pivot_kws={'index': 'X',
        'columns': 'Y', 'values': 'I'}, **kwargs)
    for l in hmap.ax_heatmap.get_yticklabels():
        l.set_rotation('horizontal')
    return hmap


def is_list(data_to_check):
    """ Check whether the given data is a list."""
    flag = False
    if isinstance(data_to_check, list):
        flag = True
    return flag


def getid(obj):
    """Return id if argument is a Resource.

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


def comment():
    """Convert selected text to comment

    """
    pass


@classmethod
def data_dataclass_fields(cls):
    """ Sub classed by FeatureRecord below.
        """
    return cls.dataclass_fields()


def tag(item_type, item_id, user_id, *tags):
    """User <user_id> adds tags <*tags> on <item_type> <item_id>"""


def safe_issubclass(*args):
    """Like issubclass, but will just return False if not a class."""
    try:
        if issubclass(*args):
            return True
    except TypeError:
        pass
    return False


def is_separate_console_window():
    """    Check if the process owns a console window.

    Return True if the console window was opened with this process.
    Return False if the console was already open and this application was
    started within it.
    """
    import ctypes
    import ctypes.wintypes
    window = ctypes.windll.kernel32.GetConsoleWindow()
    console_pid = ctypes.wintypes.DWORD()
    ctypes.windll.user32.GetWindowThreadProcessId(window, ctypes.byref(
        console_pid))
    return console_pid.value == ctypes.windll.kernel32.GetCurrentProcessId()


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

        :param list of [MemberAddResult] val:
        :rtype: MembersAddJobStatus
        """
    return cls('complete', val)


@classmethod
def from_device_info(cls, parent, device_name, device_info, memorymap_dict,
    legacy_reg_map=True):
    """
        Process device info and the memory map to get all necessary info
        and return a Hmc instance.
        :param parent: the CasperFpga that hosts this HMC
        :param device_name: the unique device name
        :param device_info: information about this device
        :param memorymap_dict: a dictionary containing the device memory map
        :return: a Hmc object
        """
    address, length_bytes = -1, -1
    for mem_name in memorymap_dict.keys():
        if mem_name == device_name:
            address = memorymap_dict[mem_name]['address']
            length_bytes = memorymap_dict[mem_name]['bytes']
            try:
                mezzanine_site = int(device_info['mez'])
            except KeyError:
                mezzanine_site = 0
            break
    if address == -1 or length_bytes == -1:
        raise RuntimeError('Could not find address or length for Hmc %s' %
            device_name)
    return cls(parent, device_name, address, length_bytes, mezzanine_site,
        device_info, legacy_reg_map=legacy_reg_map)


@staticmethod
def _parse_response(status, response, console=False):
    """
        Parse the response and check for errors.

        Args:
          status (int): Status code of the response.
          response (string): Response string.
          console (bool, optional): Pretty print the response to the console for debugging. Defaults to False.

        Returns:
          dict: response parsed into a dictionary or raises appropriate error.
        """
    pass


def describe_vault(accountId=None, vaultName=None):
    """
    This operation returns information about a vault, including the vault's Amazon Resource Name (ARN), the date the vault was created, the number of archives it contains, and the total size of all the archives in the vault. The number of archives and their total size are as of the last inventory generation. This means that if you add or remove an archive from a vault, and then immediately use Describe Vault, the change in contents will not be immediately reflected. If you want to retrieve the latest inventory of the vault, use  InitiateJob . Amazon Glacier generates vault inventories approximately daily. For more information, see Downloading a Vault Inventory in Amazon Glacier .
    An AWS account has full permission to perform all operations (actions). However, AWS Identity and Access Management (IAM) users don't have any permissions by default. You must grant them explicit permission to perform specific actions. For more information, see Access Control Using AWS Identity and Access Management (IAM) .
    For conceptual information and underlying REST API, see Retrieving Vault Metadata in Amazon Glacier and Describe Vault in the Amazon Glacier Developer Guide .
    See also: AWS API Documentation

    Examples
    The example retrieves data about a vault named my-vault.
    Expected Output:

    :example: response = client.describe_vault(
        vaultName='string'
    )

    :type accountId: string
    :param accountId: The AccountId value is the AWS account ID of the account that owns the vault. You can either specify an AWS account ID or optionally a single '- ' (hyphen), in which case Amazon Glacier uses the AWS account ID associated with the credentials used to sign the request. If you use an account ID, do not include any hyphens ('-') in the ID.
            Note: this parameter is set to '-' bydefault if no value is not specified.

    :type vaultName: string
    :param vaultName: [REQUIRED]
            The name of the vault.

    :rtype: dict
    :return: {
        'VaultARN': 'string',
        'VaultName': 'string',
        'CreationDate': 'string',
        'LastInventoryDate': 'string',
        'NumberOfArchives': 123,
        'SizeInBytes': 123
    }

    """
    pass


def rle_get_at(rle, pos):
    """
    Return the attribute at offset pos.
    """
    x = 0
    if pos < 0:
        return None
    for a, run in rle:
        if x + run > pos:
            return a
        x += run
    return None


def py_bool(data):
    """ return python boolean """
    return data == 'true'


def in_has_compat(cp, ucd):
    """Code points that have compatibility equivalents.

    Args:
        cp (int): Code point.
        ucd (UnicodeData): Unicode character database.

    Returns:
        bool: True if `cp` is in set.
    """
    return ucd.has_compat(cp)


def case_ratio(msg):
    """Accepts a twitter message (or used with .apply(lambda x:)).
    Returns the ratio of capitalized characters out of the total number of characters.

    EX:
    df['case_ratio'] = df['text'].apply(lambda x: case_ratio(x))"""
    import numpy as np
    msg_length = len(msg)
    test_upper = [(1) for x in msg if x.isupper()]
    test_lower = [(1) for x in msg if x.islower()]
    test_ratio = np.round(sum(test_upper) / msg_length, 5)
    return test_ratio


@staticmethod
def add_callback(callback, control_instance):
    """ Method to add a callback to the control instance when the controller
        trait is modified

        Parameters
        ----------
        callback: @function (mandatory)
            the function that will be called when a 'textChanged' signal is
            emited.
        control_instance: QFrame (mandatory)
            the control widget we want to validate
        """
    pass


def releases_for_display():
    """Get the releases from the project.
        """


def valid_url(url):
    """
    Validate a URL and make sure that it has the correct URL syntax.

    Args:
        url (str): URL string to be evaluated.

    Returns:
        True if the URL is valid. False if it is invalid.
    """
    if 'http://' not in url and 'https://' not in url:
        return False
    return True


def distance_to_similarity(x, y, dist_func):
    """
    Convert the distance functions in scipy.spatial.distance into similarity functions

    Parameters
    ----------
    x : array_like, Shape(N,)
        First input vector.
    y : array_like, Shape(N,)
        Second input vector.

    dist_func : collable
        collabel distance function (e.g., any distance function in scipy.spatial.distance)

    Returns
    -------
    similarity between x and y.

    """
    return 1 - dist_func(x, y)


@classmethod
def apply(cls, v1, v2, op):
    """
		Return a new canonical representation of the
		pyddlib.DD object for the result of `v1` `op` `v2`.

		:param v1: root vertex of left operand
		:type v1: pyddlib.DD
		:param v2: root vertex of right operand
		:type v2: pyddlib.DD
		:param op: a binary operator
		:type op: callable object or function
		:rtype: pyddlib.DD
		"""
    T = {}
    return cls.__apply_step(v1, v2, op, T).reduce()


def create_definition_base(title, server):
    """
    New users won't have any of the required meta information about their
    Swagger/OAS documentation so we can just generate them a base after
    asking some questions.

    For now, just the title and server will be enough. If the user is
    interested enough, they can see examples of valid syntax here:

    https://swagger.io/specification/#infoObject

    :param title: string
    :param server: string
    :return: dictionary
    """
    return {'openapi': '3.0.0', 'info': {'version': '1.0.0', 'title': title
        }, 'servers': [{'url': server, 'description':
        f'The production server for {title}'}]}


@staticmethod
def create_unique_transfer_operation_id(ase):
    """Create a unique transfer operation id
        :param blobxfer.models.azure.StorageEntity ase: storage entity
        :rtype: str
        :return: unique transfer id
        """
    return ';'.join((ase._client.primary_endpoint, ase.path, str(ase.
        vectored_io)))


def select_linked():
    """Select all curve points linked to already selected ones

    """
    pass


@classmethod
def StreamingCommand(cls, usb, service, command='', timeout_ms=None):
    """One complete set of USB packets for a single command.

    Sends service:command in a new connection, reading the data for the
    response. All the data is held in memory, large responses will be slow and
    can fill up memory.

    Args:
      usb: USB device handle with BulkRead and BulkWrite methods.
      service: The service on the device to talk to.
      command: The command to send to the service.
      timeout_ms: Timeout for USB packets, in milliseconds.

    Raises:
      InterleavedDataError: Multiple streams running over usb.
      InvalidCommandError: Got an unexpected response command.

    Yields:
      The responses from the service.
    """
    if isinstance(command, str):
        command = command.encode('utf8')
    connection = cls.Open(usb, destination=b'%s:%s' % (service, command),
        timeout_ms=timeout_ms)
    for data in connection.ReadUntilClose():
        yield data.decode('utf8')


def normalize_name(string):
    """convert to lowercase, remove spaces and underscores"""
    return string.replace(' ', '').replace('_', '').lower()


def underscores_to_camelcase(argument):
    """ Converts a camelcase param like the_new_attribute to the equivalent
    camelcase version like theNewAttribute. Note that the first letter is
    NOT capitalized by this function """
    result = ''
    previous_was_underscore = False
    for char in argument:
        if char != '_':
            if previous_was_underscore:
                result += char.upper()
            else:
                result += char
        previous_was_underscore = char == '_'
    return result


def feel(value):
    """
    Get the table of the value (or class).
    """
    if not isinstance(value, type):
        value = value.__class__
    from . import tables
    return tables[value]


def array_type(data_types, field):
    """
    Allows conversion of Django ArrayField to SQLAlchemy Array.
    Takes care of mapping the type of the array element.
    """
    from sqlalchemy.dialects import postgresql
    internal_type = field.base_field.get_internal_type()
    if internal_type in data_types and internal_type != 'ArrayField':
        sub_type = data_types[internal_type](field)
        if not isinstance(sub_type, (list, tuple)):
            sub_type = [sub_type]
    else:
        raise RuntimeError('Unsupported array element type')
    return postgresql.ARRAY(sub_type)


def calculate_inline_non_replaced_height(node, context):
    """Implements S10.6.1"""
    node.layout.content_height = node.intrinsic.height
    node.layout.content_top += (node.layout.margin_top + node.layout.
        border_top_width + node.layout.padding_top)


def overlap(obj1, obj2):
    """Test if obj1 and obj2 overlap on times"""
    if obj2.end_time <= obj1.get_start_time(
        ) or obj1.end_time <= obj2.get_start_time():
        return False
    return True


def is_derivative_symbol(expr, t_symbol=None):
    """
    Returns whether expr is a derivative symbol (w.r.t. t)

    :param expr:
    :param t_symbol:
    :return: True or False
    """
    if t_symbol is not None:
        raise NotImplementedError
    if hasattr(expr, 'difforder') and expr.difforder > 0:
        return True
    else:
        return False


@staticmethod
def extension():
    """Return most common file extension for format."""
    return 'php'


def get_redundant_indices(indices):
    """
    :type indices list[indexdigest.schema.Index]
    :rtype: list[tuple]
    """
    redundant_indices = []
    for index in indices:
        for compare in indices:
            if index.is_covered_by(compare):
                redundant_indices.append((index, compare))
    return redundant_indices


def terms():
    """Return a list of all terms in this node, excluding NOT subtrees."""


@staticmethod
def _is_ngram_worthy(token):
    """Decide if we should use this token for ngram counting.

        Excludes every word with digits in them, hyperlinks or
        an assigned word vector."""
    return (not token.has_vector and not token.like_url and not token.
        like_num and not token.like_email and not token.is_punct)


def mean(input, dim):
    """Reduce average the input tensor along the given dim.

    Parameters
    ----------
    input : Tensor
        The input tensor.
    dim : int
        The reduce dim.

    Returns
    -------
    Tensor
        A framework-specific tensor.
    """
    pass


def matrix_det(A):
    """ 2D matrix determinant, vectorized """
    (a, b), (c, d) = A
    return a * d - b * c


def context_values(context, min=None, max=None, limit=100):
    """Filter IStatusUpdate values by IMicroblogContext object.
        min and max are longint IStatusUpdate.id keys.
        limit returns [:limit] most recent items
        """


@classmethod
def walk(cls, obj, *args):
    """
        Main entrypoint to the walk.

        Arguments:
            obj (.Schema):
                Schema node.

        Raises:
            SchemaError:
                When the schema is misconfigured.
        """
    return cls.dispatch(obj, '', [], *args)


@staticmethod
def _get_container_string(cont_dict, pid):
    """ Returns the nextflow containers string from a dictionary object

        If the dictionary has at least on of the container directives, these
        will be compiled for each process in the dictionary and returned
        as a string read for injection in the nextflow config file template.

        This dictionary should be::

            dict = {"processA": {"container": "asd", "version": "1.0.0"},
                    "processB": {"container": "dsd"}}

        Parameters
        ----------
        cont_dict : dict
            Dictionary with the containers for processes.
        pid : int
            Unique identified of the process

        Returns
        -------
        str
            nextflow config string
        """
    config_str = ''
    for p, directives in cont_dict.items():
        container = ''
        if 'container' in directives:
            container += directives['container']
            if 'version' in directives:
                container += ':{}'.format(directives['version'])
            else:
                container += ':latest'
        config_str += '\n\t${}_{}.container = "{}"'.format(p, pid, container)
    return config_str


def _setId(id):
    """Called to set the new id of a copied object.
        """


def array_1d(array):
    """
    Check if the given array has only one dimension. Following formats will
    return True:
        (x,), (x,1) and (1,x)
    """
    if not len(array.shape) == 1:
        if len(array.shape) == 2:
            if array.shape[0] == 1 or array.shape[1] == 1:
                return True
            else:
                raise ValueError('only 1D arrays are accepted')
    else:
        return True
    return True


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

        :param SharedLinkDisableType val:
        :rtype: EventType
        """
    return cls('shared_link_disable', val)


def getLevel(unique_name):
    """Returns a ILevel in the hierarchy with the given unique name."""


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