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]


def get_appliance(oneandone_conn, appliance, full_object=False):
    """
    Validates the appliance exists by ID or name.
    Return the appliance ID.
    """
    for _appliance in oneandone_conn.list_appliances(q='IMAGE'):
        if appliance in (_appliance['id'], _appliance['name']):
            if full_object:
                return _appliance
            return _appliance['id']


def _build_key(host, port):
    """Build a key based upon the hostname or address supplied."""
    return '%s:%s' % (host, port)


@staticmethod
def nested_get(dict, keys, key_delimiter='.'):
    """ Get the value of a nested dictionary at the nested key sequence `keys`

        Args:
            dict (:obj:`dict`): dictionary to retrieve value from
            keys (:obj:`str` or :obj:`list`): list of nested keys to retrieve
            key_delimiter (:obj:`str`, optional): delimiter for `keys`

        Returns:
            :obj:`object`: The value of `dict` from the nested keys list
        """
    if isinstance(keys, str):
        keys = keys.split(key_delimiter)
    nested_dict = dict
    for key in keys:
        nested_dict = nested_dict[key]
    return nested_dict


def getDependencies(item, attributeName='dependency.Dependency.dependencies'):
    """Helper method to initialize dependencies."""
    return getattr(item, attributeName, [])


def decimal_default(obj):
    """JSON serialization of Decimal.

    *Usage:*
      ``json.dumps(data, default=decimal_default)``

    Converts decimal to string.

    """
    if obj.__class__.__name__ == 'Decimal':
        return str(obj)
    raise TypeError


def Dt(f):
    """UFL operator: <Not implemented yet!> The partial derivative of *f* with respect to time."""
    raise NotImplementedError


def get_item_in_dict(dictionary, item):
    """
    Get dictionary item from a dotted-word.

    >>> get_item_in_dict({"x": 1}, "x")
    1
    >>> get_item_in_dict({"x": {"y": 42}}, "x.y")
    42
    """
    current = dictionary
    for word in item.split('.'):
        if word in current:
            current = current[word]
        else:
            return None
    return current


def _writeChunk(chunk, i, outfile, sep, missingValues, colnames, idcol):
    """Write a chunk of data to a file.

    :arg chunk:         ``pandas.DataFrame`` containing the data to write
    :arg i:             Chunk index - if ``0``, column headers are written
    :arg outfile:       File to write to
    :arg sep:           Separater character
    :arg missingValues: String to use for missing values
    :arg colnames:      Names for all columns
    :arg idcol:         Name for the index column
    """
    if i > 0:
        mode = 'a'
        colnames = False
        idcol = None
    else:
        mode = 'w'
    chunk.to_csv(outfile, sep=sep, na_rep=missingValues, header=colnames,
        index_label=idcol, mode=mode)


def match_node(var_name, node_id, node_label):
    """Query to match a node into the variable.

    Parameters
    ----------
    var_name
        Variable name to use for the matched node
    node_id
        Id of the node to match
    label
        Label of the node to match, default is 'node'
    """
    return "MATCH ({}:{} {{ id : '{}' }})\n".format(var_name, node_label,
        node_id)


def get_tensor_dimension(t):
    """Return dimension of the TF tensor in Int

    `get_shape()` returns `TensorShape`.

    """
    return len(t.get_shape())


def query_analysis(query, store, connection):
    """
    Helper function.

    For executing EXPLAIN on all dispatched SQL statements -
    for the pupose of analyzing index usage.

    """
    res = connection.execute('explain ' + query)
    rt = res.fetchall()[0]
    (table, joinType, posKeys, _key, key_len, comparedCol, rowsExamined, extra
        ) = rt
    if not _key:
        assert joinType == 'ALL'
        if not hasattr(store, 'queryOptMarks'):
            store.queryOptMarks = {}
        hits = store.queryOptMarks.get(('FULL SCAN', table), 0)
        store.queryOptMarks['FULL SCAN', table] = hits + 1
    if not hasattr(store, 'queryOptMarks'):
        store.queryOptMarks = {}
    hits = store.queryOptMarks.get((_key, table), 0)
    store.queryOptMarks[_key, table] = hits + 1


def add(filedata, meta, transaction, linkrev, p1, p2):
    """Add a new revision to the store.

        Takes file data, dictionary of metadata, a transaction, linkrev,
        and parent nodes.

        Returns the node that was added.

        May no-op if a revision matching the supplied data is already stored.
        """


@staticmethod
def claim_messages(client, queue_name, **params):
    """Claim messages from the queue

        :param client: the Zaqar client
        :type client: zaqarclient.queues.client

        :param queue_name: Name of the target queue.
        :type queue_name: `six.string_type`

        :returns: List of claims
        :rtype: `list`
        """
    queue = client.queue(queue_name)
    return queue.claim(**params)


def exit_ok():
    """A python implementation of /bin/true that can be used for testing"""
    return 0


def os_print_tofile(vv, file1, mode1='a'):
    """
    Here is a list of the different modes of opening a file:
r
Opens a file for reading only. The file pointer is placed at the beginning of the file.
This is the default mode.

rb

Opens a file for reading only in binary format. The file pointer is placed at the
beginning of the file. This is the default mode.
r+

Opens a file for both reading and writing. The file pointer will be at the beginning of the file.
rb+

Opens a file for both reading and writing in binary format. The file pointer will be at the
beginning of the file.
w

Opens a file for writing only. Overwrites the file if the file exists. If the file does not exist,
creates a new file for writing.
wb

Opens a file for writing only in binary format. Overwrites the file if the file exists.
If the file does not exist, creates a new file for writing.
w+

Opens a file for both writing and reading. Overwrites the existing file if the file exists.
If the file does not exist, creates a new file for reading and writing.
wb+

Opens a file for both writing and reading in binary format. Overwrites the existing file if
the file exists. If the file does not exist, creates a new file for reading and writing.
a

Opens a file for appending. The file pointer is at the end of the file if the file exists. That is,
the file is in the append mode. If the file does not exist, it creates a new file for writing.
ab

Opens a file for appending in binary format. The file pointer is at the end of the file if the file
exists. That is, the file is in the append mode. If the file does not exist, it creates a new file
for writing.
a+

Opens a file for both appending and reading. The file pointer is at the end of the file if the
file exists. The file opens in the append mode. If the file does not exist, it creates a new file
for reading and writing.
ab+

Opens a file for both appending and reading in binary format. The file pointer is at the end of
the file if the file exists. The file opens in the append mode. If the file does not exist,
it creates a new file for reading and writing.
To open a text file, use:
fh = open("hello.txt", "r")

To read a text file, use:
print fh.read()

To read one line at a time, use:
print fh.readline()

To read a list of lines use:
print fh.readlines()

To write to a file, use:
fh = open("hello.txt", "w")
lines_of_text = ["a line of text", "another line of text", "a third line"]
fh.writelines(lines_of_text)
fh.close()

To append to file, use:
fh = open("Hello.txt", "a")
fh.close()

    """
    with open(file1, mode1) as text_file:
        text_file.write(str(vv))


def point_on_rectangle(rect, point, border=False):
    """
    Return the point on which ``point`` can be projecten on the
    rectangle.  ``border = True`` will make sure the point is bound to
    the border of the reactangle. Otherwise, if the point is in the
    rectangle, it's okay.

    >>> point_on_rectangle(Rectangle(0, 0, 10, 10), (11, -1))
    (10, 0)
    >>> point_on_rectangle((0, 0, 10, 10), (5, 12))
    (5, 10)
    >>> point_on_rectangle(Rectangle(0, 0, 10, 10), (12, 5))
    (10, 5)
    >>> point_on_rectangle(Rectangle(1, 1, 10, 10), (3, 4))
    (3, 4)
    >>> point_on_rectangle(Rectangle(1, 1, 10, 10), (0, 3))
    (1, 3)
    >>> point_on_rectangle(Rectangle(1, 1, 10, 10), (4, 3))
    (4, 3)
    >>> point_on_rectangle(Rectangle(1, 1, 10, 10), (4, 9), border=True)
    (4, 11)
    >>> point_on_rectangle((1, 1, 10, 10), (4, 6), border=True)
    (1, 6)
    >>> point_on_rectangle(Rectangle(1, 1, 10, 10), (5, 3), border=True)
    (5, 1)
    >>> point_on_rectangle(Rectangle(1, 1, 10, 10), (8, 4), border=True)
    (11, 4)
    >>> point_on_rectangle((1, 1, 10, 100), (5, 8), border=True)
    (1, 8)
    >>> point_on_rectangle((1, 1, 10, 100), (5, 98), border=True)
    (5, 101)
    """
    px, py = point
    rx, ry, rw, rh = tuple(rect)
    x_inside = y_inside = False
    if px < rx:
        px = rx
    elif px > rx + rw:
        px = rx + rw
    elif border:
        x_inside = True
    if py < ry:
        py = ry
    elif py > ry + rh:
        py = ry + rh
    elif border:
        y_inside = True
    if x_inside and y_inside:
        if min(abs(rx - px), abs(rx + rw - px)) > min(abs(ry - py), abs(ry +
            rh - py)):
            if py < ry + rh / 2.0:
                py = ry
            else:
                py = ry + rh
        elif px < rx + rw / 2.0:
            px = rx
        else:
            px = rx + rw
    return px, py


def _get_start_size(d: dict) ->tuple((int, int)):
    """Returns a tuple of ints that represent the true start byte and size
    based on the provided dict.

    This is a convenience function such that if you have these values in a
    dictionary with a *StartByte* and *Bytes* keys.

    Since the StartByte labels on an ISIS cube are 1-based counts, and not
    0-based, in order to convert from the numbers provided in the labels
    to a byte count for Python's read() functions, you must subtract one
    from the listed StartByte, which this function does.
    """
    start = int(d['StartByte']) - 1
    size = int(d['Bytes'])
    return start, size


def pypi_url(varmap):
    """Return the PyPI URL for program ``name`` from the setup vars.
    """
    return 'http://pypi.org/project/{}'.format(varmap['name'])


@staticmethod
def p_qp_blob(p):
    """qp_blob : QP_BLOB IDENT"""


def get_model_class(full_name, settings_meta):
    """
    Returns a model class loaded from *full_name*. *settings_meta* is the name
    of the corresponding settings variable (used for error messages).
    """
    from django.core.exceptions import ImproperlyConfigured
    try:
        app_label, model_name = full_name.split('.')
    except ValueError:
        raise ImproperlyConfigured(
            "%s must be of the form 'app_label.model_name'" % settings_meta)
    model_class = None
    try:
        from django.apps import apps
        model_class = apps.get_model(app_label, model_name)
    except ImportError:
        from django.db.models import get_model
        model_class = get_model(app_label, model_name)
    if model_class is None:
        raise ImproperlyConfigured(
            "%s refers to model '%s' that has not been installed" % (
            settings_meta, full_name))
    return model_class


@classmethod
def check_exist_hash(cls, hash_key):
    """
        指定されたハッシュキーのレコードがあるか判定する

        :param hash_key: 検索対象値
        :return: bool
        """
    cls._setup()
    return cls._check_exist_hash(hash_key)


def map_float(to_float) ->float:
    """Maps value to float from a string.

    Parameters
    ----------
    to_float: various (usually str)
        Value to be converted to float.

    Returns
    -------
    mapped_float: float
        Value mapped to float.

    Examples
    --------
    >>> number_one = "1"

    >>> error_value = "will cause error"

    >>> one_to_float = map_float(number_one) # will convert to 1.0

    >>> error_to_float = map_float(error_value) # will cause exception
    """
    try:
        mapped_float = float(to_float)
    except ValueError:
        raise ValueError("Float Value Expected Got '{}'".format(to_float))
    return mapped_float


def remove_allowed_sender(allowed_sender):
    """
        Removes 'allowed_sender' from the list of allowed senders.  'allowed
        sender' can be either an email address or a userid.
        """


def brush_remove():
    """Remove active Grease Pencil drawing brush

    """
    pass


def _validate_dependencies_met():
    """
    Verifies that PyOpenSSL's package-level dependencies have been met.
    Throws `ImportError` if they are not met.
    """
    from cryptography.x509.extensions import Extensions
    if getattr(Extensions, 'get_extension_for_class', None) is None:
        raise ImportError(
            "'cryptography' module missing required functionality.  Try upgrading to v1.3.4 or newer."
            )
    from OpenSSL.crypto import X509
    x509 = X509()
    if getattr(x509, '_x509', None) is None:
        raise ImportError(
            "'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer."
            )


def get_name_tuple(name):
    """
    Returns a tuple of the stack name, split on the slashes.

    :param name: The Stack's name.
    :type name: str
    :returns: A tuple of the stack's name.
    :rtype: tuple
    """
    return tuple(name.split('/'))


@staticmethod
def _normalize_header(raw_headers_list):
    """Lower-case all header strings and replace periods with underscores.

        Args:
            raw_headers_list (List[str]): A list of the headers from the Annovar txt output file.

        Returns:
            List[str]: A list of the normalized headers, in the same order as the input list.
        """
    normalized_headers_list = []
    for curr_header in raw_headers_list:
        normalized_headers_list.append(curr_header.lower().replace('.', '_'))
    return normalized_headers_list


def p_value_fields0(p):
    """
    value_fields : value_field
    """
    p[0] = [p[1]]


def rip_edge_move(MESH_OT_rip_edge=None, TRANSFORM_OT_translate=None):
    """Extend vertices and move the result

    :param MESH_OT_rip_edge: Extend Vertices, Extend vertices along the edge closest to the cursor
    :param TRANSFORM_OT_translate: Move, Move selected items
    """
    pass


def mkIterableSequence(obj):
    """Place obj in a tuple if obj is not a sequence container.

    Useful for handing cases where a single event can be passed to
        a function that habitually handles sequences of events.
    """
    if not hasattr(obj, '__iter__'):
        obj = obj,
    return obj


def _downsample(st, sr):
    """
        Downsampling the MSEED to the designated sampling rate
    """
    for i in range(0, len(st)):
        st[i].decimate(factor=int(st[i].stats.sampling_rate / sr),
            strict_length=False)
    return st


@classmethod
def start(cls):
    """Start the thread where the Metrics Collector starts."""
    cls.thread.start()


@classmethod
def from_rgba(cls, red=0, green=0, blue=0, alpha=255):
    """
        Create color from RGBa components.
        """
    new = object.__new__(cls)
    new._fromrgba(red, green, blue, alpha)
    return new


@staticmethod
def isIDEVersionCompatible(ideVersion):
    """Codimension makes this call before activating a plugin.

        The passed ideVersion is a string representing
        the current IDE version.
        True should be returned if the plugin is compatible with the IDE.
        """
    raise Exception('isIDEVersionCompatible() must be overridden')


def __call__():
    """Return the opaque items value.
        """


def func_mv_ppf(x, variant_params, p):
    """Function CDF of max of pareto random variables for root-finding."""
    cdf = 1.0
    for a, b in variant_params:
        cdf *= 1 - (b / x) ** a
    return cdf - p


def weld_verts(bm: 'bmesh.types.BMesh', targetmap: dict):
    """Welds verts together (kind-of like remove doubles, merge, etc, all of which use or will use this bmop). You pass in mappings from vertices to the vertices they weld with.

    :param bm: The bmesh to operate on.
    :type bm: 'bmesh.types.BMesh'
    :param targetmap: Undocumented.
    :type targetmap: dict
    """
    pass


def comma_separate(elements) ->str:
    """Map a list to strings and make comma separated."""
    return ', '.join(map(str, elements))


def filte_dict(_dict, callback):
    """
    >>> from django.conf import settings
    >>> settings.configure()
    >>> d = {"a":1, "b":2, "c":3}
    >>> filte_dict(d, lambda k,v: k != "b")

    :param _dict:
    :param callback:
    :return:
    """
    if not isinstance(_dict, dict):
        raise TypeError('Invalid dict:%s' % _dict)
    rs = {}
    for k, v in _dict.items():
        if callback(k, v):
            rs[k] = v
    return rs


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 match_texture_space():
    """Match texture space to object’s bounding box

    """
    pass


def union(a, b):
    """
    union(list, list):
    """
    c = a[:]
    for i in b:
        if i not in c:
            c.append(i)
    return c


def rotateRight(arr, l, r):
    """Right rotation of all array elements between l and r"""
    temp = arr[r]
    for i in range(r, l, -1):
        arr[i] = arr[i - 1]
    arr[l] = temp


def default_key_func(key, key_prefix, version):
    """
    Default function to generate keys.

    Constructs the key used by all other methods. By default it prepends
    the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
    function with custom key making behavior.
    """
    return '%s:%s:%s' % (key_prefix, version, key)


def total_memory_read(st):
    """ Memory read (in GB) including overlapping read at segment boundaries.
    """
    return st.nsegment * st.vismem


def drop_named_material(name: str='Material'):
    """Undocumented contribute <https://developer.blender.org/T51061>

    :param name: Name, Material name to assign
    :type name: str
    """
    pass


def Akmaev_adjustment(theta, q, beta, n_k, theta_k, s_k, t_k):
    """Single column only."""
    L = q.size
    k = 1
    n_k[k - 1] = 1
    theta_k[k - 1] = theta[k - 1]
    l = 2
    while True:
        n = 1
        thistheta = theta[l - 1]
        while True:
            if theta_k[k - 1] <= thistheta:
                k += 1
                break
            else:
                if n <= 1:
                    s = q[l - 1]
                    t = s * thistheta
                if n_k[k - 1] <= 1:
                    s_k[k - 1] = q[l - n - 1]
                    t_k[k - 1] = s_k[k - 1] * theta_k[k - 1]
                n += n_k[k - 1]
                s += s_k[k - 1]
                t += t_k[k - 1]
                s_k[k - 1] = s
                t_k[k - 1] = t
                thistheta = t / s
                if k == 1:
                    break
                k -= 1
        if l == L:
            break
        l += 1
        n_k[k - 1] = n
        theta_k[k - 1] = thistheta
    while True:
        while True:
            if n == 1:
                break
            while True:
                theta[l - 1] = thistheta
                if n == 1:
                    break
                l -= 1
                n -= 1
        if k == 1:
            break
        k -= 1
        l -= 1
        n = n_k[k - 1]
        thistheta = theta_k[k - 1]
    return theta


@classmethod
def _merge(cls, default, user):
    """Append user options to default options. Return yala section."""
    section = cls._CFG_SECTION
    merged = default[section]
    if section not in user:
        return merged
    user = user[section]
    for key, value in user.items():
        if key in merged:
            merged[key] += ' ' + value
        else:
            merged[key] = value
    return merged


def _set_graph_edge(graph, tokens, word_a, word_b):
    """Sets an edge between nodes named word_a and word_b if they exists in `tokens` and `graph`, inplace.

    Parameters
    ----------
    graph : :class:~gensim.summarization.graph.Graph
        Given graph.
    tokens : dict
        Original units (words) as keys and processed units (tokens) as values.
    word_a : str
        First word, name of first node.
    word_b : str
        Second word, name of second node.

    """
    if word_a in tokens and word_b in tokens:
        lemma_a = tokens[word_a].token
        lemma_b = tokens[word_b].token
        edge = lemma_a, lemma_b
        if graph.has_node(lemma_a) and graph.has_node(lemma_b
            ) and not graph.has_edge(edge):
            graph.add_edge(edge)


def filter_except(validator, iterable, *exceptions):
    """Yield the items from *iterable* for which the *validator* function does
    not raise one of the specified *exceptions*.

    *validator* is called for each item in *iterable*.
    It should be a function that accepts one argument and raises an exception
    if that item is not valid.

    >>> iterable = ['1', '2', 'three', '4', None]
    >>> list(filter_except(int, iterable, ValueError, TypeError))
    ['1', '2', '4']

    If an exception other than one given by *exceptions* is raised by
    *validator*, it is raised like normal.
    """
    exceptions = tuple(exceptions)
    for item in iterable:
        try:
            validator(item)
        except exceptions:
            pass
        else:
            yield item


def registerDB(wrapper):
    """Register a storage wrapper IStorageWrapper.

        The passed object is a wrapper object that provides an upcall
        interface to support composition.

        Note that, for historical reasons, this is called registerDB rather
        than register_wrapper.
        """


def unmute(unselected: bool=False):
    """Unmute (un)selected strips

    :param unselected: Unselected, Unmute unselected rather than selected strips
    :type unselected: bool
    """
    pass


@staticmethod
def verify_credentials():
    """
        Checks if the service is properly set-up
        Returns True or False
        """
    raise NotImplementedError


def write_output(entry, description, sequence):
    """Write a sequence and its header to its .txt file.

    While writing, also increase the marker counter and count the number of
    times this particular sequence has been found.

    :arg list entry: Library entry.
    :arg str description: Sequence header.
    :arg str sequence:  The sequence.
    """
    entry[3].write('>{}\n'.format(description))
    entry[3].write('{}\n'.format(sequence))
    entry[5] += 1
    if sequence in entry[6]:
        entry[6][sequence][1] += 1
    else:
        entry[6][sequence] = [description, 1]


def add_vertex(location: float=(0.0, 0.0)):
    """Add vertex to active spline

    :param location: Location, Location of vertex in normalized space
    :type location: float
    """
    pass


@staticmethod
def static_detect_presence(path):
    """For auto detection"""
    raise NotImplementedError(
        'Base class detect_presence method must be overridden')


def append_rainfall(network_source, rainfall_source, destination=
    './temp_network.inp', event_name='TestRain'):
    """

    Appends rainfall timeseries from a pandas time series to the swmm input file by creating
    a new copy of the network.

    Parameters
    ----------
    network_source
        Path to swmm input file
    rainfall_source
        Pandas.Series of timestamped rainfall
    destination
        Path to make the copy of the swmm file
    event_name
        Name of the Event

    Returns
    -------
    path
        Path to the swmm inp file with Rainfall
    """
    path_to_file = destination
    with open(network_source) as source:
        with open(path_to_file, 'w') as destination:
            for line in source:
                destination.write(line)
            destination.write('\n')
            destination.write('[TIMESERIES] \n')
            destination.write(';;Name           Date       Time       Value \n'
                )
            destination.write(
                ';;-------------- ---------- ---------- ---------- \n')
            for i in range(0, len(rainfall_source)):
                destination.write(
                    '{0: <14}   {1}/{2}/{3:<6} {4}:{5}:{6: <3}   {7} \n'.
                    format(event_name, rainfall_source.index[i].month,
                    rainfall_source.index[i].day, rainfall_source.index[i].
                    year, rainfall_source.index[i].hour, rainfall_source.
                    index[i].minute, rainfall_source.index[i].second,
                    rainfall_source[i]))
    return path_to_file


def write_gmt(d_gmt, filename):
    """
    Write a dictionary of sets to a gmt file.

    :param d_gmt: a dictionary of sets
    :param filename: filename for the GMT file
    :return: returns nothing
    """
    with open(filename, 'w') as out:
        for term, items in d_gmt.items():
            out.write(term + '\t' + '\t'.join(list(items)) + '\n')
    return


def confirm(prompt=None, resp=False):
    """
        Source: http://code.activestate.com/recipes/541096-prompt-the-user-for-confirmation/

        prompts for yes or no response from the user. Returns True for yes and
        False for no.

        'resp' should be set to the default value assumed by the caller when
        user simply types ENTER.

        >>> confirm(prompt='Create Directory?', resp=True)
        Create Directory? [y]|n:
        True
    """
    if prompt is None:
        prompt = 'Confirm'
    if resp:
        prompt = '%s [Y/n]: ' % prompt
    else:
        prompt = '%s [y/N]: ' % prompt
    while True:
        ans = input(prompt)
        if not ans:
            return resp
        if ans not in ['y', 'Y', 'n', 'N']:
            print('please enter y or n.')
            continue
        if ans == 'y' or ans == 'Y':
            return True
        if ans == 'n' or ans == 'N':
            return False


def replace():
    """Replace text with the specified text

    """
    pass


def strings_differ(string1, string2):
    """Check whether two strings differ while avoiding timing attacks.

    This function returns True if the given strings differ and False
    if they are equal.  It's careful not to leak information about *where*
    they differ as a result of its running time, which can be very important
    to avoid certain timing-related crypto attacks:

        http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf

    """
    if len(string1) != len(string2):
        return True
    invalid_bits = 0
    for a, b in zip(string1, string2):
        invalid_bits += a != b
    return invalid_bits != 0


def format_range(range):
    """Format a range into a string suitable for a Content-Range: header.
    """
    return 'bytes {0}-{1}/{2}'.format(*range)


def _getNumUniqueValues(values, bgVals):
    """Get the number of unique values connected to this junction.
       All background values are considered the same"""
    v, b = set(values), set(bgVals)
    return len(v.difference(b)) + (1 if v.intersection(b) else 0)


def printstepcolophon(step, *, file, id):
    """Prints out the heading of the step to the output file"""
    print('--- ' + step.name + ' ---', file=file)


def add_instance_groups(InstanceGroups=None, JobFlowId=None):
    """
    Adds one or more instance groups to a running cluster.
    See also: AWS API Documentation

    :example: response = client.add_instance_groups(
        InstanceGroups=[
            {
                'Name': 'string',
                'Market': 'ON_DEMAND'|'SPOT',
                'InstanceRole': 'MASTER'|'CORE'|'TASK',
                'BidPrice': 'string',
                'InstanceType': 'string',
                'InstanceCount': 123,
                'Configurations': [
                    {
                        'Classification': 'string',
                        'Configurations': {'... recursive ...'},
                        'Properties': {
                            'string': 'string'
                        }
                    },
                ],
                'EbsConfiguration': {
                    'EbsBlockDeviceConfigs': [
                        {
                            'VolumeSpecification': {
                                'VolumeType': 'string',
                                'Iops': 123,
                                'SizeInGB': 123
                            },
                            'VolumesPerInstance': 123
                        },
                    ],
                    'EbsOptimized': True|False
                },
                'AutoScalingPolicy': {
                    'Constraints': {
                        'MinCapacity': 123,
                        'MaxCapacity': 123
                    },
                    'Rules': [
                        {
                            'Name': 'string',
                            'Description': 'string',
                            'Action': {
                                'Market': 'ON_DEMAND'|'SPOT',
                                'SimpleScalingPolicyConfiguration': {
                                    'AdjustmentType': 'CHANGE_IN_CAPACITY'|'PERCENT_CHANGE_IN_CAPACITY'|'EXACT_CAPACITY',
                                    'ScalingAdjustment': 123,
                                    'CoolDown': 123
                                }
                            },
                            'Trigger': {
                                'CloudWatchAlarmDefinition': {
                                    'ComparisonOperator': 'GREATER_THAN_OR_EQUAL'|'GREATER_THAN'|'LESS_THAN'|'LESS_THAN_OR_EQUAL',
                                    'EvaluationPeriods': 123,
                                    'MetricName': 'string',
                                    'Namespace': 'string',
                                    'Period': 123,
                                    'Statistic': 'SAMPLE_COUNT'|'AVERAGE'|'SUM'|'MINIMUM'|'MAXIMUM',
                                    'Threshold': 123.0,
                                    'Unit': 'NONE'|'SECONDS'|'MICRO_SECONDS'|'MILLI_SECONDS'|'BYTES'|'KILO_BYTES'|'MEGA_BYTES'|'GIGA_BYTES'|'TERA_BYTES'|'BITS'|'KILO_BITS'|'MEGA_BITS'|'GIGA_BITS'|'TERA_BITS'|'PERCENT'|'COUNT'|'BYTES_PER_SECOND'|'KILO_BYTES_PER_SECOND'|'MEGA_BYTES_PER_SECOND'|'GIGA_BYTES_PER_SECOND'|'TERA_BYTES_PER_SECOND'|'BITS_PER_SECOND'|'KILO_BITS_PER_SECOND'|'MEGA_BITS_PER_SECOND'|'GIGA_BITS_PER_SECOND'|'TERA_BITS_PER_SECOND'|'COUNT_PER_SECOND',
                                    'Dimensions': [
                                        {
                                            'Key': 'string',
                                            'Value': 'string'
                                        },
                                    ]
                                }
                            }
                        },
                    ]
                }
            },
        ],
        JobFlowId='string'
    )

    :type InstanceGroups: list
    :param InstanceGroups: [REQUIRED]
            Instance groups to add.
            (dict) --Configuration defining a new instance group.
            Name (string) --Friendly name given to the instance group.
            Market (string) --Market type of the EC2 instances used to create a cluster node.
            InstanceRole (string) -- [REQUIRED]The role of the instance group in the cluster.
            BidPrice (string) --Bid price for each EC2 instance in the instance group when launching nodes as Spot Instances, expressed in USD.
            InstanceType (string) -- [REQUIRED]The EC2 instance type for all instances in the instance group.
            InstanceCount (integer) -- [REQUIRED]Target number of instances for the instance group.
            Configurations (list) --
            Note
            Amazon EMR releases 4.x or later.
            The list of configurations supplied for an EMR cluster instance group. You can specify a separate configuration for each instance group (master, core, and task).
            (dict) --
            Note
            Amazon EMR releases 4.x or later.
            An optional configuration specification to be used when provisioning cluster instances, which can include configurations for applications and software bundled with Amazon EMR. A configuration consists of a classification, properties, and optional nested configurations. A classification refers to an application-specific configuration file. Properties are the settings you want to change in that file. For more information, see Configuring Applications .
            Classification (string) --The classification within a configuration.
            Configurations (list) --A list of additional configurations to apply within a configuration object.
            Properties (dict) --A set of properties specified within a configuration classification.
            (string) --
            (string) --

            EbsConfiguration (dict) --EBS configurations that will be attached to each EC2 instance in the instance group.
            EbsBlockDeviceConfigs (list) --An array of Amazon EBS volume specifications attached to a cluster instance.
            (dict) --Configuration of requested EBS block device associated with the instance group with count of volumes that will be associated to every instance.
            VolumeSpecification (dict) -- [REQUIRED]EBS volume specifications such as volume type, IOPS, and size (GiB) that will be requested for the EBS volume attached to an EC2 instance in the cluster.
            VolumeType (string) -- [REQUIRED]The volume type. Volume types supported are gp2, io1, standard.
            Iops (integer) --The number of I/O operations per second (IOPS) that the volume supports.
            SizeInGB (integer) -- [REQUIRED]The volume size, in gibibytes (GiB). This can be a number from 1 - 1024. If the volume type is EBS-optimized, the minimum value is 10.
            VolumesPerInstance (integer) --Number of EBS volumes with a specific volume configuration that will be associated with every instance in the instance group

            EbsOptimized (boolean) --Indicates whether an Amazon EBS volume is EBS-optimized.
            AutoScalingPolicy (dict) --An automatic scaling policy for a core instance group or task instance group in an Amazon EMR cluster. The automatic scaling policy defines how an instance group dynamically adds and terminates EC2 instances in response to the value of a CloudWatch metric. See PutAutoScalingPolicy .
            Constraints (dict) -- [REQUIRED]The upper and lower EC2 instance limits for an automatic scaling policy. Automatic scaling activity will not cause an instance group to grow above or below these limits.
            MinCapacity (integer) -- [REQUIRED]The lower boundary of EC2 instances in an instance group below which scaling activities are not allowed to shrink. Scale-in activities will not terminate instances below this boundary.
            MaxCapacity (integer) -- [REQUIRED]The upper boundary of EC2 instances in an instance group beyond which scaling activities are not allowed to grow. Scale-out activities will not add instances beyond this boundary.
            Rules (list) -- [REQUIRED]The scale-in and scale-out rules that comprise the automatic scaling policy.
            (dict) --A scale-in or scale-out rule that defines scaling activity, including the CloudWatch metric alarm that triggers activity, how EC2 instances are added or removed, and the periodicity of adjustments. The automatic scaling policy for an instance group can comprise one or more automatic scaling rules.
            Name (string) -- [REQUIRED]The name used to identify an automatic scaling rule. Rule names must be unique within a scaling policy.
            Description (string) --A friendly, more verbose description of the automatic scaling rule.
            Action (dict) -- [REQUIRED]The conditions that trigger an automatic scaling activity.
            Market (string) --Not available for instance groups. Instance groups use the market type specified for the group.
            SimpleScalingPolicyConfiguration (dict) -- [REQUIRED]The type of adjustment the automatic scaling activity makes when triggered, and the periodicity of the adjustment.
            AdjustmentType (string) --The way in which EC2 instances are added (if ScalingAdjustment is a positive number) or terminated (if ScalingAdjustment is a negative number) each time the scaling activity is triggered. CHANGE_IN_CAPACITY is the default. CHANGE_IN_CAPACITY indicates that the EC2 instance count increments or decrements by ScalingAdjustment , which should be expressed as an integer. PERCENT_CHANGE_IN_CAPACITY indicates the instance count increments or decrements by the percentage specified by ScalingAdjustment , which should be expressed as a decimal. For example, 0.20 indicates an increase in 20% increments of cluster capacity. EXACT_CAPACITY indicates the scaling activity results in an instance group with the number of EC2 instances specified by ScalingAdjustment , which should be expressed as a positive integer.
            ScalingAdjustment (integer) -- [REQUIRED]The amount by which to scale in or scale out, based on the specified AdjustmentType . A positive value adds to the instance group's EC2 instance count while a negative number removes instances. If AdjustmentType is set to EXACT_CAPACITY , the number should only be a positive integer. If AdjustmentType is set to PERCENT_CHANGE_IN_CAPACITY , the value should express the percentage as a decimal. For example, -0.20 indicates a decrease in 20% increments of cluster capacity.
            CoolDown (integer) --The amount of time, in seconds, after a scaling activity completes before any further trigger-related scaling activities can start. The default value is 0.

            Trigger (dict) -- [REQUIRED]The CloudWatch alarm definition that determines when automatic scaling activity is triggered.
            CloudWatchAlarmDefinition (dict) -- [REQUIRED]The definition of a CloudWatch metric alarm. When the defined alarm conditions are met along with other trigger parameters, scaling activity begins.
            ComparisonOperator (string) -- [REQUIRED]Determines how the metric specified by MetricName is compared to the value specified by Threshold .
            EvaluationPeriods (integer) --The number of periods, expressed in seconds using Period , during which the alarm condition must exist before the alarm triggers automatic scaling activity. The default value is 1 .
            MetricName (string) -- [REQUIRED]The name of the CloudWatch metric that is watched to determine an alarm condition.
            Namespace (string) --The namespace for the CloudWatch metric. The default is AWS/ElasticMapReduce .
            Period (integer) -- [REQUIRED]The period, in seconds, over which the statistic is applied. EMR CloudWatch metrics are emitted every five minutes (300 seconds), so if an EMR CloudWatch metric is specified, specify 300 .
            Statistic (string) --The statistic to apply to the metric associated with the alarm. The default is AVERAGE .
            Threshold (float) -- [REQUIRED]The value against which the specified statistic is compared.
            Unit (string) --The unit of measure associated with the CloudWatch metric being watched. The value specified for Unit must correspond to the units specified in the CloudWatch metric.
            Dimensions (list) --A CloudWatch metric dimension.
            (dict) --A CloudWatch dimension, which is specified using a Key (known as a Name in CloudWatch), Value pair. By default, Amazon EMR uses one dimension whose Key is JobFlowID and Value is a variable representing the cluster ID, which is ${emr.clusterId} . This enables the rule to bootstrap when the cluster ID becomes available.
            Key (string) --The dimension name.
            Value (string) --The dimension value.

    :type JobFlowId: string
    :param JobFlowId: [REQUIRED]
            Job flow in which to add the instance groups.

    :rtype: dict
    :return: {
        'JobFlowId': 'string',
        'InstanceGroupIds': [
            'string',
        ]
    }

    :returns:
    (string) --

    """
    pass


def my_range(start, end, step):
    """Iterable `range` adapted for fractions.

    Parameters
    ----------
    start : Number
        Start value (included).
    end : Number
        End value (excluded).
    step : Number
        Increment of the counter.

    Examples
    --------
        >>> for x in my_range(0, 1, Fraction(1, 3)):
        ...     print(x)
        0
        1/3
        2/3

        >>> for x in my_range(1, 0, - Fraction(1, 3)):
        ...     print(x)
        1
        2/3
        1/3
    """
    val = start
    if step > 0:
        while val < end:
            yield val
            val += step
    else:
        while val > end:
            yield val
            val += step


@classmethod
def from_dict(cls, parsed_dict):
    """Create an InviteEvent from a dictionary.

        Args:
            parsed_dict (dict): The dictionary representation of the event.

        """
    raise NotImplementedError()


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

        :param TeamMergeRequestReminderShownToPrimaryTeamType val:
        :rtype: EventType
        """
    return cls('team_merge_request_reminder_shown_to_primary_team', val)


def increment_version(current):
    """Increments minor revision number by one"""
    major = '.'.join(current.split('.')[:2])
    minor = int(current.split('.')[-1]) + 1
    return '.'.join([major, str(minor)])


def make_pre_wrappable(html, wrap_limit=60, split_on=';?&@!$#-/\\"\''):
    """
    Like ``make_wrappable()`` but intended for text that will
    go in a ``<pre>`` block, so wrap on a line-by-line basis.
    """
    lines = html.splitlines()
    new_lines = []
    for line in lines:
        if len(line) > wrap_limit:
            for char in split_on:
                if char in line:
                    parts = line.split(char)
                    line = '<wbr>'.join(parts)
                    break
        new_lines.append(line)
    return '\n'.join(lines)


def get_ldap_value(data, key):
    """Safely extract LDAP values"""
    data = data.get(key)
    if isinstance(data, (list, tuple)):
        return data[0] if len(data) else None
    else:
        return data


def is_power_of_2(num):
    """
    Returns whether num is a power of two or not
    :param num: an integer positive number
    :return: True if num is a power of 2, False otherwise
    """
    return num != 0 and num & num - 1 == 0


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

        :param WebSessionsChangeActiveSessionLimitType val:
        :rtype: EventType
        """
    return cls('web_sessions_change_active_session_limit', val)


def get(id, connection=None):
    """
        Returns the object with the given `id`.  If `connection` is
        given, then get the object from the given connection
        (otherwise use the default or configured connection)

        It raises ``SQLObjectNotFound`` if no row exists with that ID.
        """


def get_meta_data():
    """
        Get the readings meta-data.
        """
    return {'air_temperature': {'type': 'gauge', 'unit': 'C', 'precision':
        2, 'range_low': 0, 'range_high': 100, 'sensor': 'flower_power'},
        'soil_temperature': {'type': 'gauge', 'unit': 'C', 'precision': 2,
        'range_low': 0, 'range_high': 100, 'sensor': 'flower_power'}}


def to_numpy_matrix(G, edge_sign=1.0, not_edge_sign=0.0):
    """
    Returns the graph adjacency matrix as a NumPy matrix.

    Parameters
    ----------
    edge_sign : float
        Sign for the position of matrix where there is an edge

    not_edge_sign : float
        Sign for the position of matrix where there is no edge

    """
    import numpy as np
    index_of_node = dict(zip(G.nodes, range(len(G))))
    N = len(G)
    M = np.full((N, N), not_edge_sign)
    for u, udict in G.adj.items():
        for v, data in udict.items():
            M[index_of_node[u], index_of_node[v]] = edge_sign
    M = np.asmatrix(M)
    return M


def __get_name_options_mapping(cls):
    """
        Dict of {'name': option} mapping.
        DO NOT change this dict. TODO: make it immutable.

        :return: dict {"name": option}
        """
    return cls.__name_options_mapping__


def get_requester_ip(request):
    """
    Get Client IP Address
    :return:
    """
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip


def lfn_unmerged_bases():
    """Return list of LFN unmerged bases"""
    out = ['/store/unmerged', '/store/data', '/store/temp']
    return out


def isnumeric(value):
    """Return True if `value` can be converted to a float."""
    try:
        float(value)
        return True
    except (ValueError, TypeError):
        return False


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 set_libodbc_path(path):
    """
    Set the first path that GraphLab Create will search for libodbc.so.

    Since ODBC requires a driver manager to be installed system-wide, we
    provide this to help you if it is installed in a non-standard location.
    GraphLab Create will also search on the system's default library paths, so
    if you installed your driver manager in a standard way, you shouldn't need
    to worry about this function.
    """
    from .. import set_runtime_config
    set_runtime_config('GRAPHLAB_LIBODBC_PREFIX', path)


def _read_tag_garbage_str(dmfile):
    """
    DM4 has four bytes of % symbols in the tag.  Ensure it is there.
    """
    garbage_str = dmfile.read(4).decode('utf-8')
    assert garbage_str == '%%%%'


def hide_link(url: str) ->str:
    """
    Hide URL (HTML only)
    Can be used for adding an image to a text message

    :param url:
    :return:
    """
    return f''


def ftos(Float_Value):
    """
    string ftos(float)

    convert float to string
    Instead of using python's ftos(), use this one to control the precision
    my Float to String mini function

    Precision = %.4f
    Unnecessary 0 will be discarded
    """
    S = '%.4f' % Float_Value
    n = len(S)
    if S[n - 5] == '.':
        if S[n - 4:n] == '0000':
            S = S[0:n - 5]
        elif S[n - 3:n] == '000':
            S = S[0:n - 3]
        elif S[n - 2:n] == '00':
            S = S[0:n - 2]
        elif S[n - 1] == '0':
            S = S[0:n - 1]
    return S


def get_all_utilities_registered_for(interface, context=None):
    """Return all registered utilities for an interface

        This includes overridden utilities.

        An iterable of utility instances is returned.  No names are
        returned.
        """


def unshuffle(sinogram):
    """ unshuffle singram by angle

    Return a list of 51 sinograms, by unshuffling the provided
    sinogram; so that all projections in the result correspond
    to the same gantry rotation angle, analogous to a fluence map.

    Parameters
    ----------
    sinogram : np.array

    Returns
    -------
    unshuffled: list of sinograms

    """
    unshufd = [[] for i in range(51)]
    idx = 0
    for prj in sinogram:
        unshufd[idx].append(prj)
        idx = (idx + 1) % 51
    return unshufd


def json_converter(obj):
    """
    Converts sets to list during JSON serialization
    """
    if isinstance(obj, (set, frozenset)):
        return tuple(obj)
    raise TypeError


def addslashes(s, escaped_chars=None):
    """Add slashes for given characters. Default is for ``\\`` and ``'``.

    :param s: string
    :param escaped_chars: list of characters to prefix with a slash ``\\``
    :return: string with slashed characters
    :rtype: str

    :Example:
        >>> addslashes("'")
        "\\'"
    """
    if escaped_chars is None:
        escaped_chars = ['\\', "'"]
    for i in escaped_chars:
        if i in s:
            s = s.replace(i, '\\' + i)
    return s


def properties():
    """Toggle the properties region visibility

    """
    pass


def volumic_power_to_power(volumic_power, volume):
    """Convert volumic power to power."""
    return volumic_power * volume


def move_detach_links(NODE_OT_links_detach=None, TRANSFORM_OT_translate=
    None, NODE_OT_insert_offset=None):
    """Move a node to detach links

    :param NODE_OT_links_detach: Detach Links, Remove all links to selected nodes, and try to connect neighbor nodes together
    :param TRANSFORM_OT_translate: Translate, Translate (move) selected items
    :param NODE_OT_insert_offset: Insert Offset, Automatically offset nodes on insertion
    """
    pass


def _get_timezone_name(timezone):
    """
    Returns the name of ``timezone``.
    """
    try:
        return timezone.zone
    except AttributeError:
        return timezone.tzname(None)


def num_items():
    """Number of items in index."""


def format_timedelta(td):
    """Format timedelta in a human friendly format
    """
    ts = td.total_seconds()
    s = ts % 60
    m = int(ts / 60) % 60
    h = int(ts / 3600) % 24
    txt = '%.2f seconds' % s
    if m:
        txt = '%d minutes %s' % (m, txt)
    if h:
        txt = '%d hours %s' % (h, txt)
    if td.days:
        txt = '%d days %s' % (td.days, txt)
    return txt


@classmethod
def tenor(cls, today, expiration):
    """tenor computes the tenor of an SPX option following the
        CBOE's VIX methodology (see white paper).

        Args:
            today (datetime): A datetime object containing the quote datetime
                   of the option. Must have year, month, day, hour, minute and
                   second.
            expiration (date): A date object containing the expiration
                   date of the option. Must have year, month and day only.

        Returns:
            tenor (float): Tenor of the option in years.
        """
    assert expiration.isoweekday() != 7, 'Option expires on Sunday'
    if expiration.isoweekday() == 6:
        expiration = expiration.replace(day=expiration.day - 1)
    minutes_current_day = (today.replace(hour=23, minute=59) - today
        ).seconds // 60 + 1
    minutes_other = ((expiration - today.date()).days - 1) * (24 * 60)
    if cls.isStandard(expiration):
        minutes_settlement = 9.5 * 60
    else:
        minutes_settlement = (9.5 + 2.5 + 4) * 60
    minutes_to_expiration = (minutes_current_day + minutes_other +
        minutes_settlement)
    return minutes_to_expiration / cls.MINUTES_IN_YEAR


def dmas_bn(module, input, output):
    """DMAs estimation for `torch.nn.modules.batchnorm._BatchNorm`"""
    input_dma = input.numel()
    ops_dma = module.running_mean.numel() + module.running_var.numel() + 1
    if module.affine:
        ops_dma += module.weight.data.numel() + module.bias.data.numel()
    if module.momentum:
        ops_dma += 1
    if module.training and module.track_running_stats:
        ops_dma += module.num_batches_tracked.numel(
            ) + module.running_mean.numel() + module.running_var.numel()
    output_dma = output.numel()
    return input_dma + ops_dma + output_dma


def read_genome_dir_file(genome_dir_file):
    """Read genome directories from file.

    Parameters
    ----------
    genome_dir_file : str
        File to read.

    Returns
    -------
    dict : d[genome_id] -> directory
        Directory for each genome.
    """
    genome_dirs = {}
    for line in open(genome_dir_file):
        line_split = line.split('\t')
        genome_dirs[line_split[0]] = line_split[1].strip()
    return genome_dirs


def get_pub_id(title, authors, year):
    """construct publication id"""
    if len(title.split(' ')) > 1 and title.split(' ')[0].lower() in ['the', 'a'
        ]:
        _first_word = title.split(' ')[1].split('_')[0]
    else:
        _first_word = title.split(' ')[0].split('_')[0]
    pub_id = authors[0].split(',')[0].split(' ')[0] + _first_word + str(year)
    return pub_id


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 edge2Taz(tazs):
    """Returns the associative array of the TAZ of each SUMO edge"""
    edge2Tazs = {}
    for taz, edges in tazs.items():
        for edge in edges:
            if edge in edge2Tazs:
                print('error for edge: {} (taz {}/{})'.format(edge,
                    edge2Tazs[edge], taz))
            edge2Tazs[edge] = taz
    return edge2Tazs


def rect(img, corners, color='r', linewidth=3):
    """
        Draw rectangle on image

        Add limits according to image dimensions
        Parameters
        ----------
        corners : list
            ymin,ymax,xmin,xmax
        linewidth : int
            number of pixels the lines od the rectangle cover. Should
            be odd.
        Returns
        -------
    """
    colrgb = [255, 0, 0]
    olap = (linewidth - 1) / 2
    img[corners[1] - olap:corners[1] + olap + 1, corners[2]:corners[3]
        ] = colrgb
    img[corners[0] - olap:corners[0] + olap + 1, corners[2]:corners[3]
        ] = colrgb
    img[corners[0]:corners[1], corners[2] - olap:corners[2] + olap + 1
        ] = colrgb
    img[corners[0]:corners[1], corners[3] - olap:corners[3] + olap + 1
        ] = colrgb
    return img


def extract(fname):
    """Extracts file contents.

    .. warning:: Bytes are returned for Python 3.

    :param str|unicode fname:

    :rtype: bytes|str
    """


def _remove_empty_events(sse):
    """
    Given a sequence of synchronous events (SSE) sse consisting of a pool of
    pixel positions and associated synchronous events (see below), returns a
    copy of sse where all empty events have been removed.

    sse must be provided as a dictionary of type

    .. centered:: {(i1, j1): S1, (i2, j2): S2, ..., (iK, jK): SK},

    where each i, j is an integer and each S is a set of neuron ids.
    (See also: extract_sse() that extracts SSEs from given spiketrains).

    Parameters
    ----------
    sse : dict
        a dictionary of pixel positions (i, j) as keys, and sets S of
        synchronous events as values (see above).

    Returns
    -------
    sse_new : dict
        a copy of sse where all empty events have been removed.
    """
    sse_new = sse.copy()
    for pixel, link in sse.items():
        if link == set([]):
            del sse_new[pixel]
    return sse_new


def with_suffix(number, base=1000):
    """Convert number to string with SI suffix, e.g.: 14226 -> 14.2k, 5395984 -> 5.39M"""
    mapping = {(base ** 3): 'G', (base ** 2): 'M', base: 'k'}
    for bucket, suffix in mapping.items():
        if number > 0.999 * bucket:
            return '{:.3g}{}'.format(number / bucket, suffix)
    return '{:.3g}'.format(number)


def dt_average(a, b):
    """ Average function that is friendly with datetime formats that only
    support substraction. """
    return a + (b - a) / 2


@classmethod
def validate_exported_energy(cls, measures):
    """
        Check if there are ProfileHour with energy != 0 in periods with RE coefficient == 0
        :param measures: A list ProfileHour objects
        :return valid: A boolean that indicates if all the profiles in measures are valid
        :return invalid_profiles: A list containing the invalid profiles in measures
        """
    valid = True
    invalid_profiles = []
    coefficients = cls.get_range(min(measures).date, max(measures).date)
    for measure in measures:
        if measure[1] != 0:
            cof = False
            for c in coefficients:
                if c.hour == measure[0]:
                    cof = c
                    break
            if cof:
                if cof.cof['A'] == 0:
                    invalid_profiles.append(measure)
                    valid = False
    return valid, invalid_profiles


def has_units(qty, units):
    """
    Test quantity (`qty`) for compatibility with given `units`.

    .. note::
        The following two expressions are equivalent:

            1. ``chemtk.units.has_units(qty, units)``
            2. ``qty.has_units(units)``

    Parameters
    ----------
    qty : :class:`Quantity` or NoneType
        Specify the quantity to test
    units : str or :class:`Quantity`
        Describe the units `qty` must be convertible to

    Returns
    -------
    is_compatible : bool
        True if and only if the units of `qty` can be converted to `units`.
    """
    return qty.has_units(units)


@classmethod
def get_doc_type_minus_list(cls):
    """ Returns List of Identified doctype that a minus effect on the entity"""
    return []


def _read_star_block2(lines, iline, line0, log, debug=False):
    """
    because this uses file streaming, there are 30,000 places where a try except
    block is needed, so this should probably be used all over.
    """
    line0 = lines[iline].strip().lower()
    data_lines = []
    while not line0.startswith('*'):
        data_lines.append(line0.strip(', ').split(','))
        iline += 1
        line0 = lines[iline].strip().lower()
    if debug:
        for line in data_lines:
            log.debug(line)
    return data_lines, iline, line0


def __call__(resource, default):
    """ Return a result for the index value related to the resource or the
        default."""


def merge_dicts(*dict_args):
    """
    Merge all dicts passed as arguments, skips None objects.

    Repeating keys will replace the keys from previous dicts.
    """
    result = None
    for dictionary in dict_args:
        if dictionary is not None:
            if result is None:
                result = dictionary
            else:
                result.update(dictionary)
    return result


@staticmethod
def _pull_data_by_rec(query, table):
    """Pull the value for the table."""
    for rec in query:
        if rec['destinationTable'] == table:
            return rec['value']
    return None


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 delete_slot_type_version(name=None, version=None):
    """
    Deletes a specific version of a slot type. To delete all versions of a slot type, use the operation.
    This operation requires permissions for the lex:DeleteSlotTypeVersion action.
    See also: AWS API Documentation

    :example: response = client.delete_slot_type_version(
        name='string',
        version='string'
    )

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

    :type version: string
    :param version: [REQUIRED]
            The version of the slot type to delete. You cannot delete the $LATEST version of the slot type. To delete the $LATEST version, use the operation.

    """
    pass


def get_version_counter_unrecoverable():
    """Return the number of unrecoverable versions of the file. For a
         healthy file, this will be 0."""


def unescape_newlines(s):
    """ Unescape newlines in a text string

    :param s: (:code:`str`) String to search and replace against
    :returns: (:code:`str`) String with unescaped newlines
    """
    if type(s) == bytes:
        s = s.decode('utf-8')
    return s.replace('\\n', '\n')


def wave_period_tlv(wavelength, velocity):
    """Usage: Calculate wave period (T) using wavelength (l) and velocity (v)"""
    return wavelength / velocity


def filterNonJournals(citesLst, invert=False):
    """Removes the `Citations` from _citesLst_ that are not journals

    # Parameters

    _citesLst_ : `list [Citation]`

    > A list of citations to be filtered

    _invert_ : `optional [bool]`

    > Default `False`, if `True` non-journals will be kept instead of journals

    # Returns

    `list [Citation]`

    > A filtered list of Citations from _citesLst_
    """
    retCites = []
    for c in citesLst:
        if c.isJournal():
            if not invert:
                retCites.append(c)
        elif invert:
            retCites.append(c)
    return retCites


def get_rb_data_attribute(xmldict, attr):
    """Get Attribute `attr` from dict `xmldict`

    Parameters
    ----------
    xmldict : dict
        Blob Description Dictionary
    attr : string
        Attribute key

    Returns
    -------
    sattr : int
        Attribute Values
    """
    try:
        sattr = int(xmldict['@' + attr])
    except KeyError:
        raise KeyError(
            'Attribute @{0} is missing from Blob Description. There may be some problems with your file'
            .format(attr))
    return sattr


def adjust_gravity_volume(vol, og, ng):
    """
    Returns the new volume needed to achieve the desired new gravity.
    This is unit independent and the return value can be used for liters
    and or gallons.

    New Volume = (Volume * original Gravity) / new Gravity

    :arg vol: Original volume of wort
    :arg og: The current gravity of the wort
    :arg ng: The desired gravity of the wort
    :returns: The amount to adjust the wort volume by
    """
    og = (og - 1) * 1000
    ng = (ng - 1) * 1000
    return vol * og / ng


def pos_distribution(doc):
    """Get POS distribution from a processed text.

    Let us suppose that a given sentence has the following pos tags:
    ``[NOUN, VERB, ADJ, VERB, ADJ]``. The PoS distribution would be

    * ``NOUN: 1``
    * ``VERB: 2``
    * ``ADJ: 2``

    This function returns this distrubution as a dict.

    :param doc: Processed text
    :type doc: Spacy Doc
    :return: POS distribution as a dict key POS, value Count
    :rtype: dict
    """
    distribution = {}
    for token in doc:
        distribution[token.pos_] = distribution.get(token.pos_, 0) + 1
    return distribution


@classmethod
def dynamallow_fields(cls):
    """ Returns a dictionary of key value pairs where keys are attributes and values are type classes """
    raise NotImplementedError('{0} class must implement dynamallow_fields'.
        format(cls.__name__))


@classmethod
def map_relation_model(cls, model_class, result):
    """
        Map result to relational model data

        :type model_class: spannerorm.base_model.BaseModel
        :param model_class: relation model class

        :type result: dict
        :param result: result set

        :rtype: spannerorm.base_model.BaseModel
        :return:
        """
    table_name = model_class._meta().db_table
    column_prop_maps = cls.model_column_attr_maps(model_class, table_name)
    model_object = model_class()
    model_object._model_state().is_new = False
    for column_name in column_prop_maps:
        model_prop = getattr(model_object, column_prop_maps.get(column_name))
        model_prop.value = result.get(column_name)
    return model_object


def add_signaling_arguments(parser):
    """
    Add signaling method arguments to an argparse.ArgumentParser.
    """
    parser.add_argument('--signaling', '-s', choices=['copy-and-paste',
        'tcp-socket', 'unix-socket', 'websocket'])
    parser.add_argument('--signaling-host', default='127.0.0.1', help=
        'Signaling host (tcp-socket and websocket only)')
    parser.add_argument('--signaling-port', default=1234, help=
        'Signaling port (tcp-socket only)')
    parser.add_argument('--signaling-path', default='aiortcdc.socket', help
        ='Signaling socket path (unix-socket only)')


def clear_render_border():
    """Clear the boundaries of the render region and disable render region

    """
    pass


@classmethod
def add_items(cls, chunk_ids):
    """Given a chuck of items get some information"""
    raise NotImplemented('You need to figure this out..')


def update(*args, **kwds):
    """od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        """
    if len(args) > 2:
        raise TypeError(
            'update() takes at most 2 positional arguments (%d given)' % (
            len(args),))
    elif not args:
        raise TypeError('update() takes at least 1 argument (0 given)')
    self = args[0]
    other = ()
    if len(args) == 2:
        other = args[1]
    if isinstance(other, dict):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, 'keys'):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value


@staticmethod
def populate_context(channel):
    """Populate context with settings."""
    raise NotImplementedError('Must be implemented by a subclass.')


@staticmethod
def formula_linear(col1, col2):
    """ Linear interpolation between data points.

        :return:
        :rtype:
        """
    items = []
    for k in range(len(col1) - 1):
        x1 = col1.iloc[k]
        x2 = col1.iloc[k + 1]
        y1 = col2.iloc[k]
        y2 = col2.iloc[k + 1]
        m = (y2 - y1) / (x2 - x1)
        formula = '{} + {}*(time-{})'.format(y1, m, x1)
        condition = 'time >= {} && time < {}'.format(x1, x2)
        s = '{}, {}'.format(formula, condition)
        items.append(s)
    s = '{}, time >= {}'.format(col2.iloc[len(col1) - 1], col1.iloc[len(
        col1) - 1])
    items.append(s)
    items.append('0.0')
    return 'piecewise({})'.format(', '.join(items))


@classmethod
def register_notification(cls, notification_cls):
    """Register a class as notification.

        Use only to register concrete notification or payload classes,
        do not register base classes intended for inheritance only.
        """
    cls.register_if(False)(notification_cls)
    cls.notification_classes.append(notification_cls)
    return notification_cls


def convert_by_vocab(vocab, items):
    """Converts a sequence of [tokens|ids] using the vocab."""
    output = []
    for item in items:
        output.append(vocab[item])
    return output


def parse_dimension(value, original_dimension):
    """
    Returns an int dimension value from a string input (in number or percent).
    """
    try:
        return int(value)
    except ValueError:
        if value.rfind('%'):
            return int(int(value.split('%')[0]) * original_dimension / 100)
        raise


def notification_event_payload(resource_type, resource_id, user_id, meta):
    """Create event payload."""
    return {'resource_type': resource_type, 'resource_id': resource_id,
        'user_id': user_id, 'meta': meta}


def str_to_bool(s):
    """Convert string boolean values to bool.

    The conversion is case insensitive.

    :param val: input string

    :return: True if val is 'true' otherwise False
    """
    return str(s).lower() == 'true'


def hms(seconds):
    """Return elapsed cassette time at given frame."""
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    return h, m, s


def merge_intervals(intervals):
    """ Merges intervals in the form of list. """
    if intervals is None:
        return None
    intervals.sort(key=lambda i: i[0])
    out = [intervals.pop(0)]
    for i in intervals:
        if out[-1][-1] >= i[0]:
            out[-1][-1] = max(out[-1][-1], i[-1])
        else:
            out.append(i)
    return out


@staticmethod
def _get_name_from_dn(dn):
    """
        Get the instance name from the dn

        :param dn: string containing the distinguished name URL
        :return: string containing the name
        """
    name = dn.split('/fan-')[1].split('/')[0]
    return name


def _is_whitespace_or_comment(directive):
    """Is this directive either a whitespace or comment directive?"""
    return len(directive) == 0 or directive[0] == '#'


def getAnswerFor(userid):
    """Get a specific user's answer"""


def compare_dicts(dict1, dict2):
    """
    Compares two dictionaries. Returns True if they hold the same
    keys and the same values, returns False otherwise.
    """
    if not isinstance(dict1, dict) or not isinstance(dict2, dict):
        return False
    key_set_1 = set(dict1.keys())
    key_set_2 = set(dict2.keys())
    same_keys = key_set_1 & key_set_2
    if len(same_keys) == len(key_set_1) and len(same_keys) == len(key_set_2):
        for k in same_keys:
            if dict1[k] != dict2[k]:
                return False
        return True
    else:
        return False


@classmethod
def get_object_url_prefix(cls):
    """
        Returns a prefix which (by default) applies to all "object" URLs
        provided by this view class.
        """
    prefix = getattr(cls, 'object_url_prefix', None)
    if prefix:
        return prefix
    return '/{}'.format(cls.get_route_prefix())


def make_tokens(parse_buffer):
    """
    Takes a list of pairs (token_type, read_result) and
    applies token_type(read_result).

    Footnotes are already parsed before this point,
    and span-level parsing is started here.
    """
    tokens = []
    for token_type, result in parse_buffer:
        token = token_type(result)
        if token is not None:
            tokens.append(token)
    return tokens


def is_informational(status):
    """
    Check if HTTP status code is informational.

    :param status: http status code
    :returns: True if status is successful, else False
    """
    return 100 <= status <= 199


def format_uptime(uptime_in_seconds):
    """Format number of seconds into human-readable string.

    :param uptime_in_seconds: The server uptime in seconds.
    :returns: A human-readable string representing the uptime.

    >>> uptime = format_uptime('56892')
    >>> print(uptime)
    15 hours 48 min 12 sec
    """
    m, s = divmod(int(uptime_in_seconds), 60)
    h, m = divmod(m, 60)
    d, h = divmod(h, 24)
    uptime_values = []
    for value, unit in ((d, 'days'), (h, 'hours'), (m, 'min'), (s, 'sec')):
        if value == 0 and not uptime_values:
            continue
        elif value == 1 and unit.endswith('s'):
            unit = unit[:-1]
        uptime_values.append('{0} {1}'.format(value, unit))
    uptime = ' '.join(uptime_values)
    return uptime


def get_motion_default(settings, motion_frames, queue_com, name):
    """
    Set the default values for the motion correction software.

    settings - TranSPHIRE settings.
    motion_frames - Sub frame settings.
    queue_com - Queue for communication.
    name - Name of the process.

    Returns:
    True, if dose weighting will be applied.
    """
    motion_name = settings['Copy']['Motion']
    if (motion_name == 'MotionCor2 v1.0.0' or motion_name ==
        'MotionCor2 v1.0.5' or motion_name == 'MotionCor2 v1.1.0'):
        motion_frames['last'] = int(settings['General']['Number of frames']
            ) - int(settings[motion_name]['-Trunc'])
        motion_frames['first'] = int(settings[motion_name]['-Throw']) + 1
        return bool(settings[motion_name]['-FmDose'] != '0' and settings[
            motion_name]['-PixSize'] != '0' and settings[motion_name]['-kV'
            ] != '0')
    else:
        message = '\n'.join(['{0}: Motion version not known.'.format(
            motion_name), 'Please contact the TranSPHIRE authors!'])
        queue_com['error'].put(message, name)
        raise IOError(message)


def primitive_nurbs_circle_add(radius: float=1.0, view_align: bool=False,
    enter_editmode: bool=False, location: float=(0.0, 0.0, 0.0), rotation:
    float=(0.0, 0.0, 0.0), layers: bool=(False, False, False, False, False,
    False, False, False, False, False, False, False, False, False, False,
    False, False, False, False, False)):
    """Construct a Nurbs Circle

    :param radius: Radius
    :type radius: float
    :param view_align: Align to View, Align the new object to the view
    :type view_align: bool
    :param enter_editmode: Enter Editmode, Enter editmode when adding this object
    :type enter_editmode: bool
    :param location: Location, Location for the newly added object
    :type location: float
    :param rotation: Rotation, Rotation for the newly added object
    :type rotation: float
    :param layers: Layer
    :type layers: bool
    """
    pass


def face_make_planar(factor: float=1.0, repeat: int=1):
    """Flatten selected faces

    :param factor: Factor
    :type factor: float
    :param repeat: Iterations
    :type repeat: int
    """
    pass


def absolutelyNonDecreasing(buffer, item, attempts):
    """
    Stops after the buffer has seen an absolute value larger than the one being searched for.
    The example halting condition given in the documentation.
    """
    if abs(buffer._cache[-1]) > abs(item):
        return True
    return False


def _print_info_dict(info_dict):
    """Print the information dictionary"""
    for key, stat in info_dict.items():
        print('{key:>10}: {stat}'.format(key=key, stat=stat))


def calculated():
    """ The date and time of the calculation
        """


@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)


def _validate_vg(module, vg):
    """
    Check the current state of volume group.

    :param module: Ansible module argument spec.
    :param vg: Volume Group name.
    :return: True (VG in varyon state) or False (VG in varyoff state) or
             None (VG does not exist), message.
    """
    lsvg_cmd = module.get_bin_path('lsvg', True)
    rc, current_active_vgs, err = module.run_command('%s -o' % lsvg_cmd)
    if rc != 0:
        module.fail_json(msg='Failed executing %s command.' % lsvg_cmd)
    rc, current_all_vgs, err = module.run_command('%s' % lsvg_cmd)
    if rc != 0:
        module.fail_json(msg='Failed executing %s command.' % lsvg_cmd)
    if vg in current_all_vgs and vg not in current_active_vgs:
        msg = 'Volume group %s is in varyoff state.' % vg
        return False, msg
    elif vg in current_active_vgs:
        msg = 'Volume group %s is in varyon state.' % vg
        return True, msg
    else:
        msg = 'Volume group %s does not exist.' % vg
        return None, msg


def _try_compile(source, name):
    """Attempts to compile the given source, first as an expression and
       then as a statement if the first approach fails.

       Utility function to accept strings in functions that otherwise
       expect code objects
    """
    try:
        c = compile(source, name, 'eval')
    except SyntaxError:
        c = compile(source, name, 'exec')
    return c


@classmethod
def userFromResponse(cls, userData: dict):
    """
        create a user object from an OG operation response
        :param userData: the user data received from the OG operation
        :type userData: dict
        :return: The created user object
        :rtype: User
        """
    user = cls()
    user.businessPhones = userData.get('businessPhones')
    user.displayName = userData.get('displayName')
    user.givenName = userData.get('givenName')
    user.jobTitle = userData.get('jobTitle')
    user.mail = userData.get('mail')
    user.mobilePhone = userData.get('mobilePhone')
    user.officeLocation = userData.get('officeLocation')
    user.preferredLanguage = userData.get('preferredLanguage')
    user.surname = userData.get('surname')
    user.userPrincipalName = userData.get('userPrincipalName')
    user.uid = userData.get('id')
    return user


@staticmethod
def get_bool_val(key, default):
    """
        the key may be exist in the config, with '' as value.
        In that case, return this function default as the value..
        """
    key_configured = isinstance(key, bool)
    return key if key_configured else default


def delete():
    """Remove all selected keyframes

    """
    pass


def wait_for(button):
    """
    If You Want to Wait For the User to Press a Key (Keyboard or Mouse) Use This Function.
    """
    if button.lower() in ('middle', 'left', 'right', 'back', 'forward'):
        if button.lower()[:1] == 'b':
            button = 'x'
        if button.lower()[:1] == 'f':
            button = 'x2'
        import mouse
        mouse.wait(button)
    else:
        import keyboard
        try:
            keyboard.wait(button)
        except:
            raise ValueError('Incorrect Button Name.')


def get_model_name(model_class):
    """Example: ModelName"""
    return model_class.__name__


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

        :param SharedLinkSettingsAllowDownloadDisabledDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_settings_allow_download_disabled_details', val)


def add(intr):
    """ Add the IIntrospectable ``intr`` (use instead of
        :meth:`pyramid.interfaces.IIntrospector.add` when you have a custom
        IIntrospectable). Replaces any existing introspectable registered
        using the same category/discriminator.

        This method is not typically called directly, instead it's called
        indirectly by :meth:`pyramid.interfaces.IIntrospector.register`"""


def get_prim_obj_from_sol(sol, parameters=None):
    """
    Gets the primal objective from the solution of the LP problem

    Parameters
    -------------
    sol
        Solution of the ILP problem by the given algorithm
    parameters
        Possible parameters of the algorithm

    Returns
    -------------
    prim_obj
        Primal objective
    """
    return sol['primal objective']


def describe_no_tasks(nick, task_match):
    """ No tasks matched """
    tmpl = '{nick}, I could not find {state} tasks for {user}.'
    msg = tmpl.format(nick=nick, state=task_match.state, user=task_match.user)
    return msg


def _lif_sdram_usage(size_in, size_out, size_learnt_out, n_neurons):
    """Approximation of SDRAM usage."""
    total_size_out = size_out + size_learnt_out
    size = n_neurons * (size_in + total_size_out + 2) + total_size_out
    return size * 4


def xmlSchema(filename, schema=u'', policy=u''):
    """Given a filename relative to the current module, return an
        interface representing the schema contained in that file. If there
        are multiple <schema /> blocks, return the unnamed one, unless
        a name is supplied, in which case the 'name' attribute of the schema
        will be matched to the schema name.

        The policy argument can be used to pick a different parsing policy.
        Policies must be registered as named utilities providing
        ISchemaPolicy.

        Raises a KeyError if the schema cannot be found.
        Raises an IOError if the file cannot be opened.
        """


@staticmethod
def PrecTime(sec, microseconds=None, string=False):
    """
        >param sec: Enter the n. of seconds
        >param microseconds: optional, enter the . of microseconds
        >param string: optional, if 'string' is true, the func return a string,
        in the other case, it return a tuple.
        >return: tuple or string of <hour, minute, seconds, milliseconds, microseconds>
        """
    sec = int(sec)
    rest = sec % 3600
    sec -= rest
    hours = sec / 3600
    sec = rest
    rest = sec % 60
    sec -= rest
    minutes = sec / 60
    sec = rest
    seconds = rest
    if not microseconds:
        milliseconds = 0
        microseconds = 0
    else:
        rest = microseconds % 1000
        microseconds -= rest
        milliseconds = float(microseconds) / 1000
        microseconds = rest
    if not string:
        return int(hours), int(minutes), int(seconds), int(milliseconds), int(
            microseconds)
    else:
        return (
            f'{int(hours)}:{int(minutes)}:{int(seconds)}.{int(milliseconds)}')


def zero_cols(full_mat, non_zero=False):
    """
    Returns the list of indices of columns that are zero or non_zero
    depending on the parameter non_zero

    :param mat: The matrix to search over

    :param non_zero: If False, returns the indices of columns that are zero, otherwise
        returns indices of columns that a not zero.

    :return: A list of indices of columns of the type determined by the parameter non_zero.
    """
    size = len(full_mat)
    rval = []
    rval_other = []
    for col in range(size):
        is_zero = True
        for row in range(size):
            if full_mat[row, col] != 0:
                is_zero = False
                break
        if is_zero:
            rval.append(col)
        else:
            rval_other.append(col)
    if non_zero:
        return rval_other
    else:
        return rval


@staticmethod
def get_name():
    """
        Get the name of the extractor.
        :return: the name of the extractor
        """
    return 'Basecaller 1d square sequencing summary'


def slugify(value):
    """
    Normalizes string, converts to lowercase, removes non-alpha characters,
    and converts spaces to hyphens.
    """
    import re
    import unicodedata
    value = str(value)
    value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore'
        ).decode('utf8').strip().lower()
    value = re.sub('[^\\w\\s\\-\\.]', '', value)
    value = re.sub('[-\\s]+', '-', value)
    return value


@classmethod
def get_query_for_field(cls, condition):
    """
        Returns Q object with query for parsed condition
        """
    field = cls.get_field_name_to_field().get(condition.name)
    if field is None:
        field = cls._field_source_to_search_field_instance.get(condition.name)
    if field is None:
        field_type = getattr(cls.get_full_mapping().get(condition.name),
            'field_type', None)
        field = cls._field_type_to_field_class.get(field_type, cls.
            _default_field)()
    return field.get_query(condition)


def default_tzinfo(dt, tzinfo):
    """
    Sets the ``tzinfo`` parameter on naive datetimes only

    This is useful for example when you are provided a datetime that may have
    either an implicit or explicit time zone, such as when parsing a time zone
    string.

    .. doctest::

        >>> from dateutil.tz import tzoffset
        >>> from dateutil.parser import parse
        >>> from dateutil.utils import default_tzinfo
        >>> dflt_tz = tzoffset("EST", -18000)
        >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz))
        2014-01-01 12:30:00+00:00
        >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz))
        2014-01-01 12:30:00-05:00

    :param dt:
        The datetime on which to replace the time zone

    :param tzinfo:
        The :py:class:`datetime.tzinfo` subclass instance to assign to
        ``dt`` if (and only if) it is naive.

    :return:
        Returns an aware :py:class:`datetime.datetime`.
    """
    if dt.tzinfo is not None:
        return dt
    else:
        return dt.replace(tzinfo=tzinfo)


def browserify_file(entry_point, output_file, babelify=False, export_as=None):
    """
    Browserify a single javascript entry point plus non-external
    dependencies into a single javascript file. Generates source maps
    in debug mode. Minifies the output in release mode.

    By default, it is not possible to ``require()`` any exports from the entry
    point or included files. If ``export_as`` is specified, any module exports
    in the specified entry point are exposed for ``require()`` with the
    name specified by ``export_as``.
    """
    from .modules import browserify
    if not isinstance(entry_point, str):
        raise RuntimeError(
            'Browserify File compiler takes a single entry point as input.')
    return {'dependencies_fn': browserify.browserify_deps_file,
        'compiler_fn': browserify.browserify_compile_file, 'input':
        entry_point, 'output': output_file, 'kwargs': {'babelify': babelify,
        'export_as': export_as}}


@classmethod
def lookup_relativedelta_parameter(cls, unit_string):
    """
        >>> lrp = Schedule.lookup_relativedelta_parameter
        >>> lrp('Years')
        'years'
        >>> lrp('yr')
        'years'
        >>> lrp('s')
        'seconds'
        """
    try:
        return cls._rdp_map()[unit_string.lower()]
    except KeyError:
        raise ValueError("%s doesn't match any supported time/date unit")


def Singleton(C):
    """A class decorator for singleton classes."""
    return C()


def sysinfo(filepath: str=''):
    """Generate system information, saved into a text file

    :param filepath: filepath
    :type filepath: str
    """
    pass


def _mk_helper_float_comparison_filter_wildcard(attributeValue,
    compareTagAttributeValueToTestValueLambda):
    """
        _mk_helper_float_comparison_filter_wildcard - A helper function to make a function which will

            test a given attribute value, as a float, and compare it using a provided compare function/lambda.

            Wildcard version, all attributes.

            @param attributeValue <float/int/str> - The attribute value to test

            @param compareTagAttributeValueToTestValueLambda <function/lambda> - The comparison function to use, should return bool (True = match, False = no match)

            @return <function> - A special comparitive function to use to compare a provided tag against the given attribute value and comparison function
    """
    try:
        _attributeValueFloat = float(attributeValue)
    except ValueError:
        _innerFunc = lambda prevTag: []
        return _innerFunc
    _compareTagAttributeValueToTestValueLambda = (
        compareTagAttributeValueToTestValueLambda)

    def _innerFunc(prevTag):
        for tagAttributeName, tagAttributeValue in prevTag.attributesDict.items(
            ):
            try:
                tagAttributeValueFloat = float(tagAttributeValue)
            except ValueError:
                continue
            if _compareTagAttributeValueToTestValueLambda(
                tagAttributeValueFloat, _attributeValueFloat) is True:
                return [prevTag]
        return []
    return _innerFunc


def set_kernel_process_name(name):
    """Changes the Kernel's /proc/self/status process name on Linux.

  The kernel name is NOT what will be shown by the ps or top command.
  It is a 15 character string stored in the kernel's process table that
  is included in the kernel log when a process is OOM killed.
  The first 15 bytes of name are used.  Non-ASCII unicode is replaced with '?'.

  Does nothing if /proc/self/comm cannot be written or prctl() fails.

  Args:
    name: bytes|unicode, the Linux kernel's command name to set.
  """
    if not isinstance(name, bytes):
        name = name.encode('ascii', 'replace')
    try:
        with open('/proc/self/comm', 'wb') as proc_comm:
            proc_comm.write(name[:15])
    except EnvironmentError:
        try:
            import ctypes
        except ImportError:
            return
        try:
            libc = ctypes.CDLL('libc.so.6')
        except EnvironmentError:
            return
        pr_set_name = ctypes.c_ulong(15)
        zero = ctypes.c_ulong(0)
        try:
            libc.prctl(pr_set_name, name, zero, zero, zero)
        except AttributeError:
            return


def authenticated_userid(request):
    """ Return the authenticated :term:`userid` or ``None`` if
        no authenticated userid can be found. This method of the
        policy should ensure that a record exists in whatever
        persistent store is used related to the user (the user
        should not have been deleted); if a record associated with
        the current id does not exist in a persistent store, it
        should return ``None``.

        """


def get_yad_version():
    """Extract version number from yad, if it is available."""
    try:
        import sh
        from sh import yad
        from io import StringIO
        buffer = StringIO()
        try:
            yad('--version', _out=buffer)
        except sh.ErrorReturnCode_252:
            pass
        return buffer.getvalue()
    except Exception:
        return 'None'


def SizeBenefitAnn(t):
    """Annuity benefit per policy"""
    return 0


def color_scale_columns(df, matplotlib_cmap='Greens', subset=None):
    """DataFrame Styler:
    Takes a df, any valid matplotlib colormap column names
    (matplotlib.org/tutorials/colors/colormaps.html) and
    returns a dataframe with a gradient colormap applied to column values.

    Example:
    df_styled = color_scale_columns(df,cmap = "YlGn",subset=['Columns','to','color'])

    Parameters:
    -----------
        df:
            DataFrame containing columns to style.
    subset:
         Names of columns to color-code.
    cmap:
        Any matplotlib colormap.
        https://matplotlib.org/tutorials/colors/colormaps.html

    Returns:
    ----------
        df_style:
            styled dataframe.

    """
    from IPython.display import display
    import seaborn as sns
    cm = matplotlib_cmap
    df_style = df.style.background_gradient(cmap=cm, subset=subset)
    return df_style


def timestamp_to_ms(timestamp):
    """
    Converts a Unix timestamp into one with millisecond resolution.

    Parameters
    ----------
    timestamp : float or int
        Unix timestamp.

    Returns
    -------
    int
        `timestamp` with millisecond resolution (13 integer digits).

    """
    num_integer_digits = len(str(timestamp).split('.')[0])
    return int(timestamp * 10 ** (13 - num_integer_digits))


def _verify_legacy_symbol(op_name, func_name, sym):
    """Verify if the sym is a legacy symbol.

    Parameters
    ----------
    op_name : str
        Operator full name registered in backend.
    func_name : str
        Operator name exposed to users. This is usually the name by stripping off
        the prefix of the full operator names registered in backend.
    sym : symbol to be verified
    """
    from .numpy._symbol import _Symbol as np_symbol
    if isinstance(sym, np_symbol):
        raise TypeError(
            'Operator `{}` registered in backend is known as `{}` in Python. This is a legacy operator which can only accept legacy ndarrays, while received an MXNet numpy ndarray. Please call `as_nd_ndarray()` upon the numpy ndarray to convert it to a legacy ndarray, and then feed the converted array to this operator.'
            .format(op_name, func_name))


@staticmethod
def _generate_section_header_md(section_type, title, prepend_newline=True):
    """generates markdown section header."""
    prefix = '\n' if prepend_newline else ''
    return prefix + '## {}:{}\n'.format(section_type, title)


@staticmethod
def supportedViews():
    """Overrides :meth:`.ControlMixin.supportedViews`. The
        ``PowerSpectrumToolBar`` is only intended to be added to
        :class:`.PowerSpectrumPanel` views.
        """
    from fsleyes.views.powerspectrumpanel import PowerSpectrumPanel
    return [PowerSpectrumPanel]


def iter_and_close(file_like, block_size):
    """Yield file contents by block then close the file."""
    while 1:
        try:
            block = file_like.read(block_size)
            if block:
                yield block
            else:
                raise StopIteration
        except StopIteration:
            file_like.close()
            return


def _to_text(nodes_or_text):
    """Convert a xpath object (a string or a list of nodes) to string"""
    element0 = nodes_or_text[0] if isinstance(nodes_or_text, list
        ) else nodes_or_text
    return element0 if isinstance(element0, str) else element0.xpath(
        'string(.)')


@staticmethod
def extension():
    """Serve as placeholder; override this in subclasses."""
    return ''


def is_set_bit(byte, position):
    """Checks if n bit is set in byte.

    :param byte: Single-byte integer
    :type byte: int
    :param position: Bit position
    :type position: int
    :return: True if the bit at position is set otherwise False
    :rtype: bool
    """
    return bool(byte >> position & 1)


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 no_help(func):
    """ Decorator: define a function that will never display its help if asked
    """
    func.no_help = True
    return func


def one_dec_places(x, pos):
    """
    Adds 1/10th decimal to plot ticks.
    """
    return '%.1f' % x


def ParseEnum(field, value):
    """Parse an enum value.

  The value can be specified by a number (the enum value), or by
  a string literal (the enum name).

  Args:
    field: Enum field descriptor.
    value: String value.

  Returns:
    Enum value number.

  Raises:
    ValueError: If the enum value could not be parsed.
  """
    enum_descriptor = field.enum_type
    try:
        number = int(value, 0)
    except ValueError:
        enum_value = enum_descriptor.values_by_name.get(value, None)
        if enum_value is None:
            raise ValueError('Enum type "%s" has no value named %s.' % (
                enum_descriptor.full_name, value))
    else:
        if hasattr(field.file, 'syntax'):
            if field.file.syntax == 'proto3':
                return number
        enum_value = enum_descriptor.values_by_number.get(number, None)
        if enum_value is None:
            raise ValueError('Enum type "%s" has no value with number %d.' %
                (enum_descriptor.full_name, number))
    return enum_value.number


def make_ordered_list(values):
    """  Make an ordered list of unique values given a list of values.

    Parameters
    ----------
    values : list, shape [n_values]
        values to find uniques and sort

    Returns
    -------
    uniques : list
        A sorted list of unique values from 'values'

    """
    uniques = list(set(values))
    uniques.sort()
    return uniques


def from_unit_box(x, lb, ub):
    """Maps a set of points from the unit box to the original domain

    :param x: Points to be mapped from the unit box, of size npts x dim
    :type x: numpy.array
    :param lb: Lower bounds, of size 1 x dim
    :type lb: numpy.array
    :param ub: Upper bounds, of size 1 x dim
    :type ub: numpy.array
    :return: Points mapped to the original domain
    :rtype: numpy.array
    """
    return lb + (ub - lb) * x


def lod_by_name():
    """Add levels of detail to this object based on object names

    """
    pass


def __call__():
    """ Returns a list of catalog brains
        """


def get_path(obj):
    """ Return the path used to store the object's json dump. """
    from midz import cfg, kernel
    try:
        return obj._container.path
    except:
        pass


@staticmethod
def gather_all_feature_text(feature):
    """Return a single string of all text in the feature (+qualifiers)."""
    return ' '.join([feature.type] + list(map(str, feature.qualifiers.keys(
        ))) + list(map(str, feature.qualifiers.values())))


def parse_jcamp_value(text):
    """
    Parse value text from Bruker JCAMP-DX file returning the value.
    """
    if '<' in text:
        return text[1:-1]
    elif '.' in text or 'e' in text or 'inf' in text:
        return float(text)
    else:
        return int(text)


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


def has_pattern():
    """Check whether the `pattern <https://github.com/clips/pattern>`_ package is installed.

    Returns
    -------
    bool
        Is `pattern` installed?

    """
    try:
        from pattern.en import parse
        return True
    except ImportError:
        return False


@classmethod
def _replace_same_name_entities(cls, tree):
    """
        Changes same section names in the doc by adding <-{index}>
        to the next section occurrences.

        :param tree: ElementTree of the doc
        :return: ElementTree
        """
    sec_map = {}
    prop_map = {}
    root = tree.getroot()
    for sec in root.iter('section'):
        sec_name = sec.find('name')
        if sec_name is not None:
            cls._change_entity_name(tree, sec_map, sec_name)
        else:
            raise Exception('Section attribute name is not specified')
        for prop in sec.iter('property'):
            if prop.getparent() == sec:
                prop_name = prop.find('name')
                if prop_name is not None:
                    cls._change_entity_name(tree, prop_map, prop_name)
        prop_map.clear()
    return tree


@classmethod
def can_edit(cls, editor_type_name):
    """
        Must be implemented to return True if the given editor_type_name
        matches this editor.
        """
    return editor_type_name in ('percent', 'progress')


def creditscore_threshold(score):
    """Alternate credit bureau scoring policy."""
    return max(score, 600)