def format_timedelta(timedelta):
    """
    Format a timedelta into a human-friendly string.

    Parameters
    ----------
    timedelta : timedelta

    Returns
    -------
    str
        Formatted timedelta.

    Examples
    --------
    >>> from datetime import timedelta
    >>> from tomputils import mattermost as mm
    >>> td = timedelta(days=2, hours=4, seconds=5)
    >>> print(mm.format_timedelta(td))
    2d 4h 5s
    >>>

    """
    seconds = timedelta.total_seconds()
    days, rmainder = divmod(seconds, 60 * 60 * 24)
    hours, rmainder = divmod(rmainder, 60 * 60)
    minutes, rmainder = divmod(rmainder, 60)
    seconds = rmainder
    timestring = ''
    if days > 0:
        timestring += '%dd ' % days
    if hours > 0:
        timestring += '%dh ' % hours
    if minutes > 0:
        timestring += '%dm ' % minutes
    if seconds > 0:
        timestring += '%ds' % seconds
    return timestring.strip()


def adjust_volume_gravity(vol, og, new_vol):
    """
    Calculate the new gravity after boil off or dilution to ``new_vol``
    This is unit independent and the volume can be used for liters
    and or gallons.

    Ending Gravity = (Beginning Volume * Beginning Gravity) / End Volume

    :arg vol: Original volume of wort
    :arg og: The current gravity of the wort
    :arg new_vol: The new volume of the wort
    :returns: The new gravity after boiloff or dilution
    """
    og = (og - 1) * 1000
    return 1 + vol * og / new_vol / 1000


def flatten_inplace(seq):
    """Flatten a sequence in place."""
    k = 0
    while k != len(seq):
        while hasattr(seq[k], '__iter__'):
            seq[k:k + 1] = seq[k]
        k += 1
    return seq


def getSessionTypes(assoc_type):
    """Return the allowed session types for a given association type"""
    assoc_to_session = {'HMAC-SHA1': ['DH-SHA1', 'no-encryption'],
        'HMAC-SHA256': ['DH-SHA256', 'no-encryption']}
    return assoc_to_session.get(assoc_type, [])


def find_param_by_keyword(keyword, params):
    """
    Searches for a specific param by keyword.
    This function will try to look for the keyword as-is first, and then tries
    to find the uppercase'd version of the keyword.
    """
    if keyword in params:
        return params[keyword]
    keyword = keyword.upper()
    if keyword in params:
        return params[keyword]
    raise KeyError('No param named {} defined'.format(keyword))


def disable_swagger(callback):
    """
    Decorator for removing endpoint from OpenAPI Swagger JSON
    """
    callback.enable_swagger = False
    return callback


def restore_pymysql():
    """Restores pymysql"""
    try:
        import pymysql
    except ImportError:
        pass
    else:
        setattr(pymysql, 'connect', getattr(pymysql.connect, '__wrapped__',
            pymysql.connect))


def is_naive(dt):
    """Determines if a given datetime.datetime is naive."""
    return dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None


def keys_of(d):
    """
    Returns the keys of a dict.
    """
    try:
        return list(d.keys())
    except:
        raise ValueError('keys_of(d) must be passed a dict')


def Now(dt):
    """ A context processor that sets the current datetime. """
    from datetime import date, time, datetime
    try:
        from unittest import mock
    except ImportError:
        import mock
    if isinstance(dt, date) and not isinstance(dt, datetime):
        dt = datetime.combine(dt, time(0))
    return mock.patch('{}._now'.format(__name__), lambda : dt)


def get(name):
    """ Look up name, return the uid. """


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

        :param PaperDocResolveCommentType val:
        :rtype: EventType
        """
    return cls('paper_doc_resolve_comment', val)


def swap(s1, s2, A):
    """Applies the Swap operator onto two sets of samples, `s1` and `s2`.

    The sites that will be swapped are defined by `A`.

    :param s1: A rank 2 tensor of spin samples representing the first replica.
    :type s1: torch.Tensor
    :param s2: A rank 2 tensor of spin samples representing the second replica.
    :type s2: torch.Tensor
    :param A: The sites that will be swapped between the two replicas.
    :type A: int or list or np.array or torch.Tensor
    """
    _s = s1[:, (A)].clone()
    s1[:, (A)] = s2[:, (A)]
    s2[:, (A)] = _s
    return s1, s2


def parse_bsrate_report(report):
    """Parse bsrate report file."""
    bsrate_dict = {}
    with open(report, 'r') as r:
        first_line = r.readline()
        if not first_line.startswith(
            'Bisulfite conversion rate process skipped.'):
            bsrate_dict['Overall conversion rate'] = first_line.split()[-1]
            for strand in ['positive', 'negative']:
                line = r.readline().split()
                bsrate_dict[f'Conversion rate on {strand}'] = line[-2]
                bsrate_dict[f'Number of nucleotides used on {strand} strand'
                    ] = line[-1]
    return bsrate_dict


@classmethod
def cy(cls, *args):
    """
        Either the y position of cursor, or sets the y position.
        Example:
        ::

            # gets the y position of cursor
            my_y = cls.cy()

            # set the y position to 20
            cls.cy(20)

            # moves down 2 spots
            cls.cy(cls.cy() + 2)

        :param y: optional y position to move to
        :return: if y not specified, returns the y position of cursor
        """
    x, y = cls.getxy()
    if not args:
        return y
    return cls.move(x, args[0])


def upload_file(sftp, local_filepath, remote_filepath):
    """Upload a file to the server.

    :param sftp: Paramiko SFTPClient connection to a server.
    :type sftp: SFTPClient
    :param local_filepath: Absoluate path to file to be uploaded.
    :type local_filepath: str
    :param remote_filepath: Absoluate path to server destination.
    :type remote_filepath: str
    :returns: Indicates whether upload was successful.
    :rtype: bool
    """
    try:
        sftp.put(local_filepath, remote_filepath)
        result = True
    except:
        print(
            'Problems encountered with the specified local or destination directories.'
            )
        result = False
    return result


def min_element(l, base=0):
    """ @return pair containing the index and value respectively of the minimum element of list l """
    return min(enumerate(l, base), key=lambda x: x[1])


@classmethod
def get_natural_key_info(cls):
    """
        Derive natural key from first unique_together definition, noting
        which fields are related objects vs. regular fields.
        """
    fields = cls.get_natural_key_definition()
    info = []
    for name in fields:
        field = cls._meta.get_field(name)
        rel_to = None
        if hasattr(field, 'rel'):
            rel_to = field.rel.to if field.rel else None
        elif hasattr(field, 'remote_field'):
            if field.remote_field:
                rel_to = field.remote_field.model
            else:
                rel_to = None
        info.append((name, rel_to))
    return info


@staticmethod
def WhereNet():
    """Network that determines where to move the gaze"""
    raise NotImplementedError


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

        :param MemberChangeStatusDetails val:
        :rtype: EventDetails
        """
    return cls('member_change_status_details', val)


@classmethod
def __find_mp3_start__(cls, mp3file):
    """places mp3file at the position of the MP3 file's start"""
    from audiotools.id3 import skip_id3v2_comment
    skip_id3v2_comment(mp3file)
    from audiotools.bitstream import BitstreamReader
    reader = BitstreamReader(mp3file, False)
    pos = reader.getpos()
    frame_sync, mpeg_id, layer = reader.parse('11u 2u 2u 1p')
    while not (frame_sync == 2047 and mpeg_id in (0, 2, 3) and layer in (1,
        2, 3)):
        reader.setpos(pos)
        reader.skip(8)
        pos = reader.getpos()
    reader.setpos(pos)


def guess_mapping(emitter, receiver):
    """Guess connection mapping between emitter and receiver.

    Suppose emitter and receiver have common inputs:
    ip, ssh_key, ssh_user

    Then we return a connection mapping like this:

    {
        'ip': '<receiver>.ip',
        'ssh_key': '<receiver>.ssh_key',
        'ssh_user': '<receiver>.ssh_user'
    }

    :param emitter:
    :param receiver:
    :return:
    """
    guessed = {}
    for key in emitter.db_obj.meta_inputs:
        if key in receiver.db_obj.meta_inputs:
            guessed[key] = key
    return guessed


@classmethod
def format_str(cls):
    """ Return a string describing the fitted function.

        The string must contain one formatting argument for each coefficient.
        """
    return 'FORMAT STRING NOT DEFINED'


def authGSSClientWrap(context, data, user=None, protect=0):
    """
    Perform the client side GSSAPI wrap step.

    @param data: The result of the L{authGSSClientResponse} after the
        L{authGSSClientUnwrap}.

    @param user: The user to authorize.

    @param protect: If C{0}, then just provide integrity protection.
        If C{1}, then provide confidentiality as well.

    @return: A result code (see above)
    """


def collection_holdout_set():
    """Mask collection in the active view layer

    """
    pass


@classmethod
def _decrypt(cls, secret, data):
    """ Placeholder symmetric decryptor.

        Data should be bytes-like. Key should be bytes-like.
        """
    return data


def load_handlers(name):
    """Load the (URL pattern, handler) tuples for each component."""
    mod = __import__(name, fromlist=['default_handlers'])
    return mod.default_handlers


@classmethod
def _UseForTag(cls, tag, raise_if_fail=True):
    """Return the ElementDeclaration object corresponding to the element name.

        @param tag: The L{ExpandedName} of an element in the class."""
    try:
        rv = cls._ElementMap[tag]
    except KeyError:
        if raise_if_fail:
            raise
        rv = None
    return rv


def on_token(token: str, **kwargs):
    """Callback; set this attribute in the parent class."""
    raise NotImplementedError


def region_2d_to_origin_3d(region, rv3d, coord, clamp=None):
    """
    Return the 3d view origin from the region relative 2d coords.

    .. note::

       Orthographic views have a less obvious origin,
       the far clip is used to define the viewport near/far extents.
       Since far clip can be a very large value,
       the result may give with numeric precision issues.

       To avoid this problem, you can optionally clamp the far clip to a
       smaller value based on the data you're operating on.

    :arg region: region of the 3D viewport, typically bpy.context.region.
    :type region: :class:`bpy.types.Region`
    :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: :class:`bpy.types.RegionView3D`
    :arg coord: 2d coordinates relative to the region;
       (event.mouse_region_x, event.mouse_region_y) for example.
    :type coord: 2d vector
    :arg clamp: Clamp the maximum far-clip value used.
       (negative value will move the offset away from the view_location)
    :type clamp: float or None
    :return: The origin of the viewpoint in 3d space.
    :rtype: :class:`mathutils.Vector`
    """
    viewinv = rv3d.view_matrix.inverted()
    if rv3d.is_perspective:
        origin_start = viewinv.translation.copy()
    else:
        persmat = rv3d.perspective_matrix.copy()
        dx = 2.0 * coord[0] / region.width - 1.0
        dy = 2.0 * coord[1] / region.height - 1.0
        persinv = persmat.inverted()
        origin_start = persinv.col[0].xyz * dx + persinv.col[1
            ].xyz * dy + persinv.translation
        if clamp != 0.0:
            if rv3d.view_perspective != 'CAMERA':
                origin_offset = persinv.col[2].xyz
                if clamp is not None:
                    if clamp < 0.0:
                        origin_offset.negate()
                        clamp = -clamp
                    if origin_offset.length > clamp:
                        origin_offset.length = clamp
                origin_start -= origin_offset
    return origin_start


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 calcshcs(Zpu, Vnom, Vpu=1.0):
    """Calculates the short circuit current in Amperes.
    Vpu = Pre-fault voltage (optional)
    Vnom = Vnom in kV
    Zpu = Impedance in per unit on 100 MVA base
    """
    Spu = Vpu / Zpu
    return 100 * Spu / (3 ** 0.5 * Vnom)


def atom_from_issue_value(issue: str, value: str) ->str:
    """
    takes a tuple representation of an issue value asignement and converts it into an atmoic one.
    Also correctly handles atoms that include . in the name, e.g. ("float","0.9") which can trip up
    ProbLog. This is the inverse of :func:`issue_value_tuple_from_atom`.

    >>> issue_value_tuple_from_atom(("Boolean","True))
    'Boolean_True'
    >>> issue_value_tuple_from_atom(('float', '0.9'))
    "'float_0.9'"

    :param issue: The issue
    :type issue: str
    :param value: the value
    :type value: str
    :raises ValueError: if the given atom does not have a valid format
    :return: A tuple containing the issue and value respectively.
    :rtype: str
    """
    if '_' in issue or '_' in value:
        raise ValueError(f'{issue} or {value} contained illigal character: _')
    if '.' in str(value):
        return f"'{issue}_{value}'"
    return f'{issue}_{value}'


def dummy_function():
    """ Dummy function to initialize process pools """
    return None


def get_default_resolution_size_units():
    """
    Returns list with all default resolution size units
    NOTE: The order is VERY important, is the same order that there is in Maya Render Settings
    :return: list(str)
    """
    return ['pixels', 'inches', 'cm', 'mm', 'points', 'picas']


def update_dict_of_lists(master, newdata):
    """
    Extend the list values of `master` with those from `newdata`.

    Both parameters must be dictionaries containing list values.
    """
    for key, values in list(newdata.items()):
        master.setdefault(key, []).extend(values)


@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 {'title'}


def linear(x, param):
    """Linear function.

    f = param[0] * x + param[1] .

    Parameters:
        x (np.ndarray):    Positions at which to evaluate function.
        param (np.ndarray):    Necessary parameters.

    Returns:
        (np.ndarray):    Values of function at x.

    """
    return param[0] * x + param[1]


def vertex_weight_normalize_active_vertex():
    """Normalize active vertex’s weights

    """
    pass


def convert_to_sql_wildcards(pattern, sql_escape='|'):
    """Converts wildcards '*' and '?' to SQL versions '%' and '_'.
       A state machine is used to allow for using the backslash to
       escape this characters:
            t\\e\\s\\t -> test
            test -> test
            test* -> test%
            test\\* -> test*
            test\\\\* -> test\\%
            test\\\\\\* -> test\\*
            test\\\\\\\\* -> test\\\\%
            test\\\\\\\\\\* -> test\\\\*
            % -> \\%
            _ -> \\_
            test_test% -> test\\_test\\%
            test__test% -> test\\_\\_test\\%
            test\\_test\\% -> test\\_test\\%
            test\\\\_test\\\\% -> test\\\\_test\\\\%
            test\\\\\\_test\\\\\\% -> test\\\\_test\\\\%
            test\\\\\\\\_test\\\\\\% -> test\\\\\\_test\\\\%
    """
    pat = ''
    esc = False
    for p in pattern:
        if p not in '*?\\':
            esc = False
            if p in '%_':
                pat += sql_escape
            pat += p
        elif esc:
            esc = False
            pat += p
        elif p == '\\':
            esc = True
        elif p == '*':
            pat += '%'
        elif p == '?':
            pat += '_'
    return pat


def write_file(path, data):
    """Write data bytes to file at given path."""
    with open(path, 'wb') as f:
        f.write(data)


@staticmethod
def write_partition(df, path, fs, filename, partition_on, return_metadata,
    **kwargs):
    """
        Output a partition of a dask.DataFrame. This will correspond to
        one output file, unless partition_on is set, in which case, it will
        correspond to up to one file in each sub-directory.

        Parameters
        ----------
        df: dask.dataframe.DataFrame
        path: str
            Destination directory for data.  Prepend with protocol like ``s3://``
            or ``hdfs://`` for remote data.
        fs: FileSystem
        filename: str
        partition_on: List(str)
            Column(s) to use for dataset partitioning in parquet.
        return_metadata : bool
            Whether to return list of instances from this write, one for each
            output file. These will be passed to write_metadata if an output
            metadata file is requested.
        **kwargs: dict
            Other keyword arguments (including `fmd` and `index_cols`)

        Returns
        -------
        List of metadata-containing instances (if `return_metadata` is `True`)
        or empty list
        """
    raise NotImplementedError


def isEqual(lhs, rhs):
    """types should be a either a list, tuple, etc"""
    for x, y in zip(lhs, rhs):
        if x == y:
            continue
        else:
            return False
    return True


def _print(*args):
    """Print an object in the stdout."""
    return print(*args)


def summary(m):
    """ Prints information about the fitted metalog m.
      Prints to console:
        - metalog.output_dict['params']['term_limit']
        - metalog.output_dict['params']['term_lower_bound']
        - metalog.output_dict['params']['boundedness']
        - metalog.output_dict['params']['bounds']
        - metalog.output_dict['params']['step_len']
        - metalog.output_dict['params']['fit_method']
        - metalog.output_dict['Validation']

  Args:
      m (:obj:`metalog`): A fitted metalog object.

  """
    print(' -----------------------------------------------\n',
        """Summary of Metalog Distribution Object
""",
        '-----------------------------------------------\n',
        '\nParameters\n', 'Term Limit: ', m.output_dict['params'][
        'term_limit'], '\n', 'Term Lower Bound: ', m.output_dict['params'][
        'term_lower_bound'], '\n', 'Boundedness: ', m.output_dict['params']
        ['boundedness'], '\n', 'Bounds (only used based on boundedness): ',
        m.output_dict['params']['bounds'], '\n',
        'Step Length for Distribution Summary: ', m.output_dict['params'][
        'step_len'], '\n', 'Method Use for Fitting: ', m.output_dict[
        'params']['fit_method'], '\n', """

 Validation and Fit Method""")
    print(m.output_dict['Validation'].to_string(index=False))


@classmethod
def _add_content_mapper(cls, mapper):
    """
        add a model content definition for the class
        """
    if cls.__name__ not in cls._content_mappers:
        cls._content_mappers[cls.__name__] = []
    cls._content_mappers[cls.__name__].insert(0, mapper)


@classmethod
def create_exclude_package(cls, package_name, recursive=True):
    """Convenience constructor for a package exclusion rule.

        Essentially equivalent to just using ``shading_exclude('package_name.**')``.

        :param string package_name: Package name to exclude (eg, ``org.pantsbuild.example``).
        :param bool recursive: Whether to exclude everything under any subpackage of ``package_name``,
          or just direct children of the package. (Defaults to True).
        """
    return cls.create_relocate(from_pattern=cls._format_package_glob(
        package_name, recursive), shade_prefix='')


def console_has_colours(stream):
    """
    Detects if the specified stream has colourising capability.

    :param stream: stream to check (typically sys.stdout)
    """
    if not hasattr(stream, 'isatty'):
        return False
    if not stream.isatty():
        return False
    try:
        import curses
        curses.setupterm()
        return curses.tigetnum('colors') > 2
    except:
        return False


def _getattr_path(obj, path):
    """
    getattr for a dot separated path

    If an AttributeError is raised, it will return None.
    """
    if not path:
        return None
    for attr in path.split('.'):
        obj = getattr(obj, attr, None)
    return obj


def z_axis(rot):
    """Return the z-axis vector from 3x3 (row major) rotation matrix
	``rot``.

	"""
    return rot[2], rot[5], rot[8]


def _tidy_names(names, nnames, extra_names=None):
    """Truncate or extend names so that its len is nnames.

    The list is modified, this function returns nothing.

    Args:
        names (list): list of names.
        nnames (int): desired number of names.
        extra_names (list of str): list of names to be used to extend the list
            if needed. If this list isn't provided, a range is used instead.
    """
    if len(names) < nnames and extra_names is not None:
        names.extend(extra_names)
    names.extend(range(nnames - len(names)))
    del names[nnames:]


def degrees(B, nodes, weight=None):
    """Returns the degrees of the two node sets in the bipartite graph B.

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

    nodes: list or container
      Nodes in one node set of the bipartite graph.

    weight : string or None, optional (default=None)
       The edge attribute that holds the numerical value used as a weight.
       If None, then each edge has weight 1.
       The degree is the sum of the edge weights adjacent to the node.

    Returns
    -------
    (degX,degY) : tuple of dictionaries
       The degrees of the two bipartite sets as dictionaries keyed by node.

    Examples
    --------
    >>> from networkx.algorithms import bipartite
    >>> G = nx.complete_bipartite_graph(3,2)
    >>> Y=set([3,4])
    >>> degX,degY=bipartite.degrees(G,Y)
    >>> dict(degX)
    {0: 2, 1: 2, 2: 2}

    Notes
    -----
    The container of nodes passed as argument must contain all nodes
    in one of the two bipartite node sets to avoid ambiguity in the
    case of disconnected graphs.
    See :mod:`bipartite documentation <networkx.algorithms.bipartite>`
    for further details on how bipartite graphs are handled in NetworkX.

    See Also
    --------
    color, density
    """
    bottom = set(nodes)
    top = set(B) - bottom
    return B.degree(top, weight), B.degree(bottom, weight)


@classmethod
def from_yaml(cls, constructor, node):
    """Construct a DAGReference from a scalar YAML node"""
    return cls(constructor.construct_scalar(node))


def align_file_position(f, size):
    """ Align the position in the file to the next block of specified size """
    align = size - 1 - f.tell() % size
    f.seek(align, 1)


def tabify(s):
    """Convert all groups of 4 spaces in `s` to tabs. Return the result."""
    tabwidth = 4
    tabtoken = ' ' * tabwidth
    out = ''
    for line in s.split('\n'):
        prefix = ''
        newLine = ''
        inPrefix = True
        for c in line:
            if inPrefix and c == ' ':
                prefix += ' '
            elif inPrefix and c == '\t':
                prefix += tabtoken
            elif inPrefix:
                inPrefix = False
            if not inPrefix:
                newLine += c
        newPrefix = '\t' * ((len(prefix) + tabwidth - 1) // tabwidth)
        out += newPrefix
        out += newLine
        out += '\n'
    return out


def hide_axis(plt=None, ax=None, x_or_y=None, remove_gridlines=False,
    remove_labels=False):
    """
    Removes axis of a Matplotlib plot.

    Parameters
    ----------
    plt : matplotlib figure
        The figure to modify. N.B. Either plt or ax can be specified,
        not both.
    ax : matplotlib axis
        The axis to modify. N.B. Either plt or ax can be specified,
        not both.
    x_or_y : str
        The x or y coordinates to modify.
    remove_gridlines : bool, optional, default = False
        Specify whether to fully hide the x or y axis. If set to False
        then just the tick labels are hidden and not the ticks
        themselves.

    References
    ----------
    Stackoverflow : Hiding axis text in matplotlib plots
    """
    if plt is None and ax is None:
        raise ValueError('[gu.hide_axis]: Must specify either plt or ax plots.'
            )
    if plt is not None and ax is not None:
        raise ValueError(
            '[gu.hide_axis]: Can only specify either plt or ax, not both.')
    if x_or_y is None:
        raise ValueError("[gu.hide_axis]: x_or_y only takes either 'x' or 'y'."
            )
    if plt is not None:
        ax = plt.gca()
    if x_or_y == 'x':
        if remove_gridlines:
            ax.axes.get_xaxis().set_ticks([])
        elif not remove_gridlines:
            ax.axes.get_xaxis().set_ticklabels([])
        else:
            raise ValueError(
                'remove_gridlines is a boolean parameter and accepts either True or False'
                )
        if remove_labels:
            ax.set_xlabel('')
    elif x_or_y == 'y':
        if remove_gridlines:
            ax.axes.get_yaxis().set_ticks([])
        elif not remove_gridlines:
            ax.axes.get_yaxis().set_ticklabels([])
        else:
            raise ValueError(
                'remove_gridlines is a boolean parameter and accepts either True or False'
                )
        if remove_labels:
            ax.set_ylabel('')
    else:
        raise ValueError("x_or_y only takes either 'x' or 'y'.")
    return


def track_markers(backwards: bool=False, sequence: bool=False):
    """Track selected markers

    :param backwards: Backwards, Do backwards tracking
    :type backwards: bool
    :param sequence: Track Sequence, Track marker during image sequence rather than single image
    :type sequence: bool
    """
    pass


@staticmethod
def unit(val):
    """
        takes one value and returns a generator that yields that value.

        Complexity: O(1)
        params:
            val: the value to yield
        returns:
            the generator of the parameter
        """
    yield val


def screaming_snake_to_snake_case(text: str) ->str:
    """Convert SCREAMING_SNAKE_CASE to snake_case."""
    return text.lower()


def linear(x):
    """Linear (i.e. identity) activation function.

    # Arguments
        x: Input tensor.

    # Returns
        Input tensor, unchanged.
    """
    return x


def dissolve_mode(use_verts: bool=False, use_face_split: bool=False,
    use_boundary_tear: bool=False):
    """Dissolve geometry based on the selection mode

    :param use_verts: Dissolve Verts, Dissolve remaining vertices
    :type use_verts: bool
    :param use_face_split: Face Split, Split off face corners to maintain surrounding geometry
    :type use_face_split: bool
    :param use_boundary_tear: Tear Boundary, Split off face corners instead of merging faces
    :type use_boundary_tear: bool
    """
    pass


@classmethod
def from_finite_set(cls, s):
    """Create Integer set object from a finite set."""
    intervals = []
    for el in s:
        if type(el) != int:
            val = int(el)
        else:
            val = el
        intervals.append(val)
    return cls(intervals)


def info_fi():
    """Print class info in Finnish, infraformaatti 2.3.

    Main site: http://www.citygeomodel.fi/
    Link to file: http://www.citygeomodel.fi/Infra_formaatti_v2.3_211215.pdf
    """
    helper_str = """    tiedot kerätty infraformaatti 2.3
        Pääsivu: http://www.citygeomodel.fi/
        Linkki tiedostoon: http://www.citygeomodel.fi/Infra_formaatti_v2.3_211215.pdf

    LYHENTEET:
        i    kokonaisluku
        t    tekstikenttä, pituutta ei ole rajoitettu.
                 ei sisällä välilyöntejä.
        c    tekstikenttä, pituus on rajoitettu.
                 ei sisällä välilyöntejä
                 c4 = neljä merkkiä pitkä tekstikenttä
        f    desimaaliluku, jossa desimaalien määrää ei ole rajoitettu.
        '-'  tietoa ei käsitellä luvussa eikä kirjoituksessa.
                 kun jonkun kentän arvoa ei anneta, tilalla esitetään '-' merkki.
        v    vakio attribuutti (K/E, H/P)
            ei alkuperäinen tunnus infraformaatissa

        isolla kirjaimella merkitty havaintoarvon oltava olemassa ilman '-' –merkkiä

    TUNNUKSET (LYHYT)

        TIEDOSTOKOHTAISET
            FO, 3 (t, t ,t)
            KJ, 2 (T, t)
        PISTEKOHTAISET
            OM, 1 (t)
            ML, 1 (t)
            OR, 1 (t)
            TY, 2 (T, t)
            PK, 4 (i, t, t, t)
            TT, 5 (T, i, T, t, t)
            LA, 2 (i, t)
            XY, 5 (F, F, F, T, t)
            LN, 3 (T, f, f)
            -1, 1 (T)
            GR, 3 (t, t, t)
            GL, 1 (t)
            AT, 2 (T, T) # kallionäytekairauksissa
            AL, 3 (F, t, t)
            ZP, 5 (f, f, f, f, f)
            TP, 5 (t, f, t, t, t)
            LP, 5 (t, t, v, t, t)
        RIVIKOHTAISET
            HM, 1 (t) # välilyönnit sallittu
            TX, 1 (t) # välilyönnit sallittu
            HT, 1 (t)
            EM, 1 (t)
            VH, 0 ()
            KK, 3 (F, F, i)

        TUTKIMUSTAPATUNNUKSET
            PA/WST,  4 (F, f, i, t)
            PI,      2 (F, t)
            LY,      4 (F, f, i, t)
            SI/FVT,  5 (F, f, f, f, f)
            HE/DP,   3 (F, i, t)
            HK/DP,   4 (F, i, f, t)
            PT,      2 (F, t)
            TR,      2 (F, t)
            PR,      4 (F, f, f, t)
            CP/CPT,  5 (F, f, f, f, t)
            CU/CPTU, 6 (F, f, f, f, f, t)
            HP,      5
                H,   5 (F, i, f, V, t)
                P,   5 (F, f, f, V, t)
            PO,      3 (F, i, t)
            MW,      9 (F, F, F, f, f, f, f, V, t)

            VP       6 (F, T, f, f, f, t)
            VO       6 (F, T, f, f, f, t)
            VK       3 (F, T, v)
            VPK      2 (F, T)
            HV       4 (f, f, t, t)
            PS/PMT   3 (f, f, f)
            PM       3 (f, t, t)
            KO       6 (f, t, f, i, f, f)
            KE       2 (F, f)
            KR       2 (F, F)
            NO       4 (F, T, F, t)
            NE       4 (F, T, F, t)
            LB       3 (T, T, t)
            RK       2 (F, F)

    TIEDOSTOTUNNUKSET

        TIEDOSTOKOHTAISET
        FO: Formaattitiedot
            t   Formaatin versio nro
            t   Kirjoittava sovellus
            t   Sov. versio nro
        KJ: Mittausjärjestelmä
            T   Koordinaatisto
            t   Korkeusjärj.

        PISTEKOHTAISET
        OM: Tiedon omistaja
            t   Nimi
        ML: Maa- tai kalliolajiluokitus (SFS-EN ISO 14688-2)
            t   Nimi
        OR: Tutkimusorganisaatio
            t   Nimi
        TY: Työnumero
            T   Työnumero
            t   Nimi
        PK: Pöytäkirja
            i   Pöytäkirjan nro
            t   Kairaaja
            t   Tarkastaja
            t   Käsittelijä
        TT: Tutkimustapa
            T   Tutkimustapalyhenne
            i   Luokka
            T   Tunnus1
            t   Noudatettu standardi
            t   Näytteenotin
        LA: Laitetiedot
            i   Laitenumero
            t   Laitteen selitysteksti
        XY: Koordinaattitiedot
            F   x
            F   y
            F   kair. aloitustaso
            T   Päiväys
            t   Tunnus2
        LN: Linjatiedot
            T   Linjan nimi tai nro
            f   Paalu
            f   Etäisyys
        -1: Päättymistapa
            T   Päättymistapa
        GR: Pohjatutk. ohj. yleistiedot
            t   Ohjelman nimi
            t   Päiväys
            t   Ohjelmoija
        GL: Pohjatutk.ohj.tekstirivit
            t   Pohjatutk. ohj. tekstirivit
        AT: Syvyyden attribuuttitieto (kallionäytekairauksissa)
            T   Kallionäyteattribuutin nimi
            T   Mahdollinen arvo
        AL: Alkukairaustiedot
            F   Alkukair. syvyys (m)
            t   Alkukair. tapa
            t   Alkukair. maalaji
        ZP: Vesiputken tasotiedot
            f   Putken yläpään taso (m) PP
            f   Maanpinnan taso (m) MP
            f   Suojaputken yläpää taso (m) SP
            f   Kaivon kannen taso (m) KN
            f   Suod. alap. taso (m)
        TP: Vesiputken rakenne
            t   Yläosan rakenne (putki, suojap, kaivo)
            f   Suodattimen pit. (m)
            t   Suodatinmalli
            t   Putkenhalkaisija (sisä/ulko mm)
            t   Putkiaines (taul 11)
        LP: Vesiputken lisätiedot
            t   Mittauskohta (PP, MP, SP, KN)
            t   Lisätieto
            v   Lukittu Kyllä / Ei (vakiot = K/E)
            t   Lukon omistaja
            t   Asentaja

        RIVIKOHTAISET
        HM: Huomautustekstit
            t   Huomautusteksti (välilyönnit sallitaan)
        TX: Vapaat tekstit
            t   Vapaa teksti (välilyönnit sallitaan)
        HT: Piiloteksti
            t   Ei tulostettava teksti
        EM: Epävirallinen maalaji
            t   Epävirallinen maalaji
        VH: Vedenpinnan havainto
            -
        KK: Kallionäytekairaustiedot (Vino kairaus)
            F   Suuntakulma (aste)
            F   Pystykulma (aste)
            i   Halkaisija (mm)

        TUTKIMUSTAPATUNNUKSET
        PA/WST: Painokairaus
            F    Syvyys (m)
            f    Kuorma (kN)
            i    Puolikierrokset (-)
            t    Maalaji
        PI: Pistokairaus
            F    Syvyys (m)
            t    Maalaji
        LY: Lyöntikairaus
            F    Syvyys (m)
            f    Kuorma (kN)
            i    Lyönnit (-)
            t    Maalaji
        SI/FVT: Siipikairaus
            F    Syvyys (m)
            f    Leikkauslujuus (kN/m^2)
            f    Häiritty leikkauslujuus (kN/m^2)
            f    Sensitiivisyys (-)
            f    Jäännöslujuus (MPa)
        HE/DP: Heijarikairaus
            F    Syvyys (m)
            i    Lyönnit (-)
            t    Maalaji
        HK/DP: Heijarikairaus vääntömomentilla
            F    Syvyys (m)
            i    Lyönnit (-)
            f    Vääntömomentti (Nm)
            t    Maalaji
        PT: Putkikairaus
            F    Syvyys (m)
            t    Maalaji
        TR: Tärykairaus
            F    Syvyys (m)
            t    Maalaji
        PR: Puristinkairaus
            F    Syvyys (m)
            f    Kokonaisvastus (MN/m^2)
            f    Vaippavastus (kN/m^2)
            t    Maalaji
        CP/CPT: Puristinkairaus (CPT)
            F    Syvyys (m)
            f    Kokonaisvastus (MN/m^2)
            f    Vaippavastus (kN/m^2)
            f    Kärkivastus (MN/m^2)
            t    Maalaji
        CU/CPTU: Huokospainekairaus (CPTU)
            F    Syvyys (m)
            f    Kokonaisvastus (MN/m^2)
            f    Vaippavastus (kN/m^2)
            f    Kärkivastus (MN/m^2)
            f    Huokospaine (kN/m^2)
            t    Maalaji
        HP: Puristin-heijari -kairaus
            HP Heijarivaihe
            F    Syvyys (m)
            i    Lyönnit (-)
            f    Vääntömomentti (Nm)
            v    Vakio=H
            t    Maalaji
            HP Puristinvaihe
            F    Syvyys (m)
            f    Puristinpaine (MN/m^2)
            f    Vääntömomentti (Nm)
            v    Vakio=P
            t    Maalaji
        PO: Porakonekairaus
            F    Syvyys (m)
            i    Aika (s)
            t    Maalaji
        MW: MWD-kairaus
            F    Syvyys (m)
            F    Etenemisnopeus (cm/min)
            F    Puristusvoima (kN)
            f    Huuhtelupaine (bar)
            f    Vesimenekki (l/min)
            f    Vääntömomentti(Nm)
            f    Pyöritysnopeus (rmp)
            v    Isku (Vakio=0/1)
            t    Maalaji
        VP: Pohjaveden mittausputki
            F    Pinnan korkeusasema
            T    Päiväys
            f    Putken yläpään korkeusasema
            f    Putken alapaan korkeusasema
            f    Siiviläosan pituus (m)
            t    Mittaaja
        VO: Orsiveden mittausputki
            F    Pinnan korkeusasema
            T    Päiväys
            f    Putken yläpään korkeusasema
            f    Putken alapaan korkeusasema
            f    Siiviläosan pituus (m)
            t    Mittaaja
        VK: Vedenpinnan mittaus kaivosta
            F    Pinnan korkeusasema
            T    Päiväys
            v    Tyyppi O=orsivesi/P=pohjavesi(vakio=O/P)
        VPK: Kalliopohjavesiputki
            F    Pinnan korkeusasema
            T    Päiväys
        HV: Huokosvedenpaineen mittaus
            f    Syvyys (m)
            f    Paine (kN/m^2)
            t    Päiväys
            t    Mittaaja
        PS/PMT: Pressometrikoe
            f    Syvyys (m)
            f    Pressometrimoduli (MN/m^2)
            f    Murtopaine (MN/m^2)
        PM: Painumamittaus
            f    Korkeusluku
            t    Päiväys
            t    Mittaaja
        KO: Koekuoppa
            f    Syvyys (m)
            t    Maalaji
            f    Kivisyys
            i    Lohkareisuus
            f    Maksimileveys
            f    Minimileveys
        KE: Kallionäytekairaus laajennettu
            F    Alkusyvyys (m)
            f    Loppusyvyys (m)
        KR: Kallionäytekairaus videoitu
            F    Alkusyvyys (m)
            F    Loppusyvyys (m)
        NO: Näytteenotto häiritty
            F    Syvyystieto1 (m)
            T    Käyttäjän antama näytteen tunnus
            F    Näytteen syvyystieto2 (m)
            t    Maalaji
        NE: Näytteenotto häiriintymätön
            F    Syvyystieto1 (m)
            T    Käyttäjän antama näytteen tunnus
            F    Näytteen syvyystieto2 (m)
            t    Maalaji
        LB: Laboratoriotutkimukset / Kallionäytetutkimus
            T    Laboratoriolyhenne / Kallionäyteattribuutin nimi
            T    Tutkimustulos
            t    Yksikkö (esim. kg)
        RK: Rakeisuuskäyrä
            F    Seulamillimetri
            F    Läpäisyprosentti
    """
    return helper_str


def clearness_index(H_dn, H_ea):
    """
    Compute clearness index defined as:

    :math:`Kt=\\dfrac{H_{dn}}{H_{ea}}`

    where
    :math:`H_{dn}` is the direct-normal insolation (kWh/m2)
    :math:`H_{ea}` is the extraterrestrial insolation (kWh/m2)
    over the same time frame.
    Extraterrestrial irradiation can be computed using ``pvlib.irradiance.extraradiation``.
    Irradiation can be converted to insolation using ``pecos.pv.insolation``.

    Parameters
    -----------
    H_dn : pandas Series or float
        Direct normal insolation

    H_ea : pandas Series or float
        Extraterrestrial insolation

    Returns
    -------
    pandas Series or float
        Clearness index in a pandas Series (if H_dn or H_ea are Series) or
        float (if H_dn and H_ea are floats)
    """
    Kt = H_dn / H_ea
    return Kt


def get_text(FileName):
    """Return the text contained in the specified file"""
    src_file = open(FileName, 'r')
    text = ''
    for line in src_file.readlines():
        text += line
    return text


def clear(scrollback: bool=True, history: bool=False):
    """Clear text by type

    :param scrollback: Scrollback, Clear the scrollback history
    :type scrollback: bool
    :param history: History, Clear the command history
    :type history: bool
    """
    pass


@classmethod
def getIdentifierForCurrentRequest(kls, request):
    """ It is not possible to get the user's email address from a request"""
    return 'current'


def extract_label_signature(autodoc_line):
    """Extract the object name and signature of the object being document.

    For example::

        >>> extract_label_signature(':: foo(a, b)')
        'foo', 'foo(a, b)'
        >>> extract_label_signature(':: foo')
        'foo', None
    """
    _, what = autodoc_line.split('::')
    if '(' in what:
        signature = what.strip()
        what, *_ = what.partition('(')
    else:
        signature = None
    return what.strip(), signature


def post_install(context):
    """Post install script"""


@classmethod
def _remote_auth_url(cls, auth_url):
    """Return auth_url of the remote Keystone Service Provider.

        Remote cloud's auth_url is an endpoint for getting federated unscoped
        token, typically that would be
        ``https://remote.example.com:5000/v3/OS-FEDERATION/identity_providers/
        <idp>/protocols/<protocol_id>/auth``. However we need to generate a
        real auth_url, used for token scoping.  This function assumes there are
        static values today in the remote auth_url stored in the Service
        Provider attribute and those can be used as a delimiter. If the
        sp_auth_url doesn't comply with standard federation auth url the
        function will simply return whole string.

        :param auth_url: auth_url of the remote cloud
        :type auth_url: str

        :returns: auth_url of remote cloud where a token can be validated or
                  scoped.
        :rtype: str

        """
    PATTERN = '/OS-FEDERATION/'
    idx = auth_url.index(PATTERN) if PATTERN in auth_url else len(auth_url)
    return auth_url[:idx]


def _String(parser, propObj, propCls, propName, propHelp, shortArg, longArg,
    atype=str):
    """Adds an argument to the given parser for the given :class:`.String`
    property.

    :param parser:   An ``ArgumentParser`` instance.

    :param propCls:  A ``HasProperties`` class or instance.

    :param propObj:  The ``PropertyBase`` class.

    :param propName: Name of the property.

    :param propHelp: Custom help text for the property.

    :param shortArg: String to use as the short argument.

    :param longArg:  String to use as the long argument.

    :param atype:    Data type to expect (defaults to ``str``). This allows
                     the conversion type to be overridden for some, but not
                     all, property types.
    """
    parser.add_argument(shortArg, longArg, help=propHelp, type=atype)


def frange(start, end=None, inc=None):
    """A range function, that does accept float increments..."""
    if end == None:
        end = start + 0.0
        start = 0.0
    if inc == None:
        inc = 1.0
    L = []
    end = end - inc * 0.0001
    while 1:
        next = start + len(L) * inc
        if inc > 0 and next >= end:
            break
        elif inc < 0 and next <= end:
            break
        L.append(next)
    return L


def default_create_action_space(env, config):
    """Create an action space that can be pickled
    (or None to leave it for the remote client to sort out).
    """
    return env.action_space


def p_indexes(t):
    """trackitems : trackitem
                  | trackitems trackitem"""
    if len(t) == 2:
        t[0] = [t[1]]
    else:
        t[0] = t[1] + [t[2]]


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


def get_mxnet_model_info(model):
    """Get native MXNet model details for given Keras Model.
    `data_names` and `data_shapes` are returned that can be used to bind the model in MXNet Module.
    `data_names` and `data_shapes` represents input layer name and shape.
    You can change the first dimension of data_shapes to match batch size for inference.

    Note: You should use `save_mxnet_model()` API for saving the model in native MXNet model format.

    # Arguments
        model: Keras model instance from which to extract MXNet model details.

    # Returns
        data_names, data_shapes

    # Raises
        AssertionError if Model is not compiled.
    """
    assert model is not None, 'MXNet Backend: Invalid state. Model cannot be None.'
    symbol = model._pred_mxnet_symbol
    module = model._module
    assert symbol is not None, 'MXNet Backend: Invalid state. MXNet Symbol cannot be None.'
    assert module is not None, 'MXNet Backend: Invalid state. MXNet Module cannot be None.'
    pred_module = module._buckets['pred']
    data_names = pred_module.data_names
    data_shapes = pred_module.data_shapes
    return data_names, data_shapes


def sato(target, mol_weight='pore.molecular_weight', boiling_temperature=
    'pore.boiling_point', temperature='pore.temperature',
    critical_temperature='pore.critical_temperature'):
    """
    Uses Sato et al. model to estimate thermal conductivity for pure liquids
    from first principles at conditions of interest

    Parameters
    ----------
    target : OpenPNM Object
        The object for which these values are being calculated.  This
        controls the length of the calculated array, and also provides
        access to other necessary thermofluid properties.

    boiling_temperature :  string
        Dictionary key containing the toiling temperature of the component (K)

    mol_weight : string
        Dictionary key containing the molecular weight of the component
        (kg/mol)

    temperature : string
        The dictionary key containing the temperature values (K)

    critical_temperature : string
        The dictionary key containing the critical temperature values (K)

    Returns
    -------
    value : NumPy ndarray
        Array containing thermal conductivity values in [W/m.K]

    """
    T = target[temperature]
    Tc = target[critical_temperature]
    MW = target[mol_weight]
    Tbr = target[boiling_temperature] / Tc
    Tr = T / Tc
    value = 1.11 / (MW * 1000.0) ** 0.5 * (3 + 20 * (1 - Tr) ** (2 / 3)) / (
        3 + 20 * (1 - Tbr) ** (2 / 3))
    return value


def build_transmitter_name(network_name, site_name):
    """
    Return a string that is the network name with spaces removed followed
    by an underscore followed by the site name with spaces removed.

    EXAMPLES:

    >>> build_transmitter_name('Slap hAppy', 'Go go ')
    'SlaphAppy_Gogo'
    """
    return network_name.replace(' ', '') + '_' + site_name.replace(' ', '')


def get_item_properties(item, fields, mixed_case_fields=(), formatters=None):
    """Return a tuple containing the item properties.

    :param item: a single item resource (e.g. Server, Tenant, etc)
    :param fields: tuple of strings with the desired field names
    :param mixed_case_fields: tuple of field names to preserve case
    :param formatters: dictionary mapping field names to callables
       to format the values
    """
    if formatters is None:
        formatters = {}
    row = []
    for field in fields:
        if field in formatters:
            row.append(formatters[field](item))
        else:
            if field in mixed_case_fields:
                field_name = field.replace(' ', '_')
            else:
                field_name = field.lower().replace(' ', '_')
            if not hasattr(item, field_name) and isinstance(item, dict):
                data = item[field_name]
            else:
                data = getattr(item, field_name, '')
            if data is None:
                data = ''
            row.append(data)
    return tuple(row)


def dict_strict_update(base_dict, update_dict):
    """
    This function updates base_dict with update_dict if and only if update_dict does not contain
    keys that are not already in base_dict. It is essentially a more strict interpretation of the
    term "updating" the dict.

    If update_dict contains keys that are not in base_dict, a RuntimeError is raised.

    :param base_dict: The dict that is to be updated. This dict is modified.
    :param update_dict: The dict containing the new values.
    """
    additional_keys = set(update_dict.keys()) - set(base_dict.keys())
    if len(additional_keys) > 0:
        raise RuntimeError(
            'The update dictionary contains keys that are not part of the base dictionary: {}'
            .format(str(additional_keys)), additional_keys)
    base_dict.update(update_dict)


@classmethod
def nested(cls, src: dict, delim: str, root_key: str) ->'package':
    """ Split all keys in <src> on <delim> and nest package dicts in a hierarchy based on these splits.
            If one key is a prefix of another, it may occupy a slot needed for another level of dicts.
            If this happens, move the value one level deeper under <root_key>. """
    pkg = cls()
    for k, v in src.items():
        d = pkg
        *first, last = k.split(delim)
        for i in first:
            if i not in d:
                d[i] = cls()
            elif not isinstance(d[i], cls):
                d[i] = cls({root_key: d[i]})
            d = d[i]
        if last not in d or not isinstance(d[last], cls):
            d[last] = v
        else:
            d[last][root_key] = v
    return pkg


def get(isamAppliance, uuid, check_mode=False, force=False):
    """
    Get a specific logdb object
    """
    return isamAppliance.invoke_get('Get a specific logdb object',
        '/core/rsp_logdb_objs/{0}'.format(uuid))


def is_email_link(href=None):
    """Utility function to determine whether the supplied href attribute
    is an email link."""
    print('email_link()')
    return href and 'mailto:' in href


@classmethod
def open_newline_mode(cls, mode):
    """Returns the open() newline mode that best corresponds to the given mode."""
    if mode == cls.N or mode == cls.Unknown:
        return None
    if mode == cls.R:
        return '\r'
    if mode == cls.RN:
        return '\r\n'
    return ''


def is_gzipped(response):
    """Return True if the response is gzipped, or False otherwise"""
    ctype = response.headers.get('Content-Type', b'')
    return ctype in (b'application/x-gzip', b'application/gzip')


def bC_Mg_HS_HPM88(T, P):
    """c-a: magnesium bisulfide [HPM88]."""
    b0 = 0.17
    b1 = 2.78
    b2 = 0
    C0 = 0
    C1 = 0
    alph1 = 2
    alph2 = -9
    omega = -9
    valid = T == 298.15
    return b0, b1, b2, C0, C1, alph1, alph2, omega, valid


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


def find_keys(dict):
    """
    This function can find the keys for the dictionary

    Parameters:
        dict: The dictionary that we want the keys

    Return:
        List: list of keys in the dict
    """
    set = []
    for key in dict:
        set.append(key)
    return set


def get_derived_unit(registry, key):
    """
	Get the unit of a physcial quantity in a provided unit system.

	Parameters
	----------
	registry: dict (str: unit)
		mapping 'length', 'mass', 'time', 'current', 'temperature',
		'luminous_intensity', 'amount'. If registry is ``None`` the
		function returns 1.0 unconditionally.
	key: str
		one of the registry keys or one of: 'diffusivity', 'electricalmobility',
		'permittivity', 'charge', 'energy', 'concentration', 'density',
		'radiolytic_yield'.

	Examples
	--------
	>>> m, s = quantities.meter, quantities.second
	>>> get_derived_unit(SI_base_registry, 'diffusivity') == m**2/s
	True

	"""
    if registry is None:
        return 1.0
    derived = {'diffusivity': registry['length'] ** 2 / registry['time'],
        'electrical_mobility': registry['current'] * registry['time'] ** 2 /
        registry['mass'], 'permittivity': registry['current'] ** 2 *
        registry['time'] ** 4 / (registry['length'] ** 3 * registry['mass']
        ), 'charge': registry['current'] * registry['time'], 'energy':
        registry['mass'] * registry['length'] ** 2 / registry['time'] ** 2,
        'concentration': registry['amount'] / registry['length'] ** 3,
        'density': registry['mass'] / registry['length'] ** 3}
    derived['diffusion'] = derived['diffusivity']
    derived['radiolytic_yield'] = registry['amount'] / derived['energy']
    derived['doserate'] = derived['energy'] / registry['mass'] / registry[
        'time']
    derived['linear_energy_transfer'] = derived['energy'] / registry['length']
    try:
        return derived[key]
    except KeyError:
        return registry[key]


def _always_run(*args, **kwargs) ->bool:
    """ This returns False to indicate that the step is not already completed. """
    return False


def normalize_proportions(proportions):
    """
    Proportions specified in config file are all just relative - this normalizes them to a proportion out of 1.0
    :param proportions: The proportions dictionary generated by parse_config_file
    :return: A dictionary in the same format as that generated by parse_config_file, but with normalized values.
    """
    total_count = 0.0
    for strain in proportions:
        total_count += proportions[strain]
    for strain in proportions:
        proportions[strain] = proportions[strain] / total_count
    return proportions


def generate_presigned_url(ClientMethod=None, Params=None, ExpiresIn=None,
    HttpMethod=None):
    """
    Generate a presigned url given a client, its method, and arguments

    :type ClientMethod: string
    :param ClientMethod: The client method to presign for

    :type Params: dict
    :param Params: The parameters normally passed to
            ClientMethod.

    :type ExpiresIn: int
    :param ExpiresIn: The number of seconds the presigned url is valid
            for. By default it expires in an hour (3600 seconds)

    :type HttpMethod: string
    :param HttpMethod: The http method to use on the generated url. By
            default, the http method is whatever is used in the method's model.

    """
    pass


@classmethod
def index(cls, value):
    """Return an index into the Enum given a value."""
    return cls.ALL.index(value)


def AID(val):
    """ArticleIdentifier
    The given values do not require any work"""
    return val


@classmethod
def get_by_auth_id(cls, auth_id):
    """Returns a user object based on a auth_id.

        :param auth_id:
            String representing a unique id for the user. Examples:

            - own:username
            - google:username
        :returns:
            A user object.
        """
    return cls.query(cls.auth_ids == auth_id).get()


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 moveToCompletedForNoWQJobs(reqmgrSvc, wfStatusDict, logger):
    """
    Handle the case when request is aborted/rejected before elements are created in GQ
    """
    statusTransition = {'aborted': ['aborted-completed']}
    for status, nextStatusList in statusTransition.items():
        requests = reqmgrSvc.getRequestByStatus([status], detail=False)
        count = 0
        for wf in requests:
            if wf not in wfStatusDict:
                for nextStatus in nextStatusList:
                    reqmgrSvc.updateRequestStatus(wf, nextStatus)
                    count += 1
        logger.info('Total aborted-completed: %d', count)
    return


@classmethod
def _from_dict(cls, _dict):
    """Initialize a NluEnrichmentKeywords object from a json dictionary."""
    args = {}
    if 'sentiment' in _dict:
        args['sentiment'] = _dict.get('sentiment')
    if 'emotion' in _dict:
        args['emotion'] = _dict.get('emotion')
    if 'limit' in _dict:
        args['limit'] = _dict.get('limit')
    return cls(**args)


def describe_export_tasks(ExportTaskIds=None):
    """
    Describes one or more of your export tasks.
    See also: AWS API Documentation

    :example: response = client.describe_export_tasks(
        ExportTaskIds=[
            'string',
        ]
    )

    :type ExportTaskIds: list
    :param ExportTaskIds: One or more export task IDs.
            (string) --

    :rtype: dict
    :return: {
        'ExportTasks': [
            {
                'ExportTaskId': 'string',
                'Description': 'string',
                'State': 'active'|'cancelling'|'cancelled'|'completed',
                'StatusMessage': 'string',
                'InstanceExportDetails': {
                    'InstanceId': 'string',
                    'TargetEnvironment': 'citrix'|'vmware'|'microsoft'
                },
                'ExportToS3Task': {
                    'DiskImageFormat': 'VMDK'|'RAW'|'VHD',
                    'ContainerFormat': 'ova',
                    'S3Bucket': 'string',
                    'S3Key': 'string'
                }
            },
        ]
    }

    """
    pass


def random_sample(col, n=5, filters=None):
    """Randomly select n document from query result set. If no query specified,
    then from entire collection.

    **中文文档**

    从collection中随机选择 ``n`` 个样本。
    """
    pipeline = list()
    if filters is not None:
        pipeline.append({'$match': filters})
    pipeline.append({'$sample': {'size': n}})
    return list(col.aggregate(pipeline))


def google_has_height(style):
    """check if the style of the element has the 'height' attribute explicitly defined"""
    if 'height' in style:
        return True
    return False


def toSeconds(td):
    """Converts a timedelta to an integer representing the number of seconds
    """
    return td.seconds + td.days * 86400


def get_productions_d(productions):
    """ Get productions as a dictionary """
    productions_d = dict()
    for production in productions:
        production_head = productions_d.setdefault(production.head, [])
        production_head.append(production)
    return productions_d


def get_term_bytoken(token):
    """Return an ITokenizedTerm for the passed-in token.

        If `token` is not represented in the vocabulary, `LookupError`
        is raised.
        """


def p_global(p):
    """ global : GLOBAL LBRACKET RBRACKET
               | GLOBAL LBRACKET parameter_list RBRACKET"""
    if len(p) == 4:
        p[0] = {}
    else:
        p[0] = p[3]


def _l2_grad(A, b, x):
    """The gradient of the problem ||Ax - b||^2 wrt x.
    """
    return A.T @ (A @ x - b)


def chunk_iter(chunk_size, upperbound):
    """Yields back chunk size pieces from zero to upperbound - 1."""
    chunk = []
    for i in range(0, upperbound):
        chunk.append(i)
        if len(chunk) == chunk_size:
            yield chunk
            chunk = []


def __call__():
    """ Returns a list of dicts with the following keys:

            img: the url to the image to be displayed
            title: the caption to be displayed
            url: a link to be placed on the image
        """


def fragileX(geno):
    """A disease model where an individual has increased risk of
    affected if the number of tandem repeats exceed 75.
    """
    maxRep = max(geno)
    if maxRep < 50:
        return 0
    else:
        return min(1, (maxRep - 50) * 0.05)


def sorted_by_precedence(values):
    """
    Return ``values`` sorted ascending by their ``precedence`` property.

    :param values: Sequence of values to sort (each value must have a
                   ``precedence`` property)
    :return: Sorted list of values
    :rtype: :class:`list`
    """
    return sorted(values, key=lambda value: -value.precedence)


@classmethod
def replace_non_letters_non_numbers_with_whitespace(cls, a_string):
    """
        This function replaces any sequence of non letters and non
        numbers with a single white space.
        """
    return cls.regex.sub(' ', a_string)


def unpack(iterable):
    """ Helper function to unpack an iterable """
    unpacked = []
    for tt in iterable:
        for t in tt:
            unpacked.append(t)
    return unpacked


def block(data, size):
    """Reshape image stack for faster processing"""
    return data.reshape(data.shape[0] // size, size, -1, size).swapaxes(1, 2
        ).reshape(-1, size, size)


def read_file(path):
    """
    Read an APKBUILD file

    :param path: full path to the APKBUILD
    :returns: contents of an APKBUILD as a list of strings
    """
    with open(path, encoding='utf-8') as handle:
        lines = handle.readlines()
        if handle.newlines != '\n':
            raise RuntimeError('Wrong line endings in APKBUILD: ' + path)
    return lines


def mesh_linked_uv_islands(mesh: 'bpy.types.Mesh') ->list:
    """Splits the mesh into connected polygons, use this for separating cubes from other mesh elements within 1 mesh datablock.

    :param mesh: the mesh used to group with.
    :type mesh: 'bpy.types.Mesh'
    :return:  lists of lists containing polygon indices
    """
    pass


def dump_stats(myStats):
    """
    Show stats when pings are done
    """
    print('\n----%s PYTHON PING Statistics----' % myStats.thisIP)
    if myStats.pktsSent > 0:
        myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd
            ) / myStats.pktsSent
    print(
        '%d packets transmitted, %d packets received, %0.1f%% packet loss' %
        (myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss))
    if myStats.pktsRcvd > 0:
        print('round-trip (ms)  min/avg/max = %d/%0.1f/%d' % (myStats.
            minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime))
    print('')
    return


def iter_fields(node):
    """
    Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
    that is present on *node*.
    """
    for field in node._fields:
        try:
            yield field, getattr(node, field)
        except AttributeError:
            pass


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

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

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


def cmd_exists(cmds_list, cmd):
    """Check if given command is in list of available commands

    @param cmds_list: see L{RTorrent._rpc_methods}
    @type cmds_list: list

    @param cmd: name of command to be checked
    @type cmd: str

    @return: bool
    """
    return cmd in cmds_list


def get_required_capabilities(data: dict):
    """
    Get capabilities for a given cloud formation template for the
    "create_stack" call
    """
    capabilities = []
    for _, config in data.get('Resources', {}).items():
        if config.get('Type').startswith('AWS::IAM'):
            if config.get('Properties', {}).get('RoleName'):
                capabilities.append('CAPABILITY_NAMED_IAM')
            else:
                capabilities.append('CAPABILITY_IAM')
    return capabilities


def _heidke_skill_score(table):
    """This function is borrowed with modification from the hagelslag repository
    MulticlassContingencyTable class. It is used here with permission of
    David John Gagne II <djgagne@ou.edu>
    """
    n = float(table.sum())
    nf = table.sum(axis=1)
    no = table.sum(axis=0)
    correct = float(table.trace())
    return (correct / n - (nf * no).sum() / n ** 2) / (1 - (nf * no).sum() /
        n ** 2)


def _resample_function(function, game, _):
    """Function for resampling"""
    return function(game.resample())


def parameters_ui(layout, params):
    """ Create the ui for the rig parameters."""
    r = layout.row()
    r.prop(params, 'limb_type')
    r = layout.row()
    r.prop(params, 'rotation_axis')
    r = layout.row()
    r.prop(params, 'segments')
    r = layout.row()
    r.prop(params, 'bbones')
    for layer in ['fk', 'tweak']:
        r = layout.row()
        r.prop(params, layer + '_extra_layers')
        r.active = params.tweak_extra_layers
        col = r.column(align=True)
        row = col.row(align=True)
        for i in range(8):
            row.prop(params, layer + '_layers', index=i, toggle=True, text='')
        row = col.row(align=True)
        for i in range(16, 24):
            row.prop(params, layer + '_layers', index=i, toggle=True, text='')
        col = r.column(align=True)
        row = col.row(align=True)
        for i in range(8, 16):
            row.prop(params, layer + '_layers', index=i, toggle=True, text='')
        row = col.row(align=True)
        for i in range(24, 32):
            row.prop(params, layer + '_layers', index=i, toggle=True, text='')


def ensure_read_preference_type(key, value):
    """Raise a TypeError if the value is not a type compatible for ReadPreference."""
    for attr in ('document', 'mode', 'mongos_mode', 'max_staleness'):
        if not hasattr(value, attr):
            raise TypeError('{} must be an instance of {}'.format(key,
                'pymongo.read_preference.ReadPreference'))


def version():
    """
    Returns the package version
    as defined in configure.ac
    in string format
    """
    return '1.6.0'


def is_bullish_engolfing(body, open, close):
    """ Se existir engolfo de alta retorna True."""
    if body[1] > 0 and body[0] < 0:
        if open[1] <= close[0] and close[1] >= open[0]:
            return True
    return False


def unlock(resource, owner_or_ownerid):
    """

        Unlock a resource using the lock service.  If the resource is already
        locked by a user other than the owner supplied as owner_or_ownerid or
        the resource isn't already locked with this lock type, calling this
        method will raise a :class:`substanced.locking.LockError` exception.
        Otherwise the lock will be removed.

        .. warning::

           Callers should assert that the owner has the ``sdi.lock`` permission
           against the resource before calling this function to ensure that a
           user can't lock a resource he is not permitted to.
       """


def process_default_input(dict_):
    """This functions processes the default input parameters"""
    try:
        dict_['ESTIMATION']['trim_support']
    except KeyError:
        trim = True
    else:
        trim = dict_['ESTIMATION']['trim_support']
    try:
        dict_['ESTIMATION']['reestimate_p']
    except KeyError:
        reestimate_p = False
    else:
        reestimate_p = dict_['ESTIMATION']['reestimate_p']
    try:
        dict_['ESTIMATION']['rbandwidth']
    except KeyError:
        rbandwidth = 0.05
    else:
        rbandwidth = dict_['ESTIMATION']['rbandwidth']
    return trim, rbandwidth, reestimate_p


def converse_nonimplication(a, b):
    """ if a is False, b must be True """
    return not a and b


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

        :param SharedLinkSettingsChangeExpirationDetails val:
        :rtype: EventDetails
        """
    return cls('shared_link_settings_change_expiration_details', val)


@staticmethod
def read(reader, _index):
    """
        Reads Zserio float16 type from the bit stream.

        :param reader: Bit stream from which to read.
        :param _index: Not used.
        """
    return reader.readFloat16()


def list_review_policy_results_for_hit(HITId=None, PolicyLevels=None,
    RetrieveActions=None, RetrieveResults=None, NextToken=None, MaxResults=None
    ):
    """
    The ListReviewPolicyResultsForHIT operation retrieves the computed results and the actions taken in the course of executing your Review Policies for a given HIT. For information about how to specify Review Policies when you call CreateHIT, see Review Policies. The ListReviewPolicyResultsForHIT operation can return results for both Assignment-level and HIT-level review results.
    See also: AWS API Documentation

    :example: response = client.list_review_policy_results_for_hit(
        HITId='string',
        PolicyLevels=[
            'Assignment'|'HIT',
        ],
        RetrieveActions=True|False,
        RetrieveResults=True|False,
        NextToken='string',
        MaxResults=123
    )

    :type HITId: string
    :param HITId: [REQUIRED]
            The unique identifier of the HIT to retrieve review results for.

    :type PolicyLevels: list
    :param PolicyLevels: The Policy Level(s) to retrieve review results for - HIT or Assignment. If omitted, the default behavior is to retrieve all data for both policy levels. For a list of all the described policies, see Review Policies.
            (string) --

    :type RetrieveActions: boolean
    :param RetrieveActions: Specify if the operation should retrieve a list of the actions taken executing the Review Policies and their outcomes.

    :type RetrieveResults: boolean
    :param RetrieveResults: Specify if the operation should retrieve a list of the results computed by the Review Policies.

    :type NextToken: string
    :param NextToken: Pagination token

    :type MaxResults: integer
    :param MaxResults: Limit the number of results returned.

    :rtype: dict
    :return: {
        'HITId': 'string',
        'AssignmentReviewPolicy': {
            'PolicyName': 'string',
            'Parameters': [
                {
                    'Key': 'string',
                    'Values': [
                        'string',
                    ],
                    'MapEntries': [
                        {
                            'Key': 'string',
                            'Values': [
                                'string',
                            ]
                        },
                    ]
                },
            ]
        },
        'HITReviewPolicy': {
            'PolicyName': 'string',
            'Parameters': [
                {
                    'Key': 'string',
                    'Values': [
                        'string',
                    ],
                    'MapEntries': [
                        {
                            'Key': 'string',
                            'Values': [
                                'string',
                            ]
                        },
                    ]
                },
            ]
        },
        'AssignmentReviewReport': {
            'ReviewResults': [
                {
                    'ActionId': 'string',
                    'SubjectId': 'string',
                    'SubjectType': 'string',
                    'QuestionId': 'string',
                    'Key': 'string',
                    'Value': 'string'
                },
            ],
            'ReviewActions': [
                {
                    'ActionId': 'string',
                    'ActionName': 'string',
                    'TargetId': 'string',
                    'TargetType': 'string',
                    'Status': 'Intended'|'Succeeded'|'Failed'|'Cancelled',
                    'CompleteTime': datetime(2015, 1, 1),
                    'Result': 'string',
                    'ErrorCode': 'string'
                },
            ]
        },
        'HITReviewReport': {
            'ReviewResults': [
                {
                    'ActionId': 'string',
                    'SubjectId': 'string',
                    'SubjectType': 'string',
                    'QuestionId': 'string',
                    'Key': 'string',
                    'Value': 'string'
                },
            ],
            'ReviewActions': [
                {
                    'ActionId': 'string',
                    'ActionName': 'string',
                    'TargetId': 'string',
                    'TargetType': 'string',
                    'Status': 'Intended'|'Succeeded'|'Failed'|'Cancelled',
                    'CompleteTime': datetime(2015, 1, 1),
                    'Result': 'string',
                    'ErrorCode': 'string'
                },
            ]
        },
        'NextToken': 'string'
    }

    :returns:
    (string) --

    """
    pass


def alarm(name, message):
    """Issues the given alarm with the given message.

    :param str|unicode name:

    :param str|unicode message: Message to pass to alarm.

    :rtype: None
    """


@classmethod
def set_signature(cls, data, signature):
    """
        Set the clearsigned signature
        """
    doc_id = data['id']
    cls.write([cls(doc_id)], {'digital_signature': signature})


def desc_from_builder(builder):
    """ Desc From Builder """
    class_name = builder.__class__.__name__
    if 'CMakeBuilder' in class_name:
        return 'C++ projects'
    if 'Linguist' in class_name:
        return 'translations'
    if 'Python' in class_name:
        return 'Python projects'
    return None


def _get_best_indexes(logits, n_best_size):
    """Get the n-best logits from a list."""
    index_and_score = sorted(enumerate(logits), key=lambda x: x[1], reverse
        =True)
    best_indexes = []
    for i in range(len(index_and_score)):
        if i >= n_best_size:
            break
        best_indexes.append(index_and_score[i][0])
    return best_indexes


@staticmethod
def get_dpi(value=1):
    """
        Returns current DPI used by DCC
        :param value: float
        :return: float
        """
    return 1.0


def _create_json(name, description, locked, type, jndiId, connection,
    connectionManager):
    """
    Create a JSON to be used for the REST API call
    """
    json = {'connection': connection, 'type': type, 'jndiId': jndiId,
        'name': name, 'description': description, 'locked': locked}
    if connectionManager is not None:
        json['connectionManager'] = connectionManager
    return json


def squish(s, n):
    """Truncate the middle of a string s so that it fits within a length n."""
    if len(s) > n:
        if n > 30:
            s = '{} ... {}'.format(s[0:int(n / 2) - 2], s[-int(n / 2) + 2:])
        else:
            s = '{}…{}'.format(s[0:int(n / 2)], s[-int(n / 2) + 1:])
    return s


def byte2bit_string(data):
    """
    >>> byte2bit_string(0x1b)
    '00011011'
    """
    return f'{data:08b}'


@staticmethod
def _get_placeholders(items):
    """Returns a string of placeholders, one for each item in
        `items`.

        :param items: items to create placeholders for
        :type items: `list`
        :rtype: `str`

        """
    return ('?,' * len(items)).strip(',')


def pearson7(x, a0, a1, a2, a3):
    """compute a Peason7 peak

    Inputs
    ------
    x : ndarray
        the positions at which the signal should be sampled
    a0, a1, a2, a3 : float or ndarrays of size equal to x.shape
        parameters of the Pearson7 equation

    Returns
    -------
    out : ndarray
        the signal

    Remarks
    -------
    Formula is a0 * (1/ ( (1 + ((x-a1)/a2))**2 * (2**(1/a3) -1))**a3
    """
    return a0 / (1.0 + ((x - a1) / a2) ** 2.0 * (2.0 ** (1.0 / a3) - 1.0)
        ) ** a3


def get_files(resource, bucket_name, prefix=''):
    """List only files inside a bucket (DIR excluded)."""
    files = []
    bucket = resource.Bucket(bucket_name)
    for file_ in bucket.objects.filter(Prefix=prefix):
        files.append(file_)
    return files


def create_branch(repositoryName=None, branchName=None, commitId=None):
    """
    Creates a new branch in a repository and points the branch to a commit.
    See also: AWS API Documentation

    :example: response = client.create_branch(
        repositoryName='string',
        branchName='string',
        commitId='string'
    )

    :type repositoryName: string
    :param repositoryName: [REQUIRED]
            The name of the repository in which you want to create the new branch.

    :type branchName: string
    :param branchName: [REQUIRED]
            The name of the new branch to create.

    :type commitId: string
    :param commitId: [REQUIRED]
            The ID of the commit to point the new branch to.

    """
    pass


def peek(key):
    """
        Similar to ``__getitem__``, but *does not* count
        as a hit on the key, merely returns a value if its present.
        """


@staticmethod
def p_daq_list_can_id_optional_optional(p):
    """daq_list_can_id_optional_optional : empty
                                             | daq_list_can_id_optional"""
    p[0] = tuple() if p[1] is None else (p[1],)


def bitstrBE(byte):
    """
    make a bit string from big endian byte

    :param byte byte: a byte
    :return: a string of ones and zeros, the bbits in the byte
    """
    bits = ''
    for i in range(8):
        if byte[0] >> i & 1:
            bits += '1'
        else:
            bits += '0'
    return bits


def len_in_bits(n):
    """
    Return number of bits in binary representation of @n.
    """
    try:
        return n.bit_length()
    except AttributeError:
        if n == 0:
            return 0
        return len(bin(n)) - 2


def _emplace_transcript(transcripts, parent):
    """Retrieve the primary transcript and discard all others."""
    transcripts.sort(key=lambda t: (len(t), t.get_attribute('ID')))
    pt = transcripts.pop()
    parent.children = [pt]


def p_base_variable(p):
    """base_variable : simple_indirect_reference
                     | static_member"""
    p[0] = p[1]


def _donothing_func(*args, **kwargs):
    """Perform no good and no bad"""
    pass


@staticmethod
def _get_all_parent_nodes_nested(path, delimiter='/'):
    """Get path to all parent nodes for current leaf, starting from root down to leaf's direct parent, and return only the relative key (not the fullkey)"""
    pos = path.find(delimiter)
    lastpos = 0
    while pos != -1:
        yield path[lastpos:pos]
        lastpos = pos + 1
        pos = path.find(delimiter, pos + 1)


def clean_string(txt):
    """ Returns txt without special characters """
    for character in '*."/\\[]:;|, ':
        txt = txt.replace(character, '')
    return txt


def list2numpy(l, dtype=object):
    """Converts python list of Diofant expressions to a NumPy array.

    See Also
    ========

    diofant.matrices.dense.matrix2numpy

    """
    from numpy import empty
    a = empty(len(l), dtype)
    for i, s in enumerate(l):
        a[i] = s
    return a


def _get_bar_type(ptype, pid_ref):
    """helper method for _get_bar_yz_arrays"""
    if ptype in ['PBAR', 'PBEAM']:
        bar_type = 'bar'
    elif ptype in ['PBARL', 'PBEAML']:
        bar_type = pid_ref.Type
    elif ptype == 'PBCOMP':
        bar_type = 'pbcomp'
    else:
        raise NotImplementedError(pid_ref)
    return bar_type


def realpath(*unused_args, **unused_kwargs):
    """Method os.path.realpath() is forbidden"""
    raise RuntimeError(
        'Usage of os.path.realpath() is forbidden. Use certbot.compat.filesystem.realpath() instead.'
        )


def encode_value(v):
    """If the value contains a semicolon, or starts with a left curly brace,
    then enclose it in curly braces and escape all right curly braces.
    """
    if ';' in v or v.strip(' ').startswith('{'):
        return '{%s}' % (v.replace('}', '}}'),)
    return v


def p_expr_big_op_u(p):
    """p_expr_big_op_u : BIGOP UP LBRACE expression RBRACE"""
    p[0] = p[1], p[4]


def jellyFor(jellier):
    """
        Jelly myself for jellier.
        """


def rand_str(length):
    """Generate random string"""
    import string, random
    available_chars = string.ascii_uppercase + string.digits
    return ''.join(random.choice(available_chars) for _ in range(length))


def sma(series, n, m):
    """
    扩展指数加权移动平均: 求series序列n周期的扩展指数加权移动平均

        计算公式:
        sma(x, n, m) = sma(x, n, m).shift(1) * (n - m) / n + x(n) * m / n

        注意: n必须大于m

    Args:
        series (pandas.Series): 数据序列

        n (int): 周期

        m (int): 权重

    Returns:
        pandas.Series: 扩展指数加权移动平均序列

    Example::

        from tqsdk import TqApi, TqSim, tafunc

        api = TqApi(TqSim())
        klines = api.get_kline_serial("CFFEX.IF1908", 24 * 60 * 60)
        sma = tafunc.sma(klines.close, 5, 2)  # 收盘价序列每5项计算一个扩展指数加权移动平均值
        print(list(sma))
    """
    sma_data = series.ewm(alpha=m / n, adjust=False).mean()
    return sma_data


def export_off(vertices, triangles, filename):
    """
    Exports a mesh in the (.off) format.
    """
    with open(filename, 'w') as fh:
        fh.write('OFF\n')
        fh.write('{} {} 0\n'.format(len(vertices), len(triangles)))
        for v in vertices:
            fh.write('{} {} {}\n'.format(*v))
        for f in triangles:
            fh.write('3 {} {} {}\n'.format(*f))


def uniquifying(items):
    """
    Yield items while excluding the duplicates and preserving the order.

    >>> list(uniquifying([1, 2, 1, 2, 3]))
    [1, 2, 3]
    """
    seen = set()
    for x in items:
        if x not in seen:
            yield x
        seen.add(x)


def lowest(f, c, p=20):
    """Calculate the lowest value on a rolling basis.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe containing the column ``c``.
    c : str
        Name of the column in the dataframe ``f``.
    p : int
        The period over which to calculate the rolling minimum.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    """
    return f[c].rolling(p).min()


def _printErrorMessage(response):
    """
    Method to print infromation of an error returned by the API to the console
    Builds the error description from the response object
    """
    status = response.status_code
    if status == 400:
        print('\nError 400 - Bad Request: {:s}'.format(response.url))
        payload = response.json()
        if len(payload) >= 1:
            for e in payload['errors']:
                code = e['errorCode']
                msg = e['errorMessage']
                parameters = e['parameter']
                print('   Error {:d}: {:s} (parameter: {})'.format(code,
                    msg, parameters))
    elif status == 401:
        print('Error 401 - Unauthorized: {:s}'.format(response.url))
        print(
            'Please check that your Web Services API token is valid. Find your token in your registered profile at https://data.oceannetworks.ca.'
            )
    else:
        msg = '\nError {:d} - {:s}\n'.format(status, response.reason)
        print(msg)


def filetypes():
    """Get supported graph description filetypes for network import."""
    d = {'gml': 'Graph Modelling Language', 'graphml':
        'Graph Markup Language', 'xml': 'Graph Markup Language', 'dot':
        'GraphViz DOT'}
    return d


@staticmethod
def encode(value):
    """Encode a DER UTF-8 string"""
    return value.encode('utf-8')


def _graph_view_revisions(branch, start_rev_id, end_rev_id,
    rebase_initial_depths=True, exclude_common_ancestry=False):
    """Calculate revisions to view including merges, newest to oldest.

    :param branch: the branch
    :param start_rev_id: the lower revision-id
    :param end_rev_id: the upper revision-id
    :param rebase_initial_depth: should depths be rebased until a mainline
      revision is found?
    :return: An iterator of (revision_id, dotted_revno, merge_depth) tuples.
    """
    if exclude_common_ancestry:
        stop_rule = 'with-merges-without-common-ancestry'
    else:
        stop_rule = 'with-merges'
    view_revisions = branch.iter_merge_sorted_revisions(start_revision_id=
        end_rev_id, stop_revision_id=start_rev_id, stop_rule=stop_rule)
    if not rebase_initial_depths:
        for rev_id, merge_depth, revno, end_of_merge in view_revisions:
            yield rev_id, '.'.join(map(str, revno)), merge_depth
    else:
        depth_adjustment = None
        for rev_id, merge_depth, revno, end_of_merge in view_revisions:
            if depth_adjustment is None:
                depth_adjustment = merge_depth
            if depth_adjustment:
                if merge_depth < depth_adjustment:
                    depth_adjustment = merge_depth
                merge_depth -= depth_adjustment
            yield rev_id, '.'.join(map(str, revno)), merge_depth


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

        :param NoPasswordLinkViewCreateReportDetails val:
        :rtype: EventDetails
        """
    return cls('no_password_link_view_create_report_details', val)


def sequence(context, data):
    """Generate a sequence of numbers.

    It is the memorious equivalent of the xrange function, accepting the
    ``start``, ``stop`` and ``step`` parameters.

    This can run in two ways:
    * As a single function generating all numbers in the given range.
    * Recursively, generating numbers one by one with an optional ``delay``.

    The latter mode is useful in order to generate very large sequences
    without completely clogging up the user queue.

    If an optional ``tag`` is given, each number will be emitted only once
    across multiple runs of the crawler.
    """
    number = data.get('number', context.params.get('start', 1))
    stop = context.params.get('stop')
    step = context.params.get('step', 1)
    delay = context.params.get('delay')
    prefix = context.params.get('tag')
    while True:
        tag = None if prefix is None else '%s:%s' % (prefix, number)
        if tag is None or not context.check_tag(tag):
            data['number'] = number
            context.emit(data=data)
        if tag is not None:
            context.set_tag(tag, True)
        number = number + step
        if step > 0 and number >= stop:
            break
        if step < 0 and number <= stop:
            break
        if delay is not None:
            data['number'] = number
            context.recurse(data=data, delay=delay)
            break


@classmethod
def from_dict(cls, d):
    """
        >>> x = DataArray.from_dict({'x': [2, 3]})
        """
    return cls(d)


@staticmethod
def _is_zipped(str_text: str) ->bool:
    """Checks whether given sequence is compressed with zip"""
    if len(str_text) < 2:
        return False
    return (str_text[0], str_text[1]) == (int('78', base=16), int('9c',
        base=16))


def _zones_to_regions(zones):
    """
    Return list of regions from the input list of zones
    :param zones: List of zones. This is the output from `get_zones_in_project()`.
    :return: List of regions available to the project
    """
    regions = set()
    for z in zones:
        r = z['name'][:-2]
        regions.add(r)
    return list(regions)


@classmethod
def cursor_up(cls, no_of_chars):
    """ moves the cursor up"""
    print(u'\x1b[' + str(no_of_chars) + 'A')


@classmethod
def allowed_to_disconnect(cls, user, backend_name, association_id=None):
    """Return if it's safe to disconnect the social account for the
        given user"""
    raise NotImplementedError('Implement in subclass')


@classmethod
def _build_containerized_extractors(cls, containers, container_annos,
    template, tree):
    """
        Convert container annotation trees into container extractors.
        """
    container_extractors = []
    for container_name, container_data in tree.items():
        if container_name not in containers:
            continue
        container = container_annos[container_name]
        annotation = None
        for a in template.annotations:
            if a.metadata.get('id') == container_name:
                annotation = a
                break
        if container:
            cls._add_new_container(annotation, container_extractors,
                container_data, template, container_annos, container)
    return container_extractors


@classmethod
def load(cls, path):
    """Load an item from a file."""
    return cls()


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 _k_dummy(wl):
    """ Dummy k value to be used with the dielectric model, which produces the refractive index as a complex
        number.

        :param wl: Wavelength of the light in nm.
        :return: The k value at each wavelength... set to zero.
        """
    return 0.0


def split_func(string):
    """
    Take a string like 'requiredIf("arg_name")'
    return the function name and the argument:
    (requiredIf, arg_name)
    """
    ind = string.index('(')
    return string[:ind], string[ind + 1:-1].strip('"')


def create_link(url):
    """Create an html link for the given url"""
    return f'{url}'


def stripnull(string, null=b'\x00'):
    """Return string truncated at first null character.

    Clean NULL terminated C strings. For unicode strings use null='\\0'.

    >>> stripnull(b'string\\x00')
    b'string'
    >>> stripnull('string\\x00', null='\\0')
    'string'

    """
    i = string.find(null)
    return string if i < 0 else string[:i]


def __getitem__(key):
    """Return the current state of key (a filename) in the dirstate.

        States are:
          n  normal
          m  needs merging
          r  marked for removal
          a  marked for addition
          ?  not tracked
        """


def get_all(isamAppliance):
    """
    Get all features
    """
    return isamAppliance.invoke_get('Get all features',
        '/authorization/features/v1')


def line_last_two_words(line):
    """return last two words"""
    if len(line.split()) > 1:
        return ' '.join([line.split()[-2], line.split()[-1]])
    else:
        return ''


def _get_filename(fd):
    """
    Helper function to get to file name from a file descriptor or filename.

    :param fd: file descriptor or filename.

    :returns: the filename.
    """
    if hasattr(fd, 'name'):
        return fd.name
    return fd


def _identity(X):
    """The identity function.
    """
    return X


def update_extra_fields(subtype, chan, num, aux_note, update):
    """
    Update the field if the current annotation did not
    provide a value.

    - aux_note and sub are set to default values if missing.
    - chan and num copy over previous value if missing.
    """
    if update['subtype']:
        subtype.append(0)
    if update['chan']:
        if chan == []:
            chan.append(0)
        else:
            chan.append(chan[-1])
    if update['num']:
        if num == []:
            num.append(0)
        else:
            num.append(num[-1])
    if update['aux_note']:
        aux_note.append('')
    return subtype, chan, num, aux_note


@staticmethod
def gcd(a, b):
    """
        Calculates the Greatest Common Divisor.

        :param a: the first number.
        :param b: the second number.
        :return: GCD(a, b)
        """
    while b:
        a, b = b, a % b
    return a


def _to_bool(s):
    """
    Given a bool or a string representing a boolean value sent over
    JSON, returns the corresponding bool.
    """
    if s is True or s is False:
        return s
    elif s == 'true':
        return True
    elif s == 'false':
        return False
    else:
        assert False, "Error: '%s' is not bool or JSON boolean" % str(s)


def setup_info_args(parser, parent):
    """Helper function to set up a subparser for the `info` command.

    :param parser: argparse parser to add the `info` command to
    :type args: argparse.ArgumentParser
    :param parent: argparse parser parent of the newly added subcommand.
                   used to inherit shared commands/flags
    :type args: argparse.ArgumentParser
    :return: the newly added parser
    :rtype: argparse.ArgumentParser
    """
    parser_info = parser.add_parser('info', description=
        'Display package and citation information', help=
        'Display package and citation information', parents=[parent],
        add_help=False)
    return parser_info


def have_pyrex():
    """
    Return True if Cython or Pyrex can be imported.
    """
    pyrex_impls = 'Cython.Distutils.build_ext', 'Pyrex.Distutils.build_ext'
    for pyrex_impl in pyrex_impls:
        try:
            __import__(pyrex_impl, fromlist=['build_ext']).build_ext
            return True
        except Exception:
            pass
    return False


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

        :param FileResolveCommentDetails val:
        :rtype: EventDetails
        """
    return cls('file_resolve_comment_details', val)


def position(x1, y1, x2, y2, epsilon=0.1):
    """Returns a function that computes whether a 2D bounding box has certain
    co-ordinates (+/- epsilon).

    The output function takes in a 2D bounding box (dict with keys 'x1', 'x2',
    'y1', 'y2') and returns ``True`` if the absolute difference between the
    dict's values and the specified co-ordinates are all less than ``epsilon``.

    Args:
        x1: Value to compare against the bounding box's 'x1' field.
        y1: Value to compare against the bounding box's 'y1' field.
        x2: Value to compare against the bounding box's 'x2' field.
        y2: Value to compare against the bounding box's 'y2' field.
        epsilon: Maximum difference against specified co-ordinates.

    Returns:
        A function that takes a 2D bounding box and returns ``True`` if the
        bounding box's spatial co-ordinates are all within ``epsilon`` of ``x1``,
        ``y1``, ``x2``, and ``y2``.
    """
    return lambda bbox: abs(bbox['x1'] - x1) < epsilon and abs(bbox['y1'] - y1
        ) < epsilon and abs(bbox['x2'] - x2) < epsilon and abs(bbox['y2'] - y2
        ) < epsilon


@classmethod
def from_data(cls, scene, context):
    """Creates a :class:`compas.files.GLTFScene` from a glTF scene dictionary
        and inserts it in the provided context.

        Parameters
        ----------
        scene : dict
        context : :class:`compas.files.GLTFContent`

        Returns
        -------
        :class:`compas.files.GLTFScene`
        """
    if scene is None:
        return None
    return cls(context=context, children=scene.get('nodes'), name=scene.get
        ('name'), extras=scene.get('extras'), extensions=scene.get(
        'extensions'))


def background(url):
    """This action will run an addon in the background for the provided URL.

    See 'XBMC.RunPlugin()' at
    http://wiki.xbmc.org/index.php?title=List_of_built-in_functions.
    """
    return 'XBMC.RunPlugin(%s)' % url


def onCommand(game, commandClass, username, args):
    """
    Event Hook: onCommand
    Extend the default behaviour for some commands
    """
    if commandClass.__name__ == 'MessageCommand':
        message = ' '.join(args[1:])
        modInstance = game.getModInstance('ClientMod')
        modInstance.chatMessages[args[0]] = modInstance.chatMessages.get(args
            [0], []) + [message]
        if args[0] not in ['global', 'local']:
            gui = game.getGUIState()
            chatOverlay = game.getModInstance('ClientMod').chatOverlay
            if gui:
                if gui.isOverlayOpen(chatOverlay) and gui.getOverlay(
                    chatOverlay).tab == args[0]:
                    return
                gui.gui[1].notifications.append(args[0])


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 gzip_file(source, sink):
    """
    Create a GZIP file from a source file.

    Parameters
    ----------
    source : str
        Filepath
    sink : str
        Filepath
    """
    import gzip
    with open(source, 'rb') as f_in, gzip.open(sink, 'wb') as f_out:
        f_out.writelines(f_in)


@classmethod
def roots(cls):
    """Get all roots, nodes without parents"""
    return cls.tree.roots()


def ingredients(count):
    """Prints ingredients for making `count` arepas."""
    print('{:.2} cups arepa flour'.format(0.1 * count))
    print('{:.2} cups cheese'.format(0.1 * count))
    print('{:.2} cups water'.format(0.025 * count))


@classmethod
def save(cls, ob):
    """
        Save single object `ob` to `/classes/cls`
        :param ob:
        :return:
            `response` like { "createdAt": "...", "objectId": "..."}
        """
    return cls._save_to_avos(cls.__name__, ob)


def make_tensor_5d(t):
    """Extends a tensor or numpy array to have exactly 5 dimensions.

    In doing so, it interprets 1d tensors as being aligned
    in time, 2d tensors to be aligned in space, etc.

        - 1d: t[None,None,:,None,None]
        - 2d: t[None,None,None,:,:]
        - 3d: t[None,None,:,:,:]
        - 4d: t[None,:,:,:,:]
        - 5d: t
        - 6d and more: selects the first element of t until t has 5 dimensions

    """
    if type(t.shape) is tuple:
        if len(t.shape) > 5:
            while len(t.shape) > 5:
                t = t[0]
        if len(t.shape) == 4:
            t = t[None]
        if len(t.shape) == 3:
            t = t[None, None]
        if len(t.shape) == 2:
            t = t[None, None, None]
        if len(t.shape) == 1:
            t = t[(None), (None), :, (None), (None)]
        return t
    else:
        if len(t.size()) > 5:
            while len(t.shape) > 5:
                t = t[0]
        if len(t.size()) == 4:
            t = t[None]
        if len(t.size()) == 3:
            t = t[None, None]
        if len(t.size()) == 2:
            t = t[None, None, None]
        if len(t.size()) == 1:
            t = t[(None), (None), :, (None), (None)]
        return t