def write_boot(boot, triple, outfile):
    """
    Write the current dictionary of bootstrapping output from bootstrap_triple()
    to the file passed as an argument to the function.
    """
    print(
        """P1	Hybrid	P2	Zscore	Pvalue	Gamma	AAAA	AAAB	AABA	AABB	AABC	ABAA	ABAB	ABAC	ABBA	BAAA	ABBC	CABC	BACA	BCAA	ABCD
"""
        , end='', file=outfile)
    for v in boot.values():
        print(triple[0], '\t', triple[1], '\t', triple[2], '\t', sep='',
            end='', file=outfile)
        print(v['Zscore'], '\t', sep='', end='', file=outfile)
        print(v['Pvalue'], '\t', sep='', end='', file=outfile)
        print(v['Gamma'], '\t', sep='', end='', file=outfile)
        print(v['AAAA'], '\t', sep='', end='', file=outfile)
        print(v['AAAB'], '\t', sep='', end='', file=outfile)
        print(v['AABA'], '\t', sep='', end='', file=outfile)
        print(v['AABB'], '\t', sep='', end='', file=outfile)
        print(v['AABC'], '\t', sep='', end='', file=outfile)
        print(v['ABAA'], '\t', sep='', end='', file=outfile)
        print(v['ABAB'], '\t', sep='', end='', file=outfile)
        print(v['ABAC'], '\t', sep='', end='', file=outfile)
        print(v['ABBA'], '\t', sep='', end='', file=outfile)
        print(v['BAAA'], '\t', sep='', end='', file=outfile)
        print(v['ABBC'], '\t', sep='', end='', file=outfile)
        print(v['CABC'], '\t', sep='', end='', file=outfile)
        print(v['BACA'], '\t', sep='', end='', file=outfile)
        print(v['BCAA'], '\t', sep='', end='', file=outfile)
        print(v['ABCD'], '\n', sep='', end='', file=outfile)


def add_tags_to_resource(ResourceARN=None, Tags=None):
    """
    Adds one or more tags to the specified resource. You use tags to add metadata to resources, which you can use to categorize these resources. For example, you can categorize resources by purpose, owner, environment, or team. Each tag consists of a key and a value, which you define. You can add tags to the following AWS Storage Gateway resources:
    You can create a maximum of 10 tags for each resource. Virtual tapes and storage volumes that are recovered to a new gateway maintain their tags.
    See also: AWS API Documentation

    Examples
    Adds one or more tags to the specified resource.
    Expected Output:

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

    :type ResourceARN: string
    :param ResourceARN: [REQUIRED]
            The Amazon Resource Name (ARN) of the resource you want to add tags to.

    :type Tags: list
    :param Tags: [REQUIRED]
            The key-value pair that represents the tag you want to add to the resource. The value can be an empty string.
            Note
            Valid characters for key and value are letters, spaces, and numbers representable in UTF-8 format, and the following special characters: + - = . _ : / @.
            (dict) --
            Key (string) -- [REQUIRED]
            Value (string) -- [REQUIRED]

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

    :returns:
    ResourceARN (string) -- [REQUIRED]
    The Amazon Resource Name (ARN) of the resource you want to add tags to.

    Tags (list) -- [REQUIRED]
    The key-value pair that represents the tag you want to add to the resource. The value can be an empty string.

    Note
    Valid characters for key and value are letters, spaces, and numbers representable in UTF-8 format, and the following special characters: + - = . _ : / @.

    (dict) --
    Key (string) -- [REQUIRED]
    Value (string) -- [REQUIRED]

    """
    pass


@classmethod
def parse(cls, name, data_size, reader, parsers):
    """given a 4 byte name, data_size int, BitstreamReader
        and dict of {"atom":handler} sub-parsers,
        returns an atom of this class"""
    assert name == b'mdhd'
    version, flags = reader.parse('8u 24u')
    if version == 0:
        atom_format = '32u 32u 32u 32u'
    else:
        atom_format = '64U 64U 32u 64U'
    created_utc_date, modified_utc_date, sample_rate, track_length = (reader
        .parse(atom_format))
    language = reader.parse('1p 5u 5u 5u')
    quality = reader.read(16)
    return cls(version=version, flags=flags, created_utc_date=
        created_utc_date, modified_utc_date=modified_utc_date, sample_rate=
        sample_rate, track_length=track_length, language=language, quality=
        quality)


def record_magic(dct, magic_kind, magic_name, func):
    """Utility function to store a function as a magic of a specific kind.

    Parameters
    ----------
    dct : dict
      A dictionary with 'line' and 'cell' subdicts.

    magic_kind : str
      Kind of magic to be stored.

    magic_name : str
      Key to store the magic as.

    func : function
      Callable object to store.
    """
    if magic_kind == 'line_cell':
        dct['line'][magic_name] = dct['cell'][magic_name] = func
    else:
        dct[magic_kind][magic_name] = func


def wave_frequency_t(time_period):
    """Usage: Finding the wave frequency using time period.
    f=1/T"""
    return 1 / time_period


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


@staticmethod
def p_daq_optional(p):
    """daq_optional : daq_list
                        | event
                        | timestamp_supported
                        | optimisation_type
                        | address_extension
                        | identification_field_type
                        | granularity_odt_entry
                        | prescaler_supported
                        | resume_supported
                        | IDENT
                        | NUMERIC"""
    p[0] = p.slice[1].type, p[1]


@classmethod
def _get_checks(klass):
    """ Return sequence of check functions for this class """
    return (klass._chk_sizeof_hdr, klass._chk_datatype, klass._chk_bitpix,
        klass._chk_pixdims)


def get_capsule_file_name(capsule_options):
    """from the shared capsule_options dictionary, returns the formatted capsule file name"""
    return (
        f"{capsule_options['fw_name']}_{capsule_options['fw_version_string']}.bin"
        )


def str2bool(value):
    """Convert a string into boolean.

    .. code-block:: python

        pycof.str2bool(value)

    :Parameters:
        * **value** (:obj:`str`): Value to be converted to boolean.

    :Example:
        >>> pycof.str2bool('true')
        ... True
        >>> pycof.str2bool(1)
        ... True
        >>> pycof.str2bool(0)
        ... False

    :Returns:
        * :obj:`bool`: Returns either True or False.
    """
    return str(value).lower() in ('yes', 'y', 'true', 't', '1')


@classmethod
def _norm_source(cls, source):
    """internal helper - accepts string, dict, or context"""
    if isinstance(source, dict):
        return cls(**source)
    elif isinstance(source, cls):
        return source
    else:
        self = cls()
        self.load(source)
        return self


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

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


@staticmethod
def _compute_back_link(back_indicator, project):
    """
        Based on a simple indicator, compute URL for anchor BACK.
        """
    if back_indicator is None:
        back_page_link = None
    elif back_indicator == 'burst':
        back_page_link = '/burst'
    elif back_indicator == 'operations':
        back_page_link = '/project/viewoperations/' + str(project.id)
    else:
        back_page_link = '/project/editstructure/' + str(project.id)
    return back_page_link


@classmethod
def describe(cls, policy):
    """Policy description."""
    if cls.validate(policy):
        return cls.descriptions[policy]


def _zseries_to_cseries(zs):
    """Covert z-series to a Chebyshev series.

    Covert a z series to the equivalent Chebyshev series. The result is
    never an empty array. The dtype of the return is the same as that of
    the input. No checks are run on the arguments as this routine is for
    internal use.

    Parameters
    ----------
    zs : 1-D ndarray
        Odd length symmetric z-series, ordered from  low to high.

    Returns
    -------
    c : 1-D ndarray
        Chebyshev coefficients, ordered from  low to high.

    """
    n = (zs.size + 1) // 2
    c = zs[n - 1:].copy()
    c[1:n] *= 2
    return c


@staticmethod
def __clean_filename(filename):
    """
        Simple way to rename compressed file to the original file name.
        It is not a full proof detection method, but it will hardly present any issue.
        :param filename: file path to adapt
        :return: adapted file path
        """
    return '{}.pdf'.format(filename.split('_compress_', 1)[0])


def get_model_class_by_name(registry, name):
    """ Return the model class matching `name` in the given `registry`.
    """
    for cls in registry.values():
        if getattr(cls, '__name__', None) == name:
            return cls


@classmethod
def needs_update(cls, hash, secret=None):
    """
        check if hash's configuration is outside desired bounds,
        or contains some other internal option which requires
        updating the password hash.

        :param hash:
            hash string to examine

        :param secret:
            optional secret known to have verified against the provided hash.
            (this is used by some hashes to detect legacy algorithm mistakes).

        :return:
            whether secret needs re-hashing.

        .. versionadded:: 1.7
        """
    return False


def getReferencedAttributes(obj):
    """Returns attributes which should be passe dto the storage by reference.

        Returns a dict of the format ``name:attribute``.
        """


def p_method_modifiers_empty(p):
    """method_modifiers : empty"""
    p[0] = []


@staticmethod
def _validate_response(response):
    """
        Helper function to validate the response request produced from _make_request().
           :param response: The requests response object.
           :rtype: A dictionary containing the resp_code and JSON response.
        """
    if response.status_code == 200:
        json_resp = response.json()
        return dict(status_code=response.status_code, json_resp=json_resp)
    else:
        return dict(status_code=response.status_code, error=response.text,
            resp=response.content)


def assert_not_called(_mock_self):
    """assert that the mock was never called.
        """
    self = _mock_self
    if self.call_count != 0:
        msg = "Expected '%s' to not have been called. Called %s times.%s" % (
            self._mock_name or 'mock', self.call_count, self._calls_repr())
        raise AssertionError(msg)


def urlpath(request, *args, **kwargs):
    """Generate path, including query and fragment (aka anchor), for
        ``request`` using positional arguments ``args`` and keyword arguments
        ``kwargs``. Refer to corresponding router plugin for specific signature
        for positional and key-word arguments. Returns urlpath string. This
        does not include SCRIPT_NAME, netlocation and scheme.

        ``request``,
            Plugin instance implementing :class:`IHTTPRequest` interface.
        """


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

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

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


def gcd(a, b):
    """
    gcd(a : int, b : int) -> int

    Use Euclid's algorithm to find the greatest common divisor.
    """
    if a > b:
        a, b = b, a
    while b != 0:
        a, b = b, a % b
    return a


def Eval(string: str):
    """Use eval() without dealing with exceptions."""
    try:
        return eval(string)
    except:
        return string


def spit(path, data):
    """Write the specified file with a string."""
    with open(path, 'w+') as f:
        return f.write(data)


@classmethod
def simple(cls, df, missing, maxdist, mindur):
    """Detects fixations, defined as consecutive samples with an inter-sample distance of less than a set amount of
		pixels (disregarding missing data).

		Parameters
		----------
		df : :class:`pandas.DataFrame`
			Pandas dataframe of x,y and timestamp positions
		missing : :obj:`str`
			Value to be used for missing data (default = 0.0)
		maxdist : :obj:`str`
			Maximal inter-sample distance in pixels (default = 25)
		mindur : :obj:`str`
			Minimal duration of a fixation in milliseconds; detected fixation cadidates will be
			disregarded if they are below this duration (default = 100).

		Returns
		-------
		Sfix : :class:`numpy.ndarray` shape (N)
			list of lists, each containing [starttime]
		Efix : :class:`numpy.ndarray` shape (N)
			list of lists, each containing [starttime, endtime, duration, endx, endy]

		Notes
		-----
		From https://github.com/esdalmaijer/PyGazeAnalyser/blob/master/pygazeanalyser/detectors.py

		"""
    x = df['x']
    y = df['y']
    time = df['timestamp']
    Sfix = []
    Efix = []
    si = 0
    fixstart = False
    for i in range(1, len(x)):
        dist = ((x[si] - x[i]) ** 2 + (y[si] - y[i]) ** 2) ** 0.5
        if dist <= maxdist and not fixstart:
            si = 0 + i
            fixstart = True
            Sfix.append([time[i]])
        elif dist > maxdist and fixstart:
            fixstart = False
            if time[i - 1] - Sfix[-1][0] >= mindur:
                Efix.append([Sfix[-1][0], time[i - 1], time[i - 1] - Sfix[-
                    1][0], x[si], y[si]])
            else:
                Sfix.pop(-1)
            si = 0 + i
        elif not fixstart:
            si += 1
    return Sfix, Efix


def __call__(context):
    """Create and return the Catalog.

        @param return: zope.app.catalog.catalog.Catalog instance.
        """


def s_set(p_map, p_key, p_value):
    """
    s_set(p_map, p_key, p_value)->None
    """
    try:
        p_map[p_key] = p_value
    finally:
        return


def is_geometry(value, epsg=None, expected_geom_type=None, expected_epsg=None):
    """Returns ``True`` if the given value and srid are valid according to the expected parameters.
    """
    from osgeo import ogr
    ogr.UseExceptions()
    if epsg is not None and not isinstance(epsg, int):
        return False
    if expected_epsg is not None and (epsg is None or epsg != expected_epsg):
        return False
    try:
        geom = ogr.CreateGeometryFromWkt(value)
        geom.IsValid()
    except RuntimeError:
        return False
    if expected_geom_type is not None and geom.GetGeometryName().upper(
        ) != expected_geom_type.upper():
        return False
    return True


@classmethod
def has_resuming(cls):
    """Returns whether it supports to resume the fetch process.

        :returns: this backend does not supports entries resuming
        """
    return False


def organizeControl(inputFilePath, outputFilePath, check_margin_size):
    """
        script for organizing control junction information
    """
    hIN = open(inputFilePath, 'r')
    hOUT = open(outputFilePath, 'w')
    mergedBedpeInfo = {}
    mergedreadNums = {}
    num = 1
    for line in hIN:
        F = line.rstrip('\n').split('\t')
        match = 0
        delList = []
        for key in sorted(mergedBedpeInfo):
            (tchr1, tstart1, tend1, tchr2, tstart2, tend2, tdir1, tdir2,
                inseqSize) = key.split('\t')
            tsamples, treadNums = mergedBedpeInfo[key].split('\t')
            if tend1 == '18606952':
                print(key)
            if F[0] != tchr1 or int(F[2]) > int(tend1) + check_margin_size:
                print('\t'.join([tchr1, tstart1, tend1, tchr2, tstart2,
                    tend2, 'controlJunction_' + str(num), inseqSize, tdir1,
                    tdir2, tsamples, treadNums]), file=hOUT)
                num = num + 1
                delList.append(key)
                continue
            elif F[0] == tchr1 and F[3] == tchr2 and F[8] == tdir1 and F[9
                ] == tdir2:
                flag = 0
                if F[8] == '+':
                    expectedDiffSize = int(F[2]) - int(tend1) + (int(F[7]) -
                        int(inseqSize))
                    if F[9] == '+' and int(F[5]) == int(tend2) - int(
                        expectedDiffSize) or F[9] == '-' and int(F[5]) == int(
                        tend2) + int(expectedDiffSize):
                        flag = 1
                else:
                    expectedDiffSize = int(F[2]) - int(tend1) + (int(
                        inseqSize) - int(F[7]))
                    if F[9] == '+' and int(F[5]) == int(tend2) + int(
                        expectedDiffSize) or F[9] == '-' and int(F[5]) == int(
                        tend2) - int(expectedDiffSize):
                        flag = 1
                if flag == 1:
                    match = 1
                    newKey = '\t'.join([F[0], F[1], F[2], F[3], F[4], F[5],
                        F[8], F[9], F[7]])
                    newSamples = tsamples + ';' + F[10]
                    newReadNums = treadNums + ';' + F[11]
                    if F[7] < inseqSize:
                        mergedBedpeInfo[newKey] = '\t'.join([newSamples,
                            newReadNums])
                        delList.append(key)
                    else:
                        mergedBedpeInfo[key] = '\t'.join([newSamples,
                            newReadNums])
        for item in delList:
            del mergedBedpeInfo[item]
        if match == 0:
            newKey = '\t'.join([F[0], F[1], F[2], F[3], F[4], F[5], F[8], F
                [9], F[7]])
            mergedBedpeInfo[newKey] = F[10] + '\t' + F[11]
    hIN.close()
    for key in sorted(mergedBedpeInfo):
        (tchr1, tstart1, tend1, tchr2, tstart2, tend2, tdir1, tdir2, inseqSize
            ) = key.split('\t')
        tsamples, treadNums = mergedBedpeInfo[key].split('\t')
        print('\t'.join([tchr1, tstart1, tend1, tchr2, tstart2, tend2,
            'controlJunction_' + str(num), inseqSize, tdir1, tdir2,
            tsamples, treadNums]), file=hOUT)
        num = num + 1
    hOUT.close()


def GetData(ID, season=None, cadence='lc', clobber=False, delete_raw=False,
    aperture_name=None, saturated_aperture_name=None, max_pixels=None,
    download_only=False, saturation_tolerance=None, bad_bits=None, **kwargs):
    """
  Returns a :py:obj:`DataContainer` instance with the raw data for the target.

  :param int ID: The target ID number
  :param int season: The observing season. Default :py:obj:`None`
  :param str cadence: The light curve cadence. Default `lc`
  :param bool clobber: Overwrite existing files? Default :py:obj:`False`
  :param bool delete_raw: Delete the FITS TPF after processing it? Default :py:obj:`False`
  :param str aperture_name: The name of the aperture to use. Select `custom` to call          :py:func:`GetCustomAperture`. Default :py:obj:`None`
  :param str saturated_aperture_name: The name of the aperture to use if the target is          saturated. Default :py:obj:`None`
  :param int max_pixels: Maximum number of pixels in the TPF. Default :py:obj:`None`
  :param bool download_only: Download raw TPF and return? Default :py:obj:`False`
  :param float saturation_tolerance: Target is considered saturated if flux is within          this fraction of the pixel well depth. Default :py:obj:`None`
  :param array_like bad_bits: Flagged :py:obj`QUALITY` bits to consider outliers when          computing the model. Default :py:obj:`None`

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


def getTrackingUrl(track_number):
    """
        given a track number this should return, if available for this service
        a url that can be used to track the shipment
        """


@staticmethod
def _read_fs_register_x64(concrete_target):
    """
        Injects a small shellcode to leak the fs segment register address. In Linux x64 this address is pointed by fs[0]
        :param concrete_target: ConcreteTarget which will be used to get the fs register address
        :return: fs register address
        :rtype string
        """
    exfiltration_reg = 'rax'
    read_fs0_x64 = b'dH\x8b\x04%\x00\x00\x00\x00\x90\x90\x90\x90'
    return concrete_target.execute_shellcode(read_fs0_x64, exfiltration_reg)


@staticmethod
def clean(data=None):
    """
        Generic plotting function.

        Provide arbitrary data and options objects as dictionaries,
        and a plot type as a string. The data and options dictionary will be passed
        directly to the plot, without any parsing or formatting,
        so make sure it is of the appropriate for your visualization
        (e.g. {"series": [1,2,3]} for a "line" visualization).

        Most useful when providing data to custom visualizations, as opposed
        to the included plot types (e.g. lightning.scatter, lightning.line, etc.)
        which do automatic parsing and formatting.

        Parameters
        ----------
        data : dict
            Dictionary with data to plot

        type : str
            Name of plot (e.g. 'line' or 'scatter')
        """
    return data


def register_handler(handler):
    """
    Install application-specific BUFR image handler.

    :param handler: Handler object.
    """
    global _handler
    _handler = handler


def py2_replace_help(argv):
    """

    Workaround for Python 2.7 argparse, which does not accept empty COMMAND

    If `--help` or `-h` present and every argument before it begins with `-`,
    then convert it to `help`.
    """
    try:
        ind = argv.index('--help')
    except ValueError:
        try:
            ind = argv.index('-h')
        except ValueError:
            ind = None
    if ind is not None:
        for k in range(ind):
            if argv[k][0] != '-':
                ind = None
                break
        if ind is not None:
            argv[ind] = 'help'
    return argv


def get_ident():
    """Dummy implementation of _thread.get_ident().

    Since this module should only be used when _threadmodule is not
    available, it is safe to assume that the current process is the
    only thread.  Thus a constant can be safely returned.
    """
    return -1


@staticmethod
def get_link_page_text(link_page):
    """
        Construct the dialog box to display a list of links to the user.
        """
    text = ''
    for i, link in enumerate(link_page):
        capped_link_text = link['text'] if len(link['text']) <= 20 else link[
            'text'][:19] + '…'
        text += '[{}] [{}]({})\n'.format(i, capped_link_text, link['href'])
    return text


def pretty_date(time=False):
    """
    Get a datetime object or a int() Epoch timestamp and return a
    pretty string like 'an hour ago', 'Yesterday', '3 months ago',
    'just now', etc
    """
    from datetime import datetime
    now = datetime.now()
    if type(time) is int:
        diff = now - datetime.fromtimestamp(time)
    elif isinstance(time, datetime):
        diff = now - time
    elif not time:
        diff = now - now
    second_diff = diff.seconds
    day_diff = diff.days
    if day_diff < 0:
        return ''
    if day_diff == 0:
        if second_diff < 10:
            return 'just now'
        if second_diff < 60:
            return f'{second_diff} seconds ago'
        if second_diff < 120:
            return 'a minute ago'
        if second_diff < 3600:
            return f'{round(second_diff / 60):.0f} minutes ago'
        if second_diff < 7200:
            return 'an hour ago'
        if second_diff < 86400:
            return f'{round(second_diff / 3600):.0f} hours ago'
    if day_diff == 1:
        return 'Yesterday'
    if day_diff < 7:
        return f'{day_diff} days ago'
    if day_diff < 31:
        return f'{round(day_diff / 7):.0f} weeks ago'
    if day_diff < 365:
        return f'{round(day_diff / 30):.0f} months ago'
    return f'{round(day_diff / 365):.0f} years ago'


def is_negative(value):
    """
    Returns True is the value is a negative number
    """
    return value < 0


@staticmethod
def __to_json(proxy_lst):
    """
        Turn list of strings to json format
        :param proxy_lst: list of proxies strings
        :return: json formatted list
        """
    return {'proxies': proxy_lst}


@classmethod
def from_config(cls, config):
    """Instantiate codec from a configuration object."""
    return cls(**config)


def update_headers(headers, api_version):
    """Set 'OpenStack-API-Version' header if api_version is not
       null
    """
    if api_version and api_version.ver_minor != 0:
        headers['OpenStack-API-Version'] = 'volume ' + api_version.get_string()


def Yen(Re):
    """Calculates drag coefficient of a smooth sphere using the method in
    [1]_ as described in [2]_.

    .. math::
        C_D = \\frac{24}{Re}\\left(1 + 0.15\\sqrt{Re} + 0.017Re\\right)
        - \\frac{0.208}{1+10^4Re^{-0.5}}

    Parameters
    ----------
    Re : float
        Particle Reynolds number of the sphere using the surrounding fluid
        density and viscosity, [-]

    Returns
    -------
    Cd : float
        Drag coefficient [-]

    Notes
    -----
    Range is Re <= 2E5

    Examples
    --------
    >>> Yen(200.)
    0.7822647002187014

    References
    ----------
    .. [1] B.C. Yen, Sediment Fall Velocity in Oscillating Flow, University of
       Virginia, Department of Civil Engineering, 1992.
    .. [2] Barati, Reza, Seyed Ali Akbar Salehi Neyshabouri, and Goodarz
       Ahmadi. "Development of Empirical Models with High Accuracy for
       Estimation of Drag Coefficient of Flow around a Smooth Sphere: An
       Evolutionary Approach." Powder Technology 257 (May 2014): 11-19.
       doi:10.1016/j.powtec.2014.02.045.
    """
    return 24.0 / Re * (1 + 0.15 * Re ** 0.5 + 0.017 * Re) - 0.208 / (1 +
        10000.0 * Re ** -0.5)


def inverseEnumeration(l):
    """Returns the dictionary that provides for each element in the input list its index in the input list"""
    result = {}
    for i, x in enumerate(l):
        result[x] = i
    return result


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def tools():
    """Toggle clip tools panel

    """
    pass


@classmethod
def define_action(cls, **kw):
    """Adds one or several actions or other class attributes to this
        model.

        Attributes must be specified using keyword arguments, the
        specified keys must not yet exist on the model.

        Used e.g. in :mod:`lino_xl.lib.cal` to add the `UpdateReminders`
        action to :class: `lino.modlib.users.models.User`.

        Or in :mod:`lino_xl.lib.invoicing.models` for defining a
        custom chooser.

        """
    for k, v in list(kw.items()):
        if k in cls.__dict__:
            raise Exception('Tried to redefine %s.%s' % (cls, k))
        setattr(cls, k, v)


@classmethod
def expand_code(cls, short_code):
    """
        Returns the numeric ID for a shortcode

        :param short_code:
        :return:
        """
    return cls._decode(short_code)


def _is_iterable_non_string(arg):
    """
    A helper method to return True if the given argument appears to be iterable
    (like a list) but not able to be converted to a Range.

    In particular, checks for whether python would consider the argument to be
    iterable (it has either __iter__() or __getattr__() defined), and then
    checks that it isn't a string (in which case we don't want to iterate through
    it, we want to pass it in to Range() wholesale).
    """
    return (hasattr(arg, '__iter__') or hasattr(arg, '__getattr__')
        ) and not isinstance(arg, str)


@classmethod
def get_prefix(cls):
    """Get es prefix, use in both dev and test to have central get prefix when testing curator with prefix."""
    prefix = cls.ELASTIC_INDEX_PREFIX
    if cls.ENV == 'test':
        prefix += 'test_'
    return prefix + cls.INDEX_PREFIX


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


def process_tags(inst_tags):
    """Create dict of instance tags as only name:value pairs."""
    tag_dict = {}
    for k in range(len(inst_tags)):
        tag_dict[inst_tags[k]['Key']] = inst_tags[k]['Value']
    return tag_dict


@staticmethod
def get_port(config):
    """Get instance port."""
    return config.get('port')


def is_active_staff_or_superuser(request):
    """
    Standalone mode authorization check
    """
    return request.user and request.user.is_active and (request.user.
        is_staff or request.user.is_superuser)


def outputgraph(ui, graph):
    """outputs an ASCII graph of a DAG

    this is a helper function for 'ascii' below.

    takes the following arguments:

    - ui to write to
    - graph data: list of { graph nodes/edges, text }

    this function can be monkey-patched by extensions to alter graph display
    without needing to mimic all of the edge-fixup logic in ascii()
    """
    for ln, logstr in graph:
        ui.write((ln + logstr).rstrip() + b'\n')


def wash_html_id(dirty):
    """Strip non-alphabetic or newline characters from a given string.

    It can be used as a HTML element ID (also with jQuery and in all browsers).

    :param dirty: the string to wash
    :returns: the HTML ID ready string
    """
    import re
    if not dirty[0].isalpha():
        dirty = 'i' + dirty
    non_word = re.compile('[^\\w]+')
    return non_word.sub('', dirty)


@staticmethod
def all(registry, effective_name, objct):
    """Assign all of the possible options.

        Collect all registered items into a set,
        and assign that set to a name. Note that
        even if only one item is assigned to a name,
        that name will be assigned to a set of length 1.
        """
    myset = registry.get(effective_name, set())
    myset.add(objct)
    return myset


def compute_distances(data):
    """Compute the distances to select stars in the sdss_sspp sample.

    Distance are determined using empirical color/magnitude fits from
    Ivezic et al 2008, ApJ 684:287

    Extinction correcctions come from Berry et al 2011, arXiv 1111.4985

    This distance only works for stars with log(g) > 3.3
    Other stars will have distance=-1
    """
    Ar = data['Ar']
    Au = 1.81 * Ar
    Ag = 1.4 * Ar
    Ai = 0.759 * Ar
    Az = 0.561 * Ar
    gmag = data['gpsf'] - Ag
    rmag = data['rpsf'] - Ar
    imag = data['ipsf'] - Ai
    gi = gmag - imag
    FeH = data['FeH']
    Mr0 = (-5.06 + 14.32 * gi - 12.97 * gi ** 2 + 6.127 * gi ** 3 - 1.267 *
        gi ** 4 + 0.0967 * gi ** 5)
    FeHoffset = 4.5 - 1.11 * FeH - 0.18 * FeH ** 2
    Mr = Mr0 + FeHoffset
    dist = 0.01 * 10 ** (0.2 * (rmag - Mr))
    dist[data['logg'] < 3.3] = -1
    return dist


def environmentfilter(f):
    """Decorator for marking environment dependent filters.  The current
    :class:`Environment` is passed to the filter as first argument.
    """
    f.environmentfilter = True
    return f


def get_duration_of_items(items):
    """
    Calculate the total duration of the media items using the "length" attribute
    """
    total_time = 0
    if isinstance(items, list):
        for item in items:
            try:
                length = item.get('length')
                if not length or length <= 0:
                    raise ValueError('Invalid length value!')
                total_time += length
            except TypeError:
                pass
            except ValueError:
                pass
    return round(total_time)


def convert_ListProperty(model, prop, kwargs):
    """Returns a form field for a ``db.ListProperty``."""
    return None


def delete_cookie(name, path='/', domain=None):
    """ Delete a cookie from the client. Note that path and domain must
        match how the cookie was originally set.  This sets the cookie to the
        empty string, and max_age=0 so that it should expire immediately. """


def rename_RGA_cols(data):
    """
    names columns of RGA data like they would be from PyExpLabSys+cinfdata
    """
    channels = data['channels']
    for channel, mass in channels.items():
        if mass + '-x' in data:
            print('WARNING: rename_RGA_cols() not copying ' + channel +
                ' to ' + mass +
                ' because there is existing data. Maybe rename_RGA_cols' +
                ' was already called, or maybe the same mass appears in multiple channels.'
                )
        else:
            data[mass + '-x'] = data['Time(s)'].copy()
            data[mass + '-y'] = data[channel].copy()
            data['col_types'][mass + '-x'] = 'MS'
            data['col_types'][mass + '-y'] = 'MS'
            data['data_cols'].add(mass + '-x')
            data['data_cols'].add(mass + '-y')
            print(channel + ' copied to ' + mass)


@staticmethod
def pretty_duration(hours):
    """Format a duration in days, hours, minutes, seconds."""
    seconds = int(3600 * hours)
    days, seconds = divmod(seconds, 86400)
    hours, seconds = divmod(seconds, 3600)
    minutes, seconds = divmod(seconds, 60)
    if days > 0:
        return '%dd %dh %dm' % (days, hours, minutes)
    if hours > 0:
        return '%dh %dm' % (hours, minutes)
    return '%dm' % minutes


def is_float(s):
    """Returns true if s represents a float"""
    try:
        float(s)
        return True
    except ValueError:
        return False


def dump():
    """Serialize the context to the configuration file.

        Returns a ConfigParser object.
        """


def environment_from_config(config):
    """
    This functions returns either the environment of the current configuration.

    :param config: current configuration
    :return: 'staging' or 'production'
    """
    if hasattr(config, 'DEVICE_HOST') and 'test' in config.DEVICE_HOST:
        return 'staging'
    else:
        return 'production'


def get_device_id(handler_input):
    """Return the device id from the input request.

    The method retrieves the `deviceId` property from the input request.
    This value uniquely identifies the device and is generally used as
    input for some Alexa-specific API calls. More information about this
    can be found here :
    https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#system-object

    If there is no device information in the input request, then a ``None``
    is returned.

    :param handler_input: The handler input instance that is generally
        passed in the sdk's request and exception components
    :type handler_input: ask_sdk_core.handler_input.HandlerInput
    :return: Unique device id of the device used to send the alexa request
        or `None` if device information is not present
    :rtype: Optional[str]
    """
    device = handler_input.request_envelope.context.system.device
    if device:
        return device.device_id
    else:
        return None


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

        :param FileTransfersTransferSendType val:
        :rtype: EventType
        """
    return cls('file_transfers_transfer_send', val)


@classmethod
def root(cls, frequency=None, cache_head=None):
    """
        Generate an empty root node
        """
    node = cls(None, None, frequency, cache_head)
    node.prev = node.next = node
    return node


def normalize_job_id(job_id):
    """Convert the job id into job_id, array_id."""
    pass


@classmethod
def from_xarray(cls, x, **kwargs):
    """
        Create 1d Coordinates from named xarray coordinates.

        Arguments
        ---------
        x : xarray.DataArray
            Nade DataArray of the coordinate values

        Returns
        -------
        :class:`ArrayCoordinates1d`
            1d coordinates
        """
    return cls(x.data, name=x.name, **kwargs)


def empty_func(*args):
    """
    A dummy function.
    :return: None
    """


def get_bed_size(bed):
    """Much faster than using len(bed)
    NOT IMPLEMENTED YET IN OTHER FUNCTIONS OF THIS MODULE"""
    return sum(1 for _ in open(bed.fn))


def num2strg(num):
    """
    Attempt to emulate Excel's default conversion from number to string.
    """
    s = str(num)
    if s.endswith('.0'):
        s = s[:-2]
    return s


def poly2(x, A2, A1, x0, k):
    """
    2nd order polynomial
    """
    return A2 * (x - x0) ** 2 + A1 * (x - x0) + k


def global_dependencies(context):
    """
    Dependencies that are loaded for all tethys gizmos (after gizmo dependencies).
    """
    return ('tethys_gizmos/css/tethys_gizmos.css',
        'tethys_gizmos/js/tethys_gizmos.js')


@staticmethod
def oneLR(mumax, mu):
    """ One term of the Lai & Robbins lower bound for Constant arms: (mumax - mu) / KL(mu, mumax). """
    return (mumax - mu) / abs(mumax - mu)


def describe_account_attributes():
    """
    Lists all of the AWS DMS attributes for a customer account. The attributes include AWS DMS quotas for the account, such as the number of replication instances allowed. The description for a quota includes the quota name, current usage toward that quota, and the quota's maximum value.
    This command does not take any parameters.
    See also: AWS API Documentation

    :example: response = client.describe_account_attributes()

    :rtype: dict
    :return: {
        'AccountQuotas': [
            {
                'AccountQuotaName': 'string',
                'Used': 123,
                'Max': 123
            },
        ]
    }

    """
    pass


@classmethod
def unmarshal(cls, raw: bytes):
    """Returns a new AdminBlock object, unmarshalling given bytes according to:
        https://github.com/FactomProject/FactomDocs/blob/master/factomDataStructureDetails.md#administrative-block

        Useful for working with a single ablock out of context, pulled directly from a factomd database for instance.

        AdminBlock created will not include contextual metadata, such as timestamp
        """
    block, data = cls.unmarshal_with_remainder(raw)
    assert len(data) == 0, 'Extra bytes remaining!'
    return block


def eqhash(o):
    """Call ``obj.__eqhash__``."""
    try:
        return o.__eqhash__()
    except AttributeError:
        return hash(o)


def not_in_draft_scheme(concept):
    """Return True if `concept` is in a ConceptScheme not in "draft" state.
    """
    return concept.in_scheme[0].in_state[0].name != 'draft'


def parse_pbsnode_lall(output):
    """Parse output of pbsnodes -l all
    """
    frees, exclusives, others, down = 0, 0, 0, 0
    nr_nodes = 0
    nodes = {}
    for k in output:
        if len(k) > 2:
            line = k.split()
            status = line[1]
            node = line[0].split('.')[0]
            if node.startswith('v-'):
                continue
            if status == 'free':
                frees += 1
                nr_nodes += 1
            elif status == 'job-exclusive':
                exclusives += 1
                nr_nodes += 1
            elif status == 'down,offline':
                down += 1
            elif status == 'offline':
                down += 1
            elif status == 'down':
                down += 1
            else:
                others += 1
            nodes[node] = status
    pbsnodes = {'frees': frees, 'nr_nodes': nr_nodes, 'others': others,
        'exclusives': exclusives, 'down': down}
    return pbsnodes, nodes


def upar(unit_st):
    """Parse unit_st into num (float), unit (string) pair"""
    unit_st = str(unit_st)
    try:
        ind = list(map(str.isalpha, unit_st)).index(True)
        num, unit = float(unit_st[:ind]), unit_st[ind:]
    except ValueError:
        num = float(unit_st)
        unit = 'u'
    return num, unit


def _len_struct(obj):
    """Struct length in bytes.
    """
    try:
        return obj.size
    except AttributeError:
        return 0


def text_paste():
    """Paste text from clipboard

    """
    pass


def generate_db_auth_token(DBHostname=None, Port=None, DBUsername=None,
    Region=None):
    """
    Generates an auth token used to connect to a db with IAM credentials.

    :type DBHostname: str
    :param DBHostname: The hostname of the database to connect to.

    :type Port: int
    :param Port: The port number the database is listening on.

    :type DBUsername: str
    :param DBUsername: The username to log in as.

    :type Region: str
    :param Region: The region the database is in. If None, the client
            region will be used.

    """
    pass


def sort_closeness(replicas, location):
    """
    Return a list of replicas sorted by AGIS closeness.
    :param replicas : A dict with RSEs as values and replicas as keys (URIs).
    :param location: Location dictionary containing {'ip', 'fqdn', 'site'}
    """
    return replicas


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

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

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


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

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

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


def overlap(a, b):
    """Returns overlap of a and b (symmetric)

        Cases:
        * overlap  < 0 when a and b do not overlap
        * overlap == 0 when a and b abut or at least one is zero width
        * overlap  > 0 when a and b overlap

        """
    return min(a.end, b.end) - max(a.start, b.start)


def length_difference_check(orthologLen, inparalogLen, lenRatioThr, debug=False
    ):
    """
    Check the difference in length between a inparalong and its ortholog sequence (from the same species).

    Return a tuple of type (1, 0.4) where 1 means the inparalog should be kept, and 0.4 is
    the difference in length from the closest ortholog in the cluster.
    If the inparalog should be dropped then the first value is 0
    """
    if debug:
        print('\nlength_difference_check :: START')
        print('Ortholog length: %d' % orthologLen)
        print('Inparalogs length: %d' % inparalogLen)
        print('Length difference threshold: %s' % str(lenRatioThr))
    lenDiffRatio = 0
    if orthologLen == inparalogLen:
        return 1, 0.0, 1.0
    else:
        inparaVsOrthoLen = 1.0
        if inparalogLen < orthologLen:
            seqLenDiff = orthologLen - inparalogLen
            lenDiffRatio = round(float(seqLenDiff) / float(orthologLen), 2)
            inparaVsOrthoLen = -round(float(orthologLen) / float(
                inparalogLen), 2)
        else:
            seqLenDiff = inparalogLen - orthologLen
            lenDiffRatio = round(float(seqLenDiff) / float(inparalogLen), 2)
            inparaVsOrthoLen = round(float(inparalogLen) / float(
                orthologLen), 2)
        if lenDiffRatio <= lenRatioThr:
            return 1, lenDiffRatio, inparaVsOrthoLen
        else:
            return 0, lenDiffRatio, inparaVsOrthoLen


def _rdf2dot_simple(g, stream):
    """Create a simple graph of processes and artifacts."""
    from itertools import chain
    import re
    path_re = re.compile(
        '(?P<prefix>https://\\w+/|https://\\w+/\\w+/){0,1}(?P<type>[a-zA-Z]+)/(?P<commit>\\w+)(?P<path>.+)?'
        )
    inputs = g.query(
        """
        SELECT ?input ?role ?activity ?comment
        WHERE {
            ?activity (prov:qualifiedUsage/prov:entity) ?input .
            ?activity prov:qualifiedUsage ?qual .
            ?qual prov:hadRole ?role .
            ?qual prov:entity ?input .
            ?qual rdf:type ?type .
            ?activity rdf:type wfprov:ProcessRun .
            ?activity rdfs:comment ?comment .
            FILTER NOT EXISTS {?activity rdf:type wfprov:WorkflowRun}
        }
        """
        )
    outputs = g.query(
        """
        SELECT ?activity ?role ?output ?comment
        WHERE {
            ?output (prov:qualifiedGeneration/prov:activity) ?activity .
            ?output prov:qualifiedGeneration ?qual .
            ?qual prov:hadRole ?role .
            ?qual prov:activity ?activity .
            ?qual rdf:type ?type .
            ?activity rdf:type wfprov:ProcessRun ;
                      rdfs:comment ?comment .
            FILTER NOT EXISTS {?activity rdf:type wfprov:WorkflowRun}
        }
        """
        )
    activity_nodes = {}
    artifact_nodes = {}
    for source, role, target, comment in chain(inputs, outputs):
        src_path = path_re.match(source).groupdict()
        tgt_path = path_re.match(target).groupdict()
        stream.write(
            '\t"{src_commit}:{src_path}" -> "{tgt_commit}:{tgt_path}" [label={role}] \n'
            .format(src_commit=src_path['commit'][:5], src_path=src_path.
            get('path') or '', tgt_commit=tgt_path['commit'][:5], tgt_path=
            tgt_path.get('path') or '', role=role))
        if src_path.get('type') == 'commit':
            activity_nodes.setdefault(source, {'comment': comment})
            artifact_nodes.setdefault(target, {})
        if tgt_path.get('type') == 'commit':
            activity_nodes.setdefault(target, {'comment': comment})
            artifact_nodes.setdefault(source, {})
    for node, content in activity_nodes.items():
        node_path = path_re.match(node).groupdict()
        stream.write(
            '\t"{commit}:{path}" [shape=box label="#{commit}:{path}:{comment}"] \n'
            .format(comment=content['comment'], commit=node_path['commit'][
            :5], path=node_path.get('path') or ''))
    for node, content in artifact_nodes.items():
        node_path = path_re.match(node).groupdict()
        stream.write('\t"{commit}:{path}" [label="#{commit}:{path}"] \n'.
            format(commit=node_path['commit'][:5], path=node_path.get(
            'path') or ''))
    stream.write('}\n')


def pick_output_filename(input_filename):
    """Pick a filename for the output file."""
    if input_filename.endswith('.gz'):
        return input_filename[:-len('.gz')] + '.html'
    else:
        return input_filename + '.html'


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


def get_context_from_db(url):
    """Look up the context in the database."""


def isInbetween(number, low, high):
    """Returns True if number is inbetween low and high, returns False otherwise"""
    if low <= number <= high:
        return True
    else:
        return False


def get_signed_value(obj):
    """
    Returns signed integer from LLDB value.

    :param lldb.SBValue obj: LLDB value object.
    :return: Signed integer from LLDB value.
    :rtype: int | None
    """
    return None if obj is None else obj.GetValueAsSigned()


def aai2nti(i):
    """
    # nt index is 0-based
    # aa index is 1-based
    # test
    # dict(zip(range(1,60),[aai2nti(i) for i in range(1,60)]))
    """
    return [(i - 1) * 3, (i - 1) * 3 + 1, (i - 1) * 3 + 2]


def check_pool_create(conn, poolname, logger):
    """Check the result of create storage pool.
    """
    pool_names = conn.listStoragePools()
    logger.info('poolnames is: %s ' % pool_names)
    try:
        pool_names.index(poolname)
    except ValueError:
        logger.info('check_pool_create %s storage pool pass' % poolname)
        return False
    return True


def factoring_visitor(state, primes):
    """Use with multiset_partitions_taocp to enumerate the ways a
    number can be expressed as a product of factors.  For this usage,
    the exponents of the prime factors of a number are arguments to
    the partition enumerator, while the corresponding prime factors
    are input here.

    Examples
    ========

    To enumerate the factorings of a number we can think of the elements of the
    partition as being the prime factors and the multiplicities as being their
    exponents.

    >>> primes, multiplicities = zip(*factorint(24).items())
    >>> primes
    (2, 3)
    >>> multiplicities
    (3, 1)
    >>> states = multiset_partitions_taocp(multiplicities)
    >>> [factoring_visitor(state, primes) for state in states]
    [[24], [8, 3], [12, 2], [4, 6], [4, 2, 3], [6, 2, 2], [2, 2, 2, 3]]

    """
    f, lpart, pstack = state
    factoring = []
    for i in range(lpart + 1):
        factor = 1
        for ps in pstack[f[i]:f[i + 1]]:
            if ps.v > 0:
                factor *= primes[ps.c] ** ps.v
        factoring.append(factor)
    return factoring


def set_parameter(store, parameter):
    """Add parameter to the specified store."""
    app, name = parameter.name.split('.')
    if app not in store:
        store[app] = {}
    value = parameter.value.decode('unicode_escape')
    if value == 'yes':
        value = True
    elif value == 'no':
        value = False
    elif value.isdigit():
        value = int(value)
    store[app][name.lower()] = value


def decode_data_item(row, group, byteorder) ->int:
    """Converts the bytes of data items into an integer."""
    return int.from_bytes(row[group], byteorder=byteorder)


def string_to_remote(string):
    """Return the name and the remote dictionary matching the input string.

    The input should be in the following form:
    REMOTENAME=USERNAME:PASSWORD@HOST

    Note that the PASSWORD field (along with the ':' separator) is optional.
    Return None if the input is not valid.
    """
    if '=' not in string:
        return None
    name, rstring = string.split('=', 1)
    if not name or '@' not in rstring:
        return None
    remote = {}
    lstring, remote['host'] = rstring.rsplit('@', 1)
    if not lstring or not remote['host']:
        return None
    if ':' in lstring:
        remote['username'], remote['password'] = lstring.split(':', 1)
    else:
        remote['username'] = lstring
    if not remote['username']:
        return None
    return name, remote


def null_removal_mode(dataframe, colname):
    """Replace nulls with the mode on dataframe[colname]"""
    col = dataframe[colname]
    dataframe[colname] = col.fillna(col.mode().get(0, None))
    return dataframe


def _to_distrf(broadening):
    """ Translate to qmmlpack distrf format."""
    return 'normal', (broadening,)


@staticmethod
def unigrams(words):
    """
            Input: a list of words, e.g., ["I", "am", "Denny"]
            Output: a list of unigram
        """
    assert type(words) == list
    return words


@staticmethod
def split_fixed_pattern_with_file_name(path):
    """
        Split path into fixed, masked parts and filename
        :param path: e.g
https://repo.example.com/artifactory/libs-cpp-release.snapshot/boost/1.60-pm/*.*.*/vc110/x86/win/boost.*.*.*.tar.gz
        :return:
            _path_fixed: https://repo.example.com/artifactory/libs-cpp-release.snapshot/boost/1.60-pm/
            _path_pattern: *.*.*/vc100/x86/win
            _file_name_pattern: boost.*.*.*.tar.gz
        """
    _first_pattern_pos = path.find('*')
    _path_separator_pos = path.rfind('/', 0, _first_pattern_pos)
    _path_fixed = path[:_path_separator_pos]
    _path_pattern = path[_path_separator_pos + 1:]
    _file_name_pattern_separator_pos = _path_pattern.rfind('/', 0)
    _file_name_pattern = _path_pattern[_file_name_pattern_separator_pos + 1:]
    if _path_pattern.find('*') == -1 or _file_name_pattern_separator_pos == -1:
        _path_pattern = ''
    else:
        _path_pattern = _path_pattern[:_file_name_pattern_separator_pos]
    return _path_fixed, _path_pattern, _file_name_pattern


def interpolate(shift: float=0.0):
    """Interpolate grease pencil strokes between frames

    :param shift: Shift, Bias factor for which frame has more influence on the interpolated strokes
    :type shift: float
    """
    pass


@classmethod
def parse_map_supported_features(cls, value: int):
    """The value parameter is uint32."""
    print('    RFU (31-23)', value >> 23)
    print('    Bit 22 = Message Forwarding', value >> 22 & 1)
    print('    Bit 21 = Owner Status', value >> 21 & 1)
    print('    Bit 20 = Conversationlisting', value >> 20 & 1)
    print('    Bit 19 = MapSupportedFeatures in Connect Request', value >>
        19 & 1)
    print('    Bit 18 = UTC Offset Timestamp Format', value >> 18 & 1)
    print('    Bit 17 = Notification Filtering', value >> 17 & 1)
    print('    Bit 16 = PBAP Contact Cross Reference', value >> 16 & 1)
    print('    Bit 15 = Participant Chat State Change Notification', value >>
        15 & 1)
    print('    Bit 14 = Participant Presence Change Notification', value >>
        14 & 1)
    print('    Bit 13 = Conversation Version Counters', value >> 13 & 1)
    print('    Bit 12 = Folder Version Counter', value >> 12 & 1)
    print('    Bit 11 = Database Identifier', value >> 11 & 1)
    print('    Bit 10 = Persistent Message Handles', value >> 10 & 1)
    print('    Bit 9 = MessagesListing Format Version 1.1', value >> 9 & 1)
    print('    Bit 8 = Message Format Version 1.1', value >> 8 & 1)
    print('    Bit 7 = Event Report Version 1.2', value >> 7 & 1)
    print('    Bit 6 = Extended Event Report 1.1', value >> 6 & 1)
    print('    Bit 5 = Instance Information Feature', value >> 5 & 1)
    print('    Bit 4 = Delete Feature', value >> 4 & 1)
    print('    Bit 3 = Uploading Feature', value >> 3 & 1)
    print('    Bit 2 = Browsing Feature', value >> 2 & 1)
    print('    Bit 1 = Notification Feature', value >> 1 & 1)
    print('    Bit 0 = Notification Registration Feature', value & 1)


def p_varargslist_17(p):
    """varargslist : fpdef EQUAL test varargslist_star COMMA STAR NAME COMMA DOUBLESTAR NAME"""
    p[4].args.insert(0, p[1])
    p[4].vararg = p[7][0]
    p[4].kwarg = p[10][0]
    p[4].defaults.insert(0, p[3])
    p[0] = p[4]


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

        :param PrimaryTeamRequestCanceledDetails val:
        :rtype: TeamMergeRequestCanceledExtraDetails
        """
    return cls('primary_team', val)


def open_truncate(filename):
    """Open the file name.  Return its handle."""
    return open(filename, 'wb+')


def p_import_as_names_2(p):
    """import_as_names : import_as_name COMMA"""
    p[0] = [p[1]]


def cr_uid_records(method):
    """ Decorate a traditional-style method that takes ``cr``, ``uid``, a
        recordset of model ``self`` as parameters. Such a method::

            @api.cr_uid_records
            def method(self, cr, uid, records, args):
                ...

        may be called in both record and traditional styles, like::

            # records = model.browse(cr, uid, ids, context)
            records.method(args)

            model.method(cr, uid, records, args)
    """
    method._api = 'cr_uid_records'
    return method


def check_error(input_number):
    """
	Check type errors in the input
	"""
    if type(input_number) is str or type(input_number) is float:
        raise Exception('Input must be int')
    try:
        input_number = int(input_number)
    except:
        raise Exception('n must be integer')


@staticmethod
def __vertex_json_id(vertex):
    """ A proxy property based access to vertices in current edge

        When edge is serialized to JSON object, no explicit object for its vertices are created, but rather they are referenced
        by special vertex json_ids.
        """
    if hasattr(vertex, 'json_id'):
        return vertex.json_id
    return hash(vertex)


def _format_timedelta(timedelta):
    """
    Return hh:mm:ss, or mm:ss if the amount of hours is zero.
    """
    result = '{0}'.format(timedelta).split('.')[0]
    if result.startswith('0:'):
        result = result[2:]
    return result


def loop_strand(cs):
    """
    Get the closed loop starting at crossing strand cs
    """
    strand = [cs]
    cs = cs[0].adjacent[(cs[1] + 2) % 4]
    while cs not in strand:
        strand.append(cs)
        cs = cs[0].adjacent[(cs[1] + 2) % 4]
    return strand


@classmethod
def from_str(cls, value: str) ->'TEmployee':
    """
        Construct from a JSON string (eg. a POST payload).

        Returns:
            Model instance based on the JSON string.

        """
    ...


def paths_range_update():
    """Update frame range for motion paths from the Scene’s current frame range

    """
    pass


def axesfontsize(ax, fontsize):
    """
    Change the font size for the title, x and y labels, and x and y tick labels for axis *ax* to *fontsize*.
    """
    items = [ax.title, ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels(
        ) + ax.get_yticklabels()
    for item in items:
        item.set_fontsize(fontsize)


def __deserialize_object(A, value):
    """Return a original value.

        :return: object.
        """
    return value


def add(strings, base_dir=None):
    """Add `strings` to the internal catalog.
        """


@classmethod
def paginate(cls, page, items):
    """
        Wraps Model.limit to make paginating easier.
        """
    return cls.limit(items, offset=page * items)


def min_max(iterable):
    """

    Get the min and max value of an iterable of numerics.

    :param iterable: any iterable data structure of numerics
    :type iterable: ``tuple``, ``list``, ``np.array``
    :return: (min(iterable), max(iterable))
    :rtype: ``tuple``
    """
    return min(iterable), max(iterable)


def chi2(y, f, sigma, normalize=True):
    """
    Return the chi-square value for a series of measured values y and
    uncertainties sigma that are described by model f.

                    y_i - f_i
    chi2 = sum_i( (-----------)^2 )
                     sigma_i

    Can be normalized by the number of entries.

    Inputs:
    -------
    y       :: np.array; values of the data which is to be described
    f       :: np.array; values predicted by the model
    sigma   :: np.array or float; uncertainties on values y
    normalize
            :: boolean; whether to divide the result by the length of y or not

    """
    res = sum(((y - f) / sigma) ** 2)
    res = res / len(y) if normalize else res
    return res


def get_api_name(intfspec):
    """Given an interface specification return an API name for it"""
    if len(intfspec) > 3:
        name = intfspec[3]
    else:
        name = intfspec[0].split('.')[-1]
    return name


def dump_np_dtype_dict(obj, h5f, **kwargs):
    """ dumps an np dtype object within a group"""
    h5f.create_dataset('data', data=obj)
    h5f.create_dataset('_data', data=['np_dtype'])


def exitSurvey():
    """Return the defined exit url"""


def unzip(iterable):
    """Unzips/transposes an iterable of tuples into a tuple of lists.

    WARNING: When given an empty iterable, this returns an empty list instead of a tuple. If you
    need a consistent interface then do something like this:

        left, right = list(unzip(two_columned_list)) or ([], [])

    :returns: an iterable of the unzipped input.
    """
    return map(list, zip(*iterable))


def is_empty(data):
    """
    Checks if an object, particularly :class:`Series` and :class:`DataFrame`,
    contains any values.

    .. note::
        ``DataFrame`` objects have an ``empty`` attribute, but ``Series`` don't.
        This function allows you to check both data structures using only one
        function.
    """
    try:
        return not bool(data)
    except ValueError:
        pass
    try:
        return data.empty
    except AttributeError:
        if data.tolist():
            return False
        return True


def float_from_sat(amount: int) ->float:
    """Return the float monetary value equivalent of a satoshi amount."""
    return float(amount / 100000000.0)


def stf_kolmogorov(r):
    """
    Kolmogorov structure function with r = (D/r0)
    """
    return 6.8839 * r ** (5.0 / 3)


def get_int(byte_array, signed=True):
    """
    Gets the specified integer from its byte array.
    This should be used by this module alone, as it works with big endian.

    :param byte_array: the byte array representing th integer.
    :param signed: whether the number is signed or not.
    :return: the integer representing the given byte array.
    """
    return int.from_bytes(byte_array, byteorder='big', signed=signed)


def get_utility(interface, name='', context=None):
    """Get the utility that provides interface

        Returns the nearest utility to the context that implements the
        specified interface.  If one is not found, raises
        ComponentLookupError.
        """


def SetupRuntimeAcls(acl, context):
    """
    Can be used during object initialisation to process acls.
    Acls can have a additional callback parameter called with the context
    to find out whetther to apply the single acl or not. The callback should return
    true or false. e.g. ::

        (Allow, "group:reader", "read", lambda context: context.meta.pool_state),

    or ::

        def check(context):
            return context.meta.pool_state

        (Allow, "group:reader", "read", check),

    :param acl:
    :param context:
    :return: tuple of acls to be stored as __acl__
    """
    processed = []
    for a in acl:
        if len(a) == 4:
            if a[3](*(context,)):
                processed.append(tuple(list(a[:3])))
            continue
        processed.append(tuple(a))
    return tuple(processed)


def setProps(properties, props, initialIndex=0):
    """
    Transform key, value from properties into props list items in the format
    expected by the HTTP POST request
    """
    i = initialIndex
    for key, val in properties.items():
        props['propertyId[%s]' % i] = key
        if hasattr(val, '__iter__'):
            j = 0
            props['propertyValue[%s]' % i] = val
        else:
            props['propertyValue[%s]' % i] = val
        i += 1


def weight_sample():
    """Use the mouse to sample a weight in the 3D view

    """
    pass


@staticmethod
def _filehash(url):
    """Extract MD5 hash from a download URL"""
    parts = url.partition('?')[0].split('/')
    parts.reverse()
    for part in parts:
        if len(part) == 32:
            return part
    return ''


@classmethod
def table_name_col(cls):
    """
        Returns the name of the metadata column used to store the feature table
        name.
        """
    return 'table_name'


def div(before, after):
    """Returns before divided by after.

        .. code-block:: xml

            <i>before / after</i>
        """
    return before / after


def hbytes(val):
    """Return pair value and unit."""
    unit = '', 'k', 'M', 'G', 'T', 'P'
    u = 0
    while val > 1000 and u < len(unit):
        u += 1
        val = val / 1024.0
    return val, unit[u]


def area_join(cursor: int=(0, 0)):
    """Join selected areas into new window

    :param cursor: Cursor
    :type cursor: int
    """
    pass


def init_legendre_rational(result, x, pos, cur_var):
    """Initialize the first and second order before starting the recursion.

    Mathematically this amounts to
    R_1 = (x-1)/(x+1)
    R_2 = 3/2 * (x-1)/(x+1)*P_1 - 1/2.

    .. note::

        The procedure on how an init function is built can be found in the
        docstring of the init function for
        standard polynomials *init_standard_poly*.

    :param result: Contains the observations along the first dimension
        and the function values of expansion w.r.t. an observation
        along the second dimension.
    :type result: numpy.ndarray

    :param x: The data to be expanded.
    :type x: numpy.ndarray

    :param pos: The index of the element to be computed, along the second
        dimension of result.
    :type int: int

    :param cur_var: The index of the current variable to be considered in the
        recursion. This value will have to be lower than x.shape[1].
    :type cur_var: int

    :returns: The index of the next element that will be computed in the
        recursion, the order of the next element, and the index of a special
        member. As we do not need a special element in Legendre rational
        functions, the index of the special element is set to None.
    :rtype: Tuple[int, int, int]
    """
    result[:, (pos)] = (x[:, (cur_var)] - 1.0) / (x[:, (cur_var)] + 1.0)
    result[:, (pos + 1)] = 3.0 / 2.0 * (x[:, (cur_var)] - 1.0) / (x[:, (
        cur_var)] + 1.0) * result[:, (pos)] - 1.0 / 2.0
    return pos + 2, 3, None


def glPushMatrix():
    """Push the current matrix stack

    """
    pass


def pred_filter_external_download_links(package_name, href, title):
    """
    Predicate used to filter external download links.  Currently, the only
    config value is ``allowed_extensions``.

    :param string package_name:
        Name of the Python package to retrieve and filter the simple page for.
    :param href:
        Absolute URL pointing to a downloadable file on a third-party web site.
    :param title:
        Text component of the link from the simple page.  This can include
        suffixes such as `download_url` and `home_page`, which can be used as
        part of the filter.
    :returns:
        :const:`True` if the external download link should be included in the
        output, :const:`False` otherwise.
    """
    return 'download_url' in title


def get_attribute(element_node, attribute_name, default_value=None):
    """Extract an attribute value from an element node.
    Does not fail if the attribute isn't present.
    @param element_node: the DOM element node containing the attribute.
    @param attribute_name: the name of the attribute.
    @param default_value: the value to return if the attribute is unspecified.
    @returns: the attribute value, or default_value (None) if it is unspecified.
    """
    node = element_node.attributes.get(attribute_name)
    if node:
        return node.value
    else:
        return default_value


def option_dict(options):
    """ Return a dictionary mapping option names to Option instances.
    """
    d = {}
    for option in options:
        d[option.name] = option
    return d


def update_kwargs(kwargs, **keyvalues):
    """Update dict with keys and values if keys do not already exist.

    >>> kwargs = {'one': 1, }
    >>> update_kwargs(kwargs, one=None, two=2)
    >>> kwargs == {'one': 1, 'two': 2}
    True

    """
    for key, value in keyvalues.items():
        if key not in kwargs:
            kwargs[key] = value


def values_to_deltas(past_values):
    """Turn a deque holding past gauge values into a list of deltas.
    These should be evenly distributed in time.
    """
    deltas = []
    prev_val = None
    for ival, (_, val) in enumerate(past_values):
        if ival > 0:
            deltas.append(val - prev_val)
        prev_val = val
    return deltas


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

        :param DeviceManagementEnabledType val:
        :rtype: EventType
        """
    return cls('device_management_enabled', val)


def coolwarm_transparent(max_alpha=0.7, opaque_perc=30, transparent_perc=8):
    """Modify the coolwarm color scale to have full transparency around the middle."""
    import numpy as np
    import matplotlib.pylab as pl
    from matplotlib.colors import ListedColormap
    cmap = pl.cm.coolwarm
    my_cmap = cmap(np.arange(cmap.N))
    _20perc = cmap.N * opaque_perc // 100
    midpoint = cmap.N // 2 + 1
    _10perc = cmap.N * transparent_perc // 100
    alpha = np.ones(cmap.N) * max_alpha
    alpha[midpoint - _10perc:midpoint + _10perc] = 0
    alpha[_20perc:midpoint - _10perc - 1] = np.linspace(max_alpha, 0, len(
        alpha[_20perc:midpoint - _10perc - 1]))
    alpha[midpoint + _10perc:-_20perc] = np.linspace(0, max_alpha, len(
        alpha[midpoint + _10perc:-_20perc]))
    my_cmap[:, (-1)] = alpha
    return ListedColormap(my_cmap)


@staticmethod
def return_last_value(retry_state):
    """Method used by the retryer to determine the return value of the
        retryer: we return the result of the last attempt.

        See method:`_set_retryer`.
        """
    return retry_state.outcome.result()


def is_singleton(dmrs, nodeid):
    """
    Check if a node has no links
    """
    return not any(dmrs.get_links(nodeid, itr=True))


def scale(quantity):
    """Primitive unit handling. Should probably use Piquant, quantities, or similar."""
    factors = {'ms': 1, 'mV': 1, 's': 1000, 'V': 1000, 'Hz': 1, 'nF': 1,
        'nA': 1, 'Mohm': 1, 'unknown': 1, 'unitless': 1}
    if quantity.units:
        return quantity.value * factors[quantity.units.name]
    else:
        return quantity.value


def ipv4_prefix_to_mask(prefix):
    """
    ipv4 cidr prefix to net mask

    :param prefix: cidr prefix , rang in (0, 32)
    :type prefix: int
    :return: dot separated ipv4 net mask code, eg: 255.255.255.0
    :rtype: str
    """
    if prefix > 32 or prefix < 0:
        raise ValueError('invalid cidr prefix for ipv4')
    else:
        mask = (1 << 32) - 1 ^ (1 << 32 - prefix) - 1
        eight_ones = 255
        mask_str = ''
        for i in range(0, 4):
            mask_str = str(mask & eight_ones) + mask_str
            mask = mask >> 8
            if i != 3:
                mask_str = '.' + mask_str
        return mask_str


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


def fill_element_0index(lhs=None, mhs=None, rhs=None, name=None, attr=None,
    out=None, **kwargs):
    """Fill one element of each line(row for python, column for R/Julia) in lhs according to index indicated by rhs and values indicated by mhs. This function assume rhs uses 0-based index.

    Parameters
    ----------
    lhs : NDArray
        Left operand to the function.
    mhs : NDArray
        Middle operand to the function.
    rhs : NDArray
        Right operand to the function.

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

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


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

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

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


@classmethod
def where(cls, **filters):
    """
        Shortcut for smart_query() method
        Example 1:
          Product.where(subject_ids__in=[1,2], grade_from_id=2).all()

        Example 2:
          filters = {'subject_ids__in': [1,2], 'grade_from_id': 2}
          Product.where(**filters).all()

        Example 3 (with joins):
          Post.where(public=True, user___name__startswith='Bi').all()
        """
    return cls.smart_query(filters)


def number(astring):
    """Convert a string into a float or integer
    Returns original string if it can't convert it.
    """
    try:
        num = float(astring)
        if num % 1 == 0:
            num = int(num)
        return num
    except ValueError:
        return astring


@classmethod
def _csv_filter_class_name(cls, filter_class, lookup_type):
    """
        Generate a suitable class name for a concrete filter class. This is not
        completely reliable, as not all filter class names are of the format
        <Type>Filter.

        ex::

            FilterSet._csv_filter_class_name(DateTimeFilter, 'in')

            returns 'DateTimeInFilter'

        """
    type_name = filter_class.__name__
    if type_name.endswith('Filter'):
        type_name = type_name[:-6]
    lookup_name = lookup_type.capitalize()
    return str('%s%sFilter' % (type_name, lookup_name))


@classmethod
def initAddons(cls, recurse=True):
    """
        Loads different addon modules for this class.  This method
        should not be overloaded in a subclass as it also manages the loaded
        state to avoid duplicate loads.  Instead, you can re-implement the
        _initAddons method for custom loading.

        :param      recurse | <bool>
        """
    key = '_{0}__addons_loaded'.format(cls.__name__)
    if getattr(cls, key, False):
        return
    cls._initAddons(recurse)
    setattr(cls, key, True)


@staticmethod
def _prefixize_uri_if_possible(uri, namespaces_dict):
    """
        It returns None it it doesnt find an adequate prefix

        :param uri:
        :param namespaces_dict:
        :return:
        """
    best_match = None
    for a_namespace in namespaces_dict:
        if uri.startswith(a_namespace):
            if best_match is None or len(best_match) < len(a_namespace):
                best_match = a_namespace
    return None if best_match is None else uri.replace(best_match,
        namespaces_dict[best_match] + ':')


@classmethod
def get_row_permission_prefix(cls):
    """
        Permission prefix specific to the row-level data for this batch type,
        e.g. ``'vendorcatalogs.rows'``.
        """
    return '{}.rows'.format(cls.get_permission_prefix())


def tagslist():
    """Return a list of tags ordered by revision."""


def fill_storage_map(compute_resources, storage_resources):
    """
    WARNING: The local disk resource name MUST be prefixed by the host
    resource name
    """
    storage_map = {}
    for res_id, compute in compute_resources.items():
        for storage_id, storage in storage_resources.items():
            if compute['name'] in storage['name']:
                storage_map[res_id] = storage_id
    return storage_map


def selection_set(select: bool=False):
    """Set cursor selection

    :param select: Select, Set selection end rather than cursor
    :type select: bool
    """
    pass


def lbs2kg(mass_lbs):
    """Convert mass value from lbs to kg"""
    return mass_lbs * 0.453592


def identify_first_last_gear_box_ratios(gear_box_ratios):
    """
    Identify the gear box ratio of first and last gears.

    :param gear_box_ratios:
        Gear box ratios [-].
    :type gear_box_ratios: dict[int | float]

    :return:
        Gear box ratio of first and last gears [-, -].
    :return: float, float
    """
    return gear_box_ratios[1], max(gear_box_ratios.items())[1]


@classmethod
def find_by_eid(cls, database, eid):
    """
        Finds a model by it's eid of a chunk of it, returns None if there are
        no models matching the eid chunk.

        :param db: sqlalchemy session to find the item.
        :param eid: eid to match, can be a partial.
        :returns: the model if its found None otherwise.
        """
    return database.query(cls).filter(cls.eid.like('{}%'.format(eid))).first()


def regression4sklearn():
    """基于 scikit-learn 的线性回归模型
    """
    from sklearn.linear_model import LinearRegression
    return LinearRegression(fit_intercept=False)


def _get_flavor_image_meta(key, flavor, image_meta, default=None):
    """Extract both flavor- and image-based variants of metadata."""
    flavor_key = ':'.join(['hw', key])
    image_key = '_'.join(['hw', key])
    flavor_policy = flavor.get('extra_specs', {}).get(flavor_key, default)
    image_policy = image_meta.properties.get(image_key, default)
    return flavor_policy, image_policy


def get_property(id, default=None):
    """ Return the specific property value
        """


def get_schema():
    """Schema structure of this resource

    :return: schema dictionary
    :rtype: dict
    """
    return {'mongo_indexes': {'index_tpl': [('_is_template', 1)],
        'index_name': [('name', 1)], 'index_host': [('host', 1), ('name', 1
        )]}, 'schema': {'schema_version': {'type': 'integer', 'default': 2},
        'hosts_total': {'schema_version': 1, 'title': 'Hosts count', 'type':
        'integer', 'default': 0}, 'hosts_not_monitored': {'schema_version':
        2, 'title': 'Hosts not monitored', 'type': 'integer', 'default': 0},
        'hosts_up_hard': {'schema_version': 1, 'title': 'Hosts Up hard',
        'type': 'integer', 'default': 0}, 'hosts_up_soft': {
        'schema_version': 1, 'title': 'Hosts Up soft', 'type': 'integer',
        'default': 0}, 'hosts_down_hard': {'schema_version': 1, 'title':
        'Hosts Down hard', 'type': 'integer', 'default': 0},
        'hosts_down_soft': {'schema_version': 1, 'title': 'Hosts Down soft',
        'type': 'integer', 'default': 0}, 'hosts_unreachable_hard': {
        'schema_version': 1, 'title': 'Hosts Unreachable hard', 'type':
        'integer', 'default': 0}, 'hosts_unreachable_soft': {
        'schema_version': 1, 'title': 'Hosts Unreachable soft', 'type':
        'integer', 'default': 0}, 'hosts_acknowledged': {'schema_version':
        1, 'title': 'Hosts ackowledged', 'type': 'integer', 'default': 0},
        'hosts_in_downtime': {'schema_version': 1, 'title':
        'Hosts in downtime', 'type': 'integer', 'default': 0},
        'hosts_flapping': {'schema_version': 1, 'title': 'Hosts flapping',
        'type': 'integer', 'default': 0}, 'services_total': {
        'schema_version': 1, 'title': 'Services count', 'type': 'integer',
        'default': 0}, 'services_not_monitored': {'schema_version': 2,
        'title': 'Services not monitored', 'type': 'integer', 'default': 0},
        'services_ok_hard': {'schema_version': 1, 'title':
        'Services Ok hard', 'type': 'integer', 'default': 0},
        'services_ok_soft': {'schema_version': 1, 'title':
        'Services Ok soft', 'type': 'integer', 'default': 0},
        'services_warning_hard': {'schema_version': 1, 'title':
        'Services Warning hard', 'type': 'integer', 'default': 0},
        'services_warning_soft': {'schema_version': 1, 'title':
        'Services Warning soft', 'type': 'integer', 'default': 0},
        'services_critical_hard': {'schema_version': 1, 'title':
        'Services Critical hard', 'type': 'integer', 'default': 0},
        'services_critical_soft': {'schema_version': 1, 'title':
        'Services Criticl soft', 'type': 'integer', 'default': 0},
        'services_unknown_hard': {'schema_version': 1, 'title':
        'Services Unknown hard', 'type': 'integer', 'default': 0},
        'services_unknown_soft': {'schema_version': 1, 'title':
        'Services Unknown soft', 'type': 'integer', 'default': 0},
        'services_unreachable_hard': {'schema_version': 1, 'title':
        'Services Unreachable hard', 'type': 'integer', 'default': 0},
        'services_unreachable_soft': {'schema_version': 1, 'title':
        'Services Unreachable soft', 'type': 'integer', 'default': 0},
        'services_acknowledged': {'schema_version': 1, 'title':
        'Services acknowledged', 'type': 'integer', 'default': 0},
        'services_in_downtime': {'schema_version': 1, 'title':
        'Services in downtime', 'type': 'integer', 'default': 0},
        'services_flapping': {'schema_version': 1, 'title':
        'Services flapping', 'type': 'integer', 'default': 0}, '_realm': {
        'schema_version': 1, 'title': 'Realm', 'comment':
        'Realm this element belongs to.', 'type': 'objectid',
        'data_relation': {'resource': 'realm', 'embeddable': True},
        'required': True}, '_sub_realm': {'schema_version': 1, 'title':
        'Sub-realms', 'comment':
        'Is this element visible in the sub-realms of its realm?', 'type':
        'boolean', 'default': True}, '_users_read': {'schema_version': 1,
        'type': 'list', 'schema': {'type': 'objectid', 'data_relation': {
        'resource': 'user', 'embeddable': True}}}}, 'schema_deleted': {
        'hosts_business_impact': {'schema_version': 2, 'title':
        'Hosts business impact', 'type': 'integer', 'default': 0},
        'services_business_impact': {'schema_version': 2, 'title':
        'Services business impact', 'type': 'integer', 'default': 0}}}


def get_string(value):
    """ Returns string representation of the value or empty string if None """
    if value:
        return str(value)
    else:
        return ''


def _unscale(x, C, b_scale):
    """
    Converts solution to _autoscale problem -> solution to original problem.
    """
    try:
        n = len(C)
    except TypeError as e:
        n = len(x)
    return x[:n] * b_scale * C


def parse_pid(pid):
    """ Parse the mesos pid string,

    :param pid: pid of the form "id@ip:port"
    :type pid: str
    :returns: (id, ip, port)
    :rtype: (str, str, str)
    """
    id_, second = pid.split('@')
    ip, port = second.split(':')
    return id_, ip, port


def _run_associations_arg_check(script, scriptconfig=None):
    """To be used with **associations to check given arguments."""
    pass


def update_param_vals(pars, prefix, **kwargs):
    """Update parameter values with keyword arguments."""
    for key, val in kwargs.items():
        pname = '%s%s' % (prefix, key)
        if pname in pars:
            pars[pname].value = val
    pars.update_constraints()
    return pars


def string_bool(value):
    """
    Returns False if the value is Falsish or "False", True if value is "True",
    or the original value otherwise.
    """
    if isinstance(value, bool):
        return value
    if not value or value == 'False':
        return False
    if value == 'True':
        return True
    return value


def get_mpi_env(envs):
    """get the slurm command for setting the environment
    """
    cmd = ''
    for k, v in envs.items():
        cmd += '%s=%s ' % (k, str(v))
    return cmd


@staticmethod
def delete(track_id):
    """Build a track add event.

		Parameters:
			track_id (str): A track ID.

		Returns:
			dict: A mutation dict.
		"""
    return {'delete': track_id}


def any_(f, iterable):
    """
    any :: Foldable t => (a -> Bool) -> t a -> Bool
    Determines whether any element of the structure satisfies the predicate.
    """
    for x in iterable:
        if f(x):
            return True
    return False


def centered_position(text: str, width: int) ->int:
    """
    Return the integer column to start writing a string /text/ at to
    center it within a window of width /width/.

    If width is less than 1 or the text is too long for the provided width,
    AssertionError is raised.

    >>> centered_position("Soren", 11)
    4

    >>> centered_position("Maud", 10)
    4

    >>> centered_position("Soren", 10)
    3

    >>> centered_position("Using it all", 12)
    0

    >>> centered_position("Using it all.", 13)
    0

    >>> centered_position("overwraps", 2)
    Traceback (most recent call last):
      ..
    AssertionError: text 'overwraps' can't fit in 2 columns

    >>> centered_position("Soren", -8)
    Traceback (most recent call last):
      ..
    AssertionError: width must be a positive number of columns
    """
    assert width > 0, 'width must be a positive number of columns'
    assert len(text) <= width, f"text '{text}' can't fit in {width} columns"
    if len(text) == width:
        return 0
    return (width - len(text)) // 2 + 1


def validNumber(valueToTest):
    """Determines if valueToTest is considered to be a number. This includes strings representing a number.
    If an int or float are passed then the answer is True.

    If a string is provided it is evaluated to only contain digits, sign and a decimal point. string evaluation does not yet take into account nationalization such as comma for seperating 1000's or any financial symbology

    :param valueToTest: variable to consider
    :type valueToTest: Any

    :return: True or False
    :rtype: bool

    """
    if isinstance(valueToTest, (int, float)):
        return True
    if isinstance(valueToTest, str):
        import re
        match = re.match('^[-0123456789.]*$', valueToTest)
        return match is not None
    return False


def report_email(path, link, severity, message, user):
    """
        This should email the site admin on the message
    :param path:     str of the sub url path
    :param link:     str of a link to the error
    :param severity: int of the severity 1-10
    :param message:  str of a message of the error
    :param user:     str of the user unique id
    :return:         None
    """
    pass


def create_text_header(lines):
    """Format textual header

    Create a "correct" SEG-Y textual header.  Every line will be prefixed with
    C## and there are 40 lines. The input must be a dictionary with the line
    number[1-40] as a key. The value for each key should be up to 76 character
    long string.

    Parameters
    ----------

    lines : dict
        `lines` dictionary with fields:

        - ``no`` : line number (`int`)
        - ``line`` : line (`str`)

    Returns
    -------

    text : str

    """
    rows = []
    for line_no in range(1, 41):
        line = ''
        if line_no in lines:
            line = lines[line_no]
        row = 'C{0:>2} {1:76}'.format(line_no, line)
        rows.append(row)
    rows = ''.join(rows)
    return rows


@classmethod
def from_geojson(cls, geojson):
    """
        Construct a Workflows GeometryCollection from a GeoJSON mapping.

        Note that the GeoJSON must be relatively small (under 10MiB of serialized JSON).

        Parameters
        ----------
        geojson: Dict

        Returns
        -------
        ~descarteslabs.workflows.GeometryCollection

        Example
        -------
        >>> from descarteslabs.workflows import GeometryCollection
        >>> geojson = {"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1, 2]}]}
        >>> gc = GeometryCollection.from_geojson(geojson)
        >>> gc.compute().__geo_interface__ # doctest: +SKIP
        {'type': 'GeometryCollection', 'geometries': [{'type': 'Point', 'coordinates': [1, 2]}]}
        """
    try:
        return cls._from_apply(cls._constructor, type=geojson['type'],
            geometries=geojson['geometries'])
    except KeyError:
        raise ValueError(
            "Expected a GeoJSON mapping containing the fields 'type' and 'geometries', but got {}"
            .format(geojson))


def have_same_entries(s1, s2):
    """Checks if two stencils are the same

    Examples:
        >>> stencil1 = [(1, 0), (-1, 0), (0, 1), (0, -1)]
        >>> stencil2 = [(-1, 0), (0, -1), (1, 0), (0, 1)]
        >>> have_same_entries(stencil1, stencil2)
        True
    """
    if len(s1) != len(s2):
        return False
    return len(set(s1) - set(s2)) == 0


@classmethod
def rc_notfound(cls, interface_type, resource_name=None):
    """Exception used when no resource class is provided and no default is found.
        """
    msg = ('Resource class for %s not provided and default not found.' %
        interface_type)
    if resource_name:
        msg = "Could not parse '%s'. %s" % (resource_name, msg)
    return cls(msg)


def context_set_float(data_path: str='', value: float=0.0, relative: bool=False
    ):
    """Set a context value

    :param data_path: Context Attributes, RNA context string
    :type data_path: str
    :param value: Value, Assignment value
    :type value: float
    :param relative: Relative, Apply relative to the current value (delta)
    :type relative: bool
    """
    pass


def michea_m(num_types, freq_spectrum):
    """Calculate Michéa’s M (1969, 1971).

    Used formula:
        .. math::
            M = rac{V}{D}

    Parameters:
        num_types (int): Absolute number of types.
        freq_spectrum (dict): Counted occurring frequencies.
    """
    return num_types / freq_spectrum[2]


@staticmethod
def getCmdlineForThread(pid, tid):
    """
        Returns the cmdline for a thread.
        :param pid: The pid of the parent process.
        :param tid: The tid of the thread.
        :return:
        """
    path = '/proc/{pid}/task/{tid}/cmdline'.format(pid=pid, tid=tid)
    with open(path, 'r') as fi:
        return fi.readline()


def is_unlinked_account(user):
    """
    Returns whether the provided user has authenticated via
    an InstitutionAccount not yet linked to a Uniauth profile.
    """
    return user.username and user.username.startswith('cas-')


def search_fields_to_dict(fields):
    """
    In ``SearchableQuerySet`` and ``SearchableManager``, search fields
    can either be a sequence, or a dict of fields mapped to weights.
    This function converts sequences to a dict mapped to even weights,
    so that we're consistently dealing with a dict of fields mapped to
    weights, eg: ("title", "content") -> {"title": 1, "content": 1}
    """
    if not fields:
        return {}
    try:
        int(list(dict(fields).values())[0])
    except (TypeError, ValueError):
        fields = dict(zip(fields, [1] * len(fields)))
    return fields


def grab_dims_from(struc):
    """Extract box information from CIF data

    Parameters
    ----------
    struc : list of lines
      the read cif file

    Returns
    -------
    dims : dict
      dict with keys a, b, c, alpha, beta, gamma
    """
    dims = dict()
    for line in struc:
        if line.lstrip().startswith('_cell_length_a'):
            dims['a'] = float(line.split()[1])
        elif line.lstrip().startswith('_cell_length_b'):
            dims['b'] = float(line.split()[1])
        elif line.lstrip().startswith('_cell_length_c'):
            dims['c'] = float(line.split()[1])
        elif line.lstrip().startswith('_cell_angle_alpha'):
            dims['alpha'] = float(line.split()[1])
        elif line.lstrip().startswith('_cell_angle_beta'):
            dims['beta'] = float(line.split()[1])
        elif line.lstrip().startswith('_cell_angle_gamma'):
            dims['gamma'] = float(line.split()[1])
        if len(dims) == 6:
            break
    else:
        raise ValueError('couldnt read dims')
    return dims


def p_expr_big_op_d(p):
    """p_expr_big_op_d : BIGOP DOWN LBRACE ID EQ expression RBRACE"""
    p[0] = p[1], p[4], p[6]


def difficulty_to_target(difficulty):
    """
    Calculate target from difficulty

    :param target: integer.
    :return: float.
    """
    return int(
        26959535291011309493156476344723991336010898738574164086137773096960 /
        difficulty)


@classmethod
def get_largest_left_eigs(cls, mx):
    """Get largest left eigenvectors and eigenvalues of matrix  `mx`

        Returns
        -------
        1-dimensional numpy array
            Eigenvalues
        2-dimensional numpy array
            Eigenvectors
        """
    vals, vecs = cls.get_largest_right_eigs(mx.T)
    return vals, vecs.T


def interpolate_bezier(knot1: 'mathutils.Vector', handle1:
    'mathutils.Vector', handle2: 'mathutils.Vector', knot2:
    'mathutils.Vector', resolution: int) ->list:
    """Interpolate a bezier spline segment.

    :param knot1: First bezier spline point.
    :type knot1: 'mathutils.Vector'
    :param handle1: First bezier spline handle.
    :type handle1: 'mathutils.Vector'
    :param handle2: Second bezier spline handle.
    :type handle2: 'mathutils.Vector'
    :param knot2: Second bezier spline point.
    :type knot2: 'mathutils.Vector'
    :param resolution: Number of points to return.
    :type resolution: int
    :return:  The interpolated points
    """
    pass


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


@classmethod
def get_format_string(cls):
    """See BzrDirFormat.get_format_string()."""
    return b'Bazaar-NG meta directory, format 1\n'


def get_max_release_version(version_id):
    """
    Returns current release version of 3ds Max

    :param version_id: int, release ID of the current Max version
    :return: 3ds Max release version
    :rtype: long

    .. code-block:: python

        import MaxPlus
        from dccutils.max import app

        version_id = MaxPlus.Application_Get3DSMAXVersion()
        print(app.get_max_release_version(version_id))
        # Result: 20000

    .. tip::
        Release 17000 == Max 2015, Release 179000 == 2016 alpha, etc

    .. seealso::
        `Max Plus Application Class: Get3DSMAXVersion
        <https://help.autodesk.com/view/3DSMAX/2018/ENU/?guid=__py_ref_class_max_plus_1_1_application_html>`_
    """
    version_number = version_id >> 16 & 65535
    return version_number


def _indexable(value, nullables):
    """Returns true if the value appears to be something that storable"""
    return value not in nullables


def intersect_point_tri(pt, tri_p1, tri_p2, tri_p3):
    """Takes 4 vectors: one is the point and the next 3 define the triangle.

	Parameters:
	pt (mathutils.Vector) – Point
	tri_p1 (mathutils.Vector) – First point of the triangle
	tri_p2 (mathutils.Vector) – Second point of the triangle
	tri_p3 (mathutils.Vector) – Third point of the triangle

	Returns: Point on the triangles plane or None if its outside the triangle

	Return type: mathutils.Vector or None"""
    from . import Vector
    return Vector


@staticmethod
def get_timestamp_column(expression, column_name):
    """Return the expression if defined, otherwise return column_name. Some
        engines require forcing quotes around column name, in which case this method
        can be overridden."""
    return expression or column_name


def theta_H_Sr_PK74(T, P):
    """c-c': hydrogen strontium [PK74]."""
    theta = -0.02
    valid = T == 298.15
    return theta, valid


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def remove_dupes(iterable):
    """
    Removes duplicate items from iterable object preserving original iterable order
    :param iterable: iterable
    :return: iterable
    """
    unique = set()
    new_iter = iterable.__class__()
    for item in iterable:
        if item not in unique:
            new_iter.append(item)
        unique.add(item)
    return new_iter


def to_codes(df):
    """Return a dataframe with all of the categoricals represented as codes"""
    df = df.copy()
    cat_cols = df.select_dtypes(['category']).columns
    df[cat_cols] = df[cat_cols].apply(lambda x: x.cat.codes)
    return df


def all_data_names(db: dict, record_id: int) ->list:
    """Return data names for a given record
    """
    if db['db'][str(record_id)] == {}:
        return []
    else:
        return_list = []
        for data_name in db['db'][str(record_id)]:
            return_list.append(data_name)
        return return_list