def register(function, first_interval: float=0, persistent: bool=False):
    """Add a new function that will be called after the specified amount of seconds. The function gets no arguments and is expected to return either None or a float. If None is returned, the timer will be unregistered. A returned number specifies the delay until the function is called again. functools.partial can be used to assign some parameters.

    :param function: The function that should called.
    :param first_interval: Seconds until the callback should be called the first time.
    :type first_interval: float
    :param persistent: Don’t remove timer when a new file is loaded.
    :type persistent: bool
    """
    pass


@staticmethod
def _handle_selection(selection):
    """
        Dummy placeholder for returning selection from chooser.
        """
    return selection


def skip_digits(string):
    """Skips over any potential digits (including spaces) to the next
    non-digit character and return its index. If no such character is
    found or if the first character in the string is not a digit then
    specify that the skip has failed.

    :param str string: The string to search
    :returns: a 2-tuple with the first entry indicating if a valid     character has been found and the second entry indicating the index     of this character in the 'string' argument.
    :rtype: (bool, int)

    """
    found = False
    index = 0
    for index, char in enumerate(string):
        if not (char.isdigit() or char == ' '):
            if index > 0:
                found = True
            break
    return found, index


def filter_by_type(list_, filter_type):
    """ Filter the given list down to a list of the given types.

        :param list_: The unfiltered list.
        :param filter_type: The type of element to filter down too.
        :return: The filtered list, with only elements of the given type.
    """
    filtered_list = []
    for item in list_:
        if type(item) is filter_type:
            filtered_list.append(item)
    return filtered_list


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


@classmethod
def sort(cls, columns, by=[], reverse=False):
    """
        Cubes are assumed to be sorted by default.
        """
    return columns


def parse_address(addr):
    """Parse a socket address.

        >>> parse_address('1234')
        ('localhost', 1234)

        >>> parse_address('example.com:1234')
        ('example.com', 1234)

        >>> parse_address('*:1234')
        ('', 1234)

        >>> try: parse_address('notanumber')
        ... except ValueError as e: print(e)
        Invalid address: notanumber

        >>> try: parse_address('la:la:la')
        ... except ValueError as e: print(e)
        Invalid address: la:la:la

    """
    if ':' in addr:
        try:
            host, port = addr.split(':')
        except ValueError:
            raise ValueError('Invalid address: %s' % addr)
    else:
        host, port = 'localhost', addr
    if host == '*':
        host = ''
    try:
        return host, int(port)
    except ValueError:
        raise ValueError('Invalid address: %s' % addr)


def path_to_location(path):
    """Messages take a `repeated string` of path components."""
    if path.startswith('/'):
        path = path[1:]
    return path.split('/')


def hmsm_to_days(hour=0, min=0, sec=0, micro=0):
    """
    Convert hours, minutes, seconds, and microseconds to fractional days.

    Parameters
    ----------
    hour : int, optional
        Hour number. Defaults to 0.

    min : int, optional
        Minute number. Defaults to 0.

    sec : int, optional
        Second number. Defaults to 0.

    micro : int, optional
        Microsecond number. Defaults to 0.

    Returns
    -------
    days : float
        Fractional days.

    Examples
    --------
    >>> hmsm_to_days(hour=6)
    0.25

    """
    days = sec + micro / 1000000.0
    days = min + days / 60.0
    days = hour + days / 60.0
    return days / 24.0


def finish_upgrade_tarball_install(old_install_dir_path, new_install_dir_path):
    """Performs any actions the new agent package needs to perform before the tarball upgrade process will be
    considered a success.

    In the current system, when performing a tarball upgrade, the scripts from the old package are used to
    drive the upgrade process.  However, what happens if the new agent package wants to perform some task during
    the upgrade process that wasn't foreseen in the old package?  To solve this problem we have the old scripts
    execute the new script's scalyr-agent-2-config script with a specially formatted commandline to give it the
    change to perform whatever actions it desires.

    Any output emitted while be included stdout, stderr of the original upgrade command.  Additionally, if this
    method returns a non-zero status code, the overall upgrade will fail.

    @param old_install_dir_path: The full path to a directory containing the old agent installation.  Note, this
        may not be in the original directory where it resided, but a temporary directory to which the agent was
        moved during the upgrade.
    @param new_install_dir_path:  The full path to a directory containing the new agent installation.  Note, this
        may not be in the directory where it will finally rest when installed, but a temporary directory in which
        the agent was created during the upgrade.

    @type new_install_dir_path: str
    @type old_install_dir_path: str

    @return: A zero exit status if success, otherwise non-zero.  A non-zero result will cause the overall upgrade to
        fail
    @rtype: int
    """
    return 0


def printable_fields(fields):
    """Return printable fields.

    :param fields list of tuble with (label, vallue)
    """
    for field in fields:
        yield field[0] + '=' + field[1]


def getconfirmation_input(action):
    """
    Method collects user confirmation to proceed with action
    INPUTS: action as str, description of the action
    OUTPUT: Returns boolean, True to proceed, False to not proceed.
    """
    loop = True
    while loop:
        user_input = input(f"Confirm to proceed with '{action}'? [y/N]: ")
        if (user_input == 'Y') | (user_input == 'y'):
            return True
        elif (user_input == '') | (user_input == 'N') | (user_input == 'n'):
            return False
        else:
            print(f"Invalid input '{user_input}' >> Expecting [y/Y/n/N].")


def find_position(string, index, line_offset):
    """Given a string and index, return (line, column)"""
    leading = string[:index].splitlines()
    return len(leading) + line_offset, len(leading[-1]) + 1


def colors_rotate(use_ccw: bool=False):
    """Rotate vertex colors inside faces

    :param use_ccw: Counter Clockwise
    :type use_ccw: bool
    """
    pass


def __FormatLine(filepath, line_index, max_line_number_size, lines,
    highlight=False):
    """ Format a single line."""
    if highlight:
        return '%s:%s: > %s' % (filepath, str(line_index + 1).rjust(
            max_line_number_size), lines[line_index])
    else:
        return '%s:%s:   %s' % (filepath, str(line_index + 1).rjust(
            max_line_number_size), lines[line_index])


def build_sql_file(filename, meta_data_string, select_clause, from_clause,
    variable_declarations=None):
    """Build SQL file string from components and write to `filename`"""
    with open(filename, 'w') as fout:
        print('Writing meta-data to {filename}...'.format(filename=filename))
        fout.write(meta_data_string)
        if variable_declarations:
            print('Writing variable declarations to {filename}...'.format(
                filename=filename))
            fout.write(variable_declarations)
        print('Writing select clause to {filename}...'.format(filename=
            filename))
        fout.write(select_clause)
        print('Writing from clause to {filename}...'.format(filename=filename))
        fout.write(from_clause)


def create_lzop(archive, compression, cmd, verbosity, interactive, filenames):
    """Create a LZOP archive."""
    cmdlist = [cmd]
    if verbosity > 1:
        cmdlist.append('-v')
    cmdlist.extend(['-o', archive, '--'])
    cmdlist.extend(filenames)
    return cmdlist


def fred_apikey_set(apikey, filename=None):
    """Store the Fred Token in $HOME/.updoon_fred

    Parameters:
    -----------
    apikey : str
        The API Key from the Fred Website.
        See https://research.stlouisfed.org/useraccount/apikeys

    filename : str
        Absolute path to the text where the
        Fred API Key is stored (Optional)

    """
    if filename is None:
        import pathlib
        filename = str(pathlib.Path.home()) + '/.updoon_fred'
    fileptr = open(filename, 'w')
    fileptr.write(apikey)
    fileptr.close()
    return None


def IndentationLevel(Line, TabSize=4):
    """
	return the indentation level of specified line.
	"""
    LineX = Line.expandtabs(TabSize)
    if LineX.isspace():
        return 0
    else:
        return int((len(LineX) - len(LineX.lstrip())) / TabSize)


def match_items(lines, content_old):
    """Create items for mangled lines.

    This function tries to match the lines in ``lines`` with the items (source
    file references and line numbers) in ``content_old``. The
    ``mangle_docstrings`` function changes the actual docstrings, but doesn't
    keep track of where each line came from. The manging does many operations
    on the original lines, which are hard to track afterwards.

    Many of the line changes come from deleting or inserting blank lines. This
    function tries to match lines by ignoring blank lines. All other changes
    (such as inserting figures or changes in the references) are completely
    ignored, so the generated line numbers will be off if ``mangle_docstrings``
    does anything non-trivial.

    This is a best-effort function and the real fix would be to make
    ``mangle_docstrings`` actually keep track of the ``items`` together with
    the ``lines``.

    Examples
    --------
    >>> lines = ['', 'A', '', 'B', '   ', '', 'C', 'D']
    >>> lines_old = ['a', '', '', 'b', '', 'c']
    >>> items_old = [('file1.py', 0), ('file1.py', 1), ('file1.py', 2),
    ...              ('file2.py', 0), ('file2.py', 1), ('file2.py', 2)]
    >>> content_old = ViewList(lines_old, items=items_old)
    >>> match_items(lines, content_old) # doctest: +NORMALIZE_WHITESPACE
    [('file1.py', 0), ('file1.py', 0), ('file2.py', 0), ('file2.py', 0),
     ('file2.py', 2), ('file2.py', 2), ('file2.py', 2), ('file2.py', 2)]
    >>> # first 2 ``lines`` are matched to 'a', second 2 to 'b', rest to 'c'
    >>> # actual content is completely ignored.

    Notes
    -----
    The algorithm tries to match any line in ``lines`` with one in
    ``lines_old``.  It skips over all empty lines in ``lines_old`` and assigns
    this line number to all lines in ``lines``, unless a non-empty line is
    found in ``lines`` in which case it goes to the next line in ``lines_old``.

    """
    items_new = []
    lines_old = content_old.data
    items_old = content_old.items
    j = 0
    for i, line in enumerate(lines):
        while j < len(lines_old) - 1 and not lines_old[j].strip():
            j += 1
        items_new.append(items_old[j])
        if line.strip() and j < len(lines_old) - 1:
            j += 1
    assert len(items_new) == len(lines)
    return items_new


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

        :param SharedLinkSettingsRemoveExpirationType val:
        :rtype: EventType
        """
    return cls('shared_link_settings_remove_expiration', val)


def add_feather_vertex(location: float=(0.0, 0.0)):
    """Add vertex to feather

    :param location: Location, Location of vertex in normalized space
    :type location: float
    """
    pass


def rcBase(base):
    """Return the reverse complement of the base."""
    base = base.upper()
    if base == 'A':
        return 'T'
    if base == 'C':
        return 'G'
    if base == 'G':
        return 'C'
    if base == 'T':
        return 'A'
    return 'N'


def remove(id):
    """Remove the object with the given id in the catalog
        """


def delta_percent(decimals=1):
    """A delta formatter to display the delta as a float with a given number of decimals.

    Args:
        decimals: The number of decimals to display.

    Returns:
        A delta formatter function (f(a,b)) returning (b-a)/a displayed as a percentage.

    """
    return lambda a, b: '{:+.{prec}f}%'.format(100.0 * (b - a) / a, prec=
        decimals)


def detector_class_to_mosflm(detector_class):
    """Get the mosflm detector type from the detector class."""
    if 'adsc' in detector_class:
        return 'adsc'
    if 'mar' in detector_class and 'ccd' in detector_class:
        return 'marccd'
    if 'mar' in detector_class:
        return 'mar'
    if 'pilatus' in detector_class:
        return 'pilatus'
    if 'raxis' in detector_class:
        return 'raxis4'
    if 'saturn' in detector_class:
        return 'saturn'
    raise RuntimeError('unknown detector class "%s"' % detector_class)


@classmethod
def gen_filter(cls, cop='=', lop='and', **kwargs):
    """Generate gnocchi filter from kwargs.

        :param cop: Comparison operator.
        :param lop: Logical operator in case of multiple filters.
        """
    q_filter = []
    for kwarg in sorted(kwargs):
        q_filter.append({cop: {kwarg: kwargs[kwarg]}})
    if len(kwargs) > 1:
        return cls.extend_filter(q_filter, lop=lop)
    else:
        return q_filter[0] if len(kwargs) else {}


def confine(x, low, high):
    """Confine x to [low,high]. Values outside are set to low/high.
See also restrict."""
    y = x.copy()
    y[y < low] = low
    y[y > high] = high
    return y


def join(datamanager):
    """Add a data manager to the transaction.

        *datamanager* must provide the `IDataManager`
        interface.
        """


def _generate_func_api():
    """Auto detect all available interfaces and generate a function-based
       API from them
    """
    from importlib import import_module
    from .interface.base import update_docstring_with_parameters
    from .interface.base import get_interface_groups
    from .interface.base import get_api_name
    from .interface.base import alter_interface_docs_for_api
    for grp_name, grp_descr, interfaces in get_interface_groups():
        for intfspec in interfaces:
            mod = import_module(intfspec[0], package='reproman')
            intf = getattr(mod, intfspec[1])
            spec = getattr(intf, '_params_', dict())
            update_docstring_with_parameters(intf.__call__, spec, prefix=
                alter_interface_docs_for_api(intf.__doc__), suffix=
                alter_interface_docs_for_api(intf.__call__.__doc__))
            globals()[get_api_name(intfspec)] = intf.__call__


def _is_contiguous(positions):
    """Given a non-empty list, does it consist of contiguous integers?"""
    previous = positions[0]
    for current in positions[1:]:
        if current != previous + 1:
            return False
        previous = current
    return True


def make_unpack_map(node):
    """ Make a mapping of unpack values for a template instance.

    Parameters
    ----------
    node : TemplateInstanceNode
        The compiler node for the template instantiation.

    Returns
    -------
    result : dict
        A dict mapping unpack name to compiler node for the template
        instantiation.

    """
    return dict(zip(node.names, node.iternodes()))


def dot_product(v1, v2):
    """Returns the dot product of two vectors that are modeled as dicts"""
    return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]


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

        :param TeamMergeRequestExpiredDetails val:
        :rtype: EventDetails
        """
    return cls('team_merge_request_expired_details', val)


def gesture(snap: bool=False):
    """Start to draw a gesture stroke

    :param snap: Snap
    :type snap: bool
    """
    pass


def traverse_using(iterator, obj, visitors):
    """visit the given expression structure using the given iterator of
    objects.

    """
    for target in iterator:
        meth = visitors.get(target.__visit_name__, None)
        if meth:
            meth(target)
    return obj


@staticmethod
def exitCodeMap():
    """
        HTCondor mapping from the numerical value to its english meaning.
        https://htcondor-wiki.cs.wisc.edu/index.cgi/wiki?p=MagicNumbers
        """
    exitCodeMap = {(0): 'Unknown', (1): 'Idle', (2): 'Running', (3):
        'Removed', (4): 'Completed', (5): 'Held', (6): 'TransferOutput', (7
        ): 'Suspended'}
    return exitCodeMap


def values():
    """Return sequence of value elements."""


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

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

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


def _run_wsgi_app(*args):
    """This function replaces itself to ensure that the test module is not
    imported unless required.  DO NOT USE!
    """
    global _run_wsgi_app
    from ..test import run_wsgi_app as _run_wsgi_app
    return _run_wsgi_app(*args)


@staticmethod
def plot_line(x0, y0, x1, y1):
    """Zingl-Bresenham line draw algorithm"""
    x0 = int(x0)
    y0 = int(y0)
    x1 = int(x1)
    y1 = int(y1)
    dx = abs(x1 - x0)
    dy = -abs(y1 - y0)
    if x0 < x1:
        sx = 1
    else:
        sx = -1
    if y0 < y1:
        sy = 1
    else:
        sy = -1
    err = dx + dy
    while True:
        yield x0, y0
        if x0 == x1 and y0 == y1:
            break
        e2 = 2 * err
        if e2 >= dy:
            err += dy
            x0 += sx
        if e2 <= dx:
            err += dx
            y0 += sy


@staticmethod
def _validate_rpc_completion_callback(callback):
    """Verify callback is callable if not None

        :returns: boolean indicating nowait
        :raises: TypeError

        """
    if callback is None:
        return True
    if callable(callback):
        return False
    else:
        raise TypeError('Completion callback must be callable if not None')


@staticmethod
def assert_response_status_code(response, status_code):
    """Assert the response status code.

        Parameters:
        response : value
        status_code : value
        """
    if isinstance(status_code, str):
        if status_code.isdigit():
            status_code = int(status_code)
    msg = 'expected response status code to be {} but was {}'.format(
        status_code, response.status_code)
    assert response.status_code == status_code, msg


def generate_bio_assembly(data_api, struct_inflator):
    """Generate the bioassembly data.
    :param data_api the interface to the decoded data
    :param struct_inflator the interface to put the data into the client object"""
    bioassembly_count = 0
    for bioassembly in data_api.bio_assembly:
        bioassembly_count += 1
        for transform in bioassembly['transformList']:
            struct_inflator.set_bio_assembly_trans(bioassembly_count,
                transform['chainIndexList'], transform['matrix'])


def __setitem__(k, value):
    """ Set a key/value pair into the dictionary"""


def assert_dicts_not_equal(dict1, dict2):
    """tests two dicts are not equal"""
    k1, k2 = list(dict1.keys()), list(dict2.keys())
    k1.sort()
    k2.sort()
    if k1 == k2:
        for key in k1:
            if (dict1[key], key) != (dict2[key], key):
                return
        assert False, (k1, k2)


@classmethod
def _summarize_text(cls, text, max_len=24):
    """Avoid spamming logs by truncating text."""
    if len(text) > max_len:
        return '{!r} + {} chars'.format(text[:max_len], len(text) - max_len)
    return repr(text)


@staticmethod
def first_order_score(y, mean, scale, shape, skewness):
    """ GAS Poisson Update term using gradient only - native Python function

        Parameters
        ----------
        y : float
            datapoint for the time series

        mean : float
            location parameter for the Poisson distribution

        scale : float
            scale parameter for the Poisson distribution

        shape : float
            tail thickness parameter for the Poisson distribution

        skewness : float
            skewness parameter for the Poisson distribution

        Returns
        ----------
        - Score of the Poisson family
        """
    return y - mean


def confound_restricted_permutations(target, confounds):
    """
    Variant of permutation testing to restrict relabelling of the target within
    certain values/ranges of the confounds, to preserve feature-to-confound
    relationships, but break the feature-to-target relationships. Such
    permutations would help us test whether models are learning the
    confound-related or target-related info i.e. if the prediction performance is
    high even when target is permuted, we can infer model is learning the
    confound-related info.

    Parameters
    ----------
    target
    confounds

    Returns
    -------

    """
    raise NotImplementedError()


def sql_in(query=None, values_list=None):
    """
    Transform the list in values_list to be used inside a IN statement of the SQL.
    Example:
        values_list = [1,2,3,4,5]
        query = 'select * from database where' + sql_in(" col in", values_list)

        "select * from database where col in (1, 2, 3, 4, 5)"

    :param query: Query header with the first part of the query
    :param values_list: list to be transformed as a IN format
    :return: query concatenated with values_list as a IN format
    """
    if values_list is None:
        return ''
    if not isinstance(values_list, list):
        values_list = [values_list]
    separated_list = str(values_list).replace('[', '(').replace(']', ')')
    if query is None:
        return separated_list
    else:
        return query + ' ' + separated_list


def uint2int32(value):
    """
    Convert an unsigned 32 bits integer into a signed 32 bits integer.

    >>> print(uint2int32(1))
    1
    >>> print(uint2int32(2**32 + 1))  # ignore bits larger than 32 bits
    1
    >>> print(uint2int32(4294967295))
    -1
    >>> print(uint2int32(4294967294))
    -2
    >>> print(uint2int32(18446744073709551615))
    -1
    """
    value = value & 4294967295
    if value & 2147483648:
        v = value - 4294967296
    else:
        v = value
    return v


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

        :param SharedFolderMetadata val:
        :rtype: SharePathError
        """
    return cls('already_shared', val)


def new():
    """Add a new material

    """
    pass


def get_folder_id(path, c):
    """Query the folder id of the directory."""
    sql = """
        SELECT folder_id
        FROM folders
        WHERE path = ?
        """
    c.execute(sql, (path,))
    return c.fetchone()[0]


@classmethod
def get_by_hostname(cls, context, hostname, online=True):
    """Get a Conductor record by its hostname.

        :param cls: the :class:`Conductor`
        :param context: Security context
        :param hostname: the hostname on which a Conductor is running
        :param online: Specify the expected ``online`` field value for the
                       conductor to be retrieved. The ``online`` field is
                       ignored if this value is set to None.
        :returns: a :class:`Conductor` object.
        """
    db_obj = cls.dbapi.get_conductor(hostname, online=online)
    conductor = cls._from_db_object(context, cls(), db_obj)
    return conductor


def repos(ln, old_pos, new_pos):
    """
        Return a new list in which each item contains the index of the item
        in the old order.
        Uses the ranges approach (best for large arrays).
    """
    lb = min(new_pos, old_pos)
    ub = max(new_pos, old_pos)
    adj_range = []
    if new_pos < old_pos:
        adj_range.append(old_pos)
        adj_range += list(range(lb, ub))
    else:
        adj_range += list(range(lb + 1, ub + 1))
        adj_range.append(old_pos)
    return list(range(0, lb)) + adj_range + list(range(ub, ln - 1))


def find_elements(strategy, locator, root=None):
    """Finds elements on the page.

        :param strategy: Location strategy to use (type depends on the driver implementation)
        :param locator: Location of target elements.
        :param root: (optional) root node.
        :type strategy: str
        :type locator: str
        :type root: web element object or None.
        :return: iterable of web element objects
        :rtype: iterable (if depends on the driver implementation)
        """


def enable_proxies(proxy_25: bool=False, proxy_50: bool=False, proxy_75:
    bool=False, proxy_100: bool=False, overwrite: bool=False):
    """Enable selected proxies on all selected Movie strips

    :param proxy_25: 25%
    :type proxy_25: bool
    :param proxy_50: 50%
    :type proxy_50: bool
    :param proxy_75: 75%
    :type proxy_75: bool
    :param proxy_100: 100%
    :type proxy_100: bool
    :param overwrite: Overwrite
    :type overwrite: bool
    """
    pass


def tabcategorial(data, variable, hue):
    """return a pandas dataframe containing data from the category by class (useful for binary classification)"""
    pass


@classmethod
def from_sphere(cls, sphere):
    """Creates a ``BoundingVolume`` from a :class:`compas.geometry.Sphere`.

        Parameters
        ----------
        sphere: `compas.geometry.Sphere`

        Examples
        --------
        >>> from compas.geometry import Sphere
        >>> from compas_fab.robots import BoundingVolume
        >>> sphere = Sphere((1., 1., 1.), 5.)
        >>> bv = BoundingVolume.from_sphere(sphere)
        >>> bv.type
        2
        """
    return cls(cls.SPHERE, sphere)


def view_all():
    """Reset viewable area to show full strips range

    """
    pass


def gmsh_code(path_or_code):
    """Generate mesh with gmsh."""
    try:
        from pygmsh import Geometry
    except ImportError:
        from pygmsh.built_in import Geometry
    geo = Geometry()
    if isinstance(path_or_code, list):
        code = map(str, path_or_code)
    else:
        try:
            with open(path_or_code, 'r') as gmsh_f:
                code = gmsh_f.readlines()
        except (OSError, IOError):
            print('gmsh_code: could not read file...')
            return geo
    geo.add_raw_code(code)
    return geo


def get_component_registry(context=None):
    """Get the nearest site manager in the given context.

        If `context` is `None`, return the global site manager.

        If the `context` is not `None`, it is expected that an adapter
        from the `context` to `IComponentLookup` can be found. If no
        adapter is found, a `ComponentLookupError` is raised.

        """


def series_frequency(series, value, percent=True):
    """
    Calculates the frequency of a value in a list.
    :param pd.Series series: the pandas.Series.
    :param value: the value to calculate the frequency
    :return: The frequency of a value in a list
    """
    number_of_value = series.values.tolist().count(value)
    frequency_ = number_of_value / len(series)
    if percent:
        frequency_ *= 100
    return frequency_


def dict_to_pandas_data_frame(data, main_key_name=None, order=None, inverse
    =False):
    """
    Convert a dictionary to pandas.DataFrame

    Parameters
    ----------
    data : dict
        dictionary of handling
    main_key_name : str, optional
        if the json or dict does not have the main key as a single `{main_element : dict}` present, it needs to be specified
    order : dict, list, optional
        list with the column names in order or dict with specified key positions
    inverse : bool, optional
        if columns and rows shall be switched

    Returns
    -------
    pandas.DataFrame
        DataFrame representing the dictionary

    """
    if not isinstance(data, dict):
        raise TypeError
    if main_key_name and not isinstance(main_key_name, str):
        raise TypeError
    if not isinstance(inverse, bool):
        raise TypeError
    from ._helper import _create_sorted_list_from_order, _cast_main_key_name
    from pandas import DataFrame
    if not main_key_name:
        data, main_key_name = _cast_main_key_name(data)
    if not inverse:
        data_frame = DataFrame.from_dict(data, orient='index')
    else:
        data_frame = DataFrame.from_dict(data)
    data_frame.index.name = main_key_name
    if order:
        data_frame[main_key_name] = data_frame.index
        order = _create_sorted_list_from_order(order)
        data_frame = data_frame[order]
        data_frame.set_index(order[0], inplace=True)
    return data_frame


def format_from_filename(filename, format=None):
    """Detects format based on filename."""
    if format:
        return format
    else:
        return filename[filename.rfind('.') + 1:]


def oct2dec(x):
    """
    Convert octal string to decimal number.
    For instance: '11' -> 9
    """
    return int(x, 8)


def get_depression():
    """
    Source: http://icd10cmcode.com/what-is-the-icd-10-for-depression.php
    :return:
    """
    depression_codes = ['F0390', 'F341', 'F4321', 'F0631', 'F0632F251']
    for i in range(10):
        depression_codes.append('F32' + str(i))
    for i in range(10):
        depression_codes.append('F33' + str(i))
    return depression_codes


def _check_range(val_range, min_val=None, max_val=None):
    """
    Check whether the range is a valid range.

    Args
        val_range: A pair of lower and upper bound.
        min_val: Minimal value for the lower bound.
        max_val: Maximal value for the upper bound.
    """
    if val_range[0] > val_range[1]:
        raise ValueError('interval lower bound > upper bound')
    if min_val is not None and val_range[0] < min_val:
        raise ValueError('invalid interval lower bound')
    if max_val is not None and val_range[1] > max_val:
        raise ValueError('invalid interval upper bound')


def remove_edge_attrs(graph, s, t, attrs):
    """Remove attrs of an edge specified by attrs.

    Parameters
    ----------
    graph : regraph.Graph
    s : hashable, source node id.
    t : hashable, target node id.
    attrs : dict
        Dictionary with attributes to remove.

    Raises
    ------
    GraphError
        If an edge between `s` and `t` does not exist.
    """
    graph.remove_edge_attrs(s, t, attrs)


def split_key_value(item):
    """Split KEY=VALUE specifier or raise an ValueError exception.

    :param item: input KEY=VALUE string option.
    :type item: str

    :raises ValueError: if cannot split

    :return: pair of split key and value
    :rtype: str, str
    """
    try:
        key, value = item.split('=', 1)
    except ValueError:
        raise ValueError('Missing KEY=VALUE pair in option "{}"'.format(item))
    return key, value


def create_result(*args):
    """Called by normalise with (*vals, meta, original_val, dividers)"""
    raise NotImplementedError()


@staticmethod
def p_compu_method_optional_list_optional(p):
    """compu_method_optional_list_optional : empty
                                               | compu_method_optional_list"""
    p[0] = tuple() if p[1] is None else p[1]


@classmethod
def target_types(cls):
    """Returns a list of target type names (e.g.: `scala_library`) this rewriter operates on."""
    raise NotImplementedError()


def getTOFalpha(ins, dsp):
    """get TOF peak profile alpha

    :param dict ins: instrument parameters with at least 'alpha'
      as values only
    :param float dsp: d-spacing of peak

    :returns: flaot getTOFalpha: peak alpha

    """
    return ins['alpha'] / dsp


def log2(data=None, out=None, name=None, **kwargs):
    """Returns element-wise Base-2 logarithmic value of the input.

    ``2**log2(x) = x``

    The storage type of ``log2`` output is always dense

    Defined in src/operator/tensor/elemwise_unary_op_logexp.cc:L105

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

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

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


def bytes_to_human_readable_repr(b: bytes) ->str:
    "Converts bytes into some human-readable representation. Unprintable\n    bytes such as the nul byte are escaped. For example:\n\n        >>> b = bytes([102, 111, 111, 10, 0])\n        >>> s = bytes_to_human_readable_repr(b)\n        >>> print(s)\n        foo\n\x00\n        >>> print(repr(s))\n        'foo\\n\\x00'\n    "
    return repr(b)[2:-1]


def get_html_subsection(name):
    """
    Return a subsection as HTML, with the given name

    :param name: subsection name
    :type name: str
    :rtype: str
    """
    return '<h2>{}</h2>'.format(name)


def printUsage():
    """
    Print program usage information.
    :return:
    """
    print('USAGE:')
    print('python   wordsearch.py   <word-list-file>   <cols>   <rows>')


def get_account_summary():
    """
    Retrieves information about IAM entity usage and IAM quotas in the AWS account.
    For information about limitations on IAM entities, see Limitations on IAM Entities in the IAM User Guide .
    See also: AWS API Documentation

    Examples
    The following command returns information about the IAM entity quotas and usage in the current AWS account.
    Expected Output:

    :example: response = client.get_account_summary()

    :rtype: dict
    :return: {
        'SummaryMap': {
            'string': 123
        }
    }

    """
    pass


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

        :param FileTransfersTransferDeleteType val:
        :rtype: EventType
        """
    return cls('file_transfers_transfer_delete', val)


def group_remove():
    """Remove the active bone group

    """
    pass


def next():
    """Return the next replica to try.

        Return None if there are no more replicas defined.
        """


def words(byte_stream):
    """A generator that delivers a stream of 16 bit numbers, given a stream of bytes"""
    low = None
    for b in byte_stream:
        if low is not None:
            yield low + (b << 8)
            low = None
        else:
            low = b
    if low is not None:
        yield low


@classmethod
def apply(cls, x, palette, na_value=None):
    """
        Scale data discretely

        Parameters
        ----------
        x : array_like
            Discrete values to scale
        palette : callable ``f(x)``
            Palette to use
        na_value : object
            Value to use for missing values.

        Returns
        -------
        out : array_like
            Scaled values
        """
    limits = cls.train(x)
    return cls.map(x, palette, limits, na_value)


def p_op_key(p):
    """ op_key : BROADCAST_ADDR
               | ROUTERS
               | DOMAIN_NAME_SERVERS
               | DOMAIN_NAME
               | HOST_NAME
    """
    p[0] = p[1]


def truncate_to_max(errors, max_errors):
    """If max_errors was specified, truncate the list of errors.

    Give the total number of times that the error was found elsewhere.
    """
    if len(errors) > max_errors:
        start1, end1, err1, msg1, replacements = errors[0]
        if len(errors) == max_errors + 1:
            msg1 += ' Found once elsewhere.'
        else:
            msg1 += ' Found {} times elsewhere.'.format(len(errors))
        errors = errors[1:max_errors]
        errors = [(start1, end1, err1, msg1, replacements)] + errors
    return errors


def format_file_contents(contents: str, filename: str) ->str:
    """Add markdown code block around file contents with extension for code highlighting.

    If a file is empty or contains only whitespace, note this in the log.
    """
    if not contents.rstrip():
        return '*File empty*'
    return '```{}\n'.format(filename.split('.')[-1]) + contents + '\n```\n'


@staticmethod
def _load_file(path):
    """ Returns the contents of a file.

        :param path: the path of the file to load
        :type path: str
        :returns: the content of the file
        :rtype: str

        """
    with open(path, 'r') as file_to_read:
        return file_to_read.read()


def type_object_attrgetter(obj, attr, *defargs):
    """
    This implements an improved attrgetter for type objects (i.e. classes)
    that can handle class attributes that are implemented as properties on
    a metaclass.

    Normally `getattr` on a class with a `property` (say, "foo"), would return
    the `property` object itself.  However, if the class has a metaclass which
    *also* defines a `property` named "foo", ``getattr(cls, 'foo')`` will find
    the "foo" property on the metaclass and resolve it.  For the purposes of
    autodoc we just want to document the "foo" property defined on the class,
    not on the metaclass.

    For example::

        >>> class Meta(type):
        ...     @property
        ...     def foo(cls):
        ...         return 'foo'
        ...
        >>> class MyClass(metaclass=Meta):
        ...     @property
        ...     def foo(self):
        ...         ""\"Docstring for MyClass.foo property.""\"
        ...         return 'myfoo'
        ...
        >>> getattr(MyClass, 'foo')
        'foo'
        >>> type_object_attrgetter(MyClass, 'foo')
        <property at 0x...>
        >>> type_object_attrgetter(MyClass, 'foo').__doc__
        'Docstring for MyClass.foo property.'

    The last line of the example shows the desired behavior for the purposes
    of autodoc.
    """
    for base in obj.__mro__:
        if attr in base.__dict__:
            if isinstance(base.__dict__[attr], property):
                return base.__dict__[attr]
            break
    return getattr(obj, attr, *defargs)


def align_options(options):
    """
    Indents flags and aligns help texts.
    """
    l = 0
    for opt in options:
        if len(opt[0]) > l:
            l = len(opt[0])
    s = []
    for opt in options:
        s.append('  {0}{1}  {2}'.format(opt[0], ' ' * (l - len(opt[0])),
            opt[1]))
    return '\n'.join(s)


def group(iterable, count):
    """returns elements from the iterable grouped by count
    The last set, possibly incomplete, is also returned"""
    itr = iter(iterable)
    while True:
        chunk = []
        for _i in range(count):
            try:
                chunk.append(next(itr))
            except StopIteration:
                if chunk:
                    yield chunk
                return
        yield chunk


def format_field(results, field_name):
    """
    Helper function for output formatting.
    """
    value = results[field_name]
    if field_name == 'value':
        if results['operation'] == 'normal':
            return str(value)
        else:
            return ''
    if value == None:
        return ''
    elif value == True:
        return '1'
    elif value == False:
        return '0'
    else:
        return str(value)


@classmethod
def get_opened_cache(cls, unique_id):
    """Return a currently-opened cache by its unique identifier.

        This method allows entries stored in the database to reference
        living `Cache` objects by their persistent identifier, which
        is useful for running additional queries on the database or
        retrieving opened file objects.

        """
    return cls.opened_caches_[unique_id]


def GM(L_850, L_1660):
    """
        Goddijn-Murphy Index ====================================================
            From: "Proof of concept for a model of light reflectance of plastics
            floating on natural waters" by Lonneke Goddijn-Murphy and Juvenal
            Dufaur. - See Table 5

            Convert numpy arrays of radiance data to a Goddijn-Murphy map

        Inputs =================================================================
            L_850 : At-sensor radiance at 850 nm wavelength (numpy array)
            L_1660 : At-sensor radiance at 1660 nm wavelength (numpy array)

        Returns ================================================================
            Goddijn-Murphy Map
    """
    return L_850 - L_1660


def hagenbach_bischoff(votes, seats):
    """Calculate the Hagenbach-Bischoff quota.

    :math:`\\frac{votes}{seats + 1}`

    :param int votes: the number of votes
    :param int seats: the number of seats
    """
    return 1.0 * votes / (seats + 1)


def vector_to_diagonal(v):
    """Converts a vector to a diagonal matrix with vector elements
    as the diagonal elements of the matrix"""
    diag_matrix = [[(0) for i in range(len(v))] for j in range(len(v))]
    for i in range(len(v)):
        diag_matrix[i][i] = v[i]
    return diag_matrix


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

        :param PaperDocChangeSubscriptionDetails val:
        :rtype: EventDetails
        """
    return cls('paper_doc_change_subscription_details', val)


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


def count(text):
    """
  Count net number of braces in text (add 1 for each opening brace,
  subtract one for each closing brace).

  Parameters
  ----------
  text: String
     A string.

  Returns
  -------
  counts: Integer
     Net number of braces.

  Examples
  --------
  >>> from bibmanager.utils import count
  >>> count('{Hello} world')
  0
  """
    return text.count('{') - text.count('}')


def dequantize(df, method='linear'):
    """
    Tries to undo results of a non-constant sampling rate (ie due to indeterministic buffering).

    :param str method: see :method:`pd.DataFrame.interpolate()` that is used to fill-in column-values that are held constant

    .. Note::
        The results wil never have a flat section, so checking for some value (ie 0)
        must always apply for some margin (ie (-e-4, e-4).
    """
    df1 = df.where(df.diff() != 0)
    df1.iloc[[0, -1]] = df.iloc[[0, -1]]
    df1.interpolate(method=method, inplace=True)
    return df1


def _unpack_obs(id, payoff, **_):
    """Unpack an observation"""
    return id, payoff


def finalize_wrapper(finalizable):
    """
    Wrapper around the finalize method for the object
    :param finalizable: an object with the finalize method
    :return:
    """
    finalizable.finalize()
    return finalizable


def check_url(name):
    """Returns true if the name looks like a URL"""
    if ':' not in name:
        return False
    scheme = name.split(':', 1)[0].lower()
    return scheme in ['http', 'https', 'file', 'ftp']


def get_extraction_region(hdu, segment, mode='spectrum'):
    """Get y_start,y_end for given extraction

    """
    if mode == 'spectrum':
        height = hdu[1].header['SP_HGT_%s' % segment]
        location = hdu[1].header['SP_LOC_%s' % segment]
    elif mode == 'background1':
        height = hdu[1].header['B_HGT1_%s' % segment]
        location = hdu[1].header['B_BKG1_%s' % segment]
    elif mode == 'background2':
        height = hdu[1].header['B_HGT2_%s' % segment]
        location = hdu[1].header['B_BKG2_%s' % segment]
    y_start = location - height // 2
    y_end = location + height // 2
    return y_start, y_end


def find_sync_package(pkgname, syncdbs):
    """Finds a package name of the form 'repo/pkgname' or 'pkgname' in a list of DBs"""
    if '/' in pkgname:
        repo, pkgname = pkgname.split('/', 1)
        db = syncdbs.get(repo)
        if db is None:
            return False, "repository '%s' does not exist" % repo
        pkg = db.get_pkg(pkgname)
        if pkg is None:
            return False, "package '%s' was not found in repository '%s'" % (
                pkgname, repo)
        return True, pkg
    else:
        for db in syncdbs.values():
            pkg = db.get_pkg(pkgname)
            if pkg is not None:
                return True, pkg
        return False, "package '%s' was not found" % pkgname


@classmethod
def get_all(cls, user=None):
    """
        Get all location (by owner)
        """
    locations = cls.objects
    user = None
    if user:
        locations = locations.filter(owner=user)
    return locations.order_by('label')


def identity(x):
    """The identity function."""
    return x


def _xhj_gc_commands_to_rmfiles(hsize, files):
    """Return the history files to remove to get under the command limit."""
    rmfiles = []
    n = 0
    ncmds = 0
    for ts, fcmds, f in files[::-1]:
        if fcmds == 0:
            rmfiles.append((ts, fcmds, f))
        if ncmds + fcmds > hsize:
            break
        ncmds += fcmds
        n += 1
    rmfiles += files[:-n]
    return rmfiles


def de_select_first():
    """(De)select first of visible part of each NURBS

    """
    pass


def _add_source(source, code, path, lineno=1):
    """
    Add a file to the list of source code chunks, tagged with path and line.
    """
    path = path.replace('\\', '/')
    source.append('#line %d "%s"' % (lineno, path))
    source.append(code)


def refine_positions(npa, atol=1e-05):
    """
    给定一个精度，让靠近1的元素变成零。则使得坐标在0～1之间可以直接比较。
    """
    flatten_npa = npa.flatten()
    for i, val in enumerate(flatten_npa):
        if val < atol or val > 1 - atol:
            flatten_npa[i] = 0
        else:
            flatten_npa[i] = val
    return flatten_npa.reshape(npa.shape)


def id_delete():
    """Delete the ID under cursor

    """
    pass


def strip_quotes(s: str):
    """
    Remove quotes from a string.
    """
    if not s:
        return ''
    return s.strip().replace('"', '').replace("'", '')


def unlock(library, session):
    """Relinquishes a lock for the specified resource.

    Corresponds to viUnlock function of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    return library.viUnlock(session)


def get_bb(figure, axis, component, transform=None):
    """
	Get the bounding box of the given component.

	:param figure: The figure that the component occupies.
				   This is used to get the figure renderer.
	:type figure: :class:`matplotlib.figure.Figure`
	:param axis: The axis (or subplot) where the component is plotted.
	:type axis: :class:`matplotlib.axis.Axis`
	:param component: The component whose bounding box will be fetched.
	:type component: object
	:param transform: The bounding box transformation.
					  If `None` is given, the data transformation is used.
	:type transform: None or :class:`matplotlib.transforms.TransformNode`

	:return: The bounding box of the text object.
	:rtype: :class:`matplotlib.transforms.Bbox`
	"""
    transform = axis.transData if transform is None else transform
    renderer = figure.canvas.get_renderer()
    bb = component.get_window_extent(renderer).inverse_transformed(transform)
    return bb


def _is_json_mime(mime):
    """Is a key a JSON mime-type that should be left alone?"""
    return mime == 'application/json' or mime.startswith('application/'
        ) and mime.endswith('+json')


def handle_spaces(text):
    """Chained whitespaces are removed and replaced by a single space.
    Exception when between two containers separated by whitespaces: there is no space.
    Eg. '..._<html>_<head>_...' => '..._<html><head>_...' """
    ret_splitted = text.split(' ')
    ret = list()
    for i in range(len(ret_splitted)):
        e = ret_splitted[i]
        if len(e) > 0:
            if e[0] == '<' and e[-1] == '>' and '<' not in e[1:]:
                if len(ret) > 0:
                    last = ret[-1]
                    ret.pop(-1)
                    ret.append(''.join([last, e]))
                else:
                    ret.append(e)
            else:
                ret.append(e)
    return ' '.join(ret)


def mode_assignment(arg):
    """
    Translates arg to enforce proper assignment
    """
    arg = arg.upper()
    stream_args = 'STREAM', 'CONSOLE', 'STDOUT'
    try:
        if arg in stream_args:
            return 'STREAM'
        else:
            return arg
    except Exception:
        return None


def is_valid_boolstr(val):
    """Check if the provided string is a valid bool string or not."""
    boolstrs = 'true', 'false', 'yes', 'no', 'y', 'n', '1', '0'
    return str(val).lower() in boolstrs


def certificate_reference_format(value):
    """Space-separated certificate thumbprints."""
    cert = {'thumbprint': value, 'thumbprint_algorithm': 'sha1'}
    return cert


def setthis(this, key, value):
    """Set attribute `key` on `this` to value and return `this`."""
    try:
        this.__dict__[key] = value
    except TypeError:
        setattr(this, key, value)
        return this
    else:
        return this


def ft_short(data, i, cols, rel=0, p=2, *args, **kwargs):
    """Generates a context feature based on the length of the value the
    `form` column. Positive if value is shorted than the provided threshold.

    :param data: data
    :type: np.recarray
    :param i: focus position
    :type i: int
    :param cols: column map
    :type cols: dict
    :param rel: relative position of context features
    :type rel: int
    :param p: threshold
    :type p: int
    :return: feature
    :rtype: str
    """
    shrt = None
    if 0 <= i + rel < len(data):
        shrt = len(data[i + rel][cols['form']]) < p
    return 'short[%s]=%s' % (str(rel), shrt)


def list_rpm(archive, compression, cmd, verbosity, interactive):
    """List a RPM archive."""
    cmdlist = [cmd, '-q', '-l']
    if verbosity > 1:
        cmdlist.append('-v')
    cmdlist.extend(['-p', '--', archive])
    return cmdlist


def grup(txtval):
    """Trasforms a string to uppercase special for Greek comparison

    :param txtval:
    :return:
    """
    ar1 = 'ΆΈΉΐΊΌΰΎΏ'
    ar2 = 'ΑΕΗΪΙΟΫΥΩ'
    ftxt = list(str(txtval).upper())
    for i, letter in enumerate(ftxt):
        if letter in ar1:
            ftxt[i] = ar2[ar1.index(letter)]
    return ''.join(ftxt)


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

        :param ShowcaseDeleteCommentDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_delete_comment_details', val)


def KK_RC20(w, Rs, R_values, t_values):
    """
    Kramers-Kronig Function: -RC-

    Kristian B. Knudsen (kknu@berkeley.edu / kristianbknudsen@gmail.com)
    """
    return Rs + R_values[0] / (1 + w * 1.0j * t_values[0]) + R_values[1] / (
        1 + w * 1.0j * t_values[1]) + R_values[2] / (1 + w * 1.0j * t_values[2]
        ) + R_values[3] / (1 + w * 1.0j * t_values[3]) + R_values[4] / (1 +
        w * 1.0j * t_values[4]) + R_values[5] / (1 + w * 1.0j * t_values[5]
        ) + R_values[6] / (1 + w * 1.0j * t_values[6]) + R_values[7] / (1 +
        w * 1.0j * t_values[7]) + R_values[8] / (1 + w * 1.0j * t_values[8]
        ) + R_values[9] / (1 + w * 1.0j * t_values[9]) + R_values[10] / (1 +
        w * 1.0j * t_values[10]) + R_values[11] / (1 + w * 1.0j * t_values[11]
        ) + R_values[12] / (1 + w * 1.0j * t_values[12]) + R_values[13] / (
        1 + w * 1.0j * t_values[13]) + R_values[14] / (1 + w * 1.0j *
        t_values[14]) + R_values[15] / (1 + w * 1.0j * t_values[15]
        ) + R_values[16] / (1 + w * 1.0j * t_values[16]) + R_values[17] / (
        1 + w * 1.0j * t_values[17]) + R_values[18] / (1 + w * 1.0j *
        t_values[18]) + R_values[19] / (1 + w * 1.0j * t_values[19])


@staticmethod
def val2bool(val):
    """
            Converts standard input to boolean values

            True:  'on',  '1', 1, True
            False: 'off', '0', 0, False
            """
    if isinstance(val, str):
        val = val.lower()
        if val == 'on' or val == '1':
            return True
        elif val == 'off' or val == '0':
            return False
        else:
            raise ValueError('Invalid input')
    return bool(val)


def offline_str(status):
    """Convert the offline node status from a boolean to a string."""
    if status:
        return 'Offline'
    return 'Online'


def _format__arrayline(_arrayline, operator):
    """Formats a single line of an array"""
    formatted = getattr(_arrayline, operator)().split(')')[0].split('(')[-1]
    return formatted


def get_largest_item_size(iterable):
    """
        Given a iterable, get the size/length of its largest key value.
    """
    largest_key = 0
    for key in iterable:
        if len(key) > largest_key:
            largest_key = len(key)
    return largest_key


def discard_ows(input_string: str) ->str:
    """Remove leading space from input_string."""
    return input_string.lstrip(' ')


@classmethod
def register_count_log2(cls, parameters_byte):
    """
        Extracts the log2(register_count) from the parameters byte of a serialized ``HLLType.FULL`` HLL.

        :param byte parameters_byte: the parameters byte of the serialized HLL
        :returns: log2(registerCount) of the serialized HLL
        :rtype: int
        """
    return parameters_byte & cls.LOG2_REGISTER_COUNT_MASK


def setGS(gs):
    """Set fixation bias, if `gs` is given."""
    if gs > 0:
        selgamma = ['global shape2;\n', 'category rateCatSel =(' + str(gs) +
            """, EQUAL, MEAN, GammaDist(_x_,shape2,shape2), CGammaDist(_x_,shape2,shape2),0,1e25);
"""
            ]
    else:
        selgamma = ['rateCatSel := 1.0;\n']
    return selgamma


def set_threads(thread_count, tiles=2):
    """ Set to None to disable parallel processing """
    global _thread_count, _tiles
    if thread_count == 1:
        thread_count = None
    _thread_count = thread_count
    _tiles = tiles


def write_list(path_out, image_list):
    """Hepler function to write image list into the file.
    The format is as below,
    integer_image_index 	 float_label_index 	 path_to_image
    Note that the blank between number and tab is only used for readability.
    Parameters
    ----------
    path_out: string
    image_list: list
    """
    with open(path_out, 'w') as fout:
        for i, item in enumerate(image_list):
            line = '%d\t' % item[0]
            for j in item[2:]:
                line += '%f\t' % j
            line += '%s\n' % item[1]
            fout.write(line)


@classmethod
def size(cls, pid):
    """Return the number of connections in the pool

        :param str pid: The pool id
        :rtype int

        """
    with cls._lock:
        cls._ensure_pool_exists(pid)
        return len(cls._pools[pid])


def is_published():
    """Return true if this object is visible to the public.
        """


@classmethod
def from_rgb(cls, r, g, b):
    """Constructs a :class:`Colour` from an RGB tuple."""
    return cls((r << 16) + (g << 8) + b)


def remove_isolated_nodes(net):
    """
    Removes nodes with no edges from network.

    It modifies the provided graph inplace.

    Parameters
    ----------
    net : nx.DiGraph

    """
    to_remove = set()
    for i in net.nodes:
        if len(list(net.predecessors(i))) == 0 and len(list(net.successors(i))
            ) == 0:
            to_remove.add(i)
    net.remove_nodes_from(to_remove)


def can_paginate(operation_name=None):
    """
    Check if an operation can be paginated.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    """
    pass


def get_canon_name(file: str, allow_no_source: bool=False) ->str:
    """ Gets the canonical path of a game file taken from an extracted graphic pack """
    name = str(file).replace('\\', '/').replace('.s', '.').replace('Content',
        'content').replace('Aoc', 'aoc')
    if 'aoc/' in name:
        return name.replace('aoc/content', 'aoc').replace('aoc', 'Aoc')
    elif 'content/' in name and '/aoc' not in name:
        return name.replace('content/', '')
    elif allow_no_source:
        return name


def put_data(f, data):
    """
    Put data to a Sparky file object.

    This function does not untile data. This should be done before calling
    this function

    """
    f.write(data.astype('>f4').tostring())
    return


def create_or_update_file(file_path: str, file_content: str='',
    file_content_encoding: str='utf-8') ->None:
    """Create or update file.

    :param file_path: path to the file.
    :param file_content: file content.
    :param file_content_encoding: file content encoding e.g. `latin-1`.
    """
    with open(file_path, 'wb+') as file:
        file.write(file_content.encode(file_content_encoding))


def load_args(ap):
    """Load user arguments."""
    cmd = ap.parse_args()
    return cmd


def multi_phase_options(printout=True):
    """Retrieve all the options for multiple scattering radiation"""
    if printout:
        print(
            "Can also set delta_eddington=True/False in approx['delta_eddington']"
            )
    return ['N=2', 'N=1']


def flush_log(console):
    """Flush console output log buffer.

    Console output is written to the log when end of line is reached. Call this
    function when you want to log the latest console output but the end of the
    last line has not been reached yet.

    .. note::

       In order to support this operation the
       :py:attr:`pexpect:pexpect.spawn.logfile_read` console attribute must be
       set to :py:class:`alpy.pexpect_log.LogfileRead` instance. The console
       objects returned by :py:func:`alpy.console.create` and
       :py:func:`alpy.console.connect` functions are configured in this way.

    :param console: console object
    :type console: :py:class:`pexpect:pexpect.spawn` - like class
    """
    console.logfile_read.log_remaining_text()


@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)


def _get_gtf_column(column_name, gtf_path, df):
    """
    Helper function which returns a dictionary column or raises an ValueError
    abou the absence of that column in a GTF file.
    """
    if column_name in df.columns:
        return list(df[column_name])
    else:
        raise ValueError("Missing '%s' in columns of %s, available: %s" % (
            column_name, gtf_path, list(df.columns)))


def nullint(value):
    """
    Return int(value) if bool(value) is not False. Return None otherwise.
    Useful for coercing optional values to an integer.

    >>> nullint('10')
    10
    >>> nullint('') is None
    True
    """
    if value:
        return int(value)


@classmethod
def update_hash(cls, filelike, digest):
    """Update the digest of a single file in a memory-efficient manner."""
    block_size = digest.block_size * 1024
    for chunk in iter(lambda : filelike.read(block_size), b''):
        digest.update(chunk)


@classmethod
def from_json(cls, json_blob):
    """
        Given an authentication JSON blob, which should look like::

            {
                "auth": {
                    "RAX-KSKEY:apiKeyCredentials": {
                        "username": "user",
                        "apiKey": "key"
                    },
                    "tenantId": "111111"
                }
            }

        ``"tenantId"`` is interchanable with ``"tenantName"``, and is
        optional.

        :return: a class:`APIKeyCredentials` object
        """
    tenant_id = json_blob['auth'].get('tenantName')
    if tenant_id is None:
        tenant_id = json_blob['auth'].get('tenantId')
    username = json_blob['auth'][cls.type_key]['username']
    api_key = json_blob['auth'][cls.type_key]['apiKey']
    return cls(username=username, api_key=api_key, tenant_id=tenant_id)


def get_stopwords(filename):
    """Read stopword list from file.

    Assumes that the list is defined as a newline separated words. It is
    a utility in case you'd like to provide your own stopwords list.
    Assumes encoding ``utf8``.

    :param filename: Name of the file containing stopword list.
    :type filename: string
    :return: List of stopwords
    :rtype: set
    """
    stopwords = set()
    with open(filename, 'r', encoding='utf8') as fp:
        for line in fp:
            word = line.strip()
            stopwords.add(word)
    return stopwords


def file_from_list_of_images(file_list, current_file, request):
    """
    return filename from file_list depends of request
    request: position on the list
    """
    if file_list:
        if request == 'first':
            file = file_list[0]
        elif request == 'previous':
            if current_file in file_list:
                position = file_list.index(current_file)
                if position > 0:
                    file = file_list[position - 1]
                else:
                    file = None
            else:
                file = file_list[0]
        elif request == 'next':
            if current_file in file_list:
                position = file_list.index(current_file)
                if position <= len(file_list) - 2:
                    file = file_list[position + 1]
                else:
                    file = None
            else:
                file = file_list[-1]
        elif request == 'last':
            file = file_list[-1]
        else:
            file = None
    else:
        file = None
    if file == current_file:
        file = None
    return file


def __new__(cls, fx_or_grid, fy_or_field=None, fz=None, dtype=complex, freq
    =None):
    """Initiate a new Source Field."""
    if freq is None:
        print(f'* ERROR   :: SourceField requires the frequency.')
        raise ValueError('SourceField needs `freq`.')
    if freq > 0:
        dtype = complex
    else:
        dtype = float
    return super().__new__(cls, fx_or_grid, fy_or_field=fy_or_field, fz=fz,
        dtype=dtype, freq=freq)


def lineIntersection(x1, y1, x2, y2, x3, y3, x4, y4):
    """
    Computes intersection point of two lines if any, and the t value on p1p2
    (attn: if you want to use the t value order your segments accordingly!)
    Adapted from Andre LaMothe, "Tricks of the Windows Game Programming Gurus".
    G. Bach, http://stackoverflow.com/a/1968345

    Takes four scalars describing line and four scalars describing otherLine.
    """
    Bx_Ax = x2 - x1
    By_Ay = y2 - y1
    Dx_Cx = x4 - x3
    Dy_Cy = y4 - y3
    determinant = -Dx_Cx * By_Ay + Bx_Ax * Dy_Cy
    if abs(determinant) < 1e-20:
        return None
    s = (-By_Ay * (x1 - x3) + Bx_Ax * (y1 - y3)) / determinant
    t = (Dx_Cx * (y1 - y3) - Dy_Cy * (x1 - x3)) / determinant
    if s >= 0 and s <= 1 and t >= 0 and t <= 1:
        return x1 + t * Bx_Ax, y1 + t * By_Ay, t
    return None


def activate_printanswers(texfile):
    """ Activate printanswers mod in texfile """
    output_fname = 'corr_' + texfile
    with open(texfile, 'r') as input_f:
        with open(output_fname, 'w') as output_f:
            for line in input_f.readlines():
                output_f.write(line.replace('solution/print = false',
                    'solution/print = true'))
    return output_fname


def gpencil_modifier_copy(modifier: str=''):
    """Duplicate modifier at the same position in the stack

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


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


def _consistency(value):
    """
    Validator for 'consistency' parameter
    """
    if value and value.lower() not in ('', 'not_bounded'):
        raise ValueError('Invalid value!')
    return value


def print_source_location_info(print_fn, filename, lineno, fn_name=None,
    f_lasti=None, remapped_file=None):
    """Print out a source location , e.g. the first line in
    line in:
        (/tmp.py:2 @21):  <module>
        L -- 2 import sys,os
        (trepan3k)
    """
    if remapped_file:
        mess = '(%s:%s remapped %s' % (remapped_file, lineno, filename)
    else:
        mess = '(%s:%s' % (filename, lineno)
    if f_lasti and f_lasti != -1:
        mess += ' @%d' % f_lasti
        pass
    mess += '):'
    if fn_name and fn_name != '?':
        mess += ' %s' % fn_name
        pass
    print_fn(mess)
    return


def _get_endpoint(ks_session, **kwargs):
    """Get an endpoint using the provided keystone session."""
    endpoint_type = kwargs.get('endpoint_type') or 'publicURL'
    service_type = kwargs.get('service_type') or 'metering'
    endpoint = ks_session.get_endpoint(service_type=service_type, interface
        =endpoint_type, region_name=kwargs.get('region_name'))
    return endpoint


def rshift(val, n):
    """python port for '>>>'(right shift with padding)
    """
    return val % 4294967296 >> n


def UernPremRate():
    """Unearned Premium Rate"""
    return None


@classmethod
def _process_keyword(cls, keyword):
    """Basic keyword search assume that the model have a name and tags fields to work out of the box for simple model."""
    keyword_cleaned = cls.clean_keyword(keyword)
    keyword_low = keyword_cleaned.replace('-', ' ').strip()
    analyzer = cls.DEFAULT_ANALYZER
    if keyword_cleaned:
        analyzer = cls.get_analyzer(keyword_cleaned)
    return {'bool': {'should': [{'query_string': {'query': '%s*' %
        keyword_low, 'fields': ['name^5', 'name.*^5', 'tags^2'],
        'default_operator': 'AND', 'analyzer': analyzer, 'fuzziness':
        'auto'}}, {'term': {'name.untouched': keyword}}, {'term': {
        'tags.untouched': keyword}}]}}


def create(connection):
    """Create the latest version of the schema. This function should be
    idempotent and can be usefully called more than once per database
    for development, but stucco_evolution tries to call this only once
    in production."""


def should_build_with_cython(package, release=None):
    """Returns the previously used Cython version (or 'unknown' if not
    previously built) if Cython should be used to build extension modules from
    pyx files.  If the ``release`` parameter is not specified an attempt is
    made to determine the release flag from `astropy.version`.
    """
    try:
        version_module = __import__(package + '.cython_version', fromlist=[
            'release', 'cython_version'])
    except ImportError:
        version_module = None
    if release is None and version_module is not None:
        try:
            release = version_module.release
        except AttributeError:
            pass
    try:
        cython_version = version_module.cython_version
    except AttributeError:
        cython_version = 'unknown'
    have_cython = False
    try:
        import Cython
        have_cython = True
    except ImportError:
        pass
    if have_cython and (not release or cython_version == 'unknown'):
        return cython_version
    else:
        return False


@classmethod
def generate_messages(cls, parts):
    """
        Performs a deterministic first walk of the tree implied by a list of
        message parts.

        generate_messages(["foo", "bar", ["herp", "derp"], "baz"]) yields:
        * "foo"
        * "foo.bar"
        * "foo.bar.herp"
        * "foo.bar.herp.baz"
        * "foo.bar.derp"
        * "foo.bar.derp.baz"
        """
    for message_parts in cls.generate_message_parts(parts):
        yield '.'.join(message_parts)


def write_fits(data, filename, shape=None, overwrite=True):
    """Write the data to a fits-file.

	If the data is a Field with SeparatedCoords, the shaped field will be written to the
	fits-file, to allow for easier viewing with external tools.

	Parameters
	----------
	data : ndarray or Field
		The ndarray or Field to write to the fits file.
	filename : string
		The filename of the newly created file. This can include a path.
	shape : ndarray or None
		The shape to which to reshape the data. If this is given, it will override a potential
		shape from the grid accompaning the field.
	overwrite : boolean
		Whether to overwrite the fits-file if it already exists.
	"""
    from astropy.io import fits
    hdu = None
    if shape is not None:
        hdu = fits.PrimaryHDU(data.reshape(shape))
    elif hasattr(data, 'grid'):
        if data.grid.is_separated:
            hdu = fits.PrimaryHDU(data.shaped)
    if hdu is None:
        hdu = fits.PrimaryHDU(data)
    hdu.writeto(filename, overwrite=True)


@classmethod
def _from_et(cls, root, parent):
    """
        Create a :class:`Net` from a :code:`net` element.

        :param root: The element tree tree to parse.
        :param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
        :rtype: :class:`Net`
        """
    n = cls()
    n._init_from_et(root, parent)
    return n


def filepath():
    """
    Get the file path of the program that is executing this
    """
    import sys
    return str(sys.argv[0])


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

        :param str val:
        :rtype: MemberAddResult
        """
    return cls('user_creation_failed', val)


@staticmethod
def write(writer, value):
    """
        Writes Zserio varuint type to the bit stream.

        :param writer: Bit stream where to write.
        :param value: Zserio varuint type to write.
        """
    writer.writeVarUInt(value)


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


@staticmethod
def j2t_idea_path_valueset(message_s, jpath_s):
    """
        Calculate and return set of all values on all given jpaths in all given
        messages. Messages and jpaths can also be a single values.
        """
    result = {}
    if not isinstance(message_s, list):
        message_s = [message_s]
    if not isinstance(jpath_s, list):
        jpath_s = [jpath_s]
    for item in message_s:
        for jpath in jpath_s:
            values = item.get_jpath_values(jpath)
            for val in values:
                result[val] = 1
    return list(sorted(result.keys()))


def slip_encode_esc_chars(data_in):
    """Encode esc characters in a SLIP package.

    Replace 0xCO  with 0xDBDC and 0xDB with 0xDBDD.

     :type str data_in: str to encode
     :return: str with encoded packet
    """
    result = []
    data = []
    for i in data_in:
        data.append(ord(i))
    while len(data):
        char = data.pop(0)
        if char == 192:
            result.extend([219, 220])
        elif char == 219:
            result.extend([219, 221])
        else:
            result.append(char)
    return ''.join(chr(i) for i in result)


def check_axis_range(axis, rank):
    """Check axis range."""
    if not -rank <= axis < rank:
        raise ValueError('The axis should be in range [{}, {}), but got {}.'
            .format(-rank, rank, axis))


@classmethod
def for_flag(cls, flag):
    """Return :class:`GistCommand` matching given command line flag."""
    for cmd in cls:
        if flag in (cmd.short_flag, cmd.long_flag):
            return cmd


@classmethod
def alter_new_orm_column(cls, orm_col):
    """Allow altering default column attributes when first detected/added

        For instance special column like `__time` for Druid can be
        set to is_dttm=True. Note that this only gets called when new
        columns are detected/created"""
    pass


def _parameters_exists_in_docstring(docstring):
    """
    Get boolean of whether Parater part exists in docstring
    or not.

    Parameters
    ----------
    docstring : str
        Docstring to be checked.

    Returns
    -------
    result_bool : bool
        If exists, True will be set.
    """
    is_in = """Parameters
    ---""" in docstring
    if not is_in:
        return False
    return True


def path_reference_copy(copy_set, report=print):
    """
    Execute copying files of path_reference

    :arg copy_set: set of (from, to) pairs to copy.
    :type copy_set: set
    :arg report: function used for reporting warnings, takes a string argument.
    :type report: function
    """
    if not copy_set:
        return
    import os
    import shutil
    for file_src, file_dst in copy_set:
        if not os.path.exists(file_src):
            report('missing %r, not copying' % file_src)
        elif os.path.exists(file_dst) and os.path.samefile(file_src, file_dst):
            pass
        else:
            dir_to = os.path.dirname(file_dst)
            try:
                os.makedirs(dir_to, exist_ok=True)
            except:
                import traceback
                traceback.print_exc()
            try:
                shutil.copy(file_src, file_dst)
            except:
                import traceback
                traceback.print_exc()


def comment_width_from_str(src):
    """A simple restriction of integer:

    <xs:simpleType name="CommentWidth">
            <xs:restriction base="xs:integer">
                    <xs:maxInclusive value="100"/>
                    <xs:minInclusive value="5"/>
            </xs:restriction>
    </xs:simpleType>"""
    value = int(src)
    if value < 5 or value > 100:
        raise ValueError('Value exceeds bounds for CommentWidth: %i' % value)
    return value


def escape_doc_string_value(text: str) ->str:
    """Escape triple-quotes in doc strings."""
    return text.replace('"""', '\\"\\"\\"')


def get_authorization_header(request):
    """
    Return request's 'Authorization:' header, as a bytestring.
    From: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/authentication.py
    """
    auth = request.META.get('HTTP_AUTHORIZATION', b'')
    if isinstance(auth, type('')):
        auth = auth.encode('iso-8859-1')
    return auth


def getQualifiedIdentifiers():
    """Return a sequence of Identifier IDublinCoreElementItem.
        """


def read_numpy(fh, byteorder, dtype, count):
    """Read tag data from file and return as numpy array."""
    dtype = 'b' if dtype[-1] == 's' else byteorder + dtype[-1]
    return fh.read_array(dtype, count)


def EncodingJSONRPCServer(server):
    """
    Return wrapped JSON-RPC server that supports HTTP compression (currently
    gzip).

    @type server: t.w.r.Resource
    @param server: Instance of JSONRPCServer

    @rtype: t.w.r.EncodingResourceWrapper
    @return: Wrapper that implements HTTP compression
    """
    from twisted.web.resource import EncodingResourceWrapper
    from twisted.web.server import GzipEncoderFactory
    return EncodingResourceWrapper(server, [GzipEncoderFactory()])


def _from_r_alias(obj, r, lat_and_inv=None):
    """
    Alias for instance method that allows the method to be called in a
    multiprocessing pool
    """
    return obj._from_r(r, lat_and_inv=lat_and_inv)


def isvideotype(x):
    """Is an object a vipy.video class Video, VideoCategory, Scene?"""
    return str(type(x)) in ["<class 'vipy.video.Video'>",
        "<class 'vipy.video.VideoCategory'>", "<class 'vipy.video.Scene'>"]


def radius(d, offsets, motor_ofs):
    """return radius give data point and offsets"""
    mag, motor = d
    return (mag + offsets + motor * motor_ofs).length()


def to_pm1(samples):
    """Converts a tensor of spins from the :math:`\\sigma_i = 0, 1` convention
    to the :math:`\\sigma_i = -1, +1` convention.
    :param samples: A tensor of spins to convert.
                    Must be using the :math:`\\sigma_i = 0, 1` convention.
    :type samples: torch.Tensor
    """
    return samples.mul(2.0).sub(1.0)


@classmethod
def create_schema_instance(cls, *schema_args, **schema_kwargs):
    """Create a Schema instance for loading or dumping"""
    schema_class = cls.get_schema_class()
    if schema_class:
        schema = cls.get_schema_class()(*schema_args, **schema_kwargs)
        schema.context = schema_kwargs
        return schema


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 _convert_write_result(operation, command, result):
    """Convert a legacy write result to write commmand format."""
    affected = result.get('n', 0)
    res = {'ok': 1, 'n': affected}
    errmsg = result.get('errmsg', result.get('err', ''))
    if errmsg:
        if result.get('wtimeout'):
            res['writeConcernError'] = {'errmsg': errmsg, 'code': 64,
                'errInfo': {'wtimeout': True}}
        else:
            error = {'index': 0, 'code': result.get('code', 8), 'errmsg':
                errmsg}
            if 'errInfo' in result:
                error['errInfo'] = result['errInfo']
            res['writeErrors'] = [error]
            return res
    if operation == 'insert':
        res['n'] = len(command['documents'])
    elif operation == 'update':
        if 'upserted' in result:
            res['upserted'] = [{'index': 0, '_id': result['upserted']}]
        elif result.get('updatedExisting') is False and affected == 1:
            update = command['updates'][0]
            _id = update['u'].get('_id', update['q'].get('_id'))
            res['upserted'] = [{'index': 0, '_id': _id}]
    return res


@staticmethod
def model_version():
    """Return current version of this model, counting up from 0.

        Models may not be backwards-compatible with older versions.
        Version 1 split from version 0 on Sep 7, 2018.
        To use version 0, use --model legacy:memnn:0
        (legacy agent code is located in parlai/agents/legacy_agents).
        """
    return 2


def tree_path_parent():
    """Go to parent node tree

    """
    pass


def make_dupli_face():
    """Convert objects into instanced faces

    """
    pass


def remove_flat(tsdict):
    """Remove flat timeseries from a `TimeSeriesDict`
    """
    outdict = tsdict.copy()
    for key in tsdict.keys():
        series = tsdict[key].value
        if series.min() == series.max():
            outdict.pop(key)
    return outdict


def stream_is_unidirectional(stream_id: int) ->bool:
    """
    Returns True if the stream is unidirectional.
    """
    return bool(stream_id & 2)


def is_undefined(obj):
    """Check if the object passed is undefined.  This does nothing more than
    performing an instance check against :class:`Undefined` but looks nicer.
    This can be used for custom filters or tests that want to react to
    undefined variables.  For example a custom default filter can look like
    this::

        def default(var, default=''):
            if is_undefined(var):
                return default
            return var
    """
    from jinja2.runtime import Undefined
    return isinstance(obj, Undefined)


def find(datumname, crstype, strict=False):
    """
    Search for a datum name located in this module.

    Arguments:

    - **datumname**: The datum name to search for.
    - **crstype**: Which CRS naming convention to search (different
        CRS formats have different names for the same datum).
    - **strict** (optional): If False, ignores minor name mismatches
        such as underscore or character casing, otherwise must be exact
        match (defaults to False).
    """
    if not strict:
        datumname = datumname.lower().replace(' ', '_')
    for itemname, item in globals().items():
        if itemname.startswith('_') or itemname == 'Datum':
            continue
        try:
            if hasattr(item.name, crstype):
                itemname = getattr(item.name, crstype)
                if not strict:
                    itemname = itemname.lower().replace(' ', '_')
                if datumname == itemname:
                    return item
        except:
            pass
    else:
        return None


def set_node_attributes(G, values, name=None):
    """Set node attributes from dictionary of nodes and values

        Parameters
        ----------
        G : DyNetx Graph

        name : string
           Attribute name

        values: dict
           Dictionary of attribute values keyed by node. If `values` is not a
           dictionary, then it is treated as a single attribute value that is then
           applied to every node in `G`.

        """
    if name is not None:
        try:
            for n, v in list(values.items()):
                try:
                    G.node[n][name] = values[n]
                except KeyError:
                    pass
        except AttributeError:
            for n in G:
                G.node[n][name] = values
    else:
        for n, d in list(values.items()):
            try:
                G.node[n].update(d)
            except KeyError:
                pass


def correlation(x, y, d):
    """Return time-serial correlation of x and y for the past d days."""
    return x.rolling(d).corr(y)


@classmethod
def delete_qs(cls, qs):
    """Удаление списка записей.

        По одной что бы удалились связанные записи в родительской таблице

        """
    for item in qs:
        item.delete()
    cls._session.commit()


def decodejpg(encoded, tables=b'', photometric=None, ycbcr_subsampling=None,
    ycbcr_positioning=None):
    """Decode JPEG encoded byte string (using _czifile extension module)."""
    import _czifile
    image = _czifile.decodejpg(encoded, tables)
    if photometric == 'rgb' and ycbcr_subsampling and ycbcr_positioning:
        pass
    return image.tostring()


def provides(dotted_name):
    """Given an interface dotted name, determine if the context provides
        this interface.
        """


@staticmethod
def __int(x: str):
    """Convert str to int or None"""
    if x == '':
        return None
    if x.startswith('0x'):
        return int(x, 0)
    return int(x)


def and_dict(dict1, dict2):
    """
    Apply logical conjunction between values of dictionaries of the same keys.

    Keys set must be identical in both dictionaries. Otherwise KeyError
    exception is raised.

    :param dict1: Dictionary of bool values.
    :param dict2: Dictionary of bool values.
    :returns: A dictionary with the same set of keys but with modified values.
    """
    dict3 = {}
    for key in dict1.keys():
        dict3[key] = dict1[key] & dict2.get(key, False)
    return dict3


def remove_output(nb):
    """Remove all outputs."""
    for cell in nb['cells']:
        if 'outputs' in cell:
            cell['outputs'] = []


def __digit(value):
    """
        Converts hex to digit
    """
    return int(value, 16)


def check_domain_state(conn, guestname, logger):
    """ if a guest with the same name exists, remove it """
    running_guests = []
    ids = conn.listDomainsID()
    for id in ids:
        obj = conn.lookupByID(id)
        running_guests.append(obj.name())
    if guestname in running_guests:
        logger.info('A guest with the same name %s is running!' % guestname)
        logger.info('destroy it...')
        domobj = conn.lookupByName(guestname)
        domobj.destroy()
    defined_guests = conn.listDefinedDomains()
    if guestname in defined_guests:
        logger.info('undefine the guest with the same name %s' % guestname)
        domobj = conn.lookupByName(guestname)
        domobj.undefine()
    return 0


def convert():
    """Convert temporary relation into a real one.

        Returns real relation object
        """


@staticmethod
def simple_user_str(user):
    """
        For a user matching output of UserSchema, return 'user_name(id)'
        """
    if not user:
        return '<anonymous>'
    if 'user_name' not in user:
        return '<anonymous>(%s)' % user['id']
    return '%s(%s)' % (user['user_name'], user['id'])


def shift(shift):
    """
    Check *shift_x* and *shift_y*.
    :raises TypeError: Parameter delta must be a real number.
    """
    if not isinstance(shift, (int, float)):
        raise TypeError('\n\nParameter shift must be a real number.\n')


def restore_psycopg2():
    """Restores psycopg2"""
    try:
        import psycopg2
    except ImportError:
        pass
    else:
        setattr(psycopg2, 'connect', getattr(psycopg2.connect,
            '__wrapped__', psycopg2.connect))
        setattr(psycopg2.extensions, 'register_type', getattr(psycopg2.
            extensions.register_type, '__wrapped__', psycopg2.extensions.
            register_type))
        setattr(psycopg2._psycopg, 'register_type', getattr(psycopg2.
            _psycopg.register_type, '__wrapped__', psycopg2._psycopg.
            register_type))
        setattr(psycopg2._json, 'register_type', getattr(psycopg2._json.
            register_type, '__wrapped__', psycopg2._json.register_type))


def parse_version_req(version):
    """
     Converts a version string to a dict with following rules:
       if string starts with ':' it is a channel
       if string starts with 'sha256' it is a digest
       else it is a release
    """
    if version is None:
        version = 'default'
    if version[0] == ':' or version.startswith('channel:'):
        parts = {'key': 'channel', 'value': version.split(':')[1]}
    elif version.startswith('sha256:'):
        parts = {'key': 'digest', 'value': version.split('sha256:')[1]}
    else:
        parts = {'key': 'version', 'value': version}
    return parts


@classmethod
def _validate_doc(cls, doc):
    """Emit a warning or raise an exception if the document is invalid. Returns doc."""
    try:
        for key in doc.keys():
            cls._validate_doc(doc[cls._validate_key(key)])
    except AttributeError:
        return
    return doc


def validate_format(*_arg):
    """
    This method can be overridden with format validation logic.
    """
    return True


def format_cmd(cmd):
    """Return command in a valid format."""
    if isinstance(cmd, str):
        cmd = [cmd]
    elif not isinstance(cmd, list):
        raise ValueError('Command should be a list or a string and not {}'.
            format(type(cmd)))
    return cmd


def find_span_binsearch(degree, knot_vector, num_ctrlpts, knot, **kwargs):
    """ Finds the span of the knot over the input knot vector using binary search.

    Implementation of Algorithm A2.1 from The NURBS Book by Piegl & Tiller.

    The NURBS Book states that the knot span index always starts from zero, i.e. for a knot vector [0, 0, 1, 1];
    if FindSpan returns 1, then the knot is between the half-open interval [0, 1).

    :param degree: degree, :math:`p`
    :type degree: int
    :param knot_vector: knot vector, :math:`U`
    :type knot_vector: list, tuple
    :param num_ctrlpts: number of control points, :math:`n + 1`
    :type num_ctrlpts: int
    :param knot: knot or parameter, :math:`u`
    :type knot: float
    :return: knot span
    :rtype: int
    """
    tol = kwargs.get('tol', 1e-05)
    n = num_ctrlpts - 1
    if abs(knot_vector[n + 1] - knot) <= tol:
        return n
    low = degree
    high = num_ctrlpts
    mid = (low + high) / 2
    mid = int(round(mid + tol))
    while knot < knot_vector[mid] or knot >= knot_vector[mid + 1]:
        if knot < knot_vector[mid]:
            high = mid
        else:
            low = mid
        mid = int((low + high) / 2)
    return mid


def _convert_transpose(builder, node, graph, err):
    """
    convert to CoreML Transpose Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L3426
    """
    axes = node.attrs.get('perm', [])
    if axes == []:
        rank = builder._get_rank(node.inputs[0])
        if rank == -1:
            return err.unsupported_op_configuration(builder, node, graph,
                'Rank unknown for input')
        axes = list(range(-1, -(rank + 1), -1))
    builder.add_transpose(name=node.name, axes=axes, input_name=node.inputs
        [0], output_name=node.outputs[0])


def message_received(request):
    """ called when a confirmation message has been received from a user """


def flat_scale_parameters(band):
    """
    Return the flat scaling parameters for a given band.

    :param band: The band to use, either 'FUV' or 'NUV'.

    :type band: str

    :returns: tuple -- A three-element tuple containing the flat scaling
        parameters.
    """
    if band == 'NUV':
        flat_correct = -0.0154
        flat_t0 = 840418779.02
        flat_correct_0 = 1.9946352
        flat_correct_1 = -1.9679445e-09
        flat_correct_2 = 9.3025231e-19
    elif band == 'FUV':
        flat_correct = -0.0031
        flat_t0 = 840418779.02
        flat_correct_0 = 1.2420282
        flat_correct_1 = -2.8843099e-10
        flat_correct_2 = 0.0
    else:
        print('Band not specified.')
        exit(1)
    return flat_correct_0, flat_correct_1, flat_correct_2


def disassociate_fleet(FleetName=None, StackName=None):
    """
    Disassociates a fleet from a stack.
    See also: AWS API Documentation

    :example: response = client.disassociate_fleet(
        FleetName='string',
        StackName='string'
    )

    :type FleetName: string
    :param FleetName: [REQUIRED]
            The name of the fleet to disassociate.

    :type StackName: string
    :param StackName: [REQUIRED]
            The name of the stack with which the fleet is associated.

    :rtype: dict
    :return: {}

    :returns:
    (dict) --

    """
    pass


def get_polarization_from_s1_filename(filename, dual=False):
    """Get polarization from the filename of a Sentinel-1 scene.
    https://sentinel.esa.int/web/sentinel/user-guides/sentinel-1-sar/naming-conventions.

    :param filename: top-level SENTINEL-1 product folder name
    :param dual: boolean (default: True), optional
    :return: str or list

    >>> get_polarization_from_s1_filename("MMM_BB_TTTR_1SDH_YYYYMMDDTHHMMSS_YYYYMMDDTHHMMSS_OOOOOO_DDDDDD_CCCC.SAFE.zip")
    'HH'
    >>> get_polarization_from_s1_filename("MMM_BB_TTTR_1SSH_YYYYMMDDTHHMMSS_YYYYMMDDTHHMMSS_OOOOOO_DDDDDD_CCCC.SAFE.zip")
    'HH'
    >>> get_polarization_from_s1_filename("MMM_BB_TTTR_2SSV_YYYYMMDDTHHMMSS_YYYYMMDDTHHMMSS_OOOOOO_DDDDDD_CCCC.SAFE.zip")
    'VV'
    >>> get_polarization_from_s1_filename("MMM_BB_TTTR_1SDV_YYYYMMDDTHHMMSS_YYYYMMDDTHHMMSS_OOOOOO_DDDDDD_CCCC.SAFE.zip", True)
    ['VV', 'VH']
    """
    polarization_dict = {'SSV': 'VV', 'SSH': 'HH', 'SDV': ['VV', 'VH'],
        'SDH': ['HH', 'HV']}
    polarization = polarization_dict[filename[13:16]]
    if not dual and isinstance(polarization, list):
        return polarization[0]
    else:
        return polarization


def adapt_version(snapshot, source_ver, target_ver):
    """Adapt a snapshot from a version to another."""


@staticmethod
def _compare_bool(b1: bool, b2: bool):
    """
        Compares two booleans in the same way as Java's Boolean.compare method.

        :param b1:  The first bool.
        :param b2:  The second bool.
        :return:    -1, 0, +1 if b1 is smaller than, equal to, or larger than b2.
        """
    return 0 if b1 == b2 else 1 if b1 else -1


def getQualifiedDates():
    """Return a sequence of Date IDublinCoreElementItem.
        """


def fold_spaces(low_spaces, high_spaces):
    """
    Creates all possible combinations of hyperspaces.

    Parameters
    ----------
    * `low_spaces` [list, shape=(n_spaces,)]:
        lower spaces defined by hyperspace classes.

    * `high_spaces` [list, shape=(n_spaces,)]:
        lower spaces defined by hyperspace classes.

    Returns
    -------
    * `hyperspace` [`list of lists`, shape=(2**n_spaces, n_spaces)]:
        - All combinations of hyperspaces. Each list within hyperspace
          is a search space to be distributed across 2**n_spaces nodes.
    """
    if len(low_spaces) != len(high_spaces):
        raise ValueError(
            'low_spaces and high_spaces must have the same length. Got {} and {} respectively.'
            .format(len(low_spaces), len(high_spaces)))
    indices = len(low_spaces)
    num_hyperspaces = 2 ** indices
    hyperspace = [[] for i in range(num_hyperspaces)]
    for space in range(num_hyperspaces):
        for index in range(indices):
            bit_tester = 1 << index
            if space & bit_tester:
                hyperspace[space].insert(index, low_spaces[index])
            else:
                hyperspace[space].insert(index, high_spaces[index])
    return hyperspace


@classmethod
def is_approved(cls, tag, configuration=None):
    """
        Return if tag is an approved one or not

        Args:
            tag (str): Tag to check
            configuration (Optional[Configuration]): HDX configuration. Defaults to global configuration.

        Returns:
            bool: True if tag is approved, False if not
        """
    if tag.lower() in cls.approved_tags(configuration):
        return True
    return False


def getTagsAndStatus():
    """
            Return a list of dict with
            tag - name
            count - usage count
            system - true of false for system tag
            hidden - true or false for hidden
        """


def reflect(v, normal):
    """Reflect vector ``v`` off a ``normal`` vector, return new direction vector."""
    return v - 2 * (normal * v).sum() * normal


def ellipsis(string, max_length=100):
    """Returns a length limited version of a string, up to ``max_length``
    characters.

    If the string is longer it will be cut preserving the starting part and an
    ellipsis will be added.
    """
    if len(string) <= max_length:
        return string
    else:
        return string[:max_length - 3] + '...'


def G_matrix(q, r, contrast, FFfxn, Volfxn, args=()):
    """Calculates the response matrix :math:`G(Q,r)`

    :param float q: :math:`Q`
    :param float r: :math:`r`
    :param float contrast: :math:`|\\Delta\\rho|^2`, the scattering contrast
    :param function FFfxn: form factor function FF(q,r,args)
    :param function Volfxn: volume function Vol(r,args)
    :returns float: G(Q,r)
    """
    FF = FFfxn(q, r, args)
    Vol = Volfxn(r, args)
    return 0.0001 * (contrast * Vol * FF ** 2).T


def get_mm(xtime):
    """
	说明：根据传入的时间 ，返回分钟部分（整型）
	参数：xtime，是字符串，格式必须为 hh:mm:ss
	返回值：整型 mm
	"""
    time_str = None
    time_arr = xtime.split(':')
    if len(time_arr) >= 2:
        time_str = int(time_arr[1])
    return time_str


def addr_to_hash(addr):
    """
    Creates hashable address representation
    :param addr:
    :return:
    """
    return bytes(addr.spend_public_key + addr.view_public_key)


def eval_opencl(model_info, data, dtype='single', cutoff=0.0):
    """
    Return a model calculator using the OpenCL calculation engine.
    """


def restart_ecs_service_resource_handler(event, context):
    """Lambda handler function to restart an ECS service, as a CloudFormation resource.

    This is intended to be used in an inline deployment. The physical ID is
    the ID of the ECS service deployment
    """
    import cfnresponse
    import logging
    logging.basicConfig(level=logging.DEBUG)
    LOGGER = logging.getLogger('restarter')
    try:
        import boto3
        ecs = boto3.client('ecs')
        response = {}
        physical_id = event.get('PhysicalResourceId')
        if event['RequestType'] in ['Create', 'Update']:
            properties = event['ResourceProperties']
            update_result = ecs.update_service(cluster=properties[
                'ClusterArn'], service=properties['ServiceArn'],
                forceNewDeployment=True)
            deployment = update_result['service']['deployments'][0]
            physical_id = deployment['id']
            ecs.get_waiter('services_stable').wait(cluster=properties[
                'ClusterArn'], services=[properties['ServiceArn']])
        elif event['RequestType'] == 'Delete':
            LOGGER.info('Ignoring request to delete resource for deployment %s'
                , physical_id)
        else:
            raise ValueError('Unknown CloudFormation request type')
        cfnresponse.send(event, context, cfnresponse.SUCCESS, response,
            physical_id)
    except Exception as ex:
        LOGGER.exception('argh!')
        cfnresponse.send(event, context, cfnresponse.FAILED, {})


def get_bitstring_from_index(index, qubit_num):
    """
    Returns the bitstring in lexical order that corresponds to the given index in 0 to 2^(qubit_num)
    :param int index:
    :param int qubit_num:
    :return: the bitstring
    :rtype: str
    """
    if index > 2 ** qubit_num - 1:
        raise IndexError('Index {} too large for {} qubits.'.format(index,
            qubit_num))
    return bin(index)[2:].rjust(qubit_num, '0')


@staticmethod
def ndvi_calc(img, scale_factor=10000):
    """ Normalized difference vegetation index"""
    return img.normalizedDifference(['NIR', 'RED']).select([0], ['NDVI']
        ).multiply(scale_factor).toInt16()