def get_test_method_name(test):
    """
    This method is used to return the full method name from a
    :class:`unittest.TestCase` instance.

    It is used as a default to define the "method_name" extra value
    passed in structured loggers. You can override the default by
    implementing a "get_test_method_name" method on you TestCase subclass.
    """
    return test._testMethodName


def with_metaclass(meta, *bases):
    """Create a base class with a metaclass."""
    return meta('NewBase', bases, {})


def _split_epi_lists(in_files, pe_dir, max_trs=50):
    """
    Split input EPIs and generate an output list of PEs.

    Inputs
    ------
    in_files : list of ``BIDSFile``s
        The EPI images that will be pooled into field estimation.
    pe_dir : str
        The phase-encoding direction of the IntendedFor EPI scan.
    max_trs : int
        Index of frame after which all volumes will be discarded
        from the input EPI images.

    """
    from os import path as op
    import nibabel as nb
    matched_pe = []
    opposed_pe = []
    for i, (epi_path, epi_pe) in enumerate(in_files):
        if epi_pe[0] == pe_dir[0]:
            img = nb.load(epi_path)
            if len(img.shape) == 3:
                splitnii = [img]
            else:
                splitnii = nb.four_to_three(img.slicer[:, :, :, :max_trs])
            for j, nii in enumerate(splitnii):
                out_name = op.abspath('dir-%s_tstep-%03d_pe-%03d.nii.gz' %
                    (epi_pe, i, j))
                nii.to_filename(out_name)
                if epi_pe == pe_dir:
                    matched_pe.append(out_name)
                else:
                    opposed_pe.append(out_name)
    if matched_pe:
        return [opposed_pe, matched_pe]
    return [opposed_pe]


@classmethod
def available_machine(cls):
    """Return a list of supported machines"""
    return cls.__available


def _import_module(name, package=None, warn=True, prefix='_py_', ignore='_'):
    """Try import all public attributes from module into global namespace.

    Existing attributes with name clashes are renamed with prefix.
    Attributes starting with underscore are ignored by default.

    Return True on successful import.

    """
    import warnings
    from importlib import import_module
    try:
        if not package:
            module = import_module(name)
        else:
            module = import_module('.' + name, package=package)
    except ImportError:
        if warn:
            warnings.warn('failed to import module %s' % name)
    else:
        for attr in dir(module):
            if ignore and attr.startswith(ignore):
                continue
            if prefix:
                if attr in globals():
                    globals()[prefix + attr] = globals()[attr]
                elif warn:
                    warnings.warn('no Python implementation of ' + attr)
            globals()[attr] = getattr(module, attr)
        return True


def Figure(description=''):
    """
    Adds numbered Figure HTML anchors. Link to them in MarkDown using: [to Figure 1](#Figure-1)
    """
    return object('Figure', description)


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


@staticmethod
def isTaurusConfig(x):
    """Checks if the given argument has the structure of a configdict

        :param x: (object) object to test

        :return: (bool) True if it is a configdict, False otherwise.
        """
    if not isinstance(x, dict):
        return False
    for k in ('__orderedConfigNames__', '__itemConfigurations__',
        'ConfigVersion', '__pickable__'):
        if k not in x:
            return False
    for k in x['__orderedConfigNames__']:
        if k not in x['__itemConfigurations__']:
            print('missing configuration for "%s" in %s' % (k, repr(x)))
    return True


@classmethod
def register_dict_to_class(cls, classname, converter):
    """
        Registers a custom converter function that creates objects from a dict with the given classname tag in it.
        The function is called with two parameters: the classname and the dictionary to convert to an instance of the class.
        """
    cls.__custom_dict_to_class_registry[classname] = converter


def istype(obj, check):
    """like isinstance(obj, check), but strict

    This won't catch subclasses.
    """
    if isinstance(check, tuple):
        for cls in check:
            if type(obj) is cls:
                return True
        return False
    else:
        return type(obj) is check


def ka_get_NC_col_names(data):
    """Get column names of category and numeric

        Parameters
        ----------
        data: dataframe

        Return:
        ----------
        numerics_cols: numeric column names
        category_cols: category column names

    """
    numerics_cols = data.select_dtypes(exclude=['O']).columns.tolist()
    category_cols = data.select_dtypes(include=['O']).columns.tolist()
    return numerics_cols, category_cols


def round_into_str_with_max_digits(number: float, digits_count: int) ->str:
    """
    Round the number with digits_count
    :param number: the number to round
    :param digits_count: the digit count
    :return: the rounded number
    """
    return '{:.{}f}'.format(round(number, digits_count), digits_count)


@staticmethod
def _nullify_flavor_description(flavor_info):
    """Helper method to nullify descriptions from a set of primitive
        flavors.

        Note that we don't remove the flavor description since that would
        make the versioned notification FlavorPayload have to handle the field
        not being set on the embedded instance.flavor.

        :param dict: dict of primitive flavor objects where the values are the
            flavors which get persisted in the instance_extra.flavor table.
        """
    for flavor in flavor_info.values():
        if flavor and 'description' in flavor['nova_object.data']:
            flavor['nova_object.data']['description'] = None


def _safe_single_attr(x):
    """Handle cleaning of attributes after extraction:
      - '.'s to indicate None
      - tuples where we expect a single value
    """
    if x is None or x is '.':
        return None
    elif isinstance(x, (list, tuple)):
        return x[0]
    else:
        return x


def is_last_char_digit(dev):
    """check whether device name ends with a digit"""
    if len(dev) >= 1:
        return dev[-1].isdigit()
    return False


def select_nodes_multi(molecules, selector):
    """
    Find the nodes that correspond to a selector among multiple molecules.

    Runs a selector over multiple molecules. The selector must be a function
    that takes a node dictionary as argument and returns ``True`` if the node
    should be selected. The selection is yielded as tuples of a molecule indice
    from the molecule list input, and a key from the molecule.

    Parameters
    ----------
    molecule: collections.abc.Iterable[Molecule]
        A list of molecules.
    selector: collections.abc.Callable
        A selector function.

    Yields
    ------
    tuple[int, collections.abc.Hashable]
        Molecule/key identifier for the selected nodes.
    """
    for molecule_idx, molecule in enumerate(molecules):
        for key, node in molecule.nodes.items():
            if selector(node):
                yield molecule_idx, key


def _interlace_passes(img):
    """
    Return the subimages of img that make up the seven Adam7 interlace passes.
    """
    pass1 = img[::8, ::8]
    pass2 = img[::8, 4::8]
    pass3 = img[4::8, ::4]
    pass4 = img[::4, 2::4]
    pass5 = img[2::4, ::2]
    pass6 = img[::2, 1::2]
    pass7 = img[1::2, :]
    return pass1, pass2, pass3, pass4, pass5, pass6, pass7


@staticmethod
def sta_get_tot_num_bits(parent_num_bits, gate_str_to_rads_list):
    """
        This static (sta) method returns the total number of qbits for the
        quantum circuit generated by this class, i.e., it returns the sum of
        the qbits used by each subcircuit.

        Parameters
        ----------
        parent_num_bits : int
        gate_str_to_rads_list : dict[str, list[float]]

        Returns
        -------
        int

        """
    num_subckts = len(gate_str_to_rads_list) * 2
    if 'prior' in gate_str_to_rads_list:
        num_subckts -= 1
    return num_subckts * (parent_num_bits + 1)


@staticmethod
def user_parse(data):
    """Parse information from provider."""
    for email in data.get('emails', []):
        if email.get('primary'):
            yield 'id', email.get('email')
            yield 'email', email.get('email')
            break


def make_object():
    """ Create a new empty object instance.

    Returns
    -------
    result : object
        A new object instance.

    """
    return object()


def ogr_geom(value):
    """Returns an ``ogr.Geometry`` instance from the given value.

    Raises a ``ValueError`` if no geometry can be created from the given value.

    This function accepts values in the following formats:

    * (x, y) (2-uple of integers),
    * WKT,
    * GeoJSON.

    """
    from osgeo import ogr
    ogr.UseExceptions()
    if isinstance(value, (tuple, list)):
        x, y = value
        geom = ogr.Geometry(ogr.wkbPoint)
        geom.SetCoordinateDimension(2)
        geom.AddPoint_2D(x, y)
        return geom
    for geom_function in [ogr.CreateGeometryFromWkt, ogr.CreateGeometryFromJson
        ]:
        try:
            return geom_function(value)
        except RuntimeError:
            pass
    raise ValueError('Invalid value for Geometry: {}'.format(value))


def varint(n):
    """Varint encoding."""
    data = b''
    while n >= 128:
        data += bytes([n & 127 | 128])
        n >>= 7
    data += bytes([n])
    return data


def corbsub(isub, x, y, corfun, *args):
    """
    Compute correlation for x[isub] and y[isub]
    isub is a vector of length n,
    a bootstrap sample from the sequence of integers
    0, 1, 2, 3, ..., n

    This function is used by other functions when computing
    bootstrap estimates.

    corfun is some correlation function
    """
    corbsub_results = corfun(x[isub], y[isub], *args)['cor']
    return corbsub_results


def fractionally_isomorphic_graphs(graph):
    """Returns an iterator over all graphs that are fractionally isomorphic to
    the specified graph, including the graph itself.

    `graph` must be an instance of :class:`networkx.Graph`.

    .. warning::

       This function is currently not implemented, since it is very difficult
       to write correct code that enumerates each graph that is fractionally
       isomorphic to a given graph (that is, it seems that the code will be
       very complicated).

    """
    raise NotImplementedError


def value(entry):
    """
    check if the string entry can

    Parameters
    ----------
    entry: str
        an entry of type str

    Returns
    -------
    bool
        True if the input can become an integer, False otherwise

    Notes
    -----
    returns 'type' for the entry 'type', although type is a code object

    """
    try:
        val = eval(entry)
        if isinstance(val, type):
            return entry
        else:
            return val
    except:
        return entry


@classmethod
def from_text(cls, data):
    """Construct an instance from text format.

        Parameters
        ----------
            data : str
                text such as ``'Head:Na:中文字'``.

        .. note::

            - ``'Head:Na:中文字'`` -> **role** = ``'Head'``, **pos** = ``'Na'``, **word** = ``'中文字'``
            - ``'Head:Na'``       -> **role** = ``'Head'``, **pos** = ``'Na'``, **word** = ``None``
            - ``'Na'``            -> **role** = ``None``,   **pos** = ``'Na'``, **word** = ``None``
        """
    if ':' in data:
        fields = data.split(':')
        return cls(*fields)
    return cls(pos=data)


def outlier_removal_median(dataframe, colname, low_cut, high_cut):
    """Replace outliers with the median on dataframe[colname]"""
    col = dataframe[colname]
    col_numerics = col.loc[col.apply(lambda x: isinstance(x, (int, float)) and
        (x >= low_cut and x <= high_cut))]
    dataframe.loc[col.apply(lambda x: isinstance(x, (int, float)) and (x <
        low_cut or x > high_cut)), colname] = col_numerics.median()
    return dataframe


def effective_principals(request):
    """
    A function that returns the value of the property
    :attr:`pyramid.request.Request.effective_principals`.

    .. deprecated:: 1.5
        Use :attr:`pyramid.request.Request.effective_principals` instead.
    """
    return request.effective_principals


def list_attached_role_policies(RoleName=None, PathPrefix=None, Marker=None,
    MaxItems=None):
    """
    Lists all managed policies that are attached to the specified IAM role.
    An IAM role can also have inline policies embedded with it. To list the inline policies for a role, use the  ListRolePolicies API. For information about policies, see Managed Policies and Inline Policies in the IAM User Guide .
    You can paginate the results using the MaxItems and Marker parameters. You can use the PathPrefix parameter to limit the list of policies to only those matching the specified path prefix. If there are no policies attached to the specified role (or none that match the specified path prefix), the action returns an empty list.
    See also: AWS API Documentation

    :example: response = client.list_attached_role_policies(
        RoleName='string',
        PathPrefix='string',
        Marker='string',
        MaxItems=123
    )

    :type RoleName: string
    :param RoleName: [REQUIRED]
            The name (friendly name, not ARN) of the role to list attached policies for.
            This parameter allows (per its regex pattern ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: _+=,.@-

    :type PathPrefix: string
    :param PathPrefix: The path prefix for filtering the results. This parameter is optional. If it is not included, it defaults to a slash (/), listing all policies.
            This paramater allows (per its regex pattern ) a string of characters consisting of either a forward slash (/) by itself or a string that must begin and end with forward slashes, containing any ASCII character from the ! (u0021) thru the DEL character (u007F), including most punctuation characters, digits, and upper and lowercased letters.

    :type Marker: string
    :param Marker: Use this parameter only when paginating results and only after you receive a response indicating that the results are truncated. Set it to the value of the Marker element in the response that you received to indicate where the next call should start.

    :type MaxItems: integer
    :param MaxItems: (Optional) Use this only when paginating results to indicate the maximum number of items you want in the response. If additional items exist beyond the maximum you specify, the IsTruncated response element is true .
            If you do not include this parameter, it defaults to 100. Note that IAM might return fewer results, even when there are more results available. In that case, the IsTruncated response element returns true and Marker contains a value to include in the subsequent call that tells the service where to continue from.

    :rtype: dict
    :return: {
        'AttachedPolicies': [
            {
                'PolicyName': 'string',
                'PolicyArn': 'string'
            },
        ],
        'IsTruncated': True|False,
        'Marker': 'string'
    }

    """
    pass


def multiline_merge(lines, current_event, re_after, re_before):
    """ Merge multi-line events based.

        Some event (like Python trackback or Java stracktrace) spawn
        on multiple line. This method will merge them using two
        regular expression: regex_after and regex_before.

        If a line match re_after, it will be merged with next line.

        If a line match re_before, it will be merged with previous line.

        This function return a list of complet event. Note that because
        we don't know if an event is complet before another new event
        start, the last event will not be returned but stored in
        current_event. You should pass the same current_event to
        successive call to multiline_merge. current_event is a list
        of lines whose belong to the same event.
    """
    events = []
    for line in lines:
        if re_before and re_before.match(line):
            current_event.append(line)
        elif re_after and current_event and re_after.match(current_event[-1]):
            current_event.append(line)
        else:
            if current_event:
                events.append('\n'.join(current_event))
            current_event.clear()
            current_event.append(line)
    return events


@classmethod
def _iter_all(cls):
    """query all documents and create instances.

        This can be very big, use this just for debugging!
        """
    for _id in cls.api.get(cls.__collection_name__)['documents']:
        yield cls.load(_id)


def project_opened(project):
    """This function is called after opening the project"""


def fixation_detection(x, y, time, missing=0.0, maxdist=25, mindur=50):
    """Detects fixations, defined as consecutive samples with an inter-sample distance of less than a set amount of pixels (disregarding missing data)

	Parameters
	----------
	x : array
		Gaze x positions
	y :	array
		Gaze y positions
	time : array
		Timestamps
	missing	: float
		Value to be used for missing data (default = 0.0)
	maxdist : int
		Maximal inter sample distance in pixels (default = 25)
	mindur : int
		Minimal duration of a fixation in milliseconds; detected fixation cadidates will be disregarded if they are below this duration (default = 100)

	Returns
	-------
	Sfix : list of lists
		Each containing [starttime]
	Efix : list of lists
		Each containing [starttime, endtime, duration, endx, endy]

	"""
    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 null_removal_mode_numeric(dataframe, colname):
    """Replace nulls with the modal numeric value on dataframe[colname]"""
    col = dataframe[colname]
    col_numerics = col.loc[col.apply(lambda x: isinstance(x, (int, float)))]
    dataframe[colname] = col.fillna(col_numerics.mode().get(0, None))
    return dataframe


def f_df(X):
    """
    F dans @see fn Arrow_Hurwicz
    """
    x, y = X
    f = x ** 2 + y ** 2 - x * y + y
    d = [x * 2 - y, y * 2 - x + 1]
    return f, d


def isConversion(job, sitepath, func):
    """
    Check if job is a document viewer conversion job
    """
    return sitepath == job.args[1] and job.args[4] == func


@staticmethod
def guess_flavour(line):
    """Guess which variant of PQR format this line is

        Parameters
        ----------
        line : str
          entire line of PQR file starting with ATOM/HETATM

        Returns
        -------
        flavour : str
          ORIGINAL / GROMACS / NO_CHAINID

        .. versionadded:: 0.18.0
        """
    fields = line.split()
    if len(fields) == 11:
        try:
            float(fields[-1])
        except ValueError:
            flavour = 'GROMACS'
        else:
            flavour = 'ORIGINAL'
    else:
        flavour = 'NO_CHAINID'
    return flavour


def get_description(repo_info):
    """Return repository description"""
    try:
        return repo_info.find('p').text.strip()
    except AttributeError:
        return


def get_attachment_ids():
    """Get the list of ids of all attachments of the context"""
    pass


@classmethod
def dispatch(cls, arguments, **kwargs):
    """Dispatch arguments parsed by docopt to the cmd with matching spec.

        :param arguments:
        :param kwargs:
        :return: exit_code
        """
    for spec, func in cls._specs:
        args = []
        options = list(filter(lambda k: k.startswith('-') and (arguments[k] or
            k in spec), arguments.keys()))
        cmds = list(filter(lambda k: not (k.startswith('-') or k.startswith
            ('<')) and arguments[k], arguments.keys()))
        args_spec = list(filter(lambda k: k.startswith('<'), spec))
        cmd_spec = list(filter(lambda k: not (k.startswith('-') or k.
            startswith('<')), spec))
        for element in spec:
            if element.startswith('-'):
                if element in options:
                    args.append(arguments.get(element, False))
                    options.remove(element)
            elif element.startswith('<') and not arguments.get(element
                ) is False:
                args.append(arguments.get(element))
                if element in args_spec:
                    args_spec.remove(element)
            elif element in cmds and element in cmd_spec:
                cmds.remove(element)
                cmd_spec.remove(element)
        if options:
            continue
        if cmds:
            continue
        if args_spec:
            continue
        if cmd_spec:
            continue
        exit_code = func(*args, **kwargs)
        return exit_code
    raise Exception('No implementation for spec: %s' % arguments)


def bump_attribute_nodes(children):
    """Move attribute nodes to the top of children list."""
    que = []
    for child in children:
        if child.label[0] == '*':
            yield child
        else:
            que.append(child)
    for child in que:
        yield child


@staticmethod
def get_abspath_to_pype(plugin, name):
    """Get absoulte path to pype Python script."""
    for pype in plugin.pypes:
        if name == pype.name:
            return pype.abspath
    return None


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 render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

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


def _format_config(log_config):
    """Format config parameters before logging them"""
    for k, v in log_config.items():
        if callable(v):
            if hasattr(v, '__qualname__') and hasattr(v, '__module__'):
                log_config[k] = f'{v.__module__}.{v.__qualname__}'
            else:
                log_config[k] = str(v)
        if isinstance(v, slice):
            log_config[k] = dict(slice_start=v.start, slice_step=v.step,
                slice_stop=v.stop)


def _prf_divide(numerator, denominator):
    """Performs division and handles divide-by-zero.

    On zero-division, sets the corresponding result elements to zero.
    """
    result = numerator / denominator
    mask = denominator == 0.0
    if not mask.any():
        return result
    result[mask] = 0.0
    return result


@staticmethod
def _merge_slices(match_slices):
    """Return a list of slice indices lists derived from `match_slices`
        with no overlaps."""
    match_slices.sort(key=lambda x: (x[0], -x[1]))
    merged_slices = [match_slices.pop(0)]
    for slice_indices in match_slices:
        last_end = merged_slices[-1][1]
        if slice_indices[0] <= last_end:
            if slice_indices[1] > last_end:
                merged_slices[-1][1] = slice_indices[1]
        else:
            merged_slices.append(slice_indices)
    return merged_slices


@staticmethod
def required_attributes():
    """
        Return a set of required fields for valid task creation.

        This tuple is checked to prevent unnecessary API calls.

        Seems that :id and :title attributes are required for now, where
        :id is set automatically.
        """
    return {'name'}


@staticmethod
def get_episode_prefix(matches, episode):
    """
        Return episode prefix: episodeMarker or episodeSeparator
        """
    return matches.previous(episode, index=0, predicate=lambda m: m.name in
        ('episodeMarker', 'episodeSeparator'))


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 solar_elevation_angle_refracted(h0):
    """
    Computes the solar elevation angle corrected for refraction

    .. math ::
       h_{0}^{ref} = h_{0} + \\Delta h_{0}^{ref}

    where

    .. math ::
        \\Delta h_{0}^{ref}=0.61359\\left(0.1594+1.123h_{0}+
        0.065656h_{0}^{2}\\right)/\\left(
        1+28.9344h_{0}+277.3971h_{0}^{2}\\right)

    Parameters
    ----------
    h0 : float
        solar elevation angle
        :math:`h_{0}`
        [degrees]

    Returns
    -------
    h0ref : float
        solar elevation angle corrected for refrection
        :math:`h_{0}^{ref}`
        [degrees]
    """
    delta_h0ref = 0.061359 * (0.1594 + 1.123 * h0 + 0.065656 * h0 ** 2) / (
        1 + 28.9344 * h0 + 277.3971 * h0 ** 2)
    h0ref = h0 + delta_h0ref
    return h0ref


def candidate_priority(candidate_component: int, candidate_type: str,
    local_pref: int=65535) ->int:
    """
    See RFC 5245 - 4.1.2.1. Recommended Formula
    """
    if candidate_type == 'host':
        type_pref = 126
    elif candidate_type == 'prflx':
        type_pref = 110
    elif candidate_type == 'srflx':
        type_pref = 100
    else:
        type_pref = 0
    return (1 << 24) * type_pref + (1 << 8) * local_pref + (256 -
        candidate_component)


def end_with_dot(msg, trailing_space=False):
    """
    Utility method to make sure that the provided string ends with dot and possibly with a space.

    The string is first right-stripped before adding the dot or dot space. If a dot is already present, it is
    not duplicated.

    If the string is empty, no dot nor space is added and an empty string is returned.

    :param msg: the string message to edit
    :param trailing_space: a boolean indicating if a space should be added after the trailing dot.
    :return:
    """
    msg = msg.rstrip()
    if len(msg) > 0:
        if msg[-1] != '.':
            msg = msg + ('. ' if trailing_space else '.')
        elif trailing_space:
            msg = msg + ' '
    return msg


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

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

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


def relu(x):
    """
    Used in conjunction with :class:`_NonLinearityLayer` to create a rectified
    linear unit layer.  The user does not instantiate this directly, but instead
    passes the class as the ``activation`` or ``weight_init`` argument to
    :class:`NN` either  when creating it or adding
    certain kinds of layers.

    :param float x: input to the rectified linear unit
    :return: 0 if x < 0, otherwise x
    :rtype: float
    """
    return x * (x > 0)


def broadcast_lesser_equal(lhs=None, rhs=None, name=None, attr=None, out=
    None, **kwargs):
    """Returns the result of element-wise **lesser than or equal to** (<=) comparison operation with broadcasting.

    Example::

       x = [[ 1.,  1.,  1.],
            [ 1.,  1.,  1.]]

       y = [[ 0.],
            [ 1.]]

       broadcast_lesser_equal(x, y) = [[ 0.,  0.,  0.],
                                       [ 1.,  1.,  1.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_logic.cc:L136

    Parameters
    ----------
    lhs : Symbol
        First input to the function
    rhs : Symbol
        Second input to the function

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

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


def init(**kwargs):
    """To get access to shell defaults dict"""
    global genders_file
    db_file = kwargs.get('defaults', {}).get('genders_file', None)
    if db_file:
        genders_file = db_file


def is_optional(action):
    """
    _actions either not possessing the `required` flag or implicitly optional
    through `nargs` being '*' or '?'
    """
    return not action.required or action.nargs in ['*', '?']


def _sort_imports(x):
    """Sort a list of tuples and strings, for use with sorted."""
    if isinstance(x, tuple):
        if x[1] == '__main__':
            return 0
        return x[1]
    return x


def build_html_listbox(lst, nme):
    """
    returns the html to display a listbox
    """
    res = '<select name="' + nme + '" multiple="multiple">\n'
    for l in lst:
        res += '    <option>' + str(l) + '</option>\n'
    res += '</select>\n'
    return res


def reverse_range(object):
    """Yields reverse range of object: list(reverse_range([1, 2, 3])) -> [2, 1, 0]."""
    return range(len(object) - 1, -1, -1)


def enlarge(n):
    """
    Param n is a number
    Function will enlarge the number
    """
    return n * 100


def initialize(org_name):
    """Set constant strings."""
    global NEXUS3_BASE
    global NEXUS3_CATALOG
    global NEXUS3_PROJ_NAME_HEADER
    global DOCKER_PROJ_NAME_HEADER
    NEXUS3_BASE = 'https://nexus3.{}.org:10002'.format(org_name)
    NEXUS3_CATALOG = NEXUS3_BASE + '/v2/_catalog'
    NEXUS3_PROJ_NAME_HEADER = 'Nexus3 Project Name'
    DOCKER_PROJ_NAME_HEADER = 'Docker HUB Project Name'


def do_nothing(*args):
    """
    Used by other functions as the default callback.
    """
    return


def submit_form(element):
    """Form submission work-around

    See https://github.com/SeleniumHQ/selenium/issues/3483 for details"""
    if element._w3c:
        form = element.find_element_by_xpath('./ancestor-or-self::form')
        element._parent.execute_script(
            "var e = arguments[0].ownerDocument.createEvent('Event');e.initEvent('submit', true, true);arguments[0].dispatchEvent(e);"
            , form)
    else:
        element.submit()


def _check_wts(weights, wts):
    """helper function for deprecating `wts`
    """
    if wts is not None:
        import warnings
        warnings.warn('`wts` method is deprecated. Use `weights` instead',
            DeprecationWarning)
    weights = weights if weights is not None else wts
    return weights


@classmethod
def clean(cls):
    """ Clean finished transfers"""
    return cls.client.request('/transfers/clean', method='POST')


def check_first_arg(first, *args):
    """
    Check first arg is true.

    :param first:
        First arg.
    :type first: T

    :return:
        If first arg is true.
    :rtype: bool
    """
    return bool(first)


def __call__(context):
    """Invoke the behavior-specific factory if the context can be adapted
        to IBehaviorAssignable and
        IBehaviorAssignable(context).supports(self.behavior.interface) returns
        True.
        """


def cache_property(key, empty, type):
    """Return a new property object for a cache header.  Useful if you
    want to add support for a cache extension in a subclass."""
    return property(lambda x: x._get_cache_value(key, empty, type), lambda
        x, v: x._set_cache_value(key, v, type), lambda x: x.
        _del_cache_value(key), 'accessor for %r' % key)


def get_runner(settings):
    """
    Return the appropriate VR runner command to use with the given settings.
    """
    return 'vrun' if settings.image_url is not None else 'vrun_precise'


def apply_id_map(continuations, id_map):
    """
    Applies an id map to a set of continuations organized in
    dictionaries: face -> [continuations]
    """
    if not isinstance(continuations, dict):
        for continuation in continuations:
            continuation.segid = id_map[continuation.segid]
    else:
        for face, conts in continuations.items():
            for continuation in conts:
                continuation.segid = id_map[continuation.segid]


@classmethod
def create_scraper(cls, sess=None, **kwargs):
    """
        Convenience function for creating a ready-to-go requests.Session (subclass) object.
        """
    scraper = cls()
    if sess:
        attrs = ['auth', 'cert', 'cookies', 'headers', 'hooks', 'params',
            'proxies', 'data']
        for attr in attrs:
            val = getattr(sess, attr, None)
            if val:
                setattr(scraper, attr, val)
    return scraper


def print_dict_dimensions(entities_db, title):
    """Print dimension of the dictionary"""
    total = 0
    for k1, v1 in entities_db.items():
        m = ''
        if isinstance(v1, dict):
            for k2, v2 in v1.items():
                m += f'{k2}({len(v2)}), '
                total += len(v2)
        else:
            m += f'{len(v1)} '
            total += len(v1)
        print(f'Total number of {k1}: {m} ')
    print(f'Total: {total} ')


@classmethod
def set_validlocations(cls, locations):
    """
        Set valid locations using list of dictionaries of form {'name': 'zmb', 'title', 'Zambia'}

        Args:
            locations (List[Dict]): List of dictionaries of form {'name': 'zmb', 'title', 'Zambia'}

        Returns:
            None
        """
    cls._validlocations = locations


def sbol_rule_10204(sbol_obj, arg):
    """The displayId property of an Identified object is OPTIONAL and MAY
    contain a String that MUST be composed of only alphanumeric or underscore
    characters and MUST NOT begin with a digit.
    """
    raise NotImplementedError('Not yet implemented')


def bech32_polymod(values):
    """Internal function that computes the Bech32 checksum."""
    generator = [996825010, 642813549, 513874426, 1027748829, 705979059]
    chk = 1
    for value in values:
        top = chk >> 25
        chk = (chk & 33554431) << 5 ^ value
        for i in range(5):
            chk ^= generator[i] if top >> i & 1 else 0
    return chk


@classmethod
def _to_str(cls, value):
    """Represents values either as string or None values as empty string.

        Args:
            value: a value

        """
    if value is None:
        return ''
    else:
        return str(value)


def language_custom_handler(language):
    """
    Manages special cases on a language object.
    """
    pass


def write_build(file, build):
    """Write the build to a tag file. Path must exists"""
    with open(file, 'w') as fd:
        fd.writelines([build])


def validate_vector_shape(name, shape, nrows, nobs):
    """
    Validate the shape of a possibly time-varying vector, or raise an exception

    Parameters
    ----------
    name : str
        The name of the vector being validated (used in exception messages)
    shape : array_like
        The shape of the vector to be validated. May be of size 1 or (if
        the vector is time-varying) 2.
    nrows : int
        The expected number of rows (elements of the vector).
    nobs : int
        The number of observations (used to validate the last dimension of a
        time-varying vector)

    Raises
    ------
    ValueError
        If the vector is not of the desired shape.
    """
    ndim = len(shape)
    if ndim not in [1, 2]:
        raise ValueError(
            'Invalid value for %s vector. Requires a 1- or 2-dimensional array, got %d dimensions'
             % (name, ndim))
    if not shape[0] == nrows:
        raise ValueError(
            'Invalid dimensions for %s vector: requires %d rows, got %d' %
            (name, nrows, shape[0]))
    if nobs is None and not (ndim == 1 or shape[-1] == 1):
        raise ValueError(
            'Invalid dimensions for %s vector: time-varying vectors cannot be given unless `nobs` is specified (implicitly when a dataset is bound or else set explicity)'
             % name)
    if ndim == 2 and not shape[1] in [1, nobs]:
        raise ValueError(
            'Invalid dimensions for time-varying %s vector. Requires shape (*,%d), got %s'
             % (name, nobs, str(shape)))


def __len__():
    """Return the number of valid terms, or sys.maxint."""


def lookup(cubeWithData, cubeWithMap, sharedIndex):
    """
    Returns the value of cubeWithData indexed by the index of cubeWithMap.
    cubeWithData must be indexed by sharedIndex and cubeWithData values must correspond to elements of sharedIndex.
    For example: Let's say you have a cube with an estimated inflation rate by Country ("inflation_rate" is the name of the cube; "country" is the name of the index) and you want to assign it to the corresponding Company depending on its location. On the other hand, there's a many-to-one map where each Company is allocated to a single Country ("country_to_company_allocation"). The sharedIndex, in this case, is Country ("country").
    As a result,
        cp.lookup( inflation_rate , country_to_company_allocation , country )
    will return the estimated inflation rate by Company.
    """
    _final_cube = ((cubeWithMap == sharedIndex) * cubeWithData).sum(sharedIndex
        )
    return _final_cube


def lm(*args, **kwargs):
    """
    shortcut of list(map(*args, **kwags))

    :param args:
    :param kwargs:
    :return:
    """
    return list(map(*args, **kwargs))


def _set_np_symbol_class(cls):
    """Set the numpy-compatible symbolic class to be cls"""
    global _np_symbol_cls
    _np_symbol_cls = cls


def terminate(mgr, qname='input'):
    """*DEPRECATED*. Use TFNode.DataFeed class instead."""
    raise Exception('DEPRECATED: Use TFNode.DataFeed class instead')


def mandatory(test_item):
    """A decorator to mark whole test cases or individual methods as
    mandatory.  If a mandatory test fails, DataTestRunner will stop
    immediately (this is similar to the ``--failfast`` command line
    argument behavior)::

        @datatest.mandatory
        class TestFileFormat(datatest.DataTestCase):
            def test_columns(self):
                ...
    """
    test_item.__datatest_mandatory__ = True
    return test_item


def equal(a, b):
    """Return True if ByteStores a == b.

    Not part of public interface.
    """
    a_bitlength = a.bitlength
    b_bitlength = b.bitlength
    if a_bitlength != b_bitlength:
        return False
    if not a_bitlength:
        assert b_bitlength == 0
        return True
    if a.offset % 8 > b.offset % 8:
        a, b = b, a
    a_bitoff = a.offset % 8
    b_bitoff = b.offset % 8
    a_byteoffset = a.byteoffset
    b_byteoffset = b.byteoffset
    a_bytelength = a.bytelength
    b_bytelength = b.bytelength
    da = a._rawarray
    db = b._rawarray
    if da is db and a.offset == b.offset:
        return True
    if a_bitoff == b_bitoff:
        bits_spare_in_last_byte = 8 - (a_bitoff + a_bitlength) % 8
        if bits_spare_in_last_byte == 8:
            bits_spare_in_last_byte = 0
        if a_bytelength == 1:
            a_val = (da[a_byteoffset] << a_bitoff & 255) >> 8 - a_bitlength
            b_val = (db[b_byteoffset] << b_bitoff & 255) >> 8 - b_bitlength
            return a_val == b_val
        if da[a_byteoffset] & 255 >> a_bitoff != db[b_byteoffset
            ] & 255 >> b_bitoff:
            return False
        b_a_offset = b_byteoffset - a_byteoffset
        for x in range(1 + a_byteoffset, a_byteoffset + a_bytelength - 1):
            if da[x] != db[b_a_offset + x]:
                return False
        return da[a_byteoffset + a_bytelength - 1
            ] >> bits_spare_in_last_byte == db[b_byteoffset + b_bytelength - 1
            ] >> bits_spare_in_last_byte
    assert a_bitoff != b_bitoff
    shift = b_bitoff - a_bitoff
    if b_bytelength == 1:
        assert a_bytelength == 1
        a_val = (da[a_byteoffset] << a_bitoff & 255) >> 8 - a_bitlength
        b_val = (db[b_byteoffset] << b_bitoff & 255) >> 8 - b_bitlength
        return a_val == b_val
    if a_bytelength == 1:
        assert b_bytelength == 2
        a_val = (da[a_byteoffset] << a_bitoff & 255) >> 8 - a_bitlength
        b_val = (db[b_byteoffset] << 8) + db[b_byteoffset + 1] << b_bitoff
        b_val &= 65535
        b_val >>= 16 - b_bitlength
        return a_val == b_val
    if (da[a_byteoffset] & 255 >> a_bitoff) >> shift != db[b_byteoffset
        ] & 255 >> b_bitoff:
        return False
    for x in range(1, b_bytelength - 1):
        b_val = db[b_byteoffset + x]
        a_val = (da[a_byteoffset + x - 1] << 8) + da[a_byteoffset + x] >> shift
        a_val &= 255
        if a_val != b_val:
            return False
    final_b_bits = (b.offset + b_bitlength) % 8
    if not final_b_bits:
        final_b_bits = 8
    b_val = db[b_byteoffset + b_bytelength - 1] >> 8 - final_b_bits
    final_a_bits = (a.offset + a_bitlength) % 8
    if not final_a_bits:
        final_a_bits = 8
    if b.bytelength > a_bytelength:
        assert b_bytelength == a_bytelength + 1
        a_val = da[a_byteoffset + a_bytelength - 1] >> 8 - final_a_bits
        a_val &= 255 >> 8 - final_b_bits
        return a_val == b_val
    assert a_bytelength == b_bytelength
    a_val = da[a_byteoffset + a_bytelength - 2] << 8
    a_val += da[a_byteoffset + a_bytelength - 1]
    a_val >>= 8 - final_a_bits
    a_val &= 255 >> 8 - final_b_bits
    return a_val == b_val


def vertex_group_assign():
    """Assign the selected vertices to the active vertex group

    """
    pass


def editsource():
    """Edit UI source code of the active button

    """
    pass


def select_line():
    """Select text by line

    """
    pass


@classmethod
def _merge_recursive(cls, config_a, config_b, path=None):
    """Merge second configuration into first configuration.
        https://stackoverflow.com/a/7205107
        """
    if path is None:
        path = []
    for key in config_b:
        if key in config_a:
            if isinstance(config_a[key], dict) and isinstance(config_b[key],
                dict):
                cls._merge_recursive(config_a[key], config_b[key], path + [
                    str(key)])
            elif config_a[key] == config_b[key]:
                pass
            elif config_b[key] is None:
                pass
            else:
                dpath = '.'.join(path + [str(key)])
                raise Exception(f'configuration conflict at {dpath}')
        else:
            config_a[key] = config_b[key]
    return config_a


def DFReader_is_text_log(filename):
    """return True if a file appears to be a valid text log"""
    with open(filename, 'r') as f:
        ret = f.read(8000).find('FMT, ') != -1
    return ret


@staticmethod
def _alert_summary(alert_row):
    """Return summarized string of alert properties."""
    if 'TI Risk' in alert_row:
        return (f'{alert_row.StartTimeUtc} - {alert_row.AlertName}' +
            f' - ({alert_row.CompromisedEntity}) ' +
            f' - [id:{alert_row.SystemAlertId}]' +
            f" - TI Risk: {alert_row['TI Risk']}")
    return (f'{alert_row.StartTimeUtc} - {alert_row.AlertName}' +
        f' - ({alert_row.CompromisedEntity}) ' +
        f' - [id:{alert_row.SystemAlertId}]')


def _strtobool(val):
    """Convert a string representation of truth to true (1) or false (0).

    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
    are 'n', 'no', 'f', 'false', 'off', '0' and ''.  Raises ValueError if
    'val' is anything else.
    """
    val = val.lower()
    if val in ('y', 'yes', 't', 'true', 'on', '1'):
        return 1
    elif val in ('n', 'no', 'f', 'false', 'off', '0', ''):
        return 0
    else:
        raise ValueError('Invalid truth value: {0}'.format(val))


def is_int(obj, digit=False):
    """Check if obj is int typeable.

    Args:
        obj (:obj:`object`): object to check
        digit (:obj:`bool`, optional): default ``False`` -
            * if ``True`` obj must be (str/bytes where isdigit is True) or int
            * if ``False`` obj must be int

    Returns:
        :obj:`bool`: bool reflecting if obj is int typeable
    """
    if digit:
        if (isinstance(obj, str) or isinstance(obj, bytes)) and obj.isdigit():
            return True
    return not isinstance(obj, bool) and isinstance(obj, int)


def set_quiet(is_quiet):
    """Sets whether the messaging system is running in quiet mode. Quiet mode
    only prints messages with explicit verbosity specified. If verbosity==None
    and quiet==True, any message with level >= 0 is printed.
    """
    global quiet
    quiet = is_quiet


def enable_widget(widget, enable=True):
    """Set disabled on widget"""
    widget.disabled = not enable


def get_backlog(user_info_db):
    """returns the backlog"""
    from src.praxxis.sqlite import connection
    conn = connection.create_connection(user_info_db)
    cur = conn.cursor()
    getbacklog = 'SELECT LocalCopy, SceneID, Operation FROM "TelemBacklog"'
    cur.execute(getbacklog)
    conn.commit()
    toSend = cur.fetchall()
    conn.close()
    return toSend


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

        :param OutdatedLinkViewReportFailedType val:
        :rtype: EventType
        """
    return cls('outdated_link_view_report_failed', val)


def mod_square(c):
    """Returns the module square of a complex number, which is defined as c•c*, where c* is the complex conjugate of `c`"""
    return (c * c.conjugate()).real


def version_number_str(major, minor=0, patch=0, prerelease=None, build=None):
    """
    Takes the parts of a semantic version number, and returns a nicely
    formatted string.
    """
    version = str(major) + '.' + str(minor) + '.' + str(patch)
    if prerelease:
        if prerelease.startswith('-'):
            version = version + prerelease
        else:
            version = version + '-' + str(prerelease)
    if build:
        if build.startswith('+'):
            version = version + build
        else:
            version = version + '+' + str(build)
    return version


def optimizeAngle(angle):
    """
    Because any rotation can be expressed within 360 degrees
    of any given number, and since negative angles sometimes
    are one character longer than corresponding positive angle,
    we shorten the number to one in the range to [-90, 270[.
    """
    if angle < 0:
        angle %= -360
    else:
        angle %= 360
    if angle >= 270:
        angle -= 360
    elif angle < -90:
        angle += 360
    return angle


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

    """
    pass


def update_user_attributes(UserAttributes=None, AccessToken=None):
    """
    Allows a user to update a specific attribute (one at a time).
    See also: AWS API Documentation

    :example: response = client.update_user_attributes(
        UserAttributes=[
            {
                'Name': 'string',
                'Value': 'string'
            },
        ],
        AccessToken='string'
    )

    :type UserAttributes: list
    :param UserAttributes: [REQUIRED]
            An array of name-value pairs representing user attributes.
            For custom attributes, you must prepend the custom: prefix to the attribute name.
            (dict) --Specifies whether the attribute is standard or custom.
            Name (string) -- [REQUIRED]The name of the attribute.
            Value (string) --The value of the attribute.

    :type AccessToken: string
    :param AccessToken: [REQUIRED]
            The access token for the request to update user attributes.

    :rtype: dict
    :return: {
        'CodeDeliveryDetailsList': [
            {
                'Destination': 'string',
                'DeliveryMedium': 'SMS'|'EMAIL',
                'AttributeName': 'string'
            },
        ]
    }

    """
    pass


def convex_hull(delete_unused: bool=True, use_existing_faces: bool=True,
    make_holes: bool=False, join_triangles: bool=True, face_threshold:
    float=0.698132, shape_threshold: float=0.698132, uvs: bool=False, vcols:
    bool=False, seam: bool=False, sharp: bool=False, materials: bool=False):
    """Enclose selected vertices in a convex polyhedron

    :param delete_unused: Delete Unused, Delete selected elements that are not used by the hull
    :type delete_unused: bool
    :param use_existing_faces: Use Existing Faces, Skip hull triangles that are covered by a pre-existing face
    :type use_existing_faces: bool
    :param make_holes: Make Holes, Delete selected faces that are used by the hull
    :type make_holes: bool
    :param join_triangles: Join Triangles, Merge adjacent triangles into quads
    :type join_triangles: bool
    :param face_threshold: Max Face Angle, Face angle limit
    :type face_threshold: float
    :param shape_threshold: Max Shape Angle, Shape angle limit
    :type shape_threshold: float
    :param uvs: Compare UVs
    :type uvs: bool
    :param vcols: Compare VCols
    :type vcols: bool
    :param seam: Compare Seam
    :type seam: bool
    :param sharp: Compare Sharp
    :type sharp: bool
    :param materials: Compare Materials
    :type materials: bool
    """
    pass


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

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

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


def _integerq(x):
    """ Returns true if x is integer """
    return int(x) == x


def tcount(g):
    """Returns the amount of nodes in g that have a non-Clifford phase."""
    if not hasattr(g, 'vertices'):
        return g.tcount()
    count = 0
    phases = g.phases()
    for v in g.vertices():
        if phases[v] != 0 and phases[v].denominator > 2:
            count += 1
    return count


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

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


def chef_download_url(name, version, registry=
    'https://supermarket.chef.io/cookbooks'):
    """
    Return an Chef cookbook download url given a name, version, and base registry URL.

    For example:
    >>> c = chef_download_url('seven_zip', '1.0.4')
    >>> assert c == u'https://supermarket.chef.io/cookbooks/seven_zip/versions/1.0.4/download'
    """
    registry = registry.rstrip('/')
    return '{registry}/{name}/versions/{version}/download'.format(**locals())


def calculate_gear_box_temperature(gear_box_heat, starting_temperature,
    equivalent_gear_box_heat_capacity, thermostat_temperature):
    """
    Calculates the gear box temperature not finalized [°C].

    :param gear_box_heat:
        Gear box heat [W].
    :type gear_box_heat: float

    :param starting_temperature:
        Starting temperature [°C].
    :type starting_temperature: float

    :param equivalent_gear_box_heat_capacity:
        Equivalent gear box capacity (from cold start model) [W/°C].
    :type equivalent_gear_box_heat_capacity: float

    :param thermostat_temperature:
        Engine thermostat temperature [°C].
    :type thermostat_temperature: float

    :return:
        Gear box temperature not finalized [°C].
    :rtype: float
    """
    temp = starting_temperature
    temp += gear_box_heat / equivalent_gear_box_heat_capacity
    return min(temp, thermostat_temperature - 5.0)


def asPairs():
    """
        Represent the enumeration as a sequence of pairs.

        @rtype: C{list} of 2-C{tuple}s
        @return: A sequence of C{(value, description)}
        """


def add_feature(input_dict):
    """
    Add a feature to Annotated Document Corpus.

    :param adc: Annotated Document Corpus
    :param feature_name: the name of new feature
    :param feature_values: list of features values
    :param feature_value_prefix:  prefix to feature value

    :return: new adc
    """
    for i, document in enumerate(input_dict['adc'].documents):
        document.features[input_dict['feature_name']] = input_dict[
            'feature_value_prefix'] + str(input_dict['feature_values'][i])
    return {'adc': input_dict['adc']}


def valid_int(param, allow_zero=False, allow_negative=False):
    """Validate that param is an integer, raise an exception if not"""
    pt = param
    try:
        pt += 1
    except TypeError:
        raise TypeError("Expected integer but found argument of type '{}'".
            format(type(param)))
    if not allow_negative and param < 0:
        raise ValueError("Expected nonnegative number but got '{}'".format(
            param))
    if not allow_zero and param == 0:
        raise ValueError("Expected nonzero number but got '{}'".format(param))
    return param


@classmethod
def _check_addable(cls, obj, tagname):
    """Check if the given tagname is addable to the given obj
        """
    pass


def Nu_Griem(Re, Pr, H=None):
    """Calculates internal convection Nusselt number for turbulent vertical
    upward flow in a pipe under supercritical conditions according to [1]_,
    also shown in [2]_, [3]_ and [4]_. Has complicated rules regarding where
    properties should be evaluated.

    .. math::
        Nu_m = 0.0169Re_b^{0.8356} Pr_{sel}^{0.432}\\omega

    Parameters
    ----------
    Re : float
        Reynolds number as explained below, [-]
    Pr : float
        Prandtl number as explained below, [-]
    H : float, optional
        Enthalpy of water (if the fluid is water), [J/kg]

    Returns
    -------
    Nu : float
        Nusselt number as explained below, [-]

    Notes
    -----
    w is calculated as follows, for water only, with a reference point from
    the 1967-IFC formulation. It is set to 1 if H is not provided:
    if Hb < 1.54E6 J/kg, w = 0.82; if Hb > 1.74E6 J/kg, w = 1; otherwise
    w = 0.82 + 9E-7*(Hb-1.54E6).

    To determine heat capacity to be used, Cp should be calculated at 5 points,
    and the lowest three points should be averaged.
    The five points are: Tw, (Tw+Tf)/2, Tf, (Tb+Tf)/2, Tb.

    Viscosity should be the bulk viscosity.
    Thermal conductivity should be the average of the bulk and wall values.
    Density should be the bulk density.

    [2]_ states this correlation was developed with D = 10, 14, and 20 mm,
    P from 22 to 27 MPa, G from 300 to 2500 kg/m^2/s, and q from
    200 to 700 kW/m^2. It was ranked 6th among the 14 correlations reviewed for
    enhanced heat transfer, with a MAD of 13.8%, and 6th overall for the three
    heat transfer conditions with a overall MAD of 14.8%. [3]_ ranked it 8th
    of 14 correlations for the three heat transfer conditions.

    [2]_ has an almost complete description of the model; both [3]_ and [4]_
    simplify it.

    Examples
    --------
    >>> Nu_Griem(1E5, 1.2)
    275.4818576600527

    References
    ----------
    .. [1] Griem, H. "A New Procedure for the Prediction of Forced Convection
       Heat Transfer at near- and Supercritical Pressure." Heat and Mass
       Transfer 31, no. 5 (1996): 301-5. doi:10.1007/BF02184042.
    .. [2] Chen, Weiwei, Xiande Fang, Yu Xu, and Xianghui Su. "An Assessment of
       Correlations of Forced Convection Heat Transfer to Water at
       Supercritical Pressure." Annals of Nuclear Energy 76 (February 2015):
       451-60. doi:10.1016/j.anucene.2014.10.027.
    .. [3] Yu, Jiyang, Baoshan Jia, Dan Wu, and Daling Wang. "Optimization of
       Heat Transfer Coefficient Correlation at Supercritical Pressure Using
       Genetic Algorithms." Heat and Mass Transfer 45, no. 6 (January 8, 2009):
       757-66. doi:10.1007/s00231-008-0475-4.
    .. [4] Jäger, Wadim, Victor Hugo Sánchez Espinoza, and Antonio Hurtado.
       "Review and Proposal for Heat Transfer Predictions at Supercritical
       Water Conditions Using Existing Correlations and Experiments." Nuclear
       Engineering and Design, (W3MDM) University of Leeds International
       Symposium: What Where When? Multi-dimensional Advances for Industrial
       Process Monitoring, 241, no. 6 (June 2011): 2184-2203.
       doi:10.1016/j.nucengdes.2011.03.022.
    """
    if H:
        if H < 1540000.0:
            w = 0.82
        elif H > 1740000.0:
            w = 1
        else:
            w = 0.82 + 9e-07 * (H - 1540000.0)
    else:
        w = 1
    Nu = 0.0169 * Re ** 0.8356 * Pr ** 0.432 * w
    return Nu


def sapm_cell_from_module(module_temperature, poa_global, deltaT, irrad_ref
    =1000):
    """
    Calculate cell temperature from module temperature using the Sandia Array
    Performance Model.

    See [1]_ for details on the Sandia Array Performance Model.

    Parameters
    ----------
    module_temperature : numeric
        Temperature of back of module surface [C].

    poa_global : numeric
        Total incident irradiance [W/m^2].

    deltaT : float
        Parameter :math:`\\Delta T` in :eq:`sapm2` [C].

    irrad_ref : float, default 1000
        Reference irradiance, parameter :math:`E_{0}` in
        :eq:`sapm2` [W/m^2].

    Returns
    -------
    numeric, values in degrees C.

    Notes
    -----
    The model for cell temperature :math:`T_{C}` is given by Eq. 12 in [1]_.

    .. math::
       :label: sapm2

       T_{C} = T_{m} + \\frac{E}{E_{0}} \\Delta T

    The module back surface temperature :math:`T_{m}` is implemented in
    :py:func:`~pvlib.temperature.sapm_module`.

    Model parameters depend both on the module construction and its mounting.
    Parameter sets are provided in [1]_ for representative modules and
    mounting, and are coded for convenience in
    ``pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS``.

    +---------------+----------------+-------+---------+---------------------+
    | Module        | Mounting       | a     | b       | :math:`\\Delta T [C]`|
    +===============+================+=======+=========+=====================+
    | glass/glass   | open rack      | -3.47 | -0.0594 | 3                   |
    +---------------+----------------+-------+---------+---------------------+
    | glass/glass   | close roof     | -2.98 | -0.0471 | 1                   |
    +---------------+----------------+-------+---------+---------------------+
    | glass/polymer | open rack      | -3.56 | -0.075  | 3                   |
    +---------------+----------------+-------+---------+---------------------+
    | glass/polymer | insulated back | -2.81 | -0.0455 | 0                   |
    +---------------+----------------+-------+---------+---------------------+

    References
    ----------
    .. [1] King, D. et al, 2004, "Sandia Photovoltaic Array Performance
       Model", SAND Report 3535, Sandia National Laboratories, Albuquerque,
       NM.

    See also
    --------
    sapm_cell
    sapm_module
    """
    return module_temperature + poa_global / irrad_ref * deltaT


def doc_handle_async(event):
    """Documentation for handlers bound to ``evt.EVT_ASYNC_OPS``.

    User implementation of this event handler is optional. If a handler is
    not implemented and bound to ``evt.EVT_ASYNC_OPS`` then no response to the
    Asynchronous Operations Window
    Negotiation item will be sent in reply to the association requestor.

    Because *pynetdicom* doesn't support asynchronous operations if the
    handler is implemented then the response to the asynchronous
    operations window negotiation request will always return the default
    number of operations invoked/performed, (1, 1), regardless of what
    values are returned by the handler.

    **Event**

    ``evt.EVT_ASYNC_OPS``

    Parameters
    ----------
    event : events.Event
        The event representing an association request being received which
        contains an Asynchronous Operations Window Negotiation item. Event
        attributes are:

        * ``assoc`` : the
          :py:class:`association <pynetdicom.association.Association>`
          that received the Asynchronous Operations Window Negotiation request.
        * ``event`` : the event that occurred as ``namedtuple``.
        * ``invoked`` : the *Maximum Number Operations Invoked* parameter
          value of the Asynchronous Operations Window Negotiation request as
          an ``int``. If the value is 0 then an unlimited number of
          invocations are requested.
        * ``performed`` : the *Maximum Number Operations Performed*
          parameter value of the Asynchronous Operations Window Negotiation
          request as an ``int``. If the value is 0 then an unlimited number
          of performances are requested.
        * ``timestamp`` : the
          `date and time <https://docs.python.org/3/library/datetime.html#datetime-objects>`_
          that the negotiation request was processed by the ACSE.

    Returns
    -------
    int, int
        The (maximum number operations invoked, maximum number operations
        performed). A value of 0 indicates that an unlimited number of
        operations is supported. As asynchronous operations are not
        supported the returned values will be ignored and (1, 1) sent in
        response.
    """
    pass


@classmethod
def xor(cls, family):
    """xor of a family of Lebesgue sets."""
    return cls.operate(cls.XOR, family)


def check_log_settings(args):
    """
    Quick method to check the consistency of log settings
    from the namespace.
    :param args: a Namespace
    :return: args
    """
    if args.log == 'stderr':
        args.json_conf['log_settings']['log'] = None
    elif args.log is not None:
        args.json_conf['log_settings']['log'] = args.log
    if args.log_level is not None:
        args.json_conf['log_settings']['log_level'] = args.log_level
    elif args.verbose is True:
        args.json_conf['log_settings']['log_level'] = 'DEBUG'
    elif args.noverbose is True:
        args.json_conf['log_settings']['log_level'] = 'ERROR'
    return args


def get_barcode2bcr1r2(dbarcodes, bc2seq, oligo2seq):
    """
    row for:   RC_for_index
    col rev:   RC_rev_index
    plate for: PE1_index
    plate rev: PE2_index
    """
    import re
    dbarcodes.index = range(len(dbarcodes))
    barcode2bcr1r2 = {}
    barcode2primersr1r2 = {}
    barcode2fragsr1r2 = {}
    barcode2regsr1r2 = {}
    for i in dbarcodes.drop_duplicates(subset=['barcode']).index:
        x = dbarcodes.iloc[(i), :]
        barcode = x['barcode']
        barcode2bcr1r2[barcode] = (
            f"{bc2seq[str(x['plate for'])]}{bc2seq[str(x['row for'])]}{bc2seq[str(x['plate rev'])]}{bc2seq[str(x['col rev'])]}"
            )
        barcode2primersr1r2[barcode] = [
            f"{bc2seq[str(x['plate for'])]}{oligo2seq['plate_fivep_sticky']}{bc2seq[str(x['row for'])]}{oligo2seq['RC_fivep_sticky']}"
            ,
            f"{bc2seq[str(x['plate rev'])]}{oligo2seq['plate_threep_sticky']}{bc2seq[str(x['col rev'])]}{oligo2seq['RC_threep_sticky']}"
            ]
        barcode2fragsr1r2[barcode] = [
            f"<{bc2seq[str(x['plate for'])]}><{oligo2seq['plate_fivep_sticky']}><{bc2seq[str(x['row for'])]}><{oligo2seq['RC_fivep_sticky']}"
            ,
            f"<{bc2seq[str(x['plate rev'])]}><{oligo2seq['plate_threep_sticky']}><{bc2seq[str(x['col rev'])]}><{oligo2seq['RC_threep_sticky']}"
            ]
        reg_r1 = re.compile('^\\w{5}' + f'{barcode2primersr1r2[barcode][0]}.*')
        reg_r2 = re.compile('^\\w{5}' + f'{barcode2primersr1r2[barcode][1]}.*')
        barcode2regsr1r2[barcode] = [reg_r1, reg_r2]
    linkerr1r2 = (
        f"{oligo2seq['plate_fivep_sticky']}{oligo2seq['RC_fivep_sticky']}{oligo2seq['plate_threep_sticky']}{oligo2seq['RC_threep_sticky']}"
        )
    barcode2bcr1r2 = {'barcode2bcr1r2': barcode2bcr1r2,
        'barcode2primersr1r2': barcode2primersr1r2, 'barcode2fragsr1r2':
        barcode2fragsr1r2, 'barcode2regsr1r2': barcode2regsr1r2,
        'linkerr1r2': linkerr1r2}
    for k in barcode2bcr1r2:
        if k.startswith('barcode2'):
            dbarcodes[k.replace('barcode2', '')] = dbarcodes['barcode'].map(
                barcode2bcr1r2[k])
    return barcode2bcr1r2


def config(args):
    """execute subcommand config"""
    if args.default:
        from liesl.cli.lsl_api import init_lsl_api_cfg
        init_lsl_api_cfg(args.scope)
        return
    from liesl.cli.lsl_api import Ini
    ini = Ini(args.scope)
    ini.refresh()
    if args.sessionid:
        print(args.sessionid)
        try:
            ini.ini['lab']['SessionID'] = args.sessionid
        except KeyError:
            ini.ini['lab'] = {}
            ini.ini['lab']['SessionID'] = args.sessionid
        ini.write()
    if args.knownpeers:
        print(args.knownpeers)
        try:
            ini.ini['lab']['KnownPeers'] = '{' + args.knownpeers + '}'
        except KeyError:
            ini.ini['lab'] = {}
            ini.ini['lab']['KnownPeers'] = '{' + args.knownpeers + '}'
        ini.write()
    from liesl.cli.lsl_api import print_config
    print_config(args.scope)


def theta_OH_SO4_HMW84(T, P):
    """a-a': hydroxide sulfate [HMW84]."""
    theta = -0.013
    valid = T == 298.15
    return theta, valid


def contains_place(tweet):
    """
    Returns True if tweet contains a populated 'place' field
    """
    if 'place' in tweet and tweet['place']:
        return True
    return False


@staticmethod
def is_this_type(item, parent):
    """ Check if the passed in object represents the Object """
    return False


def populate_formset_error_messages(messages, request, formset):
    """Add errors to django messages framework by extracting them from formset)"""
    non_form_errors = formset.non_form_errors()
    if non_form_errors:
        messages.error(request, str(non_form_errors[0]))
        return
    for error in formset.errors:
        if error:
            for field in error:
                messages.error(request, str(error[field][0]))
        return


@conf
def gxx_modifier_darwin(conf):
    """Configuration flags for executing g++ on MacOS"""
    v = conf.env
    v.CXXFLAGS_cxxshlib = ['-fPIC']
    v.LINKFLAGS_cxxshlib = ['-dynamiclib']
    v.cxxshlib_PATTERN = 'lib%s.dylib'
    v.FRAMEWORKPATH_ST = '-F%s'
    v.FRAMEWORK_ST = ['-framework']
    v.ARCH_ST = ['-arch']
    v.LINKFLAGS_cxxstlib = []
    v.SHLIB_MARKER = []
    v.STLIB_MARKER = []
    v.SONAME_ST = []


def h5_save_lqcoll_to_attrs(settings, h5group):
    """
    take a LQCollection
    and create attributes inside h5group

    :param logged_quantities:
    :param h5group:
    :return: None
    """
    unit_group = h5group.create_group('units')
    for lqname, lq in settings.as_dict().items():
        try:
            h5group.attrs[lqname] = lq.val
        except:
            h5group.attrs[lqname] = lq.ini_string_value()
        if lq.unit:
            unit_group.attrs[lqname] = lq.unit


def merge_metrics_per_device_and_protocol(metrics):
    """Merge list of metrics per involved device and returns a Dict[MetricDevice, MetricDescription]"""
    metrics_per_device = {}
    for metric in metrics:
        if metric.device not in metrics_per_device:
            metrics_per_device[metric.device] = []
        metrics_per_device[metric.device].append(metric)
    return metrics_per_device


@classmethod
def fromkeys(cls, iterable, value=None):
    """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
        and values equal to v (which defaults to None).

        """
    d = cls()
    for key in iterable:
        d[key] = value
    return d


def set_gettext(gettext):
    """
    Define a function that will be used to localize messages.

    .. note:: Most common function to use for this would be default :func:`gettext.gettext`
    """
    global _gettext
    _gettext = gettext


@staticmethod
def pt_to_mm(measure):
    """Convert points to millimeters."""
    return measure * 0.352778


def square(data=None, out=None, name=None, **kwargs):
    """Returns element-wise squared value of the input.

    .. math::
       square(x) = x^2

    Example::

       square([2, 3, 4]) = [4, 9, 16]

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

       - square(default) = default
       - square(row_sparse) = row_sparse
       - square(csr) = csr

    Defined in src/operator/tensor/elemwise_unary_op_pow.cc:L118

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

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

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


def filtany(entities, **kw):
    """Filter a set of entities based on method return. Use keyword arguments.

  Example:
    filtmeth(entities, id='123')
    filtmeth(entities, name='bart')

  Multiple filters are 'OR'.
  """
    ret = set()
    for k, v in kw.items():
        for entity in entities:
            if getattr(entity, k)() == v:
                ret.add(entity)
    return ret


@staticmethod
def _ensure_tuple(attr):
    """Return tuple with the provided value. Returns the value if a tuple."""
    if not isinstance(attr, tuple):
        return attr,
    else:
        return attr


def dgl_csr_neighbor_uniform_sample(*seed_arrays, **kwargs):
    """This operator samples sub-graphs from a csr graph via an
    uniform probability. The operator is designed for DGL.

    The operator outputs three sets of NDArrays to represent the sampled results
    (the number of NDArrays in each set is the same as the number of seed NDArrays):
    1) a set of 1D NDArrays containing the sampled vertices, 2) a set of CSRNDArrays representing
    the sampled edges, 3) a set of 1D NDArrays indicating the layer where a vertex is sampled.
    The first set of 1D NDArrays have a length of max_num_vertices+1. The last element in an NDArray
    indicate the acutal number of vertices in a subgraph. The third set of NDArrays have a length
    of max_num_vertices, and the valid number of vertices is the same as the ones in the first set.

    Example:

       .. code:: python

      shape = (5, 5)
      data_np = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20], dtype=np.int64)
      indices_np = np.array([1,2,3,4,0,2,3,4,0,1,3,4,0,1,2,4,0,1,2,3], dtype=np.int64)
      indptr_np = np.array([0,4,8,12,16,20], dtype=np.int64)
      a = mx.nd.sparse.csr_matrix((data_np, indices_np, indptr_np), shape=shape)
      a.asnumpy()
      seed = mx.nd.array([0,1,2,3,4], dtype=np.int64)
      out = mx.nd.contrib.dgl_csr_neighbor_uniform_sample(a, seed, num_args=2, num_hops=1, num_neighbor=2, max_num_vertices=5)

      out[0]
      [0 1 2 3 4 5]
      <NDArray 6 @cpu(0)>

      out[1].asnumpy()
      array([[ 0,  1,  0,  3,  0],
             [ 5,  0,  0,  7,  0],
             [ 9,  0,  0, 11,  0],
             [13,  0, 15,  0,  0],
             [17,  0, 19,  0,  0]])

      out[2]
      [0 0 0 0 0]
      <NDArray 5 @cpu(0)>

    Defined in src/operator/contrib/dgl_graph.cc:L784

    Parameters
    ----------
    csr_matrix : NDArray
        csr matrix
    seed_arrays : NDArray[]
        seed vertices
    num_hops : long, optional, default=1
        Number of hops.
    num_neighbor : long, optional, default=2
        Number of neighbor.
    max_num_vertices : long, optional, default=100
        Max number of vertices.

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

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


def return_params(islitlet, csu_bar_slit_center, params, parmodel):
    """Return individual model parameters from object of type Parameters.

    Parameters
    ----------
    islitlet : int
        Number of slitlet.
    csu_bar_slit_center : float
        CSU bar slit center, in mm.
    params : :class:`~lmfit.parameter.Parameters`
        Parameters to be employed in the prediction of the distorted
        boundaries.
    parmodel : str
        Model to be assumed. Allowed values are 'longslit' and
        'multislit'.

    Returns
    -------
    c2 : float
        Coefficient corresponding to the term r**2 in distortion
        equation.
    c4 : float
        Coefficient corresponding to the term r**4 in distortion
        equation.
    ff : float
        Scaling factor to be applied to the Y axis.
    slit_gap : float
        Slit gap.
    slit_height : float
        Slit height.
    theta0 : float
        Additional rotation angle (radians).
    x0 : float
        X coordinate of reference pixel.
    y0 : float
        Y coordinate of reference pixel.
    y_baseline : float
        Y coordinate employed as baseline.

    """
    if parmodel == 'longslit':
        c2 = params['c2'].value
        c4 = params['c4'].value
        ff = params['ff'].value
        slit_gap = params['slit_gap'].value
        slit_height = params['slit_height'].value
        theta0_origin = params['theta0_origin'].value
        theta0_slope = params['theta0_slope'].value
        x0 = params['x0'].value
        y0 = params['y0'].value
        y_baseline = params['y_baseline'].value
    else:
        c2_a0s = params['c2_a0s'].value
        c2_a1s = params['c2_a1s'].value / 1000.0
        c2_a2s = params['c2_a2s'].value / 1000000.0
        c2 = (c2_a0s + c2_a1s * csu_bar_slit_center + c2_a2s *
            csu_bar_slit_center ** 2)
        c4_a0s = params['c4_a0s'].value
        c4_a1s = params['c4_a1s'].value / 1000.0
        c4_a2s = params['c4_a2s'].value / 1000000.0
        c4 = (c4_a0s + c4_a1s * csu_bar_slit_center + c4_a2s *
            csu_bar_slit_center ** 2)
        ff_a0s = params['ff_a0s'].value
        ff_a1s = params['ff_a1s'].value / 1000.0
        ff_a2s = params['ff_a2s'].value / 1000000.0
        ff = (ff_a0s + ff_a1s * csu_bar_slit_center + ff_a2s *
            csu_bar_slit_center ** 2)
        slit_gap_a0s = params['slit_gap_a0s'].value
        slit_gap_a1s = params['slit_gap_a1s'].value / 1000.0
        slit_gap_a2s = params['slit_gap_a2s'].value / 1000000.0
        slit_gap = (slit_gap_a0s + slit_gap_a1s * csu_bar_slit_center +
            slit_gap_a2s * csu_bar_slit_center ** 2)
        slit_height_a0s = params['slit_height_a0s'].value
        slit_height_a1s = params['slit_height_a1s'].value / 1000.0
        slit_height_a2s = params['slit_height_a2s'].value / 1000000.0
        slit_height = (slit_height_a0s + slit_height_a1s *
            csu_bar_slit_center + slit_height_a2s * csu_bar_slit_center ** 2)
        theta0_origin_a0s = params['theta0_origin_a0s'].value
        theta0_origin_a1s = params['theta0_origin_a1s'].value / 1000.0
        theta0_origin_a2s = params['theta0_origin_a2s'].value / 1000000.0
        theta0_origin = (theta0_origin_a0s + theta0_origin_a1s *
            csu_bar_slit_center + theta0_origin_a2s * csu_bar_slit_center ** 2)
        theta0_slope_a0s = params['theta0_slope_a0s'].value
        theta0_slope_a1s = params['theta0_slope_a1s'].value / 1000.0
        theta0_slope_a2s = params['theta0_slope_a2s'].value / 1000000.0
        theta0_slope = (theta0_slope_a0s + theta0_slope_a1s *
            csu_bar_slit_center + theta0_slope_a2s * csu_bar_slit_center ** 2)
        x0_a0s = params['x0_a0s'].value
        x0_a1s = params['x0_a1s'].value / 1000.0
        x0_a2s = params['x0_a2s'].value / 1000000.0
        x0 = (x0_a0s + x0_a1s * csu_bar_slit_center + x0_a2s *
            csu_bar_slit_center ** 2)
        y0_a0s = params['y0_a0s'].value
        y0_a1s = params['y0_a1s'].value / 1000.0
        y0_a2s = params['y0_a2s'].value / 1000000.0
        y0 = (y0_a0s + y0_a1s * csu_bar_slit_center + y0_a2s *
            csu_bar_slit_center ** 2)
        y_baseline_a0s = params['y_baseline_a0s'].value
        y_baseline_a1s = params['y_baseline_a1s'].value / 1000.0
        y_baseline_a2s = params['y_baseline_a2s'].value / 1000000.0
        y_baseline = (y_baseline_a0s + y_baseline_a1s * csu_bar_slit_center +
            y_baseline_a2s * csu_bar_slit_center ** 2)
    theta0 = theta0_origin / 1000.0 + theta0_slope / 10000.0 * islitlet
    return c2, c4, ff, slit_gap, slit_height, theta0, x0, y0, y_baseline


def memory():
    """Determine the machine's memory specifications.

    Returns
    -------
    mem_info : dictonary
        Holds the current values for the total, free and used memory of the system.
    """
    mem_info = {}
    with open('/proc/meminfo') as file:
        c = 0
        for line in file:
            lst = line.split()
            if str(lst[0]) == 'MemTotal:':
                mem_info['total'] = int(lst[1])
            elif str(lst[0]) in ('MemFree:', 'Buffers:', 'Cached:'):
                c += int(lst[1])
        mem_info['free'] = c
        mem_info['used'] = mem_info['total'] - c
    return mem_info


def p_definition(t):
    """definition : constant_def
                  | type_def
                  | program_def"""


def installRecommendation(install, uninstall, working_set=working_set,
    tuples=False):
    """Human Readable advice on which modules have to be installed on
    current Working Set.
    """
    installList = []
    for i in install:
        is_in = False
        for p in working_set:
            if i[0] == p.key and i[1] == p.version:
                is_in = True
                break
        if not is_in:
            if not tuples:
                print('~~ Install: ' + i[0] + ' version ' + i[1])
            else:
                installList.append((i[0], i[1]))
    for u in uninstall:
        is_in = False
        for p in working_set:
            if u[0] == p.key and u[1] == p.version:
                is_in = True
                break
        if is_in:
            if not tuples:
                print('~~ Uninstall: ' + u[0] + ' version ' + u[1])
    return installList


def _default_key_normalizer(key_class, request_context):
    """
    Create a pool key of type ``key_class`` for a request.

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

    :param key_class:
        The class to use when constructing the key. This should be a namedtuple
        with the ``scheme`` and ``host`` keys at a minimum.

    :param request_context:
        A dictionary-like object that contain the context for a request.
        It should contain a key for each field in the :class:`HTTPPoolKey`
    """
    context = {}
    for key in key_class._fields:
        context[key] = request_context.get(key)
    context['scheme'] = context['scheme'].lower()
    context['host'] = context['host'].lower()
    return key_class(**context)


@classmethod
def get(cls):
    """ Return a MenuManager Instance.

        This will always return the same instance. If the instance is not available
        it will be created and returned.

        :returns: always the same MenuManager
        :rtype: MenuManager
        :raises: None
        """
    if not cls.menumanager:
        cls.menumanager = cls()
    return cls.menumanager


def indent_block(text, indention='    '):
    """This function indents a text block with a default of four spaces."""
    temp = ''
    while text and text[-1] == '\n':
        temp += text[-1]
        text = text[:-1]
    lines = text.split('\n')
    return '\n'.join(map(lambda s: indention + s, lines)) + temp


def uninstall(context):
    """
    Uninstall script:
    Do something at the end of the uninstallation of this package.
    """


def set_user_settings(AccessToken=None, MFAOptions=None):
    """
    Sets the user settings like multi-factor authentication (MFA). If MFA is to be removed for a particular attribute pass the attribute with code delivery as null. If null list is passed, all MFA options are removed.
    See also: AWS API Documentation

    :example: response = client.set_user_settings(
        AccessToken='string',
        MFAOptions=[
            {
                'DeliveryMedium': 'SMS'|'EMAIL',
                'AttributeName': 'string'
            },
        ]
    )

    :type AccessToken: string
    :param AccessToken: [REQUIRED]
            The access token for the set user settings request.

    :type MFAOptions: list
    :param MFAOptions: [REQUIRED]
            Specifies the options for MFA (e.g., email or phone number).
            (dict) --Specifies the different settings for multi-factor authentication (MFA).
            DeliveryMedium (string) --The delivery medium (email message or SMS message) to send the MFA code.
            AttributeName (string) --The attribute name of the MFA option type.

    :rtype: dict
    :return: {}

    """
    pass


def remove_icon_names(inst, target=None):
    """Removes leading text on ICON project variable names

    Parameters
    ----------
    inst : pysat.Instrument
        ICON associated pysat.Instrument object
    target : str
        Leading string to remove. If none supplied,
        ICON project standards are used to identify and remove
        leading text

    Returns
    -------
    None
        Modifies Instrument object in place

    """
    if target is None:
        lev = inst.tag
        if lev == 'level_2':
            lev = 'L2'
        elif lev == 'level_0':
            lev = 'L0'
        elif lev == 'level_0p':
            lev = 'L0P'
        elif lev == 'level_1.5':
            lev = 'L1-5'
        elif lev == 'level_1':
            lev = 'L1'
        else:
            raise ValueError('Uknown ICON data level')
        sid = inst.sat_id.lower()
        if sid == 'a':
            sid = 'IVM_A'
        elif sid == 'b':
            sid = 'IVM_B'
        else:
            raise ValueError('Unknown ICON satellite ID')
        prepend_str = '_'.join(('ICON', lev, sid)) + '_'
    else:
        prepend_str = target
    inst.data.rename(columns=lambda x: x.split(prepend_str)[-1], inplace=True)
    inst.meta.data.rename(index=lambda x: x.split(prepend_str)[-1], inplace
        =True)
    orig_keys = inst.meta.keys_nD()
    for keynd in orig_keys:
        new_key = keynd.split(prepend_str)[-1]
        new_meta = inst.meta.pop(keynd)
        new_meta.data.rename(index=lambda x: x.split(prepend_str)[-1],
            inplace=True)
        inst.meta[new_key] = new_meta
    return


def valid_latlon_bounds(bounds):
    """Return whether bounds fall within [-180, 180] for x and [-90, 90] for y"""
    return -180 <= bounds[0] <= 180 and -90 <= bounds[1
        ] <= 90 and -180 <= bounds[2] <= 180 and -90 <= bounds[3] <= 90


@classmethod
def __get_checksum(cls, pesel):
    """Generate checksum for PESEL
        :param pesel: PESEL number
        :type pesel: str
        :return: Checksum for PESEL
        :rtype: int
        """
    checksum = 0
    for index, value in enumerate(pesel):
        checksum += cls.__CHECKSUM_WEIGHTS[index] * int(value)
    checksum = (10 - checksum % 10) % 10
    return checksum


def sf_machine(sf_wagner, transmission_mach, transmission_wagner):
    """Sensitivity factor for XPS machine correction from the Wagner XPS machine

    sf_wagner              : Wagner sensitivity factor
    transmission_mach      : Transmission function for the selected element
    transmission_wagner    : Wagner transmission function for the selected
                             element.
                             Proportional to 1/(kinetic_energy) [1/eV]
    """
    return sf_wagner * transmission_mach / transmission_wagner


def getCatalog(unique_name):
    """Returns a ICatalog in the Datasource with the given unique name."""


def endswith_lf(line):
    """Return True if line (a text or byte string) ends with '
'."""
    return line.endswith('\n' if isinstance(line, str) else b'\n')


def get_lempel_ziv_entropy(message: str) ->float:
    """
    Get Lempel-Ziv entropy estimate, Snippet 18.2, page 266.

    :param message: (str) encoded message
    :return: (float) Lempel-Ziv entropy
    """
    i, lib = 1, [message[0]]
    while i < len(message):
        for j in range(i, len(message)):
            message_ = message[i:j + 1]
            if message_ not in lib:
                lib.append(message_)
                break
        i = j + 1
    return len(lib) / len(message)


def set_receipt_rule_position(RuleSetName=None, RuleName=None, After=None):
    """
    Sets the position of the specified receipt rule in the receipt rule set.
    For information about managing receipt rules, see the Amazon SES Developer Guide .
    This action is throttled at one request per second.
    See also: AWS API Documentation

    Examples
    The following example sets the position of a receipt rule in a receipt rule set:
    Expected Output:

    :example: response = client.set_receipt_rule_position(
        RuleSetName='string',
        RuleName='string',
        After='string'
    )

    :type RuleSetName: string
    :param RuleSetName: [REQUIRED]
            The name of the receipt rule set that contains the receipt rule to reposition.

    :type RuleName: string
    :param RuleName: [REQUIRED]
            The name of the receipt rule to reposition.

    :type After: string
    :param After: The name of the receipt rule after which to place the specified receipt rule.

    :rtype: dict
    :return: {}

    """
    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


def create_parser(parser):
    """
    Adds argument groups to parser
    :param parser: The parser that is used to add argument groups
    :return: An updated parser
    """
    required_group = parser.add_argument_group('Required arguments',
        'These options are mandatory to run crYOLO train')
    required_group.add_argument('-c', '--conf', required=True, help=
        'Path to configuration file', widget='FileChooser', gooey_options={
        'validator': {'test': 'user_input.endswith("json")', 'message':
        'File has to end with .json!'}, 'wildcard': '*.json'})
    required_group.add_argument('-w', '--warmup', type=int, required=True,
        default=5, help=
        'Number of warmup epochs. Set it to zero if you fine tune a model.')
    optional_group = parser.add_argument_group('Optional arguments',
        'These options are optional to run crYOLO train')
    optional_group.add_argument('-g', '--gpu', default='', nargs='+', help=
        'Specifiy which gpu(s) should be used. Multiple GPUs are separated by a whitespace. If not defined otherwise by your system, it will use GPU 0 by default.'
        )
    optional_group.add_argument('-nc', '--num_cpu', type=int, default=-1,
        help=
        'Number of CPUs used during training. By default it will use half of the available CPUs.'
        )
    optional_group.add_argument('--gpu_fraction', type=float, default=1.0,
        help=
        'Specify the fraction of memory per GPU used by crYOLO during training. Only values between 0.0 and 1.0 are allowed.'
        , gooey_options={'validator': {'test':
        '0.0 <= float(user_input) <= 1.0', 'message':
        'Must be between 0 and 1.0'}})
    optional_group.add_argument('-e', '--early', default=10, type=int, help
        =
        'Early stop patience. If the validation loss did not improve longer than the early stop patience, the training is stopped.'
        )
    optional_group.add_argument('--fine_tune', action='store_true', default
        =False, help=
        'Set it to true if you only want to use the fine tune mode. When using the fine tune mode, only the last layers of your network are trained and youhave to specify pretrained_weights (see action "config"->"Training options") You typically use a general model as pretrained weights.'
        )
    optional_group.add_argument('-lft', '--layers_fine_tune', default=2,
        type=int, help='Layers to be trained when using fine tuning.')
    deexsp_group = parser.add_argument_group('Deprecated/Experimental/Special '
        , 'Contains either deprecated / experimental or very special options.')
    deexsp_group.add_argument('--seed', type=int, default=10, help=
        'Seed for random number generator. Mainly influences selection of validation images. Should be the same during different training runs!'
        )
    deexsp_group.add_argument('--warm_restarts', action='store_true', help=
        'Use warm restarts and cosine annealing during training')
    deexsp_group.add_argument('--skip_augmentation', action='store_true',
        default=False, help=
        'Use it if you want to deactivate data augmentation during training.')
    deexsp_group.add_argument('--use_multithreading', action='store_true',
        default=False, help=
        'If python multiprocessing leads to problems during training (e.g. freezing, dying workers) use multithreading instead of multiprocessing.'
        )


@staticmethod
def is_enough_quality(value):
    """Return True if value is enough quality."""
    raise NotImplementedError


def _is_tokenized(word):
    """
    Runs some checks to see if the word is tokenized.
    Note: if this functions returns True doesn't mean is really tokenized, but
    if returns False you know it's not tokenized propperly.
    """
    return not ((word.endswith('.') or word.endswith(',')) and word[:-1].
        isalpha())


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

    The ".dev0" means dirty.

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


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

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


def 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 outputForLanguage(specification, options):
    """Outputs the file(s) used by the language"""


def get_error(exception=None):
    """Gets errno from exception or returns one"""
    return getattr(exception, 'errno', 1)


def hottags():
    """
    @api {post} /music/search/hottags 热门标签
    @apiVersion 1.0.0
    @apiGroup Search
    @apiDescription 热门标签

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

    @apiSuccess (Success) {Object} rank 等级
    @apiSuccess (Success) {Object} imagePathMap 图像路径图
    @apiSuccess (Success) {String} imagePathMap.value 图像路径图值
    @apiSuccess (Success) {String} imagePathMap.key 图像路径图键
    @apiSuccess (Success) {Object} categoryID 分类编号
    @apiSuccess (Success) {Object} description 描述
    @apiSuccess (Success) {Object} categoryType 分类类型
    @apiSuccess (Success) {Object} name 名称
    @apiSuccess (Success) {Object} categoryCode 分类代码

    @apiSuccessExample {json} Success-Response:
    {
        "data": [
            {
                "rank": 999,
                "imagePathMap": [
                    {
                        "value": "",
                        "key": "JPG-320X320-NODELIST"
                    },
                    {
                        "value": "",
                        "key": "JPG-600X600-NODELIST"
                    },
                    {
                        "value": "",
                        "key": "JPG-NXN-NODELIST"
                    }
                ],
                "categoryID": 766,
                "description": "",
                "categoryType": "CT_KV",
                "name": "中国新歌声第二季",
                "categoryCode": ""
            }
        ]
    }
    """


def get_user_key(request, prefix='hacl', suffix=None):
    """
    @Linked to `lru_wrapped`
    :param request:
    :param prefix:
    :param suffix:
    :return:
    """
    if suffix is None:
        suffix = ''
    return '{prefix}:site_{site_id}:user_{user_id}{suffix}'.format(prefix=
        prefix, site_id=request.site.id, user_id=request.user.
        is_authenticated() and request.user.id or 0, suffix=suffix)


def cw2w(cw, e):
    """Transform from *w* index value to *w* count value, using the
    *e.css('cd')* (column width) as column measure."""
    if cw is None:
        w = 0
    else:
        gw = e.gw
        w = cw * (e.css('cw', 0) + gw) - gw
    return w


def split_first(s, delims):
    """
    Given a string and an iterable of delimiters, split on the first found
    delimiter. Return two split parts and the matched delimiter.

    If not found, then the first part is the full input string.

    Example::

        >>> split_first('foo/bar?baz', '?/=')
        ('foo', 'bar?baz', '/')
        >>> split_first('foo/bar?baz', '123')
        ('foo/bar?baz', '', None)

    Scales linearly with number of delims. Not ideal for large number of delims.
    """
    min_idx = None
    min_delim = None
    for d in delims:
        idx = s.find(d)
        if idx < 0:
            continue
        if min_idx is None or idx < min_idx:
            min_idx = idx
            min_delim = d
    if min_idx is None or min_idx < 0:
        return s, '', None
    return s[:min_idx], s[min_idx + 1:], min_delim


def is_xyz_space(obj):
    """ True if `obj` appears to be an XYZ space definition """
    return hasattr(obj, 'x') and hasattr(obj, 'y') and hasattr(obj, 'z'
        ) and hasattr(obj, 'to_coordsys_maker')


@classmethod
def load_from_conf_options(cls, conf, group, **kwargs):
    """Create a session object from an oslo_config object.

        The options must have been previously registered with
        register_conf_options.

        :param oslo_config.Cfg conf: config object to register with.
        :param string group: The ini group to register options in.
        :param dict kwargs: Additional parameters to pass to session
                            construction.
        :returns: A new session object.
        :rtype: :py:class:`.Session`
        """
    c = conf[group]
    kwargs['insecure'] = c.insecure
    kwargs['cacert'] = c.cafile
    if c.certfile and c.keyfile:
        kwargs['cert'] = c.certfile, c.keyfile
    kwargs['timeout'] = c.timeout
    return cls._make(**kwargs)


def from_cli(cli_name):
    """
    Takes a string from the Command Line Interface and transforms it into a
    Python identifier.
    """
    return str(cli_name).replace('-', '_')


@staticmethod
def read_line(line):
    """Reads lines of XML and delimits, strips, and returns."""
    name, value = '', ''
    if '=' in line:
        name, value = line.split('=', 1)
    return [name.strip(), value.strip()]


def _fill_list(the_list, length, fillvalue=None):
    """Fill a list to a specified length.

    Parameters
    ----------
    the_list : list
        The list to fill.
    length : int
        The required length.
    fillvalue : optional
        The value to insert. If None is given the last item in the list
        is repeated.

    """
    if fillvalue is None:
        fillvalue = the_list[-1]
    while len(the_list) < length:
        the_list.append(fillvalue)


def p_enum_constant_list_1(t):
    """enum_constant_list : enum_constant"""
    t[0] = t[1]