@classmethod
def default_info(cls):
    """
        Returns the default information for this provider

        This should compute and return the default value for the information regarding this provider.
        For example, this can compute where the metadata is stored

        Returns
        -------
        str
            Value to be set by default in INFO
        """
    return ''


def _isvalid_partition(flux_components):
    """Test if partitioned flux directions (signs) are valid."""
    fc = flux_components
    isvalid = True
    mssg = ''
    if fc.Fqt <= 0:
        isvalid = False
        mssg += 'Fqt <= 0; '
    if fc.Fqe <= 0:
        isvalid = False
        mssg += 'Fqe <= 0; '
    if fc.Fcp >= 0:
        isvalid = False
        mssg += 'Fcp >= 0; '
    if fc.Fcr <= 0:
        isvalid = False
        mssg += 'Fcr <= 0; '
    return isvalid, mssg


def forward(apps, schema_editor):
    """
    Creates a Device record for each existing Config
    TODO: delete this migration in future releases
    """
    if not schema_editor.connection.alias == 'default':
        return
    Device = apps.get_model('django_netjsonconfig', 'Device')
    Config = apps.get_model('django_netjsonconfig', 'Config')
    for config in Config.objects.all():
        device = Device(id=config.id, name=config.name, mac_address=config.
            mac_address, key=config.key, created=config.created, modified=
            config.modified)
        device.full_clean()
        device.save()
        config.device = device
        config.save()


def stitchRegions(receptor, v_seq, d_seq, j_seq, amino_acid=False):
    """
    Assemble full length region encoding

    Arguments:
      receptor (changeo.Receptor.Receptor): Receptor object
      v_seq (str): V segment germline sequence as a string
      d_seq (str): D segment germline sequence as a string
      j_seq (str): J segment germline sequence as a string
      amino_acid (bool): if True use amino acid positional fields, otherwise use nucleotide fields.

    Returns:
      str: string defining germline regions
    """
    full_junction = True if getattr(receptor, 'n1_length', None
        ) is not None else False
    regions = 'V' * len(v_seq)
    if amino_acid:
        try:
            np1_len = int(receptor.np1_aa_length)
        except (TypeError, ValueError, AttributeError):
            np1_len = 0
        regions += 'N' * np1_len
    elif not full_junction:
        try:
            np1_len = int(receptor.np1_length)
        except (TypeError, ValueError):
            np1_len = 0
        regions += 'N' * np1_len
    else:
        try:
            p3v_len = int(receptor.p3v_length)
        except (TypeError, ValueError):
            p3v_len = 0
        try:
            n1_len = int(receptor.n1_length)
        except (TypeError, ValueError):
            n1_len = 0
        try:
            p5d_len = int(receptor.p5d_length)
        except (TypeError, ValueError):
            p5d_len = 0
        regions += 'P' * p3v_len
        regions += 'N' * n1_len
        regions += 'P' * p5d_len
    regions += 'D' * len(d_seq)
    if amino_acid:
        try:
            np2_len = int(receptor.np2_aa_length)
        except (TypeError, ValueError, AttributeError):
            np2_len = 0
        regions += 'N' * np2_len
    elif not full_junction:
        try:
            np2_len = int(receptor.np2_length)
        except (TypeError, ValueError):
            np2_len = 0
        regions += 'N' * np2_len
    else:
        try:
            p3d_len = int(receptor.p3d_length)
        except (TypeError, ValueError):
            p3d_len = 0
        try:
            n2_len = int(receptor.n2_length)
        except (TypeError, ValueError):
            n2_len = 0
        try:
            p5j_len = int(receptor.p5j_length)
        except (TypeError, ValueError):
            p5j_len = 0
        regions += 'P' * p3d_len
        regions += 'N' * n2_len
        regions += 'P' * p5j_len
    regions += 'J' * len(j_seq)
    return regions


def _create_log_record(cls, dict):
    """Extra function for reduce because on Python 3 unbound methods
    can no longer be pickled.
    """
    return cls.from_dict(dict)


def get_model_fields(cls):
    """ Return dict of model fields """
    fields = {}
    for field in cls._meta.get_fields():
        fields[field.name] = {'required': not field.blank, 'type': field.
            __class__.__name__, 'default': field.default}
    return fields


def ar_and(x, y, nx, ny):
    """Dimensionless production rate for a gene regulated by one
    activator and one repressor with AND logic in the absence of
    leakage.

    Parameters
    ----------
    x : float or NumPy array
        Concentration of activator.
    y : float or NumPy array
        Concentration of repressor.
    nx : float
        Hill coefficient for activator.
    ny : float
        Hill coefficient for repressor.

    Returns
    -------
    output : NumPy array or float
        x**nx / (1 + x**nx + y**ny)
    """
    return x ** nx / (1 + x ** nx + y ** ny)


def _common_parser():
    """Returns a parser with common command-line options for all the scripts
    in the fortpy suite.
    """
    import argparse
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('-examples', action='store_true', help=
        'See detailed help and examples for this script.')
    parser.add_argument('-verbose', action='store_true', help=
        'See verbose output as the script runs.')
    parser.add_argument('-action', nargs=1, choices=['save', 'print'],
        default='print', help=
        'Specify what to do with the output (print or save)')
    parser.add_argument('-debug', action='store_true', help=
        'Print verbose calculation information for debugging.')
    return parser


def get_notebook_by_ord(current_scene_db, ordinal):
    """Returns list item referenced by input ordinal"""
    from src.praxxis.sqlite import connection
    from src.praxxis.util import error
    conn = connection.create_connection(current_scene_db)
    cur = conn.cursor()
    query = (
        'SELECT Notebook, Library FROM NotebookList WHERE ID = ? LIMIT 0, 1')
    cur.execute(query, (ordinal,))
    conn.commit()
    item = cur.fetchone()
    conn.close()
    if item is None:
        raise error.NotebookNotFoundError
    return item


def le_power_of_2(num):
    """ Gets a power of two less than or equal to num. Works for up to 64-bit
	numbers.
	"""
    num |= num >> 1
    num |= num >> 2
    num |= num >> 4
    num |= num >> 8
    num |= num >> 16
    num |= num >> 32
    return num - (num >> 1)


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


def expanded_indexer(key, ndim):
    """Given a key for indexing an ndarray, return an equivalent key which is a
    tuple with length equal to the number of dimensions.

    The expansion is done by replacing all `Ellipsis` items with the right
    number of full slices and then padding the key with full slices so that it
    reaches the appropriate dimensionality.
    """
    if not isinstance(key, tuple):
        key = key,
    new_key = []
    found_ellipsis = False
    for k in key:
        if k is Ellipsis:
            if not found_ellipsis:
                new_key.extend((ndim + 1 - len(key)) * [slice(None)])
                found_ellipsis = True
            else:
                new_key.append(slice(None))
        else:
            new_key.append(k)
    if len(new_key) > ndim:
        raise IndexError('too many indices')
    new_key.extend((ndim - len(new_key)) * [slice(None)])
    return tuple(new_key)


def crossfade_sounds():
    """Do cross-fading volume animation of two selected sound strips

    """
    pass


def _error_string(error, k=None):
    """String representation of SBMLError.

    Parameters
    ----------
    error : libsbml.SBMLError
    k : index of error

    Returns
    -------
    string representation of error
    """
    package = error.getPackage()
    if package == '':
        package = 'core'
    template = 'E{} ({}): {} ({}, L{}); {}; {}'
    error_str = template.format(k, error.getSeverityAsString(), error.
        getCategoryAsString(), package, error.getLine(), error.
        getShortMessage(), error.getMessage())
    return error_str


def assign_layer_fq_names(container, name=None):
    """Assign human-readable names to the modules (layers).

    Sometimes we need to access modules by their names, and we'd like to use
    fully-qualified names for convenience.
    """
    for name, module in container.named_modules():
        module.distiller_name = name


@classmethod
def get_state(cls, clz):
    """
        Retrieve the state of a given Class.

        :param clz: types.ClassType
        :return: Class state.
        :rtype: dict
        """
    if clz not in cls.__shared_state:
        cls.__shared_state[clz] = clz.init_state() if hasattr(clz, 'init_state'
            ) else {}
    return cls.__shared_state[clz]


@classmethod
def get_selection(cls, strings, title='Select an option', subtitle=None,
    show_exit_option=True, _menu=None):
    """
        Single-method way of getting a selection out of a list of strings.

        Args:
            strings (:obj:`list` of :obj:`str`):  The list of strings this menu should be built from.
            title (str): The title of the menu.
            subtitle (str): The subtitle of the menu.
            show_exit_option (bool): Specifies whether this menu should show an exit item by default. Defaults to True.
            _menu: Should probably only be used for testing, pass in a list and the created menu used internally by
                the method will be appended to it

        Returns:
            int: The index of the selected option.

        """
    menu = cls(strings, title, subtitle, show_exit_option=show_exit_option)
    if _menu is not None:
        _menu.append(menu)
    menu.show()
    menu.join()
    return menu.selected_option


def resolve_name(name):
    """Resolve a name like ``module.object`` to an object and return it.

    Raise `ImportError` if the module or name is not found.
    """
    parts = name.split('.')
    cursor = len(parts) - 1
    module_name = parts[:cursor]
    attr_name = parts[-1]
    while cursor > 0:
        try:
            ret = __import__('.'.join(module_name), fromlist=[attr_name])
            break
        except ImportError:
            if cursor == 0:
                raise
            cursor -= 1
            module_name = parts[:cursor]
            attr_name = parts[cursor]
            ret = ''
    for part in parts[cursor:]:
        try:
            ret = getattr(ret, part)
        except AttributeError:
            raise ImportError(name)
    return ret


@staticmethod
def tag(version, params):
    """Build and return full command to use with subprocess.Popen for 'git tag' command

        :param version:
        :param params:
        :return: list
        """
    cmd = ['git', 'tag', '-a', '-m', 'v%s' % version, str(version)]
    if params:
        cmd.extend(params)
    return cmd


def module_name(item):
    """Returns the full module name where the given object is declared.

    Examples::

       >>> module_name(module_name)
       'xotl.tools.names'

       >>> from xotl.tools.symbols import Unset
       >>> module_name(Unset)
       'xotl.tools.symbols'

    """
    from xotl.tools.future.inspect import get_attr_value
    if item is None:
        res = ''
    elif isinstance(item, str):
        res = item
    else:
        res = get_attr_value(item, '__module__', None)
        if res is None:
            res = get_attr_value(type(item), '__module__', '')
    if res.startswith('__') or res in ('builtins', 'exceptions', '<module>'):
        res = ''
    return str(res)


@classmethod
def _validate_message(cls, message):
    """Validate other parts of the message other than those
        done in _message_id."""


def rhum(dew, temperature):
    """
    Calculate relative humidity from dew temperature and ambient temperature.

    This uses the range of constants which yields results accurate in the range
    -20 to 50 Celsius.

    Parameters
    ----------
    dew : ndarray
        Dew point temperature (Celsius).
    temperature : ndarray
        Ambient temperature (Celsius).

    Returns
    -------
    rhum : ndarray
        Relative humidity (%).

    References
    ----------
    http://www.vaisala.com/Vaisala%20Documents/Application%20notes/Humidity_Conversion_Formulas_B210973EN-F.pdf

    """
    m = 7.59138
    Tn = 240.7263
    rhum = 100 * 10 ** (m * (dew / (dew + Tn) - temperature / (temperature +
        Tn)))
    return rhum


def calc_angle_speed_gain_vector(joint, dav, i, periodic_time):
    """Calculate angle speed gain for multiple Degrees of Freedom

    """
    if periodic_time == 0:
        return 1.0
    dav_gain = 1.0
    for joint_dof_index in range(joint.joint_dof):
        if dav[i + joint_dof_index] == 0:
            dav_gain = min(dav_gain, 1.0)
        else:
            tmp_gain = abs(joint.max_joint_velocity[joint_dof_index] / (dav
                [i + joint_dof_index] / periodic_time))
            dav_gain = min(tmp_gain, dav_gain)
    return dav_gain


def tile_region(rname, start, end, step):
    """ Make non-overlapping tiled windows from the specified region in
    the UCSC-style string format.

    >>> list(tile_region('chr1', 1, 250, 100))
    ['chr1:1-100', 'chr1:101-200', 'chr1:201-250']
    >>> list(tile_region('chr1', 1, 200, 100))
    ['chr1:1-100', 'chr1:101-200']
    """
    while start + step <= end:
        yield '%s:%d-%d' % (rname, start, start + step - 1)
        start += step
    if start < end:
        yield '%s:%d-%d' % (rname, start, end)


def int2CAS(i):
    """Converts CAS number of a compounds from an int to an string. This is
    helpful when dealing with int CAS numbers.

    Parameters
    ----------
    CASRN : int
        CASRN [-]

    Returns
    -------
    CASRN : string
        CASRN [-]

    Notes
    -----
    Handles CAS numbers with an unspecified number of digits. Does not work on
    floats.

    Examples
    --------
    >>> int2CAS(7704349)
    '7704-34-9'
    """
    i = str(i)
    return i[:-3] + '-' + i[-3:-1] + '-' + i[-1]


def l2rowg(X, Y, N, D):
    """
    Backpropagate through Normalization.

    Parameters
    ----------

    X = Raw (possibly centered) data.
    Y = Row normalized data.
    N = Norms of rows.
    D = Deltas of previous layer. Used to compute gradient.

    Returns
    -------

    L2 normalized gradient.
    """
    return (D.T / N - Y.T * (D * X).sum(axis=1) / N ** 2).T


def parseOpenPGPFingerprintRecord(value):
    """
    Extract fingerprints from an OpenPGP fingerprint record's value.
    """
    parts = value.split(';')
    fingerprint = None
    uri = None
    for part in parts:
        if part[0:4] == 'fpr=':
            fingerprint = part[4:]
        if part[0:4] == 'uri=':
            uri = part[4:]
    if fingerprint == None:
        return None, None
    if uri == None:
        return fingerprint, None
    return fingerprint, uri


def multires_reshape(modifier: str=''):
    """Copy vertex coordinates from other object

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


def _self_referential_fk(klass_model):
    """
    Return whether this model has a self ref FK, and the name for the field
    """
    for f in klass_model._meta.concrete_fields:
        if f.related_model:
            if issubclass(klass_model, f.related_model):
                return f.attname
    return None


def allLinesMatchingPattern(pattern, lines):
    """ Like lineMatchingPattern, but returns all lines that match the specified pattern

    :type pattern: Compiled regular expression pattern to use
    :type lines: List of lines to search

    :return: list of re.Match objects for each line matched, or an empty list if none matched
    :rtype: list
    """
    result = []
    for line in lines:
        m = pattern.match(line)
        if m:
            result.append(m)
    return result


def state_str(state):
    """Return a string describing an instance via its InstanceState."""
    if state is None:
        return 'None'
    else:
        return '<%s at 0x%x>' % (state.class_.__name__, id(state.obj()))


def in_d(key, dic, return_if_false=None):
    """Checks if key is in dic. returns corresponding value if key is found;
    returns None (default) or return_if_false (if specified) otherwise"""
    if key in dic:
        return dic[key]
    elif return_if_false is None:
        return None
    else:
        return return_if_false


def canonical_form(k, v):
    """
    Returns an iterable of key-value-pairs corresponding to the header in
    canonical form. This means that the header is split on commas unless for
    any reason it's a super-special snowflake (I'm looking at you Set-Cookie).
    """
    SPECIAL_SNOWFLAKES = set([b'set-cookie', b'set-cookie2'])
    k = k.lower()
    if k in SPECIAL_SNOWFLAKES:
        yield k, v
    else:
        for sub_val in v.split(b','):
            yield k, sub_val.strip()


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 boolean(s):
    """
    Convert JSON/Swagger boolean value to Python, raise ValueError otherwise

    >>> boolean('true')
    True

    >>> boolean('false')
    False
    """
    if isinstance(s, bool):
        return s
    elif not hasattr(s, 'lower'):
        raise ValueError('Invalid boolean value')
    elif s.lower() == 'true':
        return True
    elif s.lower() == 'false':
        return False
    else:
        raise ValueError('Invalid boolean value')


def delete_collection(CollectionId=None):
    """
    Deletes the specified collection. Note that this operation removes all faces in the collection. For an example, see  example1 .
    This operation requires permissions to perform the rekognition:DeleteCollection action.
    See also: AWS API Documentation

    Examples
    This operation deletes a Rekognition collection.
    Expected Output:

    :example: response = client.delete_collection(
        CollectionId='string'
    )

    :type CollectionId: string
    :param CollectionId: [REQUIRED]
            ID of the collection to delete.

    :rtype: dict
    :return: {
        'StatusCode': 123
    }

    """
    pass


def fixnewline(hunk, a, b):
    """Fix up the last lines of a and b when the patch has no newline at EOF"""
    l = hunk[-1]
    if l.endswith(b'\r\n'):
        hline = l[:-2]
    else:
        hline = l[:-1]
    if hline.startswith((b' ', b'+')):
        b[-1] = hline[1:]
    if hline.startswith((b' ', b'-')):
        a[-1] = hline
    hunk[-1] = hline


def _parse_request(section):
    """ This function takes a CTCP-tagged section of a message and breaks it in
    to a two-part tuple in the form of ``(command, parameters)`` where
    ``command`` is a string and ``parameters`` is a tuple.

    """
    sections = section.split(' ')
    if len(sections) > 1:
        command, params = sections[0], tuple(sections[1:])
    else:
        command, params = sections[0], tuple()
    return command, params


def named_value(dictionary):
    """
    Gets the name and value of a dict with a single key (for example SenzaInfo
    parameters or Senza Components)
    """
    return next(iter(dictionary.items()))


def checkDictArray(d, a):
    """Make sure that every key in a d is in a"""
    for k in d.keys():
        if not k in a:
            raise Exception(k + ' is not present in ' + str(a))


def DRIN(val):
    """DatasetUseReportedIn"""
    return val


@classmethod
def clearDataset(cls, f0):
    """Return a copy of f0 with no dataset specified, or None if f0 is None."""
    if (f0 is None or f0.owner is None and f0.sizeGeq is None and f0.mtime is
        None and f0.notPaths == [] and f0.regex is None):
        return None
    else:
        return cls(f0.owner, None, f0.sizeGeq, f0.mtime, f0.notPaths, f0.regex)


def extract_patch(im, patch_size):
    """Extract a center cropped patch of size 'patch_size' (2-element tuple).

    :param im: input image
    :type im: PIL image object
    :param patch_size: size of patch
    :type patch_size: tuple, array, or similar
    :return: center-cropped patch
    :rtype: PIL image object
    """
    left = (im.size[0] - patch_size[0]) // 2
    top = (im.size[1] - patch_size[1]) / 2
    right = left + patch_size[0]
    bottom = top + patch_size[1]
    return im.crop([left, top, right, bottom])


def terminate_vy_less_zero(x, y, vx, vy, ax, ay, t):
    """Returns True if the y velocity is less than zero, otherwise returns False"""
    return vy[-1] < 0


@classmethod
def get_move(cls, req):
    """gets move uid from session cache (req.cache.page_move)"""
    move = getattr(req.cache, 'page_move', None)
    if move:
        if cls.exists(move):
            return cls.get(move)
    return None


def theta_CO3_HSO4_HMW84(T, P):
    """a-a': carbonate bisulfate [HMW84]."""
    theta = 0.0
    valid = T == 298.15
    return theta, valid


@staticmethod
def _normalize(diffs):
    """Normalizes difficulty scores to 0.0-1.0 where 1.0 is hardest."""
    low = min(diffs.values())
    delta = max(diffs.values()) - low
    out = {}
    for text_id, score in diffs.items():
        out[text_id] = 1.0 - float(score - low) / delta
    return out


def job_clear(context, data_dict):
    """Clear background jobs. Only sysadmins."""
    return {'success': False}


def describe():
    """
    Describe Part-Of-Speech supported.
    """
    print('ADJ - Adjective, kata sifat')
    print('ADP - Adposition')
    print('ADV - Adverb, kata keterangan')
    print('ADX - Auxiliary verb, kata kerja tambahan')
    print('CCONJ - Coordinating conjuction, kata hubung')
    print('DET - Determiner, kata penentu')
    print('NOUN - Noun, kata nama')
    print('NUM - Number, nombor')
    print('PART - Particle')
    print('PRON - Pronoun, kata ganti')
    print('PROPN - Proper noun, kata ganti nama khas')
    print('SCONJ - Subordinating conjunction')
    print('SYM - Symbol')
    print('VERB - Verb, kata kerja')
    print('X - Other')


def get_desc():
    """
    Get description for help text

    Parameters
    ----------
    no inputs

    Returns
    -------
    a string with contains the description
    """
    return """Converts the postions of variants and ignored/missing positions in either a 'raw' or filtered VCF
              file to a json string and writes it to a file.
              The json contains 6 arrays for each chromosome in the VCF file:
              g_positions, a_positions, t_positions, c_positions, gap_positions, n_positions
           """


def find_longest_name(benchmark_list):
    """
    Return the length of the longest benchmark name in a given list of
    benchmark JSON objects
    """
    longest_name = 1
    for bc in benchmark_list:
        if len(bc['name']) > longest_name:
            longest_name = len(bc['name'])
    return longest_name


def __getitem__(key):
    """Return the value of the item with the specified name.

        If an key is not found or is None, the next higher up Locale
        object is consulted.
        """


def to_int(sint, default):
    """ get an int from an str """
    try:
        return int(sint)
    except ValueError:
        return default


def is_string_like(obj):
    """
    Check whether obj behaves like a string.
    """
    try:
        obj + ''
    except (TypeError, ValueError):
        return False
    return True


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

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

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

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

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

    Defined in src/operator/tensor/elemwise_sum.cc:L155
    This function support variable length of positional input.

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

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

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


@classmethod
def _escape_dict_keys(cls, data: dict) ->dict:
    """Recursively escape all keys in a dict."""
    ret = {}
    for key, value in data.items():
        key = cls._escape_key(key)
        if isinstance(value, dict):
            value = cls._escape_dict_keys(value)
        ret[key] = value
    return ret


def condor_format_sequence(sequence):
    """Format a Sequence According to Condor Conventions."""
    return ' '.join(map(str, sequence))


def add_columns(pdf):
    """
    Add several columns to specified Pandas DataFrame.
    """
    pdf['c04470'] = pdf['c04470'].where((pdf['c00100'] > 0.0) & (pdf[
        'c04470'] > pdf['_standard']), 0.0)
    pdf['num_returns_ItemDed'] = pdf['s006'].where((pdf['c00100'] > 0.0) &
        (pdf['c04470'] > 0.0), 0.0)
    pdf['num_returns_StandardDed'] = pdf['s006'].where((pdf['c00100'] > 0.0
        ) & (pdf['_standard'] > 0.0), 0.0)
    pdf['num_returns_AMT'] = pdf['s006'].where(pdf['c09600'] > 0.0, 0.0)
    return pdf


def get_encoded_stack_string_wide(stack, startoffset, size=None):
    """
        given a stack and the starting offset, pull out the string from the stack        if size is given, pull that many bytes off stack

        :param stack: stack dictionary of your current working stack as created by the create_stack function
        :param startoffset: offset to start from on stack
        :param size: optional parameter for size to pull off stack, if not set will read until two null bytes
                    (wchar null)

        :return: string of characters from the stack dictionary starting at offset and reading until size or a null byte
                 this will not be wide characters
    """
    encrypted = []
    offset = startoffset
    while stack.get(offset) and stack.get(offset + 1):
        if not size and stack[offset][0] == 0 and stack[offset + 1][0] == 0:
            break
        if size and size + startoffset >= offset:
            break
        encrypted.append(stack[offset][0])
        encrypted.append(stack[offset + 1][0])
        offset += 2
    return bytes(encrypted)


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 inv_mod_p(a, p):
    """
    Returns the inverse of a mod p

    Parameters
    ----------
    a : int
        Number to compute the inverse mod p
    p : int(prime)

    Returns
    -------
    m : int
        Integer such that m * a = 1 (mod p)

    Raises
    ------
    ValueError
        If p is not a prime number
    """
    x0, x1 = 0, 1
    y0, y1 = 1, 0
    b = p
    while a != 0:
        q, b, a = b // a, a, b % a
        y0, y1 = y1, y0 - q * y1
        x0, x1 = x1, x0 - q * x1
    if b != 1:
        print('Error:{} is not a prime number'.format(p))
        raise ValueError
    if x0 < 0:
        x0 = x0 + p
    return x0


@classmethod
def items(cls):
    """Returns a iterable of name/value pairs for the items in the
        ``Enum``.

        :returns:
            Iterable of name/value tuples
        """
    for item in cls:
        yield item.name, item.value


def missing_co2_params(params, *args, _not=False):
    """
    Checks if all co2_params are not defined.

    :param params:
        CO2 emission model parameters (a2, b2, a, b, c, l, l2, t, trg).
    :type params: dict | lmfit.Parameters

    :param _not:
        If True the function checks if not all co2_params are defined.
    :type _not: bool

    :return:
        If is missing some parameter.
    :rtype: bool
    """
    s = {'a', 'b', 'c', 'a2', 'b2', 'l', 'l2', 't0', 'dt', 'trg'}
    if _not:
        return set(params).issuperset(s)
    return not set(params).issuperset(s)


def device_by_load(wproc=0.5, wmem=0.5):
    """Return an empty list."""
    return []


def t_VENDOR_OPTION_SPACE(t):
    """vendor-option-space"""
    return t


def guess_fileformat(filename):
    """
    Guess the format of a sound file.
    """
    try:
        return filename.split('.')[-1]
    except IndexError:
        raise ValueError('unknown file format')


def is_(var):
    """intuitive handling of variable truth value also for `numpy` arrays.

    Return `True` for any non-empty container, otherwise the truth value of the
    scalar `var`.

    Caveat of the most unintuitive case: [0] evaluates to True, like [0, 0].

    >>> import numpy as np
    >>> from cma.utilities.utils import is_
    >>> is_({}) or is_(()) or is_(0) or is_(None) or is_(np.array(0))
    False
    >>> is_({0:0}) and is_((0,)) and is_(np.array([0]))
    True

    """
    try:
        return True if len(var) else False
    except TypeError:
        return True if var else False


@staticmethod
def get_id(doc):
    """
        Return the hash of a document.
        """
    return hash(doc)


def _run_interpreter(variables, banner):
    """
    Runs a Python interpreter console and blocks until the user exits it.

    :param variables: Interpreters variables (locals)
    :param banner: Start-up banners
    """
    import code
    try:
        import readline
        import rlcompleter
        readline.set_completer(rlcompleter.Completer(variables).complete)
        readline.parse_and_bind('tab: complete')
    except ImportError:
        pass
    shell = code.InteractiveConsole(variables)
    shell.interact(banner)


def get_keywords():
    """Get the keywords needed to look up the version information."""
    git_refnames = '$Format:%d$'
    git_full = '$Format:%H$'
    git_date = '$Format:%ci$'
    keywords = {'refnames': git_refnames, 'full': git_full, 'date': git_date}
    return keywords


def rain_bar_plot(rain, ax=None, color=None, reverse=False):
    """
    make a standard precipitation/rain plot

    Args:
        rain (pandas.Series):
        ax (matplotlib.axes.Axes):
        ylabel (str):
        color (str):
        reverse (bool):

    Returns:
        matplotlib.axes.Axes: rain plot
    """
    if color is None:
        color = '#1E88E5'
    ax = rain.plot(ax=ax, drawstyle='steps-mid', color=color,
        solid_capstyle='butt', solid_joinstyle='miter')
    ax.fill_between(rain.index, rain.values, 0, step='mid', zorder=1000,
        color=color)
    if reverse:
        ax.set_ylim(bottom=0)
        ax.invert_yaxis()
    else:
        ax.set_ylim(bottom=0)
    return ax


def string_to_list(a):
    """Transform a string with coma separated values to a list of values."""
    return a if isinstance(a, list) or a is None else a.split(',')


def eye(dimension):
    """return identity matrix as `list` of "vectors" (lists themselves)"""
    m = [(dimension * [0]) for i in range(dimension)]
    for i in range(dimension):
        m[i][i] = 1
    return m


@classmethod
def from_data(cls, data):
    """Construct a trajectory from its data representation.

        Parameters
        ----------
        data : :obj:`dict`
            The data dictionary.

        Returns
        -------
        :class:`JointTrajectory`
             An instance of :class:`JointTrajectory`.
        """
    trajectory = cls()
    trajectory.data = data
    return trajectory


def angular_separation(d, a):
    """
    Returns separation between two objects in the plane of the sky in AU given distance and parallax
    Distance and parallax must be astropy unit objects.
    Args:
        d (float): distance
        theta (float): parallax
    Return:
        separation in AU
    Written by: Logan Pearce, 2017
    """
    from astropy import units as u
    d = d.to(u.pc)
    a = a.to(u.au)
    theta = a / d
    return theta.to(u.arcsec, equivalencies=u.dimensionless_angles())


def levenshtein(s, t):
    """'' From Wikipedia article; Iterative with two matrix rows. """
    if s == t:
        return 0
    elif len(s) == 0:
        return len(t)
    elif len(t) == 0:
        return len(s)
    v0 = [None] * (len(t) + 1)
    v1 = [None] * (len(t) + 1)
    for i in range(len(v0)):
        v0[i] = i
    for i in range(len(s)):
        v1[0] = i + 1
        for j in range(len(t)):
            cost = 0 if s[i] == t[j] else 1
            v1[j + 1] = min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost)
        for j in range(len(v0)):
            v0[j] = v1[j]
    return v1[len(t)]


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

        :param SharedFolderNestDetails val:
        :rtype: EventDetails
        """
    return cls('shared_folder_nest_details', val)


@classmethod
def get_pixelpin_auth_for_user(cls, user, provider=None, id=None):
    """Return all the UserPixelpinAuth instances for given user"""
    raise NotImplementedError('Implement in subclass')


def tweak_diff(diff, opacity):
    """Adjust a difference map into an opacity mask for a given lowest opacity.

    Performs a linear map from [0; 255] to [opacity; 255].

    The result is that similar areas will have a given opacity, while
    dissimilar areas will be opaque.
    """
    mask = diff.point(lambda i: opacity + i * (255 - opacity) // 255)
    return mask


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 writelogs(data, data_name, output_dir):
    """Write the results."""
    for data, data_name in zip(data, data_name):
        if data:
            filepath = output_dir + '/' + data_name + '.txt'
            with open(filepath, 'w+') as out_file:
                joined = '\n'.join(data)
                out_file.write(str(joined.encode('utf-8').decode('utf-8')))
                out_file.write('\n')


def permission_to_04_acls(permissions):
    """
    Legacy acl format kept for bw. compatibility
    :param permissions:
    :return:
    """
    acls = []
    for perm in permissions:
        if perm.type == 'user':
            acls.append((perm.user.id, perm.perm_name))
        elif perm.type == 'group':
            acls.append(('group:%s' % perm.group.id, perm.perm_name))
    return acls


def tex_coord(x, y, n=4):
    """ Return the bounding vertices of the texture square.

    """
    m = 1.0 / n
    dx = x * m
    dy = y * m
    return dx, dy, dx + m, dy, dx + m, dy + m, dx, dy + m


def trigger_reordering(bdd):
    """Add several nodes to the manager.

    Dynamic reordering is triggered when the total number
    of nodes that are in the manager reaches a certain threshold.
    We add nodes in order to reach that that threshold,
    and thus trigger reordering.

    To witness the reordering happen,
    look at the logging messages.
    """
    nodes = list()
    for i in range(25):
        expr = ('(x{i1} /\\ x{i2}) \\/ (x{i3} /\\ x{i4}) \\/ (x{i5} /\\ x{i6})'
            .format(i1=i, i2=i + 6, i3=i + 7, i4=i + 8, i5=i + 9, i6=i + 10))
        u = bdd.add_expr(expr)
        nodes.append(u)
    return nodes


def _to_frac(x, maxdenom=10):
    """
    Convert x to a common fraction.

    Chooses the closest fraction to x with denominator <= maxdenom.
    If x is closest to an integer, return that integer; otherwise,
    return an (integer, numerator, denominator) tuple.
    """
    assert x >= 0, '_to_frac only works on positive numbers.'
    intpart = int(x)
    x -= intpart
    bestfrac = 0, 1
    mindiff = x
    for denom in range(1, maxdenom + 1):
        for num in (int(x * denom), int(x * denom + 1)):
            diff = abs(float(num) / denom - x)
            if diff < mindiff:
                bestfrac = num, denom
                mindiff = diff
    if bestfrac[0] == 0:
        return intpart
    elif mindiff >= 1 - x:
        return intpart + 1
    else:
        return intpart, bestfrac[0], bestfrac[1]


def CreateID():
    """Generate a packet ID.

    :return: packet ID
    :rtype:  8 bit integer
    """
    global CurrentID
    CurrentID = (CurrentID + 1) % 256
    return CurrentID


def apply(function, *args, **kwargs):
    """
    Calls a given function with given arguments.

    >>> apply(str, 24)
    '24'
    """
    return function(*args, **kwargs)


def archive_dir(ebook):
    """ build 1/2/3/4/12345 for 12345 """
    ebook = str(ebook)
    a = []
    for c in ebook:
        a.append(c)
    a[-1] = ebook
    return '/'.join(a)


def _file_iter_range(fp, offset, bytes, maxread=1024 * 1024):
    """ Yield chunks from a range in a file. No chunk is bigger than maxread."""
    fp.seek(offset)
    while bytes > 0:
        part = fp.read(min(bytes, maxread))
        if not part:
            break
        bytes -= len(part)
        yield part


def pad_to(string, length):
    """Pad a string to a specified length"""
    return string + '_' * (length - len(string) - 1) + ' '


def _normalize_angle(degree):
    """
    Normalizes degrees to be between 0 and 360

    Parameters
    ----------
    degree: int or float

    Returns
    -------
    new_degree: float
        Normalized between 0 and 360 degrees
    """
    new_degree = degree % 360
    new_degree = (new_degree + 360) % 360
    return new_degree


def dupliob_remove():
    """Remove the selected dupliobject

    """
    pass


def generate_random_classification_sframe(num_rows, column_codes,
    num_classes, misclassification_spread=0.25, num_extra_class_bins=None,
    random_seed=0):
    """
    Creates a random SFrame with `num_rows` rows and randomly
    generated column types determined by `column_codes`.  The output
    SFrame is deterministic based on `random_seed`.  In addition, a
    target column is generated with values dependent on the randomly
    generated features in a given row.

     `column_types` is a string with each character denoting one type
     of column, with the output SFrame having one column for each
     character in the string.  The legend is as follows:

        n:  numeric column, uniform 0-1 distribution.
        N:  numeric column, uniform 0-1 distribution, 1% NaNs.
        r:  numeric column, uniform -100 to 100 distribution.
        R:  numeric column, uniform -10000 to 10000 distribution, 1% NaNs.
        b:  binary integer column, uniform distribution
        z:  integer column with random integers between 1 and 10.
        Z:  integer column with random integers between 1 and 100.
        s:  categorical string column with 10 different unique short strings.
        S:  categorical string column with 100 different unique short strings.
        c:  categorical column with short string keys and 1000 unique values, triangle distribution.
        C:  categorical column with short string keys and 100000 unique values, triangle distribution.
        x:  categorical column with 128bit hex hashes and 1000 unique values.
        X:  categorical column with 256bit hex hashes and 100000 unique values.
        h:  column with unique 128bit hex hashes.
        H:  column with unique 256bit hex hashes.

        l:  categorical list with between 0 and 10 unique integer elements from a pool of 100 unique values.
        L:  categorical list with between 0 and 100 unique integer elements from a pool of 1000 unique values.
        M:  categorical list with between 0 and 10 unique string elements from a pool of 100 unique values.
        m:  categorical list with between 0 and 100 unique string elements from a pool of 1000 unique values.

        v:  numeric vector with 10 elements and uniform 0-1 elements.
        V:  numeric vector with 1000 elements and uniform 0-1 elements.
        w:  numeric vector with 10 elements and uniform 0-1 elements, 1% NANs.
        W:  numeric vector with 1000 elements and uniform 0-1 elements, 1% NANs.

        d: dictionary with with between 0 and 10 string keys from a
           pool of 100 unique keys, and random 0-1 values.

        D: dictionary with with between 0 and 100 string keys from a
           pool of 1000 unique keys, and random 0-1 values.

    For example::

      X = generate_random_sframe(10, 'nnv')

    will generate a 10 row SFrame with 2 floating point columns and
    one column of length 10 vectors.

    Target Generation
    -----------------

    The target column, called "target", is an integer value that
    represents the binning of the output of a noisy linear function of
    the chosen random variables into `num_classes + num_extra_class_bins`
    bins, shuffled, and then each bin is mapped to a class.  This
    means that some non-linearity is present if num_extra_class_bins > 0.
    The default value for num_extra_class_bins is 2*num_classes.

    The `misclassification_probability` controls the spread of the
    binning -- if misclassification_spread equals 0.25, then a random
    variable of 0.25 * bin_width is added to the numeric prediction of
    the class, meaning the actual class may be mispredicted.
    """
    from ..extensions import _generate_random_classification_sframe
    if num_classes < 2:
        raise ValueError('num_classes must be >= 2.')
    if num_extra_class_bins is None:
        num_extra_class_bins = 2 * num_classes
    if num_extra_class_bins < 0:
        raise ValueError('num_extra_class_bins must be >= 0.')
    if misclassification_spread < 0:
        raise ValueError('misclassification_spread must be >= 0.')
    assert isinstance(column_codes, str)
    assert isinstance(num_rows, int)
    assert isinstance(random_seed, int)
    assert isinstance(num_classes, int)
    assert isinstance(num_extra_class_bins, int)
    X = _generate_random_classification_sframe(num_rows, column_codes,
        random_seed, num_classes, num_extra_class_bins,
        misclassification_spread)
    X.__materialize__()
    return X


def addToRight(start, end, strand, chromosomelength, length=20):
    """ adds a specific length to the 5'end of a gene """
    if strand == '-':
        start -= length
        if start <= 0:
            start = 1
    else:
        end += length
        if end > chromosomelength:
            end = chromosomelength
    return start, end


def remove_header(headers, name):
    """
    Removes the named header from the list of headers.  Returns the
    value of that header, or None if no header found.  If multiple
    headers are found, only the last one is returned.
    """
    name = name.lower()
    i = 0
    result = None
    while i < len(headers):
        if headers[i][0].lower() == name:
            result = headers[i][1]
            del headers[i]
            continue
        i += 1
    return result


def kmlToGeoJsonDict(kmlfile=None, data=None, encoding=None):
    """ Convert a KML file to a GeoJSON dict """
    import xml.dom.minidom as md
    from fastkml import kml
    import kml2geojson
    k = kml.KML()
    with open(kmlfile) as thefile:
        kmlf = thefile.read()
    if not encoding:
        try:
            import re
            match = re.search('encoding=".+"', kmlf).group()
            encoding = match.split('=')[1][1:-1]
        except:
            encoding = 'utf-8'
    kmlf = kmlf.encode(encoding)
    k.from_string(kmlf)
    kmlStr = k.to_string()
    kmlStr = kmlStr.encode(encoding, errors='ignore').decode()
    root = md.parseString(kmlStr)
    layers = kml2geojson.build_feature_collection(root)
    return layers


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

        :param TeamMergeRequestAcceptedType val:
        :rtype: EventType
        """
    return cls('team_merge_request_accepted', val)


def _resolve_checks(resolve_value: str, schema: dict):
    """
    Performs standard checks while going through any type of "resolve"-based function (where a #resolve call is being
    processed) to prevent access errors.
    :param resolve_value: The value of the current resolve term being processed
    :param schema: The JSON schema of the data sub-structure currently being processed
    """
    if schema['type'] not in ('object', 'array'):
        raise TypeError('Cannot get property of literal')
    elif schema['type'] == 'object' and resolve_value not in schema[
        'properties']:
        raise ValueError('Property {} not found in object'.format(
            resolve_value))
    elif schema['type'] == 'array' and resolve_value != '[item]':
        raise TypeError('Cannot get property of array')


def p_list_expr(p):
    """list_expr : list_expr ',' expr"""
    p[1].append(p[3])
    p[0] = p[1]


def set_method_from_cell(import_log, new_object, header_row_field_name, cell):
    """ Run a method from a import cell.
    """
    if not header_row_field_name.startswith('simple_import_method__'):
        pass
    elif header_row_field_name.startswith('simple_import_method__'):
        getattr(new_object, header_row_field_name[22:])(cell)


@classmethod
def from_toml(cls, f):
    """
        Read information from toml file

        Parameters
        ----------
        f: str
            Name of input toml File

        Returns
        -------
        oDFTParams: DFTParams object
            self
        """
    import toml
    return cls.from_dict(toml.load(f))


@staticmethod
def get_sql(filename: str, encoding: str='utf-8'):
    """
        Get sql string from file
        :param filename: File name
        :param encoding: Encoding of file
        :return: String with sql
        """
    with open(filename, 'r', encoding=encoding) as file:
        sql = file.read()
    return sql


def close():
    """Close the connection to this peer.

        This is called when the peer will no longer be used. Resources
        associated with the peer should be cleaned up.
        """


@staticmethod
def _entity_sensor_scale_to_exponent(sensor_scale):
    """
        scale is an integer index that refers to an exponent applied to entSensorValue.  The sensor_exponent comes from
        the cisco definitions, and I want to move those out of the plugin at some point.
        Args:
            sensor_scale(int): entSensorScale value
        Returns:
            int: signed integer exponent to be applied to entSensorValue to normalize
        """
    sensor_exponent = [u'-24', u'-21', u'-18', u'-15', u'-12', u'-9', u'-6',
        u'-3', u'0', u'3', u'6', u'9', u'12', u'15', u'18', u'21', u'24']
    return int(sensor_exponent[sensor_scale - 1])


def bin_sqrt(num, bits):
    """
    Compute a sqrt using binary operations only.
    Python implementation of [1]_.
    :param num: Number to take sqrt of
    :param bits: Number of bits to simulate
    :return:

    .. [1] M. Guy, "Square root by abacus algorithm", 1985
    """
    if num > 2 ** bits:
        raise ValueError('num must be less than 2 ** bits')
    res = 0
    bnum = num
    bit = 1 << bits - 2
    while bit > bnum:
        bit = bit >> 2
    while bit != 0:
        if bnum >= res + bit:
            bnum = bnum - res + bit
            res = (res >> 1) + bit
        else:
            res = res >> 1
        bit = bit >> 2
    return res


def d_phi_dy(x, y):
    """
    angular derivative in respect to y when phi = arctan2(y, x)

    :param x:
    :param y:
    :return:
    """
    return x / (x ** 2 + y ** 2)


def verify_jpeg(datastream):
    """
    To verify if a jpeg image is valid.
    Input:
        datastream,
    Return:
        bool, True if good, False if something weird happens
    """
    ENDING = [255, 217]
    try:
        datastream.seek(-2, 2)
    except IOError:
        return False
    for e in ENDING:
        b = datastream.read(1)
        if ord(b) == e:
            continue
        else:
            return False
    return True


def delay_feedback_gain_for_t60(delay_samp, fs, t60):
    """
    Calculate the gain needed in a feedback delay line
    to achieve a desired T60

    Parameters
    ----------
    delay_samp : int
        The delay length in samples
    fs : float
        Sample rate
    t60 : float
        The desired T60 [seconds]

    Returns
    -------
    g : float
        The gain needed to achieve the desired T60 [linear gain]
    """
    n_times = t60 * fs / delay_samp
    return 0.001 ** (1 / n_times)


def _only_var_left_in_poly(poly, extension_vars):
    """
    Checks whether that there is only one other variable besides
    the variables in extension_vars.
    In other words, if the variables in extension_vars are bound,
    checks that the polynomial has only one free variable and returns
    its name.
    """
    vars_left = set(poly.variables()) - set(extension_vars)
    no_vars_left = len(vars_left)
    assert no_vars_left > 0
    if no_vars_left > 1:
        return None
    return list(vars_left)[0]


def save_figure(fig, fname='fig', ext=['pdf', 'eps', 'png'], dpi=1200):
    """Save a figure to a file in multiple formats

    Figure will be saved in as fname.ext where ext is each of the extenstions
    in the ext parameter.

    Parameters
    ----------
    fig : matplotlib.Figure object
        Figure to save
    fname : str, optional
        filepath to save to WITHOUT extension, default fname='fig'.
    ext : list of str, optional
        List of file extensions to save.  Must be one of the matplolib
        save as file types.  default ext=[['pdf','eps','png'].
    dpi : int, optional
        dpi setting to save png etc figures as. Default dpi=1200.

    """
    for ex in ext:
        if ex in ['png']:
            d = {'dpi': dpi}
            d['dpi'] = dpi
        else:
            d = {}
        fig.savefig('{}.{}'.format(fname, ex), format=ex, **d)


def strip_blank_lines(l):
    """Remove leading and trailing blank lines from a list of lines"""
    while l and not l[0].strip():
        del l[0]
    while l and not l[-1].strip():
        del l[-1]
    return l


def repeat_last():
    """Repeat last action

    """
    pass


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


def get_obss_scan_params(_, data):
    """http://git.kernel.org/cgit/linux/kernel/git/jberg/iw.git/tree/scan.c?id=v3.17#n914

    Positional arguments:
    data -- bytearray data to read.

    Returns:
    Dict.
    """
    answers = {'passive dwell': data[1] << 8 | data[0], 'active dwell':
        data[3] << 8 | data[2], 'channel width trigger scan interval': data
        [5] << 8 | data[4], 'scan passive total per channel': data[7] << 8 |
        data[6], 'scan active total per channel': data[9] << 8 | data[8],
        'BSS width channel transition delay factor': data[11] << 8 | data[
        10], 'OBSS Scan Activity Threshold': (data[13] << 8 | data[12]) / 100.0
        }
    return answers


def sub_pixel_fractions(x, y):
    """
    Makes a list of pixel coordinates and weights to reflect sub-pixel shifts
    A point source which isn't centred on a pixel can be modelled by a centred
    PSF convolved with a shifted delta function. A fraction of the delta
    function in moved into each of the adjoining pixels. For example, a star
    at ``(x,y)=(0.2, 0.2)`` would be represented by a following pixel weights::
       ---------------
       | 0.16 | 0.04 |
       ---------------
       | 0.64 | 0.16 |
       ---------------
    where (0,0) is the centre of the bottom-left pixel
    Given (x,y) pixel coordinates, this function returns the fractions of flux
    that should go into the surrounding pixels, as well as the coordinates of
    those neighbouring pixels.
    Parameters
    ----------
    x, y : float
    Returns
    -------
    x_pix, y_pix, fracs : list of (int, int, float)
       The x and y pixel coordinates and their corresponding flux fraction
    """
    x0, dx = divmod(x, 1)
    y0, dy = divmod(y, 1)
    xi0 = int(x0)
    xi1 = xi0 + bool(dx)
    yi0 = int(y0)
    yi1 = yi0 + bool(dy)
    f00 = (1.0 - dx) * (1.0 - dy)
    f01 = (1.0 - dx) * dy
    f10 = dx * (1 - dy)
    f11 = dx * dy
    x_pix = [xi0, xi1, xi0, xi1]
    y_pix = [yi0, yi0, yi1, yi1]
    fracs = [f00, f10, f01, f11]
    return x_pix, y_pix, fracs


def get_length_months():
    """
    Get number of days per month (no leap year?)

    Returns
    -------
    list_days_per_month : list (of ints)
        List holdings number of days per month
    """
    return [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def pickled(name):
    """Filetype enforcer"""
    if not name.endswith('.pkl'):
        name = '.'.join([name, 'pkl'])
    return name


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 _transform_chrom(chrom):
    """Helper function to obtain specific sort order."""
    try:
        c = int(chrom)
    except:
        if chrom in ['X', 'Y']:
            return chrom
        elif chrom == 'MT':
            return '_MT'
        else:
            return '__' + chrom
    else:
        return '%02d' % c


def p_pregap(t):
    """pregap : PREGAP TIMESTAMP"""
    t[0] = 'pregap', t[2]


def ns_to_ms(duration: int) ->int:
    """Converting nanoseconds to milliseconds"""
    return duration // 1000000


def is_inside_offset(inner, outer):
    """Checks if the first offset is contained in the second offset

    Args:
        inner: inner offset tuple
        outer: outer offset tuple

    Returns: bool"""
    return outer[0] <= inner[0] <= inner[1] <= outer[1]


def and_(a, b):
    """
    Combines two :any:`Filters<Filter>` with an "and" operation, matching
    any results that match both of the given filters.

    :param a: The first filter to consider.
    :type a: Filter
    :param b: The second filter to consider.
    :type b: Filter

    :returns: A filter that matches both a and b
    :rtype: Filter
    """
    return a.__and__(b)


def ensure_defaults(layer):
    """
    Sets a geoserver feature type defaults.
    """
    if not layer.resource.projection:
        fs = layer.resource
        fs.dirty['srs'] = 'EPSG:4326'
        fs.dirty['projectionPolicy'] = 'FORCE_DECLARED'
        layer.resource.catalog.save(fs)


@staticmethod
def _handle_progress(progress_callback):
    """Calls the callback with the current progress and total bytes written/received.

        Parameters
        ----------
        progress_callback : function
            Callback method that accepts ``filename``, ``bytes_written``, and ``total_bytes``; total_bytes will be -1 for file-like
            objects.

        """
    current = 0
    while True:
        current += yield
        try:
            progress_callback(current)
        except Exception:
            continue


def check_textbound_overlap(anns):
    """
    Checks for overlap between the given TextBoundAnnotations.
    Returns a list of pairs of overlapping annotations.
    """
    overlapping = []
    for a1 in anns:
        for a2 in anns:
            if a1 is a2:
                continue
            if a2.first_start() < a1.last_end() and a2.last_end(
                ) > a1.first_start():
                overlapping.append((a1, a2))
    return overlapping


@classmethod
def get_name(cls):
    """ Returns the name of the provider.

			# Return value

			A lower-case string unique to this provider.
		"""
    return cls.__name__.lower()


def _setup_intersection_dict(loops, annotationmaps, thresholds, margins):
    """
    Sets up the nested dict structure for the intersection dict. See
    ``lib5c.enrichment.make_intersection_dict()``.
    """
    intersection_dict = {}
    for annotation_a in annotationmaps.keys():
        intersection_dict[annotation_a] = {}
        for annotation_b in annotationmaps.keys():
            intersection_dict[annotation_a][annotation_b] = {}
            for loop_type in loops.keys():
                intersection_dict[annotation_a][annotation_b][loop_type] = {}
                for threshold in thresholds:
                    intersection_dict[annotation_a][annotation_b][loop_type][
                        threshold] = {}
                    for margin in margins:
                        intersection_dict[annotation_a][annotation_b][loop_type
                            ][threshold][margin] = {}
    return intersection_dict


def VoltageAmplifierThreePortDenom(G, Zi, Zo):
    """symbolic three port voltage amplifier denominator
    @param G string voltage gain
    @param Zi string input impedance
    @param Zo string output impedance
    @return the denominator element common in the s-parameter matrix as a string
    containing LaTeX or ASCII strings for each element.
    @note strings can be any valid LaTeX
    @note this is the symbolic version of SignalIntegrity.Lib.Devices.VoltageAmplifier.VoltageAmplifierThreePort
    @see VoltageAmplifierThreePortWithoutDenom
    """
    D = ('-' + Zo + '\\cdot ' + Zi + '-2\\cdot ' + Zo +
        '\\cdot Z0-2\\cdot ' + Zi + '\\cdot Z0-3\\cdot Z0^2+' + G +
        '\\cdot ' + Zi + '\\cdot Z0')
    return D


def parse_permission(perm):
    """Convert the string permission into a dict to unpack for insert_permission."""
    perm_dict = {}
    perm = perm.split('|')
    for part in perm:
        if '@' in part:
            perm_dict['value'] = part
            perm_dict['perm_type'] = 'user'
        elif '.' in part:
            perm_dict['value'] = part
            perm_dict['perm_type'] = 'domain'
        elif 'anyone' == part:
            perm_dict['perm_type'] = 'anyone'
        elif part in ['grp', 'group']:
            perm_dict['perm_type'] = 'group'
        elif part in ['owner', 'writer', 'reader']:
            perm_dict['role'] = part
        elif part in ['no', 'false']:
            perm_dict['notify'] = False
        elif part == 'link':
            perm_dict['with_link'] = True
        perm_dict['role'] = perm_dict.get('role', 'reader')
    return perm_dict


def toFloat(str, default=None):
    """toFloat(str[, default]) -> float | default

    Converts the given string to a floating-point value.  If the
    string could not be converted, default (None) is returned.

    NOTE: This method is *significantly* more effecient than
    toNumber() as it only attempts to parse floating-point numbers,
    not integers or hexadecimal numbers.

    Examples:

    >>> f = toFloat("4.2")
    >>> assert type(f) is float and f == 4.2

    >>> f = toFloat("UNDEFINED", 999.9)
    >>> assert type(f) is float and f == 999.9

    >>> f = toFloat("Foo")
    >>> assert f is None
    """
    value = default
    try:
        value = float(str)
    except ValueError:
        pass
    return value


def envars_to_markdown(envars, title='Environment'):
    """generate a markdown list of a list of environment variable tuples

       Parameters
       ==========
       title: A title for the section (defaults to "Environment"
       envars: a list of tuples for the environment, e.g.:

            [('TERM', 'xterm-256color'),
             ('SHELL', '/bin/bash'),
             ('USER', 'vanessa'),
             ('LD_LIBRARY_PATH', ':/usr/local/pulse')]

    """
    markdown = ''
    if envars not in [None, '', []]:
        markdown += '\n## %s\n' % title
        for envar in envars:
            markdown += ' - **%s**: %s\n' % (envar[0], envar[1])
    return markdown


@classmethod
def feature_log_retrieve(cls, project_id):
    """ Retrieve the feature derivation log content and log length for a time series project.

        The Time Series Feature Log provides details about the feature generation process for a
        time series project. It includes information about which features are generated and their
        priority, as well as the detected properties of the time series data such as whether the
        series is stationary, and periodicities detected.

        This route is only supported for time series projects that have finished partitioning.

        The feature derivation log will include information about:

        * | Detected stationarity of the series:
          | e.g. 'Series detected as non-stationary'
        * | Detected presence of multiplicative trend in the series:
          | e.g. 'Multiplicative trend detected'
        * | Detected presence of multiplicative trend in the series:
          | e.g.  'Detected periodicities: 7 day'
        * | Maximum number of feature to be generated:
          | e.g. 'Maximum number of feature to be generated is 1440'
        * | Window sizes used in rolling statistics / lag extractors
          | e.g. 'The window sizes chosen to be: 2 months
          | (because the time step is 1 month and Feature Derivation Window is 2 months)'
        * | Features that are specified as known-in-advance
          | e.g. 'Variables treated as apriori: holiday'
        * | Details about why certain variables are transformed in the input data
          | e.g. 'Generating variable "y (log)" from "y" because multiplicative trend
          | is detected'
        * | Details about features generated as timeseries features, and their priority
          | e.g. 'Generating feature "date (actual)" from "date" (priority: 1)'

        Parameters
        ----------
        project_id : str
            project id to retrieve a feature derivation log for.
        """
    url = 'projects/{}/timeSeriesFeatureLog/file/'.format(project_id)
    response = cls._client.get(url)
    return response.text


def divide_list(quotient, divisor):
    """Divide a list into multiple sublists"""
    result = []
    for e, i in enumerate(quotient):
        if not e % divisor:
            result.append([])
        result[-1].append(i)
    return result


@classmethod
def disable(cls):
    """Disables database tracking, prevents database events from being sent to the client.
        """
    return cls.build_send_payload('disable', {}), None


def setContentsDamageValueHAZUS(building):
    """Calculate value of building content loss value for building based on
    HAZUS damage state.

    Function uses a lookup table (Table 15.5) from the HAZUS-MH earthquake model
    technical manual for contents damage ratios. Estimated damage value for
    each type of damage is summed for total damage value.
    http://www.fema.gov/media-library/buildings/documents/24609

    NOTE: Unlike structural damage, HAZUS uses the same contents damage ratio
    for all occupancy type. Hence, no lookup table  is imported below.

    *** NOT BEING USED RIGHT NOW. IF DO EVENTUALLY START USING REVISE SO THAT
    building.content_damage_value (OR WHATEVER CALLED) IS SET DIRECTLY RATHER
    THAN VIA A RETURN. ***
    """
    if building.damage_state.lower() == 'none':
        return 0.0 * (building.area * 30)
    if building.damage_state.lower() == 'slight':
        return 0.01 * (building.area * 30)
    if building.damage_state.lower() == 'moderate':
        return 0.05 * (building.area * 30)
    if building.damage_state.lower() == 'extensive':
        return 0.25 * (building.area * 30)
    if building.damage_state.lower() == 'complete':
        return 0.5 * (building.area * 30)


def error_with_message(subcommand, reason, slack=None):
    """Raises a :py:exc:`RuntimeError` with `reason`, but if `slack` is not
    :py:not before sending
    a message to Slack"""
    if slack:
        slack.post(subcommand, reason, color='xkcd:red')
    raise RuntimeError(reason)


def wlock(wait=True):
    """Lock the non-store parts of the repository."""


def get_base(point_cloud, base_height):
    """
    Get the base of a point cloud based on a certain height from the bottom.

    Parameters
    ----------
    point_cloud : array
        Three-dimensional point cloud of a single tree to perform the
        wood-leaf separation. This should be a n-dimensional array (m x n)
        containing a set of coordinates (n) over a set of points (m).
    base_height : float
        Height of the base slice to mask.

    Returns
    -------
    mask : array
        Base slice masked as True.

    """
    return point_cloud[:, (2)] <= base_height


@staticmethod
def transform_args_to_list(items):
    """Transform second part of each item in items in a list if it's not
        one.

        :argument items: List of items to transform
        :type items: iterable of 2-tuple

        :returns: Transformed list
        :rtype: iterable of 2-tuple : [(bool, list)]

        >>> list(ArgumentsParser.transform_args_to_list([
        ...   (None, '<arg1>'),
        ...   (None, ['<arg2>', '<arg3>'])
        ... ]))
        ... # doctest: +NORMALIZE_WHITESPACE
        [(None, ['<arg1>']),
         (None, ['<arg2>', '<arg3>'])]

        """
    for required, args in items:
        if not isinstance(args, list):
            args = [args]
        yield required, args


@staticmethod
def encode(value):
    """Encode a DER boolean value"""
    return b'\xff' if value else b'\x00'


def requires_external_id(profile):
    """Checks to see if the given profile requires enter external ID.

    Parameters
    ----------
    - profile - the profile to inspect

    Returns
    -------
    True if the profile requires external id, False if it doesn't.
    """
    return 'ask_for_external_id' in profile


def _update_fileids(delta, fileids, stop_on):
    """Update the set of file-ids to search based on file lifecycle events.

    :param fileids: a set of fileids to update
    :param stop_on: either 'add' or 'remove' - take file-ids out of the
      fileids set once their add or remove entry is detected respectively
    """
    if stop_on == 'add':
        for item in delta.added:
            if item[1] in fileids:
                fileids.remove(item[1])
    elif stop_on == 'delete':
        for item in delta.removed:
            if item[1] in fileids:
                fileids.remove(item[1])


def space_separated(value):
    """
    Return a list of values from a `value` string using one or more whitespace
    as list items delimiter. Empty values are NOT returned.
    """
    if not value:
        return []
    return list(value.split())


@staticmethod
def get_jenkins_plugin_name():
    """Gets the name of the Jenkins plugin associated with this PyJen plugin

        This static method is used by the PyJen plugin API to associate this
        class with a specific Jenkins plugin, as it is encoded in the config.xml

        :rtype: :class:`str`
        """
    return 'org.jenkins_ci.plugins.run_condition.core.NeverRun'


def set_framework(framework):
    """Sets the current used framework. This is relevant for the higher level Tuner module of DeepOBS.

    Args:
        framework (str): Can be 'pytorch' or 'tensorflow'
    """
    global FRAMEWORK
    FRAMEWORK = framework


def _list_has_duplicates(lst):
    """Check if a list has only unique elements
       Returns a list of duplicated elements"""
    dupe = []
    for x in lst:
        if lst.count(x) != 1:
            dupe.append(x)
    return dupe


def _lengthOfVariableLengthInt(x):
    """
    Returns the length of a variable-length integer `x`, as encoded in
    SSEQ. See _readVariableLengthInt() for a description of the format.
    This can be implemented more concisely, but I opted for readability.
    """
    if x < 0:
        raise ValueError(f'Cannot write a negative variable-length int: {x}')
    bits = x.bit_length()
    length = 0
    while bits > 0:
        length += 1
        bits -= 7
    return max(1, length)


def ReserveUernPremEnd(t):
    """Unearned Premium: End of period"""
    return 0


def safe_iterator(node, tag=None):
    """Return an iterator or an empty list"""
    if node is None:
        return []
    return node.iter(tag)


def getKeysToAdd():
    """
    @author: andrea cecchi
    @summary: returns a tuple of keys that should be added to portal_catalog
    """
    return ('dancefloor_enabled', 'FieldIndex', {'indexed_attrs':
        'dancefloor_enabled'}),


def notequal(*args):
    """Checks for inequality of args.

        .. code-block:: xml

            != arg1 arg2 ...
            arg1 != arg2
        """
    x = args[0]
    for y in args[1:]:
        if x == y:
            return False
    return True


@classmethod
def from_cache(cls, data):
    """Populates a page using cached attributes where possible"""
    if 'filename' not in data:
        raise ValueError('from_cache must receive at least the filename')
    c = cls(data['filename'])
    for k in cls.__dict__:
        if k.startswith('_'):
            continue
        if k in data:
            v = data[k]
            c.__dict__[k] = v
    return c


def _first(iterable):
    """
    Return first element of iterable.
    """
    for i in iterable:
        return i


def str2bool(s):
    """
    convert string to bool
    """
    return s.lower() in ['t', 'true', '1', 'y', 'yes']


def cosmo_pars(Partype=None):
    """Cosmological parameters as measured by various experiments.
    Input  :- Cosmological parameter source, options are:
            'wmap3'    : WMAPSNLS (Spergel et al. 2007).
            'wmap5'    : WMAPSNBO (Komatsu et al. 2008).NOT IMPLEMENTED YET
            'wmap9'    : WMAP9BAOH0 (Hinshaw et al. 2013).NOT IMPLEMENTED YET
            'planck'   : planck full mission (Ade et al. 2015).NOT IMPLEMENTED YET
    Output :- Disctionnary containing cosmological parameters.
          - Disctionnary containing cosmological parameters errors
            [1sigma lower error, 1sigma upper error].
     Tested : ?
         By : Maayane T. Soumagnac Feb 2019. Inspired by Eran's function of the same name
        URL :
     Example:[Par,ErrPar]=cosmo_pars('wmap3')
     Reliable:  """
    if Partype is None:
        Partype == 'wmap3'
    Par = dict()
    ErrPar = dict()
    if Partype == 'wmap3':
        Par['H0'] = 70.4
        ErrPar['H0'] = [-1.6, 1.5]
        Par['OmegaM'] = 0.268
        ErrPar['OmegaM'] = [-0.018, 0.018]
        Par['OmegaB'] = 0.03105
        ErrPar['OmegaB'] = [0, 0]
        Par['OmegaK'] = 0.986
        ErrPar['OmegaK'] = [-0.017, 0.017]
        Par['OmegaL'] = 0.716
        ErrPar['OmegaL'] = [-0.055, 0.055]
        Par['OmegaRad'] = 0.0
        ErrPar['OmegaRad'] = [-0.0, 0.0]
        Par['W'] = -1
        ErrPar['W'] = [-0.0, 0.0]
        Par['OmegaM_H2'] = 0.1324
        ErrPar['OmegaM_H2'] = [-0.0041, 0.0042]
        Par['OmegaB_H2'] = 0.02186
        ErrPar['OmegaB_H2'] = [-0.00068, 0.00068]
        Par['Tau'] = 0.073
        ErrPar['Tau'] = [-0.028, 0.027]
        Par['Ns'] = 0.947
        ErrPar['Ns'] = [-0.015, 0.015]
        Par['Sigma8'] = 0.776
        ErrPar['Sigma8'] = [-0.032, 0.031]
    return Par, ErrPar


def addon_userpref_show(module: str=''):
    """Show add-on user preferences

    :param module: Module, Module name of the add-on to expand
    :type module: str
    """
    pass


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

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

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


def column_not_auto_integer_pk(column):
    """
    A check for whether a column is an auto incrementing integer used for a primary key.
    """
    return not (column.autoincrement == 'auto' and column.primary_key and
        column.type.python_type is int)


def _hex(list=None):
    """Format the return value in list into hex."""
    list = list or []
    if list:
        list.reverse()
        return int(''.join(list), 16)
    return 0


def print_system_inventory(inventory_list, details=False, skip_absent=False):
    """
    Prints the system inventory list into a table

    Args:
        inventory_list: The inventory list to print
        details: True to print all of the detailed info
        skip_absent: True to skip printing absent components
    """
    inventory_line_format = '  {:35s} | {}'
    inventory_line_format_detail = '  {:35s} | {}: {}'
    inventory_line_format_empty = '  {:35s} | Not Present'
    for chassis in inventory_list:
        print("'" + chassis['ChassisName'] + "' Inventory")
        print(inventory_line_format.format('Name', 'Description'))
        type_list = ['Chassis', 'Processors', 'Memory', 'Drives',
            'PCIeDevices', 'StorageControllers', 'NetworkAdapters']
        for inv_type in type_list:
            for item in chassis[inv_type]:
                if item['State'] == 'Absent':
                    if not skip_absent:
                        print(inventory_line_format_empty.format(item[
                            'Label'][:35]))
                else:
                    print(inventory_line_format.format(item['Label'][:35],
                        item['Description']))
                    if details:
                        detail_list = ['Manufacturer', 'Model', 'SKU',
                            'PartNumber', 'SerialNumber', 'AssetTag']
                        for detail in detail_list:
                            if item[detail] is not None:
                                print(inventory_line_format_detail.format(
                                    '', detail, item[detail]))
        print('')


def _parse_version(version):
    """Parses a VHDL version string or int, 2- or 4-digit style, to a full
    4-digit version identifier integer."""
    if version is None:
        return None
    version = int(version)
    if version < 70:
        version += 2000
    elif version < 100:
        version += 1900
    return version


@classmethod
def parse_message_hook(cls, fields):
    """ Hook to override how the message is converted into a protocol object

        Subclasses may override this method in order to customise the arguments to the constructor,
        for example converting a nested object into another ProtocolMessage object

        :param fields: dict Populated list of fields to pass to the ProtocolMessage constructor
        :return: None
        """
    pass


def kwargs_to_string(kwargs):
    """
    Given a set of kwargs, turns them into a string which can then be passed to a command.
    :param kwargs: kwargs from a function call.
    :return: outstr: A string, which is '' if no kwargs were given, and the kwargs in string format otherwise.
    """
    outstr = ''
    for arg in kwargs:
        outstr += ' {}={}'.format(arg, kwargs[arg])
    return outstr


@classmethod
def real_roots(cls, poly, radicals=True):
    """Get real roots of a polynomial."""
    return cls._get_roots('_real_roots', poly, radicals)


def _unsigned_zero(dtype):
    """
    Given a numpy dtype, finds its "zero" point, which is exactly in the
    middle of its range.
    """
    assert dtype.kind == 'u'
    return 1 << dtype.itemsize * 8 - 1


def BoolVectorProperty(name: str='', description: str='', default: list=(
    False, False, False), options: set={'ANIMATABLE'}, subtype: str='NONE',
    size: int=3, update=None, get=None, set=None):
    """Returns a new vector boolean property definition.

    :param name: Name used in the user interface.
    :type name: str
    :param description: Text used for the tooltip and api documentation.
    :type description: str
    :param default: sequence of booleans the length of size.
    :type default: list
    :param options: Enumerator in [‘HIDDEN’, ‘SKIP_SAVE’, ‘ANIMATABLE’, ‘LIBRARY_EDITABLE’, ‘PROPORTIONAL’,’TEXTEDIT_UPDATE’].
    :type options: set
    :param subtype: Enumerator in [‘COLOR’, ‘TRANSLATION’, ‘DIRECTION’, ‘VELOCITY’, ‘ACCELERATION’, ‘MATRIX’, ‘EULER’, ‘QUATERNION’, ‘AXISANGLE’, ‘XYZ’, ‘COLOR_GAMMA’, ‘LAYER’, ‘NONE’].
    :type subtype: str
    :param size: Vector dimensions in [1, 32].
    :type size: int
    :param update: Function to be called when this value is modified, This function must take 2 values (self, context) and return None. Warning there are no safety checks to avoid infinite recursion.
    :param get: Function to be called when this value is ‘read’, This function must take 1 value (self) and return the value of the property.
    :param set: Function to be called when this value is ‘written’, This function must take 2 values (self, value) and return None.
    """
    pass


def write_footer_of_settings(cmake_file, command_indent, config_expressions,
    has_property_value, **kwargs):
    """ Writes footer of settings block (default value and closes block) """
    default = kwargs['default']
    end_text = kwargs['end_text']
    indent = kwargs['indent']
    if has_property_value:
        if default:
            cmake_file.write('{}    $<$<NOT:$<OR:{}>>:{}>\n'.format(indent +
                command_indent, ','.join(config_expressions), default))
        end_text = end_text.replace('\n', '\n' + indent + command_indent)
        if end_text:
            cmake_file.write('{}{}\n'.format(indent + command_indent, end_text)
                )


@classmethod
def get_synset_language(cls, id: str) ->str:
    """Returns the verbose language name for a given synset.

        :param id: A string of the form [pos#offset] identifying the synset.
        :return: The language name as a string.
        """
    if id:
        _language_names = {'P': 'english', 'N': 'italian', 'W': 'italian',
            'Y': 'italian', 'H': 'hebrew', 'S': 'spanish', 'L': 'latin',
            'R': 'romanian'}
        if id[2].isdigit():
            return 'english'
        else:
            return _language_names[id[2]]


def add_chromsize_colors(sizes_dict, color):
    """Add matplotlib color to chromsizes dict."""
    for k in sizes_dict:
        sizes_dict[k] = sizes_dict[k], color
    return sizes_dict


@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 is_empty(coll):
    """Returns true if coll has no items.
    """
    return coll is None or len(coll) == 0


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


def pretty_string_ops(n):
    """
    Return a humanized string representation of a large number.
    """
    abbrevs = [(1000000000000, 'Tera Ops'), (1000000000, 'Giga Ops'), (
        1000000, 'Mega Ops'), (1000, 'kilo Ops')]
    for factor, suffix in abbrevs:
        if n >= factor:
            break
    return '%.1f %s' % (float(n) / factor, suffix)


def find_extra_surface_nodeids(nodeids, sorted_large_nodes):
    """ Finds nodeids present in the aligned matched region of the large DMRS,
        but which have no equivalents in the small DMRS.

        :param nodeids Nodeids from the large DMRS which have equivalents in the small one, sorted by span_pred_key of
        their nodes.
        :param sorted_large_nodes A list of nodes of the large DMRS sorted by span_pred_key.

        :return A list of additional nodeids sharing the span with nodeids but without equivalents in the small DMRS.
    """
    extra_nodeids = []
    max_cto = 0
    reached_start = False
    reached_end = False
    for i, node in enumerate(sorted_large_nodes):
        if node.nodeid == nodeids[0]:
            first_overlap_orderid = i
            min_cfrom = node.cfrom
            max_cto = node.cto
            while True and first_overlap_orderid > 0:
                prev_node = sorted_large_nodes[first_overlap_orderid - 1]
                prev_cfrom = prev_node.cfrom
                if prev_cfrom == min_cfrom:
                    first_overlap_orderid -= 1
                    extra_nodeids.append(prev_node.nodeid)
                    max_cto = max(max_cto, prev_node.cto)
                else:
                    break
            reached_start = True
        elif not reached_start:
            continue
        elif reached_end and node.cfrom >= max_cto:
            break
        else:
            max_cto = max(max_cto, node.cto)
            if node.nodeid not in nodeids and node.nodeid not in extra_nodeids:
                extra_nodeids.append(node.nodeid)
        if node.nodeid == nodeids[-1]:
            reached_end = True
    return extra_nodeids


def intersect(rectangle_a, rectangle_b):
    """Determine whether the two Rectangles intersect each other.

    Args:
        rectangle_a (Rectangle): the 1st rectangle
        rectangle_b (Rectangle): the 2nd rectangle

    Returns:
        bool: True if rectangle_a and rectangle_b intersect / overlap
              otherwise False.

    """
    if rectangle_a.nw.lon > rectangle_b.se.lon:
        return False
    if rectangle_a.se.lon < rectangle_b.nw.lon:
        return False
    if rectangle_a.nw.lat < rectangle_b.se.lat:
        return False
    if rectangle_a.se.lat > rectangle_b.nw.lat:
        return False
    return True


def content_deleted(sender, instance=None, **kwargs):
    """removes content from the ES index when deleted from DB
    """
    if getattr(instance, '_index', True):
        cls = instance.get_real_instance_class()
        index = cls.search_objects.mapping.index
        doc_type = cls.search_objects.mapping.doc_type
        cls.search_objects.client.delete(index, doc_type, instance.id,
            ignore=[404])


def left_str_strip(string, str_to_strip):
    """Strips whole string <str_to_strip> from <string> from the left side.
    Distinct from lstrip, since the latter strips all chars, in any order, from
    the string"""
    return string[len(str_to_strip):]


def get_content_type(request):
    """Return the MIME content type giving the request

    Return `None` if unknown.
    """
    if hasattr(request, 'content_type'):
        conttype = request.content_type
    else:
        header = request.META.get('CONTENT_TYPE', None)
        if not header:
            return None
        conttype = header.partition(';')[0]
    return conttype


def is_canonical(G):
    """Tests if the graph has been canonicalized.

    Parameters
    ----------
    G : NetworkX graph

    Returns
    -------
    bool
    Returns True, if the graph has been canonicalized.

    """
    if 'label_map' in G.graph and 'canonical_map' in G.graph:
        return True
    else:
        return False


@classmethod
def get_doc_type_plus_list(cls):
    """

        Returns List of Identified doctype that a plus effect on the entity
        """
    return []


def split_on_comma(tokens):
    """Split a list of tokens on commas, ie ``LiteralToken(',')``.

    Only "top-level" comma tokens are splitting points, not commas inside a
    function or blocks.

    """
    parts = []
    this_part = []
    for token in tokens:
        if token.type == 'literal' and token.value == ',':
            parts.append(this_part)
            this_part = []
        else:
            this_part.append(token)
    parts.append(this_part)
    return tuple(parts)


def render_df(df, empty_msg='No data'):
    """Render_dataframe in HTML"""
    if df.empty:
        return (
            f"

{empty_msg}

"
            )
    else:
        table = df.to_html(classes=['table', 'table-striped', 'table-hover',
            'table-scroll'], border=0, index=False, justify='justify-all',
            escape=False)
        return table


@classmethod
def init_from_dict(cls, dict_in):
    """ Create an instance of this class from the expected json dict returned from Clockify API
        Parameters
        ----------
        dict_in: Dict
            As returned from Clockify API

        Raises
        ------
        ObjectParseException
            If dict_in does not contain all required field for creating an object

        Returns
        -------
        instance of this class, initialized to the values in dict_in

        """
    return cls(obj_id=cls.get_item(dict_in=dict_in, key='id'), name=cls.
        get_item(dict_in=dict_in, key='name'))


def reset_queues(queues):
    """Resets original queue._put() method."""
    for queue in queues:
        with queue.mutex:
            queue._put = queue._pebble_old_method
        delattr(queue, '_pebble_old_method')
        delattr(queue, '_pebble_lock')


def decode_response(client_message, to_object=None):
    """ Decode response from client message"""
    parameters = dict(response=None)
    parameters['response'] = client_message.read_int()
    return parameters


def add_plot_columns(elements):
    """
    Add columns needed for the creating the plots

    Args:
        elements: pd.DataFrame
    """
    mask = elements['group_id'].notnull()
    elements.loc[mask, 'x'] = elements.loc[mask, 'group_id'].astype(int)
    elements.loc[:, ('y')] = elements.loc[:, ('period')].astype(int)
    elements.loc[mask, 'group_name'] = elements.loc[mask, 'group_id'].astype(
        int).astype(str)
    elements.loc[~mask, 'group_name'] = 'f block'
    for period in [6, 7]:
        mask = (elements['block'] == 'f') & (elements['period'] == period)
        elements.loc[mask, 'x'] = elements.loc[mask, 'atomic_number'
            ] - elements.loc[mask, 'atomic_number'].min() + 3
        elements.loc[mask, 'y'] = elements.loc[mask, 'period'] + 2.5
    elements.loc[:, ('y_symbol')] = elements['y'] - 0.05
    elements.loc[:, ('y_anumber')] = elements['y'] - 0.3
    elements.loc[:, ('y_name')] = elements['y'] + 0.18
    return elements


@staticmethod
def length_error(var1: list, var2: (list, int)) ->Exception:
    """
        Raise a ValueError exception
        :param var1: variable to check for length
        :param var2: variable or integer to compare with var1
        :return:
        """
    from optimus.helpers.debug import get_var_name
    if isinstance(var2, int):
        length_var2 = str(var2)
    else:
        length_var2 = str(len(var2))
    raise ValueError(
        "'{var2_name}' must be length '{var1_length}', received '{var2_length}'"
        .format(var2_name=get_var_name(var2), var1_length=str(len(var1)),
        var2_length=length_var2))


@classmethod
def _get_um_dm(cls, df):
    """ Up move and down move

        initialize up move and down move
        :param df: data
        """
    hd = df['high_delta']
    df['um'] = (hd + hd.abs()) / 2
    ld = -df['low_delta']
    df['dm'] = (ld + ld.abs()) / 2


def getANSIfgarray_for_ANSIcolor(ANSIcolor):
    """Return array of color codes to be used in composing an SGR escape
    sequence. Using array form lets us compose multiple color updates without
    putting out additional escapes"""
    return ['38', '5', str(ANSIcolor)]


def remap_lads(lad_name):
    """Some LADs of MSOA census data do not match
    the LAD geographies of the LAD population data
    """
    if lad_name == 'E06000048':
        lad_mapped = 'E06000057'
    elif lad_name == 'E08000020':
        lad_mapped = 'E08000037'
    elif lad_name == 'E07000097':
        lad_mapped = 'E07000242'
    elif lad_name == 'E07000100':
        lad_mapped = 'E07000240'
    elif lad_name == 'E07000101':
        lad_mapped = 'E07000243'
    elif lad_name == 'E07000104':
        lad_mapped = 'E07000241'
    else:
        lad_mapped = lad_name
    return lad_mapped


def safe_int(string_, default=1):
    """Convert a string into a integer.
    If the conversion fails, return the default value.
    """
    try:
        ret = int(float(string_))
    except ValueError:
        return default
    else:
        return ret


@classmethod
def xml_root_close(cls):
    """ Returns the closing tag of the XML root node.

        .. versionadded:: 0.0.3
        """
    return '</resource>'


def convert_deps_to_pip(deps, project=None, r=True, include_index=True):
    """"Converts a Pipfile-formatted dependency to a pip-formatted one."""
    from .vendor.requirementslib.models.requirements import Requirement
    dependencies = []
    for dep_name, dep in deps.items():
        indexes = project.sources if hasattr(project, 'sources') else []
        new_dep = Requirement.from_pipfile(dep_name, dep)
        if new_dep.index:
            include_index = True
        req = new_dep.as_line(sources=indexes if include_index else None
            ).strip()
        dependencies.append(req)
    if not r:
        return dependencies
    from .vendor.vistir.path import create_tracked_tempfile
    f = create_tracked_tempfile(suffix='-requirements.txt', delete=False)
    f.write('\n'.join(dependencies).encode('utf-8'))
    f.close()
    return f.name


def pod_mutation_hook(pod):
    """
    This setting allows altering ``Pod`` objects before they are passed to
    the Kubernetes client by the ``PodLauncher`` for scheduling.

    To define a pod mutation hook, add a ``airflow_local_settings`` module
    to your PYTHONPATH that defines this ``pod_mutation_hook`` function.
    It receives a ``Pod`` object and can alter it where needed.

    This could be used, for instance, to add sidecar or init containers
    to every worker pod launched by KubernetesExecutor or KubernetesPodOperator.
    """


def skip_successful_exit(*args):
    """ System exit in file shouldn't kill interpreter (i.e. in `timeit`)"""
    if len(args) == 1 and args[0] in (0, None):
        pass
    else:
        raise SystemExit(*args)


def _set_progress(params, name: str, index: int, value: float):
    """Adjust the Disease.progress parameter"""
    params.disease_params.progress[index] = value


@staticmethod
def _get_key_second_half(platform):
    """Get the key corresponding to the platform number.

        Returns:
             key_second_half(str): Representative submits tasks to several
                platforms.

        """
    setting_mappings = {'2': 'www2', '3': 'www3', '6': 'www6', '20': 'pic',
        '21': 'gpu'}
    return setting_mappings[platform]


def cmp(a, b):
    """Compare function that behaves like cmp in python2."""
    return (a > b) - (a < b)


def is_correct(level, user):
    """Checks if user input matches level sequence"""
    if len(level) != len(user):
        return False
    for i in range(len(level)):
        if level[i] != user[i]:
            return False
    return True


def STR_CASE_CMP(x, y):
    """
    Performs case-insensitive comparison of two strings. Returns
        1 if first string is “greater than” the second string.
        0 if the two strings are equal.
        -1 if the first string is “less than” the second string.

    https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/
    for more details
    :param x: The first string or expression of string
    :param y: The second string or expression of string
    :return: Aggregation operator
    """
    return {'$strcasecmp': [x, y]}


@classmethod
def _add_quotes(cls, val, **kwargs):
    """
        add quotes around the string
        """
    return '"{0}"'.format(val)


def _default_key_normalizer(key_class, request_context):
    """
    Create a pool key out of a request context dictionary.

    According to RFC 3986, both the scheme and host are case-insensitive.
    Therefore, this function normalizes both before constructing the pool
    key for an HTTPS request. If you wish to change this behaviour, provide
    alternate callables to ``key_fn_by_scheme``.

    :param key_class:
        The class to use when constructing the key. This should be a namedtuple
        with the ``scheme`` and ``host`` keys at a minimum.
    :type  key_class: namedtuple
    :param request_context:
        A dictionary-like object that contain the context for a request.
    :type  request_context: dict

    :return: A namedtuple that can be used as a connection pool key.
    :rtype:  PoolKey
    """
    context = request_context.copy()
    context['scheme'] = context['scheme'].lower()
    context['host'] = context['host'].lower()
    for key in ('headers', '_proxy_headers', '_socks_options'):
        if key in context and context[key] is not None:
            context[key] = frozenset(context[key].items())
    socket_opts = context.get('socket_options')
    if socket_opts is not None:
        context['socket_options'] = tuple(socket_opts)
    for key in list(context.keys()):
        context['key_' + key] = context.pop(key)
    for field in key_class._fields:
        if field not in context:
            context[field] = None
    return key_class(**context)


def mixing_beta(calc, val):
    """https://www.quantum-espresso.org/Doc/INPUT_PW.html#mixing_beta
    """
    assert isinstance(val, float)
    assert val > 0 and val < 1


@classmethod
def hget(cls, key, hash_key):
    """Get the value for a hash key in the hash table at the specified key.

        :param string key: The key to fetch.
        :param string hash_key: The hash key to fetch value for in the hash
            table.
        :returns string: The value corresponding to the hash key in the hash
            table. If either ``key`` or ``hash_key`` is not found, ``None`` is
            returned.
        :raises redis.ResponseError: If ``key`` holds something other than a
            hash table.
        """
    return cls._instance.hget(key, hash_key)


@staticmethod
def toggle_output(output_id, ramp):
    """Generate a command that toggles a single output-port.

        Toggle mode: (on->off, off->on).

        :param    int    output_id:    Output id 0..3
        :param    int    ramp:         Ramp value
        :return:    The PCK command (without address header) as text
        :rtype:    str
        """
    if output_id < 0 or output_id > 3:
        raise ValueError('Invalid output_id.')
    return 'A{:d}TA{:03d}'.format(output_id + 1, ramp)


def __processor_chain_reducer(doc, processor):
    """Calling ExtractorProcessor extract on doc returns a document with
    extracted value from the Extractor it wraps"""
    return processor.extract(doc)


@classmethod
def get_key(cls, name):
    """
        This method creates a Redis key in which instance with given name will be saved.

        :param name: name of object for which a key is to be made.
        :returns: key used in Redis for given name.
        """
    return name


@classmethod
def check_permission(cls, context):
    """
        Check if the request should be premitted.
        Raises an appropriate exception if the request is not permitted.
        """
    for permission in cls.get_permissions():
        if not permission.has_permission(context, cls):
            cls.permission_denied(context)


def project(histogram, *args):
    """
    Project to a single axis or several axes on a multidiminsional histogram.
    Provided a list of axis numbers, this will produce the histogram over those
    axes only. Flow bins are used if available.
    """
    return histogram._project(*args)


def add_link_headers(response, links):
    """Return *response* with the proper link headers set, based on the contents
    of *links*.

    :param response: :class:`flask.Response` response object for links to be
                     added
    :param dict links: Dictionary of links to be added
    :rtype :class:`flask.Response` :
    """
    link_string = '<{}>; rel=self'.format(links['self'])
    for link in links.values():
        link_string += ', <{}>; rel=related'.format(link)
    response.headers['Link'] = link_string
    return response


def insert_vcf_header(session, metadata, vcf_header):
    """Populate a table storing the original VCF header.
    """
    t = metadata.tables['vcf_header']
    session.execute(t.insert(), dict(vcf_header=vcf_header.rstrip('\r\n')))
    session.commit()


def make_citation_dict(t):
    """
    Return a dict with BibText key/values
    :param t:
    :return:
    """
    from datetime import datetime
    from appurl import Url
    try:
        if Url(t.url).proto == 'censusreporter':
            try:
                url = str(t.resolved_url.url)
            except AttributeError:
                url = t.url
            return {'type': 'dataset', 'name': t.name, 'origin':
                'United States Census Bureau', 'publisher':
                'CensusReporter.org', 'title':
                '2010 - 2015 American Community Survey, Table {}: {}'.
                format(t.name.split('_', 1).pop(0), t.description), 'year':
                2015, 'accessDate': '{}'.format(datetime.now().strftime(
                '%Y-%m-%d')), 'url': str(url)}
    except (AttributeError, KeyError) as e:
        pass
    return False


def RemoveZeros(x):
    """
    remove zeros from a list
    """
    return list(filter(lambda a: a != 0, x))


def columns_from_metadata(query):
    """Return `columns` block from query front matter,
    if present
    """
    columns = None
    if 'columns' in query.metadata.keys():
        columns = query.metadata.pop('columns')
    return columns


def normalizeCode(codestring):
    """
    Function to normalize the given code.

    @param codestring code to be normalized (string)
    @return normalized code (string)
    """
    codestring = codestring.replace('\r\n', '\n').replace('\r', '\n')
    if codestring and codestring[-1] != '\n':
        codestring = codestring + '\n'
    return codestring


@classmethod
def NewFromJsonDict(cls, data, **kwargs):
    """ Create a new instance based on a JSON dict. Any kwargs should be
        supplied by the inherited, calling class.

        Args:
            data: A JSON dict, as converted from the JSON in the twitter API.

        """
    json_data = data.copy()
    if kwargs:
        for key, val in kwargs.items():
            json_data[key] = val
    c = cls(**json_data)
    c._json = data
    return c


@classmethod
def topic(cls, **kwargs) ->str:
    """Get MQTT topic for this message type."""
    return 'rhasspy/hotword/hotwords'


def _is_private_port_speed_item(item):
    """Determine if the port speed item is private network only."""
    for attribute in item['attributes']:
        if attribute['attributeTypeKeyName'] == 'IS_PRIVATE_NETWORK_ONLY':
            return True
    return False


@staticmethod
def writable() ->bool:
    """Implement :meth:`StoredFile.writable`.
        """
    return False


def argsort(a, reverse=False):
    """return index list to get `a` in order, ie
    ``a[argsort(a)[i]] == sorted(a)[i]``, which leads to unexpected
    results with `np.nan` entries, because any comparison with `np.nan`
    is `False`.
    """
    return sorted(range(len(a)), key=a.__getitem__, reverse=reverse)