def getOutputCell(cell, wsOut):
    """
    Fetch an existing Cell object from wsOut corresponding to the coordinates of cell.

    Input:
    cell (xl.cell.cell.Cell): Cell whose coordinates are to be used to pinpoint target cell
    wsOut (xl.worksheet.worksheet.Worksheet): Worksheet from which corresponding cell is to be pulled

    Output:
    Cell objects from wsOut corresponding to coordinates of cell
    """
    return wsOut[cell.coordinate]


def tmy_monthly_total(datalist):
    """
    from a TMY dataset calculate monthly totals and other statistics

    from a TMY dataset of cumulative values (ghi, dni, dhi, but
    also e.g. rainfall) calculate the monthly and the year totals and
    the monthly and yearly averages

    input data:
    - list with 8760 cumulative values from a TMY dataset (the exact
    type does not need to be specified, as aggregation operations are
    the same), float

    output: tuple with
    - list of totals per calendar month [0..11]
    - list of the daily averages per calendar month [0..11]
    - total for the year
    - daily average for the year

    """
    month_total = 0
    month_sum = []
    month_avg = []
    month_len = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    month_idx = [0, 744, 1416, 2160, 2880, 3624, 4344, 5088, 5832, 6552,
        7296, 8016, 8760]
    for m in range(0, 12):
        month_total = 0
        hour_from = month_idx[m]
        hour_to = month_idx[m + 1]
        for h in range(hour_from, hour_to):
            month_total = month_total + datalist[h]
        month_sum.append(month_total)
        month_avg.append(round(month_total / month_len[m], 3))
    year_sum = sum(month_sum)
    return month_sum, month_avg, year_sum, round(year_sum / 365, 3)


def get_private_command_line(args):
    """ private means don't show password """
    SECRET_PARAMS = ['password', 'command']
    GLOBAL_PARAMS = ['host', 'port', 'login']
    global_options_list = []
    for p in GLOBAL_PARAMS:
        v = getattr(args, p)
        if v:
            global_options_list.append('--%s=%s' % (p, v))
    params = set(vars(args)) - set(SECRET_PARAMS + GLOBAL_PARAMS)
    options_list = []
    for p in params:
        v = getattr(args, p)
        if v:
            options_list.append('--%s=%s' % (p, v))
    params = {'global_options': ' '.join(global_options_list), 'command':
        args.command, 'options': ' '.join(options_list)}
    return 'vg_api %(global_options)s %(command)s %(options)s' % params


def TSKVsPartGetNumberOfSectors(tsk_vs_part):
    """Retrieves the number of sectors of a TSK volume system part object.

  Args:
    tsk_vs_part (pytsk3.TSK_VS_PART_INFO): TSK volume system part information.

  Returns:
    int: number of sectors or None.
  """
    return getattr(tsk_vs_part, 'len', None)


def wordify_open(p, word_chars):
    """Prepend the word start markers."""
    return '(?<![{0}]){1}'.format(word_chars, p)


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

        :param str val:
        :rtype: WriteMode
        """
    return cls('update', val)


def _expects_hastraits_instance(handler):
    """ Does a trait handler or type expect a HasTraits subclass instance?
    """
    from traits.api import HasTraits, BaseInstance, TraitInstance
    if isinstance(handler, TraitInstance):
        cls = handler.aClass
    elif isinstance(handler, BaseInstance):
        cls = handler.klass
    else:
        return False
    return issubclass(cls, HasTraits)


@classmethod
def _loss(cls, model_params, weights, X, y):
    """Calculate the loss between y and the predictions made with X using specified parameters and weights."""
    raise NotImplementedError


@classmethod
def detect(cls, mbtiles):
    """Returns the Metadata version detected from `mbtiles`."""
    return cls._detect(keys=list(cls(mbtiles=mbtiles).keys()))


def get_path(object):
    """ Return the path used to store the object's json dump. """
    try:
        return object._container.path
    except:
        pass


@staticmethod
def search_and_replace(file, to_search):
    """
        Search and replace atom_names for numbers
      """
    to_replace = range(1, len(to_search) + 1)
    with open(file, 'r+') as f:
        lines = f.readlines()
        for i, line in enumerate(lines):
            lines[i] = ' ' + line.strip('\n')
    with open(file, 'w') as f:
        f.write('\n'.join(lines))
    with open(file, 'r') as f:
        filedata = f.read()
    for item_to_search, item_to_replace in zip(to_search, to_replace):
        filedata = filedata.replace(' ' + item_to_search.strip('_') + ' ',
            ' ' + str(item_to_replace) + ' ')
    f = open(file, 'w')
    f.write(filedata)
    f.close()


def load_image(imagepath, dirname: str='', place_holder: bool=False,
    recursive: bool=False, ncase_cmp: bool=True, convert_callback=None,
    verbose=False, relpath: str=None, check_existing: bool=False,
    force_reload: bool=False) ->'bpy.types.Image':
    """Return an image from the file path with options to search multiple paths and return a placeholder if its not found.

    :param filepath: The image filename If a path precedes it, this will be searched as well.
    :type filepath: str
    :param dirname: is the directory where the image may be located - any file at the end will be ignored.
    :type dirname: str
    :param place_holder: if True a new place holder image will be created. this is useful so later you can relink the image to its original data.
    :type place_holder: bool
    :param recursive: If True, directories will be recursively searched. Be careful with this if you have files in your root directory because it may take a long time.
    :type recursive: bool
    :param ncase_cmp: on non windows systems, find the correct case for the file.
    :type ncase_cmp: bool
    :param convert_callback: a function that takes an existing path and returns a new one. Use this when loading image formats blender may not support, the CONVERT_CALLBACK can take the path for a GIF (for example), convert it to a PNG and return the PNG’s path. For formats blender can read, simply return the path that is given.
    :param relpath: If not None, make the file relative to this path.
    :type relpath: str
    :param check_existing: If true, returns already loaded image datablock if possible (based on file path).
    :type check_existing: bool
    :param force_reload: If true, force reloading of image (only useful when check_existing is also enabled).
    :type force_reload: bool
    :return:  an image or None
    """
    pass


def check_domain_running(conn, guestname, logger):
    """ check if the domain exists, may or may not be active """
    guest_names = []
    ids = conn.listDomainsID()
    for id in ids:
        obj = conn.lookupByID(id)
        guest_names.append(obj.name())
    if guestname not in guest_names:
        logger.error("%s doesn't exist or not running" % guestname)
        return 1
    else:
        return 0


def weakchecksum(data):
    """
    Generates a weak checksum from an iterable set of bytes.
    """
    a = b = 0
    l = len(data)
    for i in range(l):
        a += data[i]
        b += (l - i) * data[i]
    return b << 16 | a, a, b


def set_api_key(api_key='free'):
    """
    Set the API key.

    :param api_key: String with the API key.
    :return: `None`
    """
    global _api_key
    _api_key = api_key


def compare_pct(a, b, rel_tol):
    """Calculate max difference as percentage of larger number"""
    max_val = sorted((abs(a), abs(b))).pop()
    return max_val * rel_tol


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

        :param ShowcaseChangeExternalSharingPolicyDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_change_external_sharing_policy_details', val)


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


def copy_dimension(source_dataset, target_dataset, name, overwrite=True,
    allow_unlimited=False):
    """
    Copies a dimension to a netCDF file, deleting it if it already exists (unless overwrite is false, in which case
    this raises an exception).
    Copies the size if the dimension is not unlimited.

    :param source_dataset: the source netCDF dataset
    :param target_dataset: the target netCDF to copy into.  Must be in edit / write mode.
    :param name: the name of the dimension
    :param overwrite: if true, overwrite the dimension if found in target.  May cause bad side effects if other variables
    :param allow_unlimited: if true, allow unlimited dimensions to remain unlimited
    depend on that dimension in the target.

    :return new dimension
    """
    if name in target_dataset.dimensions:
        if overwrite:
            del target_dataset.dimensions[name]
        else:
            raise Exception(
                'Target dimension already exists, and overwrite is false')
    source_dimension = source_dataset.dimensions[name]
    if allow_unlimited and source_dimension.isunlimited():
        return target_dataset.createDimension(name, None)
    else:
        return target_dataset.createDimension(name, len(source_dimension))


@staticmethod
def parameters_dict(parameters):
    """
        Create and return a dict from a list of PS parameters.
        The dict is empty because PS does not have any control parameters.
        This is implemented to have a consistent API.
        """
    return {}


def get_rank(data, true, low_values=False):
    """Computes the rank of entity at index true[i]. If the rank is k then
    there are k-1 entities with better (higher or lower) value in data.

    Parameters
    ----------
    data: `torch.Tensor`, dtype: `torch.float`, shape: (n_facts, dimensions)
        Scores for each entity.
    true: `torch.Tensor`, dtype: `torch.int`, shape: (n_facts)
        true[i] is the index of the true entity for test i of the batch.
    low_values: bool, optional (default=False)
        if True, best rank is the lowest score else it is the highest.

    Returns
    -------
    ranks: `torch.Tensor`, dtype: `torch.int`, shape: (n_facts)
        ranks[i] - 1 is the number of entities which have better scores in data
        than the one and index true[i]
    """
    true_data = data.gather(1, true.long().view(-1, 1))
    if low_values:
        return (data < true_data).sum(dim=1) + 1
    else:
        return (data > true_data).sum(dim=1) + 1


def split_trials(trial_ids, n_splits=5, rng_seed=0):
    """
    Assign each trial to testing or training fold

    :param trial_ids:
    :type trial_ids: array-like
    :param n_splits: one split used for testing; remaining splits used for training
    :type n_splits: int
    :param rng_seed: set random state for shuffling trials
    :type rng_seed: int
    :return: list of dicts of indices with keys `train` and `test`
    """
    from sklearn.model_selection import KFold
    shuffle = True if rng_seed is not None else False
    kf = KFold(n_splits=n_splits, random_state=rng_seed, shuffle=shuffle)
    kf.get_n_splits(trial_ids)
    idxs = [None for _ in range(n_splits)]
    for i, t0 in enumerate(kf.split(trial_ids)):
        idxs[i] = {'train': t0[0], 'test': t0[1]}
    return idxs


def get_quote(code, data, name):
    """Return special char for quote."""
    if code in data:
        return name, data[code], data[code]
    return name, data['ALL'], data['ALL']


def clearList(listWidget):
    """Clear a QListWidget, since the clear function is unstable."""
    while listWidget.count() > 0:
        listWidget.takeItem(0)


def extract_function(lines):
    """Extract function code starting at first line of lines."""
    n = len(lines)
    begin = 0
    body_begin = begin
    body_end = n
    for i in range(begin, n):
        if '{' in lines[i]:
            body_begin = i
            break
    braces = 0
    for i in range(body_begin, n):
        if '{' in lines[i]:
            braces += 1
        if '}' in lines[i]:
            braces -= 1
        if braces == 0:
            body_end = i
            break
    end = body_end + 1
    sublines = lines[begin:end]
    return ''.join(sublines)


def make_an_event(new_state):
    """Turns a new/target state into an event name."""
    return ('on_%s' % new_state).lower()


def bc(temp):
    """
    Calculate Bolometric Correction Using the Teff from the previous equation.
    This correction is for main sequence stars of the Teff range given above.
    """
    return (-10.07203 + temp * 0.00434733 - temp ** 2 * 6.159563e-07 + temp **
        3 * 2.851201e-11)


def formula_2008_01_01(foyer_fiscal, period, parameters):
    """
        Investissements OUTRE-MER dans le secteur du logement et autres secteurs d’activité
        2008
        """
    f7ui = foyer_fiscal('f7ui_2008', period)
    return f7ui


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


@staticmethod
def _get_other(other):
    """ Returns the value in `other` that the dunder methods need to compare.
		"""
    if hasattr(other, 'multiplier'):
        return other.multiplier
    else:
        return other


def swap_bytes(bits, bytesize=8):
    """
    Bits is a b'' object containing a binary representation. Assuming each
    bytesize bits constitute a bytes, perform a endianness byte swap. Example:

        >>> swap_bytes(b'00011011', 2)
        b'11100100'
    """
    i = 0
    l = len(bits)
    output = [b''] * (l // bytesize + 1)
    j = len(output) - 1
    while i < l:
        output[j] = bits[i:i + bytesize]
        i += bytesize
        j -= 1
    return b''.join(output)


def first(iterable, default=None, key=None):
    """
    Return first element of `iterable` that evaluates true, else return None
    (or an optional default value).

    >>> first([0, False, None, [], (), 42])
    42

    >>> first([0, False, None, [], ()]) is None
    True

    >>> first([0, False, None, [], ()], default='ohai')
    'ohai'

    >>> import re
    >>> m = first(re.match(regex, 'abc') for regex in ['b.*', 'a(.*)'])
    >>> m.group(1)
    'bc'

    The optional `key` argument specifies a one-argument predicate function
    like that used for `filter()`.  The `key` argument, if supplied, must be
    in keyword form.  For example:

    >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
    4

    """
    if key is None:
        for el in iterable:
            if el:
                return el
    else:
        for el in iterable:
            if key(el):
                return el
    return default


def tan(data=None, out=None, name=None, **kwargs):
    """Computes the element-wise tangent of the input array.

    The input should be in radians (:math:`2\\pi` rad equals 360 degrees).

    .. math::
       tan([0, \\pi/4, \\pi/2]) = [0, 1, -inf]

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

       - tan(default) = default
       - tan(row_sparse) = row_sparse
       - tan(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L140

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

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

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


def _get_text_type_ann_map(ann_objs, restrict_types=None, ignore_types=None,
    nested_types=None):
    """
    Helper function for search. Given annotations, returns a
    dict-of-dicts, outer key annotation text, inner type, values
    annotation objects.
    """
    restrict_types = [] if restrict_types is None else restrict_types
    ignore_types = [] if ignore_types is None else ignore_types
    nested_types = [] if nested_types is None else nested_types
    text_type_ann_map = {}
    for ann_obj in ann_objs:
        for text in ann_obj.get_textbounds():
            if text.type in ignore_types:
                continue
            if restrict_types != [] and text.type not in restrict_types:
                continue
            if text.text not in text_type_ann_map:
                text_type_ann_map[text.text] = {}
            if text.type not in text_type_ann_map[text.text]:
                text_type_ann_map[text.text][text.type] = []
            text_type_ann_map[text.text][text.type].append((ann_obj, text))
    return text_type_ann_map


@staticmethod
def _get_checksum(checksum, expected='md5'):
    """Return the checksum if the type is the expected."""
    checksum = checksum.split(':')
    if checksum[0] != expected or len(checksum) != 2:
        raise AttributeError('Checksum format is not correct.')
    else:
        return checksum[1]


def normalize(s, title=None):
    """Normalize the case of a string, removing spurious spaces.

    :param s: a string
    :param title: if `True` always titleize the string, if `False`
                  never do that, if `None` (default) only when the
                  input string is all lower case or all upper case
    :rtype: unicode

    ::

      >>> assert normalize(None) is None
      >>> print(normalize('lele gaifax'))
      Lele Gaifax
      >>> print(normalize('LELE'))
      Lele
      >>> print(normalize('LeLe', title=False))
      LeLe
    """
    if s is None:
        return None
    else:
        n = ' '.join(s.strip().split())
        if title != False and (title == True or n == n.upper() or n == n.
            lower()):
            n = n.title()
        return n


def atse_unregisterSchema(schema_id):
    """ unregister schema """


@staticmethod
def _update_metadata_with_repos(metadata, repos):
    """Update action metadata with information about repositories

        :param metadata: dict contains action metadata
        :param repos:  list of Repo objects
        :return:
        """
    for repo in repos:
        metadata.setdefault('repos', []).append({'type': 'deb', 'name':
            repo.name, 'uri': repo.uri, 'suite': repo.suite, 'section':
            repo.section, 'priority': repo.priority, 'meta': repo.meta})


def coord_to_position(coordinate, curve_map):
    """ Gives a position on the curve which corresponds to given coordinate. Domain: [0, 1]
    :param coordinate: Coordinate within the space the curve is filling
    :type coordinate: (int, int)
    :param curve_map: Generated curve map
    :type curve_map: list of (int, int)
    :rtype: float
    :return:
    """
    i = 0
    max_len = len(curve_map) - 1
    while i <= max_len:
        if curve_map[i] == coordinate:
            break
        i += 1
    if i > max_len:
        raise Exception('Coordinate is not on the the curve!')
    return i / max_len


def find_current_git_ref():
    """
    Tries to find the current version of the project we are working on under git.
    If successful returns the hash of the latest commit.
    """
    import os
    import nalaf
    import re
    git_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(
        nalaf.__file__))), '.git')
    if os.path.exists(git_dir):
        if os.path.exists(os.path.join(git_dir, 'HEAD')):
            with open(os.path.join(git_dir, 'HEAD')) as file:
                ref = re.search('ref: ?(.*)', file.read())
                current_ref = os.path.join(git_dir, ref.group(1))
                if os.path.exists(current_ref):
                    with open(current_ref) as ref_file:
                        return ref_file.read()
    return None


def parsePortSpec(spec, separator='-'):
    """
    Parses a port specification in two forms into the same form.

    In the first form the specification is just an integer. In this case a
    tuple is returned containing the same integer twice.

    In the second form the specification is two numbers separated by a hyphen
    ('-' by default, specifiable with :param separator:). The two numbers are
    parsed as integers and returned in the same order as a tuple of two
    integers.

    Example:

    .. code-block: python

       parsePortSpec('12345') # -> (12345, 12345)
       parsePortSpec('12345-56789') # -> (12345, 56789)
    """
    x = list(map(lambda x: x.strip(), spec.split(separator)))
    return tuple(map(int, x * (3 - len(x))))


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

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

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


@staticmethod
def extendArgs(category, originParams, newCols):
    """
    This function will update the function argument according to the mode defined by the user. Indeed some properties can be received to validate the accuracy of the data.
    Those data should be added to the different transformation functions and the columns should be passed to the final object.
    This function will ensure that by activating the mode the columns will be automatically added to the aggregated data.

    :return: The update set of columns to be considered in the Javascript function
    """
    if category == 'age':
        originParams[1] = originParams[1] + newCols
        for c in newCols:
            originParams[2][c] = 'sum'
    return originParams


def write_layout(files_model, ex_mets, media, biomasses, outfile=
    'Consortium_layout.txt', maxCycles=1000, timeStep=0.1, spaceWidth=0.05,
    deathRate=0, numRunThreads=2, maxSpaceBiomass=10, biom_name=
    'total_biomass_log_template.txt', media_name='media_log_template.txt',
    flux_name='flux_log_template.txt'):
    """
    Writes the comets layout
    INPUTS -> files_model: list of strings containing model files,
              ex_mets: list of extracellular metabolites,
              media: dictionary of metabolite:concentration
              dictionary of files_model:initial biomass
              ... some of the COMETS parameters, that are described in http://www.bu.edu/segrelab/comets-parameters/
    OUPUTS -> creates a COMETS layout in "Consortium_layout.txt
    """
    with open(outfile, 'w') as f:
        lines4 = 'model_file\t' + '\t'.join(files_model)
        lines4 += '\n\tmodel_world\n\t\tgrid_size\t1\t1\n\t\tworld_media\n'
        f.write(lines4)
        for met in ex_mets:
            if met not in media:
                f.write('\t\t\t' + met + '\t' + '0.0\n')
            else:
                f.write('\t\t\t' + met + '\t' + str(media[met]) + '\n')
        f.write('\t\t//\n\t\tmedia\n\t\t//\n\t//\n\tinitial_pop\n')
        biomass_line = '\t\t0\t0'
        for file in files_model:
            biomass_line += '\t' + biomasses[file]
        f.write(biomass_line + '\n\t//\n')
        params = 'parameters\n    maxCycles = ' + str(maxCycles) + '\n'
        params += '    timeStep = ' + str(timeStep) + '\n'
        params += '    spaceWidth = ' + str(spaceWidth) + '\n'
        params += '    deathRate = ' + str(deathRate) + '\n'
        params += '    maxSpaceBiomass = ' + str(maxSpaceBiomass) + '\n'
        params += '    numRunThreads = ' + str(numRunThreads) + '\n'
        params += '    pixelScale = 100\n'
        params += '    allowCellOverlap = true\n'
        params += '    saveslideshow = false\n'
        params += '    writetotalbiomasslog = true\n'
        params += '    totalbiomasslogname = ' + biom_name + '\n'
        params += '    writemedialog = true\n'
        params += '    medialogname = ' + media_name + '\n'
        params += '    writefluxlog = true\n'
        params += '    fluxlogname = ' + flux_name + '\n'
        params += '    uselognametimestamp = false\n'
        params += '    exchangestyle = Monod Style\n'
        params += '    defaultKm = 0.01\n'
        params += '    defaultVmax = 20\n//\n'
        f.write(params)
    return


@staticmethod
def isValid(gid):
    """
        Prüfe, ob die übergebene Gruppen-ID sinnvoll erscheint
        """
    if not gid:
        return False
    return gid != 'None'


def get_generic_bases(annotation):
    """Get generic base types of a type or empty tuple if not possible.
    Example::
        class MyClass(List[int], Mapping[str, List[int]]):
            ...
        MyClass.__bases__ == (List, Mapping)
        get_generic_bases(MyClass) == (List[int], Mapping[str, List[int]])
    """
    return getattr(annotation, '__orig_bases__', ())


def contains_link(tweet):
    """Returns true if tweet contains link (URL or Media). Checks entities"""
    if 'entities' not in tweet:
        return False
    if 'urls' in tweet['entities']:
        if len(tweet['entities']['urls']) > 0:
            return True
    if 'media' in tweet['entities']:
        if len(tweet['entities']['media']) > 0:
            return True
    return False


def select(extend: bool=False, fill: bool=False, open: bool=True):
    """Activate/select file

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    :param fill: Fill, Select everything beginning with the last selection
    :type fill: bool
    :param open: Open, Open a directory when selecting it
    :type open: bool
    """
    pass


def identity():
    """ Return a parser that passes state unchanged. """
    return lambda state: state._replace()


def unpack(value):
    """
    Return a three tuple of data, code, and headers

    :param value:
    :return:
    """
    if not isinstance(value, tuple):
        return value, 200, {}
    try:
        data, code, headers = value
        return data, code, headers
    except ValueError:
        pass
    try:
        data, code = value
        return data, code, {}
    except ValueError:
        pass
    return value, 200, {}


def minus(before, element):
    """Returns before - element. (before defaults to 0 if not given)

        .. code-block:: xml

            before - element
            -element
        """
    return before - element


def text2wrap_normal(text, max_width, ljust=True, start_pct=0.66, sep='~',
    fill=True):
    """Returns a displayable string from an attribute"""
    length = len(text)
    if length <= max_width:
        if ljust:
            return text.ljust(max_width) if fill else text
        else:
            return text.ljust(max_width) if ljust else text.rjust(max_width)
    else:
        until = int(max_width * start_pct)
        return text[:until] + sep + text[-(max_width - until - 1):]


@classmethod
def find_matching(cls, path, patterns):
    """Yield all matching patterns for path."""
    for pattern in patterns:
        if pattern.match(path):
            yield pattern


def all_methods(obj):
    """
    Return a list of names of methods of `obj`
    """
    temp = []
    for name in dir(obj):
        func = getattr(obj, name)
        if callable(func):
            temp.append(name)
    return temp


@classmethod
def CreateAttributeContainer(cls, container_type):
    """Creates an instance of a specific attribute container type.

    Args:
      container_type (str): container type.

    Returns:
      AttributeContainer: an instance of attribute container.

    Raises:
      ValueError: if the container type is not supported.
    """
    container_class = cls._attribute_container_classes.get(container_type, None
        )
    if not container_class:
        raise ValueError('Unsupported container type: {0:s}'.format(
            container_type))
    return container_class()


def generateRequirementsTxt(packages):
    """
        generateRequirementsTxt - Generates a requirements.txt suitable for pip to ingest based on packages param.

            @param packages - Describes the required packages. Takes one of the following forms:

                String - Directly becomes contents of requirements.txt file to be ingested by pip
                List   - A list/tuple/set of package names (optionally including version requirements, e.x. MyPkg==1.2.3)
                Dict   - A dictionary of package names to versions. If no value is present, the latest will be fetched.

            @return <str> - generated requirements.txt file contents
    """
    if not packages:
        reqContents = ''
    elif isinstance(packages, (list, tuple, set)):
        reqContents = '\n'.join(packages)
    elif isinstance(packages, dict):
        reqContents = []
        for name, value in packages.items():
            if not name:
                raise ValueError('Missing name in packages dictionary.')
            if value:
                reqContents.append('%s==%s' % (str(name), str(value)))
            else:
                reqContents.append('%s' % (str(name),))
        reqContents = '\n'.join(reqContents)
    else:
        reqContents = packages
    return reqContents


def get_bool_from_text_value(value):
    """ to be deprecated
    It has issues, as accepting into the registry whatever=value, as False, without
    complaining
    """
    return value == '1' or value.lower() == 'yes' or value.lower(
        ) == 'y' or value.lower() == 'true' if value else True


def __call__():
    """Return the database to use."""


def delete_subgraph(tx, subgraph):
    """ Delete data in a remote :class:`.Graph` based on a local
    :class:`.Subgraph`.

    :param tx:
    :param subgraph:
    :return:
    """
    graph = tx.graph
    node_identities = []
    for relationship in subgraph.relationships:
        if relationship.graph is graph:
            graph.relationship_cache.update(relationship.identity, None)
            relationship.graph = None
            relationship.identity = None
    for node in subgraph.nodes:
        if node.graph is graph:
            graph.node_cache.update(node.identity, None)
            node_identities.append(node.identity)
            node.graph = None
            node.identity = None
    list(tx.run('MATCH (_) WHERE id(_) IN $x DETACH DELETE _', x=
        node_identities))


def _evolve_chain(niterations_chain):
    """Evolves a chain for some number of iterations.

    This is used by ``Sampler.run`` to evolve a collection of chains in a
    parallel environment. This is not a staticmethod of ``Sampler`` because
    such functions need to be picklable when using python's multiprocessing
    pool.

    Parameters
    ----------
    niterations_chain : tuple of int, chain
        The number of iterations to run on the given chain.
    """
    niterations, chain = niterations_chain
    for _ in range(niterations):
        chain.step()
    return chain


def convert_listlike_cols_to_str(df, list_cols, convert_nan=False,
    nanreplacement='[]'):
    """ Convert listlike values in pandas DataFrame to stringlists.

    Writing a DataFrame to excel and csv raises errors due to presence of listlike or arraylike data.
    Here, all listlike and arraylike data is converted to a "stringlist"

    Parameters
    ----------
    df : pandas DataFrame
        Pandas DataFrame where some values are listlike or arraylike
    list_cols : list
        List of columns that contain listlike/arraylike should be converted to stringlists
    convert_nan : bool
        Whether np.nan values will be converted
    nanreplacement : string
        String to replace np.nan with. Default is a string representing an empty list. "[]"

    Returns
    ----------
    df : pandas DataFrame
        DataFrame with listlike and arraylike converted to stringlists

    Note:
    ----------
    # Convert individual stringlist back to a numpy array as follows
    np.array(ast.literal_eval(stringlist))
    # convert a column of stringlists back to arrays as follows
    df.loc[:,"x"] = df.loc[:,"x"].apply(lambda x : np.array(ast.literal_eval(x)))
    """
    for col in list_cols:
        if col in df:
            series = df[col].dropna()
            if series.empty == False:
                example_data1 = series[0]
                if 'ndarray' in str(type(example_data1)) or 'Series' in str(
                    type(example_data1)):
                    df[col] = series.apply(lambda x: list(x))
                example_data2 = df[col].dropna()[0]
                if 'list' in str(type(example_data2)):
                    df[col] = df[col].dropna().apply(lambda x: str(x))
                else:
                    raise TypeError(
                        'datatype for col {a}, ({b}) is not listlike'.
                        format(a=col, b=str(type(example_data2))))
                if convert_nan == True:
                    df[col] = df[col].fillna(nanreplacement)
            else:
                pass
        else:
            raise KeyError('The column {} is not in the dataframe'.format(col))
    return df


def code_to_line(code, cursor_pos):
    """Turn a multiline code block and cursor position into a single line
    and new cursor position.

    For adapting ``complete_`` and ``object_info_request``.
    """
    if not code:
        return '', 0
    for line in code.splitlines(True):
        n = len(line)
        if cursor_pos > n:
            cursor_pos -= n
        else:
            break
    return line, cursor_pos


def _refresh_instance(instance):
    """
    Invalidate cache for the instance and reload it.
    """
    type(instance).objects.invalidate(instance)
    return type(instance).objects.get(pk=instance.pk)


def loop_separate(loop: 'bmesh.types.BMLoop'):
    """Rip a vertex in a face away and add a new vertex.

    :param loop: The loop to separate.
    :type loop: 'bmesh.types.BMLoop'
    """
    pass


def encode_integer_leb128(value):
    """Encode an integer with signed LEB128 encoding.

    :param int value: The value to encode.

    :return: ``value`` encoded as a variable-length integer in LEB128 format.
    :rtype: bytes
    """
    if value == 0:
        return b'\x00'
    n_bits = value.bit_length() + 1
    if n_bits % 7:
        n_bits += 7 - n_bits % 7
    mask = (1 << n_bits) - 1
    value &= mask
    output = bytearray(n_bits // 7)
    for i in range(n_bits // 7):
        output[i] = 128 | value & 127
        value >>= 7
    output[-1] &= 127
    return bytes(output)


@staticmethod
def confirm_deletion(item):
    """Delete confirmation."""
    confirm = input("Вы уверены что хотите удалить '{}'? Y/N: ".format(item))
    if confirm.lower() == 'y':
        confirm = True
        print("\x1b[91m'{}' - удален. \x1b[0m".format(item))
    else:
        confirm = False
        print('\nВы отменили удаление.\n')
    input('\n[ENTER] - выйти.')
    return confirm


def push_projection():
    """Add to the projection matrix stack.

    """
    pass


def readrecf(filename):
    """reads .rec files output by EvTAF
    and returns rec_dict with (approximately)
    the same structure as the rec struct
    returned by readrec.m

    Parameters
    ----------
    filename : str
        Name of .rec file

    Returns
    -------
    rec_dict : dict
        with following key, value pairs
            header : str
                header from .rec file
            time_before : float
                time in seconds of additional audio added to file by EvTAF
                from before sound amplitude went above threshold for recording
            time_after : float
                time in seconds of additional audio added to file by EvTAF
                after sound amplitude dropped below threshold for recording
            iscatch : bool
                list of whether each occurrence of auditory feedback triggered
                was a 'catch trial' (where feedback would have been triggered but
                was withheld so behavior on that trial could be measured)
            num_channels : int
                number of channels from DAQ board recored by EvTAF
            sample_freq : int
                sampling frequency of audio file associated with this .rec file, in Hertz
            num_samples : int
                number of audio samples in file
            outfile : str
                name of audio file played as auditory feedback (if there was any)
            thresholds : int
                thresholds used by ring counter to determine whether to trigger auditory feedback
            feedback_info : dict
                maps feedback type to time it occurred in milliseconds

    Examples
    --------
    >>> recf = 'gy6or6_baseline_230312_0808.138.rec'
    >>> rec_dict = readrecf(recf)
    >>> num_samples = rec_dict['num_samples'}
    >>> sample_freq = rec_dict['sample_freq'}
    >>> print(f"file duration in seconds: {num_samples / sample_freq:.3f}")
    file duration in seconds: 12.305
    """
    rec_dict = {}
    with open(filename, 'r') as recfile:
        line_tmp = ''
        while 1:
            if line_tmp == '':
                line = recfile.readline()
            else:
                line = line_tmp
                line_tmp = ''
            if line == '':
                break
            elif line == '\n':
                continue
            elif 'Catch' in line:
                ind = line.find('=')
                rec_dict['iscatch'] = line[ind + 1:]
            elif 'Chans' in line:
                ind = line.find('=')
                rec_dict['num_channels'] = int(line[ind + 1:])
            elif 'ADFREQ' in line:
                ind = line.find('=')
                try:
                    rec_dict['sample_freq'] = int(line[ind + 1:])
                except ValueError:
                    sample_freq_float = float(line[ind + 1:])
                    try:
                        rec_dict['sample_freq'] = int(sample_freq_float)
                    except ValueError:
                        raise ValueError(
                            "Couldn't convert following value for ADFREQ in .rec file {} to an integer: {}"
                            .format(filename, sample_freq_float))
            elif 'Samples' in line:
                ind = line.find('=')
                rec_dict['num_samples'] = int(line[ind + 1:])
            elif 'T After' in line or 'T AFTER' in line:
                ind = line.find('=')
                rec_dict['time_after'] = float(line[ind + 1:])
            elif 'T Before' in line or 'T BEFORE' in line:
                ind = line.find('=')
                rec_dict['time_before'] = float(line[ind + 1:])
            elif 'Output Sound File' in line:
                ind = line.find('=')
                rec_dict['outfile'] = line[ind + 1:]
            elif 'Thresholds' in line or 'THRESHOLDS' in line:
                th_list = []
                while 1:
                    line = recfile.readline()
                    if line == '':
                        break
                    try:
                        th_list.append(float(line))
                    except ValueError:
                        line_tmp = line
                        break
                rec_dict['thresholds'] = th_list
                if line == '':
                    break
            elif 'Feedback information' in line:
                fb_dict = {}
                while 1:
                    line = recfile.readline()
                    if line == '':
                        break
                    elif line == '\n':
                        continue
                    ind = line.find('msec')
                    time = float(line[:ind - 1])
                    ind = line.find(':')
                    fb_type = line[ind + 2:]
                    fb_dict[time] = fb_type
                rec_dict['feedback_info'] = fb_dict
                if line == '':
                    break
            elif 'File created' in line:
                header = [line]
                for counter in range(4):
                    line = recfile.readline()
                    header.append(line)
                rec_dict['header'] = header
    return rec_dict


def blend_air_and_wave_velocity_cpp(wave_cpp, air_cpp, elevation_cpp,
    direction, eta_eps, air=None, psi_wave_cpp=None, psi_air_cpp=None,
    slope_cpp=None):
    """
    Return C++ code which blends the velocities in the water into the velocities
    in the air in such a way that the C++ code replicates the Python results
    from the blend_air_and_wave_velocities() function
    """
    if air is None:
        return 'x[2] < (%s) + %r ? (%s) : (%s)' % (elevation_cpp, eta_eps,
            wave_cpp, '0.0')
    cpp = (
        """[&]() {{
        const double elev = ({ecpp});

        const double val_water = ({uw_cpp});
        if (x[2] < elev + {eps!r}) {{
            // The point is below the free surface
            return val_water;
        }}

        const double d = {d!r};
        const double val_air = ({ua_cpp});
        if (x[2] < d) {{
            // The point is in the blending zone
            const double Z = (x[2] - elev) / (d - elev);

            // Cubic smoothstep
            //const double f = Z * Z * (3 - 2 * Z);
            //const double dfdZ = Z * (6 - 6 * Z);

            // Fift order smootherstep
            const double f = Z * Z * Z * (Z * (Z * 6 - 15) + 10);
            const double dfdZ = Z * Z * (30 + Z * (30 * Z - 60));

            // Derivatives needed in the product rules
            const double dZdx = (x[2] - d) / pow(d - elev, 2) * ({slope_cpp});
            const double dZdz = 1.0 / (d - elev);
            const double dfdx = dfdZ * dZdx;
            const double dfdz = dfdZ * dZdz;

            return (1 - f) * val_water + f * val_air + %r * (%s);
        }}

        // The point is above the blending zone
        return val_air;
    }}()"""
        .format(ecpp=elevation_cpp, uw_cpp=wave_cpp, ua_cpp=air_cpp, eps=
        eta_eps, d=air.blending_height + air.depth_water, slope_cpp=slope_cpp))
    if direction == 'x':
        sign = -1
        prcode = 'dfdz * (%s) - dfdz * (%s)' % (psi_wave_cpp, psi_air_cpp)
    elif direction == 'z':
        sign = +1
        prcode = 'dfdx * (%s) - dfdx * (%s)' % (psi_wave_cpp, psi_air_cpp)
    return cpp % (sign, prcode)


def saturation_distance(mean_mu_squared, wavenumber, scale):
    """Saturation distance according to Wenzel.

    :param mean_mu_squared: Mean mu squared.
    :param wavenumber: Wavenumber.
    :param scale: Outer length scale.

    See Daigle, 1987: equation 5

    .. math:: r_s = \\frac{1}{2 \\langle \\mu^2 \\rangle k^2 L}

    """
    return 1.0 / (2.0 * mean_mu_squared * wavenumber * wavenumber * scale)


def _mlsd2(ftp, path='.'):
    """
    Fall back to using `dir` instead of `mlsd` if not supported.

    This parses a Linux style `ls -l` response to `dir`, but the response may
    be platform dependent.

    Parameters
    ----------
    ftp: ftplib.FTP
    path: str
        Expects to be given path, but defaults to ".".
    """
    lines = []
    minfo = []
    ftp.dir(path, lines.append)
    for line in lines:
        line = line.split()
        this = line[-1], {'modify': ' '.join(line[5:8]), 'unix.owner': line
            [2], 'unix.group': line[3], 'unix.mode': line[0], 'size': line[4]}
        if 'd' == this[1]['unix.mode'][0]:
            this[1]['type'] = 'dir'
        else:
            this[1]['type'] = 'file'
        minfo.append(this)
    return minfo


@classmethod
def from_msm(cls, msm, n_macrostates):
    """Create and fit lumped model from pre-existing MSM.

        Parameters
        ----------
        msm : MarkovStateModel
            The input microstate msm to use.
        n_macrostates : int
            The number of macrostates

        Returns
        -------
        lumper : cls
            The fit PCCA(+) object.
        """
    params = msm.get_params()
    lumper = cls(n_macrostates, **params)
    lumper.transmat_ = msm.transmat_
    lumper.populations_ = msm.populations_
    lumper.mapping_ = msm.mapping_
    lumper.countsmat_ = msm.countsmat_
    lumper.n_states_ = msm.n_states_
    lumper._do_lumping()
    return lumper


def setTTL(ttl):
    """
        Set time to live on multicast packets.
        """


@classmethod
def to_yaml(cls, representer, data):
    """
        Convert a Python object to a representation node.
        """
    return representer.represent_yaml_object(cls.yaml_tag, data, cls,
        flow_style=cls.yaml_flow_style)


@classmethod
def get_object(cls, api_token, image_id, mocked):
    """
            Class method that will return an Image object by ID.
        """
    image = cls(token=api_token, id=image_id, mocked=mocked)
    image.mock_data = 'images/single.json'
    image.load()
    return image


def check_between(v_min, v_max, **params):
    """Checks parameters are in a specified range

    Parameters
    ----------

    v_min : float, minimum allowed value (inclusive)

    v_max : float, maximum allowed value (inclusive)

    params : object
        Named arguments, parameters to be checked

    Raises
    ------
    ValueError : unacceptable choice of parameters
    """
    for p in params:
        if params[p] < v_min or params[p] > v_max:
            raise ValueError('Expected {} between {} and {}, got {}'.format
                (p, v_min, v_max, params[p]))


def _stringify(s):
    """Convert input to string, wrap with quotes if already a string"""
    return '"{}"'.format(s) if isinstance(s, str) else str(s)


def report_item_value(report_item, report_item_name):
    """
    Function returns value of given report item e.g. pluginName
    :param report_item: particular report item for scanned host
    :param report_item_name: exact report item name for scanned host
    :return: value of given report item
    """
    report_item_content_value = report_item.get(report_item_name)
    if report_item_content_value is None:
        report_item_content = report_item.find(report_item_name)
        if report_item_content is not None:
            report_item_content_value = report_item_content.text
    return report_item_content_value


def supportinternal(repo):
    """True if the internal phase can be used on a repository"""
    return b'internal-phase' in repo.requirements


def ns_join(ns, name):
    """Joins a namespace and property name into clark notation."""
    return '{%s:}%s' % (ns, name)


def _set_summary_fields(ctx):
    """Sets related experiment viewer urls.

    """
    ctx.ext.summary_fields += (ctx.doc.canonical_name, ctx.doc.name, ctx.
        doc.long_name)


@staticmethod
def _get_message_from_stream(stream):
    """
        make the request and return the body

        :param stream: the stream
        :type method: request
        :returns: the message
        :rtype: dictionary
        """
    message = ''
    for char in stream.iter_content():
        if char == '\n':
            yield message
            message = ''
        else:
            message += char


def rescale_layout(pos, scale=1):
    """Returns scaled position array to (-scale, scale) in all axes.

    The function acts on NumPy arrays which hold position information.
    Each position is one row of the array. The dimension of the space
    equals the number of columns. Each coordinate in one column.

    To rescale, the mean (center) is subtracted from each axis separately.
    Then all values are scaled so that the largest magnitude value
    from all axes equals `scale` (thus, the aspect ratio is preserved).
    The resulting NumPy Array is returned (order of rows unchanged).

    Parameters
    ----------
    pos : numpy array
        positions to be scaled. Each row is a position.

    scale : number (default: 1)
        The size of the resulting extent in all directions.

    Returns
    -------
    pos : numpy array
        scaled positions. Each row is a position.

    """
    lim = 0
    for i in range(pos.shape[1]):
        pos[:, (i)] -= pos[:, (i)].mean()
        lim = max(abs(pos[:, (i)]).max(), lim)
    if lim > 0:
        for i in range(pos.shape[1]):
            pos[:, (i)] *= scale / lim
    return pos


@staticmethod
def rgb_to_ansi(color):
    """
        Converts hex RGB to the 6x6x6 xterm color space

        Args:
            color (str): RGB color string in the format "#RRGGBB"

        Returns:
            str: ansi color string in the format "ansi_n", where n
                is between 16 and 230

        Reference:
            https://github.com/chadj2/bash-ui/blob/master/COLORS.md
        """
    if color[0] != '#' or len(color) != 7:
        return None
    try:
        r = round(int(color[1:3], 16) / 51.0)
        g = round(int(color[3:5], 16) / 51.0)
        b = round(int(color[5:7], 16) / 51.0)
        n = int(36 * r + 6 * g + b + 16)
        return 'ansi_{0:d}'.format(n)
    except ValueError:
        return None


@staticmethod
def search(mattermost, term, prefix_only=False):
    """Search custom Emojis on Mattermost.

        Parameters
        ----------
        mattermost : :obj:`mattermostdriver.Driver`
            an instance of `mattermostdriver`_
        term: str
            The term to match against the emoji name.
        prefix_only: bool
            Set to only search for names starting with the search term.

        Returns
        -------
        :obj:`list` of `dict`
            Returns a list of Emojis
        """
    return mattermost.emoji.search_custom_emoji(options={'term': term,
        'prefix_only': prefix_only})


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


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

    The ".dev0" means dirty.

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


@staticmethod
def process_catalog(cat):
    """Process comma separated q-string files into a list

        Parameters:
            cat (str): comma separated q-string files
        """
    cat = cat.replace("'", '')
    return cat.split(',')


def head(_b, _x):
    """Determine the number of leading b's in vector x.

    Parameters
    ----------
    b: int
        Integer for counting at head of vector.
    x: array
        Vector of integers.

    Returns
    -------
    head: int
        Number of leading b's in x.
    """
    _head = 0
    for i in _x:
        if i == _b:
            _head += 1
        else:
            break
    return _head


def solve(f, M0, e, h):
    """ Newton-Raphson solver for eccentricity anomaly
    from https://stackoverflow.com/questions/20659456/python-implementing-a-numerical-equation-solver-newton-raphson
    Inputs:
        f (function): function to solve (transcendental ecc. anomaly function)
        M0 (float): mean anomaly
        e (float): eccentricity
        h (float): termination criteria for solver
    Returns: nextE (float): converged solution for eccentric anomaly
        Written by Logan Pearce, 2019
    """
    import numpy as np
    if M0 / (1.0 - e) - np.sqrt(6.0 * (1 - e) / e) <= 0:
        E0 = M0 / (1.0 - e)
    else:
        E0 = (6.0 * M0 / e) ** (1.0 / 3.0)
    lastE = E0
    nextE = lastE + 10 * h
    number = 0
    while abs(lastE - nextE) > h and number < 1001:
        new = f(nextE, e, M0)
        lastE = nextE
        nextE = lastE - new / (1.0 - e * np.cos(lastE))
        number = number + 1
        if number >= 1000:
            nextE = float('NaN')
    return nextE


def _gen_type_octet(hn, ln):
    """Generates a type octet from a high nibble and low nibble."""
    return hn << 4 | ln


@staticmethod
def delivery_count(properties):
    """
        Returns the delivery count for a message from the rabbit queue. The
        value is auto-set by rabbitmq. Will raise KeyError if x-delivery-count
        is missing from message headers.

        :param properties: Message properties

        :returns: Delivery count value
        :rtype: int

        """
    delivery_count = 0
    delivery_count = properties.headers['x-delivery-count']
    return delivery_count + 1


def bic(y, y_pred, p):
    """
    Returns the BIC score of a model.

    Input:-
    y: the labelled data in shape of an array of size  = number of samples.
        type = vector/array/list
    y_pred: predicted values of y from a regression model in shape of an array
        type = vector/array/list
    p: number of variables used for prediction in the model.
        type = int

    Output:-
    score: It outputs the BIC score
        type = int

    Tests:-
    Raise Error if length(y) <= 1 or length(y_pred) <= 1.
    Raise Error if length(y) != length(y_pred).
    Raise TypeError if y and y_pred are not vector.
    Raise TypeError if elements of y or y_pred are not integers.
    Raise TypeError if p is not an int.
    Raise Error if p < 0.
    """
    import numpy as np
    import pandas as pd
    import collections
    if not isinstance(y, (collections.Sequence, np.ndarray, pd.core.series.
        Series)):
        raise TypeError('Argument 1 not like an array.')
    if not isinstance(y_pred, (collections.Sequence, np.ndarray, pd.core.
        series.Series)):
        raise TypeError('Argument 2 not like an array.')
    for i in y:
        if not isinstance(i, (int, float)):
            raise TypeError('All elements of argument 1 must be int or float.')
    for i in y_pred:
        if not isinstance(i, (int, float)):
            raise TypeError('All elements of argument 2 must be int or float.')
    if not isinstance(p, (int, float)):
        raise TypeError("'Number of variables' must be of type int or float.")
    if p <= 0:
        raise TypeError("'Number of variables' must be positive integer.")
    if isinstance(p, int) != True:
        raise TypeError('Expect positive integer')
    if len(y) <= 1 or len(y_pred) <= 1:
        raise TypeError('observed and predicted values must be greater than 1')
    if not len(y) == len(y_pred):
        raise TypeError(
            'Equal length of observed and predicted values expected.')
    else:
        n = len(y)
    residual = np.subtract(y_pred, y)
    SSE = np.sum(np.power(residual, 2))
    BIC = n * np.log(SSE / n) + p * np.log(n)
    return BIC


def get_full_class_name(class_):
    """
    Get full class name of class
    :param class_:  The class
    :type  class_:  class
    :return:        The full class name
    :rtype:         string
    """
    return class_.__module__ + '.' + class_.__name__


def p_type_list(p):
    """type : LBRACKET type RBRACKET"""
    p[0] = ['list', [p[2]]]


@classmethod
def base_url(klass, space_id, parent_resource_id, resource_url='entries',
    resource_id=None, environment_id=None):
    """
        Returns the URI for the snapshot.
        """
    return 'spaces/{0}{1}/{2}/{3}/snapshots/{4}'.format(space_id,
        '/environments/{0}'.format(environment_id) if environment_id is not
        None else '', resource_url, parent_resource_id, resource_id if
        resource_id is not None else '')


def _on_message_callback(client, userdata, message):
    """Internal callback"""
    userdata['callback'](client, userdata['userdata'], message)


def line_search_return(line):
    """get the source/facet in the return statement
        TODO: return multiple return values not just one
    """
    l = line.split()
    if 'return' in l:
        i = l.index('return')
        if len(l) > i + 1:
            return l[i + 1]
    else:
        return None


@classmethod
def finetune_grid_search_cv(cls, Xs, Y, *, n_splits, test_size, eval_fn=
    None, probs=False, return_all=False, **kwargs):
    """
        Performs cross validated grid search over config items defined using "GridSearchable" objects and returns either full results or
        the config object that relates to the best results. The default config contains grid searchable objects for the
        most important parameters to search over.

        It should be noted that the cv splits are not guaranteed unique, but each split is given to each set of hparams.

        :param Xs: Input text. Either [num_samples] or [sequence, num_samples] for single or multi input models respectively.
        :param Y: Targets, A list of targets, [num_samples] that correspond to each sample in Xs.
        :param n_splits: Number of CV splits to do.
        :param test_size: Int or float. If an int is given this number of samples is used to validate, if a float is
            given then that fraction of samples is used.
        :param eval_fn: An eval function that takes 2 batches of outputs and returns a float, with a max value being
            desired. An arithmetic mean must make sense for this metric.
        :param probs: If true, eval_fn is passed probability outputs from predict_proba, otherwise the output of predict is used.
        :param return_all: If True, all results are returned, if False, only the best config is returned.
        :param kwargs: Keyword arguments to pass to get_config()
        :return: default is to return the best config object. If return_all is true, it returns a list of tuples of the
            form [(config, eval_fn output), ... ]
        """
    results = []
    for _ in range(n_splits):
        res = cls.finetune_grid_search(Xs, Y, test_size=test_size, probs=
            probs, eval_fn=eval_fn, return_all=True, **kwargs)
        results.append(res)
    results = list(zip(*results))
    aggregated_results = []
    for configuration in results:
        config_common = None
        sum_res = 0
        n_res = 0
        for config, result in configuration:
            config_common = config_common or config
            assert config == config_common
            n_res += 1
            sum_res += result
        aggregated_results.append((config_common, sum_res / n_res))
    if return_all:
        return aggregated_results
    return max(aggregated_results, key=lambda x: x[1])[0]


@staticmethod
def get_frequencies(archive):
    """ Return channel frequencies in MHz, as a numpy array"""
    raise NotImplementedError


def __split_message(plaintext):
    """
        Input: plaintext - String

        Output: messages - List of lists of lists (List of 4x4 Matrices)

        Splits message into 128 bits (16 characters) chunks and each of these
        chunks is then transformed into matrix with decimal values. These matrices
        are stored into list, creating a list of matrices.
    """
    message_chunks = []
    message_chunk = ''
    for i in range(len(plaintext)):
        message_chunk += plaintext[i]
        if len(message_chunk) == 16:
            message_chunks.append(message_chunk)
            message_chunk = ''
        if i == len(plaintext) - 1 and len(message_chunk) < 16:
            message_chunk += (16 - len(message_chunk)) * '\x00'
            message_chunks.append(message_chunk)
            message_chunk = ''
    messages = []
    for chunk in message_chunks:
        matrix = [[], [], [], []]
        for i in range(4):
            for j in range(4):
                number = ord(chunk[4 * i + j])
                matrix[i].append(number)
        messages.append(matrix)
    return messages


def rebuild_c_api():
    """Rebuild the C/C++ API."""
    from yggdrasil.drivers import CModelDriver, CPPModelDriver
    if CModelDriver.CModelDriver.is_installed():
        CModelDriver.CModelDriver.compile_dependencies(overwrite=True)
        CPPModelDriver.CPPModelDriver.compile_dependencies(overwrite=True)
    else:
        raise Exception(
            'The libraries necessary for running models written in C/C++ could not be located.'
            )


def cond_str(doc, label, key):
    """String formatter for gear details"""
    if key in doc:
        return f'{label}: {doc[key]}\n'
    return ''


def item(data, feed=None, service=None):
    """
    Format an opml section for a feed subscription using data found in its
    Opml feed entry.

    @param data: Opml data
    @type data: dict
    @param feed: Unused for this format. Default dict.
    @type feed: dict
    @param service: Unused for this format. Default None.
    @type service: obj
    @return:
    @rtype: basestring
    @raise TypeError: data passed was not a dict
    """
    if not isinstance(data, dict):
        raise TypeError('requires type dict.')
    opmlitem = []
    opmlitem.append(
        '<outline title="%(title)s" text="%(text)s" type="%(type)s" xmlUrl="%(xmlUrl)s" htmlUrl="%(htmlUrl)s"'
         % {'htmlUrl': data.get('htmlUrl', ''), 'title': data.get('title',
        ''), 'type': data.get('type', ''), 'xmlUrl': data.get('xmlUrl', ''),
        'description': data.get('description', ''), 'text': data.get('text',
        data['title'])})
    if data.has_key('imgUrl'):
        opmlitem.append(' imgurl="%s"' % data['imgUrl'])
    if data.has_key('altUrl'):
        opmlitem.append(' alturl="%s"' % data['altUrl'])
    if data.has_key('subId'):
        opmlitem.append(' subId="%s"' % data['subId'])
    if data.has_key('status'):
        opmlitem.append(' status="%s"' % data['status'])
    opmlitem.append('/>\n')
    return ''.join(opmlitem)


def encode_7or8bit(msg):
    """Set the Content-Transfer-Encoding header to 7bit or 8bit."""
    orig = msg.get_payload()
    if orig is None:
        msg['Content-Transfer-Encoding'] = '7bit'
        return
    try:
        if isinstance(orig, str):
            orig.encode('ascii')
        else:
            orig.decode('ascii')
    except UnicodeError:
        charset = msg.get_charset()
        output_cset = charset and charset.output_charset
        if output_cset and output_cset.lower().startswith('iso-2022-'):
            msg['Content-Transfer-Encoding'] = '7bit'
        else:
            msg['Content-Transfer-Encoding'] = '8bit'
    else:
        msg['Content-Transfer-Encoding'] = '7bit'
    if not isinstance(orig, str):
        msg.set_payload(orig.decode('ascii', 'surrogateescape'))


def get_masters(ppgraph):
    """From a protein-peptide graph dictionary (keys proteins,
    values peptides), return master proteins aka those which
    have no proteins whose peptides are supersets of them.
    If shared master proteins are found, report only the first,
    we will sort the whole proteingroup later anyway. In that
    case, the master reported here may be temporary."""
    masters = {}
    for protein, peps in ppgraph.items():
        ismaster = True
        peps = set(peps)
        multimaster = set()
        for subprotein, subpeps in ppgraph.items():
            if protein == subprotein:
                continue
            if peps.issubset(subpeps):
                if peps.union(subpeps) > peps:
                    ismaster = False
                    break
                elif peps.intersection(subpeps) == peps:
                    multimaster.update({protein, subprotein})
        if not ismaster:
            continue
        elif multimaster:
            premaster = sorted(list(multimaster))[0]
        else:
            premaster = protein
        for pep in peps:
            try:
                masters[pep].add(premaster)
            except KeyError:
                masters[pep] = {premaster}
    return masters


@classmethod
def add_attributes_to_map(cls, attr_iterator, stat_map):
    """Add attributes from the item to the stat map.

        Positional arguments:
        attr_iterator -- an iterator for the item attributes.
        stat_map -- add stats to this map

        First, some terminology. Nokka's d2s parser gives 'attributes' for the items.
        These 'attributes' are a little different than the 'stats' in ItemStatCost.txt.
        When referring to the stat as it exists in the JSON from the d2s parser, I will
        use the term 'attribute'. When referring to a stat consistent with ItemStatCost.txt,
        I will use the term 'stat'.

        attr_iterator must yield a map with an id and values field and can
        be created with the generator methods in the Item class. These maps are
        expected to follow the format of nokka's d2s parser. When converting from
        attribute to stat, we change a few things, notably with combined stat ranges
        (min-max dmg) and with charges.

        The stat_map will contain all item stats, keyed by stat id (ItemStatCost.txt).
        In the case of a simple stat (one value), the value for the stat id
        will be a list of all instance values of that stat. In the case of a complex
        stat, the value for the stat id will be another map, keyed by parameter.

        simple attribute:
        > stat_map[141] # deadly strike
        [20]

        complex attribute:
        > stat_map[204][62][30] # level 30 (30) hydra (62) charges (204 is the stat id)
        [2570]
        The game stores the current and max charges as one 16 bit value. In this case,
        there are 10 current charges (LSB) and 10 max (MSB): 2570 = 0x0A0A.
        """
    for attr in attr_iterator:
        for stat in cls.attribute_to_stats(attr):
            mdict = stat_map
            mkey = stat['stat']
            for value in attr['values'][:-1][::-1]:
                if mkey not in mdict:
                    mdict[mkey] = {}
                mdict = mdict[mkey]
                mkey = value
            if mkey not in mdict:
                mdict[mkey] = []
            mdict[mkey].append(attr['values'][-1])


def make_vs_title(x: str, y: str):
    """Creates the axes title for a plot with the given x-axis variable and
    y-axis variable

    :param x: the name for the x-variable
    :type x: str
    :param y: the name for the y-variable
    :type y: str
    :return: The correct axes title
    :rtype: str
    """
    return f'{y} vs {x}'


def handle_incoming_sms(payload):
    """ Handles an `incoming` action with `type` being `sms` """
    return


def process_tokendef(cls, name, tokendefs=None):
    """Preprocess a dictionary of token definitions."""
    processed = cls._all_tokens[name] = {}
    tokendefs = tokendefs or cls.tokens[name]
    for state in list(tokendefs):
        cls._process_state(tokendefs, processed, state)
    return processed


def getSlice(size, endpoint_memo='', forwards=True):
    """Returns a slice of the results starting after endpoint_memo.

        Note that endpoint_memo should be a simple string and is untrusted.

        :param size: The maximum number of entries to return in the slice.
        :param endpoint_memo: An endpoint memo as returned by getEndpointMemos.
            If None or '', the edge of the results is used.
        :param forwards: If True, slice forwards from endpoint_memo. Otherwise
            slice backwards from endpoint_memo (e.g. ascending indices in the
            result will indicate earlier items in the results collection).
        :return: An object honouring the tuple protocol, just like 'results' in
            the IBatchNavigatorFactory constructor call. If forwards was not
            True, the order will be reversed vs the 'results' object, otherwise
            it is identical. The object should be fully materialized from any
            backing store and have no more than size elements in it.
        """


def shape_key_feather_reset():
    """Reset feather weights on all selected points animation values

    """
    pass


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

    """
    pass


@property
def _value_(cls):
    """Internal value (integer)."""
    return NotImplemented


def build_route(pattern, finishing, kwargs, name, route_builders):
    """ Try to find suitable route builder to create a route.
        Raises ``LookupError`` if none found.
    """
    if not finishing:
        assert not name
    for try_build_route in route_builders:
        route = try_build_route(pattern, finishing, kwargs, name)
        if route:
            return route
    else:
        raise LookupError('No matching route factory found')


def __wavelength_to_rgb(wavelength, gamma=0.8):
    """Not intended for use by users, See noah.org: http://www.noah.org/wiki/Wavelength_to_RGB_in_Python .

    Parameters
    ----------
    wavelength : `float` or `int`
        wavelength of light
    gamma : `float`, optional
        output gamma

    Returns
    -------
    `tuple`
        R, G, B values

    """
    wavelength = float(wavelength)
    if wavelength >= 380 and wavelength <= 440:
        attenuation = 0.3 + 0.7 * (wavelength - 380) / (440 - 380)
        R = (-(wavelength - 440) / (440 - 380) * attenuation) ** gamma
        G = 0.0
        B = (1.0 * attenuation) ** gamma
    elif wavelength >= 440 and wavelength <= 490:
        R = 0.0
        G = ((wavelength - 440) / (490 - 440)) ** gamma
        B = 1.0
    elif wavelength >= 490 and wavelength <= 510:
        R = 0.0
        G = 1.0
        B = (-(wavelength - 510) / (510 - 490)) ** gamma
    elif wavelength >= 510 and wavelength <= 580:
        R = ((wavelength - 510) / (580 - 510)) ** gamma
        G = 1.0
        B = 0.0
    elif wavelength >= 580 and wavelength <= 645:
        R = 1.0
        G = (-(wavelength - 645) / (645 - 580)) ** gamma
        B = 0.0
    elif wavelength >= 645 and wavelength <= 750:
        attenuation = 0.3 + 0.7 * (750 - wavelength) / (750 - 645)
        R = (1.0 * attenuation) ** gamma
        G = 0.0
        B = 0.0
    else:
        R = 0.0
        G = 0.0
        B = 0.0
    return R, G, B


def birchmurnaghan(V, E0, B0, BP, V0):
    """
    BirchMurnaghan equation from PRB 70, 224107
    Eq. (3) in the paper. Note that there's a typo in the paper and it uses
    inversed expression for eta.
    """
    eta = (V0 / V) ** (1 / 3)
    E = E0 + 9 * B0 * V0 / 16 * (eta ** 2 - 1) ** 2 * (6 + BP * (eta ** 2 -
        1) - 4 * eta ** 2)
    return E


def literally(obj):
    """Forces Numba to interpret *obj* as an Literal value.

    *obj* must be either a literal or an argument of the caller function, where
    the argument must be bound to a literal. The literal requirement
    propagates up the call stack.

    This function is intercepted by the compiler to alter the compilation
    behavior to wrap the corresponding function parameters as ``Literal``.
    It has **no effect** outside of nopython-mode (interpreter, and objectmode).

    The current implementation detects literal arguments in two ways:

    1. Scans for uses of ``literally`` via a compiler pass.
    2. ``literally`` is overloaded to raise ``numba.errors.ForceLiteralArg``
       to signal the dispatcher to treat the corresponding parameter
       differently. This mode is to support indirect use (via a function call).

    The execution semantic of this function is equivalent to an identity
    function.

    See :ghfile:`numba/tests/test_literal_dispatch.py` for examples.
    """
    return obj


@staticmethod
def generate_mail_endpoint(mail_address):
    """
            @type mail_address: string
            @param mail_address: the address of mail
        """
    return 'mail:directmail:%s' % mail_address


@classmethod
def isspace(cls, nextchar):
    """ Whether the next character is whitespace """
    return nextchar.isspace()


def full_update(dct, values):
    """Fully update a dictionary."""
    dct.clear()
    dct.update(values)


def is_natural(x):
    """A non-negative integer."""
    try:
        is_integer = int(x) == x
    except (TypeError, ValueError):
        return False
    return is_integer and x >= 0


def bytes_to_environ(s):
    """
    Encode a byte string to a WSGI environ value

    For Python 2, this simply returns ``s``.
    For Python 3 this returns a 'bytes-as-unicode' string.
    """
    return s.decode('latin1')


def _create_color_generator():
    """Create a generator which will cycle through a list of default matplotlib colors"""
    from itertools import cycle
    colors = [u'#1f77b4', u'#ff7f0e', u'#2ca02c', u'#d62728', u'#9467bd',
        u'#8c564b', u'#e377c2', u'#7f7f7f', u'#bcbd22', u'#17becf']
    return cycle(colors)


def inverse(coord_map):
    """
    Invert a coord map by de-scaling and un-shifting;
    this gives the backward mapping for the gradient.
    """
    ax, a, b = coord_map
    return ax, 1 / a, -b / a


def p_expr_stmt_star_4(p):
    """expr_stmt_star : expr_stmt_star EQUAL testlist"""
    p[0] = p[1] + [p[3]]


def weightedIntersection(c1, c2, weight1=1, weight2=1):
    """Compute the weighted intersection of c1 and c2.

        If c1 and c2 are None, the output is (0, None).

        If c1 is None and c2 is not None, the output is (weight2, c2).

        If c1 is not None and c2 is None, the output is (weight1, c1).

        Else, and hereafter, c1 is not None and c2 is not None.

        If c1 and c2 are both sets, the output is the sum of the weights
        and the (unweighted) intersection of the sets.

        Else the output is 1 and a Bucket whose keys are the intersection of
        c1 and c2's keys, and whose values are::

          v1*weight1 + v2*weight2

          where:

            v1 is 1        if c1 is a set
                  c1[key]  if c1 is a mapping

            v2 is 1        if c2 is a set
                  c2[key]  if c2 is a mapping

        Note that c1 and c2 must be collections.
        """


def lda_plus_u(calc, val):
    """https://www.quantum-espresso.org/Doc/INPUT_PW.html#lda_plus_u
    """
    assert isinstance(val, bool)


def action_star(data_out, char):
    """Add a char to time."""
    data_out['time'] = char


def add_to_cache(obj, name, val):
    """Add a result to the cache of an object."""
    if not hasattr(obj, '_memoize_cache'):
        obj._memoize_cache = dict()
    obj._memoize_cache[name] = val
    return obj


@classmethod
def reguard(cls):
    """
        Enable the mass assignment restrictions.
        :return:
        """
    cls.__unguarded__ = False


@classmethod
def read_chunk(cls, opc_sync: bool, context: str) ->'IoTransferEventArgs':
    """Creates new IoTransferEventArgs of read string

		:param opc_sync: defines if the command is OPC-synchronised
		:param context: SCPI query. It is truncated to maximum of 100 characters.
		:return: IoTransferEventArgs object of a read string operation."""
    return cls(True, opc_sync, None, context)


def convert(bytes_):
    """
    takes a number of bytes as an argument and returns the most suitable human
    readable unit conversion.
    """
    if bytes_ > 1024 ** 3:
        hr = round(bytes_ / 1024 ** 3)
        unit = 'GB'
    elif bytes_ > 1024 ** 2:
        hr = round(bytes_ / 1024 ** 2)
        unit = 'MB'
    else:
        hr = round(bytes_ / 1024)
        unit = 'KB'
    hr = str(hr)
    result = hr + ' ' + unit
    return result


def transit_duration_range(period, min_radius_hint, max_radius_hint):
    """This figures out the minimum and max transit duration (q) given a period
    and min/max stellar radius hints.

    One can get stellar radii from various places:

    - GAIA distances and luminosities
    - the TESS input catalog
    - isochrone fits

    The equation used is::

        q ~ 0.076 x R**(2/3) x P**(-2/3)

        P = period in days
        R = stellar radius in solar radii

    Parameters
    ----------

    period : float
        The orbital period of the transiting planet.

    min_radius_hint,max_radius_hint : float
        The minimum and maximum radii of the star the planet is orbiting around.

    Returns
    -------

    (min_transit_duration, max_transit_duration) : tuple
        The returned tuple contains the minimum and maximum transit durations
        allowed for the orbital geometry of this planetary system. These can be
        used with the BLS period-search functions in
        :py:mod:`astrobase.periodbase.kbls` or
        :py:mod:`astrobase.periodbase.abls` to refine the period-search to only
        physically possible transit durations.

    """
    return 0.076 * min_radius_hint ** (2.0 / 3.0) * period ** (-2.0 / 3.0
        ), 0.076 * max_radius_hint ** (2.0 / 3.0) * period ** (-2.0 / 3.0)


@staticmethod
def _parse_dbpath(dbpath):
    """Converts the dbpath to a regexp pattern.

        Transforms dbpath from a string or an array of strings to a
        regexp pattern which will be used to match database names.

        Args:
            dbpath: a string or an array containing the databases to be matched
                from a cluster.

        Returns:
            A regexp pattern that will match any of the desired databases on
            on a cluster.
        """
    if isinstance(dbpath, list):
        dbpath = '|'.join(dbpath)
    if not dbpath.endswith('$'):
        dbpath = '(%s)$' % dbpath
    return dbpath


def encodeX10UnitCode(unit_code, anX10Controller):
    """
    Given an X10 Unit Code (e.g. "6"), return the value for this
    specific controller
    """
    return anX10Controller.UNIT_ENCMAP[str(unit_code)]


def decode_to_utf8(text):
    """Paramiko returns bytes object and we need to ensure it is utf-8 before
    parsing
    """
    try:
        return text.decode('utf-8')
    except (AttributeError, UnicodeEncodeError):
        return text


def ip_permission_grants_access_to_group_with_id(ipp, security_group_id):
    """
    Returns True if an EC2 security group IP permission opens access to
    a security with the given ID and False otherwise.

    >>> ip_permission_grants_access_to_group_with_id(
    ... {'UserIdGroupPairs': [{'GroupId': 'test-sgid'}]}, 'test-sgid')
    True
    >>> ip_permission_grants_access_to_group_with_id(
    ... {'UserIdGroupPairs': [{'GroupId': 'test-sgid'}]}, 'not-test-sgid')
    False
    >>> ip_permission_grants_access_to_group_with_id({}, 'test-sgid')
    False
    """
    for user_id_group_pair in ipp.get('UserIdGroupPairs', []):
        if user_id_group_pair.get('GroupId', None) == security_group_id:
            return True
    return False


def filter_macrofy(value: str) ->str:
    """
    Filter to transform an input into a valid C preprocessor identifier token.

    .. invisible-code-block: python

        from nunavut.lang.c import filter_macrofy

    .. code-block:: python

        # Given
        template = '#ifndef {{ "my full name" | macrofy }}'

        # then
        rendered = '#ifndef MY_FULL_NAME'

    .. invisible-code-block: python

        jinja_filter_tester(filter_macrofy, template, rendered, 'c')

    :param str value: The value to transform.

    :returns: A valid C preprocessor identifier token.
    """
    return value.replace(' ', '_').replace('.', '_').upper()


@classmethod
def get_model_name_plural(cls):
    """
        Get the plural name of this Model.
        Returns (str):

        """
    return cls.Meta.verbose_name_plural or '{}s'.format(cls.get_model_name())


def multi_sgd_update(*data, **kwargs):
    """Update function for Stochastic Gradient Descent (SDG) optimizer.

    It updates the weights using::

     weight = weight - learning_rate * (gradient + wd * weight)

    Defined in src/operator/optimizer_op.cc:L329

    Parameters
    ----------
    data : Symbol[]
        Weights
    lrs : tuple of <float>, required
        Learning rates.
    wds : tuple of <float>, required
        Weight decay augments the objective function with a regularization term that penalizes large weights. The penalty scales with the square of the magnitude of each weight.
    rescale_grad : float, optional, default=1
        Rescale gradient to grad = rescale_grad*grad.
    clip_gradient : float, optional, default=-1
        Clip gradient to the range of [-clip_gradient, clip_gradient] If clip_gradient <= 0, gradient clipping is turned off. grad = max(min(grad, clip_gradient), -clip_gradient).
    num_weights : int, optional, default='1'
        Number of updated weights.

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

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


def _predict_output_scikit_MLPRegressor(model, input):
    """
    Predict output function for scikit-learn MLPRegressor objects.
    """
    output = model.predict(input)
    if output.ndim == 1:
        output = output.reshape(-1, 1)
    return output


def face_vert_separate(face: 'bmesh.types.BMFace', vert: 'bmesh.types.BMVert'):
    """Rip a vertex in a face away and add a new vertex.

    :param face: The face to separate.
    :type face: 'bmesh.types.BMFace'
    :param vert: A vertex in the face to separate.
    :type vert: 'bmesh.types.BMVert'
    """
    pass


def rst_to_plain_text(text):
    """Minimal converter of reStructuredText to plain text.

    Will work at least for command descriptions.

    :param text: Text to be converted.
    :rtype: str
    """
    import re
    lines = text.splitlines()
    result = []
    for line in lines:
        if line.startswith(':'):
            line = line[1:]
        elif line.endswith('::'):
            line = line[:-1]
        line = re.sub(':doc:`(.+)-help`', '``help \\1``', line)
        result.append(line)
    return '\n'.join(result) + '\n'


def start(callback, *args, **kwargs):
    """
        Have the event loop begin watching for this event.

        When the event is detected, *callback* will be called with
        *args*.

        .. caution::

            Not all watchers accept ``**kwargs``,
            and some watchers define special meanings for certain keyword args.
        """


def bC_K_B4O5OH4_FW86(T, P):
    """c-a: potassium tetraborate [FW86]."""
    b0 = -0.022
    b1 = 0
    b2 = 0
    C0 = 0
    C1 = 0
    alph1 = 2
    alph2 = -9
    omega = -9
    valid = T == 298.15
    return b0, b1, b2, C0, C1, alph1, alph2, omega, valid


def nicenumber(number, binsize, lower=False):
    """Returns the next higher or lower "nice number", given by binsize.

    Examples:
    ---------
    >>> nicenumber(12, 10)
    20
    >>> nicenumber(19, 50)
    50
    >>> nicenumber(51, 50)
    100
    >>> nicenumber(51, 50, lower=True)
    50
    """
    e, _ = divmod(number, binsize)
    if lower:
        return e * binsize
    else:
        return (e + 1) * binsize


@classmethod
def get_num_fig_managers(cls):
    """
        Return the number of figures being managed.
        """
    return len(cls.figs)


@staticmethod
def deep_copy_set(sol_set):
    """
        Deep copy a solution set.

        :param sol_set: a solution set
        :return: the copied solution set
        """
    result_set = []
    for sol in sol_set:
        result_set.append(sol.deep_copy())
    return result_set


def get_complete_version(version=None):
    """
    Returns a tuple of the django_cryptography version. If version
    argument is non-empty, then checks for correctness of the tuple
    provided.
    """
    if version is None:
        from django_cryptography import VERSION as version
    else:
        assert len(version) == 5
        assert version[3] in ('alpha', 'beta', 'rc', 'final')
    return version


def getIndex(context=None):
    """Return the index for this subscription.  Some subscriptions
        may accept a context argument for looking up the index."""


def _split(string, max_split, remove_empty_matches, matching_function, *
    args, **kwargs):
    """
    Splits a string using a given matching-function that matches the separator.

    This function implements general features needed from the split functions
    in this module (the max-split and remove-empty-matches features).

    :param string:               The string where to split.
    :param max_split:            Defines the maximum number of splits. If 0 or
                                 less is provided, the number of splits is not
                                 limited.
    :param remove_empty_matches: Defines whether empty entries should
                                 be removed from the result.
    :param matching_function:    The matching function. It must return
                                 MatchObject's containing the matched
                                 split-separator.
    :param args:                 Positional arguments to invoke the
                                 matching_function with.
    :param kwargs:               Key-value arguments to invoke the
                                 matching_function with.
    """
    last_end_pos = 0
    for match in matching_function(*args, **kwargs):
        split_string = string[last_end_pos:match.start()]
        last_end_pos = match.end()
        if not remove_empty_matches or len(split_string) != 0:
            yield split_string
            max_split -= 1
            if max_split == 0:
                break
    if not remove_empty_matches or len(string) > last_end_pos:
        yield string[last_end_pos:]


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


def crop_image(data, header, scale):
    """
    Crop the image in the given HDUList around the centre point. If the
    original size is (W, H), the cropped size will be (scale * W, scale * H).
    """
    if scale < 0 or scale > 1:
        raise ValueError('scale must be in [0, 1]')
    h, w = data.shape
    half_h = int(h * 0.5 * scale)
    half_w = int(w * 0.5 * scale)
    mid_y = int(h / 2)
    mid_x = int(w / 2)
    data = data[mid_y - half_h:mid_y + half_h, mid_x - half_w:mid_x + half_w]
    new_h, new_w = data.shape
    header['NAXIS1'] = new_w
    header['NAXIS2'] = new_h
    return data, header


def zpad(x, l):
    " Left zero pad value `x` at least to length `l`.\n\n    >>> zpad('', 1)\n    '\x00'\n    >>> zpad('Êþ', 4)\n    '\x00\x00Êþ'\n    >>> zpad('ÿ', 1)\n    'ÿ'\n    >>> zpad('Êþ', 2)\n    'Êþ'\n    "
    return b'\x00' * max(0, l - len(x)) + x


def populate_sectors(sectors, hexfile):
    """
    Checks for which on-device sectors there is data in the hex file and
    returns a (sector, data) tuple for each touched sector where data
    is a byte array of the same size as the sector.
    """
    for sector in sectors:
        addr = sector['addr']
        size = sector['len']
        touched = False
        for start, end in hexfile.segments():
            if start < addr and end > addr:
                touched = True
                break
            elif start >= addr and start < addr + size:
                touched = True
                break
        if touched:
            yield sector, hexfile.tobinarray(addr, addr + size - 1)


def str_prepend(s, char, n):
    """
        from xdict.utils import *
        str_prepend('a','s',3)
    """
    prepend = ''
    for i in range(1, n + 1):
        prepend = ''.join((prepend, char))
    return ''.join((prepend, s))


def delpoi():
    """
    @api {post} /map/collect/delpoi 删除收藏
    @apiVersion 1.0.0
    @apiGroup Collect
    @apiDescription 删除收藏

    @apiParam (Headers) {String} token 令牌
    @apiParam (Headers) {String} device_token 设备令牌
    @apiParam (Headers) {String} content_type 内容类型
    @apiParam (Headers) {String} timestamp 时间戳
    @apiParam (Headers) {String} location 经纬度

    @apiParam (Body) {String} poi_id poi_id

    @apiSuccess (Success) {String} data 成功标识

    @apiSuccessExample {json} Success-Response:
    {
        "data": "Success.",
        "req_id": "r_049b93db7754407bb872aaee3d28f352",
        "err_resp": {
            "code": "0",
            "msg": null
        }
    }

    @apiError (Error) 21020 No poi_id in the request params

    @apiErrorExample {json} Error-Response:
    {
        "err_resp": {
            "code": "21020",
            "msg": "No poi_id in the request params!"
        },
        "req_id": "r_da328a55dfbc46bda249122030b8677d"
    }
    """


def __add__(a, b):
    """ Return sum of *a* with *b*. """
    return a.clone().add(b)


def fmt_bytesize(num: float, suffix: str='B') ->str:
    """Change a number of bytes in a human readable format.

    Args:
      num: number to format
      suffix: (Default value = 'B')

    Returns:
      The value formatted in human readable format (e.g. KiB).
    """
    for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
        if abs(num) < 1024.0:
            return f'{num:3.1f} {unit}{suffix}'
        num /= 1024.0
    return f'{num:.1f} Yi{suffix}'


def compat(context, attr):
    """ Backwards compatible widget attribute access.

    In tw1, all template attributes looked like:
        ${some_attribute}

    Whereas in tw2 they look like:
        ${w.some_attribute}

    This is a *nuisance* if you want to reuse a template between tw1 and tw2
    widgets.  With this function you can write:
        <%namespace name="tw" module="tw2.core.mako_util"/>
        ${tw.compat(attr='some_attribute')}
    or
        ${tw._('some_attribute')}

    Nice, right? :)
    """
    if not 'w' in context.keys():
        return context.get(attr)
    else:
        return getattr(context.get('w'), attr)


def normalize_coordinates(cluster_info_dataframe):
    """
    All coordinate values will be arranged between -100 and 100.
    The maximum value of each coordinate will be assumed as 100, then all the
    values will me arrange following a proportional distortion.
    """
    max_values = cluster_info_dataframe.max()
    cluster_info_dataframe['x'] *= 100 / max_values['x']
    cluster_info_dataframe['y'] *= 100 / max_values['y']
    return cluster_info_dataframe


def is_empty_arraylike(arraylike):
    """Check if arraylike is None or empty.

    Arg:
        arraylike: None or np.ndarray or list or tuple

    Return:
        a boolean indicates if this array is empty
    """
    import numpy as np
    if arraylike is None:
        return True
    if isinstance(arraylike, np.ndarray) and arraylike.size == 0:
        return True
    if isinstance(arraylike, list) and len(arraylike) == 0:
        return True
    if isinstance(arraylike, tuple) and len(arraylike) == 0:
        return True
    return False


def _stub_tag(constructor, node):
    """Stub a constructor with a dictionary."""
    seen = getattr(constructor, '_stub_seen', None)
    if seen is None:
        seen = constructor._stub_seen = set()
    if node.tag not in seen:
        print('YAML tag {} is not supported'.format(node.tag))
        seen.add(node.tag)
    return {}


def Statistics(*args, **kwargs):
    """
  Computes and plots the CDPP statistics comparison between `model` and `compare_to`
  for all long cadence light curves in a given campaign

  """
    raise NotImplementedError('This mission is not yet supported.')


def randomize_transform(random_seed: int=0, use_delta: bool=False, use_loc:
    bool=True, loc: float=(0.0, 0.0, 0.0), use_rot: bool=True, rot: float=(
    0.0, 0.0, 0.0), use_scale: bool=True, scale_even: bool=False, scale:
    float=(1.0, 1.0, 1.0)):
    """Randomize objects loc/rot/scale

    :param random_seed: Random Seed, Seed value for the random generator
    :type random_seed: int
    :param use_delta: Transform Delta, Randomize delta transform values instead of regular transform
    :type use_delta: bool
    :param use_loc: Randomize Location, Randomize the location values
    :type use_loc: bool
    :param loc: Location, Maximum distance the objects can spread over each axis
    :type loc: float
    :param use_rot: Randomize Rotation, Randomize the rotation values
    :type use_rot: bool
    :param rot: Rotation, Maximum rotation over each axis
    :type rot: float
    :param use_scale: Randomize Scale, Randomize the scale values
    :type use_scale: bool
    :param scale_even: Scale Even, Use the same scale value for all axis
    :type scale_even: bool
    :param scale: Scale, Maximum scale randomization over each axis
    :type scale: float
    """
    pass


def webMapFromDictionaryList(features):
    """creates html page with Leaflet based web map displaying a list of point features provided as parameters as a list of dictionaries with name, lat, lon properties"""
    html = """
<!DOCTYPE html>

      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css" type="text/css" crossorigin="">

"""
    return html


def _scrub_uri(uri):
    """scrub auth info from uri"""
    if ('/api/authorizations/cookie/' in uri or
        '/api/authorizations/token/' in uri):
        uri = uri.rsplit('/', 1)[0] + '/[secret]'
    return uri


def to_string(list):
    """
    Convert list to string. If empty it is set to (not set)
    """
    if list:
        return ''.join(list)
    else:
        return '(not set)'


def energy(disp, stiff):
    """
    Computes the potential energy for the current solution.

    Parameters
    ----------
    disp : ndarray (float)
        Array with the computed displacements.
    stiff : ndarray (float)
        Global stiffness matrix.

    Returns
    -------
    el_energy : scalar (float)
        Total energy in the system. :math:`-\\frac{1}{2} U^T K U`

    """
    force = stiff.dot(disp)
    el_energy = -0.5 * force.dot(disp)
    return el_energy


def sanitiseArgs(argv):
    """Sanitises command-line arguments to work around a bug in ``argparse``.

    The ``argparse`` module does not work with non-numeric optional argument
    values that begin with a hyphen, as it thinks that they are argument names
    (see https://bugs.python.org/issue9334).

    This function searches for relevant optional argument names, and prepends
    a space to their values to make sure that ``argparse`` doesn't fall over.

    :arg argv: Command-line arguments
    :returns:  Sanitised command-line arguments
    """
    argv = list(argv)
    toSanitise = [('-nv', [1]), ('--na_values', [1]), ('-re', [1, 2]), (
        '--recoding', [1, 2]), ('-cv', [2]), ('--child_values', [2])]
    for arg, idxs in toSanitise:
        try:
            argidx = argv.index(arg)
        except ValueError:
            continue
        for i in idxs:
            i = i + 1 + argidx
            val = argv[i]
            if val.startswith('-'):
                argv[i] = ' ' + val
    return argv


def create_url(token, url, customerid):
    """ Creates the url for sending data to NodePing

    Formats the url based on whether or not the
    customerid is None

    :type token: string
    :param token: Your NodePing API token
    :type url: string
    :param url: full URL to API excluding the token and/or custid
    :type customerid: string
    :param customerid: Optional subaccount ID for your account
    :return: URL that will be used for HTTP request
    :rtype: string
    """
    if '?' in url:
        token_str = '&token='
    else:
        token_str = '?token='
    if customerid:
        url = '{0}{1}{2}&customerid={3}'.format(url, token_str, token,
            customerid)
    else:
        url = '{0}{1}{2}'.format(url, token_str, token)
    return url


def _validate_hash_pyc(data, source_hash, name, exc_details):
    """Validate a hash-based pyc by checking the real source hash against the one in
    the pyc header.

    *data* is the contents of the pyc file. (Only the first 16 bytes are
    required.)

    *source_hash* is the importlib.util.source_hash() of the source file.

    *name* is the name of the module being imported. It is used for logging.

    *exc_details* is a dictionary passed to ImportError if it raised for
    improved debugging.

    An ImportError is raised if the bytecode is stale.

    """
    if data[8:16] != source_hash:
        raise ImportError(
            f"hash in bytecode doesn't match hash of source {name!r}", **
            exc_details)


@classmethod
def copy(cls, data):
    """copy data to clipboard"""
    assert type(data) in cls.__registered__classes
    if id(data) != id(cls.__current_data):
        cls.__current_data = data


def has_deriv(function):
    """ Check that function has derivative.

    Parameters
    ----------
    function : function
        Function which need to validate.

    Returns
    -------
    bool
        True if function has derivative, False otherwise.
    """
    return hasattr(function, 'deriv')


def get_from_request(name, request):
    """Read data from the request and return a {id: value} dict, or None
        The scope of the method is to obtain data in the proper format, that is commonly a string
        """